* [PATCH v11 0/6] Add Toshiba Visconti Video Input Interface driver
@ 2024-07-09 0:08 Yuji Ishikawa
2024-07-09 0:08 ` [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface Yuji Ishikawa
` (5 more replies)
0 siblings, 6 replies; 20+ messages in thread
From: Yuji Ishikawa @ 2024-07-09 0:08 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown,
Sakari Ailus, Nobuhiro Iwamatsu, Yuji Ishikawa
Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel
This series is the Video Input Interface driver
for Toshiba's ARM SoC, Visconti.
This provides DT binding documentation,
device driver, documentation and MAINTAINER files.
A visconti VIIF driver instance exposes
1 media control device file, 3 video device files for capture
and 2 video device files for controlling image signal processor.
Detailed HW/SW are described in documentation directory.
The VIIF hardware has CSI2 receiver,
image signal processor and DMAC inside.
The subdevice for image signal processor provides
vendor specific V4L2 controls.
The device driver depends on two other drivers under development;
clock framework driver and IOMMU driver.
Corresponding features will be added later.
Best regards,
Yuji
Changelog v2:
- Resend v1 because a patch exceeds size limit.
Changelog v3:
- Add documentation to describe SW and HW
- Adapted to media control framework
- Introduced ISP subdevice, capture device
- Remove private IOCTLs and add vendor specific V4L2 controls
- Change function name avoiding camelcase and uppercase letters
Changelog v4:
- Split patches because a patch exceeds size limit
- fix dt-bindings document
- stop specifying ID numbers for driver instance explicitly at device tree
- use pm_runtime to trigger initialization of HW
along with open/close of device files.
- add a entry for a header file at MAINTAINERS file
Changelog v5:
- Fix coding style problem in viif.c (patch 2/6)
Changelog v6:
- add register definition of BUS-IF and MPU in dt-bindings
- add CSI2RX subdevice (separeted from ISP subdevice)
- change directory layout (moved to media/platform/toshiba/visconti)
- change source file layout (removed hwd_xxxx.c)
- pointer to userland memory is removed from uAPI parameters
- change register access (from struct style to macro style)
- remove unused macros
Changelog v7:
- remove redundant "bindings" from header and description text
- fix multiline text of "description"
- change "compatible" to "visconti5-viif"
- explicitly define allowed properties for port::endpoint
- remove unused variables
- update kerneldoc comments
- update references to headers
Changelog v8:
- rename bindings description file
- remove/simplify items in bindings
- update operations around v4l2_async_notifier
- use v4l2_async_connection instead of v4l2_async_subdev
- use dev_err_probe()
- better error handling at probe
- remove redundant mutex
- add V4L2_CTRL_TYPE_VISCONTI_ISP constant
Changelog v9:
- dictionary ordering of dt-bindings properties
- applied sparce checker
- call div64_u64 for 64bit division
- rebase to media_staging tree
- fix warning for cast between ptr and dma_addr_t
Changelog v10:
- add an independent entry in MAINTAINERS
- add paddings to uAPI structs
- use parameter buffer to control ISP (instead of vendor specific controls)
Changelog v11:
- stop merging sensor's controls and capture device's
- fix strange indents at initializations
- remove feature VB2_USERPTR from viif_params and viif_stats
- fix usage in the document
Yuji Ishikawa (6):
dt-bindings: media: platform: visconti: Add Toshiba Visconti Video
Input Interface
media: videodev2.h: add visconti viif meta buffer format
media: platform: visconti: Add Toshiba Visconti Video Input Interface
driver
media: platform: visconti: add streaming interface for ISP parameters
and status
documentation: media: add documentation for Toshiba Visconti Video
Input Interface driver
MAINTAINERS: Add entries for Toshiba Visconti Video Input Interface
.../admin-guide/media/v4l-drivers.rst | 1 +
.../admin-guide/media/visconti-viif.dot | 18 +
.../admin-guide/media/visconti-viif.rst | 255 +++
.../media/toshiba,visconti5-viif.yaml | 105 +
.../userspace-api/media/v4l/meta-formats.rst | 1 +
.../media/v4l/metafmt-visconti-viif.rst | 48 +
MAINTAINERS | 11 +
drivers/media/platform/Kconfig | 1 +
drivers/media/platform/Makefile | 1 +
drivers/media/platform/toshiba/Kconfig | 6 +
drivers/media/platform/toshiba/Makefile | 2 +
.../media/platform/toshiba/visconti/Kconfig | 19 +
.../media/platform/toshiba/visconti/Makefile | 8 +
.../media/platform/toshiba/visconti/viif.c | 651 ++++++
.../media/platform/toshiba/visconti/viif.h | 393 ++++
.../platform/toshiba/visconti/viif_capture.c | 1431 ++++++++++++
.../platform/toshiba/visconti/viif_capture.h | 21 +
.../platform/toshiba/visconti/viif_common.c | 239 ++
.../platform/toshiba/visconti/viif_common.h | 42 +
.../platform/toshiba/visconti/viif_csi2rx.c | 657 ++++++
.../platform/toshiba/visconti/viif_csi2rx.h | 24 +
.../toshiba/visconti/viif_csi2rx_regs.h | 102 +
.../platform/toshiba/visconti/viif_isp.c | 1190 ++++++++++
.../platform/toshiba/visconti/viif_isp.h | 24 +
.../platform/toshiba/visconti/viif_params.c | 2020 +++++++++++++++++
.../platform/toshiba/visconti/viif_params.h | 19 +
.../platform/toshiba/visconti/viif_regs.h | 721 ++++++
.../platform/toshiba/visconti/viif_stats.c | 336 +++
.../platform/toshiba/visconti/viif_stats.h | 14 +
include/uapi/linux/videodev2.h | 4 +
include/uapi/linux/visconti_viif.h | 1921 ++++++++++++++++
31 files changed, 10285 insertions(+)
create mode 100644 Documentation/admin-guide/media/visconti-viif.dot
create mode 100644 Documentation/admin-guide/media/visconti-viif.rst
create mode 100644 Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml
create mode 100644 Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst
create mode 100644 drivers/media/platform/toshiba/Kconfig
create mode 100644 drivers/media/platform/toshiba/Makefile
create mode 100644 drivers/media/platform/toshiba/visconti/Kconfig
create mode 100644 drivers/media/platform/toshiba/visconti/Makefile
create mode 100644 drivers/media/platform/toshiba/visconti/viif.c
create mode 100644 drivers/media/platform/toshiba/visconti/viif.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_capture.c
create mode 100644 drivers/media/platform/toshiba/visconti/viif_capture.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_common.c
create mode 100644 drivers/media/platform/toshiba/visconti/viif_common.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_csi2rx.c
create mode 100644 drivers/media/platform/toshiba/visconti/viif_csi2rx.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_isp.c
create mode 100644 drivers/media/platform/toshiba/visconti/viif_isp.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_params.c
create mode 100644 drivers/media/platform/toshiba/visconti/viif_params.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_regs.h
create mode 100644 drivers/media/platform/toshiba/visconti/viif_stats.c
create mode 100644 drivers/media/platform/toshiba/visconti/viif_stats.h
create mode 100644 include/uapi/linux/visconti_viif.h
--
2.25.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface 2024-07-09 0:08 [PATCH v11 0/6] Add Toshiba Visconti Video Input Interface driver Yuji Ishikawa @ 2024-07-09 0:08 ` Yuji Ishikawa 2024-07-22 15:21 ` Laurent Pinchart 2024-07-09 0:08 ` [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format Yuji Ishikawa ` (4 subsequent siblings) 5 siblings, 1 reply; 20+ messages in thread From: Yuji Ishikawa @ 2024-07-09 0:08 UTC (permalink / raw) To: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, Yuji Ishikawa Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel, Krzysztof Kozlowski Adds the Device Tree binding documentation that allows to describe the Video Input Interface found in Toshiba Visconti SoCs. Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> Reviewed-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> --- Changelog v2: - no change Changelog v3: - no change Changelog v4: - fix style problems at the v3 patch - remove "index" member - update example Changelog v5: - no change Changelog v6: - add register definition of BUS-IF and MPU Changelog v7: - remove trailing "bindings" from commit header message - remove trailing "Device Tree Bindings" from title - fix text wrapping of description - change compatible to visconti5-viif - explicitly define allowed properties for port::endpoint Changelog v8: - Suggestion from Krzysztof Kozlowski - rename bindings description file - use block style array instead of inline style - remove clock-lane (as it is fixed at position 0) - update sample node's name - use lowercase hex for literals - Suggestion from Laurent Pinchart - update description message port::description - remove port::endpoint::bus-type as it is fixed to <4> - remove port::endpoint::clock-lanes from example - add port::endpoint::data-lanes to required parameters list - fix sequence of data-lanes: <1 2 3 4> because current driver does not support data reordering - update port::endpoint::data-lanes::description - remove redundant type definition for port::endpoint::data-lanes Changelog v9: - place "required" after "properties" - dictionary ordering of properties Changelog v10: - no change Changelog v11: - no change .../media/toshiba,visconti5-viif.yaml | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml diff --git a/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml b/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml new file mode 100644 index 0000000000..97e8bda427 --- /dev/null +++ b/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/toshiba,visconti5-viif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Toshiba Visconti5 SoC Video Input Interface + +maintainers: + - Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> + +description: |- + Toshiba Visconti5 SoC Video Input Interface (VIIF) receives MIPI CSI2 video + stream, processes the stream with image signal processors (L1ISP, L2ISP), + then stores pictures to main memory. + +properties: + compatible: + const: toshiba,visconti5-viif + + reg: + items: + - description: Registers for capture control + - description: Registers for CSI2 receiver control + - description: Registers for bus interface unit control + - description: Registers for Memory Protection Unit + + interrupts: + items: + - description: Sync Interrupt + - description: Status (Error) Interrupt + - description: CSI2 Receiver Interrupt + - description: L1ISP Interrupt + + port: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: CSI-2 input port, with a single endpoint connected to the CSI-2 transmitter. + + properties: + endpoint: + $ref: video-interfaces.yaml# + additionalProperties: false + + properties: + data-lanes: + description: VIIF supports 1, 2, 3 or 4 data lanes + minItems: 1 + items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + + clock-noncontinuous: true + link-frequencies: true + remote-endpoint: true + + required: + - clock-noncontinuous + - data-lanes + - link-frequencies + - remote-endpoint + +required: + - compatible + - reg + - interrupts + - port + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + video@1c000000 { + compatible = "toshiba,visconti5-viif"; + reg = <0 0x1c000000 0 0x6000>, + <0 0x1c008000 0 0x400>, + <0 0x1c00e000 0 0x1000>, + <0 0x2417a000 0 0x1000>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + csi_in0: endpoint { + clock-noncontinuous; + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <456000000>; + remote-endpoint = <&imx219_out0>; + }; + }; + }; + }; -- 2.25.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface 2024-07-09 0:08 ` [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface Yuji Ishikawa @ 2024-07-22 15:21 ` Laurent Pinchart 2024-08-01 9:21 ` yuji2.ishikawa 0 siblings, 1 reply; 20+ messages in thread From: Laurent Pinchart @ 2024-07-22 15:21 UTC (permalink / raw) To: Yuji Ishikawa Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel, Krzysztof Kozlowski Hello Ishikawa-san, Thank you for the patch. On Tue, Jul 09, 2024 at 09:08:43AM +0900, Yuji Ishikawa wrote: > Adds the Device Tree binding documentation that allows to describe > the Video Input Interface found in Toshiba Visconti SoCs. > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > Reviewed-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> > Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> > --- > Changelog v2: > - no change > > Changelog v3: > - no change > > Changelog v4: > - fix style problems at the v3 patch > - remove "index" member > - update example > > Changelog v5: > - no change > > Changelog v6: > - add register definition of BUS-IF and MPU > > Changelog v7: > - remove trailing "bindings" from commit header message > - remove trailing "Device Tree Bindings" from title > - fix text wrapping of description > - change compatible to visconti5-viif > - explicitly define allowed properties for port::endpoint > > Changelog v8: > - Suggestion from Krzysztof Kozlowski > - rename bindings description file > - use block style array instead of inline style > - remove clock-lane (as it is fixed at position 0) > - update sample node's name > - use lowercase hex for literals > - Suggestion from Laurent Pinchart > - update description message port::description > - remove port::endpoint::bus-type as it is fixed to <4> > - remove port::endpoint::clock-lanes from example > - add port::endpoint::data-lanes to required parameters list > - fix sequence of data-lanes: <1 2 3 4> because current driver does not support data reordering > - update port::endpoint::data-lanes::description > - remove redundant type definition for port::endpoint::data-lanes > > Changelog v9: > - place "required" after "properties" > - dictionary ordering of properties > > Changelog v10: > - no change > > Changelog v11: > - no change > > .../media/toshiba,visconti5-viif.yaml | 105 ++++++++++++++++++ > 1 file changed, 105 insertions(+) > create mode 100644 Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml > > diff --git a/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml b/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml > new file mode 100644 > index 0000000000..97e8bda427 > --- /dev/null > +++ b/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml > @@ -0,0 +1,105 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/media/toshiba,visconti5-viif.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Toshiba Visconti5 SoC Video Input Interface > + > +maintainers: > + - Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> > + > +description: |- > + Toshiba Visconti5 SoC Video Input Interface (VIIF) receives MIPI CSI2 video > + stream, processes the stream with image signal processors (L1ISP, L2ISP), > + then stores pictures to main memory. > + > +properties: > + compatible: > + const: toshiba,visconti5-viif > + > + reg: > + items: > + - description: Registers for capture control > + - description: Registers for CSI2 receiver control > + - description: Registers for bus interface unit control > + - description: Registers for Memory Protection Unit Is this part of the VIIF, or some sort of more standalone IOMMU ? In the latter case, should it be handled by a separate driver ? > + > + interrupts: > + items: > + - description: Sync Interrupt > + - description: Status (Error) Interrupt > + - description: CSI2 Receiver Interrupt > + - description: L1ISP Interrupt > + > + port: > + $ref: /schemas/graph.yaml#/$defs/port-base > + unevaluatedProperties: false > + description: CSI-2 input port, with a single endpoint connected to the CSI-2 transmitter. > + > + properties: > + endpoint: > + $ref: video-interfaces.yaml# > + additionalProperties: false > + > + properties: > + data-lanes: > + description: VIIF supports 1, 2, 3 or 4 data lanes > + minItems: 1 > + items: > + - const: 1 > + - const: 2 > + - const: 3 > + - const: 4 > + > + clock-noncontinuous: true > + link-frequencies: true > + remote-endpoint: true > + > + required: > + - clock-noncontinuous Does the hardware support the non-continuous clock mode only, or is it configurable ? This is a boolean property, so if both mode are supported, the property should not be required. > + - data-lanes > + - link-frequencies > + - remote-endpoint > + > +required: > + - compatible > + - reg > + - interrupts > + - port > + > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + #include <dt-bindings/interrupt-controller/irq.h> > + > + soc { > + #address-cells = <2>; > + #size-cells = <2>; > + > + video@1c000000 { > + compatible = "toshiba,visconti5-viif"; > + reg = <0 0x1c000000 0 0x6000>, > + <0 0x1c008000 0 0x400>, > + <0 0x1c00e000 0 0x1000>, > + <0 0x2417a000 0 0x1000>; > + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, > + <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, > + <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>, > + <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; > + > + port { > + #address-cells = <1>; > + #size-cells = <0>; > + > + csi_in0: endpoint { > + clock-noncontinuous; > + data-lanes = <1 2>; > + link-frequencies = /bits/ 64 <456000000>; > + remote-endpoint = <&imx219_out0>; > + }; > + }; > + }; > + }; -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface 2024-07-22 15:21 ` Laurent Pinchart @ 2024-08-01 9:21 ` yuji2.ishikawa 0 siblings, 0 replies; 20+ messages in thread From: yuji2.ishikawa @ 2024-08-01 9:21 UTC (permalink / raw) To: laurent.pinchart Cc: hverkuil, mchehab, robh, krzk+dt, conor+dt, broonie, sakari.ailus, nobuhiro1.iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel, krzysztof.kozlowski Hello Laurent, Thank you for your review. > -----Original Message----- > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Sent: Tuesday, July 23, 2024 12:21 AM > To: ishikawa yuji(石川 悠司 ○RDC□AITC○EA開) > <yuji2.ishikawa@toshiba.co.jp> > Cc: Hans Verkuil <hverkuil@xs4all.nl>; Mauro Carvalho Chehab > <mchehab@kernel.org>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski > <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Mark Brown > <broonie@kernel.org>; Sakari Ailus <sakari.ailus@linux.intel.com>; iwamatsu > nobuhiro(岩松 信洋 ○DITC□DIT○OST) > <nobuhiro1.iwamatsu@toshiba.co.jp>; linux-media@vger.kernel.org; > devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org; > linux-kernel@vger.kernel.org; Krzysztof Kozlowski > <krzysztof.kozlowski@linaro.org> > Subject: Re: [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add > Toshiba Visconti Video Input Interface > > Hello Ishikawa-san, > > Thank you for the patch. > > On Tue, Jul 09, 2024 at 09:08:43AM +0900, Yuji Ishikawa wrote: > > Adds the Device Tree binding documentation that allows to describe the > > Video Input Interface found in Toshiba Visconti SoCs. > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > Reviewed-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> > > Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> > > --- > > Changelog v2: > > - no change > > > > Changelog v3: > > - no change > > > > Changelog v4: > > - fix style problems at the v3 patch > > - remove "index" member > > - update example > > > > Changelog v5: > > - no change > > > > Changelog v6: > > - add register definition of BUS-IF and MPU > > > > Changelog v7: > > - remove trailing "bindings" from commit header message > > - remove trailing "Device Tree Bindings" from title > > - fix text wrapping of description > > - change compatible to visconti5-viif > > - explicitly define allowed properties for port::endpoint > > > > Changelog v8: > > - Suggestion from Krzysztof Kozlowski > > - rename bindings description file > > - use block style array instead of inline style > > - remove clock-lane (as it is fixed at position 0) > > - update sample node's name > > - use lowercase hex for literals > > - Suggestion from Laurent Pinchart > > - update description message port::description > > - remove port::endpoint::bus-type as it is fixed to <4> > > - remove port::endpoint::clock-lanes from example > > - add port::endpoint::data-lanes to required parameters list > > - fix sequence of data-lanes: <1 2 3 4> because current driver does not > support data reordering > > - update port::endpoint::data-lanes::description > > - remove redundant type definition for port::endpoint::data-lanes > > > > Changelog v9: > > - place "required" after "properties" > > - dictionary ordering of properties > > > > Changelog v10: > > - no change > > > > Changelog v11: > > - no change > > > > .../media/toshiba,visconti5-viif.yaml | 105 > ++++++++++++++++++ > > 1 file changed, 105 insertions(+) > > create mode 100644 > > Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml > > > > diff --git > > a/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml > > b/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml > > new file mode 100644 > > index 0000000000..97e8bda427 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/media/toshiba,visconti5-viif.y > > +++ aml > > @@ -0,0 +1,105 @@ > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 > > +--- > > +$id: http://devicetree.org/schemas/media/toshiba,visconti5-viif.yaml# > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > + > > +title: Toshiba Visconti5 SoC Video Input Interface > > + > > +maintainers: > > + - Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> > > + > > +description: |- > > + Toshiba Visconti5 SoC Video Input Interface (VIIF) receives MIPI > > +CSI2 video > > + stream, processes the stream with image signal processors (L1ISP, > > +L2ISP), > > + then stores pictures to main memory. > > + > > +properties: > > + compatible: > > + const: toshiba,visconti5-viif > > + > > + reg: > > + items: > > + - description: Registers for capture control > > + - description: Registers for CSI2 receiver control > > + - description: Registers for bus interface unit control > > + - description: Registers for Memory Protection Unit > > Is this part of the VIIF, or some sort of more standalone IOMMU ? In the latter > case, should it be handled by a separate driver ? > The MPU does not have the functionality of a general purpose IOMMU as described in the Linux IOMMU framework. It just blocks VIIF's memory accesses to the specified address range. Because it is configured to block all the accesses by default, I have to set it to by-pass mode at every power cycle. > > + > > + interrupts: > > + items: > > + - description: Sync Interrupt > > + - description: Status (Error) Interrupt > > + - description: CSI2 Receiver Interrupt > > + - description: L1ISP Interrupt > > + > > + port: > > + $ref: /schemas/graph.yaml#/$defs/port-base > > + unevaluatedProperties: false > > + description: CSI-2 input port, with a single endpoint connected to the > CSI-2 transmitter. > > + > > + properties: > > + endpoint: > > + $ref: video-interfaces.yaml# > > + additionalProperties: false > > + > > + properties: > > + data-lanes: > > + description: VIIF supports 1, 2, 3 or 4 data lanes > > + minItems: 1 > > + items: > > + - const: 1 > > + - const: 2 > > + - const: 3 > > + - const: 4 > > + > > + clock-noncontinuous: true > > + link-frequencies: true > > + remote-endpoint: true > > + > > + required: > > + - clock-noncontinuous > > Does the hardware support the non-continuous clock mode only, or is it > configurable ? This is a boolean property, so if both mode are supported, the > property should not be required. > The hardware supports both clock mode and switches them automatically. Therefore, I'll drop this property. > > + - data-lanes > > + - link-frequencies > > + - remote-endpoint > > + > > +required: > > + - compatible > > + - reg > > + - interrupts > > + - port > > + > > +additionalProperties: false > > + > > +examples: > > + - | > > + #include <dt-bindings/interrupt-controller/arm-gic.h> > > + #include <dt-bindings/interrupt-controller/irq.h> > > + > > + soc { > > + #address-cells = <2>; > > + #size-cells = <2>; > > + > > + video@1c000000 { > > + compatible = "toshiba,visconti5-viif"; > > + reg = <0 0x1c000000 0 0x6000>, > > + <0 0x1c008000 0 0x400>, > > + <0 0x1c00e000 0 0x1000>, > > + <0 0x2417a000 0 0x1000>; > > + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, > > + <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, > > + <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>, > > + <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; > > + > > + port { > > + #address-cells = <1>; > > + #size-cells = <0>; > > + > > + csi_in0: endpoint { > > + clock-noncontinuous; > > + data-lanes = <1 2>; > > + link-frequencies = /bits/ 64 <456000000>; > > + remote-endpoint = <&imx219_out0>; > > + }; > > + }; > > + }; > > + }; > > -- > Regards, > > Laurent Pinchart Regards, Yuji Ishikawa ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format 2024-07-09 0:08 [PATCH v11 0/6] Add Toshiba Visconti Video Input Interface driver Yuji Ishikawa 2024-07-09 0:08 ` [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface Yuji Ishikawa @ 2024-07-09 0:08 ` Yuji Ishikawa 2024-07-22 15:10 ` Laurent Pinchart 2024-07-09 0:08 ` [PATCH v11 4/6] media: platform: visconti: add streaming interface for ISP parameters and status Yuji Ishikawa ` (3 subsequent siblings) 5 siblings, 1 reply; 20+ messages in thread From: Yuji Ishikawa @ 2024-07-09 0:08 UTC (permalink / raw) To: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, Yuji Ishikawa Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel Adds the Toshiba Visconti VIIF specific metadata format - V4L2_META_FMT_VISCONTI_VIIF_PARAMS for ISP parameters - V4L2_META_FMT_VISCONTI_VIIF_STATS for ISP statistics Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> --- Changelog v10: - add entry for V4L2_META_FMT_VISCONTI_VIIF_PARAMS - add entry for V4L2_META_FMT_VISCONTI_VIIF_STATS Changelog v11: - no change include/uapi/linux/videodev2.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 4e91362da6..562038f144 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -858,6 +858,10 @@ struct v4l2_pix_format { /* Vendor specific - used for RaspberryPi PiSP */ #define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') /* PiSP BE configuration */ +/* Vendor specific - used for Visconti VIIF sub-system */ +#define V4L2_META_FMT_VISCONTI_VIIF_PARAMS v4l2_fourcc('V', 'I', 'F', 'P') /* ISP Params */ +#define V4L2_META_FMT_VISCONTI_VIIF_STATS v4l2_fourcc('V', 'I', 'F', 'S') /* ISP Stats */ + #ifdef __KERNEL__ /* * Line-based metadata formats. Remember to update v4l_fill_fmtdesc() when -- 2.25.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format 2024-07-09 0:08 ` [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format Yuji Ishikawa @ 2024-07-22 15:10 ` Laurent Pinchart 2024-07-22 15:12 ` Laurent Pinchart 0 siblings, 1 reply; 20+ messages in thread From: Laurent Pinchart @ 2024-07-22 15:10 UTC (permalink / raw) To: Yuji Ishikawa Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hi Ishikawa-san, Thank you for the patch. On Tue, Jul 09, 2024 at 09:08:44AM +0900, Yuji Ishikawa wrote: > Adds the Toshiba Visconti VIIF specific metadata format > > - V4L2_META_FMT_VISCONTI_VIIF_PARAMS for ISP parameters > - V4L2_META_FMT_VISCONTI_VIIF_STATS for ISP statistics > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> This patch looks fine. Assuming the corresponding documentation patch is fine too, Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > Changelog v10: > - add entry for V4L2_META_FMT_VISCONTI_VIIF_PARAMS > - add entry for V4L2_META_FMT_VISCONTI_VIIF_STATS > > Changelog v11: > - no change > > include/uapi/linux/videodev2.h | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h > index 4e91362da6..562038f144 100644 > --- a/include/uapi/linux/videodev2.h > +++ b/include/uapi/linux/videodev2.h > @@ -858,6 +858,10 @@ struct v4l2_pix_format { > /* Vendor specific - used for RaspberryPi PiSP */ > #define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') /* PiSP BE configuration */ > > +/* Vendor specific - used for Visconti VIIF sub-system */ > +#define V4L2_META_FMT_VISCONTI_VIIF_PARAMS v4l2_fourcc('V', 'I', 'F', 'P') /* ISP Params */ > +#define V4L2_META_FMT_VISCONTI_VIIF_STATS v4l2_fourcc('V', 'I', 'F', 'S') /* ISP Stats */ > + > #ifdef __KERNEL__ > /* > * Line-based metadata formats. Remember to update v4l_fill_fmtdesc() when -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format 2024-07-22 15:10 ` Laurent Pinchart @ 2024-07-22 15:12 ` Laurent Pinchart 2024-08-01 9:20 ` yuji2.ishikawa 0 siblings, 1 reply; 20+ messages in thread From: Laurent Pinchart @ 2024-07-22 15:12 UTC (permalink / raw) To: Yuji Ishikawa Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel On Mon, Jul 22, 2024 at 06:10:37PM +0300, Laurent Pinchart wrote: > Hi Ishikawa-san, > > Thank you for the patch. > > On Tue, Jul 09, 2024 at 09:08:44AM +0900, Yuji Ishikawa wrote: > > Adds the Toshiba Visconti VIIF specific metadata format > > > > - V4L2_META_FMT_VISCONTI_VIIF_PARAMS for ISP parameters > > - V4L2_META_FMT_VISCONTI_VIIF_STATS for ISP statistics > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > This patch looks fine. Assuming the corresponding documentation patch is > fine too, > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Actually I spoke a bit too fast, you need to update drivers/media/v4l2-core/v4l2-ioctl.c with the two new formats. See commit 8f6c2202222fa for an example. > > --- > > Changelog v10: > > - add entry for V4L2_META_FMT_VISCONTI_VIIF_PARAMS > > - add entry for V4L2_META_FMT_VISCONTI_VIIF_STATS > > > > Changelog v11: > > - no change > > > > include/uapi/linux/videodev2.h | 4 ++++ > > 1 file changed, 4 insertions(+) > > > > diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h > > index 4e91362da6..562038f144 100644 > > --- a/include/uapi/linux/videodev2.h > > +++ b/include/uapi/linux/videodev2.h > > @@ -858,6 +858,10 @@ struct v4l2_pix_format { > > /* Vendor specific - used for RaspberryPi PiSP */ > > #define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') /* PiSP BE configuration */ > > > > +/* Vendor specific - used for Visconti VIIF sub-system */ > > +#define V4L2_META_FMT_VISCONTI_VIIF_PARAMS v4l2_fourcc('V', 'I', 'F', 'P') /* ISP Params */ > > +#define V4L2_META_FMT_VISCONTI_VIIF_STATS v4l2_fourcc('V', 'I', 'F', 'S') /* ISP Stats */ > > + > > #ifdef __KERNEL__ > > /* > > * Line-based metadata formats. Remember to update v4l_fill_fmtdesc() when -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format 2024-07-22 15:12 ` Laurent Pinchart @ 2024-08-01 9:20 ` yuji2.ishikawa 0 siblings, 0 replies; 20+ messages in thread From: yuji2.ishikawa @ 2024-08-01 9:20 UTC (permalink / raw) To: laurent.pinchart Cc: hverkuil, mchehab, robh, krzk+dt, conor+dt, broonie, sakari.ailus, nobuhiro1.iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hello Laurent, Thank you for your review comments. > -----Original Message----- > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Sent: Tuesday, July 23, 2024 12:12 AM > To: ishikawa yuji(石川 悠司 ○RDC□AITC○EA開) > <yuji2.ishikawa@toshiba.co.jp> > Cc: Hans Verkuil <hverkuil@xs4all.nl>; Mauro Carvalho Chehab > <mchehab@kernel.org>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski > <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Mark Brown > <broonie@kernel.org>; Sakari Ailus <sakari.ailus@linux.intel.com>; iwamatsu > nobuhiro(岩松 信洋 ○DITC□DIT○OST) > <nobuhiro1.iwamatsu@toshiba.co.jp>; linux-media@vger.kernel.org; > devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer > format > > On Mon, Jul 22, 2024 at 06:10:37PM +0300, Laurent Pinchart wrote: > > Hi Ishikawa-san, > > > > Thank you for the patch. > > > > On Tue, Jul 09, 2024 at 09:08:44AM +0900, Yuji Ishikawa wrote: > > > Adds the Toshiba Visconti VIIF specific metadata format > > > > > > - V4L2_META_FMT_VISCONTI_VIIF_PARAMS for ISP parameters > > > - V4L2_META_FMT_VISCONTI_VIIF_STATS for ISP statistics > > > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > > > This patch looks fine. Assuming the corresponding documentation patch > > is fine too, > > > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > Actually I spoke a bit too fast, you need to update > drivers/media/v4l2-core/v4l2-ioctl.c with the two new formats. See commit > 8f6c2202222fa for an example. > I'll add some operations to v4l_fill_fmtdesc() as described in the specified patch. > > > --- > > > Changelog v10: > > > - add entry for V4L2_META_FMT_VISCONTI_VIIF_PARAMS > > > - add entry for V4L2_META_FMT_VISCONTI_VIIF_STATS > > > > > > Changelog v11: > > > - no change > > > > > > include/uapi/linux/videodev2.h | 4 ++++ > > > 1 file changed, 4 insertions(+) > > > > > > diff --git a/include/uapi/linux/videodev2.h > > > b/include/uapi/linux/videodev2.h index 4e91362da6..562038f144 100644 > > > --- a/include/uapi/linux/videodev2.h > > > +++ b/include/uapi/linux/videodev2.h > > > @@ -858,6 +858,10 @@ struct v4l2_pix_format { > > > /* Vendor specific - used for RaspberryPi PiSP */ > > > #define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') /* > PiSP BE configuration */ > > > > > > +/* Vendor specific - used for Visconti VIIF sub-system */ > > > +#define V4L2_META_FMT_VISCONTI_VIIF_PARAMS > v4l2_fourcc('V', 'I', 'F', 'P') /* ISP Params */ > > > +#define V4L2_META_FMT_VISCONTI_VIIF_STATS v4l2_fourcc('V', 'I', 'F', > 'S') /* ISP Stats */ > > > + > > > #ifdef __KERNEL__ > > > /* > > > * Line-based metadata formats. Remember to update > > > v4l_fill_fmtdesc() when > > -- > Regards, > > Laurent Pinchart Regards, Yuji Ishikawa ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v11 4/6] media: platform: visconti: add streaming interface for ISP parameters and status 2024-07-09 0:08 [PATCH v11 0/6] Add Toshiba Visconti Video Input Interface driver Yuji Ishikawa 2024-07-09 0:08 ` [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface Yuji Ishikawa 2024-07-09 0:08 ` [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format Yuji Ishikawa @ 2024-07-09 0:08 ` Yuji Ishikawa 2024-07-09 0:08 ` [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver Yuji Ishikawa ` (2 subsequent siblings) 5 siblings, 0 replies; 20+ messages in thread From: Yuji Ishikawa @ 2024-07-09 0:08 UTC (permalink / raw) To: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, Yuji Ishikawa Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel Add support to Image Signal Processors of Visconti's Video Input Interface. This patch adds two streaming interfaces; one for passing parameters to the signal processor, the other for receiving status. Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> --- Changelog v2: - Resend v1 because a patch exceeds size limit. Changelog v3: - Adapted to media control framework - Introduced ISP subdevice, capture device - Remove private IOCTLs and add vendor specific V4L2 controls - Change function name avoiding camelcase and uppercase letters Changelog v4: - Split patches because the v3 patch exceeds size limit - Stop using ID number to identify driver instance: - Use dynamically allocated structure to hold HW specific context, instead of static one. - Call HW layer functions with the context structure instead of ID number Changelog v5: - no change Changelog v6: - remove unused macros - removed hwd_ and HWD_ prefix - update source code documentation - Suggestion from Hans Verkuil - pointer to userland memory is removed from uAPI arguments - style of structure is now "nested" instead of "chained by pointer"; - use div64_u64 for 64bit division - vendor specific controls support TRY_EXT_CTRLS - add READ_ONLY flag to GET_CALIBRATION_STATUS control and similar ones - human friendry control names for vendor specific controls - add initial value to each vendor specific control - GET_LAST_CAPTURE_STATUS control is updated asyncnously from workqueue - remove EXECUTE_ON_WRITE flag of vendor specific control - uAPI: return value of GET_CALIBRATION_STATUS follows common rules of error codes - applied v4l2-compliance - Suggestion from Sakari Ailus - use div64_u64 for 64bit division - update copyright's year - remove redandunt cast - use bool instead of HWD_VIIF_ENABLE/DISABLE - simplify comparison to 0 - simplify statements with trigram operator - remove redundant local variables - use general integer types instead of u32/s32 - Suggestion from Laurent Pinchart - moved VIIF driver to driver/platform/toshiba/visconti - change register access: struct-style to macro-style - remove unused type definitions - define enums instead of successive macro constants - remove redundant parenthesis of macro constant - embed struct hwd_res into struct viif_device - use xxx_dma instead of xxx_paddr for variable names of IOVA - literal value: just 0 instead of 0x0 - use literal 1 or 0 instead of HWD_VIIF_ENABLE, DISABLE for register access - use true or false instead of HWD_VIIF_ENABLE, DISABLE for function calls - uAPI: return value of GET_CALIBRATION_STATUS follows common rules of error codes Changelog v7: - remove unused variables - split long statements which have multiple logical-OR and trigram operators Changelog v8: - define constant V4L2_CTRL_TYPE_VISCONTI_ISP for datatype of Visconti specific controls - Suggestion from Hans Verkuil - remove pr_info() - use pm_runtime_get_if_in_use() to get power status Changelog v9: - fix warning for cast between ptr and dma_addr_t Changelog v10: - use parameter buffer instead of vendor specific compound controls - add viif_params interface for passing ISP parameters - add viif_stats interface for passing ISP status - remove parameter validation routine; moved to userland library Changelog v11: - remove feature VB2_USERPTR from viif_params and viif_stats - fix strange indents at initializations - remove a redundant default setting of the ISP: L2_ROI - update copyright year .../media/platform/toshiba/visconti/Makefile | 2 +- .../media/platform/toshiba/visconti/viif.c | 28 +- .../platform/toshiba/visconti/viif_isp.c | 7 + .../platform/toshiba/visconti/viif_params.c | 2020 +++++++++++++++++ .../platform/toshiba/visconti/viif_params.h | 19 + .../platform/toshiba/visconti/viif_stats.c | 336 +++ .../platform/toshiba/visconti/viif_stats.h | 14 + 7 files changed, 2423 insertions(+), 3 deletions(-) create mode 100644 drivers/media/platform/toshiba/visconti/viif_params.c create mode 100644 drivers/media/platform/toshiba/visconti/viif_params.h create mode 100644 drivers/media/platform/toshiba/visconti/viif_stats.c create mode 100644 drivers/media/platform/toshiba/visconti/viif_stats.h diff --git a/drivers/media/platform/toshiba/visconti/Makefile b/drivers/media/platform/toshiba/visconti/Makefile index 5f2f9199c7..8afe8a3fdd 100644 --- a/drivers/media/platform/toshiba/visconti/Makefile +++ b/drivers/media/platform/toshiba/visconti/Makefile @@ -3,6 +3,6 @@ # Makefile for the Visconti video input device driver # -visconti-viif-objs = viif.o viif_capture.o viif_isp.o viif_csi2rx.o viif_common.o +visconti-viif-objs = viif.o viif_capture.o viif_isp.o viif_csi2rx.o viif_common.o viif_params.o viif_stats.o obj-$(CONFIG_VIDEO_VISCONTI_VIIF) += visconti-viif.o diff --git a/drivers/media/platform/toshiba/visconti/viif.c b/drivers/media/platform/toshiba/visconti/viif.c index 472b292752..0261058c62 100644 --- a/drivers/media/platform/toshiba/visconti/viif.c +++ b/drivers/media/platform/toshiba/visconti/viif.c @@ -19,6 +19,8 @@ #include "viif.h" #include "viif_capture.h" #include "viif_csi2rx.h" +#include "viif_params.h" +#include "viif_stats.h" #include "viif_common.h" #include "viif_isp.h" #include "viif_regs.h" @@ -172,6 +174,8 @@ static void viif_vsync_irq_handler_w_isp(struct viif_device *viif_dev) /* Delayed Vsync of MAIN unit */ if (event_main & MASK_INT_M_SYNC_LINES_DELAY_INT2) { + unsigned int seq0 = viif_dev->cap_dev0.sequence; + /* unmask timeout error of gamma table */ viif_main_status_err_set_irq_mask(viif_dev, MASK_INT_M_DELAY_INT_ERROR); viif_dev->masked_gamma_path = 0; @@ -190,6 +194,8 @@ static void viif_vsync_irq_handler_w_isp(struct viif_device *viif_dev) l2_transfer_status, ts); visconti_viif_capture_switch_buffer(&viif_dev->cap_dev1, status_err, l2_transfer_status, ts); + visconti_viif_stats_isr(viif_dev, seq0, ts); + visconti_viif_params_isr(viif_dev); } /* Delayed Vsync of SUB unit */ @@ -526,16 +532,32 @@ static int visconti_viif_probe(struct platform_device *pdev) goto error_isp_unregister; } + ret = visconti_viif_params_register(viif_dev); + if (ret) { + dev_err_probe(dev, ret, "failed to register parameter node\n"); + goto error_capture_unregister; + } + + ret = visconti_viif_stats_register(viif_dev); + if (ret) { + dev_err_probe(dev, ret, "failed to register stat node\n"); + goto error_params_unregister; + } + ret = visconti_viif_create_links(viif_dev); if (ret) - goto error_capture_unregister; + goto error_stats_unregister; visconti_viif_subdev_notifier_register(viif_dev); if (ret) - goto error_capture_unregister; + goto error_stats_unregister; return 0; +error_stats_unregister: + visconti_viif_stats_unregister(viif_dev); +error_params_unregister: + visconti_viif_params_unregister(viif_dev); error_capture_unregister: visconti_viif_capture_unregister(viif_dev); error_isp_unregister: @@ -560,6 +582,8 @@ static int visconti_viif_remove(struct platform_device *pdev) v4l2_async_nf_unregister(&viif_dev->notifier); v4l2_async_nf_cleanup(&viif_dev->notifier); visconti_viif_capture_unregister(viif_dev); + visconti_viif_params_unregister(viif_dev); + visconti_viif_stats_unregister(viif_dev); visconti_viif_isp_unregister(viif_dev); visconti_viif_csi2rx_unregister(viif_dev); media_device_unregister(&viif_dev->media_dev); diff --git a/drivers/media/platform/toshiba/visconti/viif_isp.c b/drivers/media/platform/toshiba/visconti/viif_isp.c index 7a66aac715..fe2de44457 100644 --- a/drivers/media/platform/toshiba/visconti/viif_isp.c +++ b/drivers/media/platform/toshiba/visconti/viif_isp.c @@ -14,6 +14,7 @@ #include "viif.h" #include "viif_common.h" #include "viif_isp.h" +#include "viif_params.h" #include "viif_regs.h" /* disable CSI2 capture at viif_mux_start() */ @@ -745,6 +746,10 @@ int visconti_viif_isp_main_set_unit(struct viif_device *viif_dev) /* Enable regbuf */ hwd_viif_isp_set_regbuf_auto_transmission(viif_dev); + /* L2 UNDIST Enable through mode as default */ + ret = visconti_viif_l2_undist_through(viif_dev); + if (ret) + dev_err(viif_dev->dev, "l2_set_undist error. %d\n", ret); return ret; } @@ -798,6 +803,8 @@ static int visconti_viif_isp_s_stream(struct v4l2_subdev *sd, int enable) } /* enabling: start ISP, MUX -> start CSI2RX, sensor */ + // prepare ISP parameters + visconti_viif_params_eval_queue(viif_dev); // start ISP viif_dev->masked_gamma_path = 0; viif_mux_start(viif_dev, 0, 0); diff --git a/drivers/media/platform/toshiba/visconti/viif_params.c b/drivers/media/platform/toshiba/visconti/viif_params.c new file mode 100644 index 0000000000..45c1a10fbc --- /dev/null +++ b/drivers/media/platform/toshiba/visconti/viif_params.c @@ -0,0 +1,2020 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* Toshiba Visconti Video Capture Support + * + * (C) Copyright 2024 TOSHIBA CORPORATION + * (C) Copyright 2024 Toshiba Electronic Devices & Storage Corporation + */ + +#include <linux/delay.h> +#include <linux/pm_runtime.h> +#include <media/v4l2-common.h> +#include <media/v4l2-subdev.h> +#include <media/videobuf2-vmalloc.h> + +#include "viif.h" +#include "viif_csi2rx.h" +#include "viif_isp.h" +#include "viif_common.h" +#include "viif_regs.h" +#include "viif_params.h" + +/* ISP_L1_SET_HDRC */ +#define VIIF_L1_HDRC_RATIO_OFFSET 10U +#define VIIF_REGBUF_ACCESS_TIME 15360UL +#define VIIF_L1_DELAY_W_HDRC 31U + +/* V4L2_CID_VISCONTI_VIIF_ISP_L2_SET_UNDIST */ +#define VIIF_L2_UNDIST_POLY_NUM 11U + +/*=======================================================================*/ +/* ISP parameter configuration */ +/*=======================================================================*/ +static void viif_l1_set_input_mode(struct viif_device *viif_dev, + const struct viif_l1_input_mode_config *arg) +{ + unsigned long irqflags; + + /* values are already tested in _try*/ + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_SYSM_INPUT_MODE, (u32)arg->mode); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_rgb_to_y_coef(struct viif_device *viif_dev, + const struct viif_l1_rgb_to_y_coef_config *arg) +{ + unsigned long irqflags; + + /* value is already tested in _try*/ + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_SYSM_YCOEF_R, (u32)arg->coef_r); + viif_capture_write(viif_dev, REG_L1_SYSM_YCOEF_G, (u32)arg->coef_g); + viif_capture_write(viif_dev, REG_L1_SYSM_YCOEF_B, (u32)arg->coef_b); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_ag_mode(struct viif_device *viif_dev, + const struct viif_l1_ag_mode_config *arg) +{ + unsigned long irqflags; + u32 val; + + /* value is already tested in _try*/ + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + /* SYSM_AG_PARAM */ + viif_capture_write(viif_dev, REG_L1_SYSM_AG_PARAM_A, + PACK_L1_SYSM_AG_PARAM(arg->sysm_ag_grad[0], arg->sysm_ag_ofst[0])); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_PARAM_B, + PACK_L1_SYSM_AG_PARAM(arg->sysm_ag_grad[1], arg->sysm_ag_ofst[1])); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_PARAM_C, + PACK_L1_SYSM_AG_PARAM(arg->sysm_ag_grad[2], arg->sysm_ag_ofst[2])); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_PARAM_D, + PACK_L1_SYSM_AG_PARAM(arg->sysm_ag_grad[3], arg->sysm_ag_ofst[3])); + + /* SYSM_AG_SEL */ + viif_capture_write(viif_dev, REG_L1_SYSM_AG_SEL_HOBC, + PACK_L1_SYSM_AG_SEL_HML(arg->sysm_ag_psel_hobc_high, + arg->sysm_ag_psel_hobc_middle_led, + arg->sysm_ag_psel_hobc_low)); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_SEL_ABPC, + PACK_L1_SYSM_AG_SEL_HML(arg->sysm_ag_psel_abpc_high, + arg->sysm_ag_psel_abpc_middle_led, + arg->sysm_ag_psel_abpc_low)); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_SEL_RCNR, + PACK_L1_SYSM_AG_SEL_HML(arg->sysm_ag_psel_rcnr_high, + arg->sysm_ag_psel_rcnr_middle_led, + arg->sysm_ag_psel_rcnr_low)); + + viif_capture_write(viif_dev, REG_L1_SYSM_AG_SEL_LSSC, + PACK_L1_SYSM_AG_SEL_SP(arg->sysm_ag_ssel_lssc, arg->sysm_ag_psel_lssc)); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_SEL_MPRO, + PACK_L1_SYSM_AG_SEL_SP(arg->sysm_ag_ssel_mpro, arg->sysm_ag_psel_mpro)); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_SEL_VPRO, + PACK_L1_SYSM_AG_SEL_SP(arg->sysm_ag_ssel_vpro, arg->sysm_ag_psel_vpro)); + + /* SYSM_AG_CONT */ + val = arg->sysm_ag_cont_hobc_en_middle_led ? MASK_L1_SYSM_AG_CONT_M_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_M_VAL, arg->sysm_ag_cont_hobc_test_middle_led); + val |= arg->sysm_ag_cont_hobc_en_high ? MASK_L1_SYSM_AG_CONT_H_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_H_VAL, arg->sysm_ag_cont_hobc_test_high); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_HOBC01_EN, val); + + val = arg->sysm_ag_cont_hobc_en_low ? MASK_L1_SYSM_AG_CONT_L_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_L_VAL, arg->sysm_ag_cont_hobc_test_low); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_HOBC2_EN, val); + + val = arg->sysm_ag_cont_abpc_en_middle_led ? MASK_L1_SYSM_AG_CONT_M_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_M_VAL, arg->sysm_ag_cont_abpc_test_middle_led); + val |= arg->sysm_ag_cont_abpc_en_high ? MASK_L1_SYSM_AG_CONT_H_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_H_VAL, arg->sysm_ag_cont_abpc_test_high); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_ABPC01_EN, val); + + val = arg->sysm_ag_cont_abpc_en_low ? MASK_L1_SYSM_AG_CONT_L_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_L_VAL, arg->sysm_ag_cont_abpc_test_low); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_ABPC2_EN, val); + + val = arg->sysm_ag_cont_rcnr_en_middle_led ? MASK_L1_SYSM_AG_CONT_M_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_M_VAL, arg->sysm_ag_cont_rcnr_test_middle_led); + val |= arg->sysm_ag_cont_rcnr_en_high ? MASK_L1_SYSM_AG_CONT_H_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_H_VAL, arg->sysm_ag_cont_rcnr_test_high); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_RCNR01_EN, val); + + val = arg->sysm_ag_cont_rcnr_en_low ? MASK_L1_SYSM_AG_CONT_L_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_L_VAL, arg->sysm_ag_cont_rcnr_test_low); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_RCNR2_EN, val); + + val = arg->sysm_ag_cont_lssc_en ? MASK_L1_SYSM_AG_CONT_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_VAL, arg->sysm_ag_cont_lssc_test); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_LSSC_EN, val); + + val = arg->sysm_ag_cont_mpro_en ? MASK_L1_SYSM_AG_CONT_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_VAL, arg->sysm_ag_cont_mpro_test); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_MPRO_EN, val); + + val = arg->sysm_ag_cont_vpro_en ? MASK_L1_SYSM_AG_CONT_EN : 0; + val |= FIELD_PREP(MASK_L1_SYSM_AG_CONT_VAL, arg->sysm_ag_cont_vpro_test); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_CONT_VPRO_EN, val); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_ag(struct viif_device *viif_dev, const struct viif_l1_ag_config *arg) +{ + unsigned long irqflags; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_SYSM_AG_H, (u32)arg->gain_h); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_M, (u32)arg->gain_m); + viif_capture_write(viif_dev, REG_L1_SYSM_AG_L, (u32)arg->gain_l); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_hdre(struct viif_device *viif_dev, const struct viif_l1_hdre_config *arg) +{ + unsigned long irqflags; + int i; + + /* value is already tested in _try*/ + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + for (i = 0; i < LEN_L1_HDRE_SRCPOINT; i++) + viif_capture_write(viif_dev, REG_L1_HDRE_SRCPOINT(i), arg->hdre_src_point[i]); + + viif_capture_write(viif_dev, REG_L1_HDRE_SRCBASE(0), 0); + for (i = 1; i < LEN_L1_HDRE_SRCBASE; i++) + viif_capture_write(viif_dev, REG_L1_HDRE_SRCBASE(i), arg->hdre_src_point[i - 1]); + + for (i = 0; i < LEN_L1_HDRE_DSTBASE; i++) + viif_capture_write(viif_dev, REG_L1_HDRE_DSTBASE(i), arg->hdre_dst_base[i]); + + for (i = 0; i < LEN_L1_HDRE_RATIO; i++) + viif_capture_write(viif_dev, REG_L1_HDRE_RATIO(i), arg->hdre_ratio[i]); + + viif_capture_write(viif_dev, REG_L1_HDRE_DSTMAXVAL, arg->hdre_dst_max_val); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_img_extraction(struct viif_device *viif_dev, + const struct viif_l1_img_extraction_config *arg) +{ + unsigned long irqflags; + + /* value is already tested in _try*/ + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_SLIC_SRCBLACKLEVEL_GR, arg->input_black_gr); + viif_capture_write(viif_dev, REG_L1_SLIC_SRCBLACKLEVEL_R, arg->input_black_r); + viif_capture_write(viif_dev, REG_L1_SLIC_SRCBLACKLEVEL_B, arg->input_black_b); + viif_capture_write(viif_dev, REG_L1_SLIC_SRCBLACKLEVEL_GB, arg->input_black_gb); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_config_vdm_tgroup(struct viif_device *viif_dev, int idx) +{ + const struct { + u32 cfg; + u32 sram_base; + u32 sram_size; + } conf[] = { + /* T01: L1_SET_DPC, L1_SET_LSC */ + { VAL_TGROUP_CFG_64BIT_RD, 0x600, 0x20 }, + /* T02: L2_UNDIST grid table */ + { VAL_TGROUP_CFG_32BIT_RD, 0x620, 0x20 }, + /* T02: L2_GAMMA (path0) */ + { VAL_TGROUP_CFG_32BIT_RD, 0x640, 0x20 }, + /* T03: L2 GAMMA (path1) */ + { VAL_TGROUP_CFG_32BIT_RD, 0x660, 0x20 }, + }; + + viif_capture_write(viif_dev, REG_VDM_TGROUP_X_CFG(idx), conf[idx].cfg); + viif_capture_write(viif_dev, REG_VDM_TGROUP_X_SRAM_BASE(idx), conf[idx].sram_base); + viif_capture_write(viif_dev, REG_VDM_TGROUP_X_SRAM_SIZE(idx), conf[idx].sram_size); +} + +static void dpc_table_transmission(struct viif_device *viif_dev, uintptr_t table_h, + uintptr_t table_m, uintptr_t table_l) +{ + u32 val = 0x0U; + + viif_config_vdm_tgroup(viif_dev, IDX_TGROUP_L1_ISP); + + if (table_h) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L1_DPC_H), + (u32)table_h); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L1_DPC_H), + VIIF_DPC_TABLE_BYTES); + val |= MASK_VDM_T_ENABLE_L1_DPC_H; + } + + if (table_m) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L1_DPC_M), + (u32)table_m); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L1_DPC_M), + VIIF_DPC_TABLE_BYTES); + val |= MASK_VDM_T_ENABLE_L1_DPC_M; + } + + if (table_l) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L1_DPC_L), + (u32)table_l); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L1_DPC_L), + VIIF_DPC_TABLE_BYTES); + val |= MASK_VDM_T_ENABLE_L1_DPC_L; + } + + val |= (viif_capture_read(viif_dev, REG_VDM_T_ENABLE) & ~MASK_VDM_T_ENABLE_L1_DPC); + viif_capture_write(viif_dev, REG_VDM_T_ENABLE, val); +} + +static void viif_l1_set_dpc(struct viif_device *viif_dev, const struct viif_l1_dpc_config *arg) +{ + const struct viif_l1_dpc *param_h, *param_m, *param_l; + dma_addr_t table_h = 0; + dma_addr_t table_m = 0; + dma_addr_t table_l = 0; + unsigned long irqflags; + u32 val; + + if (arg->param_h.abpc_sta_en) { + memcpy(viif_dev->tables->dpc_table_h, arg->table_h, VIIF_DPC_TABLE_BYTES); + table_h = (dma_addr_t)(uintptr_t)viif_dev->tables_dma->dpc_table_h; + } + if (arg->param_m.abpc_sta_en) { + memcpy(viif_dev->tables->dpc_table_m, arg->table_m, VIIF_DPC_TABLE_BYTES); + table_m = (dma_addr_t)(uintptr_t)viif_dev->tables_dma->dpc_table_m; + } + if (arg->param_l.abpc_sta_en) { + memcpy(viif_dev->tables->dpc_table_l, arg->table_l, VIIF_DPC_TABLE_BYTES); + table_l = (dma_addr_t)(uintptr_t)viif_dev->tables_dma->dpc_table_l; + } + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + dpc_table_transmission(viif_dev, table_h, table_m, table_l); + + param_h = &arg->param_h; + param_m = &arg->param_m; + param_l = &arg->param_l; + + val = (param_h->abpc_sta_en) ? MASK_L1_ABPC_ENABLE_H : 0; + val |= (param_m->abpc_sta_en) ? MASK_L1_ABPC_ENABLE_M : 0; + val |= (param_l->abpc_sta_en) ? MASK_L1_ABPC_ENABLE_L : 0; + viif_capture_write(viif_dev, REG_L1_ABPC012_STA_EN, val); + + val = (param_h->abpc_dyn_en) ? MASK_L1_ABPC_ENABLE_H : 0; + val |= (param_m->abpc_dyn_en) ? MASK_L1_ABPC_ENABLE_M : 0; + val |= (param_l->abpc_dyn_en) ? MASK_L1_ABPC_ENABLE_L : 0; + viif_capture_write(viif_dev, REG_L1_ABPC012_DYN_EN, val); + + val = (param_h->abpc_dyn_mode == VIIF_L1_DPC_2PIXEL) ? MASK_L1_ABPC_DYN_MODE_2PIXEL_H : 0; + val |= (param_m->abpc_dyn_mode == VIIF_L1_DPC_2PIXEL) ? MASK_L1_ABPC_DYN_MODE_2PIXEL_M : 0; + val |= (param_l->abpc_dyn_mode == VIIF_L1_DPC_2PIXEL) ? MASK_L1_ABPC_DYN_MODE_2PIXEL_L : 0; + viif_capture_write(viif_dev, REG_L1_ABPC012_DYN_MODE, val); + + /* setup param_h */ + viif_capture_write(viif_dev, REG_L1_ABPC0_RATIO_LIMIT, param_h->abpc_ratio_limit); + viif_capture_write(viif_dev, REG_L1_ABPC0_DARK_LIMIT, param_h->abpc_dark_limit); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_W_AG_MIN, param_h->abpc_sn_coef_w_ag_min); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_W_AG_MID, param_h->abpc_sn_coef_w_ag_mid); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_W_AG_MAX, param_h->abpc_sn_coef_w_ag_max); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_B_AG_MIN, param_h->abpc_sn_coef_b_ag_min); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_B_AG_MID, param_h->abpc_sn_coef_b_ag_mid); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_B_AG_MAX, param_h->abpc_sn_coef_b_ag_max); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_W_TH_MIN, param_h->abpc_sn_coef_w_th_min); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_W_TH_MAX, param_h->abpc_sn_coef_w_th_max); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_B_TH_MIN, param_h->abpc_sn_coef_b_th_min); + viif_capture_write(viif_dev, REG_L1_ABPC0_SN_COEF_B_TH_MAX, param_h->abpc_sn_coef_b_th_max); + + /* setup param_m */ + viif_capture_write(viif_dev, REG_L1_ABPC1_RATIO_LIMIT, param_m->abpc_ratio_limit); + viif_capture_write(viif_dev, REG_L1_ABPC1_DARK_LIMIT, param_m->abpc_dark_limit); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_W_AG_MIN, param_m->abpc_sn_coef_w_ag_min); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_W_AG_MID, param_m->abpc_sn_coef_w_ag_mid); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_W_AG_MAX, param_m->abpc_sn_coef_w_ag_max); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_B_AG_MIN, param_m->abpc_sn_coef_b_ag_min); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_B_AG_MID, param_m->abpc_sn_coef_b_ag_mid); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_B_AG_MAX, param_m->abpc_sn_coef_b_ag_max); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_W_TH_MIN, param_m->abpc_sn_coef_w_th_min); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_W_TH_MAX, param_m->abpc_sn_coef_w_th_max); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_B_TH_MIN, param_m->abpc_sn_coef_b_th_min); + viif_capture_write(viif_dev, REG_L1_ABPC1_SN_COEF_B_TH_MAX, param_m->abpc_sn_coef_b_th_max); + + /* setup param_l */ + viif_capture_write(viif_dev, REG_L1_ABPC2_RATIO_LIMIT, param_l->abpc_ratio_limit); + viif_capture_write(viif_dev, REG_L1_ABPC2_DARK_LIMIT, param_l->abpc_dark_limit); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_W_AG_MIN, param_l->abpc_sn_coef_w_ag_min); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_W_AG_MID, param_l->abpc_sn_coef_w_ag_mid); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_W_AG_MAX, param_l->abpc_sn_coef_w_ag_max); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_B_AG_MIN, param_l->abpc_sn_coef_b_ag_min); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_B_AG_MID, param_l->abpc_sn_coef_b_ag_mid); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_B_AG_MAX, param_l->abpc_sn_coef_b_ag_max); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_W_TH_MIN, param_l->abpc_sn_coef_w_th_min); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_W_TH_MAX, param_l->abpc_sn_coef_w_th_max); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_B_TH_MIN, param_l->abpc_sn_coef_b_th_min); + viif_capture_write(viif_dev, REG_L1_ABPC2_SN_COEF_B_TH_MAX, param_l->abpc_sn_coef_b_th_max); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_preset_white_balance(struct viif_device *viif_dev, + const struct viif_l1_preset_white_balance_config *arg) +{ + const struct viif_l1_preset_wb *param_h, *param_m, *param_l; + unsigned long irqflags; + + param_h = &arg->param_h; + param_m = &arg->param_m; + param_l = &arg->param_l; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_PWHB_DSTMAXVAL, arg->dstmaxval); + + viif_capture_write(viif_dev, REG_L1_PWHB_H_GR, param_h->gain_gr); + viif_capture_write(viif_dev, REG_L1_PWHB_HR, param_h->gain_r); + viif_capture_write(viif_dev, REG_L1_PWHB_HB, param_h->gain_b); + viif_capture_write(viif_dev, REG_L1_PWHB_H_GB, param_h->gain_gb); + + viif_capture_write(viif_dev, REG_L1_PWHB_M_GR, param_m->gain_gr); + viif_capture_write(viif_dev, REG_L1_PWHB_MR, param_m->gain_r); + viif_capture_write(viif_dev, REG_L1_PWHB_MB, param_m->gain_b); + viif_capture_write(viif_dev, REG_L1_PWHB_M_GB, param_m->gain_gb); + + viif_capture_write(viif_dev, REG_L1_PWHB_L_GR, param_l->gain_gr); + viif_capture_write(viif_dev, REG_L1_PWHB_LR, param_l->gain_r); + viif_capture_write(viif_dev, REG_L1_PWHB_LB, param_l->gain_b); + viif_capture_write(viif_dev, REG_L1_PWHB_L_GB, param_l->gain_gb); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void +viif_l1_set_raw_color_noise_reduction(struct viif_device *viif_dev, + const struct viif_l1_raw_color_noise_reduction_config *arg) +{ + const struct viif_l1_raw_color_noise_reduction *params[] = { + &arg->param_h, + &arg->param_m, + &arg->param_l, + }; + unsigned long irqflags; + int i; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + for (i = 0; i < 3; i++) { + const struct viif_l1_raw_color_noise_reduction *param = params[i]; + /* param_h */ + viif_capture_write(viif_dev, REG_L1_RCNR_X_SW(i), param->rcnr_sw ? 1 : 0); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_DARK_AG0(i), + param->rcnr_cnf_dark_ag0); + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_DARK_AG1(i), + param->rcnr_cnf_dark_ag1); + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_DARK_AG2(i), + param->rcnr_cnf_dark_ag2); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_RATIO_AG0(i), + param->rcnr_cnf_ratio_ag0); + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_RATIO_AG1(i), + param->rcnr_cnf_ratio_ag1); + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_RATIO_AG2(i), + param->rcnr_cnf_ratio_ag2); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_CLIP_GAIN_R(i), + param->rcnr_cnf_clip_gain_r); + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_CLIP_GAIN_G(i), + param->rcnr_cnf_clip_gain_g); + viif_capture_write(viif_dev, REG_L1_RCNR_X_CNF_CLIP_GAIN_B(i), + param->rcnr_cnf_clip_gain_b); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_A1L_DARK_AG0(i), + param->rcnr_a1l_dark_ag0); + viif_capture_write(viif_dev, REG_L1_RCNR_X_A1L_DARK_AG1(i), + param->rcnr_a1l_dark_ag1); + viif_capture_write(viif_dev, REG_L1_RCNR_X_A1L_DARK_AG2(i), + param->rcnr_a1l_dark_ag2); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_A1L_RATIO_AG0(i), + param->rcnr_a1l_ratio_ag0); + viif_capture_write(viif_dev, REG_L1_RCNR_X_A1L_RATIO_AG1(i), + param->rcnr_a1l_ratio_ag1); + viif_capture_write(viif_dev, REG_L1_RCNR_X_A1L_RATIO_AG2(i), + param->rcnr_a1l_ratio_ag2); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_INF_ZERO_CLIP(i), + param->rcnr_inf_zero_clip); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_D2BLEND_AG0(i), + param->rcnr_merge_d2blend_ag0); + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_D2BLEND_AG1(i), + param->rcnr_merge_d2blend_ag1); + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_D2BLEND_AG2(i), + param->rcnr_merge_d2blend_ag2); + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_BLACK(i), param->rcnr_merge_black); + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_MINDIV(i), + param->rcnr_merge_mindiv); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_HRY_TYPE(i), param->rcnr_hry_type); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_ANF_BLEND_AG0(i), + param->rcnr_anf_blend_ag0); + viif_capture_write(viif_dev, REG_L1_RCNR_X_ANF_BLEND_AG1(i), + param->rcnr_anf_blend_ag1); + viif_capture_write(viif_dev, REG_L1_RCNR_X_ANF_BLEND_AG2(i), + param->rcnr_anf_blend_ag2); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_LPF_THRESHOLD(i), + param->rcnr_lpf_threshold); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_HLBLEND_AG0(i), + param->rcnr_merge_hlblend_ag0); + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_HLBLEND_AG1(i), + param->rcnr_merge_hlblend_ag1); + viif_capture_write(viif_dev, REG_L1_RCNR_X_MERGE_HLBLEND_AG2(i), + param->rcnr_merge_hlblend_ag2); + + viif_capture_write(viif_dev, REG_L1_RCNR_X_GNR_SW(i), param->rcnr_gnr_sw ? 1 : 0); + + if (param->rcnr_gnr_sw) { + viif_capture_write(viif_dev, REG_L1_RCNR_X_GNR_RATIO(i), + param->rcnr_gnr_ratio); + viif_capture_write(viif_dev, REG_L1_RCNR_X_GNR_WIDE_EN(i), + param->rcnr_gnr_wide_en ? 1 : 0); + } + } + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_hdrs(struct viif_device *viif_dev, const struct viif_l1_hdrs_config *arg) +{ + unsigned long irqflags; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_HDRS_HDRMODE, arg->hdrs_hdr_mode); + + viif_capture_write(viif_dev, REG_L1_HDRS_HDRRATIO_M, arg->hdrs_hdr_ratio_m); + viif_capture_write(viif_dev, REG_L1_HDRS_HDRRATIO_L, arg->hdrs_hdr_ratio_l); + viif_capture_write(viif_dev, REG_L1_HDRS_HDRRATIO_E, arg->hdrs_hdr_ratio_e); + + viif_capture_write(viif_dev, REG_L1_HDRS_DG_H, arg->hdrs_dg_h); + viif_capture_write(viif_dev, REG_L1_HDRS_DG_M, arg->hdrs_dg_m); + viif_capture_write(viif_dev, REG_L1_HDRS_DG_L, arg->hdrs_dg_l); + viif_capture_write(viif_dev, REG_L1_HDRS_DG_E, arg->hdrs_dg_e); + + viif_capture_write(viif_dev, REG_L1_HDRS_BLENDEND_H, arg->hdrs_blendend_h); + viif_capture_write(viif_dev, REG_L1_HDRS_BLENDEND_M, arg->hdrs_blendend_m); + viif_capture_write(viif_dev, REG_L1_HDRS_BLENDEND_E, arg->hdrs_blendend_e); + + viif_capture_write(viif_dev, REG_L1_HDRS_BLENDBEG_H, arg->hdrs_blendbeg_h); + viif_capture_write(viif_dev, REG_L1_HDRS_BLENDBEG_M, arg->hdrs_blendbeg_m); + viif_capture_write(viif_dev, REG_L1_HDRS_BLENDBEG_E, arg->hdrs_blendbeg_e); + + viif_capture_write(viif_dev, REG_L1_HDRS_LEDMODE_ON, arg->hdrs_led_mode_on ? 1 : 0); + viif_capture_write(viif_dev, REG_L1_HDRS_DSTMAXVAL, arg->hdrs_dst_max_val); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void +viif_l1_set_black_level_correction(struct viif_device *viif_dev, + const struct viif_l1_black_level_correction_config *arg) +{ + unsigned long irqflags; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_BLVC_SRCBLACKLEVEL_GR, arg->srcblacklevel_gr); + viif_capture_write(viif_dev, REG_L1_BLVC_SRCBLACKLEVEL_R, arg->srcblacklevel_r); + viif_capture_write(viif_dev, REG_L1_BLVC_SRCBLACKLEVEL_B, arg->srcblacklevel_b); + viif_capture_write(viif_dev, REG_L1_BLVC_SRCBLACKLEVELGB, arg->srcblacklevel_gb); + + viif_capture_write(viif_dev, REG_L1_BLVC_MULTVAL_GR, arg->mulval_gr); + viif_capture_write(viif_dev, REG_L1_BLVC_MULTVAL_R, arg->mulval_r); + viif_capture_write(viif_dev, REG_L1_BLVC_MULTVAL_B, arg->mulval_b); + viif_capture_write(viif_dev, REG_L1_BLVC_MULTVAL_GB, arg->mulval_gb); + + viif_capture_write(viif_dev, REG_L1_BLVC_DSTMAXVAL, arg->dstmaxval); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void lsc_table_transmission(struct viif_device *viif_dev, dma_addr_t table_gr, + dma_addr_t table_r, dma_addr_t table_b, dma_addr_t table_gb) +{ + u32 val = 0x0U; + + viif_config_vdm_tgroup(viif_dev, IDX_TGROUP_L1_ISP); + + if (table_gr) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L1_LSSC_GR), + (u32)table_gr); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L1_LSSC_GR), + VIIF_LSC_TABLE_BYTES); + val |= MASK_VDM_T_ENABLE_L1_LSSC_GR; + } + + if (table_r) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L1_LSSC_R), + (u32)table_r); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L1_LSSC_R), + VIIF_LSC_TABLE_BYTES); + val |= MASK_VDM_T_ENABLE_L1_LSSC_R; + } + + if (table_b) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L1_LSSC_B), + (u32)table_b); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L1_LSSC_B), + VIIF_LSC_TABLE_BYTES); + val |= MASK_VDM_T_ENABLE_L1_LSSC_B; + } + + if (table_gb) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L1_LSSC_GB), + (u32)table_gb); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L1_LSSC_GB), + VIIF_LSC_TABLE_BYTES); + val |= MASK_VDM_T_ENABLE_L1_LSSC_GB; + } + + val |= (viif_capture_read(viif_dev, REG_VDM_T_ENABLE) & ~MASK_VDM_T_ENABLE_L1_LSSC); + viif_capture_write(viif_dev, REG_VDM_T_ENABLE, val); +} + +static inline u32 gen_grid_size(u32 param) +{ + switch (param) { + case 32U: + return 5U; + case 64U: + return 6U; + case 128U: + return 7U; + case 256U: + return 8U; + case 512U: + return 9U; + default: + return 0; + } +} + +#define PACK_PARA_COEF(max, min) (FIELD_PREP(0x1FFF0000, (max)) | FIELD_PREP(0x1FFF, (min))) + +static void viif_l1_set_lsc(struct viif_device *viif_dev, const struct viif_l1_lsc_config *arg) +{ + dma_addr_t table_gr = 0; + dma_addr_t table_gb = 0; + dma_addr_t table_r = 0; + dma_addr_t table_b = 0; + unsigned long irqflags; + u32 val; + + if (!arg->enable) { + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_LSSC_EN, 0); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); + return; + } + + if (arg->enable & VIIF_L1_LSC_GRID_EN_MASK) { + memcpy(viif_dev->tables->lsc_table_gr, arg->table_gr, VIIF_LSC_TABLE_BYTES); + memcpy(viif_dev->tables->lsc_table_r, arg->table_r, VIIF_LSC_TABLE_BYTES); + memcpy(viif_dev->tables->lsc_table_b, arg->table_b, VIIF_LSC_TABLE_BYTES); + memcpy(viif_dev->tables->lsc_table_gb, arg->table_gb, VIIF_LSC_TABLE_BYTES); + table_gr = (dma_addr_t)(uintptr_t)viif_dev->tables_dma->lsc_table_gr; + table_r = (dma_addr_t)(uintptr_t)viif_dev->tables_dma->lsc_table_r; + table_b = (dma_addr_t)(uintptr_t)viif_dev->tables_dma->lsc_table_b; + table_gb = (dma_addr_t)(uintptr_t)viif_dev->tables_dma->lsc_table_gb; + } + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + lsc_table_transmission(viif_dev, table_gr, table_r, table_b, table_gb); + + /* parabola shading */ + if (arg->enable & VIIF_L1_LSC_PARABOLA_EN_MASK) { + const struct viif_l1_lsc_parabola_param *parabola_param = + &arg->param.lssc_parabola_param; + const struct viif_l1_lsc_parabola_ag_param *params[] = { + ¶bola_param->r_2d, ¶bola_param->r_4d, ¶bola_param->gr_2d, + ¶bola_param->gr_4d, ¶bola_param->gb_2d, ¶bola_param->gb_4d, + ¶bola_param->b_2d, ¶bola_param->b_4d, + }; + int i; + + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_EN, 1); + + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_H_CENTER, + parabola_param->lssc_para_h_center); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_V_CENTER, + parabola_param->lssc_para_v_center); + + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_H_GAIN, + parabola_param->lssc_para_h_gain); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_V_GAIN, + parabola_param->lssc_para_v_gain); + + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_MGSEL2, + parabola_param->lssc_para_mgsel2); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_MGSEL4, + parabola_param->lssc_para_mgsel4); + + for (i = 0; i < 8; i++) { + const struct viif_l1_lsc_parabola_ag_param *p = params[i]; + + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_H_L(i), + PACK_PARA_COEF(p->lssc_paracoef_h_l_max, + p->lssc_paracoef_h_l_min)); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_H_R(i), + PACK_PARA_COEF(p->lssc_paracoef_h_r_max, + p->lssc_paracoef_h_r_min)); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_V_U(i), + PACK_PARA_COEF(p->lssc_paracoef_v_u_max, + p->lssc_paracoef_v_u_min)); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_V_D(i), + PACK_PARA_COEF(p->lssc_paracoef_v_d_max, + p->lssc_paracoef_v_d_min)); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_HV_LU(i), + PACK_PARA_COEF(p->lssc_paracoef_hv_lu_max, + p->lssc_paracoef_hv_lu_min)); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_HV_RU(i), + PACK_PARA_COEF(p->lssc_paracoef_hv_ru_max, + p->lssc_paracoef_hv_ru_min)); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_HV_LD(i), + PACK_PARA_COEF(p->lssc_paracoef_hv_ld_max, + p->lssc_paracoef_hv_ld_min)); + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_COEF_X_HV_RD(i), + PACK_PARA_COEF(p->lssc_paracoef_hv_rd_max, + p->lssc_paracoef_hv_rd_min)); + } + } else { + viif_capture_write(viif_dev, REG_L1_LSSC_PARA_EN, 0); + } + + /* grid shading */ + if (arg->enable & VIIF_L1_LSC_GRID_EN_MASK) { + const struct viif_l1_lsc_grid_param *grid_param = &arg->param.lssc_grid_param; + u32 grid_h_size = gen_grid_size(grid_param->lssc_grid_h_size); + u32 grid_v_size = gen_grid_size(grid_param->lssc_grid_v_size); + + viif_capture_write(viif_dev, REG_L1_LSSC_GRID_EN, 1); + viif_capture_write(viif_dev, REG_L1_LSSC_GRID_H_SIZE, grid_h_size); + viif_capture_write(viif_dev, REG_L1_LSSC_GRID_V_SIZE, grid_v_size); + viif_capture_write(viif_dev, REG_L1_LSSC_GRID_H_CENTER, + grid_param->lssc_grid_h_center); + viif_capture_write(viif_dev, REG_L1_LSSC_GRID_V_CENTER, + grid_param->lssc_grid_v_center); + viif_capture_write(viif_dev, REG_L1_LSSC_GRID_MGSEL, grid_param->lssc_grid_mgsel); + + } else { + viif_capture_write(viif_dev, REG_L1_LSSC_GRID_EN, 0); + } + + /* preset white balance */ + val = (arg->param.lssc_pwhb_r_gain_max << 16U) | (arg->param.lssc_pwhb_r_gain_min); + viif_capture_write(viif_dev, REG_L1_LSSC_PWHB_R_GAIN, val); + + val = (arg->param.lssc_pwhb_gr_gain_max << 16U) | (arg->param.lssc_pwhb_gr_gain_min); + viif_capture_write(viif_dev, REG_L1_LSSC_PWHB_GR_GAIN, val); + + val = (arg->param.lssc_pwhb_gb_gain_max << 16U) | (arg->param.lssc_pwhb_gb_gain_min); + viif_capture_write(viif_dev, REG_L1_LSSC_PWHB_GB_GAIN, val); + + val = (arg->param.lssc_pwhb_b_gain_max << 16U) | (arg->param.lssc_pwhb_b_gain_min); + viif_capture_write(viif_dev, REG_L1_LSSC_PWHB_B_GAIN, val); + + viif_capture_write(viif_dev, REG_L1_LSSC_EN, 1); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_main_process(struct viif_device *viif_dev, + const struct viif_l1_main_process_config *arg) +{ + unsigned long irqflags; + u32 val; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_MPRO_CONF, arg->damp_lsbsel << 4); + viif_capture_write(viif_dev, REG_L1_MPRO_LCS_MODE, arg->demosaic_mode); + + if (arg->colormat_enable) { + const struct viif_l1_color_matrix_correction *color_matrix = &arg->colormat_param; + + viif_capture_write(viif_dev, REG_L1_MPRO_SW, 1); + + val = (u32)color_matrix->coef_rmg_min & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_RMG_MIN, val); + + val = (u32)color_matrix->coef_rmg_max & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_RMG_MAX, val); + + val = (u32)color_matrix->coef_rmb_min & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_RMB_MIN, val); + + val = (u32)color_matrix->coef_rmb_max & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_RMB_MAX, val); + + val = (u32)color_matrix->coef_gmr_min & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_GMR_MIN, val); + + val = (u32)color_matrix->coef_gmr_max & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_GMR_MAX, val); + + val = (u32)color_matrix->coef_gmb_min & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_GMB_MIN, val); + + val = (u32)color_matrix->coef_gmb_max & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_GMB_MAX, val); + + val = (u32)color_matrix->coef_bmr_min & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_BMR_MIN, val); + + val = (u32)color_matrix->coef_bmr_max & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_BMR_MAX, val); + + val = (u32)color_matrix->coef_bmg_min & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_BMG_MIN, val); + + val = (u32)color_matrix->coef_bmg_max & 0xffffU; + viif_capture_write(viif_dev, REG_L1_MPRO_LM0_BMG_MAX, val); + + viif_capture_write(viif_dev, REG_L1_MPRO_DST_MINVAL, (u32)color_matrix->dst_minval); + } else { + viif_capture_write(viif_dev, REG_L1_MPRO_SW, 0); + } + + viif_capture_write(viif_dev, REG_L1_MPRO_DST_MAXVAL, arg->dst_maxval); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_awb(struct viif_device *viif_dev, const struct viif_l1_awb_config *arg) +{ + const struct viif_l1_awb *param = &arg->param; + unsigned long irqflags; + u32 val, ygate_data; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_AWHB_WBMRG, arg->awhb_wbmrg); + viif_capture_write(viif_dev, REG_L1_AWHB_WBMGG, arg->awhb_wbmgg); + viif_capture_write(viif_dev, REG_L1_AWHB_WBMBG, arg->awhb_wbmbg); + + val = viif_capture_read(viif_dev, REG_L1_AWHB_SW) & ~MASK_L1_AWHB_SW_EN; + + /* disabling AWB */ + if (!arg->enable) { + viif_capture_write(viif_dev, REG_L1_AWHB_SW, val); + goto op_done; + } + + /* enabling AWB */ + viif_capture_write(viif_dev, REG_L1_AWHB_SW, val | MASK_L1_AWHB_SW_EN); + + if (param->awhb_ygate_data == 64U) + ygate_data = 0U; + else if (param->awhb_ygate_data == 128U) + ygate_data = 1U; + else if (param->awhb_ygate_data == 256U) + ygate_data = 2U; + else + ygate_data = 3U; + + val = param->awhb_ygate_sel ? MASK_L1_AWHB_GATE_YGATE_SEL : 0; + val |= FIELD_PREP(MASK_L1_AWHB_GATE_YGATE_DATA, ygate_data); + val |= FIELD_PREP(MASK_L1_AWHB_GATE_CGRANGE, param->awhb_cgrange); + viif_capture_write(viif_dev, REG_L1_AWHB_GATE_CONF0, val); + + val = param->awhb_ygatesw ? MASK_L1_AWHB_GATE_YGATESW : 0; + val |= param->awhb_hexsw ? MASK_L1_AWHB_GATE_HEXSW : 0; + val |= FIELD_PREP(MASK_L1_AWHB_GATE_AREAMODE, param->awhb_areamode); + viif_capture_write(viif_dev, REG_L1_AWHB_GATE_CONF1, val); + + viif_capture_write(viif_dev, REG_L1_AWHB_AREA_HSIZE, param->awhb_area_hsize); + viif_capture_write(viif_dev, REG_L1_AWHB_AREA_VSIZE, param->awhb_area_vsize); + viif_capture_write(viif_dev, REG_L1_AWHB_AREA_HOFS, param->awhb_area_hofs); + viif_capture_write(viif_dev, REG_L1_AWHB_AREA_VOFS, param->awhb_area_vofs); + + viif_capture_write(viif_dev, REG_L1_AWHB_AREA_MASKH, param->awhb_area_maskh); + viif_capture_write(viif_dev, REG_L1_AWHB_AREA_MASKL, param->awhb_area_maskl); + + val = param->awhb_sq_sw[0] ? MASK_L1_AWHB_SQ_CONF_SQ1SW : 0; + val |= param->awhb_sq_pol[0] ? MASK_L1_AWHB_SQ_CONF_SQ1POL : 0; + val |= param->awhb_sq_sw[1] ? MASK_L1_AWHB_SQ_CONF_SQ2SW : 0; + val |= param->awhb_sq_pol[1] ? MASK_L1_AWHB_SQ_CONF_SQ2POL : 0; + val |= param->awhb_sq_sw[2] ? MASK_L1_AWHB_SQ_CONF_SQ3SW : 0; + val |= param->awhb_sq_pol[2] ? MASK_L1_AWHB_SQ_CONF_SQ3POL : 0; + viif_capture_write(viif_dev, REG_L1_AWHB_SQ_CONF, val); + + viif_capture_write(viif_dev, REG_L1_AWHB_YGATEH, (u32)param->awhb_ygateh); + viif_capture_write(viif_dev, REG_L1_AWHB_YGATEL, (u32)param->awhb_ygatel); + + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT0P, param->awhb_bycut0p); + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT0N, param->awhb_bycut0n); + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT0P, param->awhb_rycut0p); + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT0N, param->awhb_rycut0n); + + val = (u32)param->awhb_rbcut0h & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_RBCUT0H, val); + val = (u32)param->awhb_rbcut0l & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_RBCUT0L, val); + + val = (u32)param->awhb_bycut_h[0] & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT1H, val); + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT1L, param->awhb_bycut_l[0]); + val = (u32)param->awhb_bycut_h[1] & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT2H, val); + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT2L, param->awhb_bycut_l[1]); + val = (u32)param->awhb_bycut_h[2] & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT3H, val); + viif_capture_write(viif_dev, REG_L1_AWHB_BYCUT3L, param->awhb_bycut_l[2]); + + val = (u32)param->awhb_rycut_h[0] & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT1H, val); + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT1L, param->awhb_rycut_l[0]); + val = (u32)param->awhb_rycut_h[1] & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT2H, val); + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT2L, param->awhb_rycut_l[1]); + val = (u32)param->awhb_rycut_h[2] & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT3H, val); + viif_capture_write(viif_dev, REG_L1_AWHB_RYCUT3L, param->awhb_rycut_l[2]); + + val = (u32)param->awhb_awbsftu & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_AWBSFTU, val); + val = (u32)param->awhb_awbsftv & 0xffU; + viif_capture_write(viif_dev, REG_L1_AWHB_AWBSFTV, val); + + val = (param->awhb_awbhuecor ? MASK_L1_AWHB_AWBSPD_HUECOR : 0); + val |= FIELD_PREP(MASK_L1_AWHB_AWBSPD_SPD, param->awhb_awbspd); + viif_capture_write(viif_dev, REG_L1_AWHB_AWBSPD, val); + + viif_capture_write(viif_dev, REG_L1_AWHB_AWBULV, param->awhb_awbulv); + viif_capture_write(viif_dev, REG_L1_AWHB_AWBVLV, param->awhb_awbvlv); + viif_capture_write(viif_dev, REG_L1_AWHB_AWBWAIT, (u32)param->awhb_awbwait); + + viif_capture_write(viif_dev, REG_L1_AWHB_AWBONDOT, param->awhb_awbondot); + viif_capture_write(viif_dev, REG_L1_AWHB_AWBFZTIM, param->awhb_awbfztim); + + viif_capture_write(viif_dev, REG_L1_AWHB_WBGRMAX, (u32)param->awhb_wbgrmax); + viif_capture_write(viif_dev, REG_L1_AWHB_WBGBMAX, (u32)param->awhb_wbgbmax); + viif_capture_write(viif_dev, REG_L1_AWHB_WBGRMIN, (u32)param->awhb_wbgrmin); + viif_capture_write(viif_dev, REG_L1_AWHB_WBGBMIN, (u32)param->awhb_wbgbmin); + +op_done: + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_lock_awb_gain(struct viif_device *viif_dev, const u32 *enable) +{ + unsigned long irqflags; + u32 val; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + val = viif_capture_read(viif_dev, REG_L1_AWHB_SW) & ~MASK_L1_AWHB_SW_LOCK; + val |= (*enable ? MASK_L1_AWHB_SW_LOCK : 0); + viif_capture_write(viif_dev, REG_L1_AWHB_SW, val); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +/* Convert the unit of time-period (from sysclk, to num lines in the image) */ +static u32 sysclk_to_numlines(u32 time_in_sysclk, const struct viif_img_clk *img_clk) +{ + u64 v1 = (u64)time_in_sysclk * img_clk->pixel_clock; + u64 v2 = (u64)img_clk->htotal_size * VIIF_SYS_CLK; + + return (u32)div64_u64(v1, v2); +} + +static void viif_l1_set_hdrc(struct viif_device *viif_dev, const struct viif_l1_hdrc_config *arg) +{ + const struct viif_l1_hdrc *param = &arg->param; + unsigned long irqflags; + u32 val, sw_delay1; + int i; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + /* disabling HDRC */ + if (!arg->enable) { + viif_capture_write(viif_dev, REG_L1_HDRC_THR_SFT_AMT, arg->hdrc_thr_sft_amt); + viif_capture_write(viif_dev, REG_L1_HDRC_EN, 0); + + goto done_op; + } + + /* enabling HDRC */ + viif_capture_write(viif_dev, REG_L1_HDRC_RATIO, + (param->hdrc_ratio - VIIF_L1_HDRC_RATIO_OFFSET)); + viif_capture_write(viif_dev, REG_L1_HDRC_PT_RATIO, param->hdrc_pt_ratio); + + viif_capture_write(viif_dev, REG_L1_HDRC_PT_BLEND, param->hdrc_pt_blend); + viif_capture_write(viif_dev, REG_L1_HDRC_PT_BLEND2, param->hdrc_pt_blend2); + + viif_capture_write(viif_dev, REG_L1_HDRC_PT_SAT, param->hdrc_pt_sat); + viif_capture_write(viif_dev, REG_L1_HDRC_TN_TYPE, param->hdrc_tn_type); + + for (i = 0; i < LEN_L1_HDRC_UTN_TBL; i++) + viif_capture_write(viif_dev, REG_L1_HDRC_UTN_TBL(i), param->hdrc_utn_tbl[i]); + + viif_capture_write(viif_dev, REG_L1_HDRC_FLR_VAL, param->hdrc_flr_val); + viif_capture_write(viif_dev, REG_L1_HDRC_FLR_ADP, param->hdrc_flr_adp ? 1 : 0); + + viif_capture_write(viif_dev, REG_L1_HDRC_YBR_OFF, param->hdrc_ybr_off ? 1 : 0); + viif_capture_write(viif_dev, REG_L1_HDRC_ORGY_BLEND, param->hdrc_orgy_blend); + + val = ((viif_capture_read(viif_dev, REG_L1_SYSM_HEIGHT)) % 64U) / 2U; + viif_capture_write(viif_dev, REG_L1_HDRC_MAR_TOP, val); + val = ((viif_capture_read(viif_dev, REG_L1_SYSM_WIDTH)) % 64U) / 2U; + viif_capture_write(viif_dev, REG_L1_HDRC_MAR_LEFT, val); + + viif_capture_write(viif_dev, REG_L1_HDRC_EN, 1); + + /* update of sw_delay1 must be done when MAIN unit is NOT running. */ + if (!viif_dev->run_flag_main) { + sw_delay1 = sysclk_to_numlines(VIIF_REGBUF_ACCESS_TIME, &viif_dev->img_clk) + + VIIF_L1_DELAY_W_HDRC + 1U; + val = viif_capture_read(viif_dev, REG_INT_M1_LINE) & 0xffffU; + val |= (sw_delay1 << 16U); + viif_capture_write(viif_dev, REG_INT_M1_LINE, val); + /* M2_LINE is the same condition as M1_LINE */ + viif_capture_write(viif_dev, REG_INT_M2_LINE, val); + } + +done_op: + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_hdrc_ltm(struct viif_device *viif_dev, + const struct viif_l1_hdrc_ltm_config *arg) +{ + unsigned long irqflags; + int i; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + viif_capture_write(viif_dev, REG_L1_HDRC_TNP_MAX, arg->tnp_max); + viif_capture_write(viif_dev, REG_L1_HDRC_TNP_MAG, arg->tnp_mag); + + for (i = 0; i < LEN_L1_HDRC_TNP_FIL; i++) + viif_capture_write(viif_dev, REG_L1_HDRC_TNP_FIL(i), (u32)arg->tnp_fil[i]); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void viif_l1_set_gamma(struct viif_device *viif_dev, const struct viif_l1_gamma_config *arg) +{ + const struct viif_l1_gamma *param = &arg->param; + unsigned long irqflags; + int i; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + /* disabling L1 gamma */ + if (!arg->enable) { + viif_capture_write(viif_dev, REG_L1_VPRO_PGC_SW, 0); + goto done_op; + } + + /* enabling L1 gamma */ + for (i = 0; i < 44; i++) + viif_capture_write(viif_dev, REG_L1_VPRO_GAMxP(i), param->gam_p[i]); + viif_capture_write(viif_dev, REG_L1_VPRO_BLKADJ, param->blkadj); + viif_capture_write(viif_dev, REG_L1_VPRO_PGC_SW, 1); + +done_op: + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void +viif_l1_set_img_quality_adjustment(struct viif_device *viif_dev, + const struct viif_l1_img_quality_adjustment_config *arg) +{ + unsigned long irqflags; + u32 val; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + /* RGB to YUV (enabled by default, should be enabled) */ + viif_capture_write(viif_dev, REG_L1_VPRO_YUVC_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_CB_MAT, (u32)arg->coef_cb); + viif_capture_write(viif_dev, REG_L1_VPRO_CR_MAT, (u32)arg->coef_cr); + + /* brightness */ + val = (u32)arg->brightness & 0xffffU; + if (val) { + viif_capture_write(viif_dev, REG_L1_VPRO_BRIGHT_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_BRIGHT, val); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_BRIGHT_SW, 0); + } + + /* linear contrast */ + if ((u32)arg->linear_contrast != 128U) { + viif_capture_write(viif_dev, REG_L1_VPRO_LCNT_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_LCONT_LEV, arg->linear_contrast); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_LCNT_SW, 0); + } + + /* nonlinear contrast */ + if (arg->enable & VIIF_L1_IQA_NONLINEAR_CONTRAST_EN_MASK) { + const struct viif_l1_nonlinear_contrast *nonlinear_contrast = + &arg->nonlinear_contrast; + + viif_capture_write(viif_dev, REG_L1_VPRO_NLCNT_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_BLK_KNEE, nonlinear_contrast->blk_knee); + viif_capture_write(viif_dev, REG_L1_VPRO_WHT_KNEE, nonlinear_contrast->wht_knee); + + viif_capture_write(viif_dev, REG_L1_VPRO_BLK_CONT0, + nonlinear_contrast->blk_cont[0]); + viif_capture_write(viif_dev, REG_L1_VPRO_BLK_CONT1, + nonlinear_contrast->blk_cont[1]); + viif_capture_write(viif_dev, REG_L1_VPRO_BLK_CONT2, + nonlinear_contrast->blk_cont[2]); + + viif_capture_write(viif_dev, REG_L1_VPRO_WHT_CONT0, + nonlinear_contrast->wht_cont[0]); + viif_capture_write(viif_dev, REG_L1_VPRO_WHT_CONT1, + nonlinear_contrast->wht_cont[1]); + viif_capture_write(viif_dev, REG_L1_VPRO_WHT_CONT2, + nonlinear_contrast->wht_cont[2]); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_NLCNT_SW, 0); + } + + /* luminance noise reduction */ + if (arg->enable & VIIF_L1_IQA_LUM_NOISE_REDUCTION_EN_MASK) { + const struct viif_l1_lum_noise_reduction *lum_noise_reduction = + &arg->lum_noise_reduction; + + viif_capture_write(viif_dev, REG_L1_VPRO_YNR_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_YNR_GAIN_MIN, + lum_noise_reduction->gain_min); + viif_capture_write(viif_dev, REG_L1_VPRO_YNR_GAIN_MAX, + lum_noise_reduction->gain_max); + viif_capture_write(viif_dev, REG_L1_VPRO_YNR_LIM_MIN, lum_noise_reduction->lim_min); + viif_capture_write(viif_dev, REG_L1_VPRO_YNR_LIM_MAX, lum_noise_reduction->lim_max); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_YNR_SW, 0); + } + + /* edge enhancement */ + if (arg->enable & VIIF_L1_IQA_EDGE_ENHANCEMENT_EN_MASK) { + const struct viif_l1_edge_enhancement *edge_enhancement = &arg->edge_enhancement; + + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_GAIN_MIN, edge_enhancement->gain_min); + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_GAIN_MAX, edge_enhancement->gain_max); + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_LIM_MIN, edge_enhancement->lim_min); + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_LIM_MAX, edge_enhancement->lim_max); + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_CORING_MIN, + edge_enhancement->coring_min); + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_CORING_MAX, + edge_enhancement->coring_max); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_ETE_SW, 0); + } + + /* UV suppression */ + if (arg->enable & VIIF_L1_IQA_UV_SUPPRESSION_EN_MASK) { + const struct viif_l1_uv_suppression *uv_suppression = &arg->uv_suppression; + + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_UVSUP_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_BK_SLV, uv_suppression->bk_slv); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_BK_MP, uv_suppression->bk_mp); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_BLACK, uv_suppression->black); + + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_WH_SLV, uv_suppression->wh_slv); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_WH_MP, uv_suppression->wh_mp); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_WHITE, uv_suppression->white); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_UVSUP_SW, 0); + } + + /* coring suppression */ + if (arg->enable & VIIF_L1_IQA_CORING_SUPPRESSION_EN_MASK) { + const struct viif_l1_coring_suppression *coring_suppression = + &arg->coring_suppression; + + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_CORING_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_CORING_LV_MIN, + coring_suppression->lv_min); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_CORING_LV_MAX, + coring_suppression->lv_max); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_CORING_GAIN_MIN, + coring_suppression->gain_min); + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_CORING_GAIN_MAX, + coring_suppression->gain_max); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_CSUP_CORING_SW, 0); + } + + /* edge suppression */ + if (arg->enable & VIIF_L1_IQA_EDGE_SUPPRESSION_EN_MASK) { + const struct viif_l1_edge_suppression *edge_suppression = &arg->edge_suppression; + + viif_capture_write(viif_dev, REG_L1_VPRO_EDGE_SUP_SW, 1); + viif_capture_write(viif_dev, REG_L1_VPRO_EDGE_SUP_GAIN, edge_suppression->gain); + viif_capture_write(viif_dev, REG_L1_VPRO_EDGE_SUP_LIM, edge_suppression->lim); + } else { + viif_capture_write(viif_dev, REG_L1_VPRO_EDGE_SUP_SW, 0); + } + + /* color level */ + if (arg->enable & VIIF_L1_IQA_COLOR_LEVEL_EN_MASK) { + const struct viif_l1_color_level *color_level = &arg->color_level; + + viif_capture_write(viif_dev, REG_L1_VPRO_CB_GAIN, color_level->cb_gain); + viif_capture_write(viif_dev, REG_L1_VPRO_CR_GAIN, color_level->cr_gain); + viif_capture_write(viif_dev, REG_L1_VPRO_CBR_MGAIN_MIN, color_level->cbr_mgain_min); + viif_capture_write(viif_dev, REG_L1_VPRO_CB_P_GAIN_MAX, color_level->cbp_gain_max); + viif_capture_write(viif_dev, REG_L1_VPRO_CB_M_GAIN_MAX, color_level->cbm_gain_max); + viif_capture_write(viif_dev, REG_L1_VPRO_CR_P_GAIN_MAX, color_level->crp_gain_max); + viif_capture_write(viif_dev, REG_L1_VPRO_CR_M_GAIN_MAX, color_level->crm_gain_max); + } else { + /* disable */ + viif_capture_write(viif_dev, REG_L1_VPRO_CB_GAIN, 1024U); + viif_capture_write(viif_dev, REG_L1_VPRO_CR_GAIN, 1024U); + viif_capture_write(viif_dev, REG_L1_VPRO_CBR_MGAIN_MIN, 1024U); + viif_capture_write(viif_dev, REG_L1_VPRO_CB_P_GAIN_MAX, 0U); + viif_capture_write(viif_dev, REG_L1_VPRO_CB_M_GAIN_MAX, 0U); + viif_capture_write(viif_dev, REG_L1_VPRO_CR_P_GAIN_MAX, 0U); + viif_capture_write(viif_dev, REG_L1_VPRO_CR_M_GAIN_MAX, 0U); + } + + /* color noise reduction */ + viif_capture_write(viif_dev, REG_L1_VPRO_CNR_SW, + arg->enable & VIIF_L1_IQA_COLOR_NOISE_REDUCTION_EN_MASK ? 1 : 0); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static inline u32 pack_weight(const u32 *vec) +{ + return (vec[0] << 14) | (vec[1] << 12) | (vec[2] << 10) | (vec[3] << 8) | (vec[4] << 6) | + (vec[5] << 4) | (vec[6] << 2U) | (vec[7]); +} + +static void viif_l1_set_avg_lum_generation(struct viif_device *viif_dev, + const struct viif_l1_avg_lum_generation_config *arg) +{ + unsigned long irqflags; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + /* disabling aggregation */ + if (!arg->enable) { + viif_capture_write(viif_dev, REG_L1_AEXP_ON, 0); + goto op_done; + } + + /* enabling aggregation */ + viif_capture_write(viif_dev, REG_L1_AEXP_ON, 1); + viif_capture_write(viif_dev, REG_L1_AEXP_START_X, arg->aexp_start_x); + viif_capture_write(viif_dev, REG_L1_AEXP_START_Y, arg->aexp_start_y); + viif_capture_write(viif_dev, REG_L1_AEXP_BLOCK_WIDTH, arg->aexp_block_width); + viif_capture_write(viif_dev, REG_L1_AEXP_BLOCK_HEIGHT, arg->aexp_block_height); + + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_0, pack_weight(arg->aexp_weight[0])); + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_1, pack_weight(arg->aexp_weight[1])); + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_2, pack_weight(arg->aexp_weight[2])); + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_3, pack_weight(arg->aexp_weight[3])); + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_3, pack_weight(arg->aexp_weight[4])); + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_4, pack_weight(arg->aexp_weight[5])); + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_5, pack_weight(arg->aexp_weight[6])); + viif_capture_write(viif_dev, REG_L1_AEXP_WEIGHT_7, pack_weight(arg->aexp_weight[7])); + + viif_capture_write(viif_dev, REG_L1_AEXP_SATUR_RATIO, arg->aexp_satur_ratio); + viif_capture_write(viif_dev, REG_L1_AEXP_BLACK_RATIO, arg->aexp_black_ratio); + viif_capture_write(viif_dev, REG_L1_AEXP_SATUR_LEVEL, arg->aexp_satur_level); + + viif_capture_write(viif_dev, REG_L1_AEXP_AVE4LINESY0, arg->aexp_ave4linesy[0]); + viif_capture_write(viif_dev, REG_L1_AEXP_AVE4LINESY1, arg->aexp_ave4linesy[1]); + viif_capture_write(viif_dev, REG_L1_AEXP_AVE4LINESY2, arg->aexp_ave4linesy[2]); + viif_capture_write(viif_dev, REG_L1_AEXP_AVE4LINESY3, arg->aexp_ave4linesy[3]); + +op_done: + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static void undist_table_transmission(struct viif_device *viif_dev, dma_addr_t write_g, + dma_addr_t read_b, dma_addr_t read_g, dma_addr_t read_r, + u32 size) +{ + u32 val = 0U; + + if (read_b) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L2_UNDIST_RD_B), + (u32)read_b); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L2_UNDIST_RD_B), size); + val |= MASK_VDM_T_ENABLE_L2_UNDIST_RD_B; + } + if (read_g) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L2_UNDIST_RD_G), + (u32)read_g); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L2_UNDIST_RD_G), size); + val |= MASK_VDM_T_ENABLE_L2_UNDIST_RD_G; + } + if (read_r) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L2_UNDIST_RD_R), + (u32)read_r); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L2_UNDIST_RD_R), size); + val |= MASK_VDM_T_ENABLE_L2_UNDIST_RD_R; + } + if (write_g) { + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(IDX_TPORT_L2_UNDIST_WR_G), + (u32)write_g); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(IDX_TPORT_L2_UNDIST_WR_G), size); + val |= MASK_VDM_T_ENABLE_L2_UNDIST_WR_G; + } + + if (val) + viif_config_vdm_tgroup(viif_dev, IDX_TGROUP_L2_UNDIST); + + val |= viif_capture_read(viif_dev, REG_VDM_T_ENABLE) & ~MASK_VDM_T_ENABLE_L2_UNDIST; + viif_capture_write(viif_dev, REG_VDM_T_ENABLE, val); +} + +static void undist_setup(struct viif_device *viif_dev, const struct viif_l2_undist *param) +{ + u32 val; + unsigned int i; + + /* Undist through mode */ + if (param->through_mode) { + /* Enable through mode */ + viif_capture_write(viif_dev, REG_L2_MODE, 1); + return; + } + + /* Undist operation */ + val = (param->roi_mode[0] << 1U) | (param->roi_mode[1] << 3U); + viif_capture_write(viif_dev, REG_L2_MODE, val); + val = (u32)param->sensor_crop_ofs_h & GENMASK(13, 0); + viif_capture_write(viif_dev, REG_L2_SENSOR_CROP_OFS_H, val); + val = (u32)param->sensor_crop_ofs_v & GENMASK(12, 0); + viif_capture_write(viif_dev, REG_L2_SENSOR_CROP_OFS_V, val); + viif_capture_write(viif_dev, REG_L2_NORM_SCALE, param->norm_scale); + viif_capture_write(viif_dev, REG_L2_VALID_R_NORM2_POLY, param->valid_r_norm2_poly); + viif_capture_write(viif_dev, REG_L2_VALID_R_NORM2_GRID, param->valid_r_norm2_grid); + viif_capture_write(viif_dev, REG_L2_ROI_WRITE_AREA_DELTA(0), + param->roi_write_area_delta[0]); + viif_capture_write(viif_dev, REG_L2_ROI_WRITE_AREA_DELTA(1), + param->roi_write_area_delta[1]); + + for (i = 0; i < VIIF_L2_UNDIST_POLY_NUM; i++) { + val = (u32)param->poly_write_g_coef[i]; + viif_capture_write(viif_dev, REG_L2_POLY10_WRITE_G_COEF(i), val); + val = (u32)param->poly_read_b_coef[i]; + viif_capture_write(viif_dev, REG_L2_POLY10_READ_B_COEF(i), val); + val = (u32)param->poly_read_g_coef[i]; + viif_capture_write(viif_dev, REG_L2_POLY10_READ_G_COEF(i), val); + val = (u32)param->poly_read_r_coef[i]; + viif_capture_write(viif_dev, REG_L2_POLY10_READ_R_COEF(i), val); + } + viif_capture_write(viif_dev, REG_L2_GRID_NODE_NUM_H, param->grid_node_num_h); + viif_capture_write(viif_dev, REG_L2_GRID_NODE_NUM_V, param->grid_node_num_v); + viif_capture_write(viif_dev, REG_L2_GRID_PATCH_HSIZE_INV, param->grid_patch_hsize_inv); + viif_capture_write(viif_dev, REG_L2_GRID_PATCH_VSIZE_INV, param->grid_patch_vsize_inv); +} + +static void viif_l2_set_undist(struct viif_device *viif_dev, + const struct viif_l2_undist_config *arg) +{ + dma_addr_t table_write_g = 0; + dma_addr_t table_read_b = 0; + dma_addr_t table_read_g = 0; + dma_addr_t table_read_r = 0; + unsigned long irqflags; + + if (arg->param.roi_mode[0] != VIIF_L2_UNDIST_POLY || + arg->param.roi_mode[1] != VIIF_L2_UNDIST_POLY) { + memcpy(viif_dev->tables->undist_write_g, arg->write_g, arg->size); + memcpy(viif_dev->tables->undist_read_b, arg->read_b, arg->size); + memcpy(viif_dev->tables->undist_read_g, arg->read_g, arg->size); + memcpy(viif_dev->tables->undist_read_r, arg->read_r, arg->size); + + table_write_g = (uintptr_t)viif_dev->tables_dma->undist_write_g; + table_read_b = (uintptr_t)viif_dev->tables_dma->undist_read_b; + table_read_g = (uintptr_t)viif_dev->tables_dma->undist_read_g; + table_read_r = (uintptr_t)viif_dev->tables_dma->undist_read_r; + } + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + undist_table_transmission(viif_dev, table_write_g, table_read_b, table_read_g, table_read_r, + arg->size); + + undist_setup(viif_dev, &arg->param); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +int visconti_viif_l2_undist_through(struct viif_device *viif_dev) +{ + struct viif_l2_undist undist = { 0 }; + + undist.through_mode = VIIF_ENABLE; + undist.sensor_crop_ofs_h = + 1 - FIELD_GET(0x1FFF, viif_capture_read(viif_dev, REG_L2_SENSOR_CROP_HSIZE)); + undist.sensor_crop_ofs_v = + 1 - FIELD_GET(0x0FFF, viif_capture_read(viif_dev, REG_L2_SENSOR_CROP_VSIZE)); + undist.grid_node_num_h = 16; + undist.grid_node_num_v = 16; + + undist_setup(viif_dev, &undist); + + return 0; +} + +static void viif_l2_set_roi_wrap(struct viif_device *viif_dev, const struct viif_l2_roi_config *roi) +{ + unsigned long irqflags; + + /* update ROI parameter */ + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + visconti_viif_l2_set_roi(viif_dev, roi); + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); + + /* reflect change to pad::compose_rect */ + visconti_viif_isp_set_compose_rect(viif_dev, roi); +} + +struct viif_l2_gamma_table { + dma_addr_t table[VIIF_L2_GAMMA_TABLE_CH_NUM]; +}; + +static void l2_gamma_table_transmission(struct viif_device *viif_dev, u32 post_id, + const struct viif_l2_gamma_table *gamma_table) +{ + u32 vdm_enable = 0U; + u32 i; + + /* 0: LUT0-G/Y, 1: LUT1-G/Y, 2: LUT0-B/U, 3: LUT1-B/U, 4: LUT0-R/V, 5: LUT1-R/V */ + for (i = 0; i < VIIF_L2_GAMMA_TABLE_CH_NUM; i++) { + if (gamma_table->table[i]) { + int idx = IDX_TPORT_L2_GAMMA_LUT(post_id, i); + + viif_capture_write(viif_dev, REG_VDM_TPORT_X_STADR(idx), + (u32)gamma_table->table[i]); + viif_capture_write(viif_dev, REG_VDM_TPORT_X_SIZE(idx), + VIIF_L2_GAMMA_TABLE_BYTES); + vdm_enable |= MASK_VDM_T_ENABLE_L2_GAMMA(post_id, i); + } + } + if (vdm_enable) + viif_config_vdm_tgroup(viif_dev, IDX_TGROUP_L2_GAMMA_LUT(post_id)); + + vdm_enable |= viif_capture_read(viif_dev, REG_VDM_T_ENABLE) & + ~MASK_VDM_T_ENABLE_L2_GAMMA_ALL(post_id); + + viif_capture_write(viif_dev, REG_VDM_T_ENABLE, vdm_enable); +} + +static void viif_l2_set_gamma(struct viif_device *viif_dev, int pathid, + const struct viif_l2_gamma_config *l2_gamma) +{ + struct viif_l2_gamma_table dma_table = { 0 }; + int postid = (pathid == CAPTURE_PATH_MAIN_POST0) ? VIIF_L2ISP_POST_0 : VIIF_L2ISP_POST_1; + unsigned long irqflags; + int table_en; + u32 val; + int i; + + table_en = l2_gamma->table_en; + for (i = 0; i < 6; i++) { + if (table_en & BIT(i)) { + memcpy(viif_dev->tables->l2_gamma_table[pathid][i], l2_gamma->table[i], + VIIF_L2_GAMMA_TABLE_BYTES); + dma_table.table[i] = + (dma_addr_t)(uintptr_t) + viif_dev->tables_dma->l2_gamma_table[pathid][i]; + } + } + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + l2_gamma_table_transmission(viif_dev, postid, &dma_table); + + val = (l2_gamma->vsplit << 16U) | (l2_gamma->mode << 4U) | (table_en != 0 ? 1 : 0); + viif_capture_write(viif_dev, REG_L2_POST_X_GAMMA_M(postid), val); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static const struct viif_l1_input_mode_config defval_l1_set_input_mode = { + .mode = VIIF_L1_INPUT_HDR, +}; + +static const struct viif_l1_rgb_to_y_coef_config defval_l1_set_rgb_to_y_coef = { + /* ITU-R BT.601 */ + .coef_r = 0x4C8C, + .coef_g = 0x9644, + .coef_b = 0x1D30, +}; + +static const struct viif_l1_ag_mode_config defval_l1_set_ag_mode = { 0 }; + +static const struct viif_l1_ag_config defval_l1_set_ag = { 0 }; + +static const struct viif_l1_hdre_config defval_l1_set_hdre = { + .hdre_src_point[0] = 0x3FFF, + .hdre_dst_max_val = 0xFFFFFF, +}; + +static const struct viif_l1_img_extraction_config defval_l1_set_img_extraction = { + .input_black_gr = 256, + .input_black_r = 256, + .input_black_b = 256, + .input_black_gb = 256, +}; + +static const struct viif_l1_dpc_config defval_l1_set_dpc = { 0 }; + +static const struct viif_l1_preset_white_balance_config defval_l1_set_preset_white_balance = { + .dstmaxval = 0x0FFF, + .param_h = { + .gain_gr = 0x4000, + .gain_r = 0x4000, + .gain_b = 0x4000, + .gain_gb = 0x4000, + }, + .param_m = { + .gain_gr = 0x4000, + .gain_r = 0x4000, + .gain_b = 0x4000, + .gain_gb = 0x4000, + }, + .param_l = { + .gain_gr = 0x4000, + .gain_r = 0x4000, + .gain_b = 0x4000, + .gain_gb = 0x4000, + }, +}; + +static const +struct viif_l1_raw_color_noise_reduction_config defval_l1_set_raw_color_noise_reduction = { + .param_h = { + .rcnr_cnf_clip_gain_r = 3, + .rcnr_cnf_clip_gain_g = 2, + .rcnr_cnf_clip_gain_b = 3, + .rcnr_merge_black = 0x20, + .rcnr_merge_mindiv = 4, + .rcnr_anf_blend_ag0 = 1, + .rcnr_anf_blend_ag1 = 2, + .rcnr_anf_blend_ag2 = 2, + .rcnr_lpf_threshold = 8, + }, + .param_m = { + .rcnr_cnf_clip_gain_r = 3, + .rcnr_cnf_clip_gain_g = 2, + .rcnr_cnf_clip_gain_b = 3, + .rcnr_merge_black = 0x20, + .rcnr_merge_mindiv = 4, + .rcnr_anf_blend_ag0 = 1, + .rcnr_anf_blend_ag1 = 2, + .rcnr_anf_blend_ag2 = 2, + .rcnr_lpf_threshold = 8, + }, + .param_l = { + .rcnr_cnf_clip_gain_r = 3, + .rcnr_cnf_clip_gain_g = 2, + .rcnr_cnf_clip_gain_b = 3, + .rcnr_merge_black = 0x20, + .rcnr_merge_mindiv = 4, + .rcnr_anf_blend_ag0 = 1, + .rcnr_anf_blend_ag1 = 2, + .rcnr_anf_blend_ag2 = 2, + .rcnr_lpf_threshold = 8, + }, +}; + +static const struct viif_l1_hdrs_config defval_l1_set_hdrs = { + .hdrs_hdr_mode = 1, + .hdrs_hdr_ratio_m = 0x10000, + .hdrs_hdr_ratio_l = 0x400000, + .hdrs_hdr_ratio_e = 0x400, + .hdrs_dg_h = 0x400, + .hdrs_dg_m = 0x400, + .hdrs_dg_l = 0x400, + .hdrs_dg_e = 0x400, + .hdrs_blendend_h = 0xFA0, + .hdrs_blendend_m = 0xFA0, + .hdrs_blendend_e = 0xFA0, + .hdrs_blendbeg_h = 0x12C, + .hdrs_blendbeg_m = 0x12C, + .hdrs_blendbeg_e = 0x12C, + .hdrs_dst_max_val = 0xFFFFFF, +}; + +static const struct viif_l1_black_level_correction_config defval_l1_set_black_level_correction = { + .srcblacklevel_gr = 0x40, + .srcblacklevel_r = 0x40, + .srcblacklevel_b = 0x40, + .srcblacklevel_gb = 0x40, + .mulval_gr = 0x40000, + .mulval_r = 0x40000, + .mulval_b = 0x40000, + .mulval_gb = 0x40000, + .dstmaxval = 0xFFFFFF, +}; + +static const struct viif_l1_lsc_config defval_l1_set_lsc = { 0 }; + +static const struct viif_l1_main_process_config defval_l1_set_main_process = { + .damp_lsbsel = 0x8, + .demosaic_mode = 1, + .colormat_enable = 0, + .dst_maxval = 0xFFFFFF, +}; + +static const struct viif_l1_awb_config defval_l1_set_awb = { + .enable = 0, + .awhb_wbmrg = 256, + .awhb_wbmgg = 256, + .awhb_wbmbg = 256, +}; + +static const u32 defval_l1_lock_awb_gain; + +static const struct viif_l1_hdrc_config defval_l1_set_hdrc = { + .enable = 1, + .param = { + .hdrc_ratio = 0x0E + VIIF_L1_HDRC_RATIO_OFFSET, + .hdrc_pt_ratio = 7, + .hdrc_pt_sat = 0xFFC0, + .hdrc_tn_type = 1, + }, +}; + +static const struct viif_l1_hdrc_ltm_config defval_l1_set_hdrc_ltm = { + .tnp_max = 0x3FFFFF, + .tnp_mag = 0x40, + .tnp_fil = { 0x88, 0x84, 0x7A, 0x6A, 0x54 }, +}; + +static const struct viif_l1_gamma_config defval_l1_set_gamma = { + .enable = 1, + .param = { + .gam_p = { + 0x02F, 0x01B, 0x02A, 0x023, 0x020, 0x037, 0x031, 0x057, 0x04D, 0x088, + 0x078, 0x0D6, 0x0BD, 0x14F, 0x12A, 0x20D, 0x1D3, 0x1AB, 0x18D, 0x2DC, + 0x29E, 0x271, 0x47C, 0x41B, 0x3D4, 0x70A, 0x672, 0x601, 0xB0C, 0xA1D, + 0x96C, 0x8E2, 0x874, 0xFDD, 0xEC9, 0xDF2, 0xD42, 0xCB1, 0xC35, 0xBC9, + 0xB6A, 0xB16, 0xACB, 0xA86}, + .blkadj = 0x1000, + }, +}; + +static const struct viif_l1_img_quality_adjustment_config defval_l1_set_img_quality_adjustment = { + .enable = 0, + .coef_cb = 0x9078, + .coef_cr = 0xB699, + .brightness = 0, + .linear_contrast = 128, +}; + +static const struct viif_l1_avg_lum_generation_config defval_l1_set_avg_lum_generation = { + .enable = 0 +}; + +static const struct viif_l2_undist_config defval_l2_set_undist = { + .param = { + .through_mode = 1, + .roi_mode = { 0, 0 }, + .grid_node_num_h = 0x10, + .grid_node_num_v = 0x10, + }, +}; + +static const struct viif_l2_gamma_config defval_l2_set_gamma = { 0 }; + +static void viif_apply_default_parameter(struct viif_device *viif_dev) +{ + viif_l1_set_input_mode(viif_dev, &defval_l1_set_input_mode); + viif_l1_set_rgb_to_y_coef(viif_dev, &defval_l1_set_rgb_to_y_coef); + viif_l1_set_ag_mode(viif_dev, &defval_l1_set_ag_mode); + viif_l1_set_ag(viif_dev, &defval_l1_set_ag); + viif_l1_set_hdre(viif_dev, &defval_l1_set_hdre); + viif_l1_set_img_extraction(viif_dev, &defval_l1_set_img_extraction); + viif_l1_set_dpc(viif_dev, &defval_l1_set_dpc); + viif_l1_set_preset_white_balance(viif_dev, &defval_l1_set_preset_white_balance); + viif_l1_set_raw_color_noise_reduction(viif_dev, &defval_l1_set_raw_color_noise_reduction); + viif_l1_set_hdrs(viif_dev, &defval_l1_set_hdrs); + viif_l1_set_black_level_correction(viif_dev, &defval_l1_set_black_level_correction); + viif_l1_set_lsc(viif_dev, &defval_l1_set_lsc); + viif_l1_set_main_process(viif_dev, &defval_l1_set_main_process); + viif_l1_set_awb(viif_dev, &defval_l1_set_awb); + viif_l1_lock_awb_gain(viif_dev, &defval_l1_lock_awb_gain); + viif_l1_set_hdrc(viif_dev, &defval_l1_set_hdrc); + viif_l1_set_hdrc_ltm(viif_dev, &defval_l1_set_hdrc_ltm); + viif_l1_set_gamma(viif_dev, &defval_l1_set_gamma); + viif_l1_set_img_quality_adjustment(viif_dev, &defval_l1_set_img_quality_adjustment); + viif_l1_set_avg_lum_generation(viif_dev, &defval_l1_set_avg_lum_generation); + viif_l2_set_undist(viif_dev, &defval_l2_set_undist); + viif_l2_set_gamma(viif_dev, CAPTURE_PATH_MAIN_POST0, &defval_l2_set_gamma); + viif_l2_set_gamma(viif_dev, CAPTURE_PATH_MAIN_POST1, &defval_l2_set_gamma); +} + +/*=======================================================================*/ +/* parameter buffer streaming interface */ +/*=======================================================================*/ +struct viif_buffer { + struct vb2_v4l2_buffer vb; + struct list_head queue; +}; + +static bool viif_params_get_buffer(struct params_dev *params_dev, struct viif_buffer **buf, + struct visconti_viif_isp_config **cfg) +{ + if (list_empty(¶ms_dev->params_queue)) + return false; + + *buf = list_first_entry(¶ms_dev->params_queue, struct viif_buffer, queue); + *cfg = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0); + + return true; +} + +static int viif_apply_queued_parameter(struct viif_device *viif_dev, bool initial_cfg) +{ + struct params_dev *params_dev = &viif_dev->params_dev; + struct visconti_viif_isp_config *new_params; + struct viif_buffer *cur_buf; + int ret = 0; + + spin_lock(¶ms_dev->params_lock); + + if (!viif_params_get_buffer(params_dev, &cur_buf, &new_params)) { + ret = 1; + goto unlock; + } + + /* evaluate new_params */ + if (initial_cfg) { + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_INPUT_MODE) + viif_l1_set_input_mode(viif_dev, &new_params->l1_input_mode); + } + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_RGB_TO_Y_COEF) + viif_l1_set_rgb_to_y_coef(viif_dev, &new_params->l1_rgb_to_y_coef); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_AG_MODE) + viif_l1_set_ag_mode(viif_dev, &new_params->l1_ag_mode); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_AG) + viif_l1_set_ag(viif_dev, &new_params->l1_ag); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_HDRE) + viif_l1_set_hdre(viif_dev, &new_params->l1_hdre); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_IMG_EXTRACTION) + viif_l1_set_img_extraction(viif_dev, &new_params->l1_img_extraction); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_DPC) + viif_l1_set_dpc(viif_dev, &new_params->l1_dpc); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_PRESET_WHITE_BALANCE) + viif_l1_set_preset_white_balance(viif_dev, &new_params->l1_preset_white_balance); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_RAW_COLOR_NOISE_REDUCTION) + viif_l1_set_raw_color_noise_reduction(viif_dev, + &new_params->l1_raw_color_noise_reduction); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_HDRS) + viif_l1_set_hdrs(viif_dev, &new_params->l1_hdrs); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_BLACK_LEVEL_CORRECTION) + viif_l1_set_black_level_correction(viif_dev, + &new_params->l1_black_level_correction); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_LSC) + viif_l1_set_lsc(viif_dev, &new_params->l1_lsc); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_MAIN_PROCESS) + viif_l1_set_main_process(viif_dev, &new_params->l1_main_process); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_AWB) + viif_l1_set_awb(viif_dev, &new_params->l1_awb); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_LOCK_AWB_GAIN) + viif_l1_lock_awb_gain(viif_dev, &new_params->lock_awb_gain); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_HDRC) + viif_l1_set_hdrc(viif_dev, &new_params->l1_hdrc); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_HDRC_LTM) + viif_l1_set_hdrc_ltm(viif_dev, &new_params->l1_hdrc_ltm); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_GAMMA) + viif_l1_set_gamma(viif_dev, &new_params->l1_gamma); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_IMG_QUALITY_ADJUSTMENT) + viif_l1_set_img_quality_adjustment(viif_dev, + &new_params->l1_img_quality_adjustment); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L1_AVG_LUM_GENERATION) + viif_l1_set_avg_lum_generation(viif_dev, &new_params->l1_avg_lum_generation); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L2_UNDIST) + viif_l2_set_undist(viif_dev, &new_params->l2_undist); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L2_ROI) + viif_l2_set_roi_wrap(viif_dev, &new_params->l2_roi); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L2_GAMMA_POST0) + viif_l2_set_gamma(viif_dev, CAPTURE_PATH_MAIN_POST0, &new_params->l2_gamma_post0); + if (new_params->update_cfg & VISCONTI_VIIF_CFG_ISP_L2_GAMMA_POST1) + viif_l2_set_gamma(viif_dev, CAPTURE_PATH_MAIN_POST1, &new_params->l2_gamma_post1); + + /* release buffer */ + list_del(&cur_buf->queue); + cur_buf->vb.sequence = 0; + vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + +unlock: + spin_unlock(¶ms_dev->params_lock); + return ret; +} + +void visconti_viif_params_isr(struct viif_device *viif_dev) +{ + viif_apply_queued_parameter(viif_dev, false); +} + +void visconti_viif_params_eval_queue(struct viif_device *viif_dev) +{ + if (viif_apply_queued_parameter(viif_dev, true)) + viif_apply_default_parameter(viif_dev); +} + +static int viif_params_enum_fmt_meta_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + struct video_device *vdev = video_devdata(file); + + if (f->index > 0 || f->type != vdev->queue->type) + return -EINVAL; + + f->pixelformat = V4L2_META_FMT_VISCONTI_VIIF_PARAMS; + + return 0; +} + +static int viif_params_g_fmt_meta_out(struct file *file, void *fh, struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_meta_format *meta = &f->fmt.meta; + + if (f->type != vdev->queue->type) + return -EINVAL; + + memset(meta, 0, sizeof(*meta)); + meta->dataformat = V4L2_META_FMT_VISCONTI_VIIF_PARAMS; + meta->buffersize = sizeof(struct visconti_viif_isp_config); + + return 0; +} + +static int viif_params_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + strscpy(cap->driver, VIIF_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, vdev->name, sizeof(cap->card)); + strscpy(cap->bus_info, VIIF_BUS_INFO_BASE "-0", sizeof(cap->bus_info)); + + return 0; +} + +static const struct v4l2_ioctl_ops viif_params_ioctl = { + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_enum_fmt_meta_out = viif_params_enum_fmt_meta_out, + .vidioc_g_fmt_meta_out = viif_params_g_fmt_meta_out, + .vidioc_s_fmt_meta_out = viif_params_g_fmt_meta_out, + .vidioc_try_fmt_meta_out = viif_params_g_fmt_meta_out, + .vidioc_querycap = viif_params_querycap, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct v4l2_file_operations viif_params_fops = { + .mmap = vb2_fop_mmap, + .unlocked_ioctl = video_ioctl2, + .poll = vb2_fop_poll, + .open = v4l2_fh_open, + .release = vb2_fop_release, +}; + +static int viif_params_vb2_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, + unsigned int *num_planes, unsigned int sizes[], + struct device *alloc_devs[]) +{ + *num_buffers = clamp_t(u32, *num_buffers, 2, 8); + *num_planes = 1; + sizes[0] = sizeof(struct visconti_viif_isp_config); + return 0; +} + +static inline struct viif_buffer *vb2_to_viif(struct vb2_v4l2_buffer *vbuf) +{ + return container_of(vbuf, struct viif_buffer, vb); +} + +static inline struct params_dev *vb2queue_to_paramsdev(struct vb2_queue *vq) +{ + return (struct params_dev *)vb2_get_drv_priv(vq); +} + +static void viif_params_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct params_dev *params_dev = vb2queue_to_paramsdev(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct viif_buffer *buf = vb2_to_viif(vbuf); + + spin_lock_irq(¶ms_dev->params_lock); + list_add_tail(&buf->queue, ¶ms_dev->params_queue); + spin_unlock_irq(¶ms_dev->params_lock); +} + +static int viif_params_vb2_buf_prepare(struct vb2_buffer *vb) +{ + if (vb2_plane_size(vb, 0) < sizeof(struct visconti_viif_isp_config)) + return -EINVAL; + + vb2_set_plane_payload(vb, 0, sizeof(struct visconti_viif_isp_config)); + return 0; +} + +static int viif_params_vb2_start_streaming(struct vb2_queue *q, unsigned int arg) +{ + return 0; +} + +static void viif_params_vb2_stop_streaming(struct vb2_queue *q) +{ + struct params_dev *params_dev = vb2queue_to_paramsdev(q); + struct viif_buffer *buf; + LIST_HEAD(tmp_list); + + spin_lock_irq(¶ms_dev->params_lock); + list_splice_init(¶ms_dev->params_queue, &tmp_list); + spin_unlock_irq(¶ms_dev->params_lock); + + list_for_each_entry(buf, &tmp_list, queue) + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); +} + +static const struct vb2_ops viif_params_vb2_ops = { + .queue_setup = viif_params_vb2_queue_setup, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .buf_queue = viif_params_vb2_buf_queue, + .buf_prepare = viif_params_vb2_buf_prepare, + .start_streaming = viif_params_vb2_start_streaming, + .stop_streaming = viif_params_vb2_stop_streaming, +}; + +int visconti_viif_params_register(struct viif_device *viif_dev) +{ + struct params_dev *params_dev = &viif_dev->params_dev; + struct video_device *vdev = ¶ms_dev->vdev; + struct vb2_queue *q = ¶ms_dev->vb2_vq; + int ret; + + mutex_init(¶ms_dev->vlock); + INIT_LIST_HEAD(¶ms_dev->params_queue); + spin_lock_init(¶ms_dev->params_lock); + + strscpy(vdev->name, "viif_params", sizeof(vdev->name)); + + /* Register the video device */ + video_set_drvdata(vdev, params_dev); + vdev->ioctl_ops = &viif_params_ioctl; + vdev->fops = &viif_params_fops; + vdev->release = video_device_release_empty; + vdev->lock = ¶ms_dev->vlock; + vdev->v4l2_dev = &viif_dev->v4l2_dev; + vdev->queue = ¶ms_dev->vb2_vq; + vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT; + vdev->vfl_dir = VFL_DIR_TX; + + /* Initialize vb2 queue */ + q->type = V4L2_BUF_TYPE_META_OUTPUT; + q->io_modes = VB2_MMAP | VB2_DMABUF; + q->drv_priv = params_dev; + q->ops = &viif_params_vb2_ops; + q->mem_ops = &vb2_vmalloc_memops; + q->buf_struct_size = sizeof(struct viif_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = ¶ms_dev->vlock; + q->dev = viif_dev->v4l2_dev.dev; + + ret = vb2_queue_init(q); + if (ret) + return ret; + + params_dev->params_pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&vdev->entity, VIIF_PARAMS_PAD_NUM, ¶ms_dev->params_pad); + if (ret) + goto error; + + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(viif_dev->v4l2_dev.dev, "video_register_device failed: %d\n", ret); + goto error; + } + + return 0; + +error: + media_entity_cleanup(&vdev->entity); + mutex_destroy(¶ms_dev->vlock); + + return ret; +} + +void visconti_viif_params_unregister(struct viif_device *viif_dev) +{ + struct params_dev *params = &viif_dev->params_dev; + struct video_device *vdev = ¶ms->vdev; + + if (!video_is_registered(vdev)) + return; + + vb2_video_unregister_device(vdev); + media_entity_cleanup(&vdev->entity); + mutex_destroy(¶ms->vlock); +} diff --git a/drivers/media/platform/toshiba/visconti/viif_params.h b/drivers/media/platform/toshiba/visconti/viif_params.h new file mode 100644 index 0000000000..e5b41a0f30 --- /dev/null +++ b/drivers/media/platform/toshiba/visconti/viif_params.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* Toshiba Visconti Video Capture Support + * + * (C) Copyright 2024 TOSHIBA CORPORATION + * (C) Copyright 2024 Toshiba Electronic Devices & Storage Corporation + */ + +#ifndef VIIF_PARAMS_H +#define VIIF_PARAMS_H + +struct viif_device; + +void visconti_viif_params_eval_queue(struct viif_device *viif_dev); +void visconti_viif_params_isr(struct viif_device *viif_dev); +int visconti_viif_params_register(struct viif_device *viif_dev); +void visconti_viif_params_unregister(struct viif_device *viif_dev); + +int visconti_viif_l2_undist_through(struct viif_device *viif_dev); +#endif /* VIIF_PARAMS_H */ diff --git a/drivers/media/platform/toshiba/visconti/viif_stats.c b/drivers/media/platform/toshiba/visconti/viif_stats.c new file mode 100644 index 0000000000..05935f6650 --- /dev/null +++ b/drivers/media/platform/toshiba/visconti/viif_stats.c @@ -0,0 +1,336 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* Toshiba Visconti Video Capture Support + * + * (C) Copyright 2024 TOSHIBA CORPORATION + * (C) Copyright 2024 Toshiba Electronic Devices & Storage Corporation + */ + +#include <linux/delay.h> +#include <linux/pm_runtime.h> +#include <media/v4l2-common.h> +#include <media/v4l2-subdev.h> +#include <media/videobuf2-vmalloc.h> + +#include "viif.h" +#include "viif_csi2rx.h" +#include "viif_isp.h" +#include "viif_common.h" +#include "viif_regs.h" +#include "viif_stats.h" + +struct viif_buffer { + struct vb2_v4l2_buffer vb; + struct list_head queue; +}; + +static void read_isp_capture_regs(struct viif_l1_info *l1_info, struct viif_device *viif_dev) +{ + unsigned long irqflags; + int i, j; + u32 val; + + spin_lock_irqsave(&viif_dev->regbuf_lock, irqflags); + hwd_viif_isp_guard_start(viif_dev); + + /* change register buffer to regbuf0 where driver gets information */ + viif_capture_write(viif_dev, REG_L1_CRGBF_ACC_CONF, VAL_L1_CRGBF_ACC_CONF_MODE_BUFFER0); + + /* get AWB info */ + l1_info->awb_ave_u = viif_capture_read(viif_dev, REG_L1_AWHB_AVE_USIG); + l1_info->awb_ave_v = viif_capture_read(viif_dev, REG_L1_AWHB_AVE_VSIG); + l1_info->awb_accumulated_pixel = viif_capture_read(viif_dev, REG_L1_AWHB_NUM_UVON); + l1_info->awb_gain_r = viif_capture_read(viif_dev, REG_L1_AWHB_AWBGAINR); + l1_info->awb_gain_g = viif_capture_read(viif_dev, REG_L1_AWHB_AWBGAING); + l1_info->awb_gain_b = viif_capture_read(viif_dev, REG_L1_AWHB_AWBGAINB); + val = viif_capture_read(viif_dev, REG_L1_AWHB_R_CTR_STOP); + l1_info->awb_status_u = (FIELD_GET(BIT(1), val) != 0); + l1_info->awb_status_v = (FIELD_GET(BIT(0), val) != 0); + + /* get average luminance info */ + l1_info->avg_lum_weight = viif_capture_read(viif_dev, REG_L1_AEXP_RESULT_AVE); + val = viif_capture_read(viif_dev, REG_L1_AEXP_SATUR_BLACK_PIXNUM); + l1_info->avg_satur_pixnum = FIELD_GET(GENMASK(31, 16), val); + l1_info->avg_black_pixnum = FIELD_GET(GENMASK(15, 0), val); + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + l1_info->avg_lum_block[i][j] = + viif_capture_read(viif_dev, REG_L1_AEXP_AVE(i, j)); + } + } + l1_info->avg_lum_four_line_lum[0] = viif_capture_read(viif_dev, REG_L1_AEXP_AVE4LINES0); + l1_info->avg_lum_four_line_lum[1] = viif_capture_read(viif_dev, REG_L1_AEXP_AVE4LINES1); + l1_info->avg_lum_four_line_lum[2] = viif_capture_read(viif_dev, REG_L1_AEXP_AVE4LINES2); + l1_info->avg_lum_four_line_lum[3] = viif_capture_read(viif_dev, REG_L1_AEXP_AVE4LINES3); + + /* revert to register access from register buffer access */ + viif_capture_write(viif_dev, REG_L1_CRGBF_ACC_CONF, VAL_L1_CRGBF_ACC_CONF_MODE_BYPASS); + + hwd_viif_isp_guard_end(viif_dev); + spin_unlock_irqrestore(&viif_dev->regbuf_lock, irqflags); +} + +static const struct viif_csi2rx_dphy_calibration_status calib_status_not_streaming = { + .term_cal_with_rext = -EAGAIN, + .clock_lane_offset_cal = -EAGAIN, + .data_lane0_offset_cal = -EAGAIN, + .data_lane1_offset_cal = -EAGAIN, + .data_lane2_offset_cal = -EAGAIN, + .data_lane3_offset_cal = -EAGAIN, + .data_lane0_ddl_tuning_cal = -EAGAIN, + .data_lane1_ddl_tuning_cal = -EAGAIN, + .data_lane2_ddl_tuning_cal = -EAGAIN, + .data_lane3_ddl_tuning_cal = -EAGAIN, +}; + +static const struct viif_csi2rx_err_status csi_err_not_streaming; + +void visconti_viif_stats_isr(struct viif_device *viif_dev, unsigned int sequence, u64 timestamp) +{ + struct visconti_viif_isp_stat *cur_stat_buf; + struct stats_dev *stats_dev = &viif_dev->stats_dev; + struct viif_buffer *cur_buf; + + spin_lock(&stats_dev->stats_lock); + + if (list_empty(&stats_dev->stats_queue)) + goto done; + + cur_buf = list_first_entry(&stats_dev->stats_queue, struct viif_buffer, queue); + list_del(&cur_buf->queue); + cur_stat_buf = (struct visconti_viif_isp_stat *)vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0); + + if (!vb2_start_streaming_called(&viif_dev->cap_dev0.vb2_vq)) { + cur_stat_buf->csi2rx_dphy_calibration = calib_status_not_streaming; + } else { + visconti_viif_csi2rx_get_calibration_status(viif_dev, + &cur_stat_buf->csi2rx_dphy_calibration); + } + + if (!vb2_is_streaming(&viif_dev->cap_dev0.vb2_vq)) + cur_stat_buf->csi2rx_err = csi_err_not_streaming; + else + visconti_viif_csi2rx_get_err_status(viif_dev, &cur_stat_buf->csi2rx_err); + + read_isp_capture_regs(&cur_stat_buf->isp_capture.l1_info, viif_dev); + + cur_stat_buf->errors.main = viif_dev->reported_err_main; + cur_stat_buf->errors.sub = viif_dev->reported_err_sub; + cur_stat_buf->errors.csi2rx = viif_dev->reported_err_csi2rx; + viif_dev->reported_err_main = 0; + viif_dev->reported_err_sub = 0; + viif_dev->reported_err_csi2rx = 0; + + vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0, sizeof(struct visconti_viif_isp_stat)); + + cur_buf->vb.sequence = sequence; + cur_buf->vb.vb2_buf.timestamp = timestamp; + vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + +done: + spin_unlock(&stats_dev->stats_lock); +} + +static int viif_stats_enum_fmt_meta_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + struct video_device *vdev = video_devdata(file); + + if (f->index > 0 || f->type != vdev->queue->type) + return -EINVAL; + + f->pixelformat = V4L2_META_FMT_VISCONTI_VIIF_STATS; + + return 0; +} + +static int viif_stats_g_fmt_meta_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_meta_format *meta = &f->fmt.meta; + + if (f->type != vdev->queue->type) + return -EINVAL; + + memset(meta, 0, sizeof(*meta)); + meta->dataformat = V4L2_META_FMT_VISCONTI_VIIF_STATS; + meta->buffersize = sizeof(struct visconti_viif_isp_stat); + + return 0; +} + +static int viif_stats_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + strscpy(cap->driver, VIIF_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, vdev->name, sizeof(cap->card)); + strscpy(cap->bus_info, VIIF_BUS_INFO_BASE "-0", sizeof(cap->bus_info)); + + return 0; +} + +static const struct v4l2_ioctl_ops viif_stats_ioctl = { + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_enum_fmt_meta_cap = viif_stats_enum_fmt_meta_cap, + .vidioc_g_fmt_meta_cap = viif_stats_g_fmt_meta_cap, + .vidioc_s_fmt_meta_cap = viif_stats_g_fmt_meta_cap, + .vidioc_try_fmt_meta_cap = viif_stats_g_fmt_meta_cap, + .vidioc_querycap = viif_stats_querycap, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct v4l2_file_operations viif_stats_fops = { + .mmap = vb2_fop_mmap, + .unlocked_ioctl = video_ioctl2, + .poll = vb2_fop_poll, + .open = v4l2_fh_open, + .release = vb2_fop_release, +}; + +static int viif_stats_vb2_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, + unsigned int *num_planes, unsigned int sizes[], + struct device *alloc_devs[]) +{ + *num_planes = 1; + *num_buffers = clamp_t(u32, *num_buffers, 2, 8); + sizes[0] = sizeof(struct visconti_viif_isp_stat); + + return 0; +} + +static inline struct viif_buffer *vb2_to_viif(struct vb2_v4l2_buffer *vbuf) +{ + return container_of(vbuf, struct viif_buffer, vb); +} + +static inline struct stats_dev *vb2queue_to_statsdev(struct vb2_queue *q) +{ + return (struct stats_dev *)vb2_get_drv_priv(q); +} + +static void viif_stats_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct stats_dev *stats_dev = vb2queue_to_statsdev(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct viif_buffer *buf = vb2_to_viif(vbuf); + + spin_lock_irq(&stats_dev->stats_lock); + list_add_tail(&buf->queue, &stats_dev->stats_queue); + spin_unlock_irq(&stats_dev->stats_lock); +} + +static int viif_stats_vb2_buf_prepare(struct vb2_buffer *vb) +{ + if (vb2_plane_size(vb, 0) < sizeof(struct visconti_viif_isp_stat)) + return -EINVAL; + + vb2_set_plane_payload(vb, 0, sizeof(struct visconti_viif_isp_stat)); + + return 0; +} + +static void viif_stats_vb2_stop_streaming(struct vb2_queue *q) +{ + struct stats_dev *stats_dev = vb2queue_to_statsdev(q); + struct viif_buffer *buf; + unsigned int i; + + spin_lock_irq(&stats_dev->stats_lock); + for (i = 0; i < 8; i++) { + if (list_empty(&stats_dev->stats_queue)) + break; + buf = list_first_entry(&stats_dev->stats_queue, struct viif_buffer, queue); + list_del(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + spin_unlock_irq(&stats_dev->stats_lock); +} + +static const struct vb2_ops viif_stats_vb2_ops = { + .queue_setup = viif_stats_vb2_queue_setup, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .buf_queue = viif_stats_vb2_buf_queue, + .buf_prepare = viif_stats_vb2_buf_prepare, + .stop_streaming = viif_stats_vb2_stop_streaming, +}; + +int visconti_viif_stats_register(struct viif_device *viif_dev) +{ + struct stats_dev *stats_dev = &viif_dev->stats_dev; + struct video_device *vdev = &stats_dev->vdev; + struct vb2_queue *q = &stats_dev->vb2_vq; + int ret; + + mutex_init(&stats_dev->vlock); + INIT_LIST_HEAD(&stats_dev->stats_queue); + spin_lock_init(&stats_dev->stats_lock); + + strscpy(vdev->name, "viif_stats", sizeof(vdev->name)); + + /* Register the video device */ + video_set_drvdata(vdev, stats_dev); + vdev->ioctl_ops = &viif_stats_ioctl; + vdev->fops = &viif_stats_fops; + vdev->release = video_device_release_empty; + vdev->lock = &stats_dev->vlock; + vdev->v4l2_dev = &viif_dev->v4l2_dev; + vdev->queue = &stats_dev->vb2_vq; + vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; + vdev->vfl_dir = VFL_DIR_RX; + + /* Initialize vb2 queue */ + q->type = V4L2_BUF_TYPE_META_CAPTURE; + q->io_modes = VB2_MMAP | VB2_DMABUF; + q->drv_priv = stats_dev; + q->ops = &viif_stats_vb2_ops; + q->mem_ops = &vb2_vmalloc_memops; + q->buf_struct_size = sizeof(struct viif_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &stats_dev->vlock; + q->dev = viif_dev->v4l2_dev.dev; + + ret = vb2_queue_init(q); + if (ret) + return ret; + + stats_dev->stats_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&vdev->entity, VIIF_STATS_PAD_NUM, &stats_dev->stats_pad); + if (ret) + goto error; + + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(viif_dev->v4l2_dev.dev, "video_register_device failed: %d\n", ret); + goto error; + } + + return 0; + +error: + media_entity_cleanup(&vdev->entity); + mutex_destroy(&stats_dev->vlock); + + return ret; +} + +void visconti_viif_stats_unregister(struct viif_device *viif_dev) +{ + struct stats_dev *stats_dev = &viif_dev->stats_dev; + struct video_device *vdev = &stats_dev->vdev; + + if (!video_is_registered(vdev)) + return; + + vb2_video_unregister_device(vdev); + media_entity_cleanup(&vdev->entity); + mutex_destroy(&stats_dev->vlock); +} diff --git a/drivers/media/platform/toshiba/visconti/viif_stats.h b/drivers/media/platform/toshiba/visconti/viif_stats.h new file mode 100644 index 0000000000..65f390a441 --- /dev/null +++ b/drivers/media/platform/toshiba/visconti/viif_stats.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* Toshiba Visconti Video Capture Support + * + * (C) Copyright 2024 TOSHIBA CORPORATION + * (C) Copyright 2024 Toshiba Electronic Devices & Storage Corporation + */ + +#ifndef VIIF_STATS_H +#define VIIF_STATS_H + +void visconti_viif_stats_isr(struct viif_device *viif_dev, unsigned int sequence, u64 timestamp); +int visconti_viif_stats_register(struct viif_device *viif_dev); +void visconti_viif_stats_unregister(struct viif_device *viif_dev); +#endif /* VIIF_STATS_H */ -- 2.25.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver 2024-07-09 0:08 [PATCH v11 0/6] Add Toshiba Visconti Video Input Interface driver Yuji Ishikawa ` (2 preceding siblings ...) 2024-07-09 0:08 ` [PATCH v11 4/6] media: platform: visconti: add streaming interface for ISP parameters and status Yuji Ishikawa @ 2024-07-09 0:08 ` Yuji Ishikawa 2024-07-22 18:02 ` Laurent Pinchart 2024-07-09 0:08 ` [PATCH v11 6/6] MAINTAINERS: Add entries for Toshiba Visconti Video Input Interface Yuji Ishikawa [not found] ` <20240709000848.1108788-4-yuji2.ishikawa@toshiba.co.jp> 5 siblings, 1 reply; 20+ messages in thread From: Yuji Ishikawa @ 2024-07-09 0:08 UTC (permalink / raw) To: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, Yuji Ishikawa Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel Added description of Video Input Interface driver of Toshiba Visconti architecture. It includes hardware organization, structure of the driver and metadata format for embedded image signal processor. Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> --- Changelog v3: - Newly add documentation to describe SW and HW Changelog v4: - no change Changelog v5: - no change Changelog v6: - add description of CSI2RX subdevice - add ordering of ioctl(S_FMT) and ioctl(S_EXT_CTRLS) Changelog v7: - no change Changelog v8: - add usage of V4L2_CTRL_TYPE_VISCONTI_ISP Changelog v9: - fix warning: set reference target for keyword V4L2_CTRL_TYPE_VISCONTI_ISP Changelog v10: - use parameter buffers instead of compound control - removed description of vendor specific compound control - add description of parameter buffers for ISP control - update directory structure - remove documents under driver-api - add documents to admin-guide, userspace-api Changelog v11: - update usage of the driver .../admin-guide/media/v4l-drivers.rst | 1 + .../admin-guide/media/visconti-viif.dot | 18 ++ .../admin-guide/media/visconti-viif.rst | 255 ++++++++++++++++++ .../userspace-api/media/v4l/meta-formats.rst | 1 + .../media/v4l/metafmt-visconti-viif.rst | 48 ++++ 5 files changed, 323 insertions(+) create mode 100644 Documentation/admin-guide/media/visconti-viif.dot create mode 100644 Documentation/admin-guide/media/visconti-viif.rst create mode 100644 Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst index 4120eded9a..c7e67f455a 100644 --- a/Documentation/admin-guide/media/v4l-drivers.rst +++ b/Documentation/admin-guide/media/v4l-drivers.rst @@ -31,5 +31,6 @@ Video4Linux (V4L) driver-specific documentation si476x starfive_camss vimc + visconti-viif visl vivid diff --git a/Documentation/admin-guide/media/visconti-viif.dot b/Documentation/admin-guide/media/visconti-viif.dot new file mode 100644 index 0000000000..239d9fa2b3 --- /dev/null +++ b/Documentation/admin-guide/media/visconti-viif.dot @@ -0,0 +1,18 @@ +digraph board { + rankdir=TB + n00000001 [label="{{<port0> 0} | visconti-viif:csi2rx\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green] + n00000001:port1 -> n00000004:port0 + n00000004 [label="{{<port0> 0 | <port4> 4} | visconti-viif:isp\n/dev/v4l-subdev1 | {<port1> 1 | <port2> 2 | <port3> 3 | <port5> 5}}", shape=Mrecord, style=filled, fillcolor=green] + n00000004:port1 -> n0000000b + n00000004:port2 -> n0000000f + n00000004:port3 -> n00000013 + n00000004:port5 -> n0000001b + n0000000b [label="viif_capture_post0\n/dev/video0", shape=box, style=filled, fillcolor=yellow] + n0000000f [label="viif_capture_post1\n/dev/video1", shape=box, style=filled, fillcolor=yellow] + n00000013 [label="viif_capture_sub\n/dev/video2", shape=box, style=filled, fillcolor=yellow] + n00000017 [label="viif_params\n/dev/video3", shape=box, style=filled, fillcolor=yellow] + n00000017 -> n00000004:port4 + n0000001b [label="viif_stats\n/dev/video4", shape=box, style=filled, fillcolor=yellow] + n0000002b [label="{{} | imx219 1-0010\n/dev/v4l-subdev2 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green] + n0000002b:port0 -> n00000001:port0 +} diff --git a/Documentation/admin-guide/media/visconti-viif.rst b/Documentation/admin-guide/media/visconti-viif.rst new file mode 100644 index 0000000000..4ef676754c --- /dev/null +++ b/Documentation/admin-guide/media/visconti-viif.rst @@ -0,0 +1,255 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================================== +Visconti Video Input Interface Driver (visconti-viif) +====================================================== + +Introduction +============ + +This file documents the driver for the Video Input Interface (VIIF) that is +part of Toshiba Visconti SoCs. +The driver is located under drivers/media/platform/toshiba/visconti and uses +the Media-Controller API. + +The Visconti VIIF Hardware +========================== + +The Visconti VIIF hardware is a proprietary video capture device. +Following function modules are integrated: + +* MIPI CSI2 receiver (CSI2RX) +* L1 Image Signal Processor (L1ISP) + + * Correction, enhancement, adjustment on RAW pictures. + +* L2 Image Signal Processor (L2ISP) + + * Lens distortion correction + * Scaling + * Cropping + +* Video DMAC + + * format picture (RGB, YUV, Grayscale, ...) + * write picture into DRAM + +Visconti5 SoC has two VIIF hardware instances. + +Topology +======== + +.. _visconti_viif_topology_graph: + +.. kernel-figure:: visconti-viif.dot + :alt: Diagram of the default media pipeline topology + :align: center + +The driver has 5 video devices: + +- viif_capture_post0: capture device for image. + - corresponds to L2ISP and Video DMAC HW. +- viif_capture_post1: capture device for image. + - corresponds to L2ISP and Video DMAC HW. +- viif_capture_sub: capture device for RAW image. + - corresponds to Video DMAC HW. +- viif_params: a metadata output device that receives ISP parameters. + - corresponds to L1ISP and L2ISP HW. +- viif_stats: a metadata capture device that sends statistics. + - corresponds to L1ISP and L2ISP HW. + +The driver has 2 subdevices: + +- visconti-viif:csi2rx: CSI2 receiver operation. + - corresponds to CSI2RX HW. +- visconti-viif:isp: Image Signal Processor operation. + - corresponds to L1ISP and L2ISP HW. + +viif_capture_post0, viif_capture_post1 - Processed Image Capture Video Node +--------------------------------------------------------------------------- + +These video nodes are used for capturing images processed at ISPs. +They capture only following formats: + +- RGB3 +- AR24 +- YM16 +- YM24 +- Y16 + +Bayer format is not supported. Use viif_capture_sub instead. + +POST0 and POST1 can output images from the same input image +using different cropping and scaling settings. + +viif_capture_sub - Raw Image Capture Video Node +----------------------------------------------- + +This video node is used for capturing bayer image from the sensor. +The output picture has exactly the same resolution and format as the sensor input. +The following depth of bayer format is supported: + +- 8bit +- 10bit +- 12bit +- 14bit + +visconti-viif:csi2rx - CSI2 Receiver Subdevice Node +--------------------------------------------------- + +This subdevice node corresponds to a MIPI CSI2 receiver. +It resides between an image sensor subdevice and the ISP subdevice. +It controls CSI2 link configuration and training process. + +visconti-viif:isp - ISP Subdevice Node +-------------------------------------- + +This subdevice node corresponds to L1/L2 ISPs. +It receives pictures from an sensor (via CSI2RX), +applies multiple operations on pictures, then passes resulting images to capture nodes. + +L1 ISP provides following operations: + +- Input: accepts 8, 10, 12, 14bit bayer format +- Preprocessing: generate intermediate data (24bit RAW) + - HDRE: HDR expansion (only for PWL image); + see :c:type:`viif_l1_hdre_config`, :c:type:`viif_l1_input_mode_config` + - SLIC: Image Extraction (x3 12bit planes for preprocessing); + see :c:type:`viif_l1_img_extraction_config` + - ABPC/DPC: Defect pixel correction :c:type:`viif_l1_dpc_config` + - PWHB: Preset white balance; see :c:type:`viif_l1_preset_white_balance_config` + - RCNR: RAW color noise reduction; see :c:type:`viif_l1_raw_color_noise_reduction_config` + - HDRS: HDR synthesis; see :c:type:`viif_l1_hdrs_config` +- Processing on RAW image + - BLVC: black level correction and normalization; + see :c:type:`viif_l1_black_level_correction_config` + - LSSC: Lens shading correction; see :c:type:`viif_l1_lsc_config` + - MPRO: digital amplifier; see :c:type:`viif_l1_main_process_config` + - MPRO: bayer demosaicing; see :c:type:`viif_l1_main_process_config` + - MPRO: color matrix correction; see :c:type:`viif_l1_main_process_config` + - HDRC: HDR compression; + see :c:type:`viif_l1_hdrc_config`, :c:type:`viif_l1_hdrc_ltm_config`, + :c:type:`viif_l1_rgb_to_y_coef_config` +- Processing on RGB/YUV image + - VPRO: gamma correction; see :c:type:`viif_l1_gamma_config` + - VPRO: RGB2YUV; + see :c:type:`viif_l1_rgb_to_y_coef_config`, + :c:type:`viif_l1_img_quality_adjustment_config` + - VPRO: image quality adjustment; see :c:type:`viif_l1_img_quality_adjustment_config` +- Output: 16bit YUV +- Feedback loop with software + - AWHB: auto white balance; see :c:type:`viif_l1_awb_config`, + :c:type:`viif_isp_capture_status` + - AEXP: auto exposure (average luminance calculation); + see :c:type:`viif_l1_avg_lum_generation_config`, + :c:type:`viif_l1_rgb_to_y_coef_config`, :c:type:`viif_isp_capture_status` + - AG: analog gain calculation; + see :c:type:`viif_l1_ag_mode_config`, :c:type:`viif_l1_ag_config` + +L2 ISP provides following operations: + +- Input: accepts 16bit YUV +- Operations: + - Lens undistortion; see :c:type:`viif_l2_undist` + - Scaling; see :c:type:`viif_l2_roi` + - Cropping; see :c:type:`viif_l2_roi` + - Gamma correction; see :c:type:`viif_l2_gamma_config` + - YUV2RGB +- Output: RGB, YUV422, YUV444 + +ISP configurations/parameters are passed from userland via viif_params node. +The status of ISP operations are passed to userland via viif_stats node. + +.. _viif_params: + +viif_params - ISP Parameters Video Node +--------------------------------------- + +The viif_params video node receives a set of ISP parameters from userspace +to be applied to the hardware during a video stream. + +The buffer format is defined by struct :c:type:`visconti_viif_isp_config`, and userspace should set +:ref:`V4L2_META_FMT_VISCONTI_VIIF_PARAMS <v4l2-meta-fmt-visconti-viif-params>` as the data format. + +.. _viif_stats: + +viif_stats - Statistics Video Node +---------------------------------- + +The viif_stats video node provides current status of ISP. + +Following information is included: + +* statistics of auto white balance +* average luminance information which can be used by auto exposure software impl. + +The buffer format is defined by struct :c:type:`visconti_viif_isp_stat`, and userspace should set +:ref:`V4L2_META_FMT_VISCONTI_VIIF_STATS <v4l2-meta-fmt-visconti-viif-stats>` as the data format. + +Capturing Video Frames Example +============================== + +In the following example, +imx219 camera is connected to pad 0 of 'visconti-viif:isp'. + +The following commands can be used to capture video from the main path 0 +with dimension 1024x1024 and RGB format. + +.. code-block:: bash + + # set the links + media-ctl -d platform:visconti-viif-0 -r + media-ctl -d platform:visconti-viif-0 -l '"imx219 1-0010":0 -> "visconti-viif:csi2rx":0 [1]' + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:csi2rx":1 -> "visconti-viif:isp":0 [1]' + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":1 -> "viif_capture_post0":0 [1]' + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":2 -> "viif_capture_post1":0 [1]' + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":3 -> "viif_capture_sub":0 [1]' + media-ctl -d platform:visconti-viif-0 -l '"viif_params":0 -> "visconti-viif:isp":4 [1]' + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":5 -> "viif_stats":0 [1]' + + # set format for imx219 + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"imx219 1-0010":0 [fmt:SRGGB10_1X10/1920x1080]' + + # set format for csi2rx + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:csi2rx":0 [fmt:SRGGB10_1X10/1920x1080]' + + # set format for isp sink pad + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:isp":0 [fmt:SRGGB10_1X10/1920x1080 compose:(0,0)/1920x1080]' + + # set format for isp source pad + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:isp":1 [fmt:YUV8_1X24/1024 crop:(640,0)/1024x1024]' + + # set format for main path0 + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 -v "width=1024,height=1024" + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 -v "pixelformat=RGB3" + + # start streaming + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 --stream-mmap --stream-count 10 + + +Use of coherent memory +====================== + +Visconti5 SoC has two independent DDR SDRAM controllers. +Each controller is mapped to 36bit address space. + +Accelerator bus masters have two paths to access memory; +one is directly connected to SDRAM controller, +the another is connected via a cache coherency bus +which keeps coherency among CPUs. + +From accelerators and CPUs, the address map is following: + +* 0x0_8000_0000 DDR0 direct access +* 0x4_8000_0000 DDR0 coherency bus +* 0x8_8000_0000 DDR1 direct access +* 0xC_8000_0000 DDR1 coherency bus + +The base address can be specified with "memory" and "reserved-memory" elements +in a device tree description. +It's not recommended to mix direct address and coherent address. + +The Visconti5 VIIF driver always use only direct address to configure Video DMACs of the hardware. +This design is to avoid great performance loss at coherency bus caused by massive memory access. +You should not put the dma_coherent attribute to viif element in device tree. +Cache operations are done automatically by videobuf2 driver. diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst index c6e56b5888..23fa0ebe45 100644 --- a/Documentation/userspace-api/media/v4l/meta-formats.rst +++ b/Documentation/userspace-api/media/v4l/meta-formats.rst @@ -18,6 +18,7 @@ These formats are used for the :ref:`metadata` interface only. metafmt-pisp-be metafmt-rkisp1 metafmt-uvc + metafmt-visconti-viif metafmt-vivid metafmt-vsp1-hgo metafmt-vsp1-hgt diff --git a/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst b/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst new file mode 100644 index 0000000000..dc4b31627f --- /dev/null +++ b/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst @@ -0,0 +1,48 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _v4l2-meta-fmt-visconti-viif-params: + +.. _v4l2-meta-fmt-visconti-viif-stats: + +*************************************************************************************** +V4L2_META_FMT_VISCONTI_VIIF_PARAMS ('vifp'), V4L2_META_FMT_VISCONTI_VIIF_STATS ('vifs') +*************************************************************************************** + +Configuration parameters +======================== + +The configuration parameters are passed to the +:ref:`viif_params <viif_params>` metadata output video node, using +the :c:type:`v4l2_meta_format` interface. The buffer contains +a single instance of the C structure :c:type:`visconti_viif_isp_config` defined in +``visconti_viif.h``. So the structure can be obtained from the buffer by: + +.. code-block:: c + + struct visconti_viif_isp_config *params = (struct visconti_viif_isp_config*) buffer; + +VIIF statistics +=============== + +The VIIF device collects different statistics over an input Bayer frame. +Those statistics are obtained from the :ref:`viif_stats <viif_stats>` +metadata capture video node, +using the :c:type:`v4l2_meta_format` interface. The buffer contains a single +instance of the C structure :c:type:`visconti_viif_isp_stat` defined in +``visconti_viif.h``. So the structure can be obtained from the buffer by: + +.. code-block:: c + + struct visconti_viif_isp_stat *stats = (struct visconti_viif_isp_stat*) buffer; + +The statistics collected are Exposure, AWB (auto white balance) and errors. +See :c:type:`visconti_viif_isp_stat` for details of the statistics. + +The statistics and configuration parameters described here are usually +consumed and produced by dedicated user space libraries that comprise the +tuning tools using software control loop. + +visconti viif uAPI data types +============================= + +.. kernel-doc:: include/uapi/linux/visconti_viif.h -- 2.25.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver 2024-07-09 0:08 ` [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver Yuji Ishikawa @ 2024-07-22 18:02 ` Laurent Pinchart 2024-08-01 9:23 ` yuji2.ishikawa 0 siblings, 1 reply; 20+ messages in thread From: Laurent Pinchart @ 2024-07-22 18:02 UTC (permalink / raw) To: Yuji Ishikawa Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hi Ishikawa-san, Thank you for the patch. On Tue, Jul 09, 2024 at 09:08:47AM +0900, Yuji Ishikawa wrote: > Added description of Video Input Interface driver of > Toshiba Visconti architecture. > It includes hardware organization, structure of the driver > and metadata format for embedded image signal processor. > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > --- > Changelog v3: > - Newly add documentation to describe SW and HW > > Changelog v4: > - no change > > Changelog v5: > - no change > > Changelog v6: > - add description of CSI2RX subdevice > - add ordering of ioctl(S_FMT) and ioctl(S_EXT_CTRLS) > > Changelog v7: > - no change > > Changelog v8: > - add usage of V4L2_CTRL_TYPE_VISCONTI_ISP > > Changelog v9: > - fix warning: set reference target for keyword V4L2_CTRL_TYPE_VISCONTI_ISP > > Changelog v10: > - use parameter buffers instead of compound control > - removed description of vendor specific compound control > - add description of parameter buffers for ISP control > - update directory structure > - remove documents under driver-api > - add documents to admin-guide, userspace-api > > Changelog v11: > - update usage of the driver > > .../admin-guide/media/v4l-drivers.rst | 1 + > .../admin-guide/media/visconti-viif.dot | 18 ++ > .../admin-guide/media/visconti-viif.rst | 255 ++++++++++++++++++ > .../userspace-api/media/v4l/meta-formats.rst | 1 + > .../media/v4l/metafmt-visconti-viif.rst | 48 ++++ > 5 files changed, 323 insertions(+) > create mode 100644 Documentation/admin-guide/media/visconti-viif.dot > create mode 100644 Documentation/admin-guide/media/visconti-viif.rst > create mode 100644 Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > > diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst > index 4120eded9a..c7e67f455a 100644 > --- a/Documentation/admin-guide/media/v4l-drivers.rst > +++ b/Documentation/admin-guide/media/v4l-drivers.rst > @@ -31,5 +31,6 @@ Video4Linux (V4L) driver-specific documentation > si476x > starfive_camss > vimc > + visconti-viif > visl > vivid > diff --git a/Documentation/admin-guide/media/visconti-viif.dot b/Documentation/admin-guide/media/visconti-viif.dot > new file mode 100644 > index 0000000000..239d9fa2b3 > --- /dev/null > +++ b/Documentation/admin-guide/media/visconti-viif.dot > @@ -0,0 +1,18 @@ > +digraph board { > + rankdir=TB > + n00000001 [label="{{<port0> 0} | visconti-viif:csi2rx\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green] > + n00000001:port1 -> n00000004:port0 > + n00000004 [label="{{<port0> 0 | <port4> 4} | visconti-viif:isp\n/dev/v4l-subdev1 | {<port1> 1 | <port2> 2 | <port3> 3 | <port5> 5}}", shape=Mrecord, style=filled, fillcolor=green] > + n00000004:port1 -> n0000000b > + n00000004:port2 -> n0000000f > + n00000004:port3 -> n00000013 > + n00000004:port5 -> n0000001b > + n0000000b [label="viif_capture_post0\n/dev/video0", shape=box, style=filled, fillcolor=yellow] > + n0000000f [label="viif_capture_post1\n/dev/video1", shape=box, style=filled, fillcolor=yellow] > + n00000013 [label="viif_capture_sub\n/dev/video2", shape=box, style=filled, fillcolor=yellow] > + n00000017 [label="viif_params\n/dev/video3", shape=box, style=filled, fillcolor=yellow] > + n00000017 -> n00000004:port4 > + n0000001b [label="viif_stats\n/dev/video4", shape=box, style=filled, fillcolor=yellow] > + n0000002b [label="{{} | imx219 1-0010\n/dev/v4l-subdev2 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green] > + n0000002b:port0 -> n00000001:port0 > +} > diff --git a/Documentation/admin-guide/media/visconti-viif.rst b/Documentation/admin-guide/media/visconti-viif.rst > new file mode 100644 > index 0000000000..4ef676754c > --- /dev/null > +++ b/Documentation/admin-guide/media/visconti-viif.rst > @@ -0,0 +1,255 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +====================================================== > +Visconti Video Input Interface Driver (visconti-viif) > +====================================================== > + > +Introduction > +============ > + > +This file documents the driver for the Video Input Interface (VIIF) that is > +part of Toshiba Visconti SoCs. > +The driver is located under drivers/media/platform/toshiba/visconti and uses > +the Media-Controller API. > + > +The Visconti VIIF Hardware > +========================== > + > +The Visconti VIIF hardware is a proprietary video capture device. In what sense is it "proprietary" ? I know the hardware itself isn't open-source, but that's the case of most of the devices the kernel supports :-) > +Following function modules are integrated: > + > +* MIPI CSI2 receiver (CSI2RX) > +* L1 Image Signal Processor (L1ISP) > + > + * Correction, enhancement, adjustment on RAW pictures. > + > +* L2 Image Signal Processor (L2ISP) > + > + * Lens distortion correction > + * Scaling > + * Cropping > + > +* Video DMAC > + > + * format picture (RGB, YUV, Grayscale, ...) > + * write picture into DRAM > + > +Visconti5 SoC has two VIIF hardware instances. Could you provide a block diagram of the hardware, that shows how the components are connected ? The .dot file above shows the media graph, but doesn't map to a more detailed hardware view. I would like to see, in particular, how the CSI-2 RX, L1ISP, L2ISP and DMAC are connected, and ideally also the processing blocks inside the L1ISP and L2ISP, and how they are ordered. It is very important, for instance, to know exactly where in the processing pipeline the statistics are collected. See https://lore.kernel.org/linux-media/20240709132906.3198927-9-dan.scally@ideasonboard.com/ and https://lore.kernel.org/linux-media/20240709132906.3198927-15-dan.scally@ideasonboard.com/ for examples of the level of details. The diagram in the first link is a good candidate for this section of the documentation, and the one from the second link could go below in the "visconti-viif:isp - ISP Subdevice Node" section. You can use ascii art of .dot or .svg, up to you. > + > +Topology > +======== > + > +.. _visconti_viif_topology_graph: > + > +.. kernel-figure:: visconti-viif.dot > + :alt: Diagram of the default media pipeline topology > + :align: center > + > +The driver has 5 video devices: > + > +- viif_capture_post0: capture device for image. > + - corresponds to L2ISP and Video DMAC HW. > +- viif_capture_post1: capture device for image. > + - corresponds to L2ISP and Video DMAC HW. > +- viif_capture_sub: capture device for RAW image. > + - corresponds to Video DMAC HW. Does the raw capture occur right after the CSI-2 receiver, or is there any processing applied to the image ? That's a question that would be answered by a hardware block diagram. > +- viif_params: a metadata output device that receives ISP parameters. > + - corresponds to L1ISP and L2ISP HW. > +- viif_stats: a metadata capture device that sends statistics. > + - corresponds to L1ISP and L2ISP HW. > + > +The driver has 2 subdevices: > + > +- visconti-viif:csi2rx: CSI2 receiver operation. > + - corresponds to CSI2RX HW. > +- visconti-viif:isp: Image Signal Processor operation. > + - corresponds to L1ISP and L2ISP HW. > + > +viif_capture_post0, viif_capture_post1 - Processed Image Capture Video Node > +--------------------------------------------------------------------------- > + > +These video nodes are used for capturing images processed at ISPs. > +They capture only following formats: > + > +- RGB3 > +- AR24 > +- YM16 > +- YM24 > +- Y16 Please list the formats using the V4L2_PIX_FMT_* macros instead of the 4CC value, it will be easier to read. > + > +Bayer format is not supported. Use viif_capture_sub instead. > + > +POST0 and POST1 can output images from the same input image > +using different cropping and scaling settings. Are there any other processing parameters that can differ between POST0 and POST1 ? I'm thinking for instance about colour spaces. If so, this should be explained here. > + > +viif_capture_sub - Raw Image Capture Video Node > +----------------------------------------------- > + > +This video node is used for capturing bayer image from the sensor. > +The output picture has exactly the same resolution and format as the sensor input. > +The following depth of bayer format is supported: > + > +- 8bit > +- 10bit > +- 12bit > +- 14bit Does the hardware support capturing embedded data from the sensor ? > + > +visconti-viif:csi2rx - CSI2 Receiver Subdevice Node > +--------------------------------------------------- > + > +This subdevice node corresponds to a MIPI CSI2 receiver. > +It resides between an image sensor subdevice and the ISP subdevice. > +It controls CSI2 link configuration and training process. > + > +visconti-viif:isp - ISP Subdevice Node > +-------------------------------------- > + > +This subdevice node corresponds to L1/L2 ISPs. > +It receives pictures from an sensor (via CSI2RX), > +applies multiple operations on pictures, then passes resulting images to capture nodes. > + > +L1 ISP provides following operations: > + > +- Input: accepts 8, 10, 12, 14bit bayer format > +- Preprocessing: generate intermediate data (24bit RAW) > + - HDRE: HDR expansion (only for PWL image); > + see :c:type:`viif_l1_hdre_config`, :c:type:`viif_l1_input_mode_config` > + - SLIC: Image Extraction (x3 12bit planes for preprocessing); > + see :c:type:`viif_l1_img_extraction_config` > + - ABPC/DPC: Defect pixel correction :c:type:`viif_l1_dpc_config` > + - PWHB: Preset white balance; see :c:type:`viif_l1_preset_white_balance_config` > + - RCNR: RAW color noise reduction; see :c:type:`viif_l1_raw_color_noise_reduction_config` > + - HDRS: HDR synthesis; see :c:type:`viif_l1_hdrs_config` > +- Processing on RAW image > + - BLVC: black level correction and normalization; > + see :c:type:`viif_l1_black_level_correction_config` > + - LSSC: Lens shading correction; see :c:type:`viif_l1_lsc_config` > + - MPRO: digital amplifier; see :c:type:`viif_l1_main_process_config` > + - MPRO: bayer demosaicing; see :c:type:`viif_l1_main_process_config` > + - MPRO: color matrix correction; see :c:type:`viif_l1_main_process_config` > + - HDRC: HDR compression; > + see :c:type:`viif_l1_hdrc_config`, :c:type:`viif_l1_hdrc_ltm_config`, > + :c:type:`viif_l1_rgb_to_y_coef_config` > +- Processing on RGB/YUV image > + - VPRO: gamma correction; see :c:type:`viif_l1_gamma_config` > + - VPRO: RGB2YUV; > + see :c:type:`viif_l1_rgb_to_y_coef_config`, > + :c:type:`viif_l1_img_quality_adjustment_config` > + - VPRO: image quality adjustment; see :c:type:`viif_l1_img_quality_adjustment_config` > +- Output: 16bit YUV > +- Feedback loop with software > + - AWHB: auto white balance; see :c:type:`viif_l1_awb_config`, > + :c:type:`viif_isp_capture_status` > + - AEXP: auto exposure (average luminance calculation); > + see :c:type:`viif_l1_avg_lum_generation_config`, > + :c:type:`viif_l1_rgb_to_y_coef_config`, :c:type:`viif_isp_capture_status` > + - AG: analog gain calculation; > + see :c:type:`viif_l1_ag_mode_config`, :c:type:`viif_l1_ag_config` > + > +L2 ISP provides following operations: > + > +- Input: accepts 16bit YUV > +- Operations: > + - Lens undistortion; see :c:type:`viif_l2_undist` > + - Scaling; see :c:type:`viif_l2_roi` > + - Cropping; see :c:type:`viif_l2_roi` > + - Gamma correction; see :c:type:`viif_l2_gamma_config` > + - YUV2RGB > +- Output: RGB, YUV422, YUV444 > + > +ISP configurations/parameters are passed from userland via viif_params node. > +The status of ISP operations are passed to userland via viif_stats node. > + > +.. _viif_params: > + > +viif_params - ISP Parameters Video Node > +--------------------------------------- > + > +The viif_params video node receives a set of ISP parameters from userspace > +to be applied to the hardware during a video stream. > + > +The buffer format is defined by struct :c:type:`visconti_viif_isp_config`, and userspace should set > +:ref:`V4L2_META_FMT_VISCONTI_VIIF_PARAMS <v4l2-meta-fmt-visconti-viif-params>` as the data format. > + > +.. _viif_stats: > + > +viif_stats - Statistics Video Node > +---------------------------------- > + > +The viif_stats video node provides current status of ISP. > + > +Following information is included: > + > +* statistics of auto white balance > +* average luminance information which can be used by auto exposure software impl. s/impl/implementation/ Out of curiosity, is there no statistics for auto-focus ? > + > +The buffer format is defined by struct :c:type:`visconti_viif_isp_stat`, and userspace should set > +:ref:`V4L2_META_FMT_VISCONTI_VIIF_STATS <v4l2-meta-fmt-visconti-viif-stats>` as the data format. > + > +Capturing Video Frames Example > +============================== > + > +In the following example, > +imx219 camera is connected to pad 0 of 'visconti-viif:isp'. > + > +The following commands can be used to capture video from the main path 0 > +with dimension 1024x1024 and RGB format. > + > +.. code-block:: bash > + > + # set the links > + media-ctl -d platform:visconti-viif-0 -r > + media-ctl -d platform:visconti-viif-0 -l '"imx219 1-0010":0 -> "visconti-viif:csi2rx":0 [1]' > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:csi2rx":1 -> "visconti-viif:isp":0 [1]' > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":1 -> "viif_capture_post0":0 [1]' > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":2 -> "viif_capture_post1":0 [1]' > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":3 -> "viif_capture_sub":0 [1]' > + media-ctl -d platform:visconti-viif-0 -l '"viif_params":0 -> "visconti-viif:isp":4 [1]' > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":5 -> "viif_stats":0 [1]' > + > + # set format for imx219 > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"imx219 1-0010":0 [fmt:SRGGB10_1X10/1920x1080]' > + > + # set format for csi2rx > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:csi2rx":0 [fmt:SRGGB10_1X10/1920x1080]' > + > + # set format for isp sink pad > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:isp":0 [fmt:SRGGB10_1X10/1920x1080 compose:(0,0)/1920x1080]' > + > + # set format for isp source pad > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:isp":1 [fmt:YUV8_1X24/1024 crop:(640,0)/1024x1024]' > + > + # set format for main path0 > + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 -v "width=1024,height=1024" > + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 -v "pixelformat=RGB3" > + > + # start streaming > + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 --stream-mmap --stream-count 10 > + > + > +Use of coherent memory > +====================== > + > +Visconti5 SoC has two independent DDR SDRAM controllers. > +Each controller is mapped to 36bit address space. > + > +Accelerator bus masters have two paths to access memory; > +one is directly connected to SDRAM controller, > +the another is connected via a cache coherency bus > +which keeps coherency among CPUs. > + > +From accelerators and CPUs, the address map is following: > + > +* 0x0_8000_0000 DDR0 direct access > +* 0x4_8000_0000 DDR0 coherency bus > +* 0x8_8000_0000 DDR1 direct access > +* 0xC_8000_0000 DDR1 coherency bus > + > +The base address can be specified with "memory" and "reserved-memory" elements > +in a device tree description. > +It's not recommended to mix direct address and coherent address. > + > +The Visconti5 VIIF driver always use only direct address to configure Video DMACs of the hardware. > +This design is to avoid great performance loss at coherency bus caused by massive memory access. > +You should not put the dma_coherent attribute to viif element in device tree. > +Cache operations are done automatically by videobuf2 driver. > diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst > index c6e56b5888..23fa0ebe45 100644 > --- a/Documentation/userspace-api/media/v4l/meta-formats.rst > +++ b/Documentation/userspace-api/media/v4l/meta-formats.rst > @@ -18,6 +18,7 @@ These formats are used for the :ref:`metadata` interface only. > metafmt-pisp-be > metafmt-rkisp1 > metafmt-uvc > + metafmt-visconti-viif > metafmt-vivid > metafmt-vsp1-hgo > metafmt-vsp1-hgt > diff --git a/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst b/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > new file mode 100644 > index 0000000000..dc4b31627f > --- /dev/null > +++ b/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > @@ -0,0 +1,48 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +.. _v4l2-meta-fmt-visconti-viif-params: > + > +.. _v4l2-meta-fmt-visconti-viif-stats: > + > +*************************************************************************************** > +V4L2_META_FMT_VISCONTI_VIIF_PARAMS ('vifp'), V4L2_META_FMT_VISCONTI_VIIF_STATS ('vifs') > +*************************************************************************************** > + > +Configuration parameters > +======================== > + > +The configuration parameters are passed to the > +:ref:`viif_params <viif_params>` metadata output video node, using > +the :c:type:`v4l2_meta_format` interface. The buffer contains > +a single instance of the C structure :c:type:`visconti_viif_isp_config` defined in > +``visconti_viif.h``. So the structure can be obtained from the buffer by: > + > +.. code-block:: c > + > + struct visconti_viif_isp_config *params = (struct visconti_viif_isp_config*) buffer; > + > +VIIF statistics > +=============== > + > +The VIIF device collects different statistics over an input Bayer frame. > +Those statistics are obtained from the :ref:`viif_stats <viif_stats>` > +metadata capture video node, > +using the :c:type:`v4l2_meta_format` interface. The buffer contains a single > +instance of the C structure :c:type:`visconti_viif_isp_stat` defined in > +``visconti_viif.h``. So the structure can be obtained from the buffer by: > + > +.. code-block:: c > + > + struct visconti_viif_isp_stat *stats = (struct visconti_viif_isp_stat*) buffer; > + > +The statistics collected are Exposure, AWB (auto white balance) and errors. > +See :c:type:`visconti_viif_isp_stat` for details of the statistics. > + > +The statistics and configuration parameters described here are usually > +consumed and produced by dedicated user space libraries that comprise the > +tuning tools using software control loop. > + > +visconti viif uAPI data types > +============================= > + > +.. kernel-doc:: include/uapi/linux/visconti_viif.h -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver 2024-07-22 18:02 ` Laurent Pinchart @ 2024-08-01 9:23 ` yuji2.ishikawa 2024-08-01 16:06 ` Laurent Pinchart 0 siblings, 1 reply; 20+ messages in thread From: yuji2.ishikawa @ 2024-08-01 9:23 UTC (permalink / raw) To: laurent.pinchart Cc: hverkuil, mchehab, robh, krzk+dt, conor+dt, broonie, sakari.ailus, nobuhiro1.iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hello Laurent, Thank you for your review. > -----Original Message----- > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Sent: Tuesday, July 23, 2024 3:03 AM > To: ishikawa yuji(石川 悠司 ○RDC□AITC○EA開) > <yuji2.ishikawa@toshiba.co.jp> > Cc: Hans Verkuil <hverkuil@xs4all.nl>; Mauro Carvalho Chehab > <mchehab@kernel.org>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski > <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Mark Brown > <broonie@kernel.org>; Sakari Ailus <sakari.ailus@linux.intel.com>; iwamatsu > nobuhiro(岩松 信洋 ○DITC□DIT○OST) > <nobuhiro1.iwamatsu@toshiba.co.jp>; linux-media@vger.kernel.org; > devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v11 5/6] documentation: media: add documentation for > Toshiba Visconti Video Input Interface driver > > Hi Ishikawa-san, > > Thank you for the patch. > > On Tue, Jul 09, 2024 at 09:08:47AM +0900, Yuji Ishikawa wrote: > > Added description of Video Input Interface driver of Toshiba Visconti > > architecture. > > It includes hardware organization, structure of the driver and > > metadata format for embedded image signal processor. > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > --- > > Changelog v3: > > - Newly add documentation to describe SW and HW > > > > Changelog v4: > > - no change > > > > Changelog v5: > > - no change > > > > Changelog v6: > > - add description of CSI2RX subdevice > > - add ordering of ioctl(S_FMT) and ioctl(S_EXT_CTRLS) > > > > Changelog v7: > > - no change > > > > Changelog v8: > > - add usage of V4L2_CTRL_TYPE_VISCONTI_ISP > > > > Changelog v9: > > - fix warning: set reference target for keyword > > V4L2_CTRL_TYPE_VISCONTI_ISP > > > > Changelog v10: > > - use parameter buffers instead of compound control > > - removed description of vendor specific compound control > > - add description of parameter buffers for ISP control > > - update directory structure > > - remove documents under driver-api > > - add documents to admin-guide, userspace-api > > > > Changelog v11: > > - update usage of the driver > > > > .../admin-guide/media/v4l-drivers.rst | 1 + > > .../admin-guide/media/visconti-viif.dot | 18 ++ > > .../admin-guide/media/visconti-viif.rst | 255 > ++++++++++++++++++ > > .../userspace-api/media/v4l/meta-formats.rst | 1 + > > .../media/v4l/metafmt-visconti-viif.rst | 48 ++++ > > 5 files changed, 323 insertions(+) > > create mode 100644 Documentation/admin-guide/media/visconti-viif.dot > > create mode 100644 Documentation/admin-guide/media/visconti-viif.rst > > create mode 100644 > > Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > > > > diff --git a/Documentation/admin-guide/media/v4l-drivers.rst > > b/Documentation/admin-guide/media/v4l-drivers.rst > > index 4120eded9a..c7e67f455a 100644 > > --- a/Documentation/admin-guide/media/v4l-drivers.rst > > +++ b/Documentation/admin-guide/media/v4l-drivers.rst > > @@ -31,5 +31,6 @@ Video4Linux (V4L) driver-specific documentation > > si476x > > starfive_camss > > vimc > > + visconti-viif > > visl > > vivid > > diff --git a/Documentation/admin-guide/media/visconti-viif.dot > > b/Documentation/admin-guide/media/visconti-viif.dot > > new file mode 100644 > > index 0000000000..239d9fa2b3 > > --- /dev/null > > +++ b/Documentation/admin-guide/media/visconti-viif.dot > > @@ -0,0 +1,18 @@ > > +digraph board { > > + rankdir=TB > > + n00000001 [label="{{<port0> 0} | > visconti-viif:csi2rx\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, > style=filled, fillcolor=green] > > + n00000001:port1 -> n00000004:port0 > > + n00000004 [label="{{<port0> 0 | <port4> 4} | > visconti-viif:isp\n/dev/v4l-subdev1 | {<port1> 1 | <port2> 2 | <port3> 3 | > <port5> 5}}", shape=Mrecord, style=filled, fillcolor=green] > > + n00000004:port1 -> n0000000b > > + n00000004:port2 -> n0000000f > > + n00000004:port3 -> n00000013 > > + n00000004:port5 -> n0000001b > > + n0000000b [label="viif_capture_post0\n/dev/video0", shape=box, > style=filled, fillcolor=yellow] > > + n0000000f [label="viif_capture_post1\n/dev/video1", shape=box, > style=filled, fillcolor=yellow] > > + n00000013 [label="viif_capture_sub\n/dev/video2", shape=box, > style=filled, fillcolor=yellow] > > + n00000017 [label="viif_params\n/dev/video3", shape=box, > style=filled, fillcolor=yellow] > > + n00000017 -> n00000004:port4 > > + n0000001b [label="viif_stats\n/dev/video4", shape=box, > style=filled, fillcolor=yellow] > > + n0000002b [label="{{} | imx219 1-0010\n/dev/v4l-subdev2 | > {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green] > > + n0000002b:port0 -> n00000001:port0 } > > diff --git a/Documentation/admin-guide/media/visconti-viif.rst > > b/Documentation/admin-guide/media/visconti-viif.rst > > new file mode 100644 > > index 0000000000..4ef676754c > > --- /dev/null > > +++ b/Documentation/admin-guide/media/visconti-viif.rst > > @@ -0,0 +1,255 @@ > > +.. SPDX-License-Identifier: GPL-2.0 > > + > > > +================================================ > ====== > > +Visconti Video Input Interface Driver (visconti-viif) > > > +================================================ > ====== > > + > > +Introduction > > +============ > > + > > +This file documents the driver for the Video Input Interface (VIIF) > > +that is part of Toshiba Visconti SoCs. > > +The driver is located under drivers/media/platform/toshiba/visconti > > +and uses the Media-Controller API. > > + > > +The Visconti VIIF Hardware > > +========================== > > + > > +The Visconti VIIF hardware is a proprietary video capture device. > > In what sense is it "proprietary" ? I know the hardware itself isn't open-source, > but that's the case of most of the devices the kernel supports :-) > It's more accurate to say "in-house" device rather than "proprietary" one. I'll fix it. > > +Following function modules are integrated: > > + > > +* MIPI CSI2 receiver (CSI2RX) > > +* L1 Image Signal Processor (L1ISP) > > + > > + * Correction, enhancement, adjustment on RAW pictures. > > + > > +* L2 Image Signal Processor (L2ISP) > > + > > + * Lens distortion correction > > + * Scaling > > + * Cropping > > + > > +* Video DMAC > > + > > + * format picture (RGB, YUV, Grayscale, ...) > > + * write picture into DRAM > > + > > +Visconti5 SoC has two VIIF hardware instances. > > Could you provide a block diagram of the hardware, that shows how the > components are connected ? The .dot file above shows the media graph, but > doesn't map to a more detailed hardware view. I would like to see, in particular, > how the CSI-2 RX, L1ISP, L2ISP and DMAC are connected, and ideally also the > processing blocks inside the L1ISP and L2ISP, and how they are ordered. It is > very important, for instance, to know exactly where in the processing pipeline > the statistics are collected. > > See > https://lore.kernel.org/linux-media/20240709132906.3198927-9-dan.scally@i > deasonboard.com/ > and > https://lore.kernel.org/linux-media/20240709132906.3198927-15-dan.scally@ > ideasonboard.com/ > for examples of the level of details. The diagram in the first link is a good > candidate for this section of the documentation, and the one from the second > link could go below in the "visconti-viif:isp - ISP Subdevice Node" section. You > can use ascii art of .dot or .svg, up to you. > I'll add block diagrams of the hardware (whole VIIF / inside ISPs). > > + > > +Topology > > +======== > > + > > +.. _visconti_viif_topology_graph: > > + > > +.. kernel-figure:: visconti-viif.dot > > + :alt: Diagram of the default media pipeline topology > > + :align: center > > + > > +The driver has 5 video devices: > > + > > +- viif_capture_post0: capture device for image. > > + - corresponds to L2ISP and Video DMAC HW. > > +- viif_capture_post1: capture device for image. > > + - corresponds to L2ISP and Video DMAC HW. > > +- viif_capture_sub: capture device for RAW image. > > + - corresponds to Video DMAC HW. > > Does the raw capture occur right after the CSI-2 receiver, or is there any > processing applied to the image ? That's a question that would be answered by > a hardware block diagram. > RAW capture occurs right after the CSI-2 receiver without any image processings. > > +- viif_params: a metadata output device that receives ISP parameters. > > + - corresponds to L1ISP and L2ISP HW. > > +- viif_stats: a metadata capture device that sends statistics. > > + - corresponds to L1ISP and L2ISP HW. > > + > > +The driver has 2 subdevices: > > + > > +- visconti-viif:csi2rx: CSI2 receiver operation. > > + - corresponds to CSI2RX HW. > > +- visconti-viif:isp: Image Signal Processor operation. > > + - corresponds to L1ISP and L2ISP HW. > > + > > +viif_capture_post0, viif_capture_post1 - Processed Image Capture > > +Video Node > > +--------------------------------------------------------------------- > > +------ > > + > > +These video nodes are used for capturing images processed at ISPs. > > +They capture only following formats: > > + > > +- RGB3 > > +- AR24 > > +- YM16 > > +- YM24 > > +- Y16 > > Please list the formats using the V4L2_PIX_FMT_* macros instead of the 4CC > value, it will be easier to read. > I'll use V4L2_PIX_FMT_*. > > + > > +Bayer format is not supported. Use viif_capture_sub instead. > > + > > +POST0 and POST1 can output images from the same input image using > > +different cropping and scaling settings. > > Are there any other processing parameters that can differ between POST0 and > POST1 ? I'm thinking for instance about colour spaces. If so, this should be > explained here. > POST0 and POST1 support the same functions and color spaces. > > + > > +viif_capture_sub - Raw Image Capture Video Node > > +----------------------------------------------- > > + > > +This video node is used for capturing bayer image from the sensor. > > +The output picture has exactly the same resolution and format as the > sensor input. > > +The following depth of bayer format is supported: > > + > > +- 8bit > > +- 10bit > > +- 12bit > > +- 14bit > > Does the hardware support capturing embedded data from the sensor ? > The hardware supports capturing embdded data, however the software is not fully tested for that feature. > > + > > +visconti-viif:csi2rx - CSI2 Receiver Subdevice Node > > +--------------------------------------------------- > > + > > +This subdevice node corresponds to a MIPI CSI2 receiver. > > +It resides between an image sensor subdevice and the ISP subdevice. > > +It controls CSI2 link configuration and training process. > > + > > +visconti-viif:isp - ISP Subdevice Node > > +-------------------------------------- > > + > > +This subdevice node corresponds to L1/L2 ISPs. > > +It receives pictures from an sensor (via CSI2RX), applies multiple > > +operations on pictures, then passes resulting images to capture nodes. > > + > > +L1 ISP provides following operations: > > + > > +- Input: accepts 8, 10, 12, 14bit bayer format > > +- Preprocessing: generate intermediate data (24bit RAW) > > + - HDRE: HDR expansion (only for PWL image); > > + > see :c:type:`viif_l1_hdre_config`, :c:type:`viif_l1_input_mode_config` > > + - SLIC: Image Extraction (x3 12bit planes for preprocessing); > > + see :c:type:`viif_l1_img_extraction_config` > > + - ABPC/DPC: Defect pixel correction :c:type:`viif_l1_dpc_config` > > + - PWHB: Preset white balance; > see :c:type:`viif_l1_preset_white_balance_config` > > + - RCNR: RAW color noise reduction; > see :c:type:`viif_l1_raw_color_noise_reduction_config` > > + - HDRS: HDR synthesis; see :c:type:`viif_l1_hdrs_config` > > +- Processing on RAW image > > + - BLVC: black level correction and normalization; > > + see :c:type:`viif_l1_black_level_correction_config` > > + - LSSC: Lens shading correction; see :c:type:`viif_l1_lsc_config` > > + - MPRO: digital amplifier; see :c:type:`viif_l1_main_process_config` > > + - MPRO: bayer demosaicing; see :c:type:`viif_l1_main_process_config` > > + - MPRO: color matrix correction; > see :c:type:`viif_l1_main_process_config` > > + - HDRC: HDR compression; > > + see :c:type:`viif_l1_hdrc_config`, :c:type:`viif_l1_hdrc_ltm_config`, > > + :c:type:`viif_l1_rgb_to_y_coef_config` > > +- Processing on RGB/YUV image > > + - VPRO: gamma correction; see :c:type:`viif_l1_gamma_config` > > + - VPRO: RGB2YUV; > > + see :c:type:`viif_l1_rgb_to_y_coef_config`, > > + :c:type:`viif_l1_img_quality_adjustment_config` > > + - VPRO: image quality adjustment; see > > +:c:type:`viif_l1_img_quality_adjustment_config` > > +- Output: 16bit YUV > > +- Feedback loop with software > > + - AWHB: auto white balance; see :c:type:`viif_l1_awb_config`, > > + :c:type:`viif_isp_capture_status` > > + - AEXP: auto exposure (average luminance calculation); > > + see :c:type:`viif_l1_avg_lum_generation_config`, > > > + :c:type:`viif_l1_rgb_to_y_coef_config`, :c:type:`viif_isp_capture_status > ` > > + - AG: analog gain calculation; > > + see :c:type:`viif_l1_ag_mode_config`, > > +:c:type:`viif_l1_ag_config` > > + > > +L2 ISP provides following operations: > > + > > +- Input: accepts 16bit YUV > > +- Operations: > > + - Lens undistortion; see :c:type:`viif_l2_undist` > > + - Scaling; see :c:type:`viif_l2_roi` > > + - Cropping; see :c:type:`viif_l2_roi` > > + - Gamma correction; see :c:type:`viif_l2_gamma_config` > > + - YUV2RGB > > +- Output: RGB, YUV422, YUV444 > > + > > +ISP configurations/parameters are passed from userland via viif_params > node. > > +The status of ISP operations are passed to userland via viif_stats node. > > + > > +.. _viif_params: > > + > > +viif_params - ISP Parameters Video Node > > +--------------------------------------- > > + > > +The viif_params video node receives a set of ISP parameters from > > +userspace to be applied to the hardware during a video stream. > > + > > +The buffer format is defined by struct > > +:c:type:`visconti_viif_isp_config`, and userspace should > set :ref:`V4L2_META_FMT_VISCONTI_VIIF_PARAMS > <v4l2-meta-fmt-visconti-viif-params>` as the data format. > > + > > +.. _viif_stats: > > + > > +viif_stats - Statistics Video Node > > +---------------------------------- > > + > > +The viif_stats video node provides current status of ISP. > > + > > +Following information is included: > > + > > +* statistics of auto white balance > > +* average luminance information which can be used by auto exposure > software impl. > > s/impl/implementation/ > I'll fix it. > Out of curiosity, is there no statistics for auto-focus ? > The VIIF HW does not support auto-focus. It supports only auto-exposure and auto-white-balance. > > + > > +The buffer format is defined by struct > > +:c:type:`visconti_viif_isp_stat`, and userspace should > set :ref:`V4L2_META_FMT_VISCONTI_VIIF_STATS > <v4l2-meta-fmt-visconti-viif-stats>` as the data format. > > + > > +Capturing Video Frames Example > > +============================== > > + > > +In the following example, > > +imx219 camera is connected to pad 0 of 'visconti-viif:isp'. > > + > > +The following commands can be used to capture video from the main > > +path 0 with dimension 1024x1024 and RGB format. > > + > > +.. code-block:: bash > > + > > + # set the links > > + media-ctl -d platform:visconti-viif-0 -r > > + media-ctl -d platform:visconti-viif-0 -l '"imx219 1-0010":0 -> > "visconti-viif:csi2rx":0 [1]' > > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:csi2rx":1 -> > "visconti-viif:isp":0 [1]' > > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":1 -> > "viif_capture_post0":0 [1]' > > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":2 -> > "viif_capture_post1":0 [1]' > > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":3 -> > "viif_capture_sub":0 [1]' > > + media-ctl -d platform:visconti-viif-0 -l '"viif_params":0 -> > "visconti-viif:isp":4 [1]' > > + media-ctl -d platform:visconti-viif-0 -l '"visconti-viif:isp":5 -> > "viif_stats":0 [1]' > > + > > + # set format for imx219 > > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"imx219 1-0010":0 > [fmt:SRGGB10_1X10/1920x1080]' > > + > > + # set format for csi2rx > > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:csi2rx":0 > [fmt:SRGGB10_1X10/1920x1080]' > > + > > + # set format for isp sink pad > > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:isp":0 > [fmt:SRGGB10_1X10/1920x1080 compose:(0,0)/1920x1080]' > > + > > + # set format for isp source pad > > + media-ctl -d platform:visconti-viif-0 --set-v4l2 '"visconti-viif:isp":1 > [fmt:YUV8_1X24/1024 crop:(640,0)/1024x1024]' > > + > > + # set format for main path0 > > + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 -v > "width=1024,height=1024" > > + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 -v > "pixelformat=RGB3" > > + > > + # start streaming > > + v4l2-ctl -z platform:visconti-viif-0 -d viif_capture_post0 > > +--stream-mmap --stream-count 10 > > + > > + > > +Use of coherent memory > > +====================== > > + > > +Visconti5 SoC has two independent DDR SDRAM controllers. > > +Each controller is mapped to 36bit address space. > > + > > +Accelerator bus masters have two paths to access memory; one is > > +directly connected to SDRAM controller, the another is connected via > > +a cache coherency bus which keeps coherency among CPUs. > > + > > +From accelerators and CPUs, the address map is following: > > + > > +* 0x0_8000_0000 DDR0 direct access > > +* 0x4_8000_0000 DDR0 coherency bus > > +* 0x8_8000_0000 DDR1 direct access > > +* 0xC_8000_0000 DDR1 coherency bus > > + > > +The base address can be specified with "memory" and "reserved-memory" > > +elements in a device tree description. > > +It's not recommended to mix direct address and coherent address. > > + > > +The Visconti5 VIIF driver always use only direct address to configure Video > DMACs of the hardware. > > +This design is to avoid great performance loss at coherency bus caused by > massive memory access. > > +You should not put the dma_coherent attribute to viif element in device > tree. > > +Cache operations are done automatically by videobuf2 driver. > > diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst > > b/Documentation/userspace-api/media/v4l/meta-formats.rst > > index c6e56b5888..23fa0ebe45 100644 > > --- a/Documentation/userspace-api/media/v4l/meta-formats.rst > > +++ b/Documentation/userspace-api/media/v4l/meta-formats.rst > > @@ -18,6 +18,7 @@ These formats are used for the :ref:`metadata` interface > only. > > metafmt-pisp-be > > metafmt-rkisp1 > > metafmt-uvc > > + metafmt-visconti-viif > > metafmt-vivid > > metafmt-vsp1-hgo > > metafmt-vsp1-hgt > > diff --git > > a/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > > b/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > > new file mode 100644 > > index 0000000000..dc4b31627f > > --- /dev/null > > +++ b/Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > > @@ -0,0 +1,48 @@ > > +.. SPDX-License-Identifier: GPL-2.0 > > + > > +.. _v4l2-meta-fmt-visconti-viif-params: > > + > > +.. _v4l2-meta-fmt-visconti-viif-stats: > > + > > +********************************************************************* > > +****************** V4L2_META_FMT_VISCONTI_VIIF_PARAMS ('vifp'), > > +V4L2_META_FMT_VISCONTI_VIIF_STATS ('vifs') > > +********************************************************************* > > +****************** > > + > > +Configuration parameters > > +======================== > > + > > +The configuration parameters are passed to the :ref:`viif_params > > +<viif_params>` metadata output video node, using the > > +:c:type:`v4l2_meta_format` interface. The buffer contains a single > > +instance of the C structure :c:type:`visconti_viif_isp_config` > > +defined in ``visconti_viif.h``. So the structure can be obtained from the > buffer by: > > + > > +.. code-block:: c > > + > > + struct visconti_viif_isp_config *params = (struct > > +visconti_viif_isp_config*) buffer; > > + > > +VIIF statistics > > +=============== > > + > > +The VIIF device collects different statistics over an input Bayer frame. > > +Those statistics are obtained from the :ref:`viif_stats <viif_stats>` > > +metadata capture video node, using the :c:type:`v4l2_meta_format` > > +interface. The buffer contains a single instance of the C structure > > +:c:type:`visconti_viif_isp_stat` defined in ``visconti_viif.h``. So > > +the structure can be obtained from the buffer by: > > + > > +.. code-block:: c > > + > > + struct visconti_viif_isp_stat *stats = (struct > > +visconti_viif_isp_stat*) buffer; > > + > > +The statistics collected are Exposure, AWB (auto white balance) and errors. > > +See :c:type:`visconti_viif_isp_stat` for details of the statistics. > > + > > +The statistics and configuration parameters described here are > > +usually consumed and produced by dedicated user space libraries that > > +comprise the tuning tools using software control loop. > > + > > +visconti viif uAPI data types > > +============================= > > + > > +.. kernel-doc:: include/uapi/linux/visconti_viif.h > > -- > Regards, > > Laurent Pinchart Regards, Yuji Ishikawa ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver 2024-08-01 9:23 ` yuji2.ishikawa @ 2024-08-01 16:06 ` Laurent Pinchart 2024-08-08 0:42 ` yuji2.ishikawa 0 siblings, 1 reply; 20+ messages in thread From: Laurent Pinchart @ 2024-08-01 16:06 UTC (permalink / raw) To: yuji2.ishikawa Cc: hverkuil, mchehab, robh, krzk+dt, conor+dt, broonie, sakari.ailus, nobuhiro1.iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hello Ishikawa-san, On Thu, Aug 01, 2024 at 09:23:43AM +0000, yuji2.ishikawa@toshiba.co.jp wrote: > On Tuesday, July 23, 2024 3:03 AM, Laurent Pinchart wrote: > > On Tue, Jul 09, 2024 at 09:08:47AM +0900, Yuji Ishikawa wrote: > > > Added description of Video Input Interface driver of Toshiba Visconti > > > architecture. > > > It includes hardware organization, structure of the driver and > > > metadata format for embedded image signal processor. > > > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > > --- > > > Changelog v3: > > > - Newly add documentation to describe SW and HW > > > > > > Changelog v4: > > > - no change > > > > > > Changelog v5: > > > - no change > > > > > > Changelog v6: > > > - add description of CSI2RX subdevice > > > - add ordering of ioctl(S_FMT) and ioctl(S_EXT_CTRLS) > > > > > > Changelog v7: > > > - no change > > > > > > Changelog v8: > > > - add usage of V4L2_CTRL_TYPE_VISCONTI_ISP > > > > > > Changelog v9: > > > - fix warning: set reference target for keyword > > > V4L2_CTRL_TYPE_VISCONTI_ISP > > > > > > Changelog v10: > > > - use parameter buffers instead of compound control > > > - removed description of vendor specific compound control > > > - add description of parameter buffers for ISP control > > > - update directory structure > > > - remove documents under driver-api > > > - add documents to admin-guide, userspace-api > > > > > > Changelog v11: > > > - update usage of the driver > > > > > > .../admin-guide/media/v4l-drivers.rst | 1 + > > > .../admin-guide/media/visconti-viif.dot | 18 ++ > > > .../admin-guide/media/visconti-viif.rst | 255 ++++++++++++++++++ > > > .../userspace-api/media/v4l/meta-formats.rst | 1 + > > > .../media/v4l/metafmt-visconti-viif.rst | 48 ++++ > > > 5 files changed, 323 insertions(+) > > > create mode 100644 Documentation/admin-guide/media/visconti-viif.dot > > > create mode 100644 Documentation/admin-guide/media/visconti-viif.rst > > > create mode 100644 Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst [snip] > > > diff --git a/Documentation/admin-guide/media/visconti-viif.rst b/Documentation/admin-guide/media/visconti-viif.rst > > > new file mode 100644 > > > index 0000000000..4ef676754c > > > --- /dev/null > > > +++ b/Documentation/admin-guide/media/visconti-viif.rst > > > @@ -0,0 +1,255 @@ [snip] > > > +viif_capture_sub - Raw Image Capture Video Node > > > +----------------------------------------------- > > > + > > > +This video node is used for capturing bayer image from the sensor. > > > +The output picture has exactly the same resolution and format as the sensor input. > > > +The following depth of bayer format is supported: > > > + > > > +- 8bit > > > +- 10bit > > > +- 12bit > > > +- 14bit > > > > Does the hardware support capturing embedded data from the sensor ? > > The hardware supports capturing embdded data, however the software is > not fully tested for that feature. OK. Support for this can be added later. I recommend already checking what it would imply in terms of changes to the media graph. Changing the media graph later in a way that could break userspace won't be allowed, so it's worth it preparing for embedded data support in the media graph design already. Adding new pads to existing entities and adding new entities later are fine, but renumbering existing pads or inserting new entities between two existing entities could break userspace. [snip] -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver 2024-08-01 16:06 ` Laurent Pinchart @ 2024-08-08 0:42 ` yuji2.ishikawa 0 siblings, 0 replies; 20+ messages in thread From: yuji2.ishikawa @ 2024-08-08 0:42 UTC (permalink / raw) To: laurent.pinchart Cc: hverkuil, mchehab, robh, krzk+dt, conor+dt, broonie, sakari.ailus, nobuhiro1.iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hello Laurent, > -----Original Message----- > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Sent: Friday, August 2, 2024 1:06 AM > To: ishikawa yuji(石川 悠司 ○RDC□AITC○EA開) > <yuji2.ishikawa@toshiba.co.jp> > Cc: hverkuil@xs4all.nl; mchehab@kernel.org; robh@kernel.org; > krzk+dt@kernel.org; conor+dt@kernel.org; broonie@kernel.org; > sakari.ailus@linux.intel.com; iwamatsu nobuhiro(岩松 信洋 ○DITC□DI > T○OST) <nobuhiro1.iwamatsu@toshiba.co.jp>; > linux-media@vger.kernel.org; devicetree@vger.kernel.org; > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v11 5/6] documentation: media: add documentation for > Toshiba Visconti Video Input Interface driver > > Hello Ishikawa-san, > > On Thu, Aug 01, 2024 at 09:23:43AM +0000, yuji2.ishikawa@toshiba.co.jp > wrote: > > On Tuesday, July 23, 2024 3:03 AM, Laurent Pinchart wrote: > > > On Tue, Jul 09, 2024 at 09:08:47AM +0900, Yuji Ishikawa wrote: > > > > Added description of Video Input Interface driver of Toshiba > > > > Visconti architecture. > > > > It includes hardware organization, structure of the driver and > > > > metadata format for embedded image signal processor. > > > > > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > > > --- > > > > Changelog v3: > > > > - Newly add documentation to describe SW and HW > > > > > > > > Changelog v4: > > > > - no change > > > > > > > > Changelog v5: > > > > - no change > > > > > > > > Changelog v6: > > > > - add description of CSI2RX subdevice > > > > - add ordering of ioctl(S_FMT) and ioctl(S_EXT_CTRLS) > > > > > > > > Changelog v7: > > > > - no change > > > > > > > > Changelog v8: > > > > - add usage of V4L2_CTRL_TYPE_VISCONTI_ISP > > > > > > > > Changelog v9: > > > > - fix warning: set reference target for keyword > > > > V4L2_CTRL_TYPE_VISCONTI_ISP > > > > > > > > Changelog v10: > > > > - use parameter buffers instead of compound control > > > > - removed description of vendor specific compound control > > > > - add description of parameter buffers for ISP control > > > > - update directory structure > > > > - remove documents under driver-api > > > > - add documents to admin-guide, userspace-api > > > > > > > > Changelog v11: > > > > - update usage of the driver > > > > > > > > .../admin-guide/media/v4l-drivers.rst | 1 + > > > > .../admin-guide/media/visconti-viif.dot | 18 ++ > > > > .../admin-guide/media/visconti-viif.rst | 255 > ++++++++++++++++++ > > > > .../userspace-api/media/v4l/meta-formats.rst | 1 + > > > > .../media/v4l/metafmt-visconti-viif.rst | 48 ++++ > > > > 5 files changed, 323 insertions(+) create mode 100644 > > > > Documentation/admin-guide/media/visconti-viif.dot > > > > create mode 100644 > > > > Documentation/admin-guide/media/visconti-viif.rst > > > > create mode 100644 > > > > Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > > [snip] > > > > > diff --git a/Documentation/admin-guide/media/visconti-viif.rst > > > > b/Documentation/admin-guide/media/visconti-viif.rst > > > > new file mode 100644 > > > > index 0000000000..4ef676754c > > > > --- /dev/null > > > > +++ b/Documentation/admin-guide/media/visconti-viif.rst > > > > @@ -0,0 +1,255 @@ > > [snip] > > > > > +viif_capture_sub - Raw Image Capture Video Node > > > > +----------------------------------------------- > > > > + > > > > +This video node is used for capturing bayer image from the sensor. > > > > +The output picture has exactly the same resolution and format as the > sensor input. > > > > +The following depth of bayer format is supported: > > > > + > > > > +- 8bit > > > > +- 10bit > > > > +- 12bit > > > > +- 14bit > > > > > > Does the hardware support capturing embedded data from the sensor ? > > > > The hardware supports capturing embdded data, however the software is > > not fully tested for that feature. > > OK. Support for this can be added later. I recommend already checking what it > would imply in terms of changes to the media graph. Changing the media graph > later in a way that could break userspace won't be allowed, so it's worth it > preparing for embedded data support in the media graph design already. > Adding new pads to existing entities and adding new entities later are fine, but > renumbering existing pads or inserting new entities between two existing > entities could break userspace. Thank you for the advice. I will be careful not to break the userspace in future releases. > > [snip] > > -- > Regards, > > Laurent Pinchart Regards, Yuji Ishikawa ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v11 6/6] MAINTAINERS: Add entries for Toshiba Visconti Video Input Interface 2024-07-09 0:08 [PATCH v11 0/6] Add Toshiba Visconti Video Input Interface driver Yuji Ishikawa ` (3 preceding siblings ...) 2024-07-09 0:08 ` [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver Yuji Ishikawa @ 2024-07-09 0:08 ` Yuji Ishikawa 2024-07-22 15:17 ` Laurent Pinchart [not found] ` <20240709000848.1108788-4-yuji2.ishikawa@toshiba.co.jp> 5 siblings, 1 reply; 20+ messages in thread From: Yuji Ishikawa @ 2024-07-09 0:08 UTC (permalink / raw) To: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, Yuji Ishikawa Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel Added entries for visconti Video Input Interface driver, including; * device tree bindings * source files * documentation files Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> Reviewed-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> --- Changelog v2: - no change Changelog v3: - added entry for driver API documentation Changelog v4: - added entry for header file Changelog v5: - no change Changelog v6: - update path to VIIF driver source files Changelog v7: - no change Changelog v8: - rename bindings description file Changelog v9: - no change Changelog v10: - add a separate entry of VIIF driver Changelog v11: - no change MAINTAINERS | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3c4fdf74a3..f051f4ab34 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22734,6 +22734,17 @@ F: Documentation/devicetree/bindings/media/i2c/tc358743.txt F: drivers/media/i2c/tc358743* F: include/media/i2c/tc358743.h +TOSHIBA VISCONTI VIIF DRIVER +M: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> +M: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> +L: linux-media@vger.kernel.org +S: Maintained +F: Documentation/admin-guide/media/visconti-viif.* +F: Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml +F: Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst +F: drivers/media/platform/toshiba/visconti/ +F: include/uapi/linux/visconti_viif.h + TOSHIBA WMI HOTKEYS DRIVER M: Azael Avalos <coproscefalo@gmail.com> L: platform-driver-x86@vger.kernel.org -- 2.25.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v11 6/6] MAINTAINERS: Add entries for Toshiba Visconti Video Input Interface 2024-07-09 0:08 ` [PATCH v11 6/6] MAINTAINERS: Add entries for Toshiba Visconti Video Input Interface Yuji Ishikawa @ 2024-07-22 15:17 ` Laurent Pinchart 0 siblings, 0 replies; 20+ messages in thread From: Laurent Pinchart @ 2024-07-22 15:17 UTC (permalink / raw) To: Yuji Ishikawa Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown, Sakari Ailus, Nobuhiro Iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hi Ishikawa-san, Thank you for the patch. On Tue, Jul 09, 2024 at 09:08:48AM +0900, Yuji Ishikawa wrote: > Added entries for visconti Video Input Interface driver, including; > * device tree bindings > * source files > * documentation files > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > Reviewed-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > Changelog v2: > - no change > > Changelog v3: > - added entry for driver API documentation > > Changelog v4: > - added entry for header file > > Changelog v5: > - no change > > Changelog v6: > - update path to VIIF driver source files > > Changelog v7: > - no change > > Changelog v8: > - rename bindings description file > > Changelog v9: > - no change > > Changelog v10: > - add a separate entry of VIIF driver > > Changelog v11: > - no change > > MAINTAINERS | 11 +++++++++++ > 1 file changed, 11 insertions(+) > > diff --git a/MAINTAINERS b/MAINTAINERS > index 3c4fdf74a3..f051f4ab34 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -22734,6 +22734,17 @@ F: Documentation/devicetree/bindings/media/i2c/tc358743.txt > F: drivers/media/i2c/tc358743* > F: include/media/i2c/tc358743.h > > +TOSHIBA VISCONTI VIIF DRIVER > +M: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> > +M: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > +L: linux-media@vger.kernel.org > +S: Maintained > +F: Documentation/admin-guide/media/visconti-viif.* > +F: Documentation/devicetree/bindings/media/toshiba,visconti5-viif.yaml > +F: Documentation/userspace-api/media/v4l/metafmt-visconti-viif.rst > +F: drivers/media/platform/toshiba/visconti/ > +F: include/uapi/linux/visconti_viif.h > + > TOSHIBA WMI HOTKEYS DRIVER > M: Azael Avalos <coproscefalo@gmail.com> > L: platform-driver-x86@vger.kernel.org -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <20240709000848.1108788-4-yuji2.ishikawa@toshiba.co.jp>]
* Re: [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti Video Input Interface driver [not found] ` <20240709000848.1108788-4-yuji2.ishikawa@toshiba.co.jp> @ 2024-07-09 7:47 ` Markus Elfring 2024-07-18 23:46 ` yuji2.ishikawa [not found] ` <20240722220815.GA9047@pendragon.ideasonboard.com> 1 sibling, 1 reply; 20+ messages in thread From: Markus Elfring @ 2024-07-09 7:47 UTC (permalink / raw) To: Yuji Ishikawa, linux-media, devicetree, linux-arm-kernel, Conor Dooley, Hans Verkuil, Krzysztof Kozlowski, Laurent Pinchart, Mark Brown, Mauro Carvalho Chehab, Nobuhiro Iwamatsu, Rob Herring, Sakari Ailus Cc: LKML … > +++ b/drivers/media/platform/toshiba/visconti/viif_capture.c > @@ -0,0 +1,1431 @@ … > +static int viif_set_img(struct cap_dev *cap_dev, struct vb2_buffer *vb) > +{ … > + if (cap_dev->pathid == CAPTURE_PATH_MAIN_POST0) { > + spin_lock(&viif_dev->regbuf_lock); > + hwd_viif_isp_guard_start(viif_dev); … > + hwd_viif_isp_guard_end(viif_dev); > + spin_unlock(&viif_dev->regbuf_lock); … Under which circumstances would you become interested to apply a statement like “guard(spinlock)(&viif_dev->regbuf_lock);”? https://elixir.bootlin.com/linux/v6.10-rc7/source/include/linux/spinlock.h#L561 Regards, Markus ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti Video Input Interface driver 2024-07-09 7:47 ` [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti Video Input Interface driver Markus Elfring @ 2024-07-18 23:46 ` yuji2.ishikawa 0 siblings, 0 replies; 20+ messages in thread From: yuji2.ishikawa @ 2024-07-18 23:46 UTC (permalink / raw) To: Markus.Elfring, linux-media, devicetree, linux-arm-kernel, conor+dt, hverkuil, krzk+dt, laurent.pinchart, broonie, mchehab, nobuhiro1.iwamatsu, robh, sakari.ailus Cc: linux-kernel Hello Markus, Thank you for your review. > -----Original Message----- > From: Markus Elfring <Markus.Elfring@web.de> > Sent: Tuesday, July 9, 2024 4:48 PM > To: ishikawa yuji(石川 悠司 ○RDC□AITC○EA開) > <yuji2.ishikawa@toshiba.co.jp>; linux-media@vger.kernel.org; > devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org; Conor > Dooley <conor+dt@kernel.org>; Hans Verkuil <hverkuil@xs4all.nl>; Krzysztof > Kozlowski <krzk+dt@kernel.org>; Laurent Pinchart > <laurent.pinchart@ideasonboard.com>; Mark Brown <broonie@kernel.org>; > Mauro Carvalho Chehab <mchehab@kernel.org>; iwamatsu nobuhiro(岩松 信 > 洋 ○DITC□DIT○OST) <nobuhiro1.iwamatsu@toshiba.co.jp>; Rob > Herring <robh@kernel.org>; Sakari Ailus <sakari.ailus@linux.intel.com> > Cc: LKML <linux-kernel@vger.kernel.org> > Subject: Re: [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti > Video Input Interface driver > > … > > +++ b/drivers/media/platform/toshiba/visconti/viif_capture.c > > @@ -0,0 +1,1431 @@ > … > > +static int viif_set_img(struct cap_dev *cap_dev, struct vb2_buffer > > +*vb) { > … > > + if (cap_dev->pathid == CAPTURE_PATH_MAIN_POST0) { > > + spin_lock(&viif_dev->regbuf_lock); > > + hwd_viif_isp_guard_start(viif_dev); > … > > + hwd_viif_isp_guard_end(viif_dev); > > + spin_unlock(&viif_dev->regbuf_lock); > … > > Under which circumstances would you become interested to apply a statement > like “guard(spinlock)(&viif_dev->regbuf_lock);”? > https://elixir.bootlin.com/linux/v6.10-rc7/source/include/linux/spinlock.h#L5 > 61 Thank you for the interesting advice encouraging me to use guard macros. I investigated the implementation of the DEFINE_LOCK_GUARD_1 macro and guard macro. Also, I checked a web article of __cleanup__ attribute and its applications [*1]. Now I understand that the use of guard macros can provide the same functionality as a combination of spin_lock() and spin_unlock concisely. I'll try use guard macros for the next patch. *1: https://javiercarrascocruz.github.io/kernel-auto-cleanup-1 > > Regards, > Markus Regards, Yuji ^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <20240722220815.GA9047@pendragon.ideasonboard.com>]
[parent not found: <OSZPR01MB9427EDDADF59D6061DDF1DD492B22@OSZPR01MB9427.jpnprd01.prod.outlook.com>]
* Re: [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti Video Input Interface driver [not found] ` <OSZPR01MB9427EDDADF59D6061DDF1DD492B22@OSZPR01MB9427.jpnprd01.prod.outlook.com> @ 2024-08-01 17:28 ` Laurent Pinchart 2024-08-08 0:48 ` yuji2.ishikawa 0 siblings, 1 reply; 20+ messages in thread From: Laurent Pinchart @ 2024-08-01 17:28 UTC (permalink / raw) To: yuji2.ishikawa Cc: hverkuil, mchehab, robh, krzk+dt, conor+dt, broonie, sakari.ailus, nobuhiro1.iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hi Ishikawa-san, Sakari, there's a question for you below. On Thu, Aug 01, 2024 at 09:27:14AM +0000, yuji2.ishikawa@toshiba.co.jp wrote: > On Tuesday, July 23, 2024 7:08 AM, Laurent Pinchart wrote: > > On Tue, Jul 09, 2024 at 09:08:45AM +0900, Yuji Ishikawa wrote: > > > Add support to Video Input Interface on Toshiba Visconti ARM SoCs. > > > The interface device includes CSI2 Receiver, > > > frame grabber, video DMAC and image signal processor. > > > > > > A driver instance provides three /dev/videoX device files; > > > one for RGB image capture, another one for optional RGB capture > > > with different parameters and the last one for RAW capture. > > > > > > Through the device files, the driver provides streaming interface. > > > Both DMABUF and MMAP operations are supported. > > > A userland application should feed phisically continuous > > > > s/phisically/physically/ > > s/continuous/contiguous/ (I often mistype them too) > > > > Maybe you could write "DMA-contiguous" as there's an IOMMU as far as I > > understand (even if it's not supported yet). > > I'll fix them. > > > > DMA-BUF instances as capture buffers. > > > > > > The driver is based on media controller framework. > > > Its operations are roughly mapped to three subdrivers; > > > CSI2 receiver subdevice, ISP subdevice and capture devices. > > > > > > The Video DMACs have 32bit address space > > > and currently corresponding IOMMU driver is not provided. > > > Therefore, memory-block address for captured image is 32bit IOVA > > > which is equal to 32bit-truncated phisical address. > > > When the Visconti IOMMU driver (currently under development) is accepted, > > > the hardware layer will use 32bit IOVA mapped by the attached IOMMU. > > > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > > --- > > > Changelog v2: > > > - Resend v1 because a patch exceeds size limit. > > > > > > Changelog v3: > > > - Adapted to media control framework > > > - Introduced ISP subdevice, capture device > > > - Remove private IOCTLs and add vendor specific V4L2 controls > > > - Change function name avoiding camelcase and uppercase letters > > > > > > Changelog v4: > > > - fix style problems at the v3 patch > > > - remove "index" member > > > - update example > > > - Split patches because the v3 patch exceeds size limit > > > - Stop using ID number to identify driver instance: > > > - Use dynamically allocated structure to hold driver's context, > > > instead of static one indexed by ID number. > > > - internal functions accept context structure instead of ID number. > > > - Use pm_runtime to trigger initialization of HW > > > along with open/close of device files. > > > > > > Changelog v5: > > > - Fix coding style problems in viif.c > > > > > > Changelog v6: > > > - update dependency description of Kconfig > > > - bugfix: usage of buffer pointed with dma_active > > > - remove unused macros > > > - add viif_common.c for commonly used register buffer control routine > > > - add initialization of Bus Controller (HWAIF) and Memory Protection Unit > > > - removed hwd_ and HWD_ prefix > > > - update source code documentation > > > - Suggestion from Hans Verkuil > > > - pointer to userland memory is removed from uAPI arguments > > > - style of structure is now "nested" instead of "chained by pointer"; > > > - use div64_u64 for 64bit division > > > - define Visconti specific control IDs in v4l2-controls.h > > > - set proper initial size to v4l2_ctrl_handler_init() > > > - set all buffers to QUEUED state on an error at start_streaming > > > - use vb2_is_busy() instead of vb2_is_streaming() > > > - add parameter check for s->type and s->target in get_selection() > > > - remove ioctls related to DV format and EDID > > > - release v4l2 fh instance on and error at opening device file > > > - support VB2_MMAP mode for streaming operation > > > - add initial value to each vendor specific control > > > - GET_LAST_CAPTURE_STATUS control is updated asyncnously from workqueue > > > - applied v4l2-compliance > > > - Suggestion from Sakari Ailus > > > - use div64_u64 for 64bit division > > > - update copyright's year > > > - use common definition of MIPI CSI2 DataTypes > > > - remove redandunt cast > > > - use bool instead of HWD_VIIF_ENABLE/DISABLE > > > - simplify comparison to 0 > > > - simplify statements with trigram operator > > > - remove redundant local variables > > > - simplify timeout loop > > > - use general integer types instead of u32/s32 > > > - Suggestion from Laurent Pinchart > > > - moved VIIF driver to driver/platform/toshiba/visconti > > > - add CSI2RX subdevice > > > - change register access: struct-style to macro-style > > > - use common definition of MIPI CSI2 DataTypes > > > - Kconfig: add SPDX header, add V4L2_ASYNC > > > - remove unused type definitions > > > - define enums instead of successive macro constants > > > - remove redundant parenthesis of macro constant > > > - embed struct hwd_res into struct viif_device > > > - turn switch-case into table lookup > > > - use xxx_dma instead of xxx_paddr for variable names of IOVA > > > - literal value: just 0 instead of 0x0 > > > - use literal 1 or 0 instead of HWD_VIIF_ENABLE, DISABLE for register access > > > - use true or false instead of HWD_VIIF_ENABLE, DISABLE for function calls > > > - remove ioctl request handlers which refers subdevices > > > > > > Changelog v7: > > > - change compatible string to visconti5-viif > > > - remove unused variables > > > - set static to internal functions > > > - Suggestion from kernel test robot <lkp@intel.com> > > > - update references to headers > > > > > > Changelog v8: > > > - bugfix: handling return value of visconti_viiif_parse_dt() > > > - add visconti_viif_subdev_notifier_register() to gather > > > all operations around v4l2_async_notifier > > > - update for v6.6-rc2 > > > - use v4l2_async_connection instead of v4l2_async_subdev > > > - aid for devices using subdev active state > > > - add __maybe_unused for runtime_pm callbacks > > > - Suggestion from Krzysztof Kozlowski > > > - use static initialization of local variable > > > - use dev_err_probe() > > > - remove error message for DMA memory allocation failure > > > - remove unused comment messages > > > - add error handling at fail of workqueue_create() > > > - remove redundant mutex for pm_runtime callback routines > > > - Suggestion from Hans Verkuil > > > - remove pr_info() calls > > > - build check with media_stage.git > > > - some lacks for kerneldoc description > > > > > > Changelog v9: > > > - applied sparse checker > > > - add static qualifier to a file scoped local variable > > > - expand functions for acquiring/releasing locks > > > - bugfix: use NULL (instead of 0) for pad::get_fmt subdevice API > > > - fix warnings for cast between ptr and dma_addr_t > > > - call div64_u64 for 64bit division > > > - rebase to media_staging tree; update Visconti specific control IDs > > > > > > Changelog v10: > > > - remove vendor specific compound controls > > > - remove "rawpack mode" flag > > > - RAW16, RAW18, RAW20 (to be implemented and tested) should be used instead > > > - catch up to v6.9-rc4 > > > > > > Changelog v11: > > > - stop merging sensor's controls to capture device's > > > - remove redundant parameter checkings > > > - update routines handling crop/compose rects of the ISP subdevice > > > - update kerneldoc comments > > > - update copyright year > > > > > > drivers/media/platform/Kconfig | 1 + > > > drivers/media/platform/Makefile | 1 + > > > drivers/media/platform/toshiba/Kconfig | 6 + > > > drivers/media/platform/toshiba/Makefile | 2 + > > > .../media/platform/toshiba/visconti/Kconfig | 19 + > > > .../media/platform/toshiba/visconti/Makefile | 8 + > > > .../media/platform/toshiba/visconti/viif.c | 627 ++++++ > > > .../media/platform/toshiba/visconti/viif.h | 393 ++++ > > > .../platform/toshiba/visconti/viif_capture.c | 1431 ++++++++++++ > > > .../platform/toshiba/visconti/viif_capture.h | 21 + > > > .../platform/toshiba/visconti/viif_common.c | 239 ++ > > > .../platform/toshiba/visconti/viif_common.h | 42 + > > > .../platform/toshiba/visconti/viif_csi2rx.c | 657 ++++++ > > > .../platform/toshiba/visconti/viif_csi2rx.h | 24 + > > > .../toshiba/visconti/viif_csi2rx_regs.h | 102 + > > > .../platform/toshiba/visconti/viif_isp.c | 1183 ++++++++++ > > > .../platform/toshiba/visconti/viif_isp.h | 24 + > > > .../platform/toshiba/visconti/viif_regs.h | 721 +++++++ > > > include/uapi/linux/visconti_viif.h | 1921 +++++++++++++++++ > > > 19 files changed, 7422 insertions(+) > > > create mode 100644 drivers/media/platform/toshiba/Kconfig > > > create mode 100644 drivers/media/platform/toshiba/Makefile > > > create mode 100644 drivers/media/platform/toshiba/visconti/Kconfig > > > create mode 100644 drivers/media/platform/toshiba/visconti/Makefile > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif.c > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif.h > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_capture.c > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_capture.h > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_common.c > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_common.h > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_csi2rx.c > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_csi2rx.h > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_isp.c > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_isp.h > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif_regs.h > > > create mode 100644 include/uapi/linux/visconti_viif.h [snip] > > > diff --git a/drivers/media/platform/toshiba/visconti/viif.c b/drivers/media/platform/toshiba/visconti/viif.c > > > new file mode 100644 > > > index 0000000000..472b292752 > > > --- /dev/null > > > +++ b/drivers/media/platform/toshiba/visconti/viif.c > > > @@ -0,0 +1,627 @@ [snip] > > > diff --git a/drivers/media/platform/toshiba/visconti/viif.h > > b/drivers/media/platform/toshiba/visconti/viif.h > > > new file mode 100644 > > > index 0000000000..72b35bd605 > > > --- /dev/null > > > +++ b/drivers/media/platform/toshiba/visconti/viif.h > > > @@ -0,0 +1,393 @@ [snip] > > > +#define VIIF_HW_AVAILABLE_IRQS 4 > > > + > > > +#define VIIF_SYS_CLK 500000UL > > > > Is that always a fixed frequency, or should it be retrieved dynamically > > at runtime from the clock ? > > The system clock for VIIF is fixed to 500MHz. > > We are also trying to expand Visconti's clock driver to support VIIF. > The value can be retrived from API in future. OK. If the clock driver doesn't expose a VIIF clock yet, then using this macro is fine. A comment above the line to indicate the frequency should be retrieved dynamically from the clock would be useful. If the clock driver has a VIIF clock that is not configurable yet but is hardcoded to 500MHz, then you can already use clk_get_rate() to get the frequency, and remove the macro. [snip] > > > diff --git a/drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h b/drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h > > > new file mode 100644 > > > index 0000000000..97e2017fec > > > --- /dev/null > > > +++ b/drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h > > > @@ -0,0 +1,102 @@ > > > +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ > > > +/* Toshiba Visconti Video Capture register definitions > > > + * > > > + * (C) Copyright 2024 TOSHIBA CORPORATION > > > + * (C) Copyright 2024 Toshiba Electronic Devices & Storage Corporation > > > + */ > > > + > > > +#ifndef VIIF_CSI2RX_REGS_H > > > +#define VIIF_CSI2RX_REGS_H > > > + > > > +/*=============================================*/ > > > +/* CSI2HOST registers */ > > > +/*=============================================*/ > > > +#define REG_CSI2RX_NLANES 0x4 > > > +#define REG_CSI2RX_PHY_SHUTDOWNZ 0x40 > > > +#define REG_CSI2RX_PHY_RSTZ 0x44 > > > + > > > +/* access to dphy external registers */ > > > +#define REG_CSI2RX_PHY_TESTCTRL0 0x50 > > > +#define BIT_TESTCTRL0_CLK_0 0 > > > +#define BIT_TESTCTRL0_CLK_1 BIT(1) > > > > Quoting drivers/media/platform/renesas/rcar-csi2.c, > > > > #define V4H_N_LANES_REG 0x0004 > > #define V4H_CSI2_RESETN_REG 0x0008 > > #define V4H_PHY_MODE_REG 0x001c > > #define V4H_PHY_SHUTDOWNZ_REG 0x0040 > > #define V4H_DPHY_RSTZ_REG 0x0044 > > ... > > #define PHTW_REG 0x50 > > > > Where does your CSI-2 receiver come from, is it a Synopsys IP ? One day > > we should really try to consolidate all that into a single driver. To > > make it easier, I think support for the CSI-2 RX should already be split > > out of this driver to a standalone subdev driver, with separate DT > > bindings. > > Yes, CSI2RX is Synopsys IP (host controller + D-Phy). > I'll try to separate the CSI2RX driver into standalone subdev driver, > using the structure of the rcar-csi2 driver as a reference. Thank you. [snip] > > > diff --git a/drivers/media/platform/toshiba/visconti/viif_isp.c b/drivers/media/platform/toshiba/visconti/viif_isp.c > > > new file mode 100644 > > > index 0000000000..7a66aac715 > > > --- /dev/null > > > +++ b/drivers/media/platform/toshiba/visconti/viif_isp.c > > > @@ -0,0 +1,1183 @@ [snip] > > > +static void visconti_viif_isp_set_sink_fmt(struct v4l2_subdev_state *sd_state, > > > + struct v4l2_mbus_framefmt *format) > > > +{ > > > + struct v4l2_mbus_framefmt *sink_fmt, *src0_fmt, *src1_fmt, *src2_fmt; > > > + > > > + sink_fmt = v4l2_subdev_state_get_format(sd_state, VIIF_ISP_PAD_SINK_VIDEO); > > > + src0_fmt = v4l2_subdev_state_get_format(sd_state, VIIF_ISP_PAD_SRC_PATH0); > > > + src1_fmt = v4l2_subdev_state_get_format(sd_state, VIIF_ISP_PAD_SRC_PATH1); > > > + src2_fmt = v4l2_subdev_state_get_format(sd_state, VIIF_ISP_PAD_SRC_PATH2); > > > + > > > + /* update mbus code only if it's available */ > > > + if (viif_is_valid_mbus_code(format->code)) > > > + sink_fmt->code = format->code; > > > > If format->code is not valid, it would be better to set sink_fmt->code > > to a default format instead of keeping the current value. It will result > > in a more predictable behaviour for userspace, making it easier to debug > > issues. > > I understand. I'll fix it. > > > > + > > > + /* sink::mbus_code is derived from src::mbus_code */ > > > > Here you seem to do it the other way around, setting the source format > > based on the sink format. > > I have no idea what to set in the source format here. > Should I use the default format even if it is not compatible to the source format? The base rule is that subdev drivers must propagate formats from sink (input of the subdev) to source (output of the subdev). This function is called when userspace sets the format on the sink pad. It needs to update the source pad format accordingly, which you do below. What I think is not correct (if I understand it right) is the comment above. You set the source format based on the sink format, so I think the comment should read /* src::mbus_code is derived from sink::mbus_code */ > > > + if (viif_get_mbus_rgb_out(sink_fmt->code)) { > > > + src0_fmt->code = MEDIA_BUS_FMT_RGB888_1X24; > > > + src1_fmt->code = MEDIA_BUS_FMT_RGB888_1X24; > > > + } else { > > > + src0_fmt->code = MEDIA_BUS_FMT_YUV8_1X24; > > > + src1_fmt->code = MEDIA_BUS_FMT_YUV8_1X24; > > > + } > > > + > > > + /* SRC2 (RAW output) follows SINK format */ > > > + src2_fmt->code = format->code; > > > + src2_fmt->width = format->width; > > > + src2_fmt->height = format->height; > > > > You need to adjust the width and height based on the hardware limits. > > > > Can src0 and src1 generate any size, or are they restricted by the sink > > size ? I would recomend propagating the sink size to all sources here. > > You should also adjust selection rectangles. > > I need to understand what should/can be propagated from sink to source, and what should not. > I have read "4.13 Sub-device Interface" but I'm still not clear. The order of the configuration parameters in a subdev is as follows: - sink format (mbus code, size, colorspace) - sink crop (rectangle) - sink compose (rectangle) - source crop (rectangle) - source format (mbus code, size, colorspace) Starting with the easy ones. To propagate the media bus code from sink to source, you need to set a media bus code on the source pads that is compatible with the media bus code on the sink pad. What that is depends on your hardware constraints. For instance, if the ISP can produce multiple RGB and YUV formats from a raw bayer format, then pick a default RGB or YUV format for the source pads.. For the colorspace information (the colorspace, ycbcr_enc, quantization and xfer_func fields), the situation is slightly more complicated, but I think it can be simplified. The ISP input can be in any color space, and the ISP can also output different color spaces. In theory, that could be controlled by the color space fields on the source pads, setting them to specific values would configure the ISP parameters accordingly (RGB2RGB matrix, RGB2YUV matrix, ...). However, this would create complexity in the driver, and would make the ISP less flexible as userspace wouldn't be able to have precise control of all the corresponding ISP parameters. For that reason, I think it's better to control all the ISP paramaters through the ISP parameters buffer, and ignore the color space fields in the sink and source pad formats. The quantization range may be an exception, you may want to control quantization using the pad format, up to you. As an example, here's how we handle colorspace propagation in the rkisp1 driver: /* * Copy the color space for the sink pad. When converting from Bayer to * YUV, default to a limited quantization range. */ src_fmt->colorspace = sink_fmt->colorspace; src_fmt->xfer_func = sink_fmt->xfer_func; src_fmt->ycbcr_enc = sink_fmt->ycbcr_enc; if (sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER && src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE; else src_fmt->quantization = sink_fmt->quantization; /* * Allow setting the source color space fields when the SET_CSC flag is * set and the source format is YUV. If the sink format is YUV, don't * set the color primaries, transfer function or YCbCr encoding as the * ISP is bypassed in that case and passes YUV data through without * modifications. * * The color primaries and transfer function are configured through the * cross-talk matrix and tone curve respectively. Settings for those * hardware blocks are conveyed through the ISP parameters buffer, as * they need to combine color space information with other image tuning * characteristics and can't thus be computed by the kernel based on the * color space. The source pad colorspace and xfer_func fields are thus * ignored by the driver, but can be set by userspace to propagate * accurate color space information down the pipeline. */ set_csc = format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC; if (set_csc && src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) { if (sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) { if (format->colorspace != V4L2_COLORSPACE_DEFAULT) src_fmt->colorspace = format->colorspace; if (format->xfer_func != V4L2_XFER_FUNC_DEFAULT) src_fmt->xfer_func = format->xfer_func; if (format->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT) src_fmt->ycbcr_enc = format->ycbcr_enc; } if (format->quantization != V4L2_QUANTIZATION_DEFAULT) src_fmt->quantization = format->quantization; } The colorspace-related fields on the source pad can be set to make userspace code simpler. By setting the colorspace on the ISP source pad to the value corresponding to the ISP parameters it sets, userspace will make sure the correct colorspace value is propagated along the pipeline to the capture device at the end. This will help writing more generic code in userspace that can take the colorspace from the capture device and use it on the consumer of the video stream (e.g. a video codec or a display device), to avoid colorspace mismatches. Now we have the sizes and rectangles to propagate: - sink format size - sink crop rectangle - sink compose rectangle - source crop rectangle - source format size, colorspace When userspace sets the sink format size, this should be propagated to the sink crop by setting the sink crop to the full sink format size. The sink compose rectangle should be reset to a 1:1 scaling ratio. The source crop rectangle should be reset to the same size (no additional cropping), and the source format size should be set to the same size too. Sakari, could you confirm this is correct ? > The sizes of src0 and src1 are not restricted by the sink size. > Src0 and src1 are processed by L2-ISP (undistortion, resize, crop). Does that mean that the resizer can both downscale and upscale ? Are there limits to the scaling factors ? > L2-ISP's operation is represented with sink.compose, src0.crop and src1.crop. > > In order to correctly map the subdevice nodes to the HW functions and ensure consistency with the pad operations, > the internal driver structure should be modified as shown below. > However due to the increased complexity of operating the L2ISP and risks of unverified HW operation patterns, I have not yet tried this. > > [HW] > sensor --- CSI2RX --- glue --- L1ISP --- L2ISP --- DMAC > > [subdevice] > Param_dev --- --- Stat_dev > Sensor --- CSI2RX --- MUX --- L1ISP --- Resizer0 --- Capture0_dev > --- Resizer1 --- Capture1_dev > -------------------------- Capture2_dev > > > > + > > > + /* size check */ > > > + sink_fmt->width = format->width; > > > + sink_fmt->height = format->height; > > > + > > > + *format = *sink_fmt; > > > +} [snip] > > > diff --git a/include/uapi/linux/visconti_viif.h b/include/uapi/linux/visconti_viif.h > > > new file mode 100644 > > > index 0000000000..3ff9bfc913 > > > --- /dev/null > > > +++ b/include/uapi/linux/visconti_viif.h > > > @@ -0,0 +1,1921 @@ [snip] > > > +/** > > > + * struct viif_l1_ag_mode_config - L1ISP parameter for analog gain > > > + * > > > + * @sysm_ag_grad: Analog gain slope. Range: [0..255], Index corresponds to psel id. > > > + * @sysm_ag_ofst: Analog gain offset. Range: [0..65535], Index corresponds to psel id. > > > + * @sysm_ag_cont_hobc_en_high: set 1 to enable control analog gain > > > + * for high sensitivity image of OBCC > > > + * @sysm_ag_psel_hobc_high: Analog gain id for high sensitivity image of OBCC. Range: [0..3] > > > + * @sysm_ag_cont_hobc_en_middle_led: set 1 to enable control analog gain > > > + * for middle sensitivity or LED image of OBCC > > > + * @sysm_ag_psel_hobc_middle_led: Analog gain id for middle sensitivity > > > + * or LED image of OBCC. Range: [0..3] > > > + * @sysm_ag_cont_hobc_en_low: set 1 to enable control analog gain > > > + * for low sensitivity image of OBCC > > > + * @sysm_ag_psel_hobc_low: Analog gain id for low sensitivity image of OBCC. Range:[0..3] > > > + * @sysm_ag_cont_abpc_en_high: set 1 to enable control analog gain > > > + * for high sensitivity image of ABPC > > > + * @sysm_ag_psel_abpc_high: Analog gain id for high sensitivity image of ABPC. Range: [0..3] > > > + * @sysm_ag_cont_abpc_en_middle_led: set 1 to enable control analog gain > > > + * for middle sensitivity or LED image of ABPC > > > + * @sysm_ag_psel_abpc_middle_led: Analog gain id for middle sensitivity > > > + * or LED image of ABPC. Range: [0..3] > > > + * @sysm_ag_cont_abpc_en_low: set 1 to enable control analog gain > > > + * for low sensitivity image of ABPC > > > + * @sysm_ag_psel_abpc_low: Analog gain id for low sensitivity image of ABPC. Range: [0..3] > > > + * @sysm_ag_cont_rcnr_en_high: set 1 to enable control analog gain > > > + * for high sensitivity image of RCNR > > > + * @sysm_ag_psel_rcnr_high: Analog gain id for high sensitivity image of RCNR. Range: [0..3] > > > + * @sysm_ag_cont_rcnr_en_middle_led: set 1 to enable control analog gain > > > + * for middle sensitivity or LED image of RCNR > > > + * @sysm_ag_psel_rcnr_middle_led: Analog gain id for middle sensitivity > > > + * or LED image of RCNR. Range: [0..3] > > > + * @sysm_ag_cont_rcnr_en_low: set 1 to enable control analog gain > > > + * for low sensitivity image of RCNR > > > + * @sysm_ag_psel_rcnr_low: Analog gain id for low sensitivity image of RCNR. Range: [0..3] > > > + * @sysm_ag_cont_lssc_en: set 1 to enable control analog gain for LSC > > > + * @sysm_ag_ssel_lssc: &enum viif_l1_img_sensitivity_mode value. Sensitive image used for LSC. > > > + * @sysm_ag_psel_lssc: Analog gain id for LSC. Range: [0..3] > > > + * @sysm_ag_cont_mpro_en: set 1 to enable control analog gain for color matrix > > > + * @sysm_ag_ssel_mpro: &enum viif_l1_img_sensitivity_mode value. > > > + * Sensitive image used for color matrix. > > > + * @sysm_ag_psel_mpro: Analog gain id for color matrix. Range: [0..3] > > > + * @sysm_ag_cont_vpro_en: set 1 to enable control analog gain for image adjustment > > > + * @sysm_ag_ssel_vpro: &enum viif_l1_img_sensitivity_mode value. > > > + * Sensitive image used for image adjustment. > > > + * @sysm_ag_psel_vpro: Analog gain id for image adjustment. Range: [0..3] > > > + * @sysm_ag_cont_hobc_test_high: Manual analog gain for high sensitivity image > > > + * of OBCC. Range: [0..255] > > > + * @sysm_ag_cont_hobc_test_middle_led: Manual analog gain for middle sensitivity > > > + * or led image of OBCC. Range: [0..255] > > > + * @sysm_ag_cont_hobc_test_low: Manual analog gain for low sensitivity image > > > + * of OBCC. Range: [0..255] > > > + * @sysm_ag_cont_abpc_test_high: Manual analog gain for high sensitivity image > > > + * of ABPC. Range: [0..255] > > > + * @sysm_ag_cont_abpc_test_middle_led: Manual analog gain for middle sensitivity > > > + * or led image of ABPC. Range: [0..255] > > > + * @sysm_ag_cont_abpc_test_low: Manual analog gain for low sensitivity image > > > + * of ABPC. Range: [0..255] > > > + * @sysm_ag_cont_rcnr_test_high: Manual analog gain for high sensitivity image > > > + * of RCNR. Range: [0..255] > > > + * @sysm_ag_cont_rcnr_test_middle_led: Manual analog gain for middle sensitivity > > > + * or led image of RCNR. Range: [0..255] > > > + * @sysm_ag_cont_rcnr_test_low: Manual analog gain for low sensitivity image > > > + * of RCNR. Range: [0..255] > > > + * @sysm_ag_cont_lssc_test: Manual analog gain for LSSC. Range: [0..255] > > > + * @sysm_ag_cont_mpro_test: Manual analog gain for color matrix. Range: [0..255] > > > + * @sysm_ag_cont_vpro_test: Manual analog gain for image adjustment. Range: [0..255] > > > + * > > > + * This parameter sets rules of generating analog gains for each feature in L1ISP. > > > > Does the ISP compute the analog gains for the sensor ? That's the first > > time I see such a ISP feature. If that's not the case, maybe I'm not > > understanding the documentation correctly. > > > > Overall, there are lots of ISP parameters here. They all have a short > > description, and ranges and formats for fixed-point integers are > > documented, which is very nice. However, reading the documentation in > > this file doesn't provide me with enough information to use most of the > > ISP parameters. There are three main options to address this: > > > > - Expanding the documentation in this header file to clearly explain how > > each ISP parameter operates and how to use them. > > > > - Providing an open userspace implementation of ISP algorithms that > > showcase how to calculate the values for the parameters. > > > > - Providing detailed hardware documentation for the ISP. This is usually > > not favoured by ISP vendors, and the V4L2 community is not pushing for > > this, but I wanted to mention it for completeness. > > > > If you would prefer the second option, any open-source camera framework > > would be acceptable, but in practice the only real option is likely > > libcamera. > > > > This does not mean that you have to open-source all your ISP control > > algorithms. Only the code needed to explain how ISP parameters are > > applied to the image and are computed is needed. Other parts, such as > > for instance AI-based computation of white balance gains, or complex AGC > > calculations, don't need to be open-source. > > > > The explain this requirement different and perhaps more clearly, the > > goal is to make sure that developers who have access to only open-source > > material (ISP kernel driver, this header, any open-source userspace > > code, public documentation, ...) will have enough information to > > configure and control the ISP. > > I read the HW manual again and found the term "analog gain" is not related to the sensor nor individual pixel values. > It is a kind of "strength" parameter commonly used in image processing algorithms. > I think I need to correct the confusing words and inconsistencies in the documents, comments and source code. That would be nice :-) > We have an offline tool for generating ISP settings, but the parameters are too many and specialized. > I think it is attractive idea to prepare a simple userland for libcamera in the future. That is what I recommend, as I think it's the simplest solution. We can help if needed. > > > + * Related features are: > > > + * > > > + * - Optical Black Clamp Correction (OBCC) > > > + * - Defect Pixel Correction (DPC) > > > + * - RAW Color Noise Reduction (RCNR) > > > + * - Lens Shading Correction (LSC) > > > + * - Color matrix correction (MPRO) > > > + * - Image quality adjustment (VPRO) > > > + * > > > + * The base gain is set with &struct viif_l1_ag_config. > > > + * > > > + * If sysm_ag_cont_xxxx_en = 1, analog_gain for each module is generated from > > > + * sysm_ag_grad, sysm_ag_ofst and the value specified with &struct viif_l1_ag_config. > > > + * If sysm_ag_cont_xxxx_en = 0, > > > + * the value of sysm_ag_cont_xxxx_test is used for analog_gain for each module. > > > + * > > > + * Up to 4 sets of parameters (sysm_ag_grad[4] and sysm_ag_ofst[4]) can be used > > > + * to generate analog gain. > > > + * The parameter sysm_ag_psel_xxxx specifies the set to be used for module xxxx. > > > + * For example, if sysm_ag_psel_hobc_high is set to 2, > > > + * values in sysm_ag_grad[2] and sysm_ag_ofst[2] are used > > > + * to generate analog gain for high sensitivity images in OBCC processing. > > > + * > > > + * Analog gain generation for each L1ISP module is disabled when > > > + * "sysm_ag_cont_xxxx_en=0" and "sysm_ag_cont_xxxx_test=0". > > > + * Be sure to disable the analog gain generation > > > + * if VIIF_L1_INPUT_HDR or VIIF_L1_INPUT_PWL is set to > > > + * &struct viif_l1_input_mode_config > > > + * > > > + */ > > > +struct viif_l1_ag_mode_config { > > > + __u8 sysm_ag_grad[4]; > > > + __u16 sysm_ag_ofst[4]; > > > + __u32 sysm_ag_cont_hobc_en_high; > > > + __u32 sysm_ag_psel_hobc_high; > > > + __u32 sysm_ag_cont_hobc_en_middle_led; > > > + __u32 sysm_ag_psel_hobc_middle_led; > > > + __u32 sysm_ag_cont_hobc_en_low; > > > + __u32 sysm_ag_psel_hobc_low; > > > + __u32 sysm_ag_cont_abpc_en_high; > > > + __u32 sysm_ag_psel_abpc_high; > > > + __u32 sysm_ag_cont_abpc_en_middle_led; > > > + __u32 sysm_ag_psel_abpc_middle_led; > > > + __u32 sysm_ag_cont_abpc_en_low; > > > + __u32 sysm_ag_psel_abpc_low; > > > + __u32 sysm_ag_cont_rcnr_en_high; > > > + __u32 sysm_ag_psel_rcnr_high; > > > + __u32 sysm_ag_cont_rcnr_en_middle_led; > > > + __u32 sysm_ag_psel_rcnr_middle_led; > > > + __u32 sysm_ag_cont_rcnr_en_low; > > > + __u32 sysm_ag_psel_rcnr_low; > > > + __u32 sysm_ag_cont_lssc_en; > > > + __u32 sysm_ag_ssel_lssc; > > > + __u32 sysm_ag_psel_lssc; > > > + __u32 sysm_ag_cont_mpro_en; > > > + __u32 sysm_ag_ssel_mpro; > > > + __u32 sysm_ag_psel_mpro; > > > + __u32 sysm_ag_cont_vpro_en; > > > + __u32 sysm_ag_ssel_vpro; > > > + __u32 sysm_ag_psel_vpro; > > > + __u8 sysm_ag_cont_hobc_test_high; > > > + __u8 sysm_ag_cont_hobc_test_middle_led; > > > + __u8 sysm_ag_cont_hobc_test_low; > > > + __u8 sysm_ag_cont_abpc_test_high; > > > + __u8 sysm_ag_cont_abpc_test_middle_led; > > > + __u8 sysm_ag_cont_abpc_test_low; > > > + __u8 sysm_ag_cont_rcnr_test_high; > > > + __u8 sysm_ag_cont_rcnr_test_middle_led; > > > + __u8 sysm_ag_cont_rcnr_test_low; > > > + __u8 sysm_ag_cont_lssc_test; > > > + __u8 sysm_ag_cont_mpro_test; > > > + __u8 sysm_ag_cont_vpro_test; > > > +}; [snip] -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti Video Input Interface driver 2024-08-01 17:28 ` Laurent Pinchart @ 2024-08-08 0:48 ` yuji2.ishikawa 0 siblings, 0 replies; 20+ messages in thread From: yuji2.ishikawa @ 2024-08-08 0:48 UTC (permalink / raw) To: laurent.pinchart Cc: hverkuil, mchehab, robh, krzk+dt, conor+dt, broonie, sakari.ailus, nobuhiro1.iwamatsu, linux-media, devicetree, linux-arm-kernel, linux-kernel Hello Laurent, > -----Original Message----- > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Sent: Friday, August 2, 2024 2:28 AM > To: ishikawa yuji(石川 悠司 ○RDC□AITC○EA開) > <yuji2.ishikawa@toshiba.co.jp> > Cc: hverkuil@xs4all.nl; mchehab@kernel.org; robh@kernel.org; > krzk+dt@kernel.org; conor+dt@kernel.org; broonie@kernel.org; > sakari.ailus@linux.intel.com; iwamatsu nobuhiro(岩松 信洋 ○DITC□DI > T○OST) <nobuhiro1.iwamatsu@toshiba.co.jp>; > linux-media@vger.kernel.org; devicetree@vger.kernel.org; > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti > Video Input Interface driver > > Hi Ishikawa-san, > > Sakari, there's a question for you below. > > On Thu, Aug 01, 2024 at 09:27:14AM +0000, yuji2.ishikawa@toshiba.co.jp > wrote: > > On Tuesday, July 23, 2024 7:08 AM, Laurent Pinchart wrote: > > > On Tue, Jul 09, 2024 at 09:08:45AM +0900, Yuji Ishikawa wrote: > > > > Add support to Video Input Interface on Toshiba Visconti ARM SoCs. > > > > The interface device includes CSI2 Receiver, frame grabber, video > > > > DMAC and image signal processor. > > > > > > > > A driver instance provides three /dev/videoX device files; one for > > > > RGB image capture, another one for optional RGB capture with > > > > different parameters and the last one for RAW capture. > > > > > > > > Through the device files, the driver provides streaming interface. > > > > Both DMABUF and MMAP operations are supported. > > > > A userland application should feed phisically continuous > > > > > > s/phisically/physically/ > > > s/continuous/contiguous/ (I often mistype them too) > > > > > > Maybe you could write "DMA-contiguous" as there's an IOMMU as far as > > > I understand (even if it's not supported yet). > > > > I'll fix them. > > > > > > DMA-BUF instances as capture buffers. > > > > > > > > The driver is based on media controller framework. > > > > Its operations are roughly mapped to three subdrivers; > > > > CSI2 receiver subdevice, ISP subdevice and capture devices. > > > > > > > > The Video DMACs have 32bit address space and currently > > > > corresponding IOMMU driver is not provided. > > > > Therefore, memory-block address for captured image is 32bit IOVA > > > > which is equal to 32bit-truncated phisical address. > > > > When the Visconti IOMMU driver (currently under development) is > > > > accepted, the hardware layer will use 32bit IOVA mapped by the attached > IOMMU. > > > > > > > > Signed-off-by: Yuji Ishikawa <yuji2.ishikawa@toshiba.co.jp> > > > > --- > > > > Changelog v2: > > > > - Resend v1 because a patch exceeds size limit. > > > > > > > > Changelog v3: > > > > - Adapted to media control framework > > > > - Introduced ISP subdevice, capture device > > > > - Remove private IOCTLs and add vendor specific V4L2 controls > > > > - Change function name avoiding camelcase and uppercase letters > > > > > > > > Changelog v4: > > > > - fix style problems at the v3 patch > > > > - remove "index" member > > > > - update example > > > > - Split patches because the v3 patch exceeds size limit > > > > - Stop using ID number to identify driver instance: > > > > - Use dynamically allocated structure to hold driver's context, > > > > instead of static one indexed by ID number. > > > > - internal functions accept context structure instead of ID number. > > > > - Use pm_runtime to trigger initialization of HW > > > > along with open/close of device files. > > > > > > > > Changelog v5: > > > > - Fix coding style problems in viif.c > > > > > > > > Changelog v6: > > > > - update dependency description of Kconfig > > > > - bugfix: usage of buffer pointed with dma_active > > > > - remove unused macros > > > > - add viif_common.c for commonly used register buffer control > > > > routine > > > > - add initialization of Bus Controller (HWAIF) and Memory > > > > Protection Unit > > > > - removed hwd_ and HWD_ prefix > > > > - update source code documentation > > > > - Suggestion from Hans Verkuil > > > > - pointer to userland memory is removed from uAPI arguments > > > > - style of structure is now "nested" instead of "chained by pointer"; > > > > - use div64_u64 for 64bit division > > > > - define Visconti specific control IDs in v4l2-controls.h > > > > - set proper initial size to v4l2_ctrl_handler_init() > > > > - set all buffers to QUEUED state on an error at start_streaming > > > > - use vb2_is_busy() instead of vb2_is_streaming() > > > > - add parameter check for s->type and s->target in get_selection() > > > > - remove ioctls related to DV format and EDID > > > > - release v4l2 fh instance on and error at opening device file > > > > - support VB2_MMAP mode for streaming operation > > > > - add initial value to each vendor specific control > > > > - GET_LAST_CAPTURE_STATUS control is updated asyncnously from > workqueue > > > > - applied v4l2-compliance > > > > - Suggestion from Sakari Ailus > > > > - use div64_u64 for 64bit division > > > > - update copyright's year > > > > - use common definition of MIPI CSI2 DataTypes > > > > - remove redandunt cast > > > > - use bool instead of HWD_VIIF_ENABLE/DISABLE > > > > - simplify comparison to 0 > > > > - simplify statements with trigram operator > > > > - remove redundant local variables > > > > - simplify timeout loop > > > > - use general integer types instead of u32/s32 > > > > - Suggestion from Laurent Pinchart > > > > - moved VIIF driver to driver/platform/toshiba/visconti > > > > - add CSI2RX subdevice > > > > - change register access: struct-style to macro-style > > > > - use common definition of MIPI CSI2 DataTypes > > > > - Kconfig: add SPDX header, add V4L2_ASYNC > > > > - remove unused type definitions > > > > - define enums instead of successive macro constants > > > > - remove redundant parenthesis of macro constant > > > > - embed struct hwd_res into struct viif_device > > > > - turn switch-case into table lookup > > > > - use xxx_dma instead of xxx_paddr for variable names of IOVA > > > > - literal value: just 0 instead of 0x0 > > > > - use literal 1 or 0 instead of HWD_VIIF_ENABLE, DISABLE for register > access > > > > - use true or false instead of HWD_VIIF_ENABLE, DISABLE for > function calls > > > > - remove ioctl request handlers which refers subdevices > > > > > > > > Changelog v7: > > > > - change compatible string to visconti5-viif > > > > - remove unused variables > > > > - set static to internal functions > > > > - Suggestion from kernel test robot <lkp@intel.com> > > > > - update references to headers > > > > > > > > Changelog v8: > > > > - bugfix: handling return value of visconti_viiif_parse_dt() > > > > - add visconti_viif_subdev_notifier_register() to gather > > > > all operations around v4l2_async_notifier > > > > - update for v6.6-rc2 > > > > - use v4l2_async_connection instead of v4l2_async_subdev > > > > - aid for devices using subdev active state > > > > - add __maybe_unused for runtime_pm callbacks > > > > - Suggestion from Krzysztof Kozlowski > > > > - use static initialization of local variable > > > > - use dev_err_probe() > > > > - remove error message for DMA memory allocation failure > > > > - remove unused comment messages > > > > - add error handling at fail of workqueue_create() > > > > - remove redundant mutex for pm_runtime callback routines > > > > - Suggestion from Hans Verkuil > > > > - remove pr_info() calls > > > > - build check with media_stage.git > > > > - some lacks for kerneldoc description > > > > > > > > Changelog v9: > > > > - applied sparse checker > > > > - add static qualifier to a file scoped local variable > > > > - expand functions for acquiring/releasing locks > > > > - bugfix: use NULL (instead of 0) for pad::get_fmt subdevice API > > > > - fix warnings for cast between ptr and dma_addr_t > > > > - call div64_u64 for 64bit division > > > > - rebase to media_staging tree; update Visconti specific control > > > > IDs > > > > > > > > Changelog v10: > > > > - remove vendor specific compound controls > > > > - remove "rawpack mode" flag > > > > - RAW16, RAW18, RAW20 (to be implemented and tested) should be > > > > used instead > > > > - catch up to v6.9-rc4 > > > > > > > > Changelog v11: > > > > - stop merging sensor's controls to capture device's > > > > - remove redundant parameter checkings > > > > - update routines handling crop/compose rects of the ISP subdevice > > > > - update kerneldoc comments > > > > - update copyright year > > > > > > > > drivers/media/platform/Kconfig | 1 + > > > > drivers/media/platform/Makefile | 1 + > > > > drivers/media/platform/toshiba/Kconfig | 6 + > > > > drivers/media/platform/toshiba/Makefile | 2 + > > > > .../media/platform/toshiba/visconti/Kconfig | 19 + > > > > .../media/platform/toshiba/visconti/Makefile | 8 + > > > > .../media/platform/toshiba/visconti/viif.c | 627 ++++++ > > > > .../media/platform/toshiba/visconti/viif.h | 393 ++++ > > > > .../platform/toshiba/visconti/viif_capture.c | 1431 > ++++++++++++ > > > > .../platform/toshiba/visconti/viif_capture.h | 21 + > > > > .../platform/toshiba/visconti/viif_common.c | 239 ++ > > > > .../platform/toshiba/visconti/viif_common.h | 42 + > > > > .../platform/toshiba/visconti/viif_csi2rx.c | 657 ++++++ > > > > .../platform/toshiba/visconti/viif_csi2rx.h | 24 + > > > > .../toshiba/visconti/viif_csi2rx_regs.h | 102 + > > > > .../platform/toshiba/visconti/viif_isp.c | 1183 ++++++++++ > > > > .../platform/toshiba/visconti/viif_isp.h | 24 + > > > > .../platform/toshiba/visconti/viif_regs.h | 721 +++++++ > > > > include/uapi/linux/visconti_viif.h | 1921 > +++++++++++++++++ > > > > 19 files changed, 7422 insertions(+) create mode 100644 > > > > drivers/media/platform/toshiba/Kconfig > > > > create mode 100644 drivers/media/platform/toshiba/Makefile > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/Kconfig > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/Makefile > > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif.c > > > > create mode 100644 drivers/media/platform/toshiba/visconti/viif.h > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_capture.c > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_capture.h > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_common.c > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_common.h > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_csi2rx.c > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_csi2rx.h > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_isp.c > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_isp.h > > > > create mode 100644 > > > > drivers/media/platform/toshiba/visconti/viif_regs.h > > > > create mode 100644 include/uapi/linux/visconti_viif.h > > [snip] > > > > > diff --git a/drivers/media/platform/toshiba/visconti/viif.c > > > > b/drivers/media/platform/toshiba/visconti/viif.c > > > > new file mode 100644 > > > > index 0000000000..472b292752 > > > > --- /dev/null > > > > +++ b/drivers/media/platform/toshiba/visconti/viif.c > > > > @@ -0,0 +1,627 @@ > > [snip] > > > > > diff --git a/drivers/media/platform/toshiba/visconti/viif.h > > > b/drivers/media/platform/toshiba/visconti/viif.h > > > > new file mode 100644 > > > > index 0000000000..72b35bd605 > > > > --- /dev/null > > > > +++ b/drivers/media/platform/toshiba/visconti/viif.h > > > > @@ -0,0 +1,393 @@ > > [snip] > > > > > +#define VIIF_HW_AVAILABLE_IRQS 4 > > > > + > > > > +#define VIIF_SYS_CLK 500000UL > > > > > > Is that always a fixed frequency, or should it be retrieved > > > dynamically at runtime from the clock ? > > > > The system clock for VIIF is fixed to 500MHz. > > > > We are also trying to expand Visconti's clock driver to support VIIF. > > The value can be retrived from API in future. > > OK. If the clock driver doesn't expose a VIIF clock yet, then using this macro is > fine. A comment above the line to indicate the frequency should be retrieved > dynamically from the clock would be useful. > > If the clock driver has a VIIF clock that is not configurable yet but is hardcoded > to 500MHz, then you can already use clk_get_rate() to get the frequency, and > remove the macro. The clock driver does not have a VIIF clock yet. I'll add a comment to the macro. > > [snip] > > > > > diff --git > > > > a/drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h > > > > b/drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h > > > > new file mode 100644 > > > > index 0000000000..97e2017fec > > > > --- /dev/null > > > > +++ b/drivers/media/platform/toshiba/visconti/viif_csi2rx_regs.h > > > > @@ -0,0 +1,102 @@ > > > > +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ > > > > +/* Toshiba Visconti Video Capture register definitions > > > > + * > > > > + * (C) Copyright 2024 TOSHIBA CORPORATION > > > > + * (C) Copyright 2024 Toshiba Electronic Devices & Storage > > > > +Corporation */ > > > > + > > > > +#ifndef VIIF_CSI2RX_REGS_H > > > > +#define VIIF_CSI2RX_REGS_H > > > > + > > > > > +/*=============================================*/ > > > > +/* CSI2HOST registers */ > > > > > +/*=============================================*/ > > > > +#define REG_CSI2RX_NLANES 0x4 > > > > +#define REG_CSI2RX_PHY_SHUTDOWNZ 0x40 > > > > +#define REG_CSI2RX_PHY_RSTZ 0x44 > > > > + > > > > +/* access to dphy external registers */ #define > > > > +REG_CSI2RX_PHY_TESTCTRL0 0x50 > > > > +#define BIT_TESTCTRL0_CLK_0 0 > > > > +#define BIT_TESTCTRL0_CLK_1 BIT(1) > > > > > > Quoting drivers/media/platform/renesas/rcar-csi2.c, > > > > > > #define V4H_N_LANES_REG 0x0004 > > > #define V4H_CSI2_RESETN_REG 0x0008 > > > #define V4H_PHY_MODE_REG 0x001c > > > #define V4H_PHY_SHUTDOWNZ_REG > 0x0040 > > > #define V4H_DPHY_RSTZ_REG 0x0044 > > > ... > > > #define PHTW_REG 0x50 > > > > > > Where does your CSI-2 receiver come from, is it a Synopsys IP ? One > > > day we should really try to consolidate all that into a single > > > driver. To make it easier, I think support for the CSI-2 RX should > > > already be split out of this driver to a standalone subdev driver, > > > with separate DT bindings. > > > > Yes, CSI2RX is Synopsys IP (host controller + D-Phy). > > I'll try to separate the CSI2RX driver into standalone subdev driver, > > using the structure of the rcar-csi2 driver as a reference. > > Thank you. > > [snip] > > > > > diff --git a/drivers/media/platform/toshiba/visconti/viif_isp.c > > > > b/drivers/media/platform/toshiba/visconti/viif_isp.c > > > > new file mode 100644 > > > > index 0000000000..7a66aac715 > > > > --- /dev/null > > > > +++ b/drivers/media/platform/toshiba/visconti/viif_isp.c > > > > @@ -0,0 +1,1183 @@ > > [snip] > > > > > +static void visconti_viif_isp_set_sink_fmt(struct v4l2_subdev_state > *sd_state, > > > > + struct v4l2_mbus_framefmt > *format) { > > > > + struct v4l2_mbus_framefmt *sink_fmt, *src0_fmt, *src1_fmt, > > > > +*src2_fmt; > > > > + > > > > + sink_fmt = v4l2_subdev_state_get_format(sd_state, > VIIF_ISP_PAD_SINK_VIDEO); > > > > + src0_fmt = v4l2_subdev_state_get_format(sd_state, > VIIF_ISP_PAD_SRC_PATH0); > > > > + src1_fmt = v4l2_subdev_state_get_format(sd_state, > VIIF_ISP_PAD_SRC_PATH1); > > > > + src2_fmt = v4l2_subdev_state_get_format(sd_state, > > > > +VIIF_ISP_PAD_SRC_PATH2); > > > > + > > > > + /* update mbus code only if it's available */ > > > > + if (viif_is_valid_mbus_code(format->code)) > > > > + sink_fmt->code = format->code; > > > > > > If format->code is not valid, it would be better to set > > > sink_fmt->code to a default format instead of keeping the current > > > value. It will result in a more predictable behaviour for userspace, > > > making it easier to debug issues. > > > > I understand. I'll fix it. > > > > > > + > > > > + /* sink::mbus_code is derived from src::mbus_code */ > > > > > > Here you seem to do it the other way around, setting the source > > > format based on the sink format. > > > > I have no idea what to set in the source format here. > > Should I use the default format even if it is not compatible to the source > format? > > The base rule is that subdev drivers must propagate formats from sink (input of > the subdev) to source (output of the subdev). This function is called when > userspace sets the format on the sink pad. It needs to update the source pad > format accordingly, which you do below. What I think is not correct (if I > understand it right) is the comment above. > You set the source format based on the sink format, so I think the comment > should read > > /* src::mbus_code is derived from sink::mbus_code */ > The comment was saying the exact opposite of what is implemented and what it should be. Very sorry for my wrong comment. I now understand the base rule. > > > > + if (viif_get_mbus_rgb_out(sink_fmt->code)) { > > > > + src0_fmt->code = MEDIA_BUS_FMT_RGB888_1X24; > > > > + src1_fmt->code = MEDIA_BUS_FMT_RGB888_1X24; > > > > + } else { > > > > + src0_fmt->code = MEDIA_BUS_FMT_YUV8_1X24; > > > > + src1_fmt->code = MEDIA_BUS_FMT_YUV8_1X24; > > > > + } > > > > + > > > > + /* SRC2 (RAW output) follows SINK format */ > > > > + src2_fmt->code = format->code; > > > > + src2_fmt->width = format->width; > > > > + src2_fmt->height = format->height; > > > > > > You need to adjust the width and height based on the hardware limits. > > > > > > Can src0 and src1 generate any size, or are they restricted by the > > > sink size ? I would recomend propagating the sink size to all sources here. > > > You should also adjust selection rectangles. > > > > I need to understand what should/can be propagated from sink to source, > and what should not. > > I have read "4.13 Sub-device Interface" but I'm still not clear. > > The order of the configuration parameters in a subdev is as follows: > > - sink format (mbus code, size, colorspace) > - sink crop (rectangle) > - sink compose (rectangle) > - source crop (rectangle) > - source format (mbus code, size, colorspace) > > Starting with the easy ones. To propagate the media bus code from sink to > source, you need to set a media bus code on the source pads that is compatible > with the media bus code on the sink pad. What that is depends on your > hardware constraints. For instance, if the ISP can produce multiple RGB and > YUV formats from a raw bayer format, then pick a default RGB or YUV format > for the source pads.. Thank you. Now I get what to do. > For the colorspace information (the colorspace, ycbcr_enc, quantization and > xfer_func fields), the situation is slightly more complicated, but I think it can be > simplified. The ISP input can be in any color space, and the ISP can also output > different color spaces. In theory, that could be controlled by the color space > fields on the source pads, setting them to specific values would configure the > ISP parameters accordingly (RGB2RGB matrix, RGB2YUV matrix, ...). However, > this would create complexity in the driver, and would make the ISP less flexible > as userspace wouldn't be able to have precise control of all the corresponding > ISP parameters. > For that reason, I think it's better to control all the ISP paramaters through the > ISP parameters buffer, and ignore the color space fields in the sink and source > pad formats. The quantization range may be an exception, you may want to > control quantization using the pad format, up to you. As an example, here's how > we handle colorspace propagation in the rkisp1 driver: > > /* > * Copy the color space for the sink pad. When converting from Bayer > to > * YUV, default to a limited quantization range. > */ > src_fmt->colorspace = sink_fmt->colorspace; > src_fmt->xfer_func = sink_fmt->xfer_func; > src_fmt->ycbcr_enc = sink_fmt->ycbcr_enc; > > if (sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER && > src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) > src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE; > else > src_fmt->quantization = sink_fmt->quantization; > > /* > * Allow setting the source color space fields when the SET_CSC flag > is > * set and the source format is YUV. If the sink format is YUV, don't > * set the color primaries, transfer function or YCbCr encoding as the > * ISP is bypassed in that case and passes YUV data through without > * modifications. > * > * The color primaries and transfer function are configured through the > * cross-talk matrix and tone curve respectively. Settings for those > * hardware blocks are conveyed through the ISP parameters buffer, > as > * they need to combine color space information with other image > tuning > * characteristics and can't thus be computed by the kernel based on > the > * color space. The source pad colorspace and xfer_func fields are thus > * ignored by the driver, but can be set by userspace to propagate > * accurate color space information down the pipeline. > */ > set_csc = format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC; > > if (set_csc && src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) { > if (sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) { > if (format->colorspace != > V4L2_COLORSPACE_DEFAULT) > src_fmt->colorspace = format->colorspace; > if (format->xfer_func != > V4L2_XFER_FUNC_DEFAULT) > src_fmt->xfer_func = format->xfer_func; > if (format->ycbcr_enc != > V4L2_YCBCR_ENC_DEFAULT) > src_fmt->ycbcr_enc = format->ycbcr_enc; > } > > if (format->quantization != V4L2_QUANTIZATION_DEFAULT) > src_fmt->quantization = format->quantization; > } > > The colorspace-related fields on the source pad can be set to make userspace > code simpler. By setting the colorspace on the ISP source pad to the value > corresponding to the ISP parameters it sets, userspace will make sure the > correct colorspace value is propagated along the pipeline to the capture device > at the end. This will help writing more generic code in userspace that can take > the colorspace from the capture device and use it on the consumer of the video > stream (e.g. a video codec or a display device), to avoid colorspace mismatches. > I'll add operations to handle colorspace as much as possible. > Now we have the sizes and rectangles to propagate: > > - sink format size > - sink crop rectangle > - sink compose rectangle > - source crop rectangle > - source format size, colorspace > > When userspace sets the sink format size, this should be propagated to the sink > crop by setting the sink crop to the full sink format size. The sink compose > rectangle should be reset to a 1:1 scaling ratio. The source crop rectangle > should be reset to the same size (no additional cropping), and the source format > size should be set to the same size too. Sakari, could you confirm this is > correct ? > I now understand how the sink format size affects other rectangles. In the same way, when the sink crop rectangle is set, the rest of the rectangles and the source format size should be updated. Is that a correct understanding? > > The sizes of src0 and src1 are not restricted by the sink size. > > Src0 and src1 are processed by L2-ISP (undistortion, resize, crop). > > Does that mean that the resizer can both downscale and upscale ? Are there > limits to the scaling factors ? > Yes, resizer can handle both downscale and upscale. The scaling factors are limited to x1/2 - x2. Let me describe the L2-ISP more. The L2-ISP processes undistortion and scaling at the same time. The two processing paths (for src0 and src1) share one undistortion parameter-set and have independent scaling parameter-sets. They have no cropping at input, but independent croppings at outputs. Because undistortion and scaling are combined in L2ISP, it is difficult to generate parameters for the scaling HW from a sink.crop rectangle and a sink.compose rectangle. We need to pass the scaling parameters via the parameter buffer. VIIF driver uses following selection targets: - sink crop rectangle: (not used; the same as sink format size) - sink compose rectangle: image after undistortion and scaling (with parameters for src0) - src0 crop rectangle: cropped image relative to sink compose rectangle (legal) - src1 crop rectangle: cropped image relative to sink compose rectangle (illegal; the compose rectangle should refer to scaling parameters for src1) > > L2-ISP's operation is represented with sink.compose, src0.crop and > src1.crop. > > > > In order to correctly map the subdevice nodes to the HW functions and > > ensure consistency with the pad operations, the internal driver structure > should be modified as shown below. > > However due to the increased complexity of operating the L2ISP and risks of > unverified HW operation patterns, I have not yet tried this. > > > > [HW] > > sensor --- CSI2RX --- glue --- L1ISP --- L2ISP --- DMAC > > > > [subdevice] > > Param_dev --- --- Stat_dev > > Sensor --- CSI2RX --- MUX --- L1ISP --- Resizer0 --- Capture0_dev > > --- Resizer1 --- Capture1_dev > > -------------------------- Capture2_dev > > > > > > + > > > > + /* size check */ > > > > + sink_fmt->width = format->width; > > > > + sink_fmt->height = format->height; > > > > + > > > > + *format = *sink_fmt; > > > > +} > > [snip] > > > > > diff --git a/include/uapi/linux/visconti_viif.h > > > > b/include/uapi/linux/visconti_viif.h > > > > new file mode 100644 > > > > index 0000000000..3ff9bfc913 > > > > --- /dev/null > > > > +++ b/include/uapi/linux/visconti_viif.h > > > > @@ -0,0 +1,1921 @@ > > [snip] > > > > > +/** > > > > + * struct viif_l1_ag_mode_config - L1ISP parameter for analog > > > > +gain > > > > + * > > > > + * @sysm_ag_grad: Analog gain slope. Range: [0..255], Index > corresponds to psel id. > > > > + * @sysm_ag_ofst: Analog gain offset. Range: [0..65535], Index > corresponds to psel id. > > > > + * @sysm_ag_cont_hobc_en_high: set 1 to enable control analog gain > > > > + * for high sensitivity image of OBCC > > > > + * @sysm_ag_psel_hobc_high: Analog gain id for high sensitivity > > > > +image of OBCC. Range: [0..3] > > > > + * @sysm_ag_cont_hobc_en_middle_led: set 1 to enable control analog > gain > > > > + * for middle sensitivity or LED > image of OBCC > > > > + * @sysm_ag_psel_hobc_middle_led: Analog gain id for middle > sensitivity > > > > + * or LED image of OBCC. Range: > [0..3] > > > > + * @sysm_ag_cont_hobc_en_low: set 1 to enable control analog gain > > > > + * for low sensitivity image of OBCC > > > > + * @sysm_ag_psel_hobc_low: Analog gain id for low sensitivity > > > > +image of OBCC. Range:[0..3] > > > > + * @sysm_ag_cont_abpc_en_high: set 1 to enable control analog gain > > > > + * for high sensitivity image of ABPC > > > > + * @sysm_ag_psel_abpc_high: Analog gain id for high sensitivity > > > > +image of ABPC. Range: [0..3] > > > > + * @sysm_ag_cont_abpc_en_middle_led: set 1 to enable control analog > gain > > > > + * for middle sensitivity or LED > image of ABPC > > > > + * @sysm_ag_psel_abpc_middle_led: Analog gain id for middle > sensitivity > > > > + * or LED image of ABPC. Range: > [0..3] > > > > + * @sysm_ag_cont_abpc_en_low: set 1 to enable control analog gain > > > > + * for low sensitivity image of ABPC > > > > + * @sysm_ag_psel_abpc_low: Analog gain id for low sensitivity > > > > +image of ABPC. Range: [0..3] > > > > + * @sysm_ag_cont_rcnr_en_high: set 1 to enable control analog gain > > > > + * for high sensitivity image of RCNR > > > > + * @sysm_ag_psel_rcnr_high: Analog gain id for high sensitivity > > > > +image of RCNR. Range: [0..3] > > > > + * @sysm_ag_cont_rcnr_en_middle_led: set 1 to enable control analog > gain > > > > + * for middle sensitivity or LED > image of RCNR > > > > + * @sysm_ag_psel_rcnr_middle_led: Analog gain id for middle > sensitivity > > > > + * or LED image of RCNR. Range: > [0..3] > > > > + * @sysm_ag_cont_rcnr_en_low: set 1 to enable control analog gain > > > > + * for low sensitivity image of RCNR > > > > + * @sysm_ag_psel_rcnr_low: Analog gain id for low sensitivity > > > > +image of RCNR. Range: [0..3] > > > > + * @sysm_ag_cont_lssc_en: set 1 to enable control analog gain for > > > > +LSC > > > > + * @sysm_ag_ssel_lssc: &enum viif_l1_img_sensitivity_mode value. > Sensitive image used for LSC. > > > > + * @sysm_ag_psel_lssc: Analog gain id for LSC. Range: [0..3] > > > > + * @sysm_ag_cont_mpro_en: set 1 to enable control analog gain for > > > > +color matrix > > > > + * @sysm_ag_ssel_mpro: &enum viif_l1_img_sensitivity_mode value. > > > > + * Sensitive image used for color matrix. > > > > + * @sysm_ag_psel_mpro: Analog gain id for color matrix. Range: > > > > +[0..3] > > > > + * @sysm_ag_cont_vpro_en: set 1 to enable control analog gain for > > > > +image adjustment > > > > + * @sysm_ag_ssel_vpro: &enum viif_l1_img_sensitivity_mode value. > > > > + * Sensitive image used for image adjustment. > > > > + * @sysm_ag_psel_vpro: Analog gain id for image adjustment. > > > > +Range: [0..3] > > > > + * @sysm_ag_cont_hobc_test_high: Manual analog gain for high > sensitivity image > > > > + * of OBCC. Range: [0..255] > > > > + * @sysm_ag_cont_hobc_test_middle_led: Manual analog gain for > middle sensitivity > > > > + * or led image of OBCC. Range: > [0..255] > > > > + * @sysm_ag_cont_hobc_test_low: Manual analog gain for low > sensitivity image > > > > + * of OBCC. Range: [0..255] > > > > + * @sysm_ag_cont_abpc_test_high: Manual analog gain for high > sensitivity image > > > > + * of ABPC. Range: [0..255] > > > > + * @sysm_ag_cont_abpc_test_middle_led: Manual analog gain for > middle sensitivity > > > > + * or led image of ABPC. Range: > [0..255] > > > > + * @sysm_ag_cont_abpc_test_low: Manual analog gain for low > sensitivity image > > > > + * of ABPC. Range: [0..255] > > > > + * @sysm_ag_cont_rcnr_test_high: Manual analog gain for high > sensitivity image > > > > + * of RCNR. Range: [0..255] > > > > + * @sysm_ag_cont_rcnr_test_middle_led: Manual analog gain for > middle sensitivity > > > > + * or led image of RCNR. Range: > [0..255] > > > > + * @sysm_ag_cont_rcnr_test_low: Manual analog gain for low sensitivity > image > > > > + * of RCNR. Range: [0..255] > > > > + * @sysm_ag_cont_lssc_test: Manual analog gain for LSSC. Range: > > > > +[0..255] > > > > + * @sysm_ag_cont_mpro_test: Manual analog gain for color matrix. > > > > +Range: [0..255] > > > > + * @sysm_ag_cont_vpro_test: Manual analog gain for image > > > > +adjustment. Range: [0..255] > > > > + * > > > > + * This parameter sets rules of generating analog gains for each feature > in L1ISP. > > > > > > Does the ISP compute the analog gains for the sensor ? That's the > > > first time I see such a ISP feature. If that's not the case, maybe > > > I'm not understanding the documentation correctly. > > > > > > Overall, there are lots of ISP parameters here. They all have a > > > short description, and ranges and formats for fixed-point integers > > > are documented, which is very nice. However, reading the > > > documentation in this file doesn't provide me with enough > > > information to use most of the ISP parameters. There are three main > options to address this: > > > > > > - Expanding the documentation in this header file to clearly explain how > > > each ISP parameter operates and how to use them. > > > > > > - Providing an open userspace implementation of ISP algorithms that > > > showcase how to calculate the values for the parameters. > > > > > > - Providing detailed hardware documentation for the ISP. This is usually > > > not favoured by ISP vendors, and the V4L2 community is not pushing for > > > this, but I wanted to mention it for completeness. > > > > > > If you would prefer the second option, any open-source camera > > > framework would be acceptable, but in practice the only real option > > > is likely libcamera. > > > > > > This does not mean that you have to open-source all your ISP control > > > algorithms. Only the code needed to explain how ISP parameters are > > > applied to the image and are computed is needed. Other parts, such > > > as for instance AI-based computation of white balance gains, or > > > complex AGC calculations, don't need to be open-source. > > > > > > The explain this requirement different and perhaps more clearly, the > > > goal is to make sure that developers who have access to only > > > open-source material (ISP kernel driver, this header, any > > > open-source userspace code, public documentation, ...) will have > > > enough information to configure and control the ISP. > > > > I read the HW manual again and found the term "analog gain" is not related to > the sensor nor individual pixel values. > > It is a kind of "strength" parameter commonly used in image processing > algorithms. > > I think I need to correct the confusing words and inconsistencies in the > documents, comments and source code. > > That would be nice :-) > > > We have an offline tool for generating ISP settings, but the parameters are > too many and specialized. > > I think it is attractive idea to prepare a simple userland for libcamera in the > future. > > That is what I recommend, as I think it's the simplest solution. We can help if > needed. > Thank you. > > > > + * Related features are: > > > > + * > > > > + * - Optical Black Clamp Correction (OBCC) > > > > + * - Defect Pixel Correction (DPC) > > > > + * - RAW Color Noise Reduction (RCNR) > > > > + * - Lens Shading Correction (LSC) > > > > + * - Color matrix correction (MPRO) > > > > + * - Image quality adjustment (VPRO) > > > > + * > > > > + * The base gain is set with &struct viif_l1_ag_config. > > > > + * > > > > + * If sysm_ag_cont_xxxx_en = 1, analog_gain for each module is > > > > +generated from > > > > + * sysm_ag_grad, sysm_ag_ofst and the value specified with &struct > viif_l1_ag_config. > > > > + * If sysm_ag_cont_xxxx_en = 0, > > > > + * the value of sysm_ag_cont_xxxx_test is used for analog_gain for each > module. > > > > + * > > > > + * Up to 4 sets of parameters (sysm_ag_grad[4] and > > > > +sysm_ag_ofst[4]) can be used > > > > + * to generate analog gain. > > > > + * The parameter sysm_ag_psel_xxxx specifies the set to be used for > module xxxx. > > > > + * For example, if sysm_ag_psel_hobc_high is set to 2, > > > > + * values in sysm_ag_grad[2] and sysm_ag_ofst[2] are used > > > > + * to generate analog gain for high sensitivity images in OBCC > processing. > > > > + * > > > > + * Analog gain generation for each L1ISP module is disabled when > > > > + * "sysm_ag_cont_xxxx_en=0" and "sysm_ag_cont_xxxx_test=0". > > > > + * Be sure to disable the analog gain generation > > > > + * if VIIF_L1_INPUT_HDR or VIIF_L1_INPUT_PWL is set to > > > > + * &struct viif_l1_input_mode_config > > > > + * > > > > + */ > > > > +struct viif_l1_ag_mode_config { > > > > + __u8 sysm_ag_grad[4]; > > > > + __u16 sysm_ag_ofst[4]; > > > > + __u32 sysm_ag_cont_hobc_en_high; > > > > + __u32 sysm_ag_psel_hobc_high; > > > > + __u32 sysm_ag_cont_hobc_en_middle_led; > > > > + __u32 sysm_ag_psel_hobc_middle_led; > > > > + __u32 sysm_ag_cont_hobc_en_low; > > > > + __u32 sysm_ag_psel_hobc_low; > > > > + __u32 sysm_ag_cont_abpc_en_high; > > > > + __u32 sysm_ag_psel_abpc_high; > > > > + __u32 sysm_ag_cont_abpc_en_middle_led; > > > > + __u32 sysm_ag_psel_abpc_middle_led; > > > > + __u32 sysm_ag_cont_abpc_en_low; > > > > + __u32 sysm_ag_psel_abpc_low; > > > > + __u32 sysm_ag_cont_rcnr_en_high; > > > > + __u32 sysm_ag_psel_rcnr_high; > > > > + __u32 sysm_ag_cont_rcnr_en_middle_led; > > > > + __u32 sysm_ag_psel_rcnr_middle_led; > > > > + __u32 sysm_ag_cont_rcnr_en_low; > > > > + __u32 sysm_ag_psel_rcnr_low; > > > > + __u32 sysm_ag_cont_lssc_en; > > > > + __u32 sysm_ag_ssel_lssc; > > > > + __u32 sysm_ag_psel_lssc; > > > > + __u32 sysm_ag_cont_mpro_en; > > > > + __u32 sysm_ag_ssel_mpro; > > > > + __u32 sysm_ag_psel_mpro; > > > > + __u32 sysm_ag_cont_vpro_en; > > > > + __u32 sysm_ag_ssel_vpro; > > > > + __u32 sysm_ag_psel_vpro; > > > > + __u8 sysm_ag_cont_hobc_test_high; > > > > + __u8 sysm_ag_cont_hobc_test_middle_led; > > > > + __u8 sysm_ag_cont_hobc_test_low; > > > > + __u8 sysm_ag_cont_abpc_test_high; > > > > + __u8 sysm_ag_cont_abpc_test_middle_led; > > > > + __u8 sysm_ag_cont_abpc_test_low; > > > > + __u8 sysm_ag_cont_rcnr_test_high; > > > > + __u8 sysm_ag_cont_rcnr_test_middle_led; > > > > + __u8 sysm_ag_cont_rcnr_test_low; > > > > + __u8 sysm_ag_cont_lssc_test; > > > > + __u8 sysm_ag_cont_mpro_test; > > > > + __u8 sysm_ag_cont_vpro_test; > > > > +}; > > [snip] > > -- > Regards, > > Laurent Pinchart Regards, Yuji Ishikawa ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2024-08-08 0:55 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-09 0:08 [PATCH v11 0/6] Add Toshiba Visconti Video Input Interface driver Yuji Ishikawa
2024-07-09 0:08 ` [PATCH v11 1/6] dt-bindings: media: platform: visconti: Add Toshiba Visconti Video Input Interface Yuji Ishikawa
2024-07-22 15:21 ` Laurent Pinchart
2024-08-01 9:21 ` yuji2.ishikawa
2024-07-09 0:08 ` [PATCH v11 2/6] media: videodev2.h: add visconti viif meta buffer format Yuji Ishikawa
2024-07-22 15:10 ` Laurent Pinchart
2024-07-22 15:12 ` Laurent Pinchart
2024-08-01 9:20 ` yuji2.ishikawa
2024-07-09 0:08 ` [PATCH v11 4/6] media: platform: visconti: add streaming interface for ISP parameters and status Yuji Ishikawa
2024-07-09 0:08 ` [PATCH v11 5/6] documentation: media: add documentation for Toshiba Visconti Video Input Interface driver Yuji Ishikawa
2024-07-22 18:02 ` Laurent Pinchart
2024-08-01 9:23 ` yuji2.ishikawa
2024-08-01 16:06 ` Laurent Pinchart
2024-08-08 0:42 ` yuji2.ishikawa
2024-07-09 0:08 ` [PATCH v11 6/6] MAINTAINERS: Add entries for Toshiba Visconti Video Input Interface Yuji Ishikawa
2024-07-22 15:17 ` Laurent Pinchart
[not found] ` <20240709000848.1108788-4-yuji2.ishikawa@toshiba.co.jp>
2024-07-09 7:47 ` [PATCH v11 3/6] media: platform: visconti: Add Toshiba Visconti Video Input Interface driver Markus Elfring
2024-07-18 23:46 ` yuji2.ishikawa
[not found] ` <20240722220815.GA9047@pendragon.ideasonboard.com>
[not found] ` <OSZPR01MB9427EDDADF59D6061DDF1DD492B22@OSZPR01MB9427.jpnprd01.prod.outlook.com>
2024-08-01 17:28 ` Laurent Pinchart
2024-08-08 0:48 ` yuji2.ishikawa
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox