Commit Graph

1118 Commits

Author SHA1 Message Date
Stefan Klug
4e720d5bae ipa: libipa: agc_mean_luminance: Fix yTarget handling in constraints
The yTarget loading code is broken and works neither for plain values
nor for arrays of values to form a PWL. Fix this by supporting both
cases. If a list is provided in the tuning file construct a PWL,
otherwise construct a single point PWL with the given value.

Fixes: 24247a12c7 ("ipa: libipa: Add AgcMeanLuminance base class")
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
2025-11-25 17:47:30 +01:00
Stefan Klug
3ed8dabe5a ipa: libipa: agc_mean_luminance: Change luminance target to piecewise linear function
In some situations it is necessary to specify the target brightness
value depending on the overall lux level. Replace the float
relativeLuminanceTraget by a PWL. As the PWL loading code loads a plain
value as single point PWL, backwards compatibility to existing tuning
files is ensured.

While at it, order the class members in reverse xmas tree notation.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-11-25 17:47:16 +01:00
Stefan Klug
7dd713ba2e ipa: rkisp1: lux: Properly handle frame context and active state
With the upcoming regulation rework the processing order in the IPA is
updated a bit so that process() updates the active state with new
measurements and fills the metadata with the data from the corresponding
frame context. In prepare() all parameters for one frame are tied
together using the most up to date values from active state.

Change the lux algorithm to support that order of events. Also prepare
for cases where stats can be null which can happen with the upcoming
regulation rework.

While at it fix a formatting issue reported by checkstyle and drop a
unnecessary local variable.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-11-25 17:42:34 +01:00
Stefan Klug
3b4414ccaa ipa: libipa: pwl: Allow to parse a plain yaml value as single point PWL
In the tuning files, it is useful to specify some values as PWL that
produces a different output value depending on an input value. For
example it is useful to specify the relativeLuminanceTarget depending on
the lux level, so that the regulation regulates a bit darker in low
light scenes. For simple setups this is not necessary and a single value
is sufficient.

This patch extends the yaml loading code, so that a single point PWL can
also be specified as a plain value. This way the following yaml
expressions are all valid:

yTarget: [ 1000, 0.15, 2000, 0.17 ]  # Regular PWL
yTarget: [ 0, 0.17 ]                 # Single point PWL
yTarget: 0.17                        # Same as above

For cases (I'm not aware of any) where a single point Pwl is not allowed
there is no change as that must be checked externally anyways.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
2025-11-25 17:40:38 +01:00
Stefan Klug
dadeb67fcc libipa: exposure_mode_helper: Set quantizationGain in absence of a sensor helper
In commit f077c58e08 ("libipa: exposure_mode_helper: Take
exposure/gain quantization into account") calculation of the
quantization gain was added to ExposureModeHelper::clampGain(). This
works as expected when a sensor helper is configured but the gain is not
reset to 1.0 in case the sensor helper is not configured. This leads to
incorrect gain calculations in ExposureModeHelper::splitExposure() as
that expects the quantization gain to be valid in any case. Fix that by
setting the quantization gain to 1.0 in case no sensor helper is
configured.

Fixes: f077c58e08 ("libipa: exposure_mode_helper: Take exposure/gain quantization into account")
Closes: https://gitlab.freedesktop.org/camera/libcamera/-/issues/292
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Tested-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
2025-11-25 17:32:50 +01:00
Isaac Scott
43ab0d487b libipa: module: Allow algorithms to be disabled via the tuning file
It is beneficial to have the option during development to disable and
enable algorithms via the tuning file without having to delete their
entries.

Add support for an optional "enabled" parameter to accomplish this.

Usage example:
version: 1
algorithms:
  - Agc:
      enabled: true
  - Awb:
      enabled: false

This will enable AGC, and disable AWB. If the enabled flag is not
present, the algorithm will be enabled.

Signed-off-by: Isaac Scott <isaac.scott@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
[Kieran: Reflow text]
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-11-24 17:29:11 +00:00
Milan Zamazal
443e5a6c31 libcamera: software_isp: Fix gamma table when CCM is used
Software CPU ISP computes a gamma lookup table.  The table incorporates
black level and contrast.  All entries in the table below the black
level are set to 0.  This is not necessarily correct all the time.

Let's consider this case: The CCM is

  [1 0 0]
  [0 1 0]
  [0 0 0]

and contrast is set to zero.  The gamma table has all the entries above
the black level set to 186 (due to zero contrast) and all the entries
below the black level set to 0.  CCM is applied before gamma, a
non-black level pixel has the blue component set to 0 with the CCM
above.  Now, when the gamma lookup is applied, the red and green
components are set to 186, while the blue component is set to 0.  The
resulting pixel is then yellow rather than grey (as it should be with
zero contrast).

There are two ways to fix this: Either clamping pixel colour channels to
the black level in debayering or setting the below black level entries
in the gamma lookup table to the lowest value of the gamma table rather
than 0.  Both should have the same effect.  Let's opt for the latter for
its simplicity.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-11-19 10:38:08 +00:00
Rui Wang
30779421e8 ipa: rkisp1: dpf: Enable strength after enable Dpf
The filter strength configuration block was previously only enabled on the
first frame (frame == 0). Apply the strength values when denoise is active.
This prevents the strength config from being disabled on subsequent frames.

Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
2025-11-14 22:03:22 +01:00
Barnabás Pőcze
79be15a5f1 ipa: libipa: agc_mean_luminance: Avoid unnecessary copies
`constraintModes()` and `exposureModeHelpers()` need not return copies of
the internal objects, exposing const references is sufficient, so do that.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-11-03 17:05:45 +01:00
Benjamin Mugnier
b1f09c013a ipa: rpi: vd56g3: Fix frameIntegrationDiff value
In the vd56g3 user manual :

  MAX_EXPOSURE_COARSE = FRAME_LENGTH − EXP_COARSE_INTG_MARGIN − 7
  EXP_COARSE_INTG_MARGIN >= 68

Therefore, frameIntegrationDiff is EXP_COARSE_INTG_MARGIN + 7, equals
75. This value is coherent with the VD56G3_EXPOSURE_MARGIN in the kernel
driver source code.

Reported-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-30 14:54:44 +00:00
Daniel Scally
6a393789f3 libipa: camera_sensor_helper: Add imx708
The imx708 sensor driver has long been available, especially in raspberry
pi kernels; and the raspberry pi ipa module has had the corresponding
helper class since 2023 (952ef94ed7). The camera sensor properties
database also has an entry for it (2fb0f25019), but the camera sensor
helper class is missing from the common libipa component. So add it, with
the same gain formula present in the raspberry pi ipa module, and the black
level taken from the rpi tuning files.

Handling the raspberry pi specific "wide" / "noir" suffixes is omitted.
They are not present in the camera sensor properties database either.

Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
[Add black level, extend commit message.]
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-30 14:50:59 +00:00
David Plowman
36f9cdcdb4 ipa: rpi: lux: Use floating statistics region to obtain the current Y value
The Y value from the first floating region is now a better choice for
a Y value that is invariant to (for example) the metering mode.

Both VC4 and PiSP platforms store full image Y statistics here.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-26 23:32:50 +00:00
David Plowman
0810b8a70a ipa: rpi: vc4: Use a floating statistics region for a full image Y sum
We're going to use a "floating statistics region" to store a full
image Y sum. The VC4 platform actually has no floating region for
this, but we can synthesize such a region as follows in software.

We know that the 15 AGC regions that we do have are arranged to cover
the whole image, and they cannot be changed. Adding up the R, G and B
values here will get us most of the way to Y. But we do also need to
know the most recent colour gains, so code must also be added to
remember the last AWB status.

With this change, algorithms can now look at the first floating region
on both VC4 and PiSP platforms to get a full image Y average value.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-26 23:32:50 +00:00
David Plowman
3bc722b5da ipa: rpi: pisp: Use a floating region to get whole image Y statistics
Floating regions are currently unused on the PiSP platform, so we can
use one of them to get an average Y value for the whole image.

If an algorithm (such as the "lux" algorithm) wants a scene-referred
estimate of absolute brightness, then this would be a better choice
than a value from Y histogram as the latter is not invariant to the
metering mode (e.g. centre-weighted, spot etc.). (So note that for the
AGC/AEC algorithm, where the metering mode is relevant, the Y
histogram is the appropriate choice.)

We also fix the loop that copies the hardware's floating region values
into our statistics structure; it was using the wrong limit which was
causing it not to do anything.

A future commit will update the lux algorithm to use this feature.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-26 23:32:50 +00:00
David Plowman
17ee3b6089 ipa: rpi: lux: Handle camera mode sensitivity correctly
The camera mode sensitivity needs to be taken into account for the lux
calculation. For example, the IMX708 binned mode (with a sensitivity
of 2.0) would otherwise show double the correct lux value.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-26 23:32:50 +00:00
David Plowman
557622308f ipa: rpi: Fix the set function for floating statistics regions
Previously it was calling the wrong internal function which would do
nothing.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-26 23:32:50 +00:00
Jacopo Mondi
19825d2334 ipa: meson.build: Remove duplicated variable
The 'ipa_names' variable is declared twice. Remove it.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2025-10-20 11:34:39 +03:00
Naushir Patuck
b320b20db7 ipa: rpi: pisp: Allow an initial decompand curve to be set on the FE
In the current code, decompand will only set a curve in the prepare
phase, which will only run after 1-2 frames pass through the FE. This
is fixed by adding an initialValues() member function to the decompand
algorithm, which will be called in the IPA before we start the hardware
streaming.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Tested-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-08 11:36:40 +01:00
Naushir Patuck
413f03a738 ipa: rpi: pisp: Add a DecompandAlgorithm class
The decompand algorithm implementation will subclass the
DecompandAlgorithm class. This will be needed for setting the initial
decompand values in a future commit.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Tested-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-08 11:36:40 +01:00
Naushir Patuck
ffcdbf0980 ipa: rpi: Add FE globals as a parameter to applyDecompand()
Don't let applyDecompand() directly change the FE global enables.
Instead pass the global mask into the function and set it in the caller.
This will be needed when a future commit will add setting the decompand
initial values.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Tested-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-08 11:36:40 +01:00
Sena Asotani
bfd09aa474 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>
Tested-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-08 11:36:40 +01:00
Milan Zamazal
f0f2aca566 ipa: simple: agc: Prevent division by zero in AGC
If the histogram size is non-zero but lower than the number of bins,
yHistValsPerBin is zero and then the AGC processing crashes on division
by it.  Let's check yHistValsPerBin for being zero and stop AGC
processing in such a case.  The condition also covers the cases where
histogramSize or yHistValsPerBinMod are zero.

Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Hans de Goede <hansg@kernel.org>
Tested-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-02 22:07:48 +01:00
Milan Zamazal
1102a96854 ipa: simple: blc: Prevent division by zero in BLC
When there are no values in the histogram, BLC simple IPA can crash on
division by zero.  We cannot get anything meaningful in such a case
anyway, let's simply return from `process()' then.

Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
Reviewed-by: Hans de Goede <hansg@kernel.org>
Tested-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-02 22:07:44 +01:00
Milan Zamazal
0201e11f27 ipa: simple: awb: Use correct type in std::accumulate
The result type of the std::accumulate() call is uint64_t; let's use the
same type for the initial value (rather than the default int) to prevent
summing up the values in a different integer type.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Hans de Goede <hansg@kernel.org>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Tested-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-02 22:07:38 +01:00
Milan Zamazal
6a7fe29a18 ipa: simple: awb: Avoid incorrect arithmetic in AWB
The R/G/B sums computed in AWB simple IPA may be zero or perhaps even
negative.  Let's make sure the sums are always positive, to prevent
division by zero or completely nonsense results.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Hans de Goede <hansg@kernel.org>
Tested-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-02 22:07:33 +01:00
Hans de Goede
07b87b8095 ipa: simple: blc: Use 16 as starting blacklevel when there is no sensor-info
At the moment the blc code uses 255 as starting blacklevel for sensors
where there is no blacklevel info in the sensor-helper.

There are a number of issues with this:

1. When the first frame is bad (e.g. mostly white) which happens sometimes
the initial blacklevel will be kept leading to a divide by zero problem
in the AGC code (this divide by 0 problem is avoided in the AGC code by
not running the AGC algorithm).

2. Not runnning the AGC algorithm means that the gain/exposure do not
change, which causes the BLC algorithm to not run on the next frames,
so we keep the bad 255 blacklevel which stops AGC from running which
stops BLC from running. Leaving things stuck at a 255 blacklevel
resulting in an unusuable image.

3. Sometimes the auto-blc code leads to an unrealistic high
blacklevel detection which results in lower image quality.

To fix this start with a blacklevel of 16, which is the highest
(4096 / 256) blacklevel used for any sensor listing a blackLevel_
value in the sensor-helper class.

Note 2. could alternatively be fixed by disabling the check for
exposure/gain changes when the blacklevel is unrealistic high,
but that still leaves the other problems.

Signed-off-by: Hans de Goede <hansg@kernel.org>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-01 16:55:54 +01:00
Hans de Goede
9b441cf198 libcamera: software_isp: Add valid flag to struct SwIspStats
Generating statistics for every single frame is not really necessary.

However a roundtrip through ipa_->processStats() still need to be done
every frame, even if there are no stats to make the IPA generate metadata
for every frame.

Add a valid flag to the statistics struct to let the IPA know when there
are no statistics for the frame being processed and modify the IPA to
only generate metadata for frames without valid statistics.

This is a preparation patch for skipping statistics generation for some
frames.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-01 16:45:17 +01:00
Hans de Goede
b5c89375f9 ipa: software_isp: AGC: Only use integers for exposure calculations
Exposure is an integer, instead of re-using the "double next" used
for again calculations, doing intermediate calculations with double
precision, use a local next variable of an integer type.

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-01 16:45:17 +01:00
Hans de Goede
5d62463915 ipa: software_isp: AGC: Raise exposure or gain not both at the same time
Raise either exposure or gain; not both at the same time.

Before this change when the last exposure raise is done, hitting
exposure-max, gain would be increased at the same time.

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-01 16:45:17 +01:00
Hans de Goede
950ca85e8a ipa: software_isp: AGC: Do not lower gain below 1.0
At the moment when the overall image brightness is considered too high
the AGC code will lower the gain all the way down to againMin before
considering lowering the exposure.

What should happen instead is lower the gain no lower than 1.0 and after
that lower the exposure instead of lowering the gain.

Otherwise there might be a heavily overexposed image (e.g. all white)
which then is made less white by a gain < 1.0 which is no good.

When there is no sensor-helper, assume the driver reported default-gain
value is close to a gain of 1.0 .

While at it also remove the weird limitation to only lower the gain
when exposure is set to the maximum. As long as the gain is higher
than the default gain, the gain should be lowered first.

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-01 16:45:17 +01:00
Hans de Goede
7a7935e4bc ipa: software_isp: Fix context_.configuration.agc.againMin init
Currently context_.configuration.agc.againMin is not initialized
when the control reports a non 0 minimum gain value.

So far only the againMin == 0 case was handled and
context_.configuration.agc.againMin was left unset otherwise.

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-10-01 16:45:17 +01:00
David Plowman
5ca7afd2d3 ipa: rpi: agc: Allow exposure mode to be updated in auto mode
The code was only allowing the exposure mode to be updated when both
exposure/gain were in manual mode, which is a mistake. It needs to be
updatable precisely when the auto modes are enabled.

The fix is to ignore the enabled/disabled status of AEC/AGC, matching
our other controls (metering mode, constraint mode etc.). While there
might be a debate to be had about what the actual behaviour of all
these controls should be, for the time being we'll just match
everything else.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-25 10:30:06 +01:00
Stefan Klug
f62a1498e9 ipa: rkisp1: Add WDR algorithm
Add a WDR algorithm to do global tone mapping. Global tone mapping is
used to increase the perceived dynamic range of an image. The typical
effect is that in areas that are normally overexposed, additional
structure becomes visible.

The overall idea is that the algorithm applies an exposure value
correction to underexpose the image to the point where only a small
number of saturated pixels is left. This artificial underexposure is
then mitigated by applying a tone mapping curve.

This algorithm implements 4 tone mapping strategies:
- Linear
- Power
- Exponential
- Histogram equalization

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
026f25f32b rkisp1: agc: Agc add yTarget to frame context
The upcoming WDR algorithm needs access to the effective yTarget value
for its calculations. Add it to the frame context.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
06fe931d79 libipa: agc_mean_luminance: Add support for additional constraints
Add support for additional constraints added at runtime. This is for
example useful for WDR use cases where you want to add an upper
constraint to limit the amount of saturated pixels.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
6eb02d6759 libipa: agc_mean_luminance: Introduce effectiveYTarget() accessor
The upcoming WDR algorithm needs to know the effective y target (Which
includes the current ExposureValue). Add an accessor for that.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul ELder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
c7cc1f7f0d pipeline: rkisp1: Query kernel for available params blocks
Query the params device for RKISP1_CID_SUPPORTED_PARAMS_BLOCKS and
inject the information into the IPA hardware context for use by the
algorithms.

To be able to modify the hardware configuration at runtime, replace the
pointer with an instance and create a copy of the static hardware
specific data.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
c8f323b7ae ipa: rkisp1: Switch histogram to RGB combined mode
The Y mode of the histogram gets captured at the ISP output, before the
output formatter.  This has the side effect that the first and the last
bins are empty in case of limited YUV range.  Another side effect is
that gamma and GWDR processing is included in the histogram which makes
algorithm development very difficult. In RGB mode the histogram is taken
after xtalk (CCM) and is therefore independent of gamma and WDR. The
limited range issue also does not apply. In the ISP reference it is
however stated that "it is not possible to calculate a luminance or
grayscale histogram from an RGB histogram since the position information
is lost during its generation".

During testing the RGB histogram provided good data and better
algorithmic stability at a possible (but not measured) inaccuracy.

Another option would be to pass the color space information into the IPA
and strip the histogram accordingly. For ease of implementation switch to
the RGB mode.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
ef830669d0 ipa: rkisp1: agc: Add correction for exposure quantization
There are several occasions where quantization can lead to visible
effects.

In WDR mode it can happen that exposure times get set to very low values
(Sometimes 2-3 lines). This intentionally introduced underexposure is
corrected by the GWDR module. As exposure time is quantized by lines,
the smallest possible change in exposure time now results in a quite
visible change in perceived brightness.

On some sensors the possible gain steps are also quite large leading to
visible jumps if e.g. if the exposure time is fixed.

Mitigate that by applying a global gain to account for the error
introduced by the exposure quantization.

ToDo: This needs perfect frame synchronous control of the sensor to work
properly which is not guaranteed in all cases. It still improves the
behavior with the current regulation and can easily be skipped, be
removing the compress algorithm from the tuning file.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
57a46118a8 libipa: exposure_mode_helper: Calculate quantization gain in splitExposure()
Calculate the error introduced by quantization as "quantization gain"
and return it separately from splitExposure(). It is not included in the
digital gain, to not silently ignore the limits imposed by the AGC
configuration.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
0ba6d930de libipa: agc_mean_luminance: Configure the exposure mode helpers
Add a function to configure the exposure mode helpers with the line
length and sensor helper to take quantization effects into account.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
3d310f106a libipa: agc_mean_luminance: Fix constraint logging
The debug log statements in constraintClampGain() are after the
assignment of gain. So they correctly log when the constraint applies,
but the gain values logged are the same. Fix that.

Fixes: 42e18c96bc ("libipa: agc_mean_luminance: Add debug logging")
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
3c3b9f1091 libipa: exposure_mode_helper: Remove unnecessary clamp calls
Except for the first iteration of the loop and in the case of an empty
gains_ vector, the values were run through clamp two times which is
unnecessary. Remove that by clamping the initial value.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
0efa130b25 libipa: exposure_mode_helper: Remove double calculation of lastStageGain
lastStageGain gets recalculated unconditionally even though it is the
stageGain of the last stage. Refactor for increased simplicity and
efficiency.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
f077c58e08 libipa: exposure_mode_helper: Take exposure/gain quantization into account
In ExposureModeHelper::splitExposure() the quantization of exposure time
and gain is not taken into account. This can lead to visible flicker
when the quantization steps are too big. As a preparation to fixing
that, add a function to set the sensor line length and the current
sensor mode helper and extend the clampXXX functions to return the
quantization error.

By default the exposure time quantization is assumed to be 1us and gain
is assumed to not be quantized at all.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
1400058ed4 libipa: camera_sensor_helper: Add quantizeGain() function
Add a small utility function that calculates the quantized gain that
gets applied by a sensor when the gain code is set to gainCode(gain).
This is needed by algorithms to calculate a digital correction gain that
gets applied to mitigate the error introduce by quantization.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Stefan Klug
b57ad23eb5 ipa: rkisp1: Add basic compression algorithm
The i.MX8 M Plus has a compression curve inside the compand block.  This
curve is necessary to process HDR stitched data and is useful for other
aspects like applying a digital gain to the incoming sensor data.

Add a basic algorithm for the compression curve. This algorithm has a
hardcoded input width of 20bit and output width of 12bit which matches
the imx8mp pipeline. Only a static gain is supported in this version.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-19 10:48:05 +01:00
Matthias Fend
e8304bc6c1 libcamera: libipa: camera_sensor: Add Himax HM1246 sensor properties
Provide the Himax HM1246 camera sensor properties and registration with
libipa for the gain code helpers.

Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-18 16:31:28 +01:00
Benjamin Mugnier
481c659c7e libcamera: libipa: Add vd55g1 support for libipa
Values are sourced initially from the vd55g1 user manual.

Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-18 12:50:02 +01:00
Benjamin Mugnier
59db8f9863 ipa: rpi: Add vd55g1 tuning files for rpi
For both vc4 and pisp, vd55g1.json has been generated using ctt with
rpi.dpc algorithm removed as this is already handled in the sensor's
ISP. vd55g1_mono.json has been adapted from vd55g1.json by removing
color correction related algorithms.

Adding Cyril Liotard as co-developer for providing the base vd55g1.json
tuning files for both vc4 and pisp. Thank you.

Co-Developed-by: Cyril Liotard <cyril.liotard@st.com>
Signed-off-by: Cyril Liotard <cyril.liotard@st.com>
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Acked-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2025-09-18 12:50:02 +01:00