From 726e9274ea95fa46352556d340c5793a8da51fcd Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Wed, 3 May 2023 13:20:27 +0100 Subject: pipeline: ipa: raspberrypi: Refactor and move the Raspberry Pi code Split the Raspberry Pi pipeline handler and IPA source code into common and VC4/BCM2835 specific file structures. For the pipeline handler, the common code files now live in src/libcamera/pipeline/rpi/common/ and the VC4-specific files in src/libcamera/pipeline/rpi/vc4/. For the IPA, the common code files now live in src/ipa/rpi/{cam_helper,controller}/ and the vc4 specific files in src/ipa/rpi/vc4/. With this change, the camera tuning files are now installed under share/libcamera/ipa/rpi/vc4/. To build the pipeline and IPA, the meson configuration options have now changed from "raspberrypi" to "rpi/vc4": meson setup build -Dipas=rpi/vc4 -Dpipelines=rpi/vc4 Signed-off-by: Naushir Patuck Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- src/ipa/rpi/cam_helper/md_parser_smia.cpp | 149 ++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/ipa/rpi/cam_helper/md_parser_smia.cpp (limited to 'src/ipa/rpi/cam_helper/md_parser_smia.cpp') diff --git a/src/ipa/rpi/cam_helper/md_parser_smia.cpp b/src/ipa/rpi/cam_helper/md_parser_smia.cpp new file mode 100644 index 00000000..210787ed --- /dev/null +++ b/src/ipa/rpi/cam_helper/md_parser_smia.cpp @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019-2021, Raspberry Pi Ltd + * + * md_parser_smia.cpp - SMIA specification based embedded data parser + */ + +#include +#include "md_parser.h" + +using namespace RPiController; +using namespace libcamera; + +/* + * This function goes through the embedded data to find the offsets (not + * values!), in the data block, where the values of the given registers can + * subsequently be found. + * + * Embedded data tag bytes, from Sony IMX219 datasheet but general to all SMIA + * sensors, I think. + */ + +constexpr unsigned int LineStart = 0x0a; +constexpr unsigned int LineEndTag = 0x07; +constexpr unsigned int RegHiBits = 0xaa; +constexpr unsigned int RegLowBits = 0xa5; +constexpr unsigned int RegValue = 0x5a; +constexpr unsigned int RegSkip = 0x55; + +MdParserSmia::MdParserSmia(std::initializer_list registerList) +{ + for (auto r : registerList) + offsets_[r] = {}; +} + +MdParser::Status MdParserSmia::parse(libcamera::Span buffer, + RegisterMap ®isters) +{ + if (reset_) { + /* + * Search again through the metadata for all the registers + * requested. + */ + ASSERT(bitsPerPixel_); + + for (const auto &kv : offsets_) + offsets_[kv.first] = {}; + + ParseStatus ret = findRegs(buffer); + /* + * > 0 means "worked partially but parse again next time", + * < 0 means "hard error". + * + * In either case, we retry parsing on the next frame. + */ + if (ret != ParseOk) + return ERROR; + + reset_ = false; + } + + /* Populate the register values requested. */ + registers.clear(); + for (const auto &[reg, offset] : offsets_) { + if (!offset) { + reset_ = true; + return NOTFOUND; + } + registers[reg] = buffer[offset.value()]; + } + + return OK; +} + +MdParserSmia::ParseStatus MdParserSmia::findRegs(libcamera::Span buffer) +{ + ASSERT(offsets_.size()); + + if (buffer[0] != LineStart) + return NoLineStart; + + unsigned int currentOffset = 1; /* after the LineStart */ + unsigned int currentLineStart = 0, currentLine = 0; + unsigned int regNum = 0, regsDone = 0; + + while (1) { + int tag = buffer[currentOffset++]; + + if ((bitsPerPixel_ == 10 && + (currentOffset + 1 - currentLineStart) % 5 == 0) || + (bitsPerPixel_ == 12 && + (currentOffset + 1 - currentLineStart) % 3 == 0)) { + if (buffer[currentOffset++] != RegSkip) + return BadDummy; + } + + int dataByte = buffer[currentOffset++]; + + if (tag == LineEndTag) { + if (dataByte != LineEndTag) + return BadLineEnd; + + if (numLines_ && ++currentLine == numLines_) + return MissingRegs; + + if (lineLengthBytes_) { + currentOffset = currentLineStart + lineLengthBytes_; + + /* Require whole line to be in the buffer (if buffer size set). */ + if (buffer.size() && + currentOffset + lineLengthBytes_ > buffer.size()) + return MissingRegs; + + if (buffer[currentOffset] != LineStart) + return NoLineStart; + } else { + /* allow a zero line length to mean "hunt for the next line" */ + while (currentOffset < buffer.size() && + buffer[currentOffset] != LineStart) + currentOffset++; + + if (currentOffset == buffer.size()) + return NoLineStart; + } + + /* inc currentOffset to after LineStart */ + currentLineStart = currentOffset++; + } else { + if (tag == RegHiBits) + regNum = (regNum & 0xff) | (dataByte << 8); + else if (tag == RegLowBits) + regNum = (regNum & 0xff00) | dataByte; + else if (tag == RegSkip) + regNum++; + else if (tag == RegValue) { + auto reg = offsets_.find(regNum); + + if (reg != offsets_.end()) { + offsets_[regNum] = currentOffset - 1; + + if (++regsDone == offsets_.size()) + return ParseOk; + } + regNum++; + } else + return IllegalTag; + } + } +} -- cgit v1.2.1