mbox series

[RFC,v2,0/7] Add support for BCM2835 camera interface (unicam)

Message ID 20220121081810.155500-1-jeanmichel.hautbois@ideasonboard.com
Headers show
Series Add support for BCM2835 camera interface (unicam) | expand

Message

Jean-Michel Hautbois Jan. 21, 2022, 8:18 a.m. UTC
Hello !

This patch series adds the BCM2835 CCP2/CSI2 camera interface named
unicam. This driver is already used in the out-of-tree linux-rpi
repository [1], and this work aims to support it in mainline.

The series is based on top of:
- Rebased on top of 5.16 Tomi Valkeinen's multiplexed stream work, on
  his multistream/work branch [2] which has been submitted as v10 at the
  time of this writing. The objective is to demonstrate the use of
  multiplexed streams on a real world widely used example as well as
  supporting unicam mainline.
- The "Add 12bit and 14bit luma-only formats" series [3] is partly
  applied (the Y10P format bug) the new formats are now part of this
  series.

The series is made of 7 patches:
- 1/7 and 2/7 introduce the new formats needed for the unicam driver
- 3/7 introduces dt-bindings documentation and MAINTAINERS entry
  I have tentatively assigned maintainership, is this fine ?
- 4/7 adds the driver support in media/platform
- 5/7 introduces the csi nodes in the bcm2711 file, in a disabled state
- 6/7 modifies imx219 driver to make it use the multiplexed streams API
- 7/7 is the imx219 dtsi file tested on my RPi 4b with the mainline dtb
  and not the downstream dtb anymore.

All those patches are in my tree [4].

Patch 4/7 comes from the linux-rpi work [1] with substantial
modifications:
- Removed the non-mc API which is deprecated, and not needed upstream
- Moved from one video node with two source pads (image and embedded) to
  two video nodes
- Added a subdev between the sensor and the video nodes to properly
  route the streams
- Added support for multiplexed streams API

In order to test it, one will need a RPi board and the camv2 (imx219)
sensor.  An updated v4l-utils is also needed [5] to have support for
multiplexed streams.

v4l2-compliance passes on both video devices, without streaming testing
though.

This series in its v2 does integrate the device tree nodes into the
upstream BCM2835 or BCM2711 device tree support.

The media-ctl topology is:
```
pi@raspberrypi:~ $ media-ctl -d0 -p
Media controller API version 5.16.0

Media device information
------------------------
driver          unicam
model           unicam
serial          
bus info        platform:fe801000.csi
hw revision     0x0
driver version  5.16.0

Device topology
- entity 1: unicam-subdev (3 pads, 3 links, 1 route)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev0
	routes:
		0/0 -> 1/0 [ACTIVE]
	pad0: Sink
		[stream:0 fmt:UYVY8_2X8/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
		<- "imx219 10-0010":0 [ENABLED,IMMUTABLE]
	pad1: Source
		[stream:0 fmt:UYVY8_2X8/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
		-> "unicam-image":0 [ENABLED,IMMUTABLE]
	pad2: Source
		-> "unicam-embedded":0 [ENABLED,IMMUTABLE]

- entity 5: imx219 10-0010 (1 pad, 1 link, 2 routes)
            type V4L2 subdev subtype Sensor flags 0
            device node name /dev/v4l-subdev1
	routes:
		0/0 -> 0/0 [ACTIVE, IMMUTABLE, SOURCE]
		0/0 -> 0/1 [ACTIVE, SOURCE]
	pad0: Source
		[stream:0 fmt:SRGGB10_1X10/3280x2464 field:none colorspace:raw
		crop.bounds:(8,8)/3280x2464
		crop:(8,8)/3280x2464]
		[stream:1 fmt:METADATA_8/16384x1 field:none
		crop.bounds:(8,8)/3280x2464
		crop:(8,8)/3280x2464]
		-> "unicam-subdev":0 [ENABLED,IMMUTABLE]

- entity 7: unicam-image (1 pad, 1 link, 0 route)
            type Node subtype V4L flags 1
            device node name /dev/video0
	pad0: Sink
		<- "unicam-subdev":1 [ENABLED,IMMUTABLE]

- entity 13: unicam-embedded (1 pad, 1 link, 0 route)
             type Node subtype V4L flags 0
             device node name /dev/video1
	pad0: Sink
		<- "unicam-subdev":2 [ENABLED,IMMUTABLE]
```

In order to properly configure the media pipeline, it is needed to call
the usual ioctls, and configure routing in order to send the embedded
data from the sensor to the "unicam-embedded" device node :

``` media=0
media-ctl -d${media} -l "'imx219 10-0010':0->'unicam-subdev':0 [1]"
media-ctl -d${media} -l "'unicam-subdev':1->'unicam-image':0 [1]"
media-ctl -d${media} -v -R "'unicam-subdev' [0/0->1/0[1],0/1->2/0[1]]"
media-ctl -d${media} -V "'imx219 10-0010':0/0
[fmt:SRGGB10_1X10/3280x2464 field:none]" v4l2-ctl -d0 --set-fmt-video
width=3280,height=2464,pixelformat='pRAA',field=none media-ctl
-d${media} -v -V "'imx219 10-0010':0/1 [fmt:METADATA_8/16384x1
field:none]" media-ctl -d${media} -p ```

Be sure to configure the routes before setting the format, as s_routing
resets the default format.

Then a frame can be capture with yavta:
`yavta --capture=1 /dev/video0 -F/tmp/test-#.bin`

Side note:
My tree [4] also includes a backport for the unicam-isp drivers, it is
then possible, and it has been successfully tested, to use libcamera and
qcam to display the camera output.

[1]: https://github.com/raspberrypi/linux/tree/rpi-5.15.y
[2]: https://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git/log/?h=multistream/work
[3]: https://patchwork.linuxtv.org/project/linux-media/list/?series=7099
[4]: https://github.com/jhautbois/linux/tree/jmh/tomba/multistream/next/work-v10-with-laurent-isp
[5]: https://github.com/tomba/v4l-utils

Jean-Michel Hautbois (7):
  media: v4l: Add V4L2-PIX-FMT-Y12P format
  media: v4l: Add V4L2-PIX-FMT-Y14P format
  media: dt-bindings: media: Add bindings for bcm2835-unicam
  media: bcm2835-unicam: Add support for for CCP2/CSI2 camera interface
  ARM: dts: bcm2711: Add unicam CSI nodes
  media: imx219: Add support for multiplexed streams
  media: bcm283x: Include the imx219 node

 .../bindings/media/brcm,bcm2835-unicam.yaml   |  103 +
 .../media/v4l/pixfmt-yuv-luma.rst             |   44 +
 MAINTAINERS                                   |    7 +
 arch/arm/boot/dts/bcm2711-rpi-4-b.dts         |    1 +
 arch/arm/boot/dts/bcm2711.dtsi                |   31 +
 arch/arm/boot/dts/bcm283x-rpi-imx219.dtsi     |  103 +
 drivers/media/i2c/imx219.c                    |  452 +--
 drivers/media/platform/Kconfig                |    1 +
 drivers/media/platform/Makefile               |    2 +
 drivers/media/platform/bcm2835/Kconfig        |   21 +
 drivers/media/platform/bcm2835/Makefile       |    3 +
 .../media/platform/bcm2835/bcm2835-unicam.c   | 2678 +++++++++++++++++
 .../media/platform/bcm2835/vc4-regs-unicam.h  |  253 ++
 13 files changed, 3488 insertions(+), 211 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml
 create mode 100644 arch/arm/boot/dts/bcm283x-rpi-imx219.dtsi
 create mode 100644 drivers/media/platform/bcm2835/Kconfig
 create mode 100644 drivers/media/platform/bcm2835/Makefile
 create mode 100644 drivers/media/platform/bcm2835/bcm2835-unicam.c
 create mode 100644 drivers/media/platform/bcm2835/vc4-regs-unicam.h

Comments

Jean-Michel Hautbois Jan. 22, 2022, 8:38 a.m. UTC | #1
Hi Laurent,

On 22/01/2022 00:27, Laurent Pinchart wrote:
> Hi Jean-Michel,
> 
> Thank you for the patch.
> 
> On Fri, Jan 21, 2022 at 09:18:06AM +0100, Jean-Michel Hautbois wrote:
>> Introduce the dt-bindinds documentation for bcm2835 CCP2/CSI2 camera
> 
> s/bindinds/bindings/
> 
> I'd mention "Unicam" somewhere here.
> 
>> interface. Also add a MAINTAINERS entry for it.

Oh my, I tis not the right dts bindings patch, I mixed up my trees... :-/

Sorry for this I will send a v2.1 soon...

>>
>> Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
>> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
>> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>
>> ---
>> Dave: I assumed you were the maintainer for this file, as I based it on the
>> bcm2835-unicam.txt file. Are  you happy to be added directly as the
>> maintainer, or should this be specified as "Raspberry Pi Kernel
>> Maintenance <kernel-list@raspberrypi.com>"
>> - in v2: multiple corrections to pass the bot checking as Rob kindly
>>    told me.
>> ---
>>   .../bindings/media/brcm,bcm2835-unicam.yaml   | 103 ++++++++++++++++++
>>   MAINTAINERS                                   |   6 +
>>   2 files changed, 109 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml b/Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml
>> new file mode 100644
>> index 000000000000..1427514142cf
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml
>> @@ -0,0 +1,103 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/media/brcm,bcm2835-unicam.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Broadcom BCM283x Camera Interface (Unicam)
>> +
>> +maintainers:
>> +  - Dave Stevenson <dave.stevenson@raspberrypi.com>
>> +
>> +description: |-
>> +  The Unicam block on BCM283x SoCs is the receiver for either
>> +  CSI-2 or CCP2 data from image sensors or similar devices.
>> +
>> +  The main platform using this SoC is the Raspberry Pi family of boards.
>> +  On the Pi the VideoCore firmware can also control this hardware block,
>> +  and driving it from two different processors will cause issues.
>> +  To avoid this, the firmware checks the device tree configuration
>> +  during boot. If it finds device tree nodes called csi0 or csi1 then
>> +  it will stop the firmware accessing the block, and it can then
>> +  safely be used via the device tree binding.
> 
> As mentioned in the review of the DT integration, the nodes should
> ideally be called just "csi", not "csi0" and "csi1" (maybe Rob could
> confirm this ?). Dave, is there a way the firmware could be updated to
> also hand over control of the Unicam instances to Linux when a "csi"
> node is found, not just "csi0" or "csi1" ?
> 
> Given that the node names are significant, they should be enforced in
> the YAML schema.
> 
>> +
>> +properties:
>> +  compatible:
>> +    const: brcm,bcm2835-unicam
>> +
>> +  reg:
>> +    description:
>> +      physical base address and length of the register sets for the device.
> 
> This can be dropped.
> 
>> +    maxItems: 1
> 
> There are two items in the example below. How does this validate ?
> 
>> +
>> +  interrupts:
>> +    description: the IRQ line for this Unicam instance.
> 
> This can be dropped.
> 
>> +    maxItems: 1
>> +
>> +  clocks:
>> +    description: |-
>> +      list of clock specifiers, corresponding to entries in clock-names
>> +      property.
> 
>    clocks:
>      items:
>        - description: The clock for ...
>        - description: The clock for ...
> 
> (with the two descriptions matching the LP and VPU clocks, I don't know
> what they are).
> 
>> +
>> +  clock-names:
>> +    items:
>> +      - const: lp
>> +      - const: vpu
>> +
>> +  port:
>> +    $ref: /schemas/graph.yaml#/properties/port
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - interrupts
>> +  - clocks
>> +  - clock-names
>> +  - port
>> +
>> +additionalProperties: False
>> +
>> +examples:
>> +  - |
>> +    csi1: csi1@7e801000 {
>> +        compatible = "brcm,bcm2835-unicam";
>> +        reg = <0x7e801000 0x800>,
>> +              <0x7e802004 0x4>;
>> +        interrupts = <2 7>;
> 
> Let's use the Pi 4 device tree as an example, as that's what we're
> upstreaming first.
> 
>> +        clocks = <&clocks BCM2835_CLOCK_CAM1>,
> 
> This will fail to compile without a proper #include, did you get this to
> pass validation ?
> 
>> +                 <&firmware_clocks 4>;
>> +        clock-names = "lp", "vpu";
>> +        port {
>> +                csi1_ep: endpoint {
>> +                        remote-endpoint = <&tc358743_0>;
>> +                        data-lanes = <1 2>;
>> +                };
>> +        };
>> +    };
>> +
>> +    i2c0: i2c@7e205000 {
>> +        tc358743: csi-hdmi-bridge@0f {
>> +            compatible = "toshiba,tc358743";
>> +            reg = <0x0f>;
>> +            clocks = <&tc358743_clk>;
>> +            clock-names = "refclk";
>> +
>> +            tc358743_clk: bridge-clk {
>> +                    compatible = "fixed-clock";
>> +                    #clock-cells = <0>;
>> +                    clock-frequency = <27000000>;
>> +            };
>> +
>> +            port {
>> +                    tc358743_0: endpoint {
>> +                            remote-endpoint = <&csi1_ep>;
>> +                            clock-lanes = <0>;
>> +                            data-lanes = <1 2>;
>> +                            clock-noncontinuous;
>> +                            link-frequencies =
>> +                                /bits/ 64 <297000000>;
>> +                    };
>> +            };
>> +        };
>> +    };
> 
> I'd drop this node completely.
> 
>> +...
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 33f75892f98e..07f238fd5ff9 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -3679,6 +3679,12 @@ F:	Documentation/media/v4l-drivers/bcm2835-isp.rst
>>   F:	drivers/staging/vc04_services/bcm2835-isp
>>   F:	include/uapi/linux/bcm2835-isp.h
>>   
>> +BROADCOM BCM2835 CAMERA DRIVER
>> +M:	Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
>> +L:	linux-media@vger.kernel.org
>> +S:	Maintained
>> +F:	Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml
>> +
>>   BROADCOM BCM47XX MIPS ARCHITECTURE
>>   M:	Hauke Mehrtens <hauke@hauke-m.de>
>>   M:	Rafał Miłecki <zajec5@gmail.com>
>
Laurent Pinchart Jan. 26, 2022, 6:42 p.m. UTC | #2
Hi Dave,

On Mon, Jan 24, 2022 at 12:31:34PM +0000, Dave Stevenson wrote:
> On Fri, 21 Jan 2022 at 22:45, Laurent Pinchart wrote:
> > On Fri, Jan 21, 2022 at 09:18:08AM +0100, Jean-Michel Hautbois wrote:
> > > Add both MIPI CSI-2 nodes in the core bcm2711 tree. Use the 3-cells
> > > interrupt declaration, corresponding clocks and default as disabled.
> > >
> > > Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>
> > > ---
> > >  arch/arm/boot/dts/bcm2711.dtsi | 31 +++++++++++++++++++++++++++++++
> > >  1 file changed, 31 insertions(+)
> > >
> > > diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
> > > index dff18fc9a906..077141df7024 100644
> > > --- a/arch/arm/boot/dts/bcm2711.dtsi
> > > +++ b/arch/arm/boot/dts/bcm2711.dtsi
> > > @@ -3,6 +3,7 @@
> > >
> > >  #include <dt-bindings/interrupt-controller/arm-gic.h>
> > >  #include <dt-bindings/soc/bcm2835-pm.h>
> > > +#include <dt-bindings/power/raspberrypi-power.h>
> > >
> > >  / {
> > >       compatible = "brcm,bcm2711";
> > > @@ -293,6 +294,36 @@ hvs: hvs@7e400000 {
> > >                       interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> > >               };
> > >
> > > +             csi0: csi1@7e800000 {
> >
> > The node name should be csi@7e800000, not csi1@7e800000. Now, this will
> > probably cause issues with the firmware that looks for csi1 (and csi0 ?)
> > to hand over control of the Unicam CSI-2 receiver to the kernel. I
> > wonder if this is something that could be handled by a firmware update,
> > to also recognize nodes named "csi" ?
> 
> It already looks for any node starting "csi". If you check the
> downstream DT [1], then the nodes are "csi0: csi@7e800000" and "csi1:
> csi@7e801000".

Oops, indeed. I think I was misled by
https://github.com/raspberrypi/linux/blob/rpi-5.10.y/Documentation/devicetree/bindings/media/bcm2835-unicam.txt
that mentions "csi0" and "csi1".

It's all good then. Jean-Michel, can you update the DT bindings in the
next iteration of the series to correct the DT node naming ?

> There is no actual action required to hand the peripheral over to the
> kernel, it just prevents the firmware from using it and causing
> problems (it masks out the interrupt, and that's checked as part of
> the firmware initialising the peripheral).
> 
> If using imx219 or one of the other sensors supported by the firmware,
> "vcgencmd get_camera" should report that the sensor isn't detected,
> and "sudo vcdbg log msg" should have a line similar to
> "020174.613: camsubs: Ignoring camera 0 as unicam device not available"
> 
>   Dave
> 
> [1] https://github.com/raspberrypi/linux/blob/rpi-5.10.y/arch/arm/boot/dts/bcm270x.dtsi#L88
> 
> > > +                     compatible = "brcm,bcm2835-unicam";
> > > +                     reg = <0x7e800000 0x800>,
> > > +                           <0x7e802000 0x4>;
> > > +                     interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
> > > +                     clocks = <&clocks BCM2835_CLOCK_CAM0>,
> > > +                              <&firmware_clocks 4>;
> > > +                     clock-names = "lp", "vpu";
> > > +                     power-domains = <&power RPI_POWER_DOMAIN_UNICAM0>;
> > > +                     #address-cells = <1>;
> > > +                     #size-cells = <0>;
> > > +                     #clock-cells = <1>;
> >
> > Why do you need #address-cells, #size-cells and #clock-cells ? They're
> > not mentioned in the binding.
> >
> > > +                     status="disabled";
> >
> > Missing spaces around the =.
> >
> > Same comment for the next node.
> >
> > > +             };
> > > +
> > > +             csi1: csi1@7e801000 {
> > > +                     compatible = "brcm,bcm2835-unicam";
> > > +                     reg = <0x7e801000 0x800>,
> > > +                           <0x7e802004 0x4>;
> > > +                     interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
> > > +                     clocks = <&clocks BCM2835_CLOCK_CAM1>,
> > > +                              <&firmware_clocks 4>;
> > > +                     clock-names = "lp", "vpu";
> > > +                     power-domains = <&power RPI_POWER_DOMAIN_UNICAM1>;
> > > +                     #address-cells = <1>;
> > > +                     #size-cells = <0>;
> > > +                     #clock-cells = <1>;
> > > +                     status="disabled";
> > > +             };
> > > +
> > >               pixelvalve3: pixelvalve@7ec12000 {
> > >                       compatible = "brcm,bcm2711-pixelvalve3";
> > >                       reg = <0x7ec12000 0x100>;