Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drivers: DAI: Intel: DMIC: Program start symmetrically for PDMx #86308

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

singalsu
Copy link
Collaborator

This PR contains proposed improvements to ACE and cAVS DMIC start sequence to avoid possible PDMx controllers out-of-sync start.

@singalsu singalsu force-pushed the dai_intel_dmic_start_improve branch from 01a30f6 to 9b87c0a Compare February 26, 2025 17:26
@singalsu
Copy link
Collaborator Author

I rebased this patch and dropped commit for spinlock set move. A SOF PR test for this patch runs now in thesofproject/sof#9859 .

This change is assumed to fix the random corruption of 4ch
capture for PDM1 channels 3-4 in PTL platform. There are no
solid facts behind this change but assumption that PDMx
controllers are not in sync if the start sequence for PDM1
is further away from PDM0. The PDM0 internal state may be
different from PDM1

The single for loop to handle the CIC and FIR start sequence
is split into two for loops to handle same registers update
tasks symmetrically for all stereo PDM controllers. E.g. two
PDMs for four microphones.

First loop programs the CIC_CONTROL and MIC_CONTROL registers
of the PDMx controllers. These features belong to the CIC block
in DMIC IP. Second loop programs the FIR_CONTROL registers of
the PDMx controllers.

In a stress test of 100 times repeated commands:

arecord -Dhw:0,6 -fS32_LE -r48000 -c4 -d 10 dmic_test_1.wav; \
sleep 0.5; \
arecord -Dhw:0,6 -fS32_LE -r48000 -c4 -d 10 dmic_test_2.wav; \
sleep 1

The corruption occurrence with xt-clang build was e.g. 87/200
fails in one of wav files giving 43.5% occurrence. The test was
done with Zephyr commit fe29c40
("llext: add inspection API test suite").

In a gcc build the occurrence of corruption is lower, around 6%
but it is seen that the channels 3-4 pdm1 are swapping randomly.

With this fix the corruption occurred zero times in xt-clang
and gcc builds with same 100 repeats.

Signed-off-by: Seppo Ingalsuo <[email protected]>
@singalsu singalsu force-pushed the dai_intel_dmic_start_improve branch from 9b87c0a to 326def7 Compare February 27, 2025 12:44
@singalsu
Copy link
Collaborator Author

I dropped the cAVS patch. The issue is more difficult to repeat than the issue with PTL. I'm using this Octave script for stress testing the issue.

function ret = dmic_noise_stress_test()
dev = "hw:0,6";
nch = 4;
test_count = 100;
level_thr = -20;

fn1 = "/tmp/dmic_test_mute_1.wav";
fn2 = "/tmp/dmic_test_mute_2.wav";
redir = "2> /dev/null";

rec_cmd = sprintf('arecord -D%s -fS32_LE -r48000 -c%d -d 5 %s %s; sleep 0.5; arecord -D%s -fS32_LE -r48000 -c%d -d 5 %s %s', ...
                  dev, nch, fn1, redir, dev, nch, fn2, redir);

sleep_cmd = "sleep 1";

n = 0;
fail_count = 0;
for i = 1:test_count
        [ret, out] = system(rec_cmd);
        if ret
                fprintf(1, "Failed: %s\n", rec_cmd);
                return
        end

        % Check 1st capture
        n = n + 1;
        levels = channel_levels(fn1);
        fail = check_levels(levels, level_thr);
        fail_count = fail_count + fail;
        print_stats(n, nch, levels, fail, fail_count);

        n = n + 1;
        levels = channel_levels(fn2);
        fail = check_levels(levels, level_thr);
        fail_count = fail_count + fail;
        print_stats(n, nch, levels, fail, fail_count);

        [ret, out] = system(sleep_cmd);
        if ret
                fprintf(1, "Failed: %s\n", rec_cmd);
                return
        end
end
end

function print_stats(n, nch, levels, fail, fail_count)
        printf("%8d,", n);
        for j = 1:nch
                printf(" %8.1f,", levels(j));
        end
        printf("%8d, %8d, %8.1f\n", fail, fail_count, 100*fail_count/n);
end

function fail = check_levels(levels, level_thr)
        idx = find(levels > level_thr);
        if isempty(idx)
                fail = 0;
        else
                fail = 1;
        end
end

function levels = channel_levels(fn)
        [x, fs] = audioread(fn);
        s = size(x);
        nch = s(2);
        for i = 1:nch
                levels(i) = level_dbfs(x(:,i));
        end
end

function dbfs = level_dbfs(x)
level_ms = mean(x.^2);
dbfs = 10*log10(level_ms + 1e-20) + 20*log10(sqrt(2));
end

@singalsu
Copy link
Collaborator Author

With the failing version, with xt-clang, the trimmed output looks like this. The -132.2 dB levels are from disconnected microphones in DUT for channels 2 and 4. In the end there is 43.5% failures.

       1,    -49.6,   -132.2,    -49.5,   -132.2,       0,        0,      0.0
       2,    -49.2,   -134.9,     -0.9,   -134.9,       1,        1,     50.0
       3,    -49.4,   -135.1,     -0.9,   -135.1,       1,        2,     66.7
       4,    -49.3,   -135.0,    -49.2,   -135.0,       0,        2,     50.0
...
     197,    -49.3,   -132.2,     -0.9,   -132.2,       1,       85,     43.1
     198,    -49.2,   -132.2,     -0.9,   -132.2,       1,       86,     43.4
     199,    -49.6,   -134.9,     -0.9,   -134.9,       1,       87,     43.7
     200,    -49.2,   -133.2,    -49.2,   -133.2,       0,       87,     43.5

With gcc build, there is channels swapping happening. It can be seen with channels 3-4 levels . The disconnected level of -73 dB is due to different version of equalizer for gcc build. In the end 5.5% are failed. The channels swaps are not counted in the script.


       1,    -47.5,    -73.3,    -73.0,    -47.0,       0,        0,      0.0
       2,    -48.8,    -73.3,    -48.8,    -73.1,       0,        0,      0.0
       3,    -47.3,    -73.1,    -47.1,    -73.1,       0,        0,      0.0
       4,    -47.8,    -73.3,    -73.0,    -47.8,       0,        0,      0.0
---
     197,    -49.7,    -73.2,    -73.0,    -49.7,       0,       10,      5.1
     198,    -49.9,    -73.1,     -1.3,    -73.1,       1,       11,      5.6
     199,    -49.7,    -73.3,    -49.6,    -73.1,       0,       11,      5.5
     200,    -50.1,    -73.2,    -50.1,   -104.4,       0,       11,      5.5

@singalsu
Copy link
Collaborator Author

I lost PTL device while stress testing this patch with xt-clang build. The gcc build test completed for 100 loops without corruptions and channels swaps.

...
     197,    -49.9,    -73.1,    -50.0,    -73.1,       0,        0,      0.0
     198,    -50.0,    -73.1,    -50.3,    -73.1,       0,        0,      0.0
     199,    -50.1,    -73.3,    -50.4,    -73.1,       0,        0,      0.0
     200,    -50.0,    -73.1,    -50.4,    -73.1,       0,        0,      0.0

@singalsu
Copy link
Collaborator Author

The PTL xt-clang build of this patch passed 500 loops without corruption or channels swap.

---
     997,    -49.8,   -132.2,    -50.5,   -132.2,       0,        0,      0.0
     998,    -49.9,   -132.2,    -50.5,   -132.2,       0,        0,      0.0
     999,    -49.9,   -132.2,    -50.5,   -132.2,       0,        0,      0.0
    1000,    -49.6,   -135.2,    -50.3,   -134.5,       0,        0,      0.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants