blob: c953def04fd7f57d52e3156d2d3e9a7c434d5e8f [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2021, Google Inc.
*
* camera_sensor_helper.cpp - Helper class that performs sensor-specific
* parameter computations
*/
#include "camera_sensor_helper.h"
#include <libcamera/base/log.h>
/**
* \file camera_sensor_helper.h
* \brief Helper class that performs sensor-specific parameter computations
*
* Computation of sensor configuration parameters is a sensor specific
* operation. Each CameraHelper derived class computes the value of
* configuration parameters, for example the analogue gain value, using
* sensor-specific functions and constants.
*
* Every subclass of CameraSensorHelper shall be registered with libipa using
* the REGISTER_CAMERA_SENSOR_HELPER() macro.
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(CameraSensorHelper)
namespace ipa {
/**
* \class CameraSensorHelper
* \brief Base class for computing sensor tuning parameters using
* sensor-specific constants
*
* Instances derived from CameraSensorHelper class are sensor-specific.
* Each supported sensor will have an associated base class defined.
*/
/**
* \brief Construct a CameraSensorHelper instance
*
* CameraSensorHelper derived class instances shall never be constructed
* manually but always through the CameraSensorHelperFactory::create() function.
*/
/**
* \brief Compute gain code from the analogue gain absolute value
* \param[in] gain The real gain to pass
*
* This function aims to abstract the calculation of the gain letting the IPA
* use the real gain for its estimations.
*
* The parameters come from the MIPI Alliance Camera Specification for
* Camera Command Set (CCS).
*
* \return The gain code to pass to V4L2
*/
uint32_t CameraSensorHelper::gainCode(double gain) const
{
ASSERT(analogueGainConstants_.m0 == 0 || analogueGainConstants_.m1 == 0);
ASSERT(analogueGainConstants_.type == AnalogueGainLinear);
return (analogueGainConstants_.c0 - analogueGainConstants_.c1 * gain) /
(analogueGainConstants_.m1 * gain - analogueGainConstants_.m0);
}
/**
* \brief Compute the real gain from the V4L2 subdev control gain code
* \param[in] gainCode The V4L2 subdev control gain
*
* This function aims to abstract the calculation of the gain letting the IPA
* use the real gain for its estimations. It is the counterpart of the function
* CameraSensorHelper::gainCode.
*
* The parameters come from the MIPI Alliance Camera Specification for
* Camera Command Set (CCS).
*
* \return The real gain
*/
double CameraSensorHelper::gain(uint32_t gainCode) const
{
ASSERT(analogueGainConstants_.m0 == 0 || analogueGainConstants_.m1 == 0);
ASSERT(analogueGainConstants_.type == AnalogueGainLinear);
return (analogueGainConstants_.m0 * static_cast<double>(gainCode) + analogueGainConstants_.c0) /
(analogueGainConstants_.m1 * static_cast<double>(gainCode) + analogueGainConstants_.c1);
}
/**
* \enum CameraSensorHelper::AnalogueGainType
* \brief The gain calculation modes as defined by the MIPI CCS
*
* Describes the image sensor analogue gain capabilities.
* Two modes are possible, depending on the sensor: Linear and Exponential.
*/
/**
* \var CameraSensorHelper::AnalogueGainLinear
* \brief Gain is computed using linear gain estimation
*
* The relationship between the integer gain parameter and the resulting gain
* multiplier is given by the following equation:
*
* \f$gain=\frac{m0x+c0}{m1x+c1}\f$
*
* Where 'x' is the gain control parameter, and m0, m1, c0 and c1 are
* image-sensor-specific constants of the sensor.
* These constants are static parameters, and for any given image sensor either
* m0 or m1 shall be zero.
*
* The full Gain equation therefore reduces to either:
*
* \f$gain=\frac{c0}{m1x+c1}\f$ or \f$\frac{m0x+c0}{c1}\f$
*/
/**
* \var CameraSensorHelper::AnalogueGainExponential
* \brief Gain is computed using exponential gain estimation
* (introduced in CCS v1.1)
*
* Starting with CCS v1.1, Alternate Global Analogue Gain is also available.
* If the image sensor supports it, then the global analogue gain can be
* controlled by linear and exponential gain formula:
*
* \f$gain = analogLinearGainGlobal * 2^{analogExponentialGainGlobal}\f$
* \todo not implemented in libipa
*/
/**
* \struct CameraSensorHelper::AnalogueGainConstants
* \brief Analogue gain constants used for gain calculation
*/
/**
* \var CameraSensorHelper::AnalogueGainConstants::type
* \brief Analogue gain calculation mode
*/
/**
* \var CameraSensorHelper::AnalogueGainConstants::m0
* \brief Constant used in the analogue Gain coding/decoding
*
* \note Either m0 or m1 shall be zero.
*/
/**
* \var CameraSensorHelper::AnalogueGainConstants::c0
* \brief Constant used in the analogue gain coding/decoding
*/
/**
* \var CameraSensorHelper::AnalogueGainConstants::m1
* \brief Constant used in the analogue gain coding/decoding
*
* \note Either m0 or m1 shall be zero.
*/
/**
* \var CameraSensorHelper::AnalogueGainConstants::c1
* \brief Constant used in the analogue gain coding/decoding
*/
/**
* \var CameraSensorHelper::analogueGainConstants_
* \brief The analogue gain parameters used for calculation
*
* The analogue gain is calculated through a formula, and its parameters are
* sensor specific. Use this variable to store the values at init time.
*/
/**
* \class CameraSensorHelperFactory
* \brief Registration of CameraSensorHelperFactory classes and creation of instances
*
* To facilitate discovery and instantiation of CameraSensorHelper classes, the
* CameraSensorHelperFactory class maintains a registry of camera sensor helper
* sub-classes. Each CameraSensorHelper subclass shall register itself using the
* REGISTER_CAMERA_SENSOR_HELPER() macro, which will create a corresponding
* instance of a CameraSensorHelperFactory subclass and register it with the
* static list of factories.
*/
/**
* \brief Construct a camera sensor helper factory
* \param[in] name Name of the camera sensor helper class
*
* Creating an instance of the factory registers it with the global list of
* factories, accessible through the factories() function.
*
* The factory \a name is used for debug purpose and shall be unique.
*/
CameraSensorHelperFactory::CameraSensorHelperFactory(const std::string name)
: name_(name)
{
registerType(this);
}
/**
* \brief Create an instance of the CameraSensorHelper corresponding to
* a named factory
* \param[in] name Name of the factory
*
* \return A unique pointer to a new instance of the CameraSensorHelper subclass
* corresponding to the named factory or a null pointer if no such factory
* exists
*/
std::unique_ptr<CameraSensorHelper> CameraSensorHelperFactory::create(const std::string &name)
{
std::vector<CameraSensorHelperFactory *> &factories =
CameraSensorHelperFactory::factories();
for (CameraSensorHelperFactory *factory : factories) {
if (name != factory->name_)
continue;
CameraSensorHelper *helper = factory->createInstance();
return std::unique_ptr<CameraSensorHelper>(helper);
}
return nullptr;
}
/**
* \brief Add a camera sensor helper class to the registry
* \param[in] factory Factory to use to construct the camera sensor helper
*
* The caller is responsible to guarantee the uniqueness of the camera sensor
* helper name.
*/
void CameraSensorHelperFactory::registerType(CameraSensorHelperFactory *factory)
{
std::vector<CameraSensorHelperFactory *> &factories =
CameraSensorHelperFactory::factories();
factories.push_back(factory);
}
/**
* \brief Retrieve the list of all camera sensor helper factories
* \return The list of camera sensor helper factories
*/
std::vector<CameraSensorHelperFactory *> &CameraSensorHelperFactory::factories()
{
/*
* The static factories map is defined inside the function to ensure
* it gets initialized on first use, without any dependency on link
* order.
*/
static std::vector<CameraSensorHelperFactory *> factories;
return factories;
}
/**
* \fn CameraSensorHelperFactory::createInstance()
* \brief Create an instance of the CameraSensorHelper corresponding to the
* factory
*
* This virtual function is implemented by the REGISTER_CAMERA_SENSOR_HELPER()
* macro. It creates a camera sensor helper instance associated with the camera
* sensor model.
*
* \return A pointer to a newly constructed instance of the CameraSensorHelper
* subclass corresponding to the factory
*/
/**
* \var CameraSensorHelperFactory::name_
* \brief The name of the factory
*/
/**
* \def REGISTER_CAMERA_SENSOR_HELPER
* \brief Register a camera sensor helper with the camera sensor helper factory
* \param[in] name Sensor model name used to register the class
* \param[in] helper Class name of CameraSensorHelper derived class to register
*
* Register a CameraSensorHelper subclass with the factory and make it available
* to try and match sensors.
*/
/* -----------------------------------------------------------------------------
* Sensor-specific subclasses
*/
#ifndef __DOXYGEN__
class CameraSensorHelperImx219 : public CameraSensorHelper
{
public:
CameraSensorHelperImx219()
{
analogueGainConstants_ = { AnalogueGainLinear, 0, 256, -1, 256 };
}
};
REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219)
class CameraSensorHelperImx258 : public CameraSensorHelper
{
public:
CameraSensorHelperImx258()
{
analogueGainConstants_ = { AnalogueGainLinear, 0, 512, -1, 512 };
}
};
REGISTER_CAMERA_SENSOR_HELPER("imx258", CameraSensorHelperImx258)
class CameraSensorHelperOv2740 : public CameraSensorHelper
{
public:
CameraSensorHelperOv2740()
{
analogueGainConstants_ = { AnalogueGainLinear, 1, 0, 0, 128 };
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov2740", CameraSensorHelperOv2740)
class CameraSensorHelperOv5670 : public CameraSensorHelper
{
public:
CameraSensorHelperOv5670()
{
analogueGainConstants_ = { AnalogueGainLinear, 1, 0, 0, 128 };
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670)
class CameraSensorHelperOv5693 : public CameraSensorHelper
{
public:
CameraSensorHelperOv5693()
{
analogueGainConstants_ = { AnalogueGainLinear, 1, 0, 0, 16 };
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693)
class CameraSensorHelperOv8865 : public CameraSensorHelper
{
public:
CameraSensorHelperOv8865()
{
analogueGainConstants_ = { AnalogueGainLinear, 1, 0, 0, 128 };
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov8865", CameraSensorHelperOv8865)
class CameraSensorHelperOv13858 : public CameraSensorHelper
{
public:
CameraSensorHelperOv13858()
{
analogueGainConstants_ = { AnalogueGainLinear, 1, 0, 0, 128 };
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858)
#endif /* __DOXYGEN__ */
} /* namespace ipa */
} /* namespace libcamera */