Skip to content

Commit 3a452f4

Browse files
asofamnaushir
authored andcommitted
ipa: rpi: pisp: Add decompand support using PiSP hardware block
This patch integrates a new decompand algorithm that utilizes the PiSP FE hardware block available on Raspberry Pi 5. The implementation enables conversion of companded sensor data into linear format prior to ISP processing. Changes include: - Implementation of decompand logic for controller and pipe interfaces - Enabling decompand block by "rpi.decompand" in tuning.json Signed-off-by: Sena Asotani <aso.fam429@gmail.com> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
1 parent 8c907eb commit 3a452f4

5 files changed

Lines changed: 138 additions & 0 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#include "libipa/pwl.h"
4+
5+
struct DecompandStatus {
6+
uint32_t bitdepth;
7+
libcamera::ipa::Pwl decompandCurve;
8+
};

src/ipa/rpi/controller/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rpi_ipa_controller_sources = files([
1414
'rpi/cac.cpp',
1515
'rpi/ccm.cpp',
1616
'rpi/contrast.cpp',
17+
'rpi/decompand.cpp',
1718
'rpi/denoise.cpp',
1819
'rpi/dpc.cpp',
1920
'rpi/geq.cpp',
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include "decompand.h"
2+
3+
#include <libcamera/base/log.h>
4+
5+
#include "../decompand_status.h"
6+
#include "../histogram.h"
7+
8+
using namespace RPiController;
9+
using namespace libcamera;
10+
11+
LOG_DEFINE_CATEGORY(RPiDecompand)
12+
13+
#define NAME "rpi.decompand"
14+
15+
Decompand::Decompand(Controller *controller)
16+
: Algorithm(controller)
17+
{
18+
}
19+
20+
char const *Decompand::name() const
21+
{
22+
return NAME;
23+
}
24+
25+
int Decompand::read(const libcamera::YamlObject &params)
26+
{
27+
config_.bitdepth = params["bitdepth"].get<uint32_t>(0);
28+
config_.decompandCurve = params["decompand_curve"].get<ipa::Pwl>(ipa::Pwl{});
29+
return config_.decompandCurve.empty() ? -EINVAL : 0;
30+
}
31+
32+
void Decompand::initialise()
33+
{
34+
}
35+
36+
void Decompand::switchMode([[maybe_unused]] CameraMode const &cameraMode,
37+
[[maybe_unused]] Metadata *metadata)
38+
{
39+
mode_ = cameraMode;
40+
}
41+
42+
void Decompand::prepare(Metadata *imageMetadata)
43+
{
44+
DecompandStatus decompandStatus;
45+
46+
if (config_.bitdepth == 0 || mode_.bitdepth == config_.bitdepth) {
47+
decompandStatus.decompandCurve = config_.decompandCurve;
48+
imageMetadata->set("decompand.status", decompandStatus);
49+
}
50+
}
51+
52+
/* Register algorithm with the system. */
53+
static Algorithm *create(Controller *controller)
54+
{
55+
return (Algorithm *)new Decompand(controller);
56+
}
57+
58+
static RegisterAlgorithm reg(NAME, &create);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include <libipa/pwl.h>
4+
5+
#include "../decompand_status.h"
6+
7+
#include "algorithm.h"
8+
9+
namespace RPiController {
10+
11+
struct DecompandConfig {
12+
uint32_t bitdepth;
13+
libcamera::ipa::Pwl decompandCurve;
14+
};
15+
16+
class Decompand : public Algorithm
17+
{
18+
public:
19+
Decompand(Controller *controller = NULL);
20+
char const *name() const override;
21+
int read(const libcamera::YamlObject &params) override;
22+
void initialise() override;
23+
void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
24+
void prepare(Metadata *imageMetadata) override;
25+
26+
private:
27+
CameraMode mode_;
28+
DecompandConfig config_;
29+
};
30+
31+
} /* namespace RPiController */

src/ipa/rpi/pisp/pisp.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "controller/cac_status.h"
3333
#include "controller/ccm_status.h"
3434
#include "controller/contrast_status.h"
35+
#include "controller/decompand_status.h"
3536
#include "controller/denoise_algorithm.h"
3637
#include "controller/denoise_status.h"
3738
#include "controller/dpc_status.h"
@@ -113,6 +114,25 @@ int generateLut(const ipa::Pwl &pwl, uint32_t *lut, std::size_t lutSize,
113114
return 0;
114115
}
115116

117+
int generateDecompandLut(const ipa::Pwl &pwl, uint16_t *lut, std::size_t lutSize = 65)
118+
{
119+
if (pwl.empty())
120+
return -EINVAL;
121+
122+
constexpr int step = 1024;
123+
for (std::size_t i = 0; i < lutSize; ++i) {
124+
int x = i * step;
125+
126+
int y = pwl.eval(x);
127+
if (y < 0)
128+
return -1;
129+
130+
lut[i] = static_cast<uint16_t>(std::min(y, 65535));
131+
}
132+
133+
return 0;
134+
}
135+
116136
void packLscLut(uint32_t packed[NumLscVertexes][NumLscVertexes],
117137
double const rgb[3][NumLscVertexes][NumLscVertexes])
118138
{
@@ -236,6 +256,7 @@ class IpaPiSP final : public IpaBase
236256
void applyLensShading(const AlscStatus *alscStatus,
237257
pisp_be_global_config &global);
238258
void applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global);
259+
void applyDecompand(const DecompandStatus *decompandStatus);
239260
void applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global);
240261
void applyTdn(const TdnStatus *tdnStatus, const DeviceStatus *deviceStatus,
241262
pisp_be_global_config &global);
@@ -351,6 +372,11 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams &params,
351372
if (noiseStatus)
352373
applyFocusStats(noiseStatus);
353374

375+
DecompandStatus *decompandStatus =
376+
rpiMetadata.getLocked<DecompandStatus>("decompand.status");
377+
if (decompandStatus)
378+
applyDecompand(decompandStatus);
379+
354380
BlackLevelStatus *blackLevelStatus =
355381
rpiMetadata.getLocked<BlackLevelStatus>("black_level.status");
356382
if (blackLevelStatus)
@@ -702,6 +728,20 @@ void IpaPiSP::applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global
702728
be_->SetDpc(dpc);
703729
}
704730

731+
void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus)
732+
{
733+
pisp_fe_global_config feGlobal;
734+
pisp_fe_decompand_config decompand = {};
735+
736+
fe_->GetGlobal(feGlobal);
737+
738+
if (!generateDecompandLut(decompandStatus->decompandCurve, decompand.lut, PISP_FE_DECOMPAND_LUT_SIZE)) {
739+
fe_->SetDecompand(decompand);
740+
feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND;
741+
fe_->SetGlobal(feGlobal);
742+
}
743+
}
744+
705745
void IpaPiSP::applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global)
706746
{
707747
pisp_be_sdn_config sdn = {};

0 commit comments

Comments
 (0)