From patchwork Tue Jan 16 09:17:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 19410 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9D16FC328C for ; Tue, 16 Jan 2024 09:18:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 39299628B6; Tue, 16 Jan 2024 10:18:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705396715; bh=M1cBQW1K2xGU/8SjiXVt7UtdIp5cFeWCtJ1uMDJ8Sgk=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=ytLY/epQ9f0R7mc56+hqVf7IoIwKdW+9vcNsixhzH+IT4rHKFntZOVIzwUZVHBgcS PkrcSJAlXDdLpqSnu31wyMkidBgJ8n0SYxHkZASmZz+sqTrt/hmaJ0Sjv+et5paftS kfFlrVG/LPpQzZhef+n/156PGdJvbfL9StxAoPcDD1V/mZNTKsxORQqiol9HGUjzMX diQZlVzRso9bAcHj3fgBhK7Wgbo+OguUF/gqB563NizePfptax8cwrAchOajhfUp1/ b8Q10vKsZiEnnbgPocQ2XsdbBzl7/QqlBb7GD32yCO9/MWEr79y3lyRm6MUPKZdY8a +59CeOJKMW8jg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3AD34628AD for ; Tue, 16 Jan 2024 10:18:32 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="KBf4+UOs"; dkim-atps=neutral Received: from pyrite.hamster-moth.ts.net (h175-177-049-156.catv02.itscom.jp [175.177.49.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A367A3D9; Tue, 16 Jan 2024 10:17:22 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1705396643; bh=M1cBQW1K2xGU/8SjiXVt7UtdIp5cFeWCtJ1uMDJ8Sgk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KBf4+UOsoO9oH9hjHg3knCmJ89wefpiRwtnAjSmgPvRZn/GaUGZdACb+F37FXNzcr NmPhRvdTygY3QujrUtWeWPJjOug/dI2rRaT8Hz4XZKIPDPJ4Ylj6r9iXKTGZxgpPTC H/WVzdiPfwfMMa1AThmpnplUjh/Sscfr2fx5xBbY= To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Jan 2024 18:17:52 +0900 Message-Id: <20240116091754.100654-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240116091754.100654-1-paul.elder@ideasonboard.com> References: <20240116091754.100654-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/3] ipa: rkisp1: Add IMX8MP_V10 version X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paul Elder via libcamera-devel From: Paul Elder Reply-To: Paul Elder Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add the version number for IMX8MP_V10, and initialize values for it. Signed-off-by: Paul Elder Reviewed-by: Kieran Bingham --- include/linux/rkisp1-config.h | 1 + src/ipa/rkisp1/rkisp1.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/include/linux/rkisp1-config.h b/include/linux/rkisp1-config.h index ec7cde8cd..0ed3dca8f 100644 --- a/include/linux/rkisp1-config.h +++ b/include/linux/rkisp1-config.h @@ -185,6 +185,7 @@ enum rkisp1_cif_isp_version { RKISP1_V11, RKISP1_V12, RKISP1_V13, + IMX8MP_V10, }; enum rkisp1_cif_isp_histogram_mode { diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 6544c925b..aa73b7db1 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -128,6 +128,7 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision, /* \todo Add support for other revisions */ switch (hwRevision) { case RKISP1_V10: + case IMX8MP_V10: hwHistBinNMax_ = RKISP1_CIF_ISP_HIST_BIN_N_MAX_V10; hwGammaOutMaxSamples_ = RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10; hwHistogramWeightGridsSize_ = RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE_V10; From patchwork Tue Jan 16 09:17:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 19411 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A50E8C323E for ; Tue, 16 Jan 2024 09:18:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0460F628DA; Tue, 16 Jan 2024 10:18:36 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705396716; bh=WjV4LZEMIYq5SMiBjkSsdtl5PoZahZ4ttfK6GttpLw8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=h7YWLytyDVP1rWl0apmjPLSk0wRWbIA3fjIdA6kJtCvwcAoSmpdGmr5eedfw/tyqM vY5hMhyg9W5QZovVe7rdnDgLm8VLYluORO9E4Jj8znL0uxKyTXXjezhX0u8uSq4Vbv UlZmxP4z2vYY3Cian4r3FL/z7B7Es6gKlrANBEdJMFoa9lMrVef/ESZOlkrqgUrXLl FTwfD9KlRhUR0leQY4gvZl1B2DFXeAuxjOtkwbUB6dg0RWXQZAQJTOnnJb0mGcceNS TCAFhCMDB6K+nOEsn0q/GojtSeAzhO0p3juyG84ZjEAvaabNRCxY31iYiXdUinYeDz L6p1u/lPFv05A== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DBAAC628AD for ; Tue, 16 Jan 2024 10:18:33 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="lpUHgxsF"; dkim-atps=neutral Received: from pyrite.hamster-moth.ts.net (h175-177-049-156.catv02.itscom.jp [175.177.49.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 440AA3D9; Tue, 16 Jan 2024 10:17:24 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1705396645; bh=WjV4LZEMIYq5SMiBjkSsdtl5PoZahZ4ttfK6GttpLw8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lpUHgxsFZWOjwi78ZrJgyR0DV6sEkHdFD7Yti5z+peg6ZRlQ6ByZlU/5P/V3vFFfN Nij79APKGzG4i7deaRcg914tBBmMbMeylCB5PJpLuTexh3mRVACYXDh+/xqiPAlGLV AuzEKs8X6Kv2IwdmoZ5vhFNwynj8UBSyak1wUWec= To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Jan 2024 18:17:53 +0900 Message-Id: <20240116091754.100654-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240116091754.100654-1-paul.elder@ideasonboard.com> References: <20240116091754.100654-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/3] pipeline: rkisp1: Fix validation when sensor max is larger than ISP input X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paul Elder via libcamera-devel From: Paul Elder Reply-To: Paul Elder Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If the maximum sensor output size is larger than the maximum ISP input size, the maximum sensor size could be selected and the pipeline would fail with an EPIPE. Fix this by clamping the sensor size to the ISP input size at validation time. Signed-off-by: Paul Elder Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 17 ++++++++++-- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 26 +++++++++---------- src/libcamera/pipeline/rkisp1/rkisp1_path.h | 4 ++- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 586b46d64..fb67ba8f4 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -1202,11 +1202,24 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) if (param_->open() < 0) return false; + /* + * Retrieve ISP maximum input size for config validation in the path + * classes + */ + Size ispMaxInSize = { 0, 0 }; + V4L2Subdevice::Formats ispFormats = isp_->formats(0); + for (const auto &[mbus, sizes] : ispFormats) { + for (const auto &size : sizes) { + if (ispMaxInSize < size.max) + ispMaxInSize = size.max; + } + } + /* Locate and open the ISP main and self paths. */ - if (!mainPath_.init(media_)) + if (!mainPath_.init(media_, ispMaxInSize)) return false; - if (hasSelfPath_ && !selfPath_.init(media_)) + if (hasSelfPath_ && !selfPath_.init(media_, ispMaxInSize)) return false; mainPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::bufferReady); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index b62b645ca..eaab7e857 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -62,7 +62,7 @@ RkISP1Path::RkISP1Path(const char *name, const Span &formats, { } -bool RkISP1Path::init(MediaDevice *media) +bool RkISP1Path::init(MediaDevice *media, const Size &ispMaxInSize) { std::string resizer = std::string("rkisp1_resizer_") + name_ + "path"; std::string video = std::string("rkisp1_") + name_ + "path"; @@ -76,6 +76,7 @@ bool RkISP1Path::init(MediaDevice *media) return false; populateFormats(); + ispMaxInSize_ = ispMaxInSize; link_ = media->link("rkisp1_isp", 2, resizer, 0); if (!link_) @@ -172,7 +173,9 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, /* Add all the RAW sizes the sensor can produce for this code. */ for (const auto &rawSize : sensor->sizes(mbusCode)) { if (rawSize.width > maxResolution_.width || - rawSize.height > maxResolution_.height) + rawSize.height > maxResolution_.height || + rawSize.width > ispMaxInSize_.width || + rawSize.height > ispMaxInSize_.height) continue; streamFormats[format].push_back({ rawSize, rawSize }); @@ -275,8 +278,9 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, if (!found) cfg->pixelFormat = isRaw ? rawFormat : formats::NV12; - Size minResolution; - Size maxResolution; + Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) + .boundedTo(resolution); + Size minResolution = minResolution_.expandedToAspectRatio(resolution); if (isRaw) { /* @@ -287,16 +291,10 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, V4L2SubdeviceFormat sensorFormat = sensor->getFormat({ mbusCode }, cfg->size); - minResolution = sensorFormat.size; - maxResolution = sensorFormat.size; - } else { - /* - * Adjust the size based on the sensor resolution and absolute - * limits of the ISP. - */ - minResolution = minResolution_.expandedToAspectRatio(resolution); - maxResolution = maxResolution_.boundedToAspectRatio(resolution) - .boundedTo(resolution); + if (!sensorFormat.size.isNull()) { + minResolution = sensorFormat.size.boundedTo(ispMaxInSize_); + maxResolution = sensorFormat.size.boundedTo(ispMaxInSize_); + } } cfg->size.boundTo(maxResolution); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index cd77957ee..c96bd5557 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -35,7 +35,7 @@ public: RkISP1Path(const char *name, const Span &formats, const Size &minResolution, const Size &maxResolution); - bool init(MediaDevice *media); + bool init(MediaDevice *media, const Size &ispMaxInSize); int setEnabled(bool enable) { return link_->setEnabled(enable); } bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; } @@ -77,6 +77,8 @@ private: std::unique_ptr resizer_; std::unique_ptr video_; MediaLink *link_; + + Size ispMaxInSize_; }; class RkISP1MainPath : public RkISP1Path From patchwork Tue Jan 16 09:17:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 19412 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 781B7C32BC for ; Tue, 16 Jan 2024 09:18:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 10CAD628EC; Tue, 16 Jan 2024 10:18:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705396720; bh=y5hJ9bKEkJDrsNyEjY73xRUJguA4iG6nxTtKXqgBf8A=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=oe1wkcE/wgpetT8lliJvFl3jV/RTMgTrFesTYE7/CpQoVS2mrEp1pG6ENFsivsKNN 4RXME5ImWflWUK6vrWa8nitos/P9JwnGJ2aZP+wdsZOKczTlpLzbVlOkGP+JCQkRMT m5+hGJSVVP0y7sEKJL7WMy5iALxw1dbzv1LwtTgeDVeR8wIIB9o0dVqNIogf2/l9GW T7ZpDXn2lgzIGCw0wSmYg7T2CThVvIxA1bXEUCK776K8FNO/DYu41YlGuE/Zew3kl8 yf6wNMwBKv926v6+vfvlLswwzDbE83ZtxrxZUxR0YMPzobnWCCdMif7pher14A+Z+Z /bYAScSUoWN8g== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C9306628D8 for ; Tue, 16 Jan 2024 10:18:35 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Jo1ekhYa"; dkim-atps=neutral Received: from pyrite.hamster-moth.ts.net (h175-177-049-156.catv02.itscom.jp [175.177.49.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DF1A415B5; Tue, 16 Jan 2024 10:17:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1705396646; bh=y5hJ9bKEkJDrsNyEjY73xRUJguA4iG6nxTtKXqgBf8A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Jo1ekhYa6f5W/4Z9DgB3zlZAuQ6JjvTVnEXfMWk4jBcDx22crIMVQR8EfXxroLo7l BSFnQco4sDOJXVaJ7SQUbDGUZDxaM7klsTdw7E8gFXD5fTnDBlKCo5DZow2kD3v452 f/78Op4ZnlC7Nnc7SIRyXQ5H9YP4ebqJAZAe/Vn4= To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Jan 2024 18:17:54 +0900 Message-Id: <20240116091754.100654-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240116091754.100654-1-paul.elder@ideasonboard.com> References: <20240116091754.100654-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/3] pipeline: rkisp1: Plumb SensorConfiguration X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paul Elder via libcamera-devel From: Paul Elder Reply-To: Paul Elder Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support to the rkisp1 pipeline handler for validating and configuring SensorConfiguration. Signed-off-by: Paul Elder --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 97 ++++++++++++++++--- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 37 +++++-- src/libcamera/pipeline/rkisp1/rkisp1_path.h | 3 +- 3 files changed, 115 insertions(+), 22 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index fb67ba8f4..74da9c1b1 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -128,7 +128,8 @@ public: const Transform &combinedTransform() { return combinedTransform_; } private: - bool fitsAllPaths(const StreamConfiguration &cfg); + bool fitsAllPaths(const StreamConfiguration &cfg, + std::optional sensorBPP); /* * The RkISP1CameraData instance is guaranteed to be valid as long as the @@ -448,17 +449,18 @@ RkISP1CameraConfiguration::RkISP1CameraConfiguration(Camera *camera, data_ = data; } -bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg) +bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg, + std::optional sensorBPP) { const CameraSensor *sensor = data_->sensor_.get(); StreamConfiguration config; config = cfg; - if (data_->mainPath_->validate(sensor, &config) != Valid) + if (data_->mainPath_->validate(sensor, &config, sensorBPP) != Valid) return false; config = cfg; - if (data_->selfPath_ && data_->selfPath_->validate(sensor, &config) != Valid) + if (data_->selfPath_ && data_->selfPath_->validate(sensor, &config, sensorBPP) != Valid) return false; return true; @@ -475,6 +477,24 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() status = validateColorSpaces(ColorSpaceFlag::StreamsShareColorSpace); + /* + * For the sensor configuration, default to the first supported bit + * depth for the sensor configuration if an unsupported one is + * supplied. + */ + std::optional bitDepth; + if (sensorConfig) { + bitDepth = sensorConfig->bitDepth; + if (bitDepth != 8 && bitDepth != 10 && bitDepth != 12) { + V4L2SubdeviceFormat format = {}; + format.mbus_code = data_->sensor_->mbusCodes().at(0); + + sensorConfig->bitDepth = format.bitsPerPixel(); + bitDepth = sensorConfig->bitDepth; + status = Adjusted; + } + } + /* Cap the number of entries to the available streams. */ if (config_.size() > pathCount) { config_.resize(pathCount); @@ -510,7 +530,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() */ std::vector order(config_.size()); std::iota(order.begin(), order.end(), 0); - if (config_.size() == 2 && fitsAllPaths(config_[0])) + if (config_.size() == 2 && fitsAllPaths(config_[0], bitDepth)) std::reverse(order.begin(), order.end()); bool mainPathAvailable = true; @@ -521,7 +541,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Try to match stream without adjusting configuration. */ if (mainPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->mainPath_->validate(sensor, &tryCfg) == Valid) { + if (data_->mainPath_->validate(sensor, &tryCfg, bitDepth) == Valid) { mainPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->mainPathStream_)); @@ -531,7 +551,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() if (selfPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->selfPath_->validate(sensor, &tryCfg) == Valid) { + if (data_->selfPath_->validate(sensor, &tryCfg, bitDepth) == Valid) { selfPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->selfPathStream_)); @@ -542,7 +562,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Try to match stream allowing adjusting configuration. */ if (mainPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->mainPath_->validate(sensor, &tryCfg) == Adjusted) { + if (data_->mainPath_->validate(sensor, &tryCfg, bitDepth) == Adjusted) { mainPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->mainPathStream_)); @@ -553,7 +573,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() if (selfPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->selfPath_->validate(sensor, &tryCfg) == Adjusted) { + if (data_->selfPath_->validate(sensor, &tryCfg, bitDepth) == Adjusted) { selfPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->selfPathStream_)); @@ -570,28 +590,75 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Select the sensor format. */ PixelFormat rawFormat; + Size rawSize; Size maxSize; for (const StreamConfiguration &cfg : config_) { const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { rawFormat = cfg.pixelFormat; + rawSize = cfg.size; + } + /* path->validate binds this to a sensor-supported resolution */ maxSize = std::max(maxSize, cfg.size); } + if (rawFormat.isValid() && sensorConfig) { + if (sensorConfig->outputSize != rawSize) { + sensorConfig->outputSize = rawSize; + status = Adjusted; + } + + const PixelFormatInfo &info = PixelFormatInfo::info(rawFormat); + if (sensorConfig->bitDepth != info.bitsPerPixel) { + sensorConfig->bitDepth = info.bitsPerPixel; + status = Adjusted; + } + } else if (!rawFormat.isValid() && sensorConfig) { + /* + * TODO Handle this properly taking into account the upscaling + * capabilities and dual ISP mode (for the i.MX8MP). + * + * x1.5 should be a reasonable hardcoded ballpark for now. + */ + double factor = 1.5; + Size before = sensorConfig->outputSize; + Size upscaleLimit = { + static_cast(maxSize.width / factor), + static_cast(maxSize.height / factor) + }; + + if (sensorConfig->outputSize < upscaleLimit) + sensorConfig->outputSize = maxSize; + + if (before != sensorConfig->outputSize) + status = Adjusted; + + /* No need to validate bpp for non-raw */ + } + std::vector mbusCodes; + Size size = maxSize; if (rawFormat.isValid()) { mbusCodes = { rawFormats.at(rawFormat) }; + size = rawSize; + } else if (sensorConfig) { + for (const auto &value : rawFormats) { + const PixelFormatInfo &info = PixelFormatInfo::info(value.first); + if (info.bitsPerPixel == sensorConfig->bitDepth) + mbusCodes.push_back(value.second); + } } else { std::transform(rawFormats.begin(), rawFormats.end(), std::back_inserter(mbusCodes), [](const auto &value) { return value.second; }); } - sensorFormat_ = sensor->getFormat(mbusCodes, maxSize); + sensorFormat_ = sensor->getFormat(mbusCodes, size); + /* This should never happen if sensorConfig is valid */ if (sensorFormat_.size.isNull()) sensorFormat_.size = sensor->resolution(); @@ -730,7 +797,13 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) V4L2SubdeviceFormat format = config->sensorFormat(); LOG(RkISP1, Debug) << "Configuring sensor with " << format; - ret = sensor->setFormat(&format, config->combinedTransform()); + if (config->sensorConfig) { + ret = sensor->applyConfiguration(*config->sensorConfig, + config->combinedTransform(), &format); + } else { + ret = sensor->setFormat(&format, config->combinedTransform()); + } + if (ret < 0) return ret; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index eaab7e857..a598b289b 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -220,7 +220,8 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, } CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, - StreamConfiguration *cfg) + StreamConfiguration *cfg, + std::optional sensorBPP) { const std::vector &mbusCodes = sensor->mbusCodes(); const Size &resolution = sensor->resolution(); @@ -231,10 +232,15 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, /* * Validate the pixel format. If the requested format isn't supported, * default to either NV12 (all versions of the ISP are guaranteed to - * support NV12 on both the main and self paths) if the requested format - * is not a raw format, or to the supported raw format with the highest - * bits per pixel otherwise. + * support NV12 on both the main and self paths) if the requested + * format is not a raw format, or otherwise to a supported raw format + * with the same number of bits per pixel, or to maximum bits per pixel + * if the same is not supported. */ + const PixelFormatInfo &formatInfo = PixelFormatInfo::info(cfg->pixelFormat); + unsigned int reqRawBitsPerPixel = formatInfo.bitsPerPixel; + PixelFormat reqRawFormat; + unsigned int rawBitsPerPixel = 0; PixelFormat rawFormat; bool found = false; @@ -250,12 +256,22 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, continue; /* - * Store the raw format with the highest bits per pixel - * for later usage. + * If the bits per pixel is supplied from the sensor + * configuration, choose a raw format that complies + * with it. Otherwise store the raw format with the + * highest bits per pixel for later usage. */ - if (info.bitsPerPixel > rawBitsPerPixel) { - rawBitsPerPixel = info.bitsPerPixel; - rawFormat = format; + if (sensorBPP) { + if (info.bitsPerPixel == sensorBPP) + rawFormat = format; + } else { + if (info.bitsPerPixel == reqRawBitsPerPixel) + reqRawFormat = format; + + if (info.bitsPerPixel > rawBitsPerPixel) { + rawBitsPerPixel = info.bitsPerPixel; + rawFormat = format; + } } } @@ -265,6 +281,9 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, } } + if (reqRawFormat.isValid()) + rawFormat = reqRawFormat; + bool isRaw = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding == PixelFormatInfo::ColourEncodingRAW; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index c96bd5557..784bcea77 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -44,7 +44,8 @@ public: const Size &resolution, StreamRole role); CameraConfiguration::Status validate(const CameraSensor *sensor, - StreamConfiguration *cfg); + StreamConfiguration *cfg, + std::optional sensorBPP); int configure(const StreamConfiguration &config, const V4L2SubdeviceFormat &inputFormat);