[libcamera-devel,v2,1/1] libcamera: ipa: raspberrypi: Add support for imx519 sensor
diff mbox series

Message ID 20211020132334.2199-2-david.plowman@raspberrypi.com
State Accepted
Commit 5004d8a969330c52449e6840bbef6552cfa8ee1a
Headers show
Series
  • Support for imx519
Related show

Commit Message

David Plowman Oct. 20, 2021, 1:23 p.m. UTC
From: Arducam info <info@arducam.com>

The necessary tuning file and CamHelper is added for the imx519 sensor.

The imx519 is a 16MP rolling shutter sensor. To enable
it, please add

dtoverlay=imx519

to the /boot/config.txt file and reboot the Pi.

Signed-off-by: Lee Jackson <info@arducam.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>

---
 src/ipa/raspberrypi/cam_helper_imx519.cpp | 185 ++++++++++++
 src/ipa/raspberrypi/data/imx519.json      | 338 ++++++++++++++++++++++
 src/ipa/raspberrypi/data/meson.build      |   1 +
 src/ipa/raspberrypi/meson.build           |   1 +
 4 files changed, 525 insertions(+)
 create mode 100644 src/ipa/raspberrypi/cam_helper_imx519.cpp
 create mode 100644 src/ipa/raspberrypi/data/imx519.json

Comments

Naushir Patuck Oct. 20, 2021, 1:47 p.m. UTC | #1
Hi Lee and David,

Thank you for your work.

On Wed, 20 Oct 2021 at 14:23, David Plowman <david.plowman@raspberrypi.com>
wrote:

> From: Arducam info <info@arducam.com>
>
> The necessary tuning file and CamHelper is added for the imx519 sensor.
>
> The imx519 is a 16MP rolling shutter sensor. To enable
> it, please add
>
> dtoverlay=imx519
>
> to the /boot/config.txt file and reboot the Pi.
>
> Signed-off-by: Lee Jackson <info@arducam.com>
> Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
>

Reviewed-by: Naushir Patuck <naush@raspberrypi.com>


>
> ---
>  src/ipa/raspberrypi/cam_helper_imx519.cpp | 185 ++++++++++++
>  src/ipa/raspberrypi/data/imx519.json      | 338 ++++++++++++++++++++++
>  src/ipa/raspberrypi/data/meson.build      |   1 +
>  src/ipa/raspberrypi/meson.build           |   1 +
>  4 files changed, 525 insertions(+)
>  create mode 100644 src/ipa/raspberrypi/cam_helper_imx519.cpp
>  create mode 100644 src/ipa/raspberrypi/data/imx519.json
>
> diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp
> b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> new file mode 100644
> index 00000000..eaf24982
> --- /dev/null
> +++ b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> @@ -0,0 +1,185 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * Based on cam_helper_imx477.cpp
> + * Copyright (C) 2020, Raspberry Pi (Trading) Limited
> + *
> + * cam_helper_imx519.cpp - camera helper for imx519 sensor
> + * Copyright (C) 2021, Arducam Technology co., Ltd.
> + */
> +
> +#include <assert.h>
> +#include <cmath>
> +#include <stddef.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +#include <libcamera/base/log.h>
> +
> +#include "cam_helper.hpp"
> +#include "md_parser.hpp"
> +
> +using namespace RPiController;
> +using namespace libcamera;
> +using libcamera::utils::Duration;
> +
> +namespace libcamera {
> +LOG_DECLARE_CATEGORY(IPARPI)
> +}
> +
> +/*
> + * We care about two gain registers and a pair of exposure registers.
> Their
> + * I2C addresses from the Sony IMX519 datasheet:
> + */
> +constexpr uint32_t expHiReg = 0x0202;
> +constexpr uint32_t expLoReg = 0x0203;
> +constexpr uint32_t gainHiReg = 0x0204;
> +constexpr uint32_t gainLoReg = 0x0205;
> +constexpr uint32_t frameLengthHiReg = 0x0340;
> +constexpr uint32_t frameLengthLoReg = 0x0341;
> +constexpr std::initializer_list<uint32_t> registerList =
> +       { expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg,
> frameLengthLoReg  };
> +
> +class CamHelperImx519 : public CamHelper
> +{
> +public:
> +       CamHelperImx519();
> +       uint32_t GainCode(double gain) const override;
> +       double Gain(uint32_t gain_code) const override;
> +       void Prepare(libcamera::Span<const uint8_t> buffer, Metadata
> &metadata) override;
> +       uint32_t GetVBlanking(Duration &exposure, Duration
> minFrameDuration,
> +                             Duration maxFrameDuration) const override;
> +       void GetDelays(int &exposure_delay, int &gain_delay,
> +                      int &vblank_delay) const override;
> +       bool SensorEmbeddedDataPresent() const override;
> +
> +private:
> +       /*
> +        * Smallest difference between the frame length and integration
> time,
> +        * in units of lines.
> +        */
> +       static constexpr int frameIntegrationDiff = 32;
> +       /* Maximum frame length allowable for long exposure calculations.
> */
> +       static constexpr int frameLengthMax = 0xffdc;
> +       /* Largest long exposure scale factor given as a left shift on the
> frame length. */
> +       static constexpr int longExposureShiftMax = 7;
> +
> +       void PopulateMetadata(const MdParser::RegisterMap &registers,
> +                             Metadata &metadata) const override;
> +};
> +
> +CamHelperImx519::CamHelperImx519()
> +       : CamHelper(std::make_unique<MdParserSmia>(registerList),
> frameIntegrationDiff)
> +{
> +}
> +
> +uint32_t CamHelperImx519::GainCode(double gain) const
> +{
> +       return static_cast<uint32_t>(1024 - 1024 / gain);
> +}
> +
> +double CamHelperImx519::Gain(uint32_t gain_code) const
> +{
> +       return 1024.0 / (1024 - gain_code);
> +}
> +
> +void CamHelperImx519::Prepare(libcamera::Span<const uint8_t> buffer,
> Metadata &metadata)
> +{
> +       MdParser::RegisterMap registers;
> +       DeviceStatus deviceStatus;
> +
> +       if (metadata.Get("device.status", deviceStatus)) {
> +               LOG(IPARPI, Error) << "DeviceStatus not found from
> DelayedControls";
> +               return;
> +       }
> +
> +       parseEmbeddedData(buffer, metadata);
> +
> +       /*
> +        * The DeviceStatus struct is first populated with values obtained
> from
> +        * DelayedControls. If this reports frame length is >
> frameLengthMax,
> +        * it means we are using a long exposure mode. Since the long
> exposure
> +        * scale factor is not returned back through embedded data, we
> must rely
> +        * on the existing exposure lines and frame length values returned
> by
> +        * DelayedControls.
> +        *
> +        * Otherwise, all values are updated with what is reported in the
> +        * embedded data.
> +        */
> +       if (deviceStatus.frame_length > frameLengthMax) {
> +               DeviceStatus parsedDeviceStatus;
> +
> +               metadata.Get("device.status", parsedDeviceStatus);
> +               parsedDeviceStatus.shutter_speed =
> deviceStatus.shutter_speed;
> +               parsedDeviceStatus.frame_length =
> deviceStatus.frame_length;
> +               metadata.Set("device.status", parsedDeviceStatus);
> +
> +               LOG(IPARPI, Debug) << "Metadata updated for long exposure:
> "
> +                                  << parsedDeviceStatus;
> +       }
> +}
> +
> +uint32_t CamHelperImx519::GetVBlanking(Duration &exposure,
> +                                      Duration minFrameDuration,
> +                                      Duration maxFrameDuration) const
> +{
> +       uint32_t frameLength, exposureLines;
> +       unsigned int shift = 0;
> +
> +       frameLength = mode_.height + CamHelper::GetVBlanking(exposure,
> minFrameDuration,
> +
> maxFrameDuration);
> +       /*
> +        * Check if the frame length calculated needs to be setup for long
> +        * exposure mode. This will require us to use a long exposure scale
> +        * factor provided by a shift operation in the sensor.
> +        */
> +       while (frameLength > frameLengthMax) {
> +               if (++shift > longExposureShiftMax) {
> +                       shift = longExposureShiftMax;
> +                       frameLength = frameLengthMax;
> +                       break;
> +               }
> +               frameLength >>= 1;
> +       }
> +
> +       if (shift) {
> +               /* Account for any rounding in the scaled frame length
> value. */
> +               frameLength <<= shift;
> +               exposureLines = ExposureLines(exposure);
> +               exposureLines = std::min(exposureLines, frameLength -
> frameIntegrationDiff);
> +               exposure = Exposure(exposureLines);
> +       }
> +
> +       return frameLength - mode_.height;
> +}
> +
> +void CamHelperImx519::GetDelays(int &exposure_delay, int &gain_delay,
> +                               int &vblank_delay) const
> +{
> +       exposure_delay = 2;
> +       gain_delay = 2;
> +       vblank_delay = 3;
> +}
> +
> +bool CamHelperImx519::SensorEmbeddedDataPresent() const
> +{
> +       return true;
> +}
> +
> +void CamHelperImx519::PopulateMetadata(const MdParser::RegisterMap
> &registers,
> +                                      Metadata &metadata) const
> +{
> +       DeviceStatus deviceStatus;
> +
> +       deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) *
> 256 + registers.at(expLoReg));
> +       deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) * 256 +
> registers.at(gainLoReg));
> +       deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256
> + registers.at(frameLengthLoReg);
> +
> +       metadata.Set("device.status", deviceStatus);
> +}
> +
> +static CamHelper *Create()
> +{
> +       return new CamHelperImx519();
> +}
> +
> +static RegisterCamHelper reg("imx519", &Create);
> diff --git a/src/ipa/raspberrypi/data/imx519.json
> b/src/ipa/raspberrypi/data/imx519.json
> new file mode 100644
> index 00000000..164d0d9d
> --- /dev/null
> +++ b/src/ipa/raspberrypi/data/imx519.json
> @@ -0,0 +1,338 @@
> +{
> +    "rpi.black_level":
> +    {
> +        "black_level": 4096
> +    },
> +    "rpi.dpc":
> +    {
> +    },
> +    "rpi.lux":
> +    {
> +        "reference_shutter_speed": 13841,
> +        "reference_gain": 2.0,
> +        "reference_aperture": 1.0,
> +        "reference_lux": 900,
> +        "reference_Y": 12064
> +    },
> +    "rpi.noise":
> +    {
> +        "reference_constant": 0,
> +        "reference_slope": 2.776
> +    },
> +    "rpi.geq":
> +    {
> +        "offset": 189,
> +        "slope": 0.01495
> +    },
> +    "rpi.sdn":
> +    {
> +    },
> +    "rpi.awb":
> +    {
> +        "priors":
> +        [
> +            {
> +                "lux": 0, "prior":
> +                [
> +                    2000, 1.0, 3000, 0.0, 13000, 0.0
> +                ]
> +            },
> +            {
> +                "lux": 800, "prior":
> +                [
> +                    2000, 0.0, 6000, 2.0, 13000, 2.0
> +                ]
> +            },
> +            {
> +                "lux": 1500, "prior":
> +                [
> +                    2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000,
> 1.0, 13000, 1.0
> +                ]
> +            }
> +        ],
> +        "modes":
> +        {
> +            "auto":
> +            {
> +                "lo": 2500,
> +                "hi": 7900
> +            },
> +            "incandescent":
> +            {
> +                "lo": 2500,
> +                "hi": 3000
> +            },
> +            "tungsten":
> +            {
> +                "lo": 3000,
> +                "hi": 3500
> +            },
> +            "fluorescent":
> +            {
> +                "lo": 4000,
> +                "hi": 4700
> +            },
> +            "indoor":
> +            {
> +                "lo": 3000,
> +                "hi": 5000
> +            },
> +            "daylight":
> +            {
> +                "lo": 5500,
> +                "hi": 6500
> +            },
> +            "cloudy":
> +            {
> +                "lo": 7000,
> +                "hi": 8000
> +            }
> +        },
> +        "bayes": 1,
> +        "ct_curve":
> +        [
> +            2890.0, 0.7328, 0.3734, 3550.0, 0.6228, 0.4763, 4500.0,
> 0.5208, 0.5825, 5700.0, 0.4467, 0.6671, 7900.0, 0.3858, 0.7411
> +        ],
> +        "sensitivity_r": 1.0,
> +        "sensitivity_b": 1.0,
> +        "transverse_pos": 0.02027,
> +        "transverse_neg": 0.01935
> +    },
> +    "rpi.agc":
> +    {
> +        "metering_modes":
> +        {
> +            "centre-weighted":
> +            {
> +                "weights":
> +                [
> +                    3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
> +                ]
> +            },
> +            "spot":
> +            {
> +                "weights":
> +                [
> +                    2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
> +                ]
> +            },
> +            "matrix":
> +            {
> +                "weights":
> +                [
> +                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
> +                ]
> +            }
> +        },
> +        "exposure_modes":
> +        {
> +            "normal":
> +            {
> +                "shutter":
> +                [
> +                    100, 10000, 30000, 60000, 120000
> +                ],
> +                "gain":
> +                [
> +                    1.0, 2.0, 4.0, 6.0, 6.0
> +                ]
> +            },
> +            "short":
> +            {
> +                "shutter":
> +                [
> +                    100, 5000, 10000, 20000, 120000
> +                ],
> +                "gain":
> +                [
> +                    1.0, 2.0, 4.0, 6.0, 6.0
> +                ]
> +            }
> +        },
> +        "constraint_modes":
> +        {
> +            "normal":
> +            [
> +                {
> +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0,
> "y_target":
> +                    [
> +                        0, 0.5, 1000, 0.5
> +                    ]
> +                }
> +            ],
> +            "highlight":
> +            [
> +                {
> +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0,
> "y_target":
> +                    [
> +                        0, 0.5, 1000, 0.5
> +                    ]
> +                },
> +                {
> +                    "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0,
> "y_target":
> +                    [
> +                        0, 0.8, 1000, 0.8
> +                    ]
> +                }
> +            ]
> +        },
> +        "y_target":
> +        [
> +            0, 0.16, 1000, 0.165, 10000, 0.17
> +        ]
> +    },
> +    "rpi.alsc":
> +    {
> +        "omega": 1.3,
> +        "n_iter": 100,
> +        "luminance_strength": 0.5,
> +        "calibrations_Cr":
> +        [
> +            {
> +                "ct": 3000, "table":
> +                [
> +                    1.527, 1.521, 1.508, 1.493, 1.476, 1.455, 1.442,
> 1.441, 1.441, 1.441, 1.448, 1.467, 1.483, 1.494, 1.503, 1.504,
> +                    1.525, 1.513, 1.496, 1.477, 1.461, 1.434, 1.418,
> 1.409, 1.409, 1.416, 1.429, 1.449, 1.469, 1.485, 1.495, 1.503,
> +                    1.517, 1.506, 1.485, 1.461, 1.434, 1.412, 1.388,
> 1.376, 1.376, 1.386, 1.405, 1.429, 1.449, 1.471, 1.488, 1.495,
> +                    1.512, 1.496, 1.471, 1.442, 1.412, 1.388, 1.361,
> 1.344, 1.344, 1.358, 1.384, 1.405, 1.431, 1.456, 1.479, 1.489,
> +                    1.508, 1.488, 1.458, 1.425, 1.393, 1.361, 1.343,
> 1.322, 1.321, 1.342, 1.358, 1.385, 1.416, 1.445, 1.471, 1.484,
> +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322,
> 1.318, 1.318, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322,
> 1.313, 1.313, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> +                    1.507, 1.485, 1.455, 1.422, 1.387, 1.355, 1.333,
> 1.319, 1.321, 1.333, 1.351, 1.381, 1.411, 1.441, 1.467, 1.483,
> +                    1.508, 1.489, 1.463, 1.432, 1.401, 1.372, 1.355,
> 1.333, 1.333, 1.351, 1.369, 1.393, 1.422, 1.448, 1.471, 1.484,
> +                    1.511, 1.494, 1.472, 1.444, 1.416, 1.398, 1.372,
> 1.361, 1.361, 1.369, 1.393, 1.411, 1.436, 1.458, 1.477, 1.487,
> +                    1.511, 1.496, 1.478, 1.455, 1.436, 1.416, 1.399,
> 1.391, 1.391, 1.397, 1.411, 1.429, 1.451, 1.466, 1.479, 1.487,
> +                    1.511, 1.495, 1.478, 1.462, 1.448, 1.432, 1.419,
> 1.419, 1.419, 1.419, 1.429, 1.445, 1.459, 1.471, 1.482, 1.487
> +                ]
> +            },
> +            {
> +                "ct": 6000, "table":
> +                [
> +                    2.581, 2.573, 2.558, 2.539, 2.514, 2.487, 2.473,
> 2.471, 2.471, 2.471, 2.479, 2.499, 2.517, 2.532, 2.543, 2.544,
> +                    2.575, 2.559, 2.539, 2.521, 2.491, 2.458, 2.435,
> 2.421, 2.421, 2.429, 2.449, 2.477, 2.499, 2.519, 2.534, 2.543,
> +                    2.561, 2.549, 2.521, 2.491, 2.457, 2.423, 2.393,
> 2.375, 2.375, 2.387, 2.412, 2.444, 2.475, 2.499, 2.519, 2.532,
> +                    2.552, 2.531, 2.498, 2.459, 2.423, 2.391, 2.349,
> 2.325, 2.325, 2.344, 2.374, 2.412, 2.444, 2.476, 2.505, 2.519,
> +                    2.543, 2.518, 2.479, 2.435, 2.392, 2.349, 2.324,
> 2.285, 2.283, 2.313, 2.344, 2.374, 2.417, 2.457, 2.489, 2.506,
> +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284,
> 2.277, 2.279, 2.283, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284,
> 2.267, 2.267, 2.281, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> +                    2.541, 2.512, 2.472, 2.425, 2.381, 2.338, 2.302,
> 2.278, 2.279, 2.301, 2.324, 2.364, 2.407, 2.447, 2.481, 2.504,
> +                    2.544, 2.519, 2.483, 2.441, 2.401, 2.363, 2.338,
> 2.302, 2.302, 2.324, 2.355, 2.385, 2.423, 2.459, 2.488, 2.506,
> +                    2.549, 2.527, 2.497, 2.463, 2.427, 2.401, 2.363,
> 2.345, 2.345, 2.355, 2.385, 2.412, 2.444, 2.473, 2.497, 2.509,
> +                    2.552, 2.532, 2.507, 2.481, 2.459, 2.427, 2.402,
> 2.389, 2.389, 2.394, 2.412, 2.444, 2.465, 2.481, 2.499, 2.511,
> +                    2.553, 2.533, 2.508, 2.489, 2.475, 2.454, 2.429,
> 2.429, 2.429, 2.429, 2.439, 2.463, 2.481, 2.492, 2.504, 2.511
> +                ]
> +            }
> +        ],
> +        "calibrations_Cb":
> +        [
> +            {
> +                "ct": 3000, "table":
> +                [
> +                    3.132, 3.126, 3.116, 3.103, 3.097, 3.091, 3.087,
> 3.086, 3.088, 3.091, 3.092, 3.102, 3.113, 3.121, 3.141, 3.144,
> +                    3.149, 3.132, 3.123, 3.108, 3.101, 3.096, 3.091,
> 3.089, 3.091, 3.092, 3.101, 3.107, 3.116, 3.129, 3.144, 3.153,
> +                    3.161, 3.149, 3.129, 3.121, 3.108, 3.103, 3.101,
> 3.101, 3.101, 3.103, 3.107, 3.116, 3.125, 3.134, 3.153, 3.159,
> +                    3.176, 3.161, 3.144, 3.129, 3.124, 3.121, 3.117,
> 3.118, 3.118, 3.119, 3.122, 3.125, 3.134, 3.146, 3.159, 3.171,
> +                    3.183, 3.176, 3.157, 3.144, 3.143, 3.143, 3.139,
> 3.141, 3.141, 3.141, 3.141, 3.141, 3.146, 3.161, 3.171, 3.179,
> +                    3.189, 3.183, 3.165, 3.157, 3.156, 3.157, 3.159,
> 3.163, 3.163, 3.163, 3.163, 3.161, 3.163, 3.169, 3.179, 3.187,
> +                    3.199, 3.189, 3.171, 3.165, 3.164, 3.167, 3.171,
> 3.173, 3.173, 3.172, 3.171, 3.169, 3.169, 3.175, 3.187, 3.189,
> +                    3.206, 3.196, 3.177, 3.171, 3.165, 3.167, 3.171,
> 3.173, 3.173, 3.172, 3.171, 3.171, 3.173, 3.177, 3.192, 3.194,
> +                    3.209, 3.197, 3.178, 3.171, 3.164, 3.161, 3.159,
> 3.161, 3.162, 3.164, 3.167, 3.171, 3.173, 3.181, 3.193, 3.198,
> +                    3.204, 3.194, 3.176, 3.165, 3.161, 3.156, 3.154,
> 3.154, 3.159, 3.161, 3.164, 3.168, 3.173, 3.182, 3.198, 3.199,
> +                    3.199, 3.191, 3.176, 3.169, 3.161, 3.157, 3.153,
> 3.153, 3.156, 3.161, 3.164, 3.168, 3.173, 3.186, 3.196, 3.199,
> +                    3.199, 3.188, 3.179, 3.173, 3.165, 3.157, 3.153,
> 3.154, 3.156, 3.159, 3.167, 3.171, 3.176, 3.185, 3.193, 3.198
> +                ]
> +            },
> +            {
> +                "ct": 6000, "table":
> +                [
> +                    1.579, 1.579, 1.577, 1.574, 1.573, 1.571, 1.571,
> 1.571, 1.571, 1.569, 1.569, 1.571, 1.572, 1.574, 1.577, 1.578,
> +                    1.584, 1.579, 1.578, 1.575, 1.573, 1.572, 1.571,
> 1.572, 1.572, 1.571, 1.571, 1.572, 1.573, 1.576, 1.578, 1.579,
> +                    1.587, 1.584, 1.579, 1.578, 1.575, 1.573, 1.573,
> 1.575, 1.575, 1.574, 1.573, 1.574, 1.576, 1.578, 1.581, 1.581,
> +                    1.591, 1.587, 1.584, 1.579, 1.578, 1.579, 1.579,
> 1.581, 1.581, 1.581, 1.578, 1.577, 1.578, 1.581, 1.585, 1.586,
> +                    1.595, 1.591, 1.587, 1.585, 1.585, 1.586, 1.587,
> 1.587, 1.588, 1.588, 1.585, 1.584, 1.584, 1.586, 1.589, 1.589,
> +                    1.597, 1.595, 1.591, 1.589, 1.591, 1.593, 1.595,
> 1.596, 1.597, 1.597, 1.595, 1.594, 1.592, 1.592, 1.593, 1.593,
> +                    1.601, 1.597, 1.593, 1.592, 1.593, 1.595, 1.598,
> 1.599, 1.602, 1.601, 1.598, 1.596, 1.595, 1.596, 1.595, 1.595,
> +                    1.601, 1.599, 1.594, 1.593, 1.593, 1.595, 1.598,
> 1.599, 1.602, 1.601, 1.598, 1.597, 1.597, 1.597, 1.597, 1.597,
> +                    1.602, 1.599, 1.594, 1.593, 1.592, 1.593, 1.595,
> 1.597, 1.597, 1.598, 1.598, 1.597, 1.597, 1.597, 1.598, 1.598,
> +                    1.599, 1.598, 1.594, 1.592, 1.591, 1.591, 1.592,
> 1.595, 1.596, 1.597, 1.597, 1.597, 1.597, 1.599, 1.599, 1.599,
> +                    1.598, 1.596, 1.594, 1.593, 1.592, 1.592, 1.592,
> 1.594, 1.595, 1.597, 1.597, 1.597, 1.598, 1.599, 1.599, 1.599,
> +                    1.597, 1.595, 1.594, 1.594, 1.593, 1.592, 1.593,
> 1.595, 1.595, 1.597, 1.598, 1.598, 1.598, 1.599, 1.599, 1.599
> +                ]
> +            }
> +        ],
> +        "luminance_lut":
> +        [
> +            2.887, 2.754, 2.381, 2.105, 1.859, 1.678, 1.625, 1.623,
> 1.623, 1.624, 1.669, 1.849, 2.092, 2.362, 2.723, 2.838,
> +            2.754, 2.443, 2.111, 1.905, 1.678, 1.542, 1.455, 1.412,
> 1.412, 1.452, 1.535, 1.665, 1.893, 2.096, 2.413, 2.723,
> +            2.443, 2.216, 1.911, 1.678, 1.537, 1.372, 1.288, 1.245,
> 1.245, 1.283, 1.363, 1.527, 1.665, 1.895, 2.193, 2.413,
> +            2.318, 2.057, 1.764, 1.541, 1.372, 1.282, 1.159, 1.113,
> 1.113, 1.151, 1.269, 1.363, 1.527, 1.749, 2.034, 2.278,
> +            2.259, 1.953, 1.671, 1.452, 1.283, 1.159, 1.107, 1.018,
> 1.017, 1.097, 1.151, 1.269, 1.437, 1.655, 1.931, 2.222,
> +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.019, 1.011,
> 1.005, 1.014, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.016, 1.001,
> 1.001, 1.007, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> +            2.257, 1.946, 1.666, 1.448, 1.281, 1.153, 1.093, 1.013,
> 1.008, 1.089, 1.143, 1.269, 1.437, 1.654, 1.934, 2.226,
> +            2.309, 2.044, 1.756, 1.532, 1.363, 1.259, 1.153, 1.093,
> 1.093, 1.143, 1.264, 1.354, 1.524, 1.746, 2.035, 2.284,
> +            2.425, 2.201, 1.896, 1.662, 1.519, 1.363, 1.259, 1.214,
> 1.214, 1.264, 1.354, 1.519, 1.655, 1.888, 2.191, 2.413,
> +            2.724, 2.417, 2.091, 1.888, 1.662, 1.519, 1.419, 1.373,
> 1.373, 1.425, 1.521, 1.655, 1.885, 2.089, 2.409, 2.722,
> +            2.858, 2.724, 2.356, 2.085, 1.842, 1.658, 1.581, 1.577,
> 1.577, 1.579, 1.653, 1.838, 2.084, 2.359, 2.722, 2.842
> +        ],
> +        "sigma": 0.00372,
> +        "sigma_Cb": 0.00244
> +    },
> +    "rpi.contrast":
> +    {
> +        "ce_enable": 1,
> +        "gamma_curve":
> +        [
> +            0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120,
> 18051, 6144, 20790, 7168, 23193,
> +            8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288,
> 33975, 13312, 35815, 14336, 37600, 15360, 39168,
> +            16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753,
> 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796,
> +            32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954,
> 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476,
> +            65535, 65535
> +        ]
> +    },
> +    "rpi.ccm":
> +    {
> +        "ccms":
> +        [
> +            {
> +                "ct": 2890, "ccm":
> +                [
> +                    1.36754, -0.18448, -0.18306, -0.32356, 1.44826,
> -0.12471, -0.00412, -0.69936, 1.70348
> +                ]
> +            },
> +            {
> +                "ct": 2920, "ccm":
> +                [
> +                    1.26704, 0.01624, -0.28328, -0.28516, 1.38934,
> -0.10419, -0.04854, -0.82211, 1.87066
> +                ]
> +            },
> +            {
> +                "ct": 3550, "ccm":
> +                [
> +                    1.42836, -0.27235, -0.15601, -0.28751, 1.41075,
> -0.12325, -0.01812, -0.54849, 1.56661
> +                ]
> +            },
> +            {
> +                "ct": 4500, "ccm":
> +                [
> +                    1.36328, -0.19569, -0.16759, -0.25254, 1.52248,
> -0.26994, -0.01575, -0.53155, 1.54729
> +                ]
> +            },
> +            {
> +                "ct": 5700, "ccm":
> +                [
> +                    1.49207, -0.37245, -0.11963, -0.21493, 1.40005,
> -0.18512, -0.03781, -0.38779, 1.42561
> +                ]
> +            },
> +            {
> +                "ct": 7900, "ccm":
> +                [
> +                    1.34849, -0.05425, -0.29424, -0.22182, 1.77684,
> -0.55502, -0.07403, -0.55336, 1.62739
> +                ]
> +            }
> +        ]
> +    },
> +    "rpi.sharpen":
> +    {
> +    }
> +}
> diff --git a/src/ipa/raspberrypi/data/meson.build
> b/src/ipa/raspberrypi/data/meson.build
> index 2def75cb..e84cd099 100644
> --- a/src/ipa/raspberrypi/data/meson.build
> +++ b/src/ipa/raspberrypi/data/meson.build
> @@ -7,6 +7,7 @@ conf_files = files([
>      'imx378.json',
>      'imx477.json',
>      'imx477_noir.json',
> +    'imx519.json',
>      'ov5647.json',
>      'ov5647_noir.json',
>      'ov9281.json',
> diff --git a/src/ipa/raspberrypi/meson.build
> b/src/ipa/raspberrypi/meson.build
> index 1af31e4a..176055f4 100644
> --- a/src/ipa/raspberrypi/meson.build
> +++ b/src/ipa/raspberrypi/meson.build
> @@ -22,6 +22,7 @@ rpi_ipa_sources = files([
>      'cam_helper_imx219.cpp',
>      'cam_helper_imx290.cpp',
>      'cam_helper_imx477.cpp',
> +    'cam_helper_imx519.cpp',
>      'cam_helper_ov9281.cpp',
>      'controller/controller.cpp',
>      'controller/histogram.cpp',
> --
> 2.20.1
>
>
Kieran Bingham Oct. 21, 2021, 9:38 a.m. UTC | #2
Hi Lee, David,

Quoting David Plowman (2021-10-20 14:23:34)
> From: Arducam info <info@arducam.com>
> 
> The necessary tuning file and CamHelper is added for the imx519 sensor.
> 
> The imx519 is a 16MP rolling shutter sensor. To enable
> it, please add
> 
> dtoverlay=imx519
> 

Great, I'm glad to see new sensor support progressing.

For this patch:

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

I see the imx519 is integrated into the Raspberry Pi kernel, who will
take this forward and post to the linux-media to get it intgrated into
the kernel directly?

--
Kieran

> to the /boot/config.txt file and reboot the Pi.
> 
> Signed-off-by: Lee Jackson <info@arducam.com>
> Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
> 
> ---
>  src/ipa/raspberrypi/cam_helper_imx519.cpp | 185 ++++++++++++
>  src/ipa/raspberrypi/data/imx519.json      | 338 ++++++++++++++++++++++
>  src/ipa/raspberrypi/data/meson.build      |   1 +
>  src/ipa/raspberrypi/meson.build           |   1 +
>  4 files changed, 525 insertions(+)
>  create mode 100644 src/ipa/raspberrypi/cam_helper_imx519.cpp
>  create mode 100644 src/ipa/raspberrypi/data/imx519.json
> 
> diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> new file mode 100644
> index 00000000..eaf24982
> --- /dev/null
> +++ b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> @@ -0,0 +1,185 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * Based on cam_helper_imx477.cpp
> + * Copyright (C) 2020, Raspberry Pi (Trading) Limited
> + *
> + * cam_helper_imx519.cpp - camera helper for imx519 sensor
> + * Copyright (C) 2021, Arducam Technology co., Ltd.
> + */
> +
> +#include <assert.h>
> +#include <cmath>
> +#include <stddef.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +#include <libcamera/base/log.h>
> +
> +#include "cam_helper.hpp"
> +#include "md_parser.hpp"
> +
> +using namespace RPiController;
> +using namespace libcamera;
> +using libcamera::utils::Duration;
> +
> +namespace libcamera {
> +LOG_DECLARE_CATEGORY(IPARPI)
> +}
> +
> +/*
> + * We care about two gain registers and a pair of exposure registers. Their
> + * I2C addresses from the Sony IMX519 datasheet:
> + */
> +constexpr uint32_t expHiReg = 0x0202;
> +constexpr uint32_t expLoReg = 0x0203;
> +constexpr uint32_t gainHiReg = 0x0204;
> +constexpr uint32_t gainLoReg = 0x0205;
> +constexpr uint32_t frameLengthHiReg = 0x0340;
> +constexpr uint32_t frameLengthLoReg = 0x0341;
> +constexpr std::initializer_list<uint32_t> registerList =
> +       { expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg, frameLengthLoReg  };
> +
> +class CamHelperImx519 : public CamHelper
> +{
> +public:
> +       CamHelperImx519();
> +       uint32_t GainCode(double gain) const override;
> +       double Gain(uint32_t gain_code) const override;
> +       void Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override;
> +       uint32_t GetVBlanking(Duration &exposure, Duration minFrameDuration,
> +                             Duration maxFrameDuration) const override;
> +       void GetDelays(int &exposure_delay, int &gain_delay,
> +                      int &vblank_delay) const override;
> +       bool SensorEmbeddedDataPresent() const override;
> +
> +private:
> +       /*
> +        * Smallest difference between the frame length and integration time,
> +        * in units of lines.
> +        */
> +       static constexpr int frameIntegrationDiff = 32;
> +       /* Maximum frame length allowable for long exposure calculations. */
> +       static constexpr int frameLengthMax = 0xffdc;
> +       /* Largest long exposure scale factor given as a left shift on the frame length. */
> +       static constexpr int longExposureShiftMax = 7;
> +
> +       void PopulateMetadata(const MdParser::RegisterMap &registers,
> +                             Metadata &metadata) const override;
> +};
> +
> +CamHelperImx519::CamHelperImx519()
> +       : CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff)
> +{
> +}
> +
> +uint32_t CamHelperImx519::GainCode(double gain) const
> +{
> +       return static_cast<uint32_t>(1024 - 1024 / gain);
> +}
> +
> +double CamHelperImx519::Gain(uint32_t gain_code) const
> +{
> +       return 1024.0 / (1024 - gain_code);
> +}
> +
> +void CamHelperImx519::Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata)
> +{
> +       MdParser::RegisterMap registers;
> +       DeviceStatus deviceStatus;
> +
> +       if (metadata.Get("device.status", deviceStatus)) {
> +               LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls";
> +               return;
> +       }
> +
> +       parseEmbeddedData(buffer, metadata);
> +
> +       /*
> +        * The DeviceStatus struct is first populated with values obtained from
> +        * DelayedControls. If this reports frame length is > frameLengthMax,
> +        * it means we are using a long exposure mode. Since the long exposure
> +        * scale factor is not returned back through embedded data, we must rely
> +        * on the existing exposure lines and frame length values returned by
> +        * DelayedControls.
> +        *
> +        * Otherwise, all values are updated with what is reported in the
> +        * embedded data.
> +        */
> +       if (deviceStatus.frame_length > frameLengthMax) {
> +               DeviceStatus parsedDeviceStatus;
> +
> +               metadata.Get("device.status", parsedDeviceStatus);
> +               parsedDeviceStatus.shutter_speed = deviceStatus.shutter_speed;
> +               parsedDeviceStatus.frame_length = deviceStatus.frame_length;
> +               metadata.Set("device.status", parsedDeviceStatus);
> +
> +               LOG(IPARPI, Debug) << "Metadata updated for long exposure: "
> +                                  << parsedDeviceStatus;
> +       }
> +}
> +
> +uint32_t CamHelperImx519::GetVBlanking(Duration &exposure,
> +                                      Duration minFrameDuration,
> +                                      Duration maxFrameDuration) const
> +{
> +       uint32_t frameLength, exposureLines;
> +       unsigned int shift = 0;
> +
> +       frameLength = mode_.height + CamHelper::GetVBlanking(exposure, minFrameDuration,
> +                                                            maxFrameDuration);
> +       /*
> +        * Check if the frame length calculated needs to be setup for long
> +        * exposure mode. This will require us to use a long exposure scale
> +        * factor provided by a shift operation in the sensor.
> +        */
> +       while (frameLength > frameLengthMax) {
> +               if (++shift > longExposureShiftMax) {
> +                       shift = longExposureShiftMax;
> +                       frameLength = frameLengthMax;
> +                       break;
> +               }
> +               frameLength >>= 1;
> +       }
> +
> +       if (shift) {
> +               /* Account for any rounding in the scaled frame length value. */
> +               frameLength <<= shift;
> +               exposureLines = ExposureLines(exposure);
> +               exposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);
> +               exposure = Exposure(exposureLines);
> +       }
> +
> +       return frameLength - mode_.height;
> +}
> +
> +void CamHelperImx519::GetDelays(int &exposure_delay, int &gain_delay,
> +                               int &vblank_delay) const
> +{
> +       exposure_delay = 2;
> +       gain_delay = 2;
> +       vblank_delay = 3;
> +}
> +
> +bool CamHelperImx519::SensorEmbeddedDataPresent() const
> +{
> +       return true;
> +}
> +
> +void CamHelperImx519::PopulateMetadata(const MdParser::RegisterMap &registers,
> +                                      Metadata &metadata) const
> +{
> +       DeviceStatus deviceStatus;
> +
> +       deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg));
> +       deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg));
> +       deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);
> +
> +       metadata.Set("device.status", deviceStatus);
> +}
> +
> +static CamHelper *Create()
> +{
> +       return new CamHelperImx519();
> +}
> +
> +static RegisterCamHelper reg("imx519", &Create);
> diff --git a/src/ipa/raspberrypi/data/imx519.json b/src/ipa/raspberrypi/data/imx519.json
> new file mode 100644
> index 00000000..164d0d9d
> --- /dev/null
> +++ b/src/ipa/raspberrypi/data/imx519.json
> @@ -0,0 +1,338 @@
> +{
> +    "rpi.black_level":
> +    {
> +        "black_level": 4096
> +    },
> +    "rpi.dpc":
> +    {
> +    },
> +    "rpi.lux":
> +    {
> +        "reference_shutter_speed": 13841,
> +        "reference_gain": 2.0,
> +        "reference_aperture": 1.0,
> +        "reference_lux": 900,
> +        "reference_Y": 12064
> +    },
> +    "rpi.noise":
> +    {
> +        "reference_constant": 0,
> +        "reference_slope": 2.776
> +    },
> +    "rpi.geq":
> +    {
> +        "offset": 189,
> +        "slope": 0.01495
> +    },
> +    "rpi.sdn":
> +    {
> +    },
> +    "rpi.awb":
> +    {
> +        "priors":
> +        [
> +            {
> +                "lux": 0, "prior":
> +                [
> +                    2000, 1.0, 3000, 0.0, 13000, 0.0
> +                ]
> +            },
> +            {
> +                "lux": 800, "prior":
> +                [
> +                    2000, 0.0, 6000, 2.0, 13000, 2.0
> +                ]
> +            },
> +            {
> +                "lux": 1500, "prior":
> +                [
> +                    2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0
> +                ]
> +            }
> +        ],
> +        "modes":
> +        {
> +            "auto":
> +            {
> +                "lo": 2500,
> +                "hi": 7900
> +            },
> +            "incandescent":
> +            {
> +                "lo": 2500,
> +                "hi": 3000
> +            },
> +            "tungsten":
> +            {
> +                "lo": 3000,
> +                "hi": 3500
> +            },
> +            "fluorescent":
> +            {
> +                "lo": 4000,
> +                "hi": 4700
> +            },
> +            "indoor":
> +            {
> +                "lo": 3000,
> +                "hi": 5000
> +            },
> +            "daylight":
> +            {
> +                "lo": 5500,
> +                "hi": 6500
> +            },
> +            "cloudy":
> +            {
> +                "lo": 7000,
> +                "hi": 8000
> +            }
> +        },
> +        "bayes": 1,
> +        "ct_curve":
> +        [
> +            2890.0, 0.7328, 0.3734, 3550.0, 0.6228, 0.4763, 4500.0, 0.5208, 0.5825, 5700.0, 0.4467, 0.6671, 7900.0, 0.3858, 0.7411
> +        ],
> +        "sensitivity_r": 1.0,
> +        "sensitivity_b": 1.0,
> +        "transverse_pos": 0.02027,
> +        "transverse_neg": 0.01935
> +    },
> +    "rpi.agc":
> +    {
> +        "metering_modes":
> +        {
> +            "centre-weighted":
> +            {
> +                "weights":
> +                [
> +                    3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
> +                ]
> +            },
> +            "spot":
> +            {
> +                "weights":
> +                [
> +                    2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
> +                ]
> +            },
> +            "matrix":
> +            {
> +                "weights":
> +                [
> +                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
> +                ]
> +            }
> +        },
> +        "exposure_modes":
> +        {
> +            "normal":
> +            {
> +                "shutter":
> +                [
> +                    100, 10000, 30000, 60000, 120000
> +                ],
> +                "gain":
> +                [
> +                    1.0, 2.0, 4.0, 6.0, 6.0
> +                ]
> +            },
> +            "short":
> +            {
> +                "shutter":
> +                [
> +                    100, 5000, 10000, 20000, 120000
> +                ],
> +                "gain":
> +                [
> +                    1.0, 2.0, 4.0, 6.0, 6.0
> +                ]
> +            }
> +        },
> +        "constraint_modes":
> +        {
> +            "normal":
> +            [
> +                {
> +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
> +                    [
> +                        0, 0.5, 1000, 0.5
> +                    ]
> +                }
> +            ],
> +            "highlight":
> +            [
> +                {
> +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
> +                    [
> +                        0, 0.5, 1000, 0.5
> +                    ]
> +                },
> +                {
> +                    "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
> +                    [
> +                        0, 0.8, 1000, 0.8
> +                    ]
> +                }
> +            ]
> +        },
> +        "y_target":
> +        [
> +            0, 0.16, 1000, 0.165, 10000, 0.17
> +        ]
> +    },
> +    "rpi.alsc":
> +    {
> +        "omega": 1.3,
> +        "n_iter": 100,
> +        "luminance_strength": 0.5,
> +        "calibrations_Cr":
> +        [
> +            {
> +                "ct": 3000, "table":
> +                [
> +                    1.527, 1.521, 1.508, 1.493, 1.476, 1.455, 1.442, 1.441, 1.441, 1.441, 1.448, 1.467, 1.483, 1.494, 1.503, 1.504,
> +                    1.525, 1.513, 1.496, 1.477, 1.461, 1.434, 1.418, 1.409, 1.409, 1.416, 1.429, 1.449, 1.469, 1.485, 1.495, 1.503,
> +                    1.517, 1.506, 1.485, 1.461, 1.434, 1.412, 1.388, 1.376, 1.376, 1.386, 1.405, 1.429, 1.449, 1.471, 1.488, 1.495,
> +                    1.512, 1.496, 1.471, 1.442, 1.412, 1.388, 1.361, 1.344, 1.344, 1.358, 1.384, 1.405, 1.431, 1.456, 1.479, 1.489,
> +                    1.508, 1.488, 1.458, 1.425, 1.393, 1.361, 1.343, 1.322, 1.321, 1.342, 1.358, 1.385, 1.416, 1.445, 1.471, 1.484,
> +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.318, 1.318, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.313, 1.313, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> +                    1.507, 1.485, 1.455, 1.422, 1.387, 1.355, 1.333, 1.319, 1.321, 1.333, 1.351, 1.381, 1.411, 1.441, 1.467, 1.483,
> +                    1.508, 1.489, 1.463, 1.432, 1.401, 1.372, 1.355, 1.333, 1.333, 1.351, 1.369, 1.393, 1.422, 1.448, 1.471, 1.484,
> +                    1.511, 1.494, 1.472, 1.444, 1.416, 1.398, 1.372, 1.361, 1.361, 1.369, 1.393, 1.411, 1.436, 1.458, 1.477, 1.487,
> +                    1.511, 1.496, 1.478, 1.455, 1.436, 1.416, 1.399, 1.391, 1.391, 1.397, 1.411, 1.429, 1.451, 1.466, 1.479, 1.487,
> +                    1.511, 1.495, 1.478, 1.462, 1.448, 1.432, 1.419, 1.419, 1.419, 1.419, 1.429, 1.445, 1.459, 1.471, 1.482, 1.487
> +                ]
> +            },
> +            {
> +                "ct": 6000, "table":
> +                [
> +                    2.581, 2.573, 2.558, 2.539, 2.514, 2.487, 2.473, 2.471, 2.471, 2.471, 2.479, 2.499, 2.517, 2.532, 2.543, 2.544,
> +                    2.575, 2.559, 2.539, 2.521, 2.491, 2.458, 2.435, 2.421, 2.421, 2.429, 2.449, 2.477, 2.499, 2.519, 2.534, 2.543,
> +                    2.561, 2.549, 2.521, 2.491, 2.457, 2.423, 2.393, 2.375, 2.375, 2.387, 2.412, 2.444, 2.475, 2.499, 2.519, 2.532,
> +                    2.552, 2.531, 2.498, 2.459, 2.423, 2.391, 2.349, 2.325, 2.325, 2.344, 2.374, 2.412, 2.444, 2.476, 2.505, 2.519,
> +                    2.543, 2.518, 2.479, 2.435, 2.392, 2.349, 2.324, 2.285, 2.283, 2.313, 2.344, 2.374, 2.417, 2.457, 2.489, 2.506,
> +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.277, 2.279, 2.283, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.267, 2.267, 2.281, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> +                    2.541, 2.512, 2.472, 2.425, 2.381, 2.338, 2.302, 2.278, 2.279, 2.301, 2.324, 2.364, 2.407, 2.447, 2.481, 2.504,
> +                    2.544, 2.519, 2.483, 2.441, 2.401, 2.363, 2.338, 2.302, 2.302, 2.324, 2.355, 2.385, 2.423, 2.459, 2.488, 2.506,
> +                    2.549, 2.527, 2.497, 2.463, 2.427, 2.401, 2.363, 2.345, 2.345, 2.355, 2.385, 2.412, 2.444, 2.473, 2.497, 2.509,
> +                    2.552, 2.532, 2.507, 2.481, 2.459, 2.427, 2.402, 2.389, 2.389, 2.394, 2.412, 2.444, 2.465, 2.481, 2.499, 2.511,
> +                    2.553, 2.533, 2.508, 2.489, 2.475, 2.454, 2.429, 2.429, 2.429, 2.429, 2.439, 2.463, 2.481, 2.492, 2.504, 2.511
> +                ]
> +            }
> +        ],
> +        "calibrations_Cb":
> +        [
> +            {
> +                "ct": 3000, "table":
> +                [
> +                    3.132, 3.126, 3.116, 3.103, 3.097, 3.091, 3.087, 3.086, 3.088, 3.091, 3.092, 3.102, 3.113, 3.121, 3.141, 3.144,
> +                    3.149, 3.132, 3.123, 3.108, 3.101, 3.096, 3.091, 3.089, 3.091, 3.092, 3.101, 3.107, 3.116, 3.129, 3.144, 3.153,
> +                    3.161, 3.149, 3.129, 3.121, 3.108, 3.103, 3.101, 3.101, 3.101, 3.103, 3.107, 3.116, 3.125, 3.134, 3.153, 3.159,
> +                    3.176, 3.161, 3.144, 3.129, 3.124, 3.121, 3.117, 3.118, 3.118, 3.119, 3.122, 3.125, 3.134, 3.146, 3.159, 3.171,
> +                    3.183, 3.176, 3.157, 3.144, 3.143, 3.143, 3.139, 3.141, 3.141, 3.141, 3.141, 3.141, 3.146, 3.161, 3.171, 3.179,
> +                    3.189, 3.183, 3.165, 3.157, 3.156, 3.157, 3.159, 3.163, 3.163, 3.163, 3.163, 3.161, 3.163, 3.169, 3.179, 3.187,
> +                    3.199, 3.189, 3.171, 3.165, 3.164, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.169, 3.169, 3.175, 3.187, 3.189,
> +                    3.206, 3.196, 3.177, 3.171, 3.165, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.171, 3.173, 3.177, 3.192, 3.194,
> +                    3.209, 3.197, 3.178, 3.171, 3.164, 3.161, 3.159, 3.161, 3.162, 3.164, 3.167, 3.171, 3.173, 3.181, 3.193, 3.198,
> +                    3.204, 3.194, 3.176, 3.165, 3.161, 3.156, 3.154, 3.154, 3.159, 3.161, 3.164, 3.168, 3.173, 3.182, 3.198, 3.199,
> +                    3.199, 3.191, 3.176, 3.169, 3.161, 3.157, 3.153, 3.153, 3.156, 3.161, 3.164, 3.168, 3.173, 3.186, 3.196, 3.199,
> +                    3.199, 3.188, 3.179, 3.173, 3.165, 3.157, 3.153, 3.154, 3.156, 3.159, 3.167, 3.171, 3.176, 3.185, 3.193, 3.198
> +                ]
> +            },
> +            {
> +                "ct": 6000, "table":
> +                [
> +                    1.579, 1.579, 1.577, 1.574, 1.573, 1.571, 1.571, 1.571, 1.571, 1.569, 1.569, 1.571, 1.572, 1.574, 1.577, 1.578,
> +                    1.584, 1.579, 1.578, 1.575, 1.573, 1.572, 1.571, 1.572, 1.572, 1.571, 1.571, 1.572, 1.573, 1.576, 1.578, 1.579,
> +                    1.587, 1.584, 1.579, 1.578, 1.575, 1.573, 1.573, 1.575, 1.575, 1.574, 1.573, 1.574, 1.576, 1.578, 1.581, 1.581,
> +                    1.591, 1.587, 1.584, 1.579, 1.578, 1.579, 1.579, 1.581, 1.581, 1.581, 1.578, 1.577, 1.578, 1.581, 1.585, 1.586,
> +                    1.595, 1.591, 1.587, 1.585, 1.585, 1.586, 1.587, 1.587, 1.588, 1.588, 1.585, 1.584, 1.584, 1.586, 1.589, 1.589,
> +                    1.597, 1.595, 1.591, 1.589, 1.591, 1.593, 1.595, 1.596, 1.597, 1.597, 1.595, 1.594, 1.592, 1.592, 1.593, 1.593,
> +                    1.601, 1.597, 1.593, 1.592, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.596, 1.595, 1.596, 1.595, 1.595,
> +                    1.601, 1.599, 1.594, 1.593, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.597, 1.597, 1.597, 1.597, 1.597,
> +                    1.602, 1.599, 1.594, 1.593, 1.592, 1.593, 1.595, 1.597, 1.597, 1.598, 1.598, 1.597, 1.597, 1.597, 1.598, 1.598,
> +                    1.599, 1.598, 1.594, 1.592, 1.591, 1.591, 1.592, 1.595, 1.596, 1.597, 1.597, 1.597, 1.597, 1.599, 1.599, 1.599,
> +                    1.598, 1.596, 1.594, 1.593, 1.592, 1.592, 1.592, 1.594, 1.595, 1.597, 1.597, 1.597, 1.598, 1.599, 1.599, 1.599,
> +                    1.597, 1.595, 1.594, 1.594, 1.593, 1.592, 1.593, 1.595, 1.595, 1.597, 1.598, 1.598, 1.598, 1.599, 1.599, 1.599
> +                ]
> +            }
> +        ],
> +        "luminance_lut":
> +        [
> +            2.887, 2.754, 2.381, 2.105, 1.859, 1.678, 1.625, 1.623, 1.623, 1.624, 1.669, 1.849, 2.092, 2.362, 2.723, 2.838,
> +            2.754, 2.443, 2.111, 1.905, 1.678, 1.542, 1.455, 1.412, 1.412, 1.452, 1.535, 1.665, 1.893, 2.096, 2.413, 2.723,
> +            2.443, 2.216, 1.911, 1.678, 1.537, 1.372, 1.288, 1.245, 1.245, 1.283, 1.363, 1.527, 1.665, 1.895, 2.193, 2.413,
> +            2.318, 2.057, 1.764, 1.541, 1.372, 1.282, 1.159, 1.113, 1.113, 1.151, 1.269, 1.363, 1.527, 1.749, 2.034, 2.278,
> +            2.259, 1.953, 1.671, 1.452, 1.283, 1.159, 1.107, 1.018, 1.017, 1.097, 1.151, 1.269, 1.437, 1.655, 1.931, 2.222,
> +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.019, 1.011, 1.005, 1.014, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.016, 1.001, 1.001, 1.007, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> +            2.257, 1.946, 1.666, 1.448, 1.281, 1.153, 1.093, 1.013, 1.008, 1.089, 1.143, 1.269, 1.437, 1.654, 1.934, 2.226,
> +            2.309, 2.044, 1.756, 1.532, 1.363, 1.259, 1.153, 1.093, 1.093, 1.143, 1.264, 1.354, 1.524, 1.746, 2.035, 2.284,
> +            2.425, 2.201, 1.896, 1.662, 1.519, 1.363, 1.259, 1.214, 1.214, 1.264, 1.354, 1.519, 1.655, 1.888, 2.191, 2.413,
> +            2.724, 2.417, 2.091, 1.888, 1.662, 1.519, 1.419, 1.373, 1.373, 1.425, 1.521, 1.655, 1.885, 2.089, 2.409, 2.722,
> +            2.858, 2.724, 2.356, 2.085, 1.842, 1.658, 1.581, 1.577, 1.577, 1.579, 1.653, 1.838, 2.084, 2.359, 2.722, 2.842
> +        ],
> +        "sigma": 0.00372,
> +        "sigma_Cb": 0.00244
> +    },
> +    "rpi.contrast":
> +    {
> +        "ce_enable": 1,
> +        "gamma_curve":
> +        [
> +            0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193,
> +            8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168,
> +            16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796,
> +            32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476,
> +            65535, 65535
> +        ]
> +    },
> +    "rpi.ccm":
> +    {
> +        "ccms":
> +        [
> +            {
> +                "ct": 2890, "ccm":
> +                [
> +                    1.36754, -0.18448, -0.18306, -0.32356, 1.44826, -0.12471, -0.00412, -0.69936, 1.70348
> +                ]
> +            },
> +            {
> +                "ct": 2920, "ccm":
> +                [
> +                    1.26704, 0.01624, -0.28328, -0.28516, 1.38934, -0.10419, -0.04854, -0.82211, 1.87066
> +                ]
> +            },
> +            {
> +                "ct": 3550, "ccm":
> +                [
> +                    1.42836, -0.27235, -0.15601, -0.28751, 1.41075, -0.12325, -0.01812, -0.54849, 1.56661
> +                ]
> +            },
> +            {
> +                "ct": 4500, "ccm":
> +                [
> +                    1.36328, -0.19569, -0.16759, -0.25254, 1.52248, -0.26994, -0.01575, -0.53155, 1.54729
> +                ]
> +            },
> +            {
> +                "ct": 5700, "ccm":
> +                [
> +                    1.49207, -0.37245, -0.11963, -0.21493, 1.40005, -0.18512, -0.03781, -0.38779, 1.42561
> +                ]
> +            },
> +            {
> +                "ct": 7900, "ccm":
> +                [
> +                    1.34849, -0.05425, -0.29424, -0.22182, 1.77684, -0.55502, -0.07403, -0.55336, 1.62739
> +                ]
> +            }
> +        ]
> +    },
> +    "rpi.sharpen":
> +    {
> +    }
> +}
> diff --git a/src/ipa/raspberrypi/data/meson.build b/src/ipa/raspberrypi/data/meson.build
> index 2def75cb..e84cd099 100644
> --- a/src/ipa/raspberrypi/data/meson.build
> +++ b/src/ipa/raspberrypi/data/meson.build
> @@ -7,6 +7,7 @@ conf_files = files([
>      'imx378.json',
>      'imx477.json',
>      'imx477_noir.json',
> +    'imx519.json',
>      'ov5647.json',
>      'ov5647_noir.json',
>      'ov9281.json',
> diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build
> index 1af31e4a..176055f4 100644
> --- a/src/ipa/raspberrypi/meson.build
> +++ b/src/ipa/raspberrypi/meson.build
> @@ -22,6 +22,7 @@ rpi_ipa_sources = files([
>      'cam_helper_imx219.cpp',
>      'cam_helper_imx290.cpp',
>      'cam_helper_imx477.cpp',
> +    'cam_helper_imx519.cpp',
>      'cam_helper_ov9281.cpp',
>      'controller/controller.cpp',
>      'controller/histogram.cpp',
> -- 
> 2.20.1
>
Kieran Bingham Nov. 2, 2021, 11:19 a.m. UTC | #3
Quoting Kieran Bingham (2021-10-21 10:38:20)
> Hi Lee, David,
> 
> Quoting David Plowman (2021-10-20 14:23:34)
> > From: Arducam info <info@arducam.com>
> > 
> > The necessary tuning file and CamHelper is added for the imx519 sensor.
> > 
> > The imx519 is a 16MP rolling shutter sensor. To enable
> > it, please add
> > 
> > dtoverlay=imx519
> > 
> 
> Great, I'm glad to see new sensor support progressing.
> 
> For this patch:
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> I see the imx519 is integrated into the Raspberry Pi kernel, who will
> take this forward and post to the linux-media to get it intgrated into
> the kernel directly?

Excellent, with
 [PATCH 1/2] dt-bindings: media: i2c: Add IMX519 CMOS sensor binding 
 https://lore.kernel.org/linux-media/38FCC5C9-9D03-4C8B-9ADF-896AE2BD90DE@arducam.com/T/#u
and
 [PATCH 2/2] media: i2c: Add driver for IMX519 sensor
 https://lore.kernel.org/linux-media/DBFF7F52-B763-4D54-8DC9-10508ECC7BD2@arducam.com/T/#u

posted, I think we should get this integrated into libcamera now.

David/Naush - I'm not able to test this. Is this fine to go in as it is?
Any impacts on the recent MC series, or anything else?

--
Kieran


> 
> --
> Kieran
> 
> > to the /boot/config.txt file and reboot the Pi.
> > 
> > Signed-off-by: Lee Jackson <info@arducam.com>
> > Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
> > 
> > ---
> >  src/ipa/raspberrypi/cam_helper_imx519.cpp | 185 ++++++++++++
> >  src/ipa/raspberrypi/data/imx519.json      | 338 ++++++++++++++++++++++
> >  src/ipa/raspberrypi/data/meson.build      |   1 +
> >  src/ipa/raspberrypi/meson.build           |   1 +
> >  4 files changed, 525 insertions(+)
> >  create mode 100644 src/ipa/raspberrypi/cam_helper_imx519.cpp
> >  create mode 100644 src/ipa/raspberrypi/data/imx519.json
> > 
> > diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> > new file mode 100644
> > index 00000000..eaf24982
> > --- /dev/null
> > +++ b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> > @@ -0,0 +1,185 @@
> > +/* SPDX-License-Identifier: BSD-2-Clause */
> > +/*
> > + * Based on cam_helper_imx477.cpp
> > + * Copyright (C) 2020, Raspberry Pi (Trading) Limited
> > + *
> > + * cam_helper_imx519.cpp - camera helper for imx519 sensor
> > + * Copyright (C) 2021, Arducam Technology co., Ltd.
> > + */
> > +
> > +#include <assert.h>
> > +#include <cmath>
> > +#include <stddef.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +
> > +#include <libcamera/base/log.h>
> > +
> > +#include "cam_helper.hpp"
> > +#include "md_parser.hpp"
> > +
> > +using namespace RPiController;
> > +using namespace libcamera;
> > +using libcamera::utils::Duration;
> > +
> > +namespace libcamera {
> > +LOG_DECLARE_CATEGORY(IPARPI)
> > +}
> > +
> > +/*
> > + * We care about two gain registers and a pair of exposure registers. Their
> > + * I2C addresses from the Sony IMX519 datasheet:
> > + */
> > +constexpr uint32_t expHiReg = 0x0202;
> > +constexpr uint32_t expLoReg = 0x0203;
> > +constexpr uint32_t gainHiReg = 0x0204;
> > +constexpr uint32_t gainLoReg = 0x0205;
> > +constexpr uint32_t frameLengthHiReg = 0x0340;
> > +constexpr uint32_t frameLengthLoReg = 0x0341;
> > +constexpr std::initializer_list<uint32_t> registerList =
> > +       { expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg, frameLengthLoReg  };
> > +
> > +class CamHelperImx519 : public CamHelper
> > +{
> > +public:
> > +       CamHelperImx519();
> > +       uint32_t GainCode(double gain) const override;
> > +       double Gain(uint32_t gain_code) const override;
> > +       void Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override;
> > +       uint32_t GetVBlanking(Duration &exposure, Duration minFrameDuration,
> > +                             Duration maxFrameDuration) const override;
> > +       void GetDelays(int &exposure_delay, int &gain_delay,
> > +                      int &vblank_delay) const override;
> > +       bool SensorEmbeddedDataPresent() const override;
> > +
> > +private:
> > +       /*
> > +        * Smallest difference between the frame length and integration time,
> > +        * in units of lines.
> > +        */
> > +       static constexpr int frameIntegrationDiff = 32;
> > +       /* Maximum frame length allowable for long exposure calculations. */
> > +       static constexpr int frameLengthMax = 0xffdc;
> > +       /* Largest long exposure scale factor given as a left shift on the frame length. */
> > +       static constexpr int longExposureShiftMax = 7;
> > +
> > +       void PopulateMetadata(const MdParser::RegisterMap &registers,
> > +                             Metadata &metadata) const override;
> > +};
> > +
> > +CamHelperImx519::CamHelperImx519()
> > +       : CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff)
> > +{
> > +}
> > +
> > +uint32_t CamHelperImx519::GainCode(double gain) const
> > +{
> > +       return static_cast<uint32_t>(1024 - 1024 / gain);
> > +}
> > +
> > +double CamHelperImx519::Gain(uint32_t gain_code) const
> > +{
> > +       return 1024.0 / (1024 - gain_code);
> > +}
> > +
> > +void CamHelperImx519::Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata)
> > +{
> > +       MdParser::RegisterMap registers;
> > +       DeviceStatus deviceStatus;
> > +
> > +       if (metadata.Get("device.status", deviceStatus)) {
> > +               LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls";
> > +               return;
> > +       }
> > +
> > +       parseEmbeddedData(buffer, metadata);
> > +
> > +       /*
> > +        * The DeviceStatus struct is first populated with values obtained from
> > +        * DelayedControls. If this reports frame length is > frameLengthMax,
> > +        * it means we are using a long exposure mode. Since the long exposure
> > +        * scale factor is not returned back through embedded data, we must rely
> > +        * on the existing exposure lines and frame length values returned by
> > +        * DelayedControls.
> > +        *
> > +        * Otherwise, all values are updated with what is reported in the
> > +        * embedded data.
> > +        */
> > +       if (deviceStatus.frame_length > frameLengthMax) {
> > +               DeviceStatus parsedDeviceStatus;
> > +
> > +               metadata.Get("device.status", parsedDeviceStatus);
> > +               parsedDeviceStatus.shutter_speed = deviceStatus.shutter_speed;
> > +               parsedDeviceStatus.frame_length = deviceStatus.frame_length;
> > +               metadata.Set("device.status", parsedDeviceStatus);
> > +
> > +               LOG(IPARPI, Debug) << "Metadata updated for long exposure: "
> > +                                  << parsedDeviceStatus;
> > +       }
> > +}
> > +
> > +uint32_t CamHelperImx519::GetVBlanking(Duration &exposure,
> > +                                      Duration minFrameDuration,
> > +                                      Duration maxFrameDuration) const
> > +{
> > +       uint32_t frameLength, exposureLines;
> > +       unsigned int shift = 0;
> > +
> > +       frameLength = mode_.height + CamHelper::GetVBlanking(exposure, minFrameDuration,
> > +                                                            maxFrameDuration);
> > +       /*
> > +        * Check if the frame length calculated needs to be setup for long
> > +        * exposure mode. This will require us to use a long exposure scale
> > +        * factor provided by a shift operation in the sensor.
> > +        */
> > +       while (frameLength > frameLengthMax) {
> > +               if (++shift > longExposureShiftMax) {
> > +                       shift = longExposureShiftMax;
> > +                       frameLength = frameLengthMax;
> > +                       break;
> > +               }
> > +               frameLength >>= 1;
> > +       }
> > +
> > +       if (shift) {
> > +               /* Account for any rounding in the scaled frame length value. */
> > +               frameLength <<= shift;
> > +               exposureLines = ExposureLines(exposure);
> > +               exposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);
> > +               exposure = Exposure(exposureLines);
> > +       }
> > +
> > +       return frameLength - mode_.height;
> > +}
> > +
> > +void CamHelperImx519::GetDelays(int &exposure_delay, int &gain_delay,
> > +                               int &vblank_delay) const
> > +{
> > +       exposure_delay = 2;
> > +       gain_delay = 2;
> > +       vblank_delay = 3;
> > +}
> > +
> > +bool CamHelperImx519::SensorEmbeddedDataPresent() const
> > +{
> > +       return true;
> > +}
> > +
> > +void CamHelperImx519::PopulateMetadata(const MdParser::RegisterMap &registers,
> > +                                      Metadata &metadata) const
> > +{
> > +       DeviceStatus deviceStatus;
> > +
> > +       deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg));
> > +       deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg));
> > +       deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);
> > +
> > +       metadata.Set("device.status", deviceStatus);
> > +}
> > +
> > +static CamHelper *Create()
> > +{
> > +       return new CamHelperImx519();
> > +}
> > +
> > +static RegisterCamHelper reg("imx519", &Create);
> > diff --git a/src/ipa/raspberrypi/data/imx519.json b/src/ipa/raspberrypi/data/imx519.json
> > new file mode 100644
> > index 00000000..164d0d9d
> > --- /dev/null
> > +++ b/src/ipa/raspberrypi/data/imx519.json
> > @@ -0,0 +1,338 @@
> > +{
> > +    "rpi.black_level":
> > +    {
> > +        "black_level": 4096
> > +    },
> > +    "rpi.dpc":
> > +    {
> > +    },
> > +    "rpi.lux":
> > +    {
> > +        "reference_shutter_speed": 13841,
> > +        "reference_gain": 2.0,
> > +        "reference_aperture": 1.0,
> > +        "reference_lux": 900,
> > +        "reference_Y": 12064
> > +    },
> > +    "rpi.noise":
> > +    {
> > +        "reference_constant": 0,
> > +        "reference_slope": 2.776
> > +    },
> > +    "rpi.geq":
> > +    {
> > +        "offset": 189,
> > +        "slope": 0.01495
> > +    },
> > +    "rpi.sdn":
> > +    {
> > +    },
> > +    "rpi.awb":
> > +    {
> > +        "priors":
> > +        [
> > +            {
> > +                "lux": 0, "prior":
> > +                [
> > +                    2000, 1.0, 3000, 0.0, 13000, 0.0
> > +                ]
> > +            },
> > +            {
> > +                "lux": 800, "prior":
> > +                [
> > +                    2000, 0.0, 6000, 2.0, 13000, 2.0
> > +                ]
> > +            },
> > +            {
> > +                "lux": 1500, "prior":
> > +                [
> > +                    2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0
> > +                ]
> > +            }
> > +        ],
> > +        "modes":
> > +        {
> > +            "auto":
> > +            {
> > +                "lo": 2500,
> > +                "hi": 7900
> > +            },
> > +            "incandescent":
> > +            {
> > +                "lo": 2500,
> > +                "hi": 3000
> > +            },
> > +            "tungsten":
> > +            {
> > +                "lo": 3000,
> > +                "hi": 3500
> > +            },
> > +            "fluorescent":
> > +            {
> > +                "lo": 4000,
> > +                "hi": 4700
> > +            },
> > +            "indoor":
> > +            {
> > +                "lo": 3000,
> > +                "hi": 5000
> > +            },
> > +            "daylight":
> > +            {
> > +                "lo": 5500,
> > +                "hi": 6500
> > +            },
> > +            "cloudy":
> > +            {
> > +                "lo": 7000,
> > +                "hi": 8000
> > +            }
> > +        },
> > +        "bayes": 1,
> > +        "ct_curve":
> > +        [
> > +            2890.0, 0.7328, 0.3734, 3550.0, 0.6228, 0.4763, 4500.0, 0.5208, 0.5825, 5700.0, 0.4467, 0.6671, 7900.0, 0.3858, 0.7411
> > +        ],
> > +        "sensitivity_r": 1.0,
> > +        "sensitivity_b": 1.0,
> > +        "transverse_pos": 0.02027,
> > +        "transverse_neg": 0.01935
> > +    },
> > +    "rpi.agc":
> > +    {
> > +        "metering_modes":
> > +        {
> > +            "centre-weighted":
> > +            {
> > +                "weights":
> > +                [
> > +                    3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
> > +                ]
> > +            },
> > +            "spot":
> > +            {
> > +                "weights":
> > +                [
> > +                    2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
> > +                ]
> > +            },
> > +            "matrix":
> > +            {
> > +                "weights":
> > +                [
> > +                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
> > +                ]
> > +            }
> > +        },
> > +        "exposure_modes":
> > +        {
> > +            "normal":
> > +            {
> > +                "shutter":
> > +                [
> > +                    100, 10000, 30000, 60000, 120000
> > +                ],
> > +                "gain":
> > +                [
> > +                    1.0, 2.0, 4.0, 6.0, 6.0
> > +                ]
> > +            },
> > +            "short":
> > +            {
> > +                "shutter":
> > +                [
> > +                    100, 5000, 10000, 20000, 120000
> > +                ],
> > +                "gain":
> > +                [
> > +                    1.0, 2.0, 4.0, 6.0, 6.0
> > +                ]
> > +            }
> > +        },
> > +        "constraint_modes":
> > +        {
> > +            "normal":
> > +            [
> > +                {
> > +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
> > +                    [
> > +                        0, 0.5, 1000, 0.5
> > +                    ]
> > +                }
> > +            ],
> > +            "highlight":
> > +            [
> > +                {
> > +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
> > +                    [
> > +                        0, 0.5, 1000, 0.5
> > +                    ]
> > +                },
> > +                {
> > +                    "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
> > +                    [
> > +                        0, 0.8, 1000, 0.8
> > +                    ]
> > +                }
> > +            ]
> > +        },
> > +        "y_target":
> > +        [
> > +            0, 0.16, 1000, 0.165, 10000, 0.17
> > +        ]
> > +    },
> > +    "rpi.alsc":
> > +    {
> > +        "omega": 1.3,
> > +        "n_iter": 100,
> > +        "luminance_strength": 0.5,
> > +        "calibrations_Cr":
> > +        [
> > +            {
> > +                "ct": 3000, "table":
> > +                [
> > +                    1.527, 1.521, 1.508, 1.493, 1.476, 1.455, 1.442, 1.441, 1.441, 1.441, 1.448, 1.467, 1.483, 1.494, 1.503, 1.504,
> > +                    1.525, 1.513, 1.496, 1.477, 1.461, 1.434, 1.418, 1.409, 1.409, 1.416, 1.429, 1.449, 1.469, 1.485, 1.495, 1.503,
> > +                    1.517, 1.506, 1.485, 1.461, 1.434, 1.412, 1.388, 1.376, 1.376, 1.386, 1.405, 1.429, 1.449, 1.471, 1.488, 1.495,
> > +                    1.512, 1.496, 1.471, 1.442, 1.412, 1.388, 1.361, 1.344, 1.344, 1.358, 1.384, 1.405, 1.431, 1.456, 1.479, 1.489,
> > +                    1.508, 1.488, 1.458, 1.425, 1.393, 1.361, 1.343, 1.322, 1.321, 1.342, 1.358, 1.385, 1.416, 1.445, 1.471, 1.484,
> > +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.318, 1.318, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> > +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.313, 1.313, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> > +                    1.507, 1.485, 1.455, 1.422, 1.387, 1.355, 1.333, 1.319, 1.321, 1.333, 1.351, 1.381, 1.411, 1.441, 1.467, 1.483,
> > +                    1.508, 1.489, 1.463, 1.432, 1.401, 1.372, 1.355, 1.333, 1.333, 1.351, 1.369, 1.393, 1.422, 1.448, 1.471, 1.484,
> > +                    1.511, 1.494, 1.472, 1.444, 1.416, 1.398, 1.372, 1.361, 1.361, 1.369, 1.393, 1.411, 1.436, 1.458, 1.477, 1.487,
> > +                    1.511, 1.496, 1.478, 1.455, 1.436, 1.416, 1.399, 1.391, 1.391, 1.397, 1.411, 1.429, 1.451, 1.466, 1.479, 1.487,
> > +                    1.511, 1.495, 1.478, 1.462, 1.448, 1.432, 1.419, 1.419, 1.419, 1.419, 1.429, 1.445, 1.459, 1.471, 1.482, 1.487
> > +                ]
> > +            },
> > +            {
> > +                "ct": 6000, "table":
> > +                [
> > +                    2.581, 2.573, 2.558, 2.539, 2.514, 2.487, 2.473, 2.471, 2.471, 2.471, 2.479, 2.499, 2.517, 2.532, 2.543, 2.544,
> > +                    2.575, 2.559, 2.539, 2.521, 2.491, 2.458, 2.435, 2.421, 2.421, 2.429, 2.449, 2.477, 2.499, 2.519, 2.534, 2.543,
> > +                    2.561, 2.549, 2.521, 2.491, 2.457, 2.423, 2.393, 2.375, 2.375, 2.387, 2.412, 2.444, 2.475, 2.499, 2.519, 2.532,
> > +                    2.552, 2.531, 2.498, 2.459, 2.423, 2.391, 2.349, 2.325, 2.325, 2.344, 2.374, 2.412, 2.444, 2.476, 2.505, 2.519,
> > +                    2.543, 2.518, 2.479, 2.435, 2.392, 2.349, 2.324, 2.285, 2.283, 2.313, 2.344, 2.374, 2.417, 2.457, 2.489, 2.506,
> > +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.277, 2.279, 2.283, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> > +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.267, 2.267, 2.281, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> > +                    2.541, 2.512, 2.472, 2.425, 2.381, 2.338, 2.302, 2.278, 2.279, 2.301, 2.324, 2.364, 2.407, 2.447, 2.481, 2.504,
> > +                    2.544, 2.519, 2.483, 2.441, 2.401, 2.363, 2.338, 2.302, 2.302, 2.324, 2.355, 2.385, 2.423, 2.459, 2.488, 2.506,
> > +                    2.549, 2.527, 2.497, 2.463, 2.427, 2.401, 2.363, 2.345, 2.345, 2.355, 2.385, 2.412, 2.444, 2.473, 2.497, 2.509,
> > +                    2.552, 2.532, 2.507, 2.481, 2.459, 2.427, 2.402, 2.389, 2.389, 2.394, 2.412, 2.444, 2.465, 2.481, 2.499, 2.511,
> > +                    2.553, 2.533, 2.508, 2.489, 2.475, 2.454, 2.429, 2.429, 2.429, 2.429, 2.439, 2.463, 2.481, 2.492, 2.504, 2.511
> > +                ]
> > +            }
> > +        ],
> > +        "calibrations_Cb":
> > +        [
> > +            {
> > +                "ct": 3000, "table":
> > +                [
> > +                    3.132, 3.126, 3.116, 3.103, 3.097, 3.091, 3.087, 3.086, 3.088, 3.091, 3.092, 3.102, 3.113, 3.121, 3.141, 3.144,
> > +                    3.149, 3.132, 3.123, 3.108, 3.101, 3.096, 3.091, 3.089, 3.091, 3.092, 3.101, 3.107, 3.116, 3.129, 3.144, 3.153,
> > +                    3.161, 3.149, 3.129, 3.121, 3.108, 3.103, 3.101, 3.101, 3.101, 3.103, 3.107, 3.116, 3.125, 3.134, 3.153, 3.159,
> > +                    3.176, 3.161, 3.144, 3.129, 3.124, 3.121, 3.117, 3.118, 3.118, 3.119, 3.122, 3.125, 3.134, 3.146, 3.159, 3.171,
> > +                    3.183, 3.176, 3.157, 3.144, 3.143, 3.143, 3.139, 3.141, 3.141, 3.141, 3.141, 3.141, 3.146, 3.161, 3.171, 3.179,
> > +                    3.189, 3.183, 3.165, 3.157, 3.156, 3.157, 3.159, 3.163, 3.163, 3.163, 3.163, 3.161, 3.163, 3.169, 3.179, 3.187,
> > +                    3.199, 3.189, 3.171, 3.165, 3.164, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.169, 3.169, 3.175, 3.187, 3.189,
> > +                    3.206, 3.196, 3.177, 3.171, 3.165, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.171, 3.173, 3.177, 3.192, 3.194,
> > +                    3.209, 3.197, 3.178, 3.171, 3.164, 3.161, 3.159, 3.161, 3.162, 3.164, 3.167, 3.171, 3.173, 3.181, 3.193, 3.198,
> > +                    3.204, 3.194, 3.176, 3.165, 3.161, 3.156, 3.154, 3.154, 3.159, 3.161, 3.164, 3.168, 3.173, 3.182, 3.198, 3.199,
> > +                    3.199, 3.191, 3.176, 3.169, 3.161, 3.157, 3.153, 3.153, 3.156, 3.161, 3.164, 3.168, 3.173, 3.186, 3.196, 3.199,
> > +                    3.199, 3.188, 3.179, 3.173, 3.165, 3.157, 3.153, 3.154, 3.156, 3.159, 3.167, 3.171, 3.176, 3.185, 3.193, 3.198
> > +                ]
> > +            },
> > +            {
> > +                "ct": 6000, "table":
> > +                [
> > +                    1.579, 1.579, 1.577, 1.574, 1.573, 1.571, 1.571, 1.571, 1.571, 1.569, 1.569, 1.571, 1.572, 1.574, 1.577, 1.578,
> > +                    1.584, 1.579, 1.578, 1.575, 1.573, 1.572, 1.571, 1.572, 1.572, 1.571, 1.571, 1.572, 1.573, 1.576, 1.578, 1.579,
> > +                    1.587, 1.584, 1.579, 1.578, 1.575, 1.573, 1.573, 1.575, 1.575, 1.574, 1.573, 1.574, 1.576, 1.578, 1.581, 1.581,
> > +                    1.591, 1.587, 1.584, 1.579, 1.578, 1.579, 1.579, 1.581, 1.581, 1.581, 1.578, 1.577, 1.578, 1.581, 1.585, 1.586,
> > +                    1.595, 1.591, 1.587, 1.585, 1.585, 1.586, 1.587, 1.587, 1.588, 1.588, 1.585, 1.584, 1.584, 1.586, 1.589, 1.589,
> > +                    1.597, 1.595, 1.591, 1.589, 1.591, 1.593, 1.595, 1.596, 1.597, 1.597, 1.595, 1.594, 1.592, 1.592, 1.593, 1.593,
> > +                    1.601, 1.597, 1.593, 1.592, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.596, 1.595, 1.596, 1.595, 1.595,
> > +                    1.601, 1.599, 1.594, 1.593, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.597, 1.597, 1.597, 1.597, 1.597,
> > +                    1.602, 1.599, 1.594, 1.593, 1.592, 1.593, 1.595, 1.597, 1.597, 1.598, 1.598, 1.597, 1.597, 1.597, 1.598, 1.598,
> > +                    1.599, 1.598, 1.594, 1.592, 1.591, 1.591, 1.592, 1.595, 1.596, 1.597, 1.597, 1.597, 1.597, 1.599, 1.599, 1.599,
> > +                    1.598, 1.596, 1.594, 1.593, 1.592, 1.592, 1.592, 1.594, 1.595, 1.597, 1.597, 1.597, 1.598, 1.599, 1.599, 1.599,
> > +                    1.597, 1.595, 1.594, 1.594, 1.593, 1.592, 1.593, 1.595, 1.595, 1.597, 1.598, 1.598, 1.598, 1.599, 1.599, 1.599
> > +                ]
> > +            }
> > +        ],
> > +        "luminance_lut":
> > +        [
> > +            2.887, 2.754, 2.381, 2.105, 1.859, 1.678, 1.625, 1.623, 1.623, 1.624, 1.669, 1.849, 2.092, 2.362, 2.723, 2.838,
> > +            2.754, 2.443, 2.111, 1.905, 1.678, 1.542, 1.455, 1.412, 1.412, 1.452, 1.535, 1.665, 1.893, 2.096, 2.413, 2.723,
> > +            2.443, 2.216, 1.911, 1.678, 1.537, 1.372, 1.288, 1.245, 1.245, 1.283, 1.363, 1.527, 1.665, 1.895, 2.193, 2.413,
> > +            2.318, 2.057, 1.764, 1.541, 1.372, 1.282, 1.159, 1.113, 1.113, 1.151, 1.269, 1.363, 1.527, 1.749, 2.034, 2.278,
> > +            2.259, 1.953, 1.671, 1.452, 1.283, 1.159, 1.107, 1.018, 1.017, 1.097, 1.151, 1.269, 1.437, 1.655, 1.931, 2.222,
> > +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.019, 1.011, 1.005, 1.014, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> > +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.016, 1.001, 1.001, 1.007, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> > +            2.257, 1.946, 1.666, 1.448, 1.281, 1.153, 1.093, 1.013, 1.008, 1.089, 1.143, 1.269, 1.437, 1.654, 1.934, 2.226,
> > +            2.309, 2.044, 1.756, 1.532, 1.363, 1.259, 1.153, 1.093, 1.093, 1.143, 1.264, 1.354, 1.524, 1.746, 2.035, 2.284,
> > +            2.425, 2.201, 1.896, 1.662, 1.519, 1.363, 1.259, 1.214, 1.214, 1.264, 1.354, 1.519, 1.655, 1.888, 2.191, 2.413,
> > +            2.724, 2.417, 2.091, 1.888, 1.662, 1.519, 1.419, 1.373, 1.373, 1.425, 1.521, 1.655, 1.885, 2.089, 2.409, 2.722,
> > +            2.858, 2.724, 2.356, 2.085, 1.842, 1.658, 1.581, 1.577, 1.577, 1.579, 1.653, 1.838, 2.084, 2.359, 2.722, 2.842
> > +        ],
> > +        "sigma": 0.00372,
> > +        "sigma_Cb": 0.00244
> > +    },
> > +    "rpi.contrast":
> > +    {
> > +        "ce_enable": 1,
> > +        "gamma_curve":
> > +        [
> > +            0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193,
> > +            8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168,
> > +            16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796,
> > +            32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476,
> > +            65535, 65535
> > +        ]
> > +    },
> > +    "rpi.ccm":
> > +    {
> > +        "ccms":
> > +        [
> > +            {
> > +                "ct": 2890, "ccm":
> > +                [
> > +                    1.36754, -0.18448, -0.18306, -0.32356, 1.44826, -0.12471, -0.00412, -0.69936, 1.70348
> > +                ]
> > +            },
> > +            {
> > +                "ct": 2920, "ccm":
> > +                [
> > +                    1.26704, 0.01624, -0.28328, -0.28516, 1.38934, -0.10419, -0.04854, -0.82211, 1.87066
> > +                ]
> > +            },
> > +            {
> > +                "ct": 3550, "ccm":
> > +                [
> > +                    1.42836, -0.27235, -0.15601, -0.28751, 1.41075, -0.12325, -0.01812, -0.54849, 1.56661
> > +                ]
> > +            },
> > +            {
> > +                "ct": 4500, "ccm":
> > +                [
> > +                    1.36328, -0.19569, -0.16759, -0.25254, 1.52248, -0.26994, -0.01575, -0.53155, 1.54729
> > +                ]
> > +            },
> > +            {
> > +                "ct": 5700, "ccm":
> > +                [
> > +                    1.49207, -0.37245, -0.11963, -0.21493, 1.40005, -0.18512, -0.03781, -0.38779, 1.42561
> > +                ]
> > +            },
> > +            {
> > +                "ct": 7900, "ccm":
> > +                [
> > +                    1.34849, -0.05425, -0.29424, -0.22182, 1.77684, -0.55502, -0.07403, -0.55336, 1.62739
> > +                ]
> > +            }
> > +        ]
> > +    },
> > +    "rpi.sharpen":
> > +    {
> > +    }
> > +}
> > diff --git a/src/ipa/raspberrypi/data/meson.build b/src/ipa/raspberrypi/data/meson.build
> > index 2def75cb..e84cd099 100644
> > --- a/src/ipa/raspberrypi/data/meson.build
> > +++ b/src/ipa/raspberrypi/data/meson.build
> > @@ -7,6 +7,7 @@ conf_files = files([
> >      'imx378.json',
> >      'imx477.json',
> >      'imx477_noir.json',
> > +    'imx519.json',
> >      'ov5647.json',
> >      'ov5647_noir.json',
> >      'ov9281.json',
> > diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build
> > index 1af31e4a..176055f4 100644
> > --- a/src/ipa/raspberrypi/meson.build
> > +++ b/src/ipa/raspberrypi/meson.build
> > @@ -22,6 +22,7 @@ rpi_ipa_sources = files([
> >      'cam_helper_imx219.cpp',
> >      'cam_helper_imx290.cpp',
> >      'cam_helper_imx477.cpp',
> > +    'cam_helper_imx519.cpp',
> >      'cam_helper_ov9281.cpp',
> >      'controller/controller.cpp',
> >      'controller/histogram.cpp',
> > -- 
> > 2.20.1
> >
Naushir Patuck Nov. 2, 2021, 11:23 a.m. UTC | #4
Hi Kieran,

On Tue, 2 Nov 2021 at 11:19, Kieran Bingham <kieran.bingham@ideasonboard.com>
wrote:

> Quoting Kieran Bingham (2021-10-21 10:38:20)
> > Hi Lee, David,
> >
> > Quoting David Plowman (2021-10-20 14:23:34)
> > > From: Arducam info <info@arducam.com>
> > >
> > > The necessary tuning file and CamHelper is added for the imx519 sensor.
> > >
> > > The imx519 is a 16MP rolling shutter sensor. To enable
> > > it, please add
> > >
> > > dtoverlay=imx519
> > >
> >
> > Great, I'm glad to see new sensor support progressing.
> >
> > For this patch:
> >
> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >
> > I see the imx519 is integrated into the Raspberry Pi kernel, who will
> > take this forward and post to the linux-media to get it intgrated into
> > the kernel directly?
>
> Excellent, with
>  [PATCH 1/2] dt-bindings: media: i2c: Add IMX519 CMOS sensor binding
>
> https://lore.kernel.org/linux-media/38FCC5C9-9D03-4C8B-9ADF-896AE2BD90DE@arducam.com/T/#u
> and
>  [PATCH 2/2] media: i2c: Add driver for IMX519 sensor
>
> https://lore.kernel.org/linux-media/DBFF7F52-B763-4D54-8DC9-10508ECC7BD2@arducam.com/T/#u
>
> posted, I think we should get this integrated into libcamera now.
>
> David/Naush - I'm not able to test this. Is this fine to go in as it is?
>

Yup, happy to have this merged now.


> Any impacts on the recent MC series, or anything else?
>

There should not be any conflicts/impact with the MC series, which
incidentally is good to go as well :-)

Regards,
Naush



>
> --
> Kieran
>
>
> >
> > --
> > Kieran
> >
> > > to the /boot/config.txt file and reboot the Pi.
> > >
> > > Signed-off-by: Lee Jackson <info@arducam.com>
> > > Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
> > >
> > > ---
> > >  src/ipa/raspberrypi/cam_helper_imx519.cpp | 185 ++++++++++++
> > >  src/ipa/raspberrypi/data/imx519.json      | 338 ++++++++++++++++++++++
> > >  src/ipa/raspberrypi/data/meson.build      |   1 +
> > >  src/ipa/raspberrypi/meson.build           |   1 +
> > >  4 files changed, 525 insertions(+)
> > >  create mode 100644 src/ipa/raspberrypi/cam_helper_imx519.cpp
> > >  create mode 100644 src/ipa/raspberrypi/data/imx519.json
> > >
> > > diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp
> b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> > > new file mode 100644
> > > index 00000000..eaf24982
> > > --- /dev/null
> > > +++ b/src/ipa/raspberrypi/cam_helper_imx519.cpp
> > > @@ -0,0 +1,185 @@
> > > +/* SPDX-License-Identifier: BSD-2-Clause */
> > > +/*
> > > + * Based on cam_helper_imx477.cpp
> > > + * Copyright (C) 2020, Raspberry Pi (Trading) Limited
> > > + *
> > > + * cam_helper_imx519.cpp - camera helper for imx519 sensor
> > > + * Copyright (C) 2021, Arducam Technology co., Ltd.
> > > + */
> > > +
> > > +#include <assert.h>
> > > +#include <cmath>
> > > +#include <stddef.h>
> > > +#include <stdio.h>
> > > +#include <stdlib.h>
> > > +
> > > +#include <libcamera/base/log.h>
> > > +
> > > +#include "cam_helper.hpp"
> > > +#include "md_parser.hpp"
> > > +
> > > +using namespace RPiController;
> > > +using namespace libcamera;
> > > +using libcamera::utils::Duration;
> > > +
> > > +namespace libcamera {
> > > +LOG_DECLARE_CATEGORY(IPARPI)
> > > +}
> > > +
> > > +/*
> > > + * We care about two gain registers and a pair of exposure registers.
> Their
> > > + * I2C addresses from the Sony IMX519 datasheet:
> > > + */
> > > +constexpr uint32_t expHiReg = 0x0202;
> > > +constexpr uint32_t expLoReg = 0x0203;
> > > +constexpr uint32_t gainHiReg = 0x0204;
> > > +constexpr uint32_t gainLoReg = 0x0205;
> > > +constexpr uint32_t frameLengthHiReg = 0x0340;
> > > +constexpr uint32_t frameLengthLoReg = 0x0341;
> > > +constexpr std::initializer_list<uint32_t> registerList =
> > > +       { expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg,
> frameLengthLoReg  };
> > > +
> > > +class CamHelperImx519 : public CamHelper
> > > +{
> > > +public:
> > > +       CamHelperImx519();
> > > +       uint32_t GainCode(double gain) const override;
> > > +       double Gain(uint32_t gain_code) const override;
> > > +       void Prepare(libcamera::Span<const uint8_t> buffer, Metadata
> &metadata) override;
> > > +       uint32_t GetVBlanking(Duration &exposure, Duration
> minFrameDuration,
> > > +                             Duration maxFrameDuration) const
> override;
> > > +       void GetDelays(int &exposure_delay, int &gain_delay,
> > > +                      int &vblank_delay) const override;
> > > +       bool SensorEmbeddedDataPresent() const override;
> > > +
> > > +private:
> > > +       /*
> > > +        * Smallest difference between the frame length and
> integration time,
> > > +        * in units of lines.
> > > +        */
> > > +       static constexpr int frameIntegrationDiff = 32;
> > > +       /* Maximum frame length allowable for long exposure
> calculations. */
> > > +       static constexpr int frameLengthMax = 0xffdc;
> > > +       /* Largest long exposure scale factor given as a left shift on
> the frame length. */
> > > +       static constexpr int longExposureShiftMax = 7;
> > > +
> > > +       void PopulateMetadata(const MdParser::RegisterMap &registers,
> > > +                             Metadata &metadata) const override;
> > > +};
> > > +
> > > +CamHelperImx519::CamHelperImx519()
> > > +       : CamHelper(std::make_unique<MdParserSmia>(registerList),
> frameIntegrationDiff)
> > > +{
> > > +}
> > > +
> > > +uint32_t CamHelperImx519::GainCode(double gain) const
> > > +{
> > > +       return static_cast<uint32_t>(1024 - 1024 / gain);
> > > +}
> > > +
> > > +double CamHelperImx519::Gain(uint32_t gain_code) const
> > > +{
> > > +       return 1024.0 / (1024 - gain_code);
> > > +}
> > > +
> > > +void CamHelperImx519::Prepare(libcamera::Span<const uint8_t> buffer,
> Metadata &metadata)
> > > +{
> > > +       MdParser::RegisterMap registers;
> > > +       DeviceStatus deviceStatus;
> > > +
> > > +       if (metadata.Get("device.status", deviceStatus)) {
> > > +               LOG(IPARPI, Error) << "DeviceStatus not found from
> DelayedControls";
> > > +               return;
> > > +       }
> > > +
> > > +       parseEmbeddedData(buffer, metadata);
> > > +
> > > +       /*
> > > +        * The DeviceStatus struct is first populated with values
> obtained from
> > > +        * DelayedControls. If this reports frame length is >
> frameLengthMax,
> > > +        * it means we are using a long exposure mode. Since the long
> exposure
> > > +        * scale factor is not returned back through embedded data, we
> must rely
> > > +        * on the existing exposure lines and frame length values
> returned by
> > > +        * DelayedControls.
> > > +        *
> > > +        * Otherwise, all values are updated with what is reported in
> the
> > > +        * embedded data.
> > > +        */
> > > +       if (deviceStatus.frame_length > frameLengthMax) {
> > > +               DeviceStatus parsedDeviceStatus;
> > > +
> > > +               metadata.Get("device.status", parsedDeviceStatus);
> > > +               parsedDeviceStatus.shutter_speed =
> deviceStatus.shutter_speed;
> > > +               parsedDeviceStatus.frame_length =
> deviceStatus.frame_length;
> > > +               metadata.Set("device.status", parsedDeviceStatus);
> > > +
> > > +               LOG(IPARPI, Debug) << "Metadata updated for long
> exposure: "
> > > +                                  << parsedDeviceStatus;
> > > +       }
> > > +}
> > > +
> > > +uint32_t CamHelperImx519::GetVBlanking(Duration &exposure,
> > > +                                      Duration minFrameDuration,
> > > +                                      Duration maxFrameDuration) const
> > > +{
> > > +       uint32_t frameLength, exposureLines;
> > > +       unsigned int shift = 0;
> > > +
> > > +       frameLength = mode_.height + CamHelper::GetVBlanking(exposure,
> minFrameDuration,
> > > +
> maxFrameDuration);
> > > +       /*
> > > +        * Check if the frame length calculated needs to be setup for
> long
> > > +        * exposure mode. This will require us to use a long exposure
> scale
> > > +        * factor provided by a shift operation in the sensor.
> > > +        */
> > > +       while (frameLength > frameLengthMax) {
> > > +               if (++shift > longExposureShiftMax) {
> > > +                       shift = longExposureShiftMax;
> > > +                       frameLength = frameLengthMax;
> > > +                       break;
> > > +               }
> > > +               frameLength >>= 1;
> > > +       }
> > > +
> > > +       if (shift) {
> > > +               /* Account for any rounding in the scaled frame length
> value. */
> > > +               frameLength <<= shift;
> > > +               exposureLines = ExposureLines(exposure);
> > > +               exposureLines = std::min(exposureLines, frameLength -
> frameIntegrationDiff);
> > > +               exposure = Exposure(exposureLines);
> > > +       }
> > > +
> > > +       return frameLength - mode_.height;
> > > +}
> > > +
> > > +void CamHelperImx519::GetDelays(int &exposure_delay, int &gain_delay,
> > > +                               int &vblank_delay) const
> > > +{
> > > +       exposure_delay = 2;
> > > +       gain_delay = 2;
> > > +       vblank_delay = 3;
> > > +}
> > > +
> > > +bool CamHelperImx519::SensorEmbeddedDataPresent() const
> > > +{
> > > +       return true;
> > > +}
> > > +
> > > +void CamHelperImx519::PopulateMetadata(const MdParser::RegisterMap
> &registers,
> > > +                                      Metadata &metadata) const
> > > +{
> > > +       DeviceStatus deviceStatus;
> > > +
> > > +       deviceStatus.shutter_speed = Exposure(registers.at(expHiReg)
> * 256 + registers.at(expLoReg));
> > > +       deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) *
> 256 + registers.at(gainLoReg));
> > > +       deviceStatus.frame_length = registers.at(frameLengthHiReg) *
> 256 + registers.at(frameLengthLoReg);
> > > +
> > > +       metadata.Set("device.status", deviceStatus);
> > > +}
> > > +
> > > +static CamHelper *Create()
> > > +{
> > > +       return new CamHelperImx519();
> > > +}
> > > +
> > > +static RegisterCamHelper reg("imx519", &Create);
> > > diff --git a/src/ipa/raspberrypi/data/imx519.json
> b/src/ipa/raspberrypi/data/imx519.json
> > > new file mode 100644
> > > index 00000000..164d0d9d
> > > --- /dev/null
> > > +++ b/src/ipa/raspberrypi/data/imx519.json
> > > @@ -0,0 +1,338 @@
> > > +{
> > > +    "rpi.black_level":
> > > +    {
> > > +        "black_level": 4096
> > > +    },
> > > +    "rpi.dpc":
> > > +    {
> > > +    },
> > > +    "rpi.lux":
> > > +    {
> > > +        "reference_shutter_speed": 13841,
> > > +        "reference_gain": 2.0,
> > > +        "reference_aperture": 1.0,
> > > +        "reference_lux": 900,
> > > +        "reference_Y": 12064
> > > +    },
> > > +    "rpi.noise":
> > > +    {
> > > +        "reference_constant": 0,
> > > +        "reference_slope": 2.776
> > > +    },
> > > +    "rpi.geq":
> > > +    {
> > > +        "offset": 189,
> > > +        "slope": 0.01495
> > > +    },
> > > +    "rpi.sdn":
> > > +    {
> > > +    },
> > > +    "rpi.awb":
> > > +    {
> > > +        "priors":
> > > +        [
> > > +            {
> > > +                "lux": 0, "prior":
> > > +                [
> > > +                    2000, 1.0, 3000, 0.0, 13000, 0.0
> > > +                ]
> > > +            },
> > > +            {
> > > +                "lux": 800, "prior":
> > > +                [
> > > +                    2000, 0.0, 6000, 2.0, 13000, 2.0
> > > +                ]
> > > +            },
> > > +            {
> > > +                "lux": 1500, "prior":
> > > +                [
> > > +                    2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000,
> 1.0, 13000, 1.0
> > > +                ]
> > > +            }
> > > +        ],
> > > +        "modes":
> > > +        {
> > > +            "auto":
> > > +            {
> > > +                "lo": 2500,
> > > +                "hi": 7900
> > > +            },
> > > +            "incandescent":
> > > +            {
> > > +                "lo": 2500,
> > > +                "hi": 3000
> > > +            },
> > > +            "tungsten":
> > > +            {
> > > +                "lo": 3000,
> > > +                "hi": 3500
> > > +            },
> > > +            "fluorescent":
> > > +            {
> > > +                "lo": 4000,
> > > +                "hi": 4700
> > > +            },
> > > +            "indoor":
> > > +            {
> > > +                "lo": 3000,
> > > +                "hi": 5000
> > > +            },
> > > +            "daylight":
> > > +            {
> > > +                "lo": 5500,
> > > +                "hi": 6500
> > > +            },
> > > +            "cloudy":
> > > +            {
> > > +                "lo": 7000,
> > > +                "hi": 8000
> > > +            }
> > > +        },
> > > +        "bayes": 1,
> > > +        "ct_curve":
> > > +        [
> > > +            2890.0, 0.7328, 0.3734, 3550.0, 0.6228, 0.4763, 4500.0,
> 0.5208, 0.5825, 5700.0, 0.4467, 0.6671, 7900.0, 0.3858, 0.7411
> > > +        ],
> > > +        "sensitivity_r": 1.0,
> > > +        "sensitivity_b": 1.0,
> > > +        "transverse_pos": 0.02027,
> > > +        "transverse_neg": 0.01935
> > > +    },
> > > +    "rpi.agc":
> > > +    {
> > > +        "metering_modes":
> > > +        {
> > > +            "centre-weighted":
> > > +            {
> > > +                "weights":
> > > +                [
> > > +                    3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
> > > +                ]
> > > +            },
> > > +            "spot":
> > > +            {
> > > +                "weights":
> > > +                [
> > > +                    2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
> > > +                ]
> > > +            },
> > > +            "matrix":
> > > +            {
> > > +                "weights":
> > > +                [
> > > +                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
> > > +                ]
> > > +            }
> > > +        },
> > > +        "exposure_modes":
> > > +        {
> > > +            "normal":
> > > +            {
> > > +                "shutter":
> > > +                [
> > > +                    100, 10000, 30000, 60000, 120000
> > > +                ],
> > > +                "gain":
> > > +                [
> > > +                    1.0, 2.0, 4.0, 6.0, 6.0
> > > +                ]
> > > +            },
> > > +            "short":
> > > +            {
> > > +                "shutter":
> > > +                [
> > > +                    100, 5000, 10000, 20000, 120000
> > > +                ],
> > > +                "gain":
> > > +                [
> > > +                    1.0, 2.0, 4.0, 6.0, 6.0
> > > +                ]
> > > +            }
> > > +        },
> > > +        "constraint_modes":
> > > +        {
> > > +            "normal":
> > > +            [
> > > +                {
> > > +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0,
> "y_target":
> > > +                    [
> > > +                        0, 0.5, 1000, 0.5
> > > +                    ]
> > > +                }
> > > +            ],
> > > +            "highlight":
> > > +            [
> > > +                {
> > > +                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0,
> "y_target":
> > > +                    [
> > > +                        0, 0.5, 1000, 0.5
> > > +                    ]
> > > +                },
> > > +                {
> > > +                    "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0,
> "y_target":
> > > +                    [
> > > +                        0, 0.8, 1000, 0.8
> > > +                    ]
> > > +                }
> > > +            ]
> > > +        },
> > > +        "y_target":
> > > +        [
> > > +            0, 0.16, 1000, 0.165, 10000, 0.17
> > > +        ]
> > > +    },
> > > +    "rpi.alsc":
> > > +    {
> > > +        "omega": 1.3,
> > > +        "n_iter": 100,
> > > +        "luminance_strength": 0.5,
> > > +        "calibrations_Cr":
> > > +        [
> > > +            {
> > > +                "ct": 3000, "table":
> > > +                [
> > > +                    1.527, 1.521, 1.508, 1.493, 1.476, 1.455, 1.442,
> 1.441, 1.441, 1.441, 1.448, 1.467, 1.483, 1.494, 1.503, 1.504,
> > > +                    1.525, 1.513, 1.496, 1.477, 1.461, 1.434, 1.418,
> 1.409, 1.409, 1.416, 1.429, 1.449, 1.469, 1.485, 1.495, 1.503,
> > > +                    1.517, 1.506, 1.485, 1.461, 1.434, 1.412, 1.388,
> 1.376, 1.376, 1.386, 1.405, 1.429, 1.449, 1.471, 1.488, 1.495,
> > > +                    1.512, 1.496, 1.471, 1.442, 1.412, 1.388, 1.361,
> 1.344, 1.344, 1.358, 1.384, 1.405, 1.431, 1.456, 1.479, 1.489,
> > > +                    1.508, 1.488, 1.458, 1.425, 1.393, 1.361, 1.343,
> 1.322, 1.321, 1.342, 1.358, 1.385, 1.416, 1.445, 1.471, 1.484,
> > > +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322,
> 1.318, 1.318, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> > > +                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322,
> 1.313, 1.313, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
> > > +                    1.507, 1.485, 1.455, 1.422, 1.387, 1.355, 1.333,
> 1.319, 1.321, 1.333, 1.351, 1.381, 1.411, 1.441, 1.467, 1.483,
> > > +                    1.508, 1.489, 1.463, 1.432, 1.401, 1.372, 1.355,
> 1.333, 1.333, 1.351, 1.369, 1.393, 1.422, 1.448, 1.471, 1.484,
> > > +                    1.511, 1.494, 1.472, 1.444, 1.416, 1.398, 1.372,
> 1.361, 1.361, 1.369, 1.393, 1.411, 1.436, 1.458, 1.477, 1.487,
> > > +                    1.511, 1.496, 1.478, 1.455, 1.436, 1.416, 1.399,
> 1.391, 1.391, 1.397, 1.411, 1.429, 1.451, 1.466, 1.479, 1.487,
> > > +                    1.511, 1.495, 1.478, 1.462, 1.448, 1.432, 1.419,
> 1.419, 1.419, 1.419, 1.429, 1.445, 1.459, 1.471, 1.482, 1.487
> > > +                ]
> > > +            },
> > > +            {
> > > +                "ct": 6000, "table":
> > > +                [
> > > +                    2.581, 2.573, 2.558, 2.539, 2.514, 2.487, 2.473,
> 2.471, 2.471, 2.471, 2.479, 2.499, 2.517, 2.532, 2.543, 2.544,
> > > +                    2.575, 2.559, 2.539, 2.521, 2.491, 2.458, 2.435,
> 2.421, 2.421, 2.429, 2.449, 2.477, 2.499, 2.519, 2.534, 2.543,
> > > +                    2.561, 2.549, 2.521, 2.491, 2.457, 2.423, 2.393,
> 2.375, 2.375, 2.387, 2.412, 2.444, 2.475, 2.499, 2.519, 2.532,
> > > +                    2.552, 2.531, 2.498, 2.459, 2.423, 2.391, 2.349,
> 2.325, 2.325, 2.344, 2.374, 2.412, 2.444, 2.476, 2.505, 2.519,
> > > +                    2.543, 2.518, 2.479, 2.435, 2.392, 2.349, 2.324,
> 2.285, 2.283, 2.313, 2.344, 2.374, 2.417, 2.457, 2.489, 2.506,
> > > +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284,
> 2.277, 2.279, 2.283, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> > > +                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284,
> 2.267, 2.267, 2.281, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
> > > +                    2.541, 2.512, 2.472, 2.425, 2.381, 2.338, 2.302,
> 2.278, 2.279, 2.301, 2.324, 2.364, 2.407, 2.447, 2.481, 2.504,
> > > +                    2.544, 2.519, 2.483, 2.441, 2.401, 2.363, 2.338,
> 2.302, 2.302, 2.324, 2.355, 2.385, 2.423, 2.459, 2.488, 2.506,
> > > +                    2.549, 2.527, 2.497, 2.463, 2.427, 2.401, 2.363,
> 2.345, 2.345, 2.355, 2.385, 2.412, 2.444, 2.473, 2.497, 2.509,
> > > +                    2.552, 2.532, 2.507, 2.481, 2.459, 2.427, 2.402,
> 2.389, 2.389, 2.394, 2.412, 2.444, 2.465, 2.481, 2.499, 2.511,
> > > +                    2.553, 2.533, 2.508, 2.489, 2.475, 2.454, 2.429,
> 2.429, 2.429, 2.429, 2.439, 2.463, 2.481, 2.492, 2.504, 2.511
> > > +                ]
> > > +            }
> > > +        ],
> > > +        "calibrations_Cb":
> > > +        [
> > > +            {
> > > +                "ct": 3000, "table":
> > > +                [
> > > +                    3.132, 3.126, 3.116, 3.103, 3.097, 3.091, 3.087,
> 3.086, 3.088, 3.091, 3.092, 3.102, 3.113, 3.121, 3.141, 3.144,
> > > +                    3.149, 3.132, 3.123, 3.108, 3.101, 3.096, 3.091,
> 3.089, 3.091, 3.092, 3.101, 3.107, 3.116, 3.129, 3.144, 3.153,
> > > +                    3.161, 3.149, 3.129, 3.121, 3.108, 3.103, 3.101,
> 3.101, 3.101, 3.103, 3.107, 3.116, 3.125, 3.134, 3.153, 3.159,
> > > +                    3.176, 3.161, 3.144, 3.129, 3.124, 3.121, 3.117,
> 3.118, 3.118, 3.119, 3.122, 3.125, 3.134, 3.146, 3.159, 3.171,
> > > +                    3.183, 3.176, 3.157, 3.144, 3.143, 3.143, 3.139,
> 3.141, 3.141, 3.141, 3.141, 3.141, 3.146, 3.161, 3.171, 3.179,
> > > +                    3.189, 3.183, 3.165, 3.157, 3.156, 3.157, 3.159,
> 3.163, 3.163, 3.163, 3.163, 3.161, 3.163, 3.169, 3.179, 3.187,
> > > +                    3.199, 3.189, 3.171, 3.165, 3.164, 3.167, 3.171,
> 3.173, 3.173, 3.172, 3.171, 3.169, 3.169, 3.175, 3.187, 3.189,
> > > +                    3.206, 3.196, 3.177, 3.171, 3.165, 3.167, 3.171,
> 3.173, 3.173, 3.172, 3.171, 3.171, 3.173, 3.177, 3.192, 3.194,
> > > +                    3.209, 3.197, 3.178, 3.171, 3.164, 3.161, 3.159,
> 3.161, 3.162, 3.164, 3.167, 3.171, 3.173, 3.181, 3.193, 3.198,
> > > +                    3.204, 3.194, 3.176, 3.165, 3.161, 3.156, 3.154,
> 3.154, 3.159, 3.161, 3.164, 3.168, 3.173, 3.182, 3.198, 3.199,
> > > +                    3.199, 3.191, 3.176, 3.169, 3.161, 3.157, 3.153,
> 3.153, 3.156, 3.161, 3.164, 3.168, 3.173, 3.186, 3.196, 3.199,
> > > +                    3.199, 3.188, 3.179, 3.173, 3.165, 3.157, 3.153,
> 3.154, 3.156, 3.159, 3.167, 3.171, 3.176, 3.185, 3.193, 3.198
> > > +                ]
> > > +            },
> > > +            {
> > > +                "ct": 6000, "table":
> > > +                [
> > > +                    1.579, 1.579, 1.577, 1.574, 1.573, 1.571, 1.571,
> 1.571, 1.571, 1.569, 1.569, 1.571, 1.572, 1.574, 1.577, 1.578,
> > > +                    1.584, 1.579, 1.578, 1.575, 1.573, 1.572, 1.571,
> 1.572, 1.572, 1.571, 1.571, 1.572, 1.573, 1.576, 1.578, 1.579,
> > > +                    1.587, 1.584, 1.579, 1.578, 1.575, 1.573, 1.573,
> 1.575, 1.575, 1.574, 1.573, 1.574, 1.576, 1.578, 1.581, 1.581,
> > > +                    1.591, 1.587, 1.584, 1.579, 1.578, 1.579, 1.579,
> 1.581, 1.581, 1.581, 1.578, 1.577, 1.578, 1.581, 1.585, 1.586,
> > > +                    1.595, 1.591, 1.587, 1.585, 1.585, 1.586, 1.587,
> 1.587, 1.588, 1.588, 1.585, 1.584, 1.584, 1.586, 1.589, 1.589,
> > > +                    1.597, 1.595, 1.591, 1.589, 1.591, 1.593, 1.595,
> 1.596, 1.597, 1.597, 1.595, 1.594, 1.592, 1.592, 1.593, 1.593,
> > > +                    1.601, 1.597, 1.593, 1.592, 1.593, 1.595, 1.598,
> 1.599, 1.602, 1.601, 1.598, 1.596, 1.595, 1.596, 1.595, 1.595,
> > > +                    1.601, 1.599, 1.594, 1.593, 1.593, 1.595, 1.598,
> 1.599, 1.602, 1.601, 1.598, 1.597, 1.597, 1.597, 1.597, 1.597,
> > > +                    1.602, 1.599, 1.594, 1.593, 1.592, 1.593, 1.595,
> 1.597, 1.597, 1.598, 1.598, 1.597, 1.597, 1.597, 1.598, 1.598,
> > > +                    1.599, 1.598, 1.594, 1.592, 1.591, 1.591, 1.592,
> 1.595, 1.596, 1.597, 1.597, 1.597, 1.597, 1.599, 1.599, 1.599,
> > > +                    1.598, 1.596, 1.594, 1.593, 1.592, 1.592, 1.592,
> 1.594, 1.595, 1.597, 1.597, 1.597, 1.598, 1.599, 1.599, 1.599,
> > > +                    1.597, 1.595, 1.594, 1.594, 1.593, 1.592, 1.593,
> 1.595, 1.595, 1.597, 1.598, 1.598, 1.598, 1.599, 1.599, 1.599
> > > +                ]
> > > +            }
> > > +        ],
> > > +        "luminance_lut":
> > > +        [
> > > +            2.887, 2.754, 2.381, 2.105, 1.859, 1.678, 1.625, 1.623,
> 1.623, 1.624, 1.669, 1.849, 2.092, 2.362, 2.723, 2.838,
> > > +            2.754, 2.443, 2.111, 1.905, 1.678, 1.542, 1.455, 1.412,
> 1.412, 1.452, 1.535, 1.665, 1.893, 2.096, 2.413, 2.723,
> > > +            2.443, 2.216, 1.911, 1.678, 1.537, 1.372, 1.288, 1.245,
> 1.245, 1.283, 1.363, 1.527, 1.665, 1.895, 2.193, 2.413,
> > > +            2.318, 2.057, 1.764, 1.541, 1.372, 1.282, 1.159, 1.113,
> 1.113, 1.151, 1.269, 1.363, 1.527, 1.749, 2.034, 2.278,
> > > +            2.259, 1.953, 1.671, 1.452, 1.283, 1.159, 1.107, 1.018,
> 1.017, 1.097, 1.151, 1.269, 1.437, 1.655, 1.931, 2.222,
> > > +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.019, 1.011,
> 1.005, 1.014, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> > > +            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.016, 1.001,
> 1.001, 1.007, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
> > > +            2.257, 1.946, 1.666, 1.448, 1.281, 1.153, 1.093, 1.013,
> 1.008, 1.089, 1.143, 1.269, 1.437, 1.654, 1.934, 2.226,
> > > +            2.309, 2.044, 1.756, 1.532, 1.363, 1.259, 1.153, 1.093,
> 1.093, 1.143, 1.264, 1.354, 1.524, 1.746, 2.035, 2.284,
> > > +            2.425, 2.201, 1.896, 1.662, 1.519, 1.363, 1.259, 1.214,
> 1.214, 1.264, 1.354, 1.519, 1.655, 1.888, 2.191, 2.413,
> > > +            2.724, 2.417, 2.091, 1.888, 1.662, 1.519, 1.419, 1.373,
> 1.373, 1.425, 1.521, 1.655, 1.885, 2.089, 2.409, 2.722,
> > > +            2.858, 2.724, 2.356, 2.085, 1.842, 1.658, 1.581, 1.577,
> 1.577, 1.579, 1.653, 1.838, 2.084, 2.359, 2.722, 2.842
> > > +        ],
> > > +        "sigma": 0.00372,
> > > +        "sigma_Cb": 0.00244
> > > +    },
> > > +    "rpi.contrast":
> > > +    {
> > > +        "ce_enable": 1,
> > > +        "gamma_curve":
> > > +        [
> > > +            0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312,
> 5120, 18051, 6144, 20790, 7168, 23193,
> > > +            8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005,
> 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168,
> > > +            16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753,
> 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796,
> > > +            32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954,
> 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476,
> > > +            65535, 65535
> > > +        ]
> > > +    },
> > > +    "rpi.ccm":
> > > +    {
> > > +        "ccms":
> > > +        [
> > > +            {
> > > +                "ct": 2890, "ccm":
> > > +                [
> > > +                    1.36754, -0.18448, -0.18306, -0.32356, 1.44826,
> -0.12471, -0.00412, -0.69936, 1.70348
> > > +                ]
> > > +            },
> > > +            {
> > > +                "ct": 2920, "ccm":
> > > +                [
> > > +                    1.26704, 0.01624, -0.28328, -0.28516, 1.38934,
> -0.10419, -0.04854, -0.82211, 1.87066
> > > +                ]
> > > +            },
> > > +            {
> > > +                "ct": 3550, "ccm":
> > > +                [
> > > +                    1.42836, -0.27235, -0.15601, -0.28751, 1.41075,
> -0.12325, -0.01812, -0.54849, 1.56661
> > > +                ]
> > > +            },
> > > +            {
> > > +                "ct": 4500, "ccm":
> > > +                [
> > > +                    1.36328, -0.19569, -0.16759, -0.25254, 1.52248,
> -0.26994, -0.01575, -0.53155, 1.54729
> > > +                ]
> > > +            },
> > > +            {
> > > +                "ct": 5700, "ccm":
> > > +                [
> > > +                    1.49207, -0.37245, -0.11963, -0.21493, 1.40005,
> -0.18512, -0.03781, -0.38779, 1.42561
> > > +                ]
> > > +            },
> > > +            {
> > > +                "ct": 7900, "ccm":
> > > +                [
> > > +                    1.34849, -0.05425, -0.29424, -0.22182, 1.77684,
> -0.55502, -0.07403, -0.55336, 1.62739
> > > +                ]
> > > +            }
> > > +        ]
> > > +    },
> > > +    "rpi.sharpen":
> > > +    {
> > > +    }
> > > +}
> > > diff --git a/src/ipa/raspberrypi/data/meson.build
> b/src/ipa/raspberrypi/data/meson.build
> > > index 2def75cb..e84cd099 100644
> > > --- a/src/ipa/raspberrypi/data/meson.build
> > > +++ b/src/ipa/raspberrypi/data/meson.build
> > > @@ -7,6 +7,7 @@ conf_files = files([
> > >      'imx378.json',
> > >      'imx477.json',
> > >      'imx477_noir.json',
> > > +    'imx519.json',
> > >      'ov5647.json',
> > >      'ov5647_noir.json',
> > >      'ov9281.json',
> > > diff --git a/src/ipa/raspberrypi/meson.build
> b/src/ipa/raspberrypi/meson.build
> > > index 1af31e4a..176055f4 100644
> > > --- a/src/ipa/raspberrypi/meson.build
> > > +++ b/src/ipa/raspberrypi/meson.build
> > > @@ -22,6 +22,7 @@ rpi_ipa_sources = files([
> > >      'cam_helper_imx219.cpp',
> > >      'cam_helper_imx290.cpp',
> > >      'cam_helper_imx477.cpp',
> > > +    'cam_helper_imx519.cpp',
> > >      'cam_helper_ov9281.cpp',
> > >      'controller/controller.cpp',
> > >      'controller/histogram.cpp',
> > > --
> > > 2.20.1
> > >
>

Patch
diff mbox series

diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp b/src/ipa/raspberrypi/cam_helper_imx519.cpp
new file mode 100644
index 00000000..eaf24982
--- /dev/null
+++ b/src/ipa/raspberrypi/cam_helper_imx519.cpp
@@ -0,0 +1,185 @@ 
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Based on cam_helper_imx477.cpp
+ * Copyright (C) 2020, Raspberry Pi (Trading) Limited
+ *
+ * cam_helper_imx519.cpp - camera helper for imx519 sensor
+ * Copyright (C) 2021, Arducam Technology co., Ltd.
+ */
+
+#include <assert.h>
+#include <cmath>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libcamera/base/log.h>
+
+#include "cam_helper.hpp"
+#include "md_parser.hpp"
+
+using namespace RPiController;
+using namespace libcamera;
+using libcamera::utils::Duration;
+
+namespace libcamera {
+LOG_DECLARE_CATEGORY(IPARPI)
+}
+
+/*
+ * We care about two gain registers and a pair of exposure registers. Their
+ * I2C addresses from the Sony IMX519 datasheet:
+ */
+constexpr uint32_t expHiReg = 0x0202;
+constexpr uint32_t expLoReg = 0x0203;
+constexpr uint32_t gainHiReg = 0x0204;
+constexpr uint32_t gainLoReg = 0x0205;
+constexpr uint32_t frameLengthHiReg = 0x0340;
+constexpr uint32_t frameLengthLoReg = 0x0341;
+constexpr std::initializer_list<uint32_t> registerList =
+	{ expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg, frameLengthLoReg  };
+
+class CamHelperImx519 : public CamHelper
+{
+public:
+	CamHelperImx519();
+	uint32_t GainCode(double gain) const override;
+	double Gain(uint32_t gain_code) const override;
+	void Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override;
+	uint32_t GetVBlanking(Duration &exposure, Duration minFrameDuration,
+			      Duration maxFrameDuration) const override;
+	void GetDelays(int &exposure_delay, int &gain_delay,
+		       int &vblank_delay) const override;
+	bool SensorEmbeddedDataPresent() const override;
+
+private:
+	/*
+	 * Smallest difference between the frame length and integration time,
+	 * in units of lines.
+	 */
+	static constexpr int frameIntegrationDiff = 32;
+	/* Maximum frame length allowable for long exposure calculations. */
+	static constexpr int frameLengthMax = 0xffdc;
+	/* Largest long exposure scale factor given as a left shift on the frame length. */
+	static constexpr int longExposureShiftMax = 7;
+
+	void PopulateMetadata(const MdParser::RegisterMap &registers,
+			      Metadata &metadata) const override;
+};
+
+CamHelperImx519::CamHelperImx519()
+	: CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff)
+{
+}
+
+uint32_t CamHelperImx519::GainCode(double gain) const
+{
+	return static_cast<uint32_t>(1024 - 1024 / gain);
+}
+
+double CamHelperImx519::Gain(uint32_t gain_code) const
+{
+	return 1024.0 / (1024 - gain_code);
+}
+
+void CamHelperImx519::Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata)
+{
+	MdParser::RegisterMap registers;
+	DeviceStatus deviceStatus;
+
+	if (metadata.Get("device.status", deviceStatus)) {
+		LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls";
+		return;
+	}
+
+	parseEmbeddedData(buffer, metadata);
+
+	/*
+	 * The DeviceStatus struct is first populated with values obtained from
+	 * DelayedControls. If this reports frame length is > frameLengthMax,
+	 * it means we are using a long exposure mode. Since the long exposure
+	 * scale factor is not returned back through embedded data, we must rely
+	 * on the existing exposure lines and frame length values returned by
+	 * DelayedControls.
+	 *
+	 * Otherwise, all values are updated with what is reported in the
+	 * embedded data.
+	 */
+	if (deviceStatus.frame_length > frameLengthMax) {
+		DeviceStatus parsedDeviceStatus;
+
+		metadata.Get("device.status", parsedDeviceStatus);
+		parsedDeviceStatus.shutter_speed = deviceStatus.shutter_speed;
+		parsedDeviceStatus.frame_length = deviceStatus.frame_length;
+		metadata.Set("device.status", parsedDeviceStatus);
+
+		LOG(IPARPI, Debug) << "Metadata updated for long exposure: "
+				   << parsedDeviceStatus;
+	}
+}
+
+uint32_t CamHelperImx519::GetVBlanking(Duration &exposure,
+				       Duration minFrameDuration,
+				       Duration maxFrameDuration) const
+{
+	uint32_t frameLength, exposureLines;
+	unsigned int shift = 0;
+
+	frameLength = mode_.height + CamHelper::GetVBlanking(exposure, minFrameDuration,
+							     maxFrameDuration);
+	/*
+	 * Check if the frame length calculated needs to be setup for long
+	 * exposure mode. This will require us to use a long exposure scale
+	 * factor provided by a shift operation in the sensor.
+	 */
+	while (frameLength > frameLengthMax) {
+		if (++shift > longExposureShiftMax) {
+			shift = longExposureShiftMax;
+			frameLength = frameLengthMax;
+			break;
+		}
+		frameLength >>= 1;
+	}
+
+	if (shift) {
+		/* Account for any rounding in the scaled frame length value. */
+		frameLength <<= shift;
+		exposureLines = ExposureLines(exposure);
+		exposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);
+		exposure = Exposure(exposureLines);
+	}
+
+	return frameLength - mode_.height;
+}
+
+void CamHelperImx519::GetDelays(int &exposure_delay, int &gain_delay,
+				int &vblank_delay) const
+{
+	exposure_delay = 2;
+	gain_delay = 2;
+	vblank_delay = 3;
+}
+
+bool CamHelperImx519::SensorEmbeddedDataPresent() const
+{
+	return true;
+}
+
+void CamHelperImx519::PopulateMetadata(const MdParser::RegisterMap &registers,
+				       Metadata &metadata) const
+{
+	DeviceStatus deviceStatus;
+
+	deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg));
+	deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg));
+	deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);
+
+	metadata.Set("device.status", deviceStatus);
+}
+
+static CamHelper *Create()
+{
+	return new CamHelperImx519();
+}
+
+static RegisterCamHelper reg("imx519", &Create);
diff --git a/src/ipa/raspberrypi/data/imx519.json b/src/ipa/raspberrypi/data/imx519.json
new file mode 100644
index 00000000..164d0d9d
--- /dev/null
+++ b/src/ipa/raspberrypi/data/imx519.json
@@ -0,0 +1,338 @@ 
+{
+    "rpi.black_level":
+    {
+        "black_level": 4096
+    },
+    "rpi.dpc":
+    {
+    },
+    "rpi.lux":
+    {
+        "reference_shutter_speed": 13841,
+        "reference_gain": 2.0,
+        "reference_aperture": 1.0,
+        "reference_lux": 900,
+        "reference_Y": 12064
+    },
+    "rpi.noise":
+    {
+        "reference_constant": 0,
+        "reference_slope": 2.776
+    },
+    "rpi.geq":
+    {
+        "offset": 189,
+        "slope": 0.01495
+    },
+    "rpi.sdn":
+    {
+    },
+    "rpi.awb":
+    {
+        "priors":
+        [
+            {
+                "lux": 0, "prior":
+                [
+                    2000, 1.0, 3000, 0.0, 13000, 0.0
+                ]
+            },
+            {
+                "lux": 800, "prior":
+                [
+                    2000, 0.0, 6000, 2.0, 13000, 2.0
+                ]
+            },
+            {
+                "lux": 1500, "prior":
+                [
+                    2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0
+                ]
+            }
+        ],
+        "modes":
+        {
+            "auto":
+            {
+                "lo": 2500,
+                "hi": 7900
+            },
+            "incandescent":
+            {
+                "lo": 2500,
+                "hi": 3000
+            },
+            "tungsten":
+            {
+                "lo": 3000,
+                "hi": 3500
+            },
+            "fluorescent":
+            {
+                "lo": 4000,
+                "hi": 4700
+            },
+            "indoor":
+            {
+                "lo": 3000,
+                "hi": 5000
+            },
+            "daylight":
+            {
+                "lo": 5500,
+                "hi": 6500
+            },
+            "cloudy":
+            {
+                "lo": 7000,
+                "hi": 8000
+            }
+        },
+        "bayes": 1,
+        "ct_curve":
+        [
+            2890.0, 0.7328, 0.3734, 3550.0, 0.6228, 0.4763, 4500.0, 0.5208, 0.5825, 5700.0, 0.4467, 0.6671, 7900.0, 0.3858, 0.7411
+        ],
+        "sensitivity_r": 1.0,
+        "sensitivity_b": 1.0,
+        "transverse_pos": 0.02027,
+        "transverse_neg": 0.01935
+    },
+    "rpi.agc":
+    {
+        "metering_modes":
+        {
+            "centre-weighted":
+            {
+                "weights":
+                [
+                    3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+                ]
+            },
+            "spot":
+            {
+                "weights":
+                [
+                    2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                ]
+            },
+            "matrix":
+            {
+                "weights":
+                [
+                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                ]
+            }
+        },
+        "exposure_modes":
+        {
+            "normal":
+            {
+                "shutter":
+                [
+                    100, 10000, 30000, 60000, 120000
+                ],
+                "gain":
+                [
+                    1.0, 2.0, 4.0, 6.0, 6.0
+                ]
+            },
+            "short":
+            {
+                "shutter":
+                [
+                    100, 5000, 10000, 20000, 120000
+                ],
+                "gain":
+                [
+                    1.0, 2.0, 4.0, 6.0, 6.0
+                ]
+            }
+        },
+        "constraint_modes":
+        {
+            "normal":
+            [
+                {
+                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
+                    [
+                        0, 0.5, 1000, 0.5
+                    ]
+                }
+            ],
+            "highlight":
+            [
+                {
+                    "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
+                    [
+                        0, 0.5, 1000, 0.5
+                    ]
+                },
+                {
+                    "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target":
+                    [
+                        0, 0.8, 1000, 0.8
+                    ]
+                }
+            ]
+        },
+        "y_target":
+        [
+            0, 0.16, 1000, 0.165, 10000, 0.17
+        ]
+    },
+    "rpi.alsc":
+    {
+        "omega": 1.3,
+        "n_iter": 100,
+        "luminance_strength": 0.5,
+        "calibrations_Cr":
+        [
+            {
+                "ct": 3000, "table":
+                [
+                    1.527, 1.521, 1.508, 1.493, 1.476, 1.455, 1.442, 1.441, 1.441, 1.441, 1.448, 1.467, 1.483, 1.494, 1.503, 1.504,
+                    1.525, 1.513, 1.496, 1.477, 1.461, 1.434, 1.418, 1.409, 1.409, 1.416, 1.429, 1.449, 1.469, 1.485, 1.495, 1.503,
+                    1.517, 1.506, 1.485, 1.461, 1.434, 1.412, 1.388, 1.376, 1.376, 1.386, 1.405, 1.429, 1.449, 1.471, 1.488, 1.495,
+                    1.512, 1.496, 1.471, 1.442, 1.412, 1.388, 1.361, 1.344, 1.344, 1.358, 1.384, 1.405, 1.431, 1.456, 1.479, 1.489,
+                    1.508, 1.488, 1.458, 1.425, 1.393, 1.361, 1.343, 1.322, 1.321, 1.342, 1.358, 1.385, 1.416, 1.445, 1.471, 1.484,
+                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.318, 1.318, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
+                    1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.313, 1.313, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483,
+                    1.507, 1.485, 1.455, 1.422, 1.387, 1.355, 1.333, 1.319, 1.321, 1.333, 1.351, 1.381, 1.411, 1.441, 1.467, 1.483,
+                    1.508, 1.489, 1.463, 1.432, 1.401, 1.372, 1.355, 1.333, 1.333, 1.351, 1.369, 1.393, 1.422, 1.448, 1.471, 1.484,
+                    1.511, 1.494, 1.472, 1.444, 1.416, 1.398, 1.372, 1.361, 1.361, 1.369, 1.393, 1.411, 1.436, 1.458, 1.477, 1.487,
+                    1.511, 1.496, 1.478, 1.455, 1.436, 1.416, 1.399, 1.391, 1.391, 1.397, 1.411, 1.429, 1.451, 1.466, 1.479, 1.487,
+                    1.511, 1.495, 1.478, 1.462, 1.448, 1.432, 1.419, 1.419, 1.419, 1.419, 1.429, 1.445, 1.459, 1.471, 1.482, 1.487
+                ]
+            },
+            {
+                "ct": 6000, "table":
+                [
+                    2.581, 2.573, 2.558, 2.539, 2.514, 2.487, 2.473, 2.471, 2.471, 2.471, 2.479, 2.499, 2.517, 2.532, 2.543, 2.544,
+                    2.575, 2.559, 2.539, 2.521, 2.491, 2.458, 2.435, 2.421, 2.421, 2.429, 2.449, 2.477, 2.499, 2.519, 2.534, 2.543,
+                    2.561, 2.549, 2.521, 2.491, 2.457, 2.423, 2.393, 2.375, 2.375, 2.387, 2.412, 2.444, 2.475, 2.499, 2.519, 2.532,
+                    2.552, 2.531, 2.498, 2.459, 2.423, 2.391, 2.349, 2.325, 2.325, 2.344, 2.374, 2.412, 2.444, 2.476, 2.505, 2.519,
+                    2.543, 2.518, 2.479, 2.435, 2.392, 2.349, 2.324, 2.285, 2.283, 2.313, 2.344, 2.374, 2.417, 2.457, 2.489, 2.506,
+                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.277, 2.279, 2.283, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
+                    2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.267, 2.267, 2.281, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504,
+                    2.541, 2.512, 2.472, 2.425, 2.381, 2.338, 2.302, 2.278, 2.279, 2.301, 2.324, 2.364, 2.407, 2.447, 2.481, 2.504,
+                    2.544, 2.519, 2.483, 2.441, 2.401, 2.363, 2.338, 2.302, 2.302, 2.324, 2.355, 2.385, 2.423, 2.459, 2.488, 2.506,
+                    2.549, 2.527, 2.497, 2.463, 2.427, 2.401, 2.363, 2.345, 2.345, 2.355, 2.385, 2.412, 2.444, 2.473, 2.497, 2.509,
+                    2.552, 2.532, 2.507, 2.481, 2.459, 2.427, 2.402, 2.389, 2.389, 2.394, 2.412, 2.444, 2.465, 2.481, 2.499, 2.511,
+                    2.553, 2.533, 2.508, 2.489, 2.475, 2.454, 2.429, 2.429, 2.429, 2.429, 2.439, 2.463, 2.481, 2.492, 2.504, 2.511
+                ]
+            }
+        ],
+        "calibrations_Cb":
+        [
+            {
+                "ct": 3000, "table":
+                [
+                    3.132, 3.126, 3.116, 3.103, 3.097, 3.091, 3.087, 3.086, 3.088, 3.091, 3.092, 3.102, 3.113, 3.121, 3.141, 3.144,
+                    3.149, 3.132, 3.123, 3.108, 3.101, 3.096, 3.091, 3.089, 3.091, 3.092, 3.101, 3.107, 3.116, 3.129, 3.144, 3.153,
+                    3.161, 3.149, 3.129, 3.121, 3.108, 3.103, 3.101, 3.101, 3.101, 3.103, 3.107, 3.116, 3.125, 3.134, 3.153, 3.159,
+                    3.176, 3.161, 3.144, 3.129, 3.124, 3.121, 3.117, 3.118, 3.118, 3.119, 3.122, 3.125, 3.134, 3.146, 3.159, 3.171,
+                    3.183, 3.176, 3.157, 3.144, 3.143, 3.143, 3.139, 3.141, 3.141, 3.141, 3.141, 3.141, 3.146, 3.161, 3.171, 3.179,
+                    3.189, 3.183, 3.165, 3.157, 3.156, 3.157, 3.159, 3.163, 3.163, 3.163, 3.163, 3.161, 3.163, 3.169, 3.179, 3.187,
+                    3.199, 3.189, 3.171, 3.165, 3.164, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.169, 3.169, 3.175, 3.187, 3.189,
+                    3.206, 3.196, 3.177, 3.171, 3.165, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.171, 3.173, 3.177, 3.192, 3.194,
+                    3.209, 3.197, 3.178, 3.171, 3.164, 3.161, 3.159, 3.161, 3.162, 3.164, 3.167, 3.171, 3.173, 3.181, 3.193, 3.198,
+                    3.204, 3.194, 3.176, 3.165, 3.161, 3.156, 3.154, 3.154, 3.159, 3.161, 3.164, 3.168, 3.173, 3.182, 3.198, 3.199,
+                    3.199, 3.191, 3.176, 3.169, 3.161, 3.157, 3.153, 3.153, 3.156, 3.161, 3.164, 3.168, 3.173, 3.186, 3.196, 3.199,
+                    3.199, 3.188, 3.179, 3.173, 3.165, 3.157, 3.153, 3.154, 3.156, 3.159, 3.167, 3.171, 3.176, 3.185, 3.193, 3.198
+                ]
+            },
+            {
+                "ct": 6000, "table":
+                [
+                    1.579, 1.579, 1.577, 1.574, 1.573, 1.571, 1.571, 1.571, 1.571, 1.569, 1.569, 1.571, 1.572, 1.574, 1.577, 1.578,
+                    1.584, 1.579, 1.578, 1.575, 1.573, 1.572, 1.571, 1.572, 1.572, 1.571, 1.571, 1.572, 1.573, 1.576, 1.578, 1.579,
+                    1.587, 1.584, 1.579, 1.578, 1.575, 1.573, 1.573, 1.575, 1.575, 1.574, 1.573, 1.574, 1.576, 1.578, 1.581, 1.581,
+                    1.591, 1.587, 1.584, 1.579, 1.578, 1.579, 1.579, 1.581, 1.581, 1.581, 1.578, 1.577, 1.578, 1.581, 1.585, 1.586,
+                    1.595, 1.591, 1.587, 1.585, 1.585, 1.586, 1.587, 1.587, 1.588, 1.588, 1.585, 1.584, 1.584, 1.586, 1.589, 1.589,
+                    1.597, 1.595, 1.591, 1.589, 1.591, 1.593, 1.595, 1.596, 1.597, 1.597, 1.595, 1.594, 1.592, 1.592, 1.593, 1.593,
+                    1.601, 1.597, 1.593, 1.592, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.596, 1.595, 1.596, 1.595, 1.595,
+                    1.601, 1.599, 1.594, 1.593, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.597, 1.597, 1.597, 1.597, 1.597,
+                    1.602, 1.599, 1.594, 1.593, 1.592, 1.593, 1.595, 1.597, 1.597, 1.598, 1.598, 1.597, 1.597, 1.597, 1.598, 1.598,
+                    1.599, 1.598, 1.594, 1.592, 1.591, 1.591, 1.592, 1.595, 1.596, 1.597, 1.597, 1.597, 1.597, 1.599, 1.599, 1.599,
+                    1.598, 1.596, 1.594, 1.593, 1.592, 1.592, 1.592, 1.594, 1.595, 1.597, 1.597, 1.597, 1.598, 1.599, 1.599, 1.599,
+                    1.597, 1.595, 1.594, 1.594, 1.593, 1.592, 1.593, 1.595, 1.595, 1.597, 1.598, 1.598, 1.598, 1.599, 1.599, 1.599
+                ]
+            }
+        ],
+        "luminance_lut":
+        [
+            2.887, 2.754, 2.381, 2.105, 1.859, 1.678, 1.625, 1.623, 1.623, 1.624, 1.669, 1.849, 2.092, 2.362, 2.723, 2.838,
+            2.754, 2.443, 2.111, 1.905, 1.678, 1.542, 1.455, 1.412, 1.412, 1.452, 1.535, 1.665, 1.893, 2.096, 2.413, 2.723,
+            2.443, 2.216, 1.911, 1.678, 1.537, 1.372, 1.288, 1.245, 1.245, 1.283, 1.363, 1.527, 1.665, 1.895, 2.193, 2.413,
+            2.318, 2.057, 1.764, 1.541, 1.372, 1.282, 1.159, 1.113, 1.113, 1.151, 1.269, 1.363, 1.527, 1.749, 2.034, 2.278,
+            2.259, 1.953, 1.671, 1.452, 1.283, 1.159, 1.107, 1.018, 1.017, 1.097, 1.151, 1.269, 1.437, 1.655, 1.931, 2.222,
+            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.019, 1.011, 1.005, 1.014, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
+            2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.016, 1.001, 1.001, 1.007, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222,
+            2.257, 1.946, 1.666, 1.448, 1.281, 1.153, 1.093, 1.013, 1.008, 1.089, 1.143, 1.269, 1.437, 1.654, 1.934, 2.226,
+            2.309, 2.044, 1.756, 1.532, 1.363, 1.259, 1.153, 1.093, 1.093, 1.143, 1.264, 1.354, 1.524, 1.746, 2.035, 2.284,
+            2.425, 2.201, 1.896, 1.662, 1.519, 1.363, 1.259, 1.214, 1.214, 1.264, 1.354, 1.519, 1.655, 1.888, 2.191, 2.413,
+            2.724, 2.417, 2.091, 1.888, 1.662, 1.519, 1.419, 1.373, 1.373, 1.425, 1.521, 1.655, 1.885, 2.089, 2.409, 2.722,
+            2.858, 2.724, 2.356, 2.085, 1.842, 1.658, 1.581, 1.577, 1.577, 1.579, 1.653, 1.838, 2.084, 2.359, 2.722, 2.842
+        ],
+        "sigma": 0.00372,
+        "sigma_Cb": 0.00244
+    },
+    "rpi.contrast":
+    {
+        "ce_enable": 1,
+        "gamma_curve":
+        [
+            0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193,
+            8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168,
+            16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796,
+            32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476,
+            65535, 65535
+        ]
+    },
+    "rpi.ccm":
+    {
+        "ccms":
+        [
+            {
+                "ct": 2890, "ccm":
+                [
+                    1.36754, -0.18448, -0.18306, -0.32356, 1.44826, -0.12471, -0.00412, -0.69936, 1.70348
+                ]
+            },
+            {
+                "ct": 2920, "ccm":
+                [
+                    1.26704, 0.01624, -0.28328, -0.28516, 1.38934, -0.10419, -0.04854, -0.82211, 1.87066
+                ]
+            },
+            {
+                "ct": 3550, "ccm":
+                [
+                    1.42836, -0.27235, -0.15601, -0.28751, 1.41075, -0.12325, -0.01812, -0.54849, 1.56661
+                ]
+            },
+            {
+                "ct": 4500, "ccm":
+                [
+                    1.36328, -0.19569, -0.16759, -0.25254, 1.52248, -0.26994, -0.01575, -0.53155, 1.54729
+                ]
+            },
+            {
+                "ct": 5700, "ccm":
+                [
+                    1.49207, -0.37245, -0.11963, -0.21493, 1.40005, -0.18512, -0.03781, -0.38779, 1.42561
+                ]
+            },
+            {
+                "ct": 7900, "ccm":
+                [
+                    1.34849, -0.05425, -0.29424, -0.22182, 1.77684, -0.55502, -0.07403, -0.55336, 1.62739
+                ]
+            }
+        ]
+    },
+    "rpi.sharpen":
+    {
+    }
+}
diff --git a/src/ipa/raspberrypi/data/meson.build b/src/ipa/raspberrypi/data/meson.build
index 2def75cb..e84cd099 100644
--- a/src/ipa/raspberrypi/data/meson.build
+++ b/src/ipa/raspberrypi/data/meson.build
@@ -7,6 +7,7 @@  conf_files = files([
     'imx378.json',
     'imx477.json',
     'imx477_noir.json',
+    'imx519.json',
     'ov5647.json',
     'ov5647_noir.json',
     'ov9281.json',
diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build
index 1af31e4a..176055f4 100644
--- a/src/ipa/raspberrypi/meson.build
+++ b/src/ipa/raspberrypi/meson.build
@@ -22,6 +22,7 @@  rpi_ipa_sources = files([
     'cam_helper_imx219.cpp',
     'cam_helper_imx290.cpp',
     'cam_helper_imx477.cpp',
+    'cam_helper_imx519.cpp',
     'cam_helper_ov9281.cpp',
     'controller/controller.cpp',
     'controller/histogram.cpp',