[{"id":23700,"web_url":"https://patchwork.libcamera.org/comment/23700/","msgid":"<165662983944.1516045.18119707270912255664@Monstersaurus>","date":"2022-06-30T22:57:19","subject":"Re: [libcamera-devel] [PATCH v3 08/23] libcamera: camera_sensor:\n\tInitialize controls","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Jacopo Mondi via libcamera-devel (2022-06-30 14:38:47)\n> Initialize the control interface of the CameraSensor class by\n> registering the control limits for controls::internal::ExposureTime,\n> controls::internal::FrameDuration and controls::internal::AnalogueGain.\n> \n> Update the CameraSensor controls in the CameraSensor::updateControlInfo()\n> function after having updated the subdevice V4L2 controls.\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  include/libcamera/internal/camera_sensor.h    |  3 +\n>  src/libcamera/camera_sensor/camera_sensor.cpp | 90 +++++++++++++++++++\n>  2 files changed, 93 insertions(+)\n> \n> diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\n> index 2a850dedc0aa..1eab5e9d53f0 100644\n> --- a/include/libcamera/internal/camera_sensor.h\n> +++ b/include/libcamera/internal/camera_sensor.h\n> @@ -63,6 +63,7 @@ public:\n>         V4L2Subdevice *device() { return subdev_.get(); }\n>  \n>         const ControlList &properties() const { return properties_; }\n> +       const ControlInfoMap &controls() const { return controls_; }\n>         int sensorInfo(IPACameraSensorInfo *info) const;\n>  \n>         void updateControlInfo();\n> @@ -81,6 +82,7 @@ private:\n>         void initStaticProperties();\n>         void initTestPatternModes();\n>         int initProperties();\n> +       int updateControls();\n>         int applyTestPatternMode(controls::draft::TestPatternModeEnum mode);\n>         int discoverAncillaryDevices();\n>  \n> @@ -104,6 +106,7 @@ private:\n>         const BayerFormat *bayerFormat_;\n>  \n>         ControlList properties_;\n> +       ControlInfoMap controls_;\n>  \n>         std::unique_ptr<CameraLens> focusLens_;\n>         std::unique_ptr<CameraSensorHelper> helper_;\n> diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp\n> index 26cfa7d0f65a..976d34aaf876 100644\n> --- a/src/libcamera/camera_sensor/camera_sensor.cpp\n> +++ b/src/libcamera/camera_sensor/camera_sensor.cpp\n> @@ -22,6 +22,7 @@\n>  #include \"libcamera/internal/bayer_format.h\"\n>  #include \"libcamera/internal/camera_lens.h\"\n>  #include \"libcamera/internal/camera_sensor_properties.h\"\n> +#include \"libcamera/internal/control_ids.h\"\n>  #include \"libcamera/internal/formats.h\"\n>  #include \"libcamera/internal/sysfs.h\"\n>  \n> @@ -180,6 +181,10 @@ int CameraSensor::init()\n>                 return -ENODEV;\n>         }\n>  \n> +       ret = updateControls();\n> +       if (ret)\n> +               return ret;\n> +\n>         ret = discoverAncillaryDevices();\n>         if (ret)\n>                 return ret;\n> @@ -455,6 +460,84 @@ int CameraSensor::initProperties()\n>         return 0;\n>  }\n>  \n> +int CameraSensor::updateControls()\n> +{\n> +       if (!bayerFormat_)\n> +               return 0;\n> +\n> +       ControlInfoMap::Map controlsMap;\n> +\n> +       /* The subdev driver has been validate already, the controls are there! */\n\n/validate/validated/\n\n> +       ControlList subdevControls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,\n> +                                                           V4L2_CID_HBLANK });\n> +       uint64_t pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();\n> +       uint32_t hblank = subdevControls.get(V4L2_CID_HBLANK).get<int32_t>();\n> +\n> +       /*  Assume the sensor has a single source pad #0. */\n\n/*  Assume/* Assume/\ndouble space can be single.\n\n> +       V4L2SubdeviceFormat subdevFormat;\n> +       subdev_->getFormat(0, &subdevFormat);\n> +\n> +       const ControlInfoMap &subdevControlsInfo = subdev_->controls();\n> +\n> +       /*\n> +        * Compute controls::ExposureTime limits by using line length and pixel\n> +        * rate converted to microseconds. Use the V4L2_CID_EXPOSURE control to\n> +        * get exposure min, max and default and convert it from lines to\n> +        * microseconds.\n> +        */\n> +       uint32_t lineLength = subdevFormat.size.width + hblank;\n> +       double lineDuration = lineLength / (pixelRate / 1000000.0F);\n> +       const ControlInfo &v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE);\n> +       int32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;\n> +       int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;\n> +       int32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;\n> +\n> +       controlsMap[&controls::internal::ExposureTime] =\n> +               ControlInfo(minExposure, maxExposure, defExposure);\n> +\n> +       /*\n> +        * Compute the frame duration limits.\n> +        *\n> +        * The frame length is computed assuming a fixed line length combined\n> +        * with the vertical frame sizes.\n> +        */\n> +       const ControlInfo &v4l2VBlank = subdevControlsInfo.at(V4L2_CID_VBLANK);\n\nDoes this need to be refreshed from the subdev?\n\n> +       std::array<uint32_t, 3> frameHeights{\n> +               v4l2VBlank.min().get<int32_t>() + subdevFormat.size.height,\n> +               v4l2VBlank.max().get<int32_t>() + subdevFormat.size.height,\n> +               v4l2VBlank.def().get<int32_t>() + subdevFormat.size.height,\n> +       };\n> +\n> +       std::array<int64_t, 3> frameDurations;\n> +       for (unsigned int i = 0; i < frameHeights.size(); ++i) {\n> +               uint64_t frameSize = lineLength * frameHeights[i];\n> +               frameDurations[i] = frameSize / (pixelRate / 1000000.0F);\n> +       }\n> +\n> +       controlsMap[&controls::internal::FrameDuration] =\n> +               ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]);\n> +\n> +       /*\n> +        * Analogue gain values.\n> +        *\n> +        * Translate the V4L2 analogue gain, expressed in sensor-specific\n> +        * gain codes, and translate them to analogue gain values.\n> +        *\n> +        * \\todo: CameraSensorHelper returns a double; there's no ControlValue\n> +        * overload for the double type.\n> +        */\n> +       const ControlInfo &v4l2AGain = subdevControlsInfo.at(V4L2_CID_ANALOGUE_GAIN);\n> +       controlsMap[&controls::internal::AnalogueGain] =\n> +               ControlInfo(static_cast<float>(helper_->gain(v4l2AGain.min().get<int32_t>())),\n> +                           static_cast<float>(helper_->gain(v4l2AGain.max().get<int32_t>())),\n> +                           static_cast<float>(helper_->gain(v4l2AGain.def().get<int32_t>())));\n> +\n> +       controls_ = ControlInfoMap(std::move(controlsMap),\n> +                                  controls::internal::controls);\n> +\n> +       return 0;\n> +}\n> +\n>  /**\n>   * \\brief Check for and initialise any ancillary devices\n>   *\n> @@ -815,6 +898,12 @@ int CameraSensor::setV4L2Controls(ControlList *ctrls)\n>   * \\return The list of camera sensor properties\n>   */\n>  \n> +/**\n> + * \\fn CameraSensor::controls()\n> + * \\brief Retrieve the map of the camera sensor controls limits\n> + * \\return The map of camera sensor control information\n> + */\n> +\n>  /**\n>   * \\brief Assemble and return the camera sensor info\n>   * \\param[out] info The camera sensor info\n> @@ -910,6 +999,7 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const\n>  void CameraSensor::updateControlInfo()\n>  {\n>         subdev_->updateControlInfo();\n> +       updateControls();\n\nAha - that answers my vblank question I think...\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n>  }\n>  \n>  /**\n> -- \n> 2.36.1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 396EFBE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 30 Jun 2022 22:57:25 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9141F65633;\n\tFri,  1 Jul 2022 00:57:24 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9C59D60412\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri,  1 Jul 2022 00:57:22 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 23C9525C;\n\tFri,  1 Jul 2022 00:57:22 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1656629844;\n\tbh=Iin9LqomMMwb8ibdM44Kzi0ORwcTwCfwLsuwXDn/WgY=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=vXfONuG6AvZ5tt6iC/gmpcH59ieJsJvwkzeBvDJWLZNQCgMN3VwcJGQvRa6Bypg1z\n\tp29di/LjTGaIPTRGCcbneHSnIyc61MMC5u+q5K6Um47JVxQC2aGJY1Pd20m6mxCqJO\n\toRUM3IeguUCSKVwrVwSjSc1g6BxxcZyNmb8HgGpJbkLkgJ3VouFN216zspJEZPVz4j\n\tBJdySkuyPxZNsBx4OOqDoGxju1+Xs5jFIOa48d/1m8VQUQ1ZccYAqZJGscJdmVQ8dG\n\t0lGPFbkzW755BPreg9FFSgopoKZdNXr0I598/K8aUL0IAx2i8BLGGt/Qtrz1c+0+Ft\n\tlhU+LaioR9/Pw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1656629842;\n\tbh=Iin9LqomMMwb8ibdM44Kzi0ORwcTwCfwLsuwXDn/WgY=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=uYyONIIPnhI513yWE9DhhQytt9NXdmGd/LFlt/ETBGh4RMz8p570b+b+oO2Ubd4NZ\n\txzuL3tpUcj/P8CiMP0HVM+e5AbWQ6RBlSWL/4Rl34T4vhf+gF9V/ieHkyZU6xlxMOx\n\tH61aX7PGLX05kiorjB+8sWtyQGDPq/pvVNaJbfkM="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"uYyONIIP\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20220630133902.321099-9-jacopo@jmondi.org>","References":"<20220630133902.321099-1-jacopo@jmondi.org>\n\t<20220630133902.321099-9-jacopo@jmondi.org>","To":"Jacopo Mondi <jacopo@jmondi.org>, libcamera-devel@lists.libcamera.org","Date":"Thu, 30 Jun 2022 23:57:19 +0100","Message-ID":"<165662983944.1516045.18119707270912255664@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v3 08/23] libcamera: camera_sensor:\n\tInitialize controls","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]