@@ -76,10 +76,7 @@ const std::map<libcamera::PixelFormat, unsigned int> maliC55FmtToCode = {
{ formats::NV21, MEDIA_BUS_FMT_YUV10_1X30 },
/* RAW formats, FR pipe only. */
- { formats::SGBRG16, MEDIA_BUS_FMT_SGBRG16_1X16 },
- { formats::SRGGB16, MEDIA_BUS_FMT_SRGGB16_1X16 },
- { formats::SBGGR16, MEDIA_BUS_FMT_SBGGR16_1X16 },
- { formats::SGRBG16, MEDIA_BUS_FMT_SGRBG16_1X16 },
+ { formats::RAW16, MEDIA_BUS_FMT_RAW_16 },
};
constexpr Size kMaliC55MinInputSize = { 640, 480 };
@@ -191,13 +188,33 @@ public:
}, input_);
}
- int pixfmtToMbusCode(const PixelFormat &pixFmt) const;
- const PixelFormat &bestRawFormat() const;
+ ColorFilterArray bayerOrder(Transform t) const
+ {
+ return std::visit(utils::overloaded{
+ [&](const Tpg &tpg) -> ColorFilterArray {
+ V4L2Subdevice::Formats formats = tpg.sd_->formats(0);
+ for (const auto &[code, sizes] : formats) {
+ auto cfa = ColorFilterArray::fromMbusCode(code);
+ if (cfa)
+ return cfa.value();
+ }
+ return ColorFilterArray::MONO;
+ },
+ [&](const Inline &in) -> ColorFilterArray {
+ return in.sensor_->bayerOrder(t);
+ },
+ [&](const Memory &mem) -> ColorFilterArray {
+ return mem.cru_->sensor()->bayerOrder(t);
+ },
+ }, input_);
+ }
+
+ int bestMbusCode(ColorFilterArray cfa) const;
+ bool isSensorRaw() const;
void updateControls(const ControlInfoMap &ipaControls);
- PixelFormat adjustRawFormat(const PixelFormat &pixFmt) const;
- Size adjustRawSizes(const PixelFormat &pixFmt, const Size &rawSize) const;
+ Size adjustRawSizes(const Size &rawSize, unsigned int rawCode) const;
Stream frStream_;
Stream dsStream_;
@@ -305,21 +322,13 @@ void MaliC55CameraData::setSensorControls(const ControlList &sensorControls)
}
/*
- * The Mali C55 ISP can only produce 16-bit RAW output in bypass modes, but the
- * sensors connected to it might produce 8/10/12/16 bits. We simply search the
- * sensor's supported formats for the one with a matching bayer order and the
- * greatest bitdepth.
+ * The Mali C55 ISP can only accept as input RAW20 and can only produce as
+ * output RAW16. The sensors connected to it might produce 8/10/12/16 bits.
+ * We simply search the sensor's supported formats for the one with greatest
+ * bitdepth and matches the bayer color filter array order.
*/
-int MaliC55CameraData::pixfmtToMbusCode(const PixelFormat &pixFmt) const
+int MaliC55CameraData::bestMbusCode(ColorFilterArray cfa) const
{
- auto it = maliC55FmtToCode.find(pixFmt);
- if (it == maliC55FmtToCode.end())
- return -EINVAL;
-
- BayerFormat bayerFormat = BayerFormat::fromMbusCode(it->second);
- if (!bayerFormat.isValid())
- return -EINVAL;
-
V4L2Subdevice::Formats formats = subdev()->formats(0);
unsigned int sensorMbusCode = 0;
unsigned int bitDepth = 0;
@@ -329,7 +338,12 @@ int MaliC55CameraData::pixfmtToMbusCode(const PixelFormat &pixFmt) const
if (!sdBayerFormat.isValid())
continue;
- if (sdBayerFormat.cfa.order != bayerFormat.cfa.order)
+ /* The pipeline currently does not support generic codes */
+ if (MediaBusFormatInfo::info(code).genericRaw)
+ continue;
+
+ auto c = ColorFilterArray::fromMbusCode(code);
+ if (!c || c != cfa)
continue;
if (sdBayerFormat.bitDepth > bitDepth) {
@@ -344,38 +358,20 @@ int MaliC55CameraData::pixfmtToMbusCode(const PixelFormat &pixFmt) const
return sensorMbusCode;
}
-/*
- * Find a RAW PixelFormat supported by both the ISP and the sensor.
- *
- * The situation is mildly complicated by the fact that we expect the sensor to
- * output something like RAW8/10/12/16, but the ISP can only accept as input
- * RAW20 and can only produce as output RAW16. The one constant in that is the
- * bayer order of the data, so we'll simply check that the sensor produces a
- * format with a bayer order that matches that of one of the formats we support,
- * and select that.
- */
-const PixelFormat &MaliC55CameraData::bestRawFormat() const
+bool MaliC55CameraData::isSensorRaw() const
{
- static const PixelFormat invalidPixFmt = {};
+ if (!std::holds_alternative<Tpg>(input_))
+ return this->sensor()->isRaw();
for (const auto &fmt : subdev()->formats(0)) {
BayerFormat sensorBayer = BayerFormat::fromMbusCode(fmt.first);
- if (!sensorBayer.isValid())
- continue;
-
- for (const auto &[pixFmt, rawCode] : maliC55FmtToCode) {
- if (!isFormatRaw(pixFmt))
- continue;
-
- BayerFormat bayer = BayerFormat::fromMbusCode(rawCode);
- if (bayer.cfa.order == sensorBayer.cfa.order)
- return pixFmt;
- }
+ if (sensorBayer.isValid())
+ return true;
}
- LOG(MaliC55, Error) << "Sensor doesn't provide a compatible format";
- return invalidPixFmt;
+ LOG(MaliC55, Error) << "Sensor doesn't provide a raw bayer format";
+ return false;
}
void MaliC55CameraData::updateControls(const ControlInfoMap &ipaControls)
@@ -402,34 +398,13 @@ void MaliC55CameraData::updateControls(const ControlInfoMap &ipaControls)
controlInfo_ = ControlInfoMap(std::move(controls), controls::controls);
}
-/*
- * Make sure the provided raw pixel format is supported and adjust it to
- * one of the supported ones if it's not.
- */
-PixelFormat MaliC55CameraData::adjustRawFormat(const PixelFormat &rawFmt) const
-{
- /* Make sure the RAW mbus code is supported by the image source. */
- int rawCode = pixfmtToMbusCode(rawFmt);
- if (rawCode < 0)
- return bestRawFormat();
-
- const auto rawSizes = sizes(rawCode);
- if (rawSizes.empty())
- return bestRawFormat();
-
- return rawFmt;
-}
-
-Size MaliC55CameraData::adjustRawSizes(const PixelFormat &rawFmt, const Size &size) const
+Size MaliC55CameraData::adjustRawSizes(const Size &size,
+ unsigned int rawCode) const
{
/* Expand the RAW size to the minimum ISP input size. */
Size rawSize = size.expandedTo(kMaliC55MinInputSize);
/* Check if the size is natively supported. */
- int rawCode = pixfmtToMbusCode(rawFmt);
- if (rawCode < 0)
- return {};
-
const auto rawSizes = sizes(rawCode);
auto sizeIt = std::find(rawSizes.begin(), rawSizes.end(), rawSize);
if (sizeIt != rawSizes.end())
@@ -552,21 +527,28 @@ CameraConfiguration::Status MaliC55CameraConfiguration::validate()
rawConfig = &config;
}
+ /* Populate a valid sensor mbus code */
+ ColorFilterArray cfa = data_->bayerOrder(combinedTransform_);
+ int code = data_->bestMbusCode(cfa);
+ if (code < 0)
+ return Invalid;
+
+ sensorFormat_.code = code;
+
/*
* The C55 can not upscale. Limit the configuration to the ISP
* capabilities and the sensor resolution.
*/
Size maxSize = kMaliC55MaxSize.boundedTo(data_->resolution());
if (rawConfig) {
- /*
- * \todo Take into account the Bayer components ordering once
- * we support rotations.
- */
- PixelFormat rawFormat =
- data_->adjustRawFormat(rawConfig->pixelFormat);
+ if (!rawConfig->bayerOrder ||
+ rawConfig->bayerOrder.value() != cfa) {
+ rawConfig->bayerOrder = cfa;
+ status = Adjusted;
+ }
- if (!rawFormat.isValid())
- return Invalid;
+ /* C55 can only produce 16-bit raw output */
+ PixelFormat rawFormat = formats::RAW16;
if (rawFormat != rawConfig->pixelFormat) {
LOG(MaliC55, Debug)
@@ -576,7 +558,7 @@ CameraConfiguration::Status MaliC55CameraConfiguration::validate()
}
Size rawSize =
- data_->adjustRawSizes(rawFormat, rawConfig->size);
+ data_->adjustRawSizes(rawConfig->size, sensorFormat_.code);
if (rawSize != rawConfig->size) {
LOG(MaliC55, Debug)
<< "RAW sizes adjusted to " << rawSize;
@@ -637,19 +619,15 @@ CameraConfiguration::Status MaliC55CameraConfiguration::validate()
/* If there's a RAW config, sensor configuration follows it. */
if (rawConfig) {
- sensorFormat_.code = data_->pixfmtToMbusCode(rawConfig->pixelFormat);
sensorFormat_.size = rawConfig->size.expandedTo(minSensorSize);
return status;
}
/* If there's no RAW config, compute the sensor configuration here. */
- PixelFormat rawFormat = data_->bestRawFormat();
- if (!rawFormat.isValid())
+ if (!data_->isSensorRaw())
return Invalid;
- sensorFormat_.code = data_->pixfmtToMbusCode(rawFormat);
-
uint16_t distance = std::numeric_limits<uint16_t>::max();
const auto sizes = data_->sizes(sensorFormat_.code);
Size bestSize;
@@ -799,6 +777,7 @@ PipelineHandlerMaliC55::generateConfiguration(Camera *camera,
std::unique_ptr<CameraConfiguration> config =
std::make_unique<MaliC55CameraConfiguration>(data);
bool frPipeAvailable = true;
+ ColorFilterArray cameraCfa = data->bayerOrder(Transform::Identity);
if (roles.empty())
return config;
@@ -838,12 +817,8 @@ PipelineHandlerMaliC55::generateConfiguration(Camera *camera,
break;
case StreamRole::Raw:
- pixelFormat = data->bestRawFormat();
- if (!pixelFormat.isValid()) {
- LOG(MaliC55, Error)
- << "Camera does not support RAW formats";
+ if (!data->isSensorRaw())
return nullptr;
- }
size = data->resolution();
break;
@@ -865,7 +840,7 @@ PipelineHandlerMaliC55::generateConfiguration(Camera *camera,
if (isRaw) {
/* Make sure the mbus code is supported. */
- int rawCode = data->pixfmtToMbusCode(pixFmt);
+ int rawCode = data->bestMbusCode(cameraCfa);
if (rawCode < 0)
continue;
@@ -896,6 +871,9 @@ PipelineHandlerMaliC55::generateConfiguration(Camera *camera,
cfg.bufferCount = 4;
cfg.size = size;
+ if (role == StreamRole::Raw)
+ cfg.bayerOrder = cameraCfa;
+
config->addConfiguration(cfg);
}
@@ -1180,10 +1158,10 @@ int PipelineHandlerMaliC55::configure(Camera *camera,
* affected by any flips that we've configured)
*/
const Transform &combinedTransform = maliConfig->combinedTransform();
- ColorFilterArray::Order cfaOrder = data->sensor()->bayerOrder(combinedTransform);
+ ColorFilterArray cfa = data->bayerOrder(combinedTransform);
ControlInfoMap ipaControls;
- ret = data->ipa_->configure(ipaConfig, utils::to_underlying(cfaOrder),
+ ret = data->ipa_->configure(ipaConfig, utils::to_underlying(cfa.order),
&ipaControls);
if (ret) {
LOG(MaliC55, Error) << "Failed to configure IPA";
Split the CFA from the pixel format. Ensure we populate the CFA order for the source (sensor, memory, TPG) in generateConfiguration() and update it during validate() depending upon the transformations. With generic formats the logic for selecting output pixel formats for raw streams is quite simplified, as we only work with 16-bit, which is formats::RAW16. So we no longer need adjustRawFormat() helper, and can replace it with a simple check to ensure the sensor advertises raw formats. We still need to figure out the source mbus code that has the largest possible bit-depth, so we repurpose pixfmtToMbusCode() to look for one, given a CFA order. Note that the Mali-C55 kernel drivers are not yet updated to work with the new generic media bus codes, so we skip those. Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com> --- src/libcamera/pipeline/mali-c55/mali-c55.cpp | 162 ++++++++++++--------------- 1 file changed, 70 insertions(+), 92 deletions(-)