From patchwork Wed Apr 8 11:56:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 26514 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 52C86BDCBD for ; Wed, 8 Apr 2026 11:57:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EB86962E48; Wed, 8 Apr 2026 13:57:00 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="ZVOsSSeC"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="ZcF0J1ty"; dkim-atps=neutral Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 50AF062E4B for ; Wed, 8 Apr 2026 13:56:58 +0200 (CEST) Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6387K0mC2451717 for ; Wed, 8 Apr 2026 11:56:57 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=eYcVgvkZPAu uUBNRpArbAVWpqRz82YVRKf3jVRDuwr4=; b=ZVOsSSeCPHJ5PgXkHjaqlyRGVtb AFFG2KLIDPMIPV1tOIeVUfl+3NRR8GS1K3DfEuqIMYSGvaCajiOZo12/K/t+2gAe itMI7Kje87p5BYtaCD9z0O1oA9sY9++RPJVqScNJba9/vR9aa/PjWDBVd4Nz9fIx D6utqFVWb4R9oeltIKV/CC+ug+lP+stQcYVc2ejRUZvfvts4orPWHne3jLF2DkvM XPslHk4JCuKPQlW4n6aj4WFaN6NvNFpOUKS3DluPVLFf1czL+ImeivxtW9rywTqn DMCTXWdymLY7eR79dIiOHv11NCNKLFlsxt6d/B5/uFUgzXLSbAR+vvi1uow== Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ddae6ampm-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2026 11:56:57 +0000 (GMT) Received: by mail-qt1-f198.google.com with SMTP id d75a77b69052e-50d8ed08aa4so101260081cf.3 for ; Wed, 08 Apr 2026 04:56:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1775649416; x=1776254216; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eYcVgvkZPAuuUBNRpArbAVWpqRz82YVRKf3jVRDuwr4=; b=ZcF0J1tytZoJII+HmGJ+shHNWPsUoGbycCahSpibknIzpzuRlk5o/87tDFWGKcYKH3 m6ToU9MYauRhemkIyiIgJCvk+OP8fPi3AV6VIWrEwwLl8JPtZ0tEkYk3Ks0iPQKU8LKA yWQiPktbT81bID0AYZzELhdYdRIAAcMTWX3ZO08cu5Vpli1ESU3IFEfkoI2+p6GyY+vy ZawuWaCRG0bzC0yJpI82jEB1crRJ28rfHX/QHHxqx1BR9EDlcjwoWnz/bjFvrHzwvJW8 QHUhx+myeIHNQF9L8qTFj/rLTF/jvr8xgYhb2D7qLoYZPEB+4EsyzI/UaMiOyWAEguxc sbDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775649416; x=1776254216; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=eYcVgvkZPAuuUBNRpArbAVWpqRz82YVRKf3jVRDuwr4=; b=oNtzqOE6W8a79lV5pqvPjZp6IaAy0Mjk6vhnEJY8fM+tZvHhfR2USvXOuTM89UoCy4 9aRztwG4mpO52TlsbFneP/dXbG/kIJoVrfABHCaX8zTcJWXOU6AjIjN81YfsYmJ2Bgob fuHX8ILq8FsT+vduVGVOGTuwFHMVG1JruzGaTD7y0Q+5XYt6hApxf/fa9rK506HlLeyo G1fljH3M7eUjVs4HIeDeOxqcK7Kw5e1bshF7Tr6BgXUwM0RL9UJbwpSrn5kRolrbyZ1F /NBYvjqnAnYSrFj6OkDRhJMitY1Mvg1sljEi+olCnzH/xpPRRuYsgD+Y23rM005+RSCT tojw== X-Gm-Message-State: AOJu0YxXRX8MW79lje8IilZr3agIbGhImLWOJrtT+VMA8yI1cA+fqN1+ 9rsLLBaIK21RxlzSIAT6maeGra3F+dQkgab7hk0XoSXE8Dr2ZwkP0SASwXJqglSIcgQHh+24LVt jo3Irz7yHah7wqd/17Ew5mUHToCB4L6yXFCm+N3Hl1/xCO1jO5TwN2nEXc7VXVf0bz7HULAlvCb q9c9kNlyyX X-Gm-Gg: AeBDietxwf8UA1tOh5M7yBj4HiMRP3AxyC7oJ9LFzfOehC93Jji4NpqBA/spuVZsbvZ kp8GrGLh4UjWPPJwtIgOgk9cNElv7xZ6d3wtWaJvPXGY1htIxICKtTT1gRUZLl10qEfG8xTd5tY x1RWH2Y8+O9193LXIxK+88S7NYR2uLAk3WfZ0BGpLiAjvOJO/ekAEQGsplZUbnRvjKXSodggDSQ R/U9f+APIyAvMQQUwv+J24jGELVpoodLpejBw2oQTzSUbqXy2cntz5bhHAOsTdHS9XsCpiHLAs/ ybrh969zb+pkXpb2WyIss96r9AgAP8EBf5reOiii2GnovdFXqoyn0gUo/1ZHO6omVbJ7xUMtDzT Gr6b/KjRZZlbqHrrJTrpkJ0fWWaizPE0orE33DZxPNMPgIaMGrj9g+ehksKAWL68A3/Oyhy21e2 AI81sMsmK3qhyS3PzPhIzhiWay3dv09Taw X-Received: by 2002:ac8:7fce:0:b0:50d:8dec:eb47 with SMTP id d75a77b69052e-50d8decef8amr171604051cf.45.1775649416007; Wed, 08 Apr 2026 04:56:56 -0700 (PDT) X-Received: by 2002:ac8:7fce:0:b0:50d:8dec:eb47 with SMTP id d75a77b69052e-50d8decef8amr171603801cf.45.1775649415493; Wed, 08 Apr 2026 04:56:55 -0700 (PDT) Received: from t14s (2001-1c00-0c32-7800-07d4-cca3-ec08-7ac7.cable.dynamic.v6.ziggo.nl. [2001:1c00:c32:7800:7d4:cca3:ec08:7ac7]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-66e7b5ffa64sm3158932a12.21.2026.04.08.04.56.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 04:56:54 -0700 (PDT) From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Loic Poulain , Hans de Goede Subject: [RFC 3/3] camss: Add Offline Processing Engine ISP support Date: Wed, 8 Apr 2026 13:56:45 +0200 Message-ID: <20260408115645.12487-4-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260408115645.12487-1-johannes.goede@oss.qualcomm.com> References: <20260408115645.12487-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNDA4MDExMCBTYWx0ZWRfXzyCayiRkei0B 2MG5Nnuj/7dwnxPxrLa2ap8SWjzxYjejVdhWUlpr7W32NcUHe237hqq0i/cgkauJ19yMO+S58KP v7NMdePB1nKc5xJPDhzV8J/TaQrwhvVGnqog1HGEZRthgmcbd7wUsa9BnsZ6quYpGTKmx08Rim7 LriL2+PMQGxXRAt094aEAYEWJpWUuchr2qZn8Kqt+eG0+f6N1dgQW2y5MsE/bVOMd2ZpV3pAdBv sbvdq1srXPRnXwhXMj/wdn3pjqJNuuMvvo2yJBcdwDPgKtCNVbVPOf3C6XflvRz5LbkPISFkXZL osjpnOR/bitHqXC1dlfEP35lKwNNJhvkbno9EfyGXotG0gz3EW7aSesbGrY+slQep2Ug43fCjmz tNE3aDwH9q5FCX+3NOVh9vKqWJ+cJHEaazvW2/sxg9tph8120HLAKPHpdyGjsVUTSHLkC6L/wEC nn1CJAsG99e6JTVMMaw== X-Proofpoint-GUID: MTotPAWfK0DtegnAyOb0Ydaq25anYu9k X-Proofpoint-ORIG-GUID: MTotPAWfK0DtegnAyOb0Ydaq25anYu9k X-Authority-Analysis: v=2.4 cv=K4AS2SWI c=1 sm=1 tr=0 ts=69d64289 cx=c_pps a=mPf7EqFMSY9/WdsSgAYMbA==:117 a=xqWC_Br6kY4A:10 a=A5OVakUREuEA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=gowsoOTTUOVcmtlkKump:22 a=VwQbUJbxAAAA:8 a=EUspDBNiAAAA:8 a=rV9jgqLbh9YbgK17brIA:9 a=dawVfQjAaf238kedN5IG:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293, Aquarius:18.0.1143, Hydra:6.1.51, FMLib:17.12.100.49 definitions=2026-04-08_03,2026-04-08_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 lowpriorityscore=0 clxscore=1015 phishscore=0 malwarescore=0 spamscore=0 bulkscore=0 adultscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2604010000 definitions=main-2604080110 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This adds support for the OPE through the RFC OPE M2M kernel driver posted upstream recently. The M2M OPE kernel driver is mainly a RFC driver and this driver will need to be changed into a proper ISP driver with e.g. a second /dev/video# input node for passing parameter-buffers to the ISP. Likewise this libcamera OPE support should mostly be seen as a proof of concept of the CamssIsp virtual base class abstraction and this will need to change / evolve to also grow an IPA and parameter buffer support as the kernel driver evolves. Link: https://lore.kernel.org/linux-media/20260323125824.211615-1-loic.poulain@oss.qualcomm.com/ Signed-off-by: Hans de Goede --- .../converter/converter_v4l2_m2m.cpp | 1 + src/libcamera/pipeline/camss/camss.cpp | 12 +- .../pipeline/camss/camss_isp_ope.cpp | 229 ++++++++++++++++++ src/libcamera/pipeline/camss/camss_isp_ope.h | 59 +++++ src/libcamera/pipeline/camss/meson.build | 1 + 5 files changed, 298 insertions(+), 4 deletions(-) create mode 100644 src/libcamera/pipeline/camss/camss_isp_ope.cpp create mode 100644 src/libcamera/pipeline/camss/camss_isp_ope.h diff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp index ffba0434e..b705b56e8 100644 --- a/src/libcamera/converter/converter_v4l2_m2m.cpp +++ b/src/libcamera/converter/converter_v4l2_m2m.cpp @@ -818,6 +818,7 @@ bool V4L2M2MConverter::supportsRequests() static std::initializer_list compatibles = { "mtk-mdp", "pxp", + "qcom-camss-ope", }; REGISTER_CONVERTER("v4l2_m2m", V4L2M2MConverter, compatibles) diff --git a/src/libcamera/pipeline/camss/camss.cpp b/src/libcamera/pipeline/camss/camss.cpp index 90d7b681e..51951ab20 100644 --- a/src/libcamera/pipeline/camss/camss.cpp +++ b/src/libcamera/pipeline/camss/camss.cpp @@ -38,6 +38,7 @@ #include "camss_csi.h" #include "camss_frames.h" #include "camss_isp.h" +#include "camss_isp_ope.h" #include "camss_isp_soft.h" namespace libcamera { @@ -571,10 +572,13 @@ bool PipelineHandlerCamss::match(DeviceEnumerator *enumerator) data->delayedCtrls_ = std::make_unique(sensor->device(), params); - data->isp_ = std::make_unique(this, sensor, &data->controlInfo_); - if (!data->isp_->isValid()) { - LOG(Camss, Error) << "Failed to create software ISP"; - continue; + data->isp_ = CamssIspOpe::match(this, enumerator, sensor, &data->controlInfo_); + if (data->isp_ == nullptr) { + data->isp_ = std::make_unique(this, sensor, &data->controlInfo_); + if (!data->isp_->isValid()) { + LOG(Camss, Error) << "Failed to create software ISP"; + continue; + } } data->isp_->inputBufferReady.connect(data->csi_.get(), diff --git a/src/libcamera/pipeline/camss/camss_isp_ope.cpp b/src/libcamera/pipeline/camss/camss_isp_ope.cpp new file mode 100644 index 000000000..7d9a831cb --- /dev/null +++ b/src/libcamera/pipeline/camss/camss_isp_ope.cpp @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Qualcomm CAMSS OPE ISP class + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "camss_isp_ope.h" + +#include + +#include +#include +#include +#include + +#include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/converter.h" +#include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/media_device.h" +#include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/v4l2_subdevice.h" +#include "libcamera/internal/v4l2_videodevice.h" + +namespace libcamera { + +LOG_DECLARE_CATEGORY(Camss) + +/** + * \class CamssIspOpe + * \brief CAMSS ISP class for the Offline Processing Engine (OPE) ISP + */ + +/** + * \brief Constructs CamssIspOpe object + * \param[in] pipe The pipeline handler in use + * \param[in] sensor Pointer to the CameraSensor instance owned by the pipeline + * \param[out] ControlInfoMap to which to add ISP provided controls + */ +CamssIspOpe::CamssIspOpe([[maybe_unused]] PipelineHandler *pipe, const CameraSensor *sensor, [[maybe_unused]] ControlInfoMap *ispControls) + : sensor_(sensor) +{ +#if 0 + swIsp_ = std::make_unique(pipe, sensor, ispControls); + + swIsp_->ispStatsReady.connect(this, + [&](uint32_t frame, uint32_t bufferId) { + statsReady.emit(frame, bufferId); + }); + swIsp_->metadataReady.connect(this, + [&](uint32_t frame, const ControlList &metadata) { + metadataReady.emit(frame, metadata); + }); + swIsp_->setSensorControls.connect(this, + [&](const ControlList &sensorControls) { + setSensorControls.emit(sensorControls); + }); +#endif +} + +CamssIspOpe::~CamssIspOpe() = default; + +bool CamssIspOpe::isValid() +{ + return true; +} + +StreamConfiguration CamssIspOpe::generateConfiguration(const StreamConfiguration &raw) const +{ + /* Converters support the same size-ranges for all output formats */ + std::vector pixelFormats = converter_->formats(raw.pixelFormat); + SizeRange sizes = converter_->sizes(raw.size); + + if (sizes.max.isNull() || pixelFormats.empty()) + return {}; + + std::vector sizesVector = { sizes }; + std::map> formats; + + for (unsigned int i = 0; i < pixelFormats.size(); i++) + formats[pixelFormats[i]] = sizesVector; + + StreamConfiguration cfg{ StreamFormats{ formats } }; + cfg.size = sizes.max; + cfg.pixelFormat = pixelFormats[0]; + cfg.bufferCount = kBufferCount; + + return cfg; +} + +namespace { + +/* + * \todo copy-pasted from src/libcamera/pipeline/simple/simple.cpp turn this + * into a member of SizeRange ? + */ +static Size adjustSize(const Size &requestedSize, const SizeRange &supportedSizes) +{ + ASSERT(supportedSizes.min <= supportedSizes.max); + + if (supportedSizes.min == supportedSizes.max) + return supportedSizes.max; + + unsigned int hStep = supportedSizes.hStep; + unsigned int vStep = supportedSizes.vStep; + + if (hStep == 0) + hStep = supportedSizes.max.width - supportedSizes.min.width; + if (vStep == 0) + vStep = supportedSizes.max.height - supportedSizes.min.height; + + Size adjusted = requestedSize.boundedTo(supportedSizes.max) + .expandedTo(supportedSizes.min); + + return adjusted.shrunkBy(supportedSizes.min) + .alignedDownTo(hStep, vStep) + .grownBy(supportedSizes.min); +} + +} /* namespace */ + +StreamConfiguration CamssIspOpe::validate(const StreamConfiguration &raw, const StreamConfiguration &req) const +{ + StreamConfiguration cfg; + + std::vector formats = converter_->formats(raw.pixelFormat); + SizeRange sizes = converter_->sizes(raw.size); + + cfg.size = adjustSize(req.size, sizes); + + if (cfg.size.isNull() || formats.empty()) + return {}; + + for (unsigned int i = 0; i < formats.size(); i++) { + if (formats[i] == req.pixelFormat) + cfg.pixelFormat = req.pixelFormat; + } + + if (!cfg.pixelFormat.isValid()) + cfg.pixelFormat = formats[0]; + + std::tie(cfg.stride, cfg.frameSize) = + converter_->strideAndFrameSize(cfg.pixelFormat, cfg.size); + + cfg.bufferCount = std::max(kBufferCount, req.bufferCount); + cfg.setStream(const_cast(&outStream_)); + + return cfg; +} + +int CamssIspOpe::configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg) +{ + std::vector> outputCfgs; + outputCfgs.push_back(outputCfg); + + int ret = converter_->configure(inputCfg, outputCfgs); + if (ret) + return ret; + + converter_->inputBufferReady.connect(this, + [&](FrameBuffer *f) { inputBufferReady.emit(f); }); + converter_->outputBufferReady.connect(this, + [&](FrameBuffer *f) { + // HACK FIXME + metadataReady.emit(f->metadata().sequence, {}); + outputBufferReady.emit(f); + }); + + return 0; +} + +int CamssIspOpe::exportOutputBuffers(const Stream *stream, unsigned int count, + std::vector> *buffers) +{ + return converter_->exportBuffers(stream, count, buffers); +} + +void CamssIspOpe::queueBuffers(Request *request, FrameBuffer *input) +{ + std::map outputs; + for (const auto &[stream, outbuffer] : request->buffers()) { + if (stream == &outStream_) + outputs[stream] = outbuffer; + } + + // swIsp_->queueRequest(request->sequence(), request->controls()); + converter_->queueBuffers(input, outputs); +} + +void CamssIspOpe::processStats([[maybe_unused]] const uint32_t frame, [[maybe_unused]] const uint32_t bufferId, + [[maybe_unused]] const ControlList &sensorControls) +{ + // swIsp_->processStats(frame, bufferId, sensorControls); +} + +int CamssIspOpe::start() +{ + return converter_->start(); +} + +void CamssIspOpe::stop() +{ + converter_->stop(); +} + +std::unique_ptr CamssIspOpe::match(PipelineHandler *pipe, + DeviceEnumerator *enumerator, + const CameraSensor *sensor, + ControlInfoMap *ispControls) +{ + std::unique_ptr ope = std::make_unique(pipe, sensor, ispControls); + + DeviceMatch opeDm("qcom-camss-ope"); + + ope->opeMediaDev_ = pipe->acquireMediaDevice(enumerator, opeDm); + if (!ope->opeMediaDev_) + return nullptr; + + ope->converter_ = ConverterFactoryBase::create(ope->opeMediaDev_); + if (!ope->converter_) + return nullptr; + + LOG(Camss, Info) << "Using OPE for " << sensor->entity()->name(); + + return ope; +} + +} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/camss/camss_isp_ope.h b/src/libcamera/pipeline/camss/camss_isp_ope.h new file mode 100644 index 000000000..4324e4c0a --- /dev/null +++ b/src/libcamera/pipeline/camss/camss_isp_ope.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Qualcomm CAMSS OPE ISP class + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#pragma once + +#include +#include + +#include "camss_isp.h" + +namespace libcamera { + +class CameraSensor; +class ControlInfoMap; +class Converter; +class DeviceEnumerator; +class MediaDevice; +class PipelineHandler; +class SoftwareIsp; + +class CamssIspOpe : public CamssIsp +{ +public: + static std::unique_ptr match(PipelineHandler *pipe, + DeviceEnumerator *enumerator, + const CameraSensor *sensor, + ControlInfoMap *ispControls); + + CamssIspOpe(PipelineHandler *pipe, const CameraSensor *sensor, ControlInfoMap *ispControls); + ~CamssIspOpe() override; + + bool isValid() override; + + StreamConfiguration generateConfiguration(const StreamConfiguration &raw) const override; + StreamConfiguration validate(const StreamConfiguration &raw, const StreamConfiguration &req) const override; + int configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg) override; + + int exportOutputBuffers(const Stream *stream, unsigned int count, + std::vector> *buffers) override; + void queueBuffers(Request *request, FrameBuffer *input) override; + + void processStats(const uint32_t frame, const uint32_t bufferId, + const ControlList &sensorControls) override; + + int start() override; + void stop() override; + +private: + std::shared_ptr opeMediaDev_; + std::unique_ptr converter_; + const CameraSensor *sensor_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/camss/meson.build b/src/libcamera/pipeline/camss/meson.build index 047559789..36478cf7d 100644 --- a/src/libcamera/pipeline/camss/meson.build +++ b/src/libcamera/pipeline/camss/meson.build @@ -5,5 +5,6 @@ libcamera_internal_sources += files([ 'camss_csi.cpp', 'camss_frames.cpp', 'camss_isp.cpp', + 'camss_isp_ope.cpp', 'camss_isp_soft.cpp', ])