libcamera: backport contrast autofocus for the main camera (r4)
Some checks failed
image / image (push) Has been cancelled

The DW9784 VCM works and libcamera discovers it through the sensor's
ancillary link, but nothing in the software ISP ever moves it. Backport
the out-of-tree autofocus work onto v0.7.2:

- 0007-0009 are Vasiliy Doylov's focus control, contrast autofocus and
  focus-loss detection from the softisp-playground branch;
- 0010 is Pavel Machek's Librem5-tested robustness work (centre-window,
  brightness-normalised sharpness, two-phase sweep, settle skip),
  squashed and adapted;
- 0011-0013 are ours: the lens write no longer sits inside the
  no-frame-start-emitter branch, the lensless-camera paths are guarded,
  and AfMode is advertised with a continuous default so that stock
  applications get autofocus without sending AfTrigger.

Provenance and the adaptations made to each patch are recorded in the
patch commit messages.
This commit is contained in:
Jorijn van der Graaf 2026-08-17 02:02:45 +02:00
commit 40ccdfeed6
8 changed files with 1605 additions and 1 deletions

View file

@ -0,0 +1,64 @@
From 5f34df040cda47cfb08d1cb02f4a288de2b8ab8c Mon Sep 17 00:00:00 2001
From: Vasiliy Doylov <nekocwd@mainlining.org>
Date: Mon, 17 Aug 2026 01:51:48 +0200
Subject: [PATCH] AF: detect focus loss
Re-trigger the focus sweep when the sharpness of the settled scene
departs from the sharpness the sweep converged on by more than 30%,
which is what happens when the scene or the subject distance changes.
Keeping the converged maximum around (instead of clearing it at every
phase transition) is what makes that comparison possible.
[Backported from 4da3fec35a15 on gitlab.com/tui/libcamera
millicam_af_6. That tree already carried the settle-skip counter, so
the skip handling of the original hunk is dropped here; it arrives
with the next patch.]
Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>
---
src/ipa/simple/algorithms/af.cpp | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/src/ipa/simple/algorithms/af.cpp b/src/ipa/simple/algorithms/af.cpp
index 3f0f98f93..f321f361e 100644
--- a/src/ipa/simple/algorithms/af.cpp
+++ b/src/ipa/simple/algorithms/af.cpp
@@ -10,6 +10,7 @@
#include <stdint.h>
#include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
#include "control_ids.h"
@@ -73,8 +74,21 @@ void Af::updateFocus([[maybe_unused]] IPAContext &context, [[maybe_unused]] IPAF
}
void Af::step(double& start, double& stop, double& step, double& focus_pos, double& max_pos, uint64_t& max_sharp, uint64_t sharp, bool& sweep){
- if(!sweep)
- return;
+ if(!sweep){
+ if(utils::abs_diff(sharp, max_sharp) > max_sharp*0.3){
+ LOG(IPASoftAutoFocus, Info) << "Focus lost :(";
+ sweep = true;
+ max_sharp = 0;
+ max_pos = 0;
+ focus_pos = 0;
+ start = 0;
+ stop = 100;
+ step = 25;
+ }
+ else {
+ return;
+ }
+ }
if(focus_pos < start) {
focus_pos = start;
return;
@@ -88,7 +102,6 @@ void Af::step(double& start, double& stop, double& step, double& focus_pos, doub
start = std::clamp(max_pos - step, 0.0, 100.0);
stop = std::clamp(max_pos + step, 0.0, 100.0);
focus_pos = start;
- max_sharp = 0;
step /= 2;
if(step <= 0.2){
sweep = false;