camera_sensor: Add minimum and maximum line length to IPACameraSensorInfo

Add fields for minimum and maximum line length (in units of pixels) to
the IPACameraSensorInfo structure. This replaces the existing lineLength
field.

Update the ipu3, raspberrypi and rkisp1 IPAs to use
IPACameraSensorInfo::minLineLength instead of
IPACameraSensorInfo::lineLength, as logically we will always want to use
the fastest sensor readout by default.

Since the IPAs now use minLineLength for their calculations, set the
starting value of the V4L2_CID_HBLANK control to its minimum in
CameraSensor::init().

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Tested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Naushir Patuck 2022-10-10 08:42:32 +01:00 committed by Laurent Pinchart
parent ae7809307e
commit e5fc0132f8
5 changed files with 51 additions and 12 deletions

View file

@ -172,10 +172,17 @@ module libcamera;
*/ */
/** /**
* \var IPACameraSensorInfo::lineLength * \var IPACameraSensorInfo::minLineLength
* \brief Total line length in pixels * \brief The minimum line length in pixels
* *
* The total line length in pixel clock periods, including blanking. * The minimum allowable line length in pixel clock periods, including blanking.
*/
/**
* \var IPACameraSensorInfo::maxLineLength
* \brief The maximum line length in pixels
*
* The maximum allowable line length in pixel clock periods, including blanking.
*/ */
/** /**
@ -189,7 +196,7 @@ module libcamera;
* To obtain the minimum frame duration: * To obtain the minimum frame duration:
* *
* \verbatim * \verbatim
frameDuration(s) = minFrameLength(lines) * lineLength(pixels) / pixelRate(pixels per second) frameDuration(s) = minFrameLength(lines) * minLineLength(pixels) / pixelRate(pixels per second)
\endverbatim \endverbatim
*/ */
@ -204,7 +211,7 @@ module libcamera;
* To obtain the maximum frame duration: * To obtain the maximum frame duration:
* *
* \verbatim * \verbatim
frameDuration(s) = maxFrameLength(lines) * lineLength(pixels) / pixelRate(pixels per second) frameDuration(s) = maxFrameLength(lines) * maxLineLength(pixels) / pixelRate(pixels per second)
\endverbatim \endverbatim
*/ */
struct IPACameraSensorInfo { struct IPACameraSensorInfo {
@ -217,7 +224,9 @@ struct IPACameraSensorInfo {
Size outputSize; Size outputSize;
uint64 pixelRate; uint64 pixelRate;
uint32 lineLength;
uint32 minLineLength;
uint32 maxLineLength;
uint32 minFrameLength; uint32 minFrameLength;
uint32 maxFrameLength; uint32 maxFrameLength;

View file

@ -336,7 +336,8 @@ int IPAIPU3::init(const IPASettings &settings,
/* Clean context */ /* Clean context */
context_.configuration = {}; context_.configuration = {};
context_.configuration.sensor.lineDuration = sensorInfo.lineLength * 1.0s / sensorInfo.pixelRate; context_.configuration.sensor.lineDuration = sensorInfo.minLineLength
* 1.0s / sensorInfo.pixelRate;
/* Load the tuning data file. */ /* Load the tuning data file. */
File file(settings.configurationFile); File file(settings.configurationFile);
@ -499,7 +500,8 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo,
context_.frameContexts.clear(); context_.frameContexts.clear();
/* Initialise the sensor configuration. */ /* Initialise the sensor configuration. */
context_.configuration.sensor.lineDuration = sensorInfo_.lineLength * 1.0s / sensorInfo_.pixelRate; context_.configuration.sensor.lineDuration = sensorInfo_.minLineLength
* 1.0s / sensorInfo_.pixelRate;
/* /*
* Compute the sensor V4L2 controls to be used by the algorithms and * Compute the sensor V4L2 controls to be used by the algorithms and

View file

@ -356,7 +356,7 @@ void IPARPi::setMode(const IPACameraSensorInfo &sensorInfo)
* Calculate the line length as the ratio between the line length in * Calculate the line length as the ratio between the line length in
* pixels and the pixel rate. * pixels and the pixel rate.
*/ */
mode_.lineLength = sensorInfo.lineLength * (1.0s / sensorInfo.pixelRate); mode_.lineLength = sensorInfo.minLineLength * (1.0s / sensorInfo.pixelRate);
/* /*
* Set the frame length limits for the mode to ensure exposure and * Set the frame length limits for the mode to ensure exposure and

View file

@ -246,7 +246,7 @@ int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info,
context_.configuration.hw.revision = hwRevision_; context_.configuration.hw.revision = hwRevision_;
context_.configuration.sensor.size = info.outputSize; context_.configuration.sensor.size = info.outputSize;
context_.configuration.sensor.lineDuration = info.lineLength * 1.0s / info.pixelRate; context_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate;
/* /*
* When the AGC computes the new exposure values for a frame, it needs * When the AGC computes the new exposure values for a frame, it needs

View file

@ -176,6 +176,32 @@ int CameraSensor::init()
if (ret) if (ret)
return ret; return ret;
/*
* Set HBLANK to the minimum to start with a well-defined line length,
* allowing IPA modules that do not modify HBLANK to use the sensor
* minimum line length in their calculations.
*
* At present, there is no way of knowing if a control is read-only.
* As a workaround, assume that if the minimum and maximum values of
* the V4L2_CID_HBLANK control are the same, it implies the control
* is read-only.
*
* \todo The control API ought to have a flag to specify if a control
* is read-only which could be used below.
*/
const ControlInfo hblank = ctrls.infoMap()->at(V4L2_CID_HBLANK);
const int32_t hblankMin = hblank.min().get<int32_t>();
const int32_t hblankMax = hblank.max().get<int32_t>();
if (hblankMin != hblankMax) {
ControlList ctrl(subdev_->controls());
ctrl.set(V4L2_CID_HBLANK, hblankMin);
ret = subdev_->setControls(&ctrl);
if (ret)
return ret;
}
return applyTestPatternMode(controls::draft::TestPatternModeEnum::TestPatternModeOff); return applyTestPatternMode(controls::draft::TestPatternModeEnum::TestPatternModeOff);
} }
@ -883,10 +909,12 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const
return -EINVAL; return -EINVAL;
} }
int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();
info->lineLength = info->outputSize.width + hblank;
info->pixelRate = ctrls.get(V4L2_CID_PIXEL_RATE).get<int64_t>(); info->pixelRate = ctrls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();
const ControlInfo hblank = ctrls.infoMap()->at(V4L2_CID_HBLANK);
info->minLineLength = info->outputSize.width + hblank.min().get<int32_t>();
info->maxLineLength = info->outputSize.width + hblank.max().get<int32_t>();
const ControlInfo vblank = ctrls.infoMap()->at(V4L2_CID_VBLANK); const ControlInfo vblank = ctrls.infoMap()->at(V4L2_CID_VBLANK);
info->minFrameLength = info->outputSize.height + vblank.min().get<int32_t>(); info->minFrameLength = info->outputSize.height + vblank.min().get<int32_t>();
info->maxFrameLength = info->outputSize.height + vblank.max().get<int32_t>(); info->maxFrameLength = info->outputSize.height + vblank.max().get<int32_t>();