Message ID | 20240620-rp1-cfe-v2-0-b8b48fdba3b3@ideasonboard.com (mailing list archive) |
---|---|
Headers | show |
Series | media: raspberrypi: Support RPi5's CFE | expand |
On Thu, Jun 20, 2024 at 02:07:52PM +0300, Tomi Valkeinen wrote: > Add support for Raspberry Pi CFE. The CFE is a hardware block that > contains: > > - MIPI D-PHY > - MIPI CSI-2 receiver > - Front End ISP (FE) > > The driver has been upported from the Raspberry Pi kernel commit > 88a681df9623 ("ARM: dts: bcm2712-rpi: Add i2c<n>_pins labels"). > > Co-developed-by: Naushir Patuck <naush@raspberrypi.com> > Signed-off-by: Naushir Patuck <naush@raspberrypi.com> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > --- > MAINTAINERS | 8 + > drivers/media/platform/raspberrypi/Kconfig | 1 + > drivers/media/platform/raspberrypi/Makefile | 1 + > drivers/media/platform/raspberrypi/rp1-cfe/Kconfig | 14 + > .../media/platform/raspberrypi/rp1-cfe/Makefile | 6 + > .../media/platform/raspberrypi/rp1-cfe/cfe-fmts.h | 332 +++ > .../media/platform/raspberrypi/rp1-cfe/cfe-trace.h | 196 ++ > drivers/media/platform/raspberrypi/rp1-cfe/cfe.c | 2526 ++++++++++++++++++++ > drivers/media/platform/raspberrypi/rp1-cfe/cfe.h | 43 + > drivers/media/platform/raspberrypi/rp1-cfe/csi2.c | 583 +++++ > drivers/media/platform/raspberrypi/rp1-cfe/csi2.h | 89 + > drivers/media/platform/raspberrypi/rp1-cfe/dphy.c | 175 ++ > drivers/media/platform/raspberrypi/rp1-cfe/dphy.h | 27 + > .../media/platform/raspberrypi/rp1-cfe/pisp-fe.c | 581 +++++ > .../media/platform/raspberrypi/rp1-cfe/pisp-fe.h | 53 + > .../uapi/linux/media/raspberrypi/pisp_fe_config.h | 273 +++ > .../linux/media/raspberrypi/pisp_fe_statistics.h | 64 + > 17 files changed, 4972 insertions(+) [snip] > diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/dphy.c b/drivers/media/platform/raspberrypi/rp1-cfe/dphy.c > new file mode 100644 > index 000000000000..c9e4a94fb80c > --- /dev/null > +++ b/drivers/media/platform/raspberrypi/rp1-cfe/dphy.c > @@ -0,0 +1,175 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * RP1 CSI-2 Driver > + * > + * Copyright (c) 2021-2024 Raspberry Pi Ltd. > + * Copyright (c) 2023-2024 Ideas on Board Oy > + */ > + > +#include <linux/delay.h> > +#include <linux/pm_runtime.h> > + > +#include "dphy.h" > + > +#define dphy_dbg(fmt, arg...) dev_dbg(dphy->dev, fmt, ##arg) > +#define dphy_err(fmt, arg...) dev_err(dphy->dev, fmt, ##arg) > + > +/* DW dphy Host registers */ > +#define DPHY_VERSION 0x000 > +#define DPHY_N_LANES 0x004 > +#define DPHY_RESETN 0x008 > +#define DPHY_PHY_SHUTDOWNZ 0x040 > +#define DPHY_PHY_RSTZ 0x044 > +#define DPHY_PHY_RX 0x048 > +#define DPHY_PHY_STOPSTATE 0x04c > +#define DPHY_PHY_TST_CTRL0 0x050 > +#define DPHY_PHY_TST_CTRL1 0x054 > +#define DPHY_PHY2_TST_CTRL0 0x058 > +#define DPHY_PHY2_TST_CTRL1 0x05c Quoting drivers/media/platform/renesas/rcar-csi2.c: /* V4H BASE registers */ #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 Time for a common PHY driver ? > + > +/* DW dphy Host Transactions */ > +#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44 > +#define DPHY_PLL_INPUT_DIV_OFFSET 0x17 > +#define DPHY_PLL_LOOP_DIV_OFFSET 0x18 > +#define DPHY_PLL_DIV_CTRL_OFFSET 0x19 > + > +static u32 dw_csi2_host_read(struct dphy_data *dphy, u32 offset) > +{ > + return readl(dphy->base + offset); > +} > + > +static void dw_csi2_host_write(struct dphy_data *dphy, u32 offset, u32 data) > +{ > + writel(data, dphy->base + offset); > +} > + > +static void set_tstclr(struct dphy_data *dphy, u32 val) > +{ > + u32 ctrl0 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL0); > + > + dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL0, (ctrl0 & ~1) | val); > +} > + > +static void set_tstclk(struct dphy_data *dphy, u32 val) > +{ > + u32 ctrl0 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL0); > + > + dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL0, (ctrl0 & ~2) | (val << 1)); > +} > + > +static uint8_t get_tstdout(struct dphy_data *dphy) > +{ > + u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1); > + > + return ((ctrl1 >> 8) & 0xff); > +} > + > +static void set_testen(struct dphy_data *dphy, u32 val) > +{ > + u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1); > + > + dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL1, > + (ctrl1 & ~(1 << 16)) | (val << 16)); > +} > + > +static void set_testdin(struct dphy_data *dphy, u32 val) > +{ > + u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1); > + > + dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL1, (ctrl1 & ~0xff) | val); > +} > + > +static uint8_t dphy_transaction(struct dphy_data *dphy, u8 test_code, > + uint8_t test_data) > +{ > + /* See page 101 of the MIPI DPHY databook. */ > + set_tstclk(dphy, 1); > + set_testen(dphy, 0); > + set_testdin(dphy, test_code); > + set_testen(dphy, 1); > + set_tstclk(dphy, 0); > + set_testen(dphy, 0); > + set_testdin(dphy, test_data); > + set_tstclk(dphy, 1); > + return get_tstdout(dphy); > +} > + > +static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t mbps) > +{ > + /* See Table 5-1 on page 65 of dphy databook */ > + static const u16 hsfreqrange_table[][2] = { > + { 89, 0b000000 }, { 99, 0b010000 }, { 109, 0b100000 }, > + { 129, 0b000001 }, { 139, 0b010001 }, { 149, 0b100001 }, > + { 169, 0b000010 }, { 179, 0b010010 }, { 199, 0b100010 }, > + { 219, 0b000011 }, { 239, 0b010011 }, { 249, 0b100011 }, > + { 269, 0b000100 }, { 299, 0b010100 }, { 329, 0b000101 }, > + { 359, 0b010101 }, { 399, 0b100101 }, { 449, 0b000110 }, > + { 499, 0b010110 }, { 549, 0b000111 }, { 599, 0b010111 }, > + { 649, 0b001000 }, { 699, 0b011000 }, { 749, 0b001001 }, > + { 799, 0b011001 }, { 849, 0b101001 }, { 899, 0b111001 }, > + { 949, 0b001010 }, { 999, 0b011010 }, { 1049, 0b101010 }, > + { 1099, 0b111010 }, { 1149, 0b001011 }, { 1199, 0b011011 }, > + { 1249, 0b101011 }, { 1299, 0b111011 }, { 1349, 0b001100 }, > + { 1399, 0b011100 }, { 1449, 0b101100 }, { 1500, 0b111100 }, > + }; > + unsigned int i; > + > + if (mbps < 80 || mbps > 1500) > + dphy_err("DPHY: Datarate %u Mbps out of range\n", mbps); > + > + for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) { > + if (mbps <= hsfreqrange_table[i][0]) > + break; > + } > + > + dphy_transaction(dphy, DPHY_HS_RX_CTRL_LANE0_OFFSET, > + hsfreqrange_table[i][1] << 1); > +} > + > +static void dphy_init(struct dphy_data *dphy) > +{ > + dw_csi2_host_write(dphy, DPHY_PHY_RSTZ, 0); > + dw_csi2_host_write(dphy, DPHY_PHY_SHUTDOWNZ, 0); > + set_tstclk(dphy, 1); > + set_testen(dphy, 0); > + set_tstclr(dphy, 1); > + usleep_range(15, 20); > + set_tstclr(dphy, 0); > + usleep_range(15, 20); > + > + dphy_set_hsfreqrange(dphy, dphy->dphy_rate); > + > + usleep_range(5, 10); > + dw_csi2_host_write(dphy, DPHY_PHY_SHUTDOWNZ, 1); > + usleep_range(5, 10); > + dw_csi2_host_write(dphy, DPHY_PHY_RSTZ, 1); > +} > + > +void dphy_start(struct dphy_data *dphy) > +{ > + dw_csi2_host_write(dphy, DPHY_N_LANES, (dphy->active_lanes - 1)); > + dphy_init(dphy); > + dw_csi2_host_write(dphy, DPHY_RESETN, 0xffffffff); > + usleep_range(10, 50); > +} > + > +void dphy_stop(struct dphy_data *dphy) > +{ > + /* Set only one lane (lane 0) as active (ON) */ > + dw_csi2_host_write(dphy, DPHY_N_LANES, 0); > + dw_csi2_host_write(dphy, DPHY_RESETN, 0); > +} > + > +void dphy_probe(struct dphy_data *dphy) > +{ > + u32 host_ver; > + u8 host_ver_major, host_ver_minor; > + > + host_ver = dw_csi2_host_read(dphy, DPHY_VERSION); > + host_ver_major = (u8)((host_ver >> 24) - '0'); > + host_ver_minor = (u8)((host_ver >> 16) - '0'); > + host_ver_minor = host_ver_minor * 10; > + host_ver_minor += (u8)((host_ver >> 8) - '0'); > + > + dphy_dbg("DW dphy Host HW v%u.%u\n", host_ver_major, host_ver_minor); > +} [snip]
This series adds support to the CFE hardware block on RaspberryPi 5. The CFE (Camera Front End) contains a CSI-2 receiver and Front End, a small ISP. This series is based on linux-media-stage with Jacopo's "[PATCH v9 0/8] media: raspberrypi: Add support for PiSP Back End". To run this, you need the basic RPi5 kernel support plus relevant dts changes to enable the cfe and camera. My work branch with everything needed to run CFE can be found from: git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git rp1-cfe A few notes about the patches: - The original work was done by RaspberryPi, mostly by Naushir Patuck. - The second video node only sets V4L2_CAP_META_CAPTURE instead of both V4L2_CAP_META_CAPTURE and V4L2_CAP_META_CAPTURE like the other nodes. This is a temporary workaround for userspace (libcamera), and hopefully can be removed soon. I have tested this with: - A single IMX219 sensor connected to the RPi5's CSI-2 port - Arducam's UB960 FPD-Link board with four imx219 sensors connected Tomi Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> --- Changes in v2: - Change the compatible string back to raspberrypi,rp1-cfe from raspberrypi,rpi5-rp1-cfe - Drop the references to rp1 headers in the DT binding example. This allows compiling the example without the rp1 support. - Fix missing remap lines for mono formats - Fix csi2_pad_set_fmt() so that the format can be changed back to the sink's format from 16-bit or compressed format. - Link to v1: https://lore.kernel.org/r/20240318-rp1-cfe-v1-0-ac6d960ff22d@ideasonboard.com --- Tomi Valkeinen (4): media: uapi: Add meta formats for PiSP FE config and stats dt-bindings: media: Add bindings for raspberrypi,rp1-cfe media: raspberrypi: Add support for RP1-CFE media: admin-guide: Document the Raspberry Pi CFE (rp1-cfe) .../admin-guide/media/raspberrypi-rp1-cfe.dot | 27 + .../admin-guide/media/raspberrypi-rp1-cfe.rst | 78 + Documentation/admin-guide/media/v4l-drivers.rst | 1 + .../bindings/media/raspberrypi,rp1-cfe.yaml | 98 + .../userspace-api/media/v4l/meta-formats.rst | 1 + .../userspace-api/media/v4l/metafmt-pisp-fe.rst | 39 + MAINTAINERS | 8 + drivers/media/platform/raspberrypi/Kconfig | 1 + drivers/media/platform/raspberrypi/Makefile | 1 + drivers/media/platform/raspberrypi/rp1-cfe/Kconfig | 14 + .../media/platform/raspberrypi/rp1-cfe/Makefile | 6 + .../media/platform/raspberrypi/rp1-cfe/cfe-fmts.h | 332 +++ .../media/platform/raspberrypi/rp1-cfe/cfe-trace.h | 196 ++ drivers/media/platform/raspberrypi/rp1-cfe/cfe.c | 2526 ++++++++++++++++++++ drivers/media/platform/raspberrypi/rp1-cfe/cfe.h | 43 + drivers/media/platform/raspberrypi/rp1-cfe/csi2.c | 583 +++++ drivers/media/platform/raspberrypi/rp1-cfe/csi2.h | 89 + drivers/media/platform/raspberrypi/rp1-cfe/dphy.c | 175 ++ drivers/media/platform/raspberrypi/rp1-cfe/dphy.h | 27 + .../media/platform/raspberrypi/rp1-cfe/pisp-fe.c | 581 +++++ .../media/platform/raspberrypi/rp1-cfe/pisp-fe.h | 53 + drivers/media/v4l2-core/v4l2-ioctl.c | 2 + .../uapi/linux/media/raspberrypi/pisp_fe_config.h | 273 +++ .../linux/media/raspberrypi/pisp_fe_statistics.h | 64 + include/uapi/linux/videodev2.h | 2 + 25 files changed, 5220 insertions(+) --- base-commit: 954ee38d40c98001cfdc570c4d5e90bcbc456ce1 change-id: 20240314-rp1-cfe-142b628b7214 prerequisite-message-id: <20240531080707.34568-1-jacopo.mondi@ideasonboard.com> prerequisite-patch-id: 42749883104fffad151e25d8127eb84800d7e9ca prerequisite-patch-id: 433ce52b6b1b72f2c29e4474d72cd5106b73c075 prerequisite-patch-id: b9b3006cd03bb4e41e03f735d97e19081a32be02 prerequisite-patch-id: abeb8c40020f0ca6140afc141e535abc86a4773b prerequisite-patch-id: 4ddf121ee47eeadeb370a5fbabc82ca6f6caa23b prerequisite-patch-id: ee469d3c346f55483733a04d89e87d02126501cc prerequisite-patch-id: 9467d5cd306aa29842128294a5f76f184b72eab7 prerequisite-patch-id: e6dbee90dfbd984bd55cbe3db56d9d8de4dc86ae Best regards,