From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 381AF1E5718 for ; Thu, 1 May 2025 00:49:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.48 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746060544; cv=none; b=qmBIuQKKmhsV2/QTck5awxdkOJgJsgxd2q9zvYTRD69CRN9tK6EgwaGVVbMPEymwbXqOCrH5WVN3DNLvj4+eYHpteKVuHcRGmLwWADrqqlbnHZlUfWwYe9kVTL7wXkw5RYu43/JwCSazcopHKld/nrHyr9x6GNdW9ce+qIz6IqE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746060544; c=relaxed/simple; bh=DR2vOXtFEs+LK/dWpb2CzJAIaDTLRmBq+dsGh8wJUgI=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=dUTZlotxwg0iJa8zG47SN5wmaqazLJxZjVumfCMKRBp3QJLZgODhQ1nNGiqiWrQPi52V54y0x3gC6jm+5GLluMDM4VCwQKTKEvF0qIzklXiLO1ZZp7P5qF3imng5pBWO14dLPUb2m6xQH++7BW5aEIP3758Nq7NDcduXxVbcOnk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=d/H6TlCn; arc=none smtp.client-ip=209.85.221.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="d/H6TlCn" Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-39c1ef4ae3aso293646f8f.1 for ; Wed, 30 Apr 2025 17:49:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1746060539; x=1746665339; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=pYvU8LGI/LvuV5/ZHSGbVwvOXcT9Aj8dP7lTePS1R6g=; b=d/H6TlCnnUHkf/50VutSzet0p01KQS4PjzMKwpxX0yIv2FaRQGwrA+/y5yuieuhV4y 7fh9/NIlYXb709gRLkhYlJfjKMWONnBFEHTPnorcJ0Bpe7eWAgUQuuWEciPGHuP8Vvzv hz1KUIdNgz0gk35X27OJl1iOpcLcKsp/3VgzTudZqO6LnnNVcQvFp6p/KM1Q7m8jyHWi 1TiRPV6ioND9Nr11FLtpB5d/2Y9uRYTLCQjREIZv6evavzhrsDy4H8mNFAdz9qXoRaP8 oGbYmT+B2IoDz0nOdWGDEGCf+hjwmNKtoY4xA0/Qlu85Bcy0StgI0iOhzUVhEiPDe/5K WtDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746060539; x=1746665339; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=pYvU8LGI/LvuV5/ZHSGbVwvOXcT9Aj8dP7lTePS1R6g=; b=TuJvRJbD2VivMIyFZJ6m2m2i/iKEjEga76DC20C7C7E1hRFJGFc8+8pc+q/xG/uzIm rI1RhuAh0X0wcPJLNTQlEKVvVpbo3hWiwRNdBbOWtT04SzZf7Ja6N5DGGEuIpC74N0yA wH39/wRMHnsEM0KGjjJhlG83b+n5O06OydfdZvbTTaLqsz1BXxwFFxvB2dCweGUjmeqr J4NShS/E0gtmqdcchSiFz3KemT+7IK16wF6FYaVeaIFc0PzlxRw2CLJT+5p7SwmBg9hJ apxvdfcbqDt5b7STN8bFwBR64NCkxAyBMu69av5SjPBPU1y75RnLO9KkGF7Wf46ZzWns oHDg== X-Forwarded-Encrypted: i=1; AJvYcCVmN3Bf5WTceLstJ7zY8dH3wle2EiK00EtoJu91znwZI2XTbOpKWR6kzUI6YoRs90ZUQH85KFTpnyX2@vger.kernel.org X-Gm-Message-State: AOJu0YysYK9GK+F6/4IYUxm4cnTyqzjYhChY3rHviwO71VqE5I07oVNU rL4QGT1ikARVXRC8+vq+tqFwlFnJZfZQfhmhQ9H8aZKnzso26tNAS933VzrnUDg= X-Gm-Gg: ASbGncvc5qFMa3ctbY3SqNLVN2EYd2vr8Bbrj/ijnqZ6NnfIzqXia4cwJ1JaYp7eFAp ht+/3Ap28eqUhaY8ZMXBbj2XP3qljKMiJGkvPjdsA2D7AgKGu055P+7nTvTD5jTMFG1sOzU/j2h JzyUQsz0X1nXyWmG7hFHoCgThjLF6E5N4720NmEciKDVYruXVtlilPct7r6IYy5OK3j0BiD/zQY 2mkCpCf7LLSclDRBzHOh7WfMNoJSKuejRhhRNkyXAgl5X43yNNsaUQJl6rIlQejHJgKY32a7JkN FXzwrLCfakLXIK8O2Vac4AXIeS2OvZTZjZs2iq4beThKY5VBl0gRH5G8PV9V/g1iribhLcxy3TD IVwM1cA== X-Google-Smtp-Source: AGHT+IExm5QKDWTtBCtGiEApqcGxgGU3IZnUc5zsY5J466n61GIPpDfm8B+SHfKQgJR/mIvjcKs6Bg== X-Received: by 2002:a05:6000:2411:b0:3a0:7afd:cbfd with SMTP id ffacd0b85a97d-3a094034df4mr341931f8f.7.1746060539398; Wed, 30 Apr 2025 17:48:59 -0700 (PDT) Received: from [192.168.0.35] (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a073c8cd7fsm18310368f8f.1.2025.04.30.17.48.56 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 30 Apr 2025 17:48:58 -0700 (PDT) Message-ID: <243932d3-65da-4934-8cea-bc0e41bf21b3@linaro.org> Date: Thu, 1 May 2025 01:48:56 +0100 Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v6 08/13] media: rockchip: rkcif: add support for mipi csi-2 capture To: michael.riesch@collabora.com, Mehdi Djait , Maxime Chevallier , =?UTF-8?Q?Th=C3=A9o_Lebrun?= , Gerald Loacker , Thomas Petazzoni , Laurent Pinchart , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Heiko Stuebner , Kever Yang , Nicolas Dufresne , Sebastian Reichel , Collabora Kernel Team , Paul Kocialkowski , Alexander Shiyan , Val Packett , Rob Herring , Philipp Zabel , Sakari Ailus Cc: 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, Michael Riesch References: <20240220-rk3568-vicap-v6-0-d2f5fbee1551@collabora.com> <20240220-rk3568-vicap-v6-8-d2f5fbee1551@collabora.com> Content-Language: en-US From: Bryan O'Donoghue In-Reply-To: <20240220-rk3568-vicap-v6-8-d2f5fbee1551@collabora.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 30/04/2025 10:15, Michael Riesch via B4 Relay wrote: > From: Michael Riesch > > The RK3568 Video Capture (VICAP) unit features a MIPI CSI-2 capture > interface 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 > Signed-off-by: Michael Riesch > --- > .../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..5e1c624e17c6 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 > */ > > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > #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 rkcif_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_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) || > + WARN_ON_ONCE(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_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) || > + WARN_ON_ONCE(id > RKCIF_ID_MAX) || > + WARN_ON_ONCE(index > RKCIF_MIPI_ID_REGISTER_MAX)) > + 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 < RKCIF_ID_MAX; j++) { > + 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--) { > + 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++) { > + 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); > + } > } > diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h > index ee1a50a59505..1248af70bdab 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 rkcif_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 62fb3580eec5..d0d929648f21 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 2dcd35771fc9..1d8815156c46 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 = &rkcif_rk3568_vicap_dvp_match_data, > + .mipi = &rkcif_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 0ec524586594..f598a62f9fbd 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) > > > -- > 2.39.5 > > > This looks pretty clean to me. Reviewed-by: Bryan O'Donoghue