From patchwork Thu Jun 30 13:38:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16466 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 C6B2CC3279 for ; Thu, 30 Jun 2022 13:39:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B38116569F; Thu, 30 Jun 2022 15:39:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596372; bh=D4LZqFIaG7h5yKFiw2jMPZjigf1V/xSbPCU74OIl17I=; 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=e9AaHM0wf+KNb/1RxUSkPgxKf1kaJHLwMmSWLzsvGIbEF1KMMiXfVOoJaRTv4AHvo pSzIBSFYyJ4JgppWfoP+fbwyiFEw3JIRF6zmyM7hrDrgU7/ZyE2JrWh7oV/i6LFbJu 6WZ7nPnGmICMUgvyAPJ+YgblMQ5LDV3mzvPIMwqGnjD0wvqIfTOe/8d4wm4wpcgVR1 xVGyZnHgFF20aXyYqS5CRTH7YiDpNRQQwCgl/bCYDrnFvScTgqsG2rzYEzrJyD9uDp DrdGj6NUkCE6uXiKD0XidpY0iDPzgy9QckELT1wUkjpM8i/4+RWgfaYJu3eK4R5gUR 1bG8ST3im/5qg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 91EC465657 for ; Thu, 30 Jun 2022 15:39:28 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id A59BA24000E; Thu, 30 Jun 2022 13:39:27 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:47 +0200 Message-Id: <20220630133902.321099-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 08/23] libcamera: camera_sensor: Initialize controls 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: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Initialize the control interface of the CameraSensor class by registering the control limits for controls::internal::ExposureTime, controls::internal::FrameDuration and controls::internal::AnalogueGain. Update the CameraSensor controls in the CameraSensor::updateControlInfo() function after having updated the subdevice V4L2 controls. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/internal/camera_sensor.h | 3 + src/libcamera/camera_sensor/camera_sensor.cpp | 90 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index 2a850dedc0aa..1eab5e9d53f0 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -63,6 +63,7 @@ public: V4L2Subdevice *device() { return subdev_.get(); } const ControlList &properties() const { return properties_; } + const ControlInfoMap &controls() const { return controls_; } int sensorInfo(IPACameraSensorInfo *info) const; void updateControlInfo(); @@ -81,6 +82,7 @@ private: void initStaticProperties(); void initTestPatternModes(); int initProperties(); + int updateControls(); int applyTestPatternMode(controls::draft::TestPatternModeEnum mode); int discoverAncillaryDevices(); @@ -104,6 +106,7 @@ private: const BayerFormat *bayerFormat_; ControlList properties_; + ControlInfoMap controls_; std::unique_ptr focusLens_; std::unique_ptr helper_; diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index 26cfa7d0f65a..976d34aaf876 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -22,6 +22,7 @@ #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/camera_lens.h" #include "libcamera/internal/camera_sensor_properties.h" +#include "libcamera/internal/control_ids.h" #include "libcamera/internal/formats.h" #include "libcamera/internal/sysfs.h" @@ -180,6 +181,10 @@ int CameraSensor::init() return -ENODEV; } + ret = updateControls(); + if (ret) + return ret; + ret = discoverAncillaryDevices(); if (ret) return ret; @@ -455,6 +460,84 @@ int CameraSensor::initProperties() return 0; } +int CameraSensor::updateControls() +{ + if (!bayerFormat_) + return 0; + + ControlInfoMap::Map controlsMap; + + /* The subdev driver has been validate already, the controls are there! */ + ControlList subdevControls = subdev_->getControls({ V4L2_CID_PIXEL_RATE, + V4L2_CID_HBLANK }); + uint64_t pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get(); + uint32_t hblank = subdevControls.get(V4L2_CID_HBLANK).get(); + + /* Assume the sensor has a single source pad #0. */ + V4L2SubdeviceFormat subdevFormat; + subdev_->getFormat(0, &subdevFormat); + + const ControlInfoMap &subdevControlsInfo = subdev_->controls(); + + /* + * Compute controls::ExposureTime limits by using line length and pixel + * rate converted to microseconds. Use the V4L2_CID_EXPOSURE control to + * get exposure min, max and default and convert it from lines to + * microseconds. + */ + uint32_t lineLength = subdevFormat.size.width + hblank; + double lineDuration = lineLength / (pixelRate / 1000000.0F); + const ControlInfo &v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE); + int32_t minExposure = v4l2Exposure.min().get() * lineDuration; + int32_t maxExposure = v4l2Exposure.max().get() * lineDuration; + int32_t defExposure = v4l2Exposure.def().get() * lineDuration; + + controlsMap[&controls::internal::ExposureTime] = + ControlInfo(minExposure, maxExposure, defExposure); + + /* + * Compute the frame duration limits. + * + * The frame length is computed assuming a fixed line length combined + * with the vertical frame sizes. + */ + const ControlInfo &v4l2VBlank = subdevControlsInfo.at(V4L2_CID_VBLANK); + std::array frameHeights{ + v4l2VBlank.min().get() + subdevFormat.size.height, + v4l2VBlank.max().get() + subdevFormat.size.height, + v4l2VBlank.def().get() + subdevFormat.size.height, + }; + + std::array frameDurations; + for (unsigned int i = 0; i < frameHeights.size(); ++i) { + uint64_t frameSize = lineLength * frameHeights[i]; + frameDurations[i] = frameSize / (pixelRate / 1000000.0F); + } + + controlsMap[&controls::internal::FrameDuration] = + ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]); + + /* + * Analogue gain values. + * + * Translate the V4L2 analogue gain, expressed in sensor-specific + * gain codes, and translate them to analogue gain values. + * + * \todo: CameraSensorHelper returns a double; there's no ControlValue + * overload for the double type. + */ + const ControlInfo &v4l2AGain = subdevControlsInfo.at(V4L2_CID_ANALOGUE_GAIN); + controlsMap[&controls::internal::AnalogueGain] = + ControlInfo(static_cast(helper_->gain(v4l2AGain.min().get())), + static_cast(helper_->gain(v4l2AGain.max().get())), + static_cast(helper_->gain(v4l2AGain.def().get()))); + + controls_ = ControlInfoMap(std::move(controlsMap), + controls::internal::controls); + + return 0; +} + /** * \brief Check for and initialise any ancillary devices * @@ -815,6 +898,12 @@ int CameraSensor::setV4L2Controls(ControlList *ctrls) * \return The list of camera sensor properties */ +/** + * \fn CameraSensor::controls() + * \brief Retrieve the map of the camera sensor controls limits + * \return The map of camera sensor control information + */ + /** * \brief Assemble and return the camera sensor info * \param[out] info The camera sensor info @@ -910,6 +999,7 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const void CameraSensor::updateControlInfo() { subdev_->updateControlInfo(); + updateControls(); } /**