From: Sakari Ailus <sakari.ailus@linux.intel.com>
To: Michael Riesch <michael.riesch@wolfvision.net>
Cc: "Mehdi Djait" <mehdi.djait@linux.intel.com>,
"Maxime Chevallier" <maxime.chevallier@bootlin.com>,
"Théo Lebrun" <theo.lebrun@bootlin.com>,
"Gerald Loacker" <gerald.loacker@wolfvision.net>,
"Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
"Laurent Pinchart" <laurent.pinchart@ideasonboard.com>,
"Mauro Carvalho Chehab" <mchehab@kernel.org>,
"Rob Herring" <robh+dt@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Heiko Stuebner" <heiko@sntech.de>,
"Kever Yang" <kever.yang@rock-chips.com>,
"Nicolas Dufresne" <nicolas.dufresne@collabora.com>,
"Sebastian Fricke" <sebastian.fricke@collabora.com>,
"Sebastian Reichel" <sebastian.reichel@collabora.com>,
"Paul Kocialkowski" <paulk@sys-base.io>,
"Alexander Shiyan" <eagle.alexander923@gmail.com>,
"Val Packett" <val@packett.cool>, "Rob Herring" <robh@kernel.org>,
"Philipp Zabel" <p.zabel@pengutronix.de>,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-rockchip@lists.infradead.org
Subject: Re: [PATCH v5 07/11] media: rockchip: rkcif: add support for mipi csi-2 receiver
Date: Mon, 28 Apr 2025 15:40:10 +0000 [thread overview]
Message-ID: <aA-hWug1bpRR_qYh@kekkonen.localdomain> (raw)
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-7-f02152534f3c@wolfvision.net>
Hi Michael,
On Thu, Mar 06, 2025 at 05:56:08PM +0100, Michael Riesch wrote:
> The RK3568 Video Capture (VICAP) unit features a MIPI CSI-2 receiver
> that can receive video data and write it into system memory using the
> ping-pong scheme. Add support for it.
>
> Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
> ---
> .../platform/rockchip/rkcif/rkcif-capture-mipi.c | 695 +++++++++++++++++++++
> .../platform/rockchip/rkcif/rkcif-capture-mipi.h | 2 +
> .../media/platform/rockchip/rkcif/rkcif-common.h | 16 +
> drivers/media/platform/rockchip/rkcif/rkcif-dev.c | 1 +
> .../platform/rockchip/rkcif/rkcif-interface.c | 5 +-
> drivers/media/platform/rockchip/rkcif/rkcif-regs.h | 24 +-
> 6 files changed, 741 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
> index 0c3f7b8cfa18..dcc0c4aeeec4 100644
> --- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
> @@ -6,22 +6,717 @@
> * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
> */
>
> +#include <linux/interrupt.h>
> +
> +#include <media/mipi-csi2.h>
> +#include <media/v4l2-common.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-fh.h>
> +#include <media/v4l2-fwnode.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-mc.h>
> +#include <media/v4l2-subdev.h>
> +
> #include "rkcif-capture-mipi.h"
> #include "rkcif-common.h"
> +#include "rkcif-interface.h"
> +#include "rkcif-regs.h"
> #include "rkcif-stream.h"
>
> +#define RKCIF_MIPI_CTRL0_COMPACT_EN BIT(6)
> +#define RKCIF_MIPI_CTRL0_CROP_EN BIT(5)
> +#define RKCIF_MIPI_CTRL0_TYPE(type) ((type) << 1)
> +#define RKCIF_MIPI_CTRL0_TYPE_RAW8 RKCIF_MIPI_CTRL0_TYPE(0x0)
> +#define RKCIF_MIPI_CTRL0_TYPE_RAW10 RKCIF_MIPI_CTRL0_TYPE(0x1)
> +#define RKCIF_MIPI_CTRL0_TYPE_RAW12 RKCIF_MIPI_CTRL0_TYPE(0x2)
> +#define RKCIF_MIPI_CTRL0_TYPE_RGB888 RKCIF_MIPI_CTRL0_TYPE(0x3)
> +#define RKCIF_MIPI_CTRL0_TYPE_YUV422SP RKCIF_MIPI_CTRL0_TYPE(0x4)
> +#define RKCIF_MIPI_CTRL0_TYPE_YUV420SP RKCIF_MIPI_CTRL0_TYPE(0x5)
> +#define RKCIF_MIPI_CTRL0_TYPE_YUV400 RKCIF_MIPI_CTRL0_TYPE(0x6)
> +#define RKCIF_MIPI_CTRL0_CAP_EN BIT(0)
> +
> +#define RKCIF_MIPI_INT_FRAME0_END(id) BIT(8 + (id) * 2 + 0)
> +#define RKCIF_MIPI_INT_FRAME1_END(id) BIT(8 + (id) * 2 + 1)
> +
> +static const struct rkcif_output_fmt mipi_out_fmts[] = {
> + /* YUV formats */
> + {
> + .fourcc = V4L2_PIX_FMT_YUYV,
> + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
> + .depth = 16,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_YUV422_8B,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_UYVY,
> + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
> + .depth = 16,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_YUV422_8B,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_YVYU,
> + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
> + .depth = 16,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_YUV422_8B,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_VYUY,
> + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
> + .depth = 16,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_YUV422_8B,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + /* RGB formats */
> + {
> + .fourcc = V4L2_PIX_FMT_RGB24,
> + .mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
> + .depth = 24,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RGB888,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RGB888,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_BGR24,
> + .mbus_code = MEDIA_BUS_FMT_BGR888_1X24,
> + .depth = 24,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RGB888,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RGB888,
> + },
> + },
> + /* Bayer formats */
> + {
> + .fourcc = V4L2_PIX_FMT_SBGGR8,
> + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
> + .depth = 8,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW8,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGBRG8,
> + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
> + .depth = 8,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW8,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGRBG8,
> + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
> + .depth = 8,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW8,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SRGGB8,
> + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
> + .depth = 8,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW8,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SBGGR10,
> + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SBGGR10P,
> + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGBRG10,
> + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGBRG10P,
> + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGRBG10,
> + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGRBG10P,
> + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SRGGB10,
> + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SRGGB10P,
> + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
> + .depth = 10,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW10,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SBGGR12,
> + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SBGGR12P,
> + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGBRG12,
> + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGBRG12P,
> + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGRBG12,
> + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SGRBG12P,
> + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SRGGB12,
> + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
> + },
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_SRGGB12P,
> + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
> + .depth = 12,
> + .cplanes = 1,
> + .mipi = {
> + .dt = MIPI_CSI2_DT_RAW12,
> + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
> + },
> + },
> +};
> +
> +static const struct rkcif_input_fmt mipi_in_fmts[] = {
> + /* YUV formats */
> + {
> + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
> + },
> + /* RGB formats */
> + {
> + .mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_BGR888_1X24,
> + },
> + /* Bayer formats */
> + {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
> + },
> +};
> +
> +const struct rkcif_mipi_match_data rk3568_vicap_mipi_match_data = {
> + .mipi_num = 1,
> + .regs = {
> + [RKCIF_MIPI_CTRL] = 0x20,
> + [RKCIF_MIPI_INTEN] = 0xa4,
> + [RKCIF_MIPI_INTSTAT] = 0xa8,
> + },
> + .regs_id = {
> + [RKCIF_ID0] = {
> + [RKCIF_MIPI_CTRL0] = 0x00,
> + [RKCIF_MIPI_CTRL1] = 0x04,
> + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x24,
> + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x2c,
> + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x34,
> + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x3c,
> + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x28,
> + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x30,
> + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x38,
> + [RKCIF_MIPI_FRAME1_VLW_UV] = 0x40,
> + [RKCIF_MIPI_CROP_START] = 0xbc,
> + },
> + [RKCIF_ID1] = {
> + [RKCIF_MIPI_CTRL0] = 0x08,
> + [RKCIF_MIPI_CTRL1] = 0x0c,
> + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x44,
> + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x4c,
> + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x54,
> + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x5c,
> + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x48,
> + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x50,
> + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x58,
> + [RKCIF_MIPI_FRAME1_VLW_UV] = 0x60,
> + [RKCIF_MIPI_CROP_START] = 0xc0,
> + },
> + [RKCIF_ID2] = {
> + [RKCIF_MIPI_CTRL0] = 0x10,
> + [RKCIF_MIPI_CTRL1] = 0x14,
> + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x64,
> + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x6c,
> + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x74,
> + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x7c,
> + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x68,
> + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x70,
> + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x78,
> + [RKCIF_MIPI_FRAME1_VLW_UV] = 0x80,
> + [RKCIF_MIPI_CROP_START] = 0xc4,
> + },
> + [RKCIF_ID3] = {
> + [RKCIF_MIPI_CTRL0] = 0x18,
> + [RKCIF_MIPI_CTRL1] = 0x1c,
> + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x84,
> + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x8c,
> + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x94,
> + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x9c,
> + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x88,
> + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x90,
> + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x98,
> + [RKCIF_MIPI_FRAME1_VLW_UV] = 0xa0,
> + [RKCIF_MIPI_CROP_START] = 0xc8,
> + },
> + },
> + .blocks = {
> + {
> + .offset = 0x80,
> + },
> + },
> +};
> +
> +static inline unsigned int rkcif_mipi_get_reg(struct rkcif_interface *interface,
> + unsigned int index)
> +{
> + struct rkcif_device *rkcif = interface->rkcif;
> + unsigned int block, offset, reg;
> +
> + block = interface->index - RKCIF_MIPI_BASE;
> +
> + if (WARN_ON(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
> + WARN_ON(index > RKCIF_MIPI_REGISTER_MAX))
> + return RKCIF_REGISTER_NOTSUPPORTED;
> +
> + offset = rkcif->match_data->mipi->blocks[block].offset;
> + reg = rkcif->match_data->mipi->regs[index];
> + if (reg == RKCIF_REGISTER_NOTSUPPORTED)
> + return reg;
> +
> + return offset + reg;
> +}
> +
> +static inline unsigned int rkcif_mipi_id_get_reg(struct rkcif_stream *stream,
> + unsigned int index)
> +{
> + struct rkcif_device *rkcif = stream->rkcif;
> + unsigned int block, id, offset, reg;
> +
> + block = stream->interface->index - RKCIF_MIPI_BASE;
> + id = stream->id;
> +
> + if (WARN_ON(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
> + WARN_ON(id > RKCIF_ID_MAX) ||
> + WARN_ON(index > RKCIF_MIPI_ID_REGISTER_MAX))
I think WARN_ON_ONCE() would be reasonable.
> + return RKCIF_REGISTER_NOTSUPPORTED;
> +
> + offset = rkcif->match_data->mipi->blocks[block].offset;
> + reg = rkcif->match_data->mipi->regs_id[id][index];
> + if (reg == RKCIF_REGISTER_NOTSUPPORTED)
> + return reg;
> +
> + return offset + reg;
> +}
> +
> +static inline __maybe_unused void
> +rkcif_mipi_write(struct rkcif_interface *interface, unsigned int index, u32 val)
> +{
> + unsigned int addr = rkcif_mipi_get_reg(interface, index);
> +
> + if (addr == RKCIF_REGISTER_NOTSUPPORTED)
> + return;
> +
> + writel(val, interface->rkcif->base_addr + addr);
> +}
> +
> +static inline __maybe_unused void
> +rkcif_mipi_stream_write(struct rkcif_stream *stream, unsigned int index,
> + u32 val)
> +{
> + unsigned int addr = rkcif_mipi_id_get_reg(stream, index);
> +
> + if (addr == RKCIF_REGISTER_NOTSUPPORTED)
> + return;
> +
> + writel(val, stream->rkcif->base_addr + addr);
> +}
> +
> +static inline __maybe_unused u32
> +rkcif_mipi_read(struct rkcif_interface *interface, unsigned int index)
> +{
> + unsigned int addr = rkcif_mipi_get_reg(interface, index);
> +
> + if (addr == RKCIF_REGISTER_NOTSUPPORTED)
> + return 0;
> +
> + return readl(interface->rkcif->base_addr + addr);
> +}
> +
> +static inline __maybe_unused u32
> +rkcif_mipi_stream_read(struct rkcif_stream *stream, unsigned int index)
> +{
> + unsigned int addr = rkcif_mipi_id_get_reg(stream, index);
> +
> + if (addr == RKCIF_REGISTER_NOTSUPPORTED)
> + return 0;
> +
> + return readl(stream->rkcif->base_addr + addr);
> +}
> +
> +static void rkcif_mipi_queue_buffer(struct rkcif_stream *stream,
> + unsigned int index)
> +{
> + struct rkcif_buffer *buffer = stream->buffers[index];
> + u32 frm_addr_y, frm_addr_uv;
> +
> + frm_addr_y = index ? RKCIF_MIPI_FRAME1_ADDR_Y :
> + RKCIF_MIPI_FRAME0_ADDR_Y;
> + frm_addr_uv = index ? RKCIF_MIPI_FRAME1_ADDR_UV :
> + RKCIF_MIPI_FRAME0_ADDR_UV;
> +
> + rkcif_mipi_stream_write(stream, frm_addr_y,
> + buffer->buff_addr[RKCIF_PLANE_Y]);
> + rkcif_mipi_stream_write(stream, frm_addr_uv,
> + buffer->buff_addr[RKCIF_PLANE_UV]);
> +}
> +
> +static int rkcif_mipi_start_streaming(struct rkcif_stream *stream)
> +{
> + struct rkcif_interface *interface = stream->interface;
> + const struct rkcif_output_fmt *active_out_fmt;
> + struct v4l2_subdev_state *state;
> + u32 ctrl0 = 0, ctrl1 = 0, int_temp = 0, int_mask = 0, vlw = 0;
> + u16 height, width;
> + int ret = -EINVAL;
> +
> + state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
> +
> + active_out_fmt = rkcif_stream_find_output_fmt(stream, false,
> + stream->pix.pixelformat);
> + if (!active_out_fmt)
> + goto out;
> +
> + height = stream->pix.height;
> + width = stream->pix.width;
> + /* TODO there may be different factors and/or alignment constraints */
> + vlw = ALIGN(width * 2, 8);
> +
> + ctrl0 |= active_out_fmt->mipi.dt << 10;
> + ctrl0 |= active_out_fmt->mipi.ctrl0_val;
> + ctrl0 |= RKCIF_MIPI_CTRL0_CROP_EN;
> + ctrl0 |= RKCIF_MIPI_CTRL0_CAP_EN;
> +
> + ctrl1 = RKCIF_XY_COORD(width, height);
> +
> + int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id);
> + int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id);
> +
> + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN);
> + int_temp |= int_mask;
> + rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp);
> +
> + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
> + int_temp &= ~int_mask;
> + rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp);
> +
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_Y, vlw);
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_Y, vlw);
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_UV, vlw);
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_UV, vlw);
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, 0x0);
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL1, ctrl1);
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, ctrl0);
> +
> + ret = 0;
> +
> +out:
> + v4l2_subdev_unlock_state(state);
> + return ret;
> +}
> +
> +static void rkcif_mipi_stop_streaming(struct rkcif_stream *stream)
> +{
> + struct rkcif_interface *interface = stream->interface;
> + struct v4l2_subdev_state *state;
> + u32 int_temp = 0, int_mask = 0;
> +
> + state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
> +
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, 0);
> +
> + int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id);
> + int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id);
> +
> + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN);
> + int_temp &= ~int_mask;
> + rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp);
> +
> + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
> + int_temp &= ~int_mask;
> + rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp);
> +
> + stream->stopping = false;
> +
> + v4l2_subdev_unlock_state(state);
> +}
> +
> +static void rkcif_mipi_set_crop(struct rkcif_stream *stream, u16 left, u16 top)
> +{
> + u32 val;
> +
> + val = RKCIF_XY_COORD(left, top);
> + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, val);
> +}
> +
> irqreturn_t rkcif_mipi_isr(int irq, void *ctx)
> {
> + struct device *dev = ctx;
> + struct rkcif_device *rkcif = dev_get_drvdata(dev);
> irqreturn_t ret = IRQ_NONE;
> + u32 intstat;
> +
> + for (int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
> + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
> + struct rkcif_interface *interface = &rkcif->interfaces[index];
> +
> + intstat = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
> + rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, intstat);
> +
> + for (int j = 0; j < interface->streams_num; j++) {
> + struct rkcif_stream *stream = &interface->streams[j];
> +
> + if (intstat & RKCIF_MIPI_INT_FRAME0_END(stream->id) ||
> + intstat & RKCIF_MIPI_INT_FRAME1_END(stream->id)) {
> + rkcif_stream_pingpong(stream);
> + ret = IRQ_HANDLED;
> + }
> + }
> + }
>
> return ret;
> }
>
> int rkcif_mipi_register(struct rkcif_device *rkcif)
> {
> + int ret, i;
> +
> + if (!rkcif->match_data->mipi)
> + return 0;
> +
> + for (i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
> + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
> + struct rkcif_interface *interface = &rkcif->interfaces[index];
> +
> + interface->index = index;
> + interface->type = RKCIF_IF_MIPI;
> + interface->in_fmts = mipi_in_fmts;
> + interface->in_fmts_num = ARRAY_SIZE(mipi_in_fmts);
> + interface->set_crop = rkcif_mipi_set_crop;
> + interface->streams_num = 0;
> + ret = rkcif_interface_register(rkcif, interface);
> + if (ret)
> + continue;
> +
> + for (int j = 0; j < 4; j++) {
Could you give a human-readable (macro) name for 4?
> + struct rkcif_stream *stream = &interface->streams[j];
> +
> + stream->id = j;
> + stream->interface = interface;
> + stream->out_fmts = mipi_out_fmts;
> + stream->out_fmts_num = ARRAY_SIZE(mipi_out_fmts);
> + stream->queue_buffer = rkcif_mipi_queue_buffer;
> + stream->start_streaming = rkcif_mipi_start_streaming;
> + stream->stop_streaming = rkcif_mipi_stop_streaming;
> + ret = rkcif_stream_register(rkcif, stream);
> + if (ret)
> + goto err;
> + interface->streams_num++;
> + }
> + }
> +
> return 0;
> +
> +err:
> + for (; i >= 0; i--) {
for (i++; i--; )
And you can make i unsigned. :-) Up to you. Same elsewhere, too.
> + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
> + struct rkcif_interface *interface = &rkcif->interfaces[index];
> +
> + for (int j = 0; j < interface->streams_num; j++)
> + rkcif_stream_unregister(&interface->streams[j]);
> +
> + rkcif_interface_unregister(interface);
> + }
> + return ret;
> }
>
> void rkcif_mipi_unregister(struct rkcif_device *rkcif)
> {
> + if (!rkcif->match_data->mipi)
> + return;
> +
> + for (int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
unsigned int i?
> + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
> + struct rkcif_interface *interface = &rkcif->interfaces[index];
> +
> + for (int j = 0; j < interface->streams_num; j++)
unsigned int j?
This applies elsewhere, too.
> + rkcif_stream_unregister(&interface->streams[j]);
> +
> + rkcif_interface_unregister(interface);
> + }
> }
> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
> index ee1a50a59505..48d04a60c750 100644
> --- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
> @@ -11,6 +11,8 @@
>
> #include "rkcif-common.h"
>
> +extern const struct rkcif_mipi_match_data rk3568_vicap_mipi_match_data;
> +
> int rkcif_mipi_register(struct rkcif_device *rkcif);
>
> void rkcif_mipi_unregister(struct rkcif_device *rkcif);
> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-common.h b/drivers/media/platform/rockchip/rkcif/rkcif-common.h
> index 32f6f0238656..99249a85048e 100644
> --- a/drivers/media/platform/rockchip/rkcif/rkcif-common.h
> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-common.h
> @@ -93,9 +93,14 @@ struct rkcif_output_fmt {
> u32 fourcc;
> u32 mbus_code;
> u8 cplanes;
> + u8 depth;
>
> union {
> u32 dvp_fmt_val;
> + struct {
> + u8 dt;
> + u32 ctrl0_val;
> + } mipi;
> };
> };
>
> @@ -183,6 +188,16 @@ struct rkcif_interface {
> void (*set_crop)(struct rkcif_stream *stream, u16 left, u16 top);
> };
>
> +struct rkcif_mipi_match_data {
> + unsigned int mipi_num;
> + unsigned int regs[RKCIF_MIPI_REGISTER_MAX];
> + unsigned int regs_id[RKCIF_ID_MAX][RKCIF_MIPI_ID_REGISTER_MAX];
> +
> + struct {
> + unsigned int offset;
> + } blocks[RKCIF_MIPI_MAX - RKCIF_MIPI_BASE];
> +};
> +
> struct rkcif_dvp_match_data {
> const struct rkcif_input_fmt *in_fmts;
> unsigned int in_fmts_num;
> @@ -198,6 +213,7 @@ struct rkcif_match_data {
> const char *const *clks;
> unsigned int clks_num;
> const struct rkcif_dvp_match_data *dvp;
> + const struct rkcif_mipi_match_data *mipi;
> };
>
> struct rkcif_device {
> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
> index 2f45229183f6..5cc4e458ffa1 100644
> --- a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
> @@ -49,6 +49,7 @@ static const struct rkcif_match_data rk3568_vicap_match_data = {
> .clks = rk3568_vicap_clks,
> .clks_num = ARRAY_SIZE(rk3568_vicap_clks),
> .dvp = &rk3568_vicap_dvp_match_data,
> + .mipi = &rk3568_vicap_mipi_match_data,
> };
>
> static const struct of_device_id rkcif_plat_of_match[] = {
> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-interface.c b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
> index 7131de68de2c..163ee9e2fc6f 100644
> --- a/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
> @@ -188,7 +188,10 @@ static int rkcif_interface_enable_streams(struct v4l2_subdev *sd,
> stream = &interface->streams[RKCIF_ID0];
> rkcif_interface_apply_crop(stream, state);
> } else {
> - /* TODO implement for MIPI */
> + for_each_active_route(&state->routing, route) {
> + stream = &interface->streams[route->sink_stream];
> + rkcif_interface_apply_crop(stream, state);
> + }
> }
>
> mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK,
> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-regs.h b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
> index 07fd64174e80..3d1f0c45c638 100644
> --- a/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
> @@ -30,7 +30,29 @@ enum rkcif_dvp_register_index {
> RKCIF_DVP_REGISTER_MAX
> };
>
> -#define RKCIF_REGISTER_NOTSUPPORTED 0x420000
> +enum rkcif_mipi_register_index {
> + RKCIF_MIPI_CTRL,
> + RKCIF_MIPI_INTEN,
> + RKCIF_MIPI_INTSTAT,
> + RKCIF_MIPI_REGISTER_MAX
> +};
> +
> +enum rkcif_mipi_id_register_index {
> + RKCIF_MIPI_CTRL0,
> + RKCIF_MIPI_CTRL1,
> + RKCIF_MIPI_FRAME0_ADDR_Y,
> + RKCIF_MIPI_FRAME0_ADDR_UV,
> + RKCIF_MIPI_FRAME0_VLW_Y,
> + RKCIF_MIPI_FRAME0_VLW_UV,
> + RKCIF_MIPI_FRAME1_ADDR_Y,
> + RKCIF_MIPI_FRAME1_ADDR_UV,
> + RKCIF_MIPI_FRAME1_VLW_Y,
> + RKCIF_MIPI_FRAME1_VLW_UV,
> + RKCIF_MIPI_CROP_START,
> + RKCIF_MIPI_ID_REGISTER_MAX
> +};
> +
> +#define RKCIF_REGISTER_NOTSUPPORTED 0x420000
>
> #define RKCIF_FETCH_Y(VAL) ((VAL) & 0x1fff)
Any other reason for macro target alignment than this is what the driver
uses? It'd be nice to clean it up but this is outside the scope of the set
IMO.
>
>
--
Regards,
Sakari Ailus
next prev parent reply other threads:[~2025-04-28 15:48 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-06 16:56 [PATCH v5 00/11] media: rockchip: add a driver for the rockchip camera interface Michael Riesch
2025-03-06 16:56 ` [PATCH v5 01/11] media: dt-bindings: media: video-interfaces: add defines for sampling modes Michael Riesch
2025-03-06 16:56 ` [PATCH v5 02/11] media: dt-bindings: media: add bindings for rockchip px30 vip Michael Riesch
2025-03-06 16:56 ` [PATCH v5 03/11] media: dt-bindings: media: add bindings for rockchip rk3568 vicap Michael Riesch
2025-03-07 7:51 ` Krzysztof Kozlowski
2025-03-07 9:49 ` Sakari Ailus
2025-04-28 8:11 ` Michael Riesch
2025-04-28 9:22 ` Laurent Pinchart
2025-04-28 9:48 ` Michael Riesch
2025-04-28 9:52 ` Laurent Pinchart
2025-03-06 16:56 ` [PATCH v5 04/11] media: dt-bindings: media: add bindings for rockchip mipi csi host Michael Riesch
2025-03-07 7:53 ` Krzysztof Kozlowski
2025-03-06 16:56 ` [PATCH v5 05/11] media: rockchip: add a driver for the rockchip camera interface Michael Riesch
2025-04-28 14:05 ` Markus Elfring
2025-04-28 15:41 ` Sakari Ailus
2025-04-29 16:08 ` Michael Riesch
2025-05-01 22:03 ` Sakari Ailus
2025-03-06 16:56 ` [PATCH v5 06/11] media: rockchip: rkcif: add driver for mipi csi-2 host Michael Riesch
2025-04-28 10:57 ` Sakari Ailus
2025-03-06 16:56 ` [PATCH v5 07/11] media: rockchip: rkcif: add support for mipi csi-2 receiver Michael Riesch
2025-04-28 15:40 ` Sakari Ailus [this message]
2025-03-06 16:56 ` [PATCH v5 08/11] arm64: dts: rockchip: add the vip node to px30 Michael Riesch
2025-03-06 16:56 ` [PATCH v5 09/11] arm64: dts: rockchip: add vicap node to rk356x Michael Riesch
2025-03-06 16:56 ` [PATCH v5 10/11] arm64: dts: rockchip: add mipi csi host " Michael Riesch
2025-03-06 16:56 ` [PATCH v5 11/11] arm64: dts: rockchip: enable vicap dvp on wolfvision pf5 io expander Michael Riesch
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aA-hWug1bpRR_qYh@kekkonen.localdomain \
--to=sakari.ailus@linux.intel.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=eagle.alexander923@gmail.com \
--cc=gerald.loacker@wolfvision.net \
--cc=heiko@sntech.de \
--cc=kever.yang@rock-chips.com \
--cc=krzk+dt@kernel.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=maxime.chevallier@bootlin.com \
--cc=mchehab@kernel.org \
--cc=mehdi.djait@linux.intel.com \
--cc=michael.riesch@wolfvision.net \
--cc=nicolas.dufresne@collabora.com \
--cc=p.zabel@pengutronix.de \
--cc=paulk@sys-base.io \
--cc=robh+dt@kernel.org \
--cc=robh@kernel.org \
--cc=sebastian.fricke@collabora.com \
--cc=sebastian.reichel@collabora.com \
--cc=theo.lebrun@bootlin.com \
--cc=thomas.petazzoni@bootlin.com \
--cc=val@packett.cool \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox