Compare commits

...

73 commits

Author SHA1 Message Date
Jacopo Maroli
c3f0119ae9 [PATCH] fix channel ordering 2024-11-22 17:05:21 +01:00
Hin-Tak Leung
c693d203d9 Merge remote-tracking branch 'origin/v6.1' into v6.5 2024-01-10 15:54:35 +00:00
HinTak
005fc23648
Merge pull request #23 from makermelissa/fix-install-config
Fix /boot/config.txt for bookworm installs
2024-01-10 15:53:37 +00:00
Melissa LeBlanc-Williams
58082f3fe8 Fix /boot/config.txt for bookworm installs 2024-01-05 10:46:23 -08:00
Hin-Tak Leung
cc37c8fb52 v6.5: ASoC: soc-core.c: add index on snd_soc_of_get_dai_name()
commit 3c8b5861850c734add65233e538d4a8c2dff95d9
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Tue Jun 20 02:14:11 2023 +0000

    ASoC: soc-core.c: add index on snd_soc_of_get_dai_name()

    Current snd_soc_of_get_dai_name() doesn't accept index
    for #sound-dai-cells. It is not useful for user.
    This patch adds it.

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Link: https://lore.kernel.org/r/87pm5qdgng.wl-kuninori.morimoto.gx@renesas.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2023-10-04 23:18:04 +01:00
Hin-Tak Leung
c3a2d96ba2 Changing install URL to point to mine. 2023-08-03 23:30:03 +01:00
Hin-Tak Leung
7aef82f3be Merge remote-tracking branch 'origin/v6.1' into v6.4 2023-08-02 02:10:52 +01:00
Hin-Tak Leung
4ab8158c18 Fine tuning the regex from discussion in the last pull 2023-08-02 02:08:55 +01:00
Hin-Tak Leung
8f377d1eaa Fine tuning the regex from discussion in the last pull 2023-08-02 02:07:04 +01:00
Hin-Tak Leung
aaa2090dbf Merge remote-tracking branch 'origin/v6.1' into v6.4 2023-08-02 02:01:48 +01:00
HinTak
f25e76508f
Merge pull request #7 from hellow554/v6.1
fix detection of kernel modules on 64-bit image
2023-08-02 01:59:17 +01:00
Hin-Tak Leung
a46c3f6324 Re-store support for v6.3 in the v6.4 branch 2023-07-27 02:08:40 +01:00
Hin-Tak Leung
2a40c7dbff v6.4: switch to use c2c_params instead of params
commit 99fddc1618ff64cc71bd51dbf83bd13e74778fe0
Merge: 72456c24c8357 1ea63f29c2771
Author: Mark Brown <broonie@kernel.org>
Date:   Wed Apr 5 16:35:09 2023 +0100

    ASoC: clarify Codec2Codec params

    Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

    ASoC is supporting Codec2Codec, but its parameter name is
    "params" and "num_params" which are very unclear naming.

    This patch-set clarifies it by replacing to c2c_params / num_c2c_params.

commit 1ea63f29c27712d6b9c45af67cd71299d849c5e3
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Sun Apr 2 23:00:17 2023 +0000

    ASoC: soc.h: remove unused params/num_params

    No drivers are using params/num_params any more.
    Let's remove these.

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Link: https://lore.kernel.org/r/87iledc2ke.wl-kuninori.morimoto.gx@renesas.com
    Signed-off-by: Mark Brown <broonie@kernel.org>

commit e7a73b05542d82e209af450dd90b730255f6e775
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Sun Apr 2 23:00:07 2023 +0000

    ASoC: samsung: switch to use c2c_params instead of params

    ASoC is now using c2c_params instead of params. This patch replace it.
    num_c2c_params (was num_params) was not mandatory before,
    but let's set it by this patch.

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Link: https://lore.kernel.org/r/87jzytc2kp.wl-kuninori.morimoto.gx@renesas.com
    Signed-off-by: Mark Brown <broonie@kernel.org>

commit 433f4a1697fae78c34377de1ef3abd26aec8214e
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Sun Apr 2 22:59:57 2023 +0000

    ASoC: meson: switch to use c2c_params instead of params

    ASoC is now using c2c_params instead of params. This patch replace it.
    num_c2c_params (was num_params) was not mandatory before,
    but let's set it by this patch.

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Link: https://lore.kernel.org/r/87lej9c2ky.wl-kuninori.morimoto.gx@renesas.com
    Signed-off-by: Mark Brown <broonie@kernel.org>

commit 7ddc7f91beb285246e926e3adf0b292b071aea33
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Sun Apr 2 22:59:35 2023 +0000

    ASoC: soc.h: clarify Codec2Codec params

    snd_soc_dai_link has params/num_params, but it is unclear that
    params for what. This patch clarify it is params for Codec2Codec.

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Link: https://lore.kernel.org/r/87o7o5c2lk.wl-kuninori.morimoto.gx@renesas.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-27 01:52:33 +01:00
Marcel Hellwig
f69370b841 fix detection of kernel modules on 64-bit image
The lib modules folder looks like `/lib/modules/6.1.21-v8+/build`, which
means that the previous regex doesn't capture anything after the `-` and
therefore it fails to detect the kernel version.
The regex now aligns with the other detection method and this works fine
on my machine™
2023-06-28 09:23:38 +02:00
Hin-Tak Leung
a03624a0ce v6.3: cleanup Playback/Capture data for snd_soc_dai
commit 3653480c68120dc16ebfeb80e529200dbbd98f92
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Tue Jan 31 02:02:04 2023 +0000

    ASoC: soc-dai.h: cleanup Playback/Capture data for snd_soc_dai

    Current snd_soc_dai has data for Playback/Capture, but it is very
    random. Someone is array (A), someone is playback/capture (B),
    and someone is tx/rx (C);

            struct snd_soc_dai {
                    ...
    (A)             unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1];

    (B)             struct snd_soc_dapm_widget *playback_widget;
    (B)             struct snd_soc_dapm_widget *capture_widget;

    (B)             void *playback_dma_data;
    (B)             void *capture_dma_data;

                    ...

    (C)             unsigned int tx_mask;
    (C)             unsigned int rx_mask;
            };

    Because of it, the code was very complicated.
    This patch creates new data structure to merge these into one,
    and tidyup the code.

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
    Link: https://lore.kernel.org/r/87cz6vea1v.wl-kuninori.morimoto.gx@renesas.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-16 23:49:29 +01:00
Hin-Tak Leung
0bb3ca6c98 v6.3: use simple i2c probe
commit a00f6d3723f5617222ab8df228228c3c2c84e3ec
Author: Stephen Kitt <steve@sk2.org>
Date:   Wed Oct 12 18:36:47 2022 +0200

    drivers/i2c: use simple i2c probe

    All these drivers have an i2c probe function which doesn't use the
    "struct i2c_device_id *id" parameter, so they can trivially be
    converted to the "probe_new" style of probe with a single argument.

    This is part of an ongoing transition to single-argument i2c probe
    functions. Old-style probe functions involve a call to i2c_match_id:
    in drivers/i2c/i2c-core-base.c,

             /*
              * When there are no more users of probe(),
              * rename probe_new to probe.
              */
             if (driver->probe_new)
                     status = driver->probe_new(client);
             else if (driver->probe)
                     status = driver->probe(client,
                                            i2c_match_id(driver->id_table, client));
             else
                     status = -EINVAL;

    Drivers which don't need the second parameter can be declared using
    probe_new instead, avoiding the call to i2c_match_id. Drivers which do
    can still be converted to probe_new-style, calling i2c_match_id
    themselves (as is done currently for of_match_id).

    This change was done using the following Coccinelle script, and fixed
    up for whitespace changes:

    @ rule1 @
    identifier fn;
    identifier client, id;
    @@

    - static int fn(struct i2c_client *client, const struct i2c_device_id *id)
    + static int fn(struct i2c_client *client)
    {
    ...when != id
    }

    @ rule2 depends on rule1 @
    identifier rule1.fn;
    identifier driver;
    @@

    struct i2c_driver driver = {
    -       .probe
    +       .probe_new
                    =
    (
                       fn
    |
    -                  &fn
    +                  fn
    )
                    ,
    };

    Signed-off-by: Stephen Kitt <steve@sk2.org>
    Signed-off-by: Wolfram Sang <wsa@kernel.org>
2023-06-16 23:36:50 +01:00
Hin-Tak Leung
18e297d2d8 64-bit-only kernel package does not have /boot/kernel.img ; use /boot/kernel8.img for version detection.
http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230405-1_arm64.deb
9a716f09695f1e6c9f951a6bc9e4ff22
27025792 Apr  5 20:13

6.1.21-v8+
2023-04-16 19:19:19 +01:00
Hin-Tak Leung
280bb390a2 Remove garbage before "Linux version"
Kernel 6.1 onwards seems to have strings re-arranged so that a newline
no long happens right before the "Linux version" string.

Tested with:

4650945eaabe1297985759ef8e3d4153  archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230306-1_armhf.deb
93830b458685feabf2262f474be4a0e0  archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230317-1_armhf.deb
5449f3dd337c594491f3e73b6ee97cbf  archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230405-1_armhf.deb

29384 5.15.84+
28712 6.1.19+ 6.1.21+
2023-04-16 19:11:24 +01:00
Hin-Tak Leung
19ca5aeb50 64-bit-only kernel package does not have /boot/kernel.img ; use /boot/kernel8.img for version detection.
http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230405-1_arm64.deb
9a716f09695f1e6c9f951a6bc9e4ff22
27025792 Apr  5 20:13

6.1.21-v8+
2023-04-16 18:56:16 +01:00
Hin-Tak Leung
ebd1fa605c Raspbian has 64-bit kernel on 32-bit userspace 2023-04-14 00:09:12 +01:00
Hin-Tak Leung
a57389693c Remove garbage before "Linux version"
Kernel 6.1 onwards seems to have strings re-arranged so that a newline
no long happens right before the "Linux version" string.

Tested with:

4650945eaabe1297985759ef8e3d4153  archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230306-1_armhf.deb
93830b458685feabf2262f474be4a0e0  archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230317-1_armhf.deb
5449f3dd337c594491f3e73b6ee97cbf  archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20230405-1_armhf.deb

29384 5.15.84+
28712 6.1.19+ 6.1.21+
2023-04-10 20:36:18 +01:00
Hin-Tak Leung
977a7ff321 Attempt to fix mis-match to "5.15.84.x 2023-01-23 11:53:49 +00:00
Hin-Tak Leung
4d0e36d426 v6.1: i2c: Make remove callback return void
commit ed5c2f5fd10dda07263f79f338a512c0f49f76f5
Author: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Date:   Mon Aug 15 10:02:30 2022 +0200

    i2c: Make remove callback return void

    The value returned by an i2c driver's remove function is mostly ignored.
    (Only an error message is printed if the value is non-zero that the
    error is ignored.)

    So change the prototype of the remove function to return no value. This
    way driver authors are not tempted to assume that passing an error to
    the upper layer is a good idea. All drivers are adapted accordingly.
    There is no intended change of behaviour, all callbacks were prepared to
    return 0 before.

    Reviewed-by: Peter Senna Tschudin <peter.senna@gmail.com>
    Reviewed-by: Jeremy Kerr <jk@codeconstruct.com.au>
    Reviewed-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
    Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
    Reviewed-by: Crt Mori <cmo@melexis.com>
    Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
    Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Acked-by: Marek Behún <kabel@kernel.org> # for leds-turris-omnia
    Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Reviewed-by: Petr Machata <petrm@nvidia.com> # for mlxsw
    Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com> # for surface3_power
    Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> # for bmc150-accel-i2c + kxcjk-1013
    Reviewed-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> # for media/* + staging/media/*
    Acked-by: Miguel Ojeda <ojeda@kernel.org> # for auxdisplay/ht16k33 + auxdisplay/lcd2s
    Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # for versaclock5
    Reviewed-by: Ajay Gupta <ajayg@nvidia.com> # for ucsi_ccg
    Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # for iio
    Acked-by: Peter Rosin <peda@axentia.se> # for i2c-mux-*, max9860
    Acked-by: Adrien Grassein <adrien.grassein@gmail.com> # for lontium-lt8912b
    Reviewed-by: Jean Delvare <jdelvare@suse.de> # for hwmon, i2c-core and i2c/muxes
    Acked-by: Corey Minyard <cminyard@mvista.com> # for IPMI
    Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
    Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
    Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> # for drivers/power
    Acked-by: Krzysztof Hałasa <khalasa@piap.pl>
    Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
    Signed-off-by: Wolfram Sang <wsa@kernel.org>
2023-01-18 00:14:00 +00:00
Hin-Tak Leung
99bbf880e9 v6.0: ASoC: simple-card-utils: Move snd_soc_component_is_codec to be local
commit 28086d05ada6d03daa886aad0e469854b811311c
Author: Charles Keepax <ckeepax@opensource.cirrus.com>
Date:   Thu May 19 16:43:18 2022 +0100

    ASoC: simple-card-utils: Move snd_soc_component_is_codec to be local

    The helper function snd_soc_component_is_codec is based off the
    presence of the non_legacy_dai_naming flag. This isn't super robust
    as CPU side components may also specify this flag, and indeed the
    kernel already contains a couple that do. After componentisation there
    isn't really a totally robust solution to identifying what is a CODEC
    driver, without introducing a flag specifically for that purpose, and
    really the desirable direction to move in is that the distinction
    doesn't matter.

    This patch does two things to try to mitigate these problems. Firstly,
    now that all the other users of the helper function have been removed,
    it makes the helper function local to the driver rather, than being
    part of the core. This should help to discourage any new code from
    being created that depends on the CODEC driver distinction. Secondly,
    it updates the helper function itself to use the endianness flag
    rather than the non_legacy_dai_naming flag. The endianness flag is
    definitely invalid on a CPU side component, so it a more reliable
    indicator that the device is definitely a CODEC. The vast majority of
    buses require the CODEC to set the endianness flag, so the number of
    corner cases should be fairly minimal. It is worth noting that CODECs
    sending audio over SPI, or built into the CPU CODECs are potential
    corner cases, however the hope is that in most cases those types of
    devices do not consitute a simple audio card.

    Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
    Link: https://lore.kernel.org/r/20220519154318.2153729-57-ckeepax@opensource.cirrus.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2022-10-30 22:45:19 +00:00
Hin-Tak Leung
8dbe3726b7 v6.0: ASoC: simple-card-utils: Make asoc_simple_clean_reference() return void
commit e6f08af6340eaf88e9eeff71bd4533eee9a04119
Author: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Date:   Sun Jun 5 17:35:37 2022 +0200

    ASoC: simple-card-utils: Make asoc_simple_clean_reference() return void

    asoc_simple_clean_reference() returns zero unconditionally. Letting it
    return void instead makes it easier to see in the caller that there is no
    error to handle.

    This is a preparation for making platform remove callbacks return void.

    Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
    Link: https://lore.kernel.org/r/20220605153537.26591-1-u.kleine-koenig@pengutronix.de
    Signed-off-by: Mark Brown <broonie@kernel.org>
2022-10-30 22:37:13 +00:00
Hin-Tak Leung
e452172d8c v6.0: ASoC: wm*: Remove now redundant non_legacy_dai_naming flag
commit 01936221278c5af60d82b8e78ca74caa491c0d31
Author: Charles Keepax <ckeepax@opensource.cirrus.com>
Date:   Thu Jun 23 13:52:50 2022 +0100

    ASoC: soc-component: Remove non_legacy_dai_naming flag

    Now all the users are moved over to the new legacy_dai_naming flag,
    remove the now unused old flag.

    Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
    Link: https://lore.kernel.org/r/20220623125250.2355471-97-ckeepax@opensource.cirrus.com
    Signed-off-by: Mark Brown <broonie@kernel.org>

commit 02004449dbe6ec05b5b64a88824939b8fe474b82
Author: Charles Keepax <ckeepax@opensource.cirrus.com>
Date:   Thu Jun 23 13:52:19 2022 +0100

    ASoC: wm*: Remove now redundant non_legacy_dai_naming flag

    The ASoC core has now been changed to default to the non-legacy DAI
    naming, as such drivers using the new scheme no longer need to specify
    the non_legacy_dai_naming flag.

    Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
    Link: https://lore.kernel.org/r/20220623125250.2355471-66-ckeepax@opensource.cirrus.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2022-10-30 22:29:10 +00:00
Hin-Tak Leung
a8ee041f21 v5.16: ASoC: soc-component: add snd_soc_component_is_codec()
commit 01e90ee15e81f57d309d0ce1f0e16869e011b800
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Oct 18 11:05:24 2021 +0900

    ASoC: soc-component: add snd_soc_component_is_codec()

    Checking .non_legacy_dai_naming is not readable.
    Let's add new snd_soc_component_is_codec().

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Link: https://lore.kernel.org/r/87h7dft7dn.wl-kuninori.morimoto.gx@renesas.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2022-10-30 22:25:19 +00:00
Hin-Tak Leung
6bf1dbd04e v5.13: cope with multi-support at asoc_simple_canonicalize_*()
commit c826ec0391c83f06354a4ebb25c7b2480c18f33a
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Apr 12 08:52:45 2021 +0900

    ASoC: simple-card-utils: multi support at asoc_simple_canonicalize_cpu/platform()

    Current asoc_simple_canonicalize_cpu/platform() is assuming single CPU,
    single Platform, but we want to support Multi support.
    This patch is prepare for it.
2021-10-09 00:55:55 +01:00
Hin-Tak Leung
b093f59250 v5.13: Conditionally re-adding asoc_simple_parse_xxx()
commit e25704f84ca2b586e8e65d1b2ab686205b3076fe
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Apr 12 08:52:13 2021 +0900

    ASoC: simple-card-utils: remove asoc_simple_parse_xxx()

    ASoC is now supporting multi DAI, but, current
    simple-card / audio-graph are assuming fixed single DAI.

    Now, asoc_simple_parse_xxx() macro is assuming single DAI.
    To support multi-CPU/Codec, this patch unpack asoc_simple_parse_xxx()
    macro, and uses "&dai_link->cpus[i]" instead of "dai_link->cpus".

$ git log --format=oneline v5.12..v5.13 -- include/sound/simple_card_utils.h
f6fcc820e0c96664e2f21c0d6bb60630243ef36a ASoC: audio-graph: move audio_graph_remove() to simple-card-utils.c
1a456b1c6be13514a8fc5c1a99e6763f491d17e9 ASoC: audio-graph: move audio_graph_card_probe() to simple-card-utils.c
343e55e71877415a23372388b3e0c59a9bba42f6 ASoC: simple-card-utils: Increase maximum number of links to 128
fcfd763bef4ff7f6371790979a6ceac9c4ac425a ASoC: simple-card-utils: tidyup asoc_simple_parse_convert()
3919249e80995ed5f125f94d05fcb6171f79e732 ASoC: simple-card-utils: tidyup dev_dbg() to use 1 line
33cd6b191f1cdb5f332717a80ce26f661f53e924 ASoC: simple-card-utils: tidyup debug info for clock
c826ec0391c83f06354a4ebb25c7b2480c18f33a ASoC: simple-card-utils: multi support at asoc_simple_canonicalize_cpu/platform()
9830d3e99f51fc1c1c6ab8be7778fd205af198ad ASoC: simple-card-utils: add simple_props_to_xxx() macro
40d8cbe70e71be170e0a4fe6ab112d9aaa9cfb18 ASoC: simple-card-utils: indicate missing CPU/Codec numbers for debug
ac813c625ad5c3ee98a99e1b37659a0d85178978 ASoC: simple-card-utils: indicate dai_fmt if exist
e25704f84ca2b586e8e65d1b2ab686205b3076fe ASoC: simple-card-utils: remove asoc_simple_parse_xxx()
fafc05aadd4b6ce5c161135de9d3a653fc054543 ASoC: simple-card-utils: use for_each_prop_xxx()
f899006d558546a8ee39c93f816eb3847c5bc6c0 ASoC: simple-card-utils: remove li->dais/li->conf
205eb17eddb473c3159743c7d3aaf68db37b7231 ASoC: simple-card-utils: share dummy DAI and reduce memory
f2138aed231c88d5c4fa8d06aa15ad19685087c2 ASoC: simple-card-utils: enable flexible CPU/Codec/Platform
050c7950fd706fec229af9f30e8ce254cea9b675 ASoC: simple-card-utils: alloc dai_link information for CPU/Codec/Platform
2021-10-09 00:45:09 +01:00
Hin-Tak Leung
8fa56e18bb Merge remote-tracking branch 'upstream/master' into v5.9
Not really a merge.
2021-09-16 23:57:03 +01:00
AIWintermuteAI
dd9391fb78 added 64-bit system installation script 2021-08-20 07:23:35 +01:00
AIWintermuteAI
d840f77541
Update install.sh 2021-08-19 09:56:53 +08:00
AIWintermuteAI
bd7623e9fb added reboot warning if active kernel version doesn't match updated kernel version 2021-08-17 03:28:54 +01:00
Baozhu Zuo
17e2875d4d
delete snd-soc-wm8960.ko first
see 14075fb3b5
2021-08-16 11:22:46 +08:00
Hin-Tak Leung
b595b95b21 Revert "libasound_module_pcm_ac108.so is no longer installed, so libasound2-plugins shouldn't be needed"
This reverts commit 8b2094fc23.

See #304 regarding missing libasound2-plugins.
2021-08-05 13:48:14 +08:00
Hin-Tak Leung
48dbb3f815 Revert "libasound_module_pcm_ac108.so is no longer installed, so libasound2-plugins shouldn't be needed"
This reverts commit 8b2094fc23.

See #304 regarding /usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_rate_samplerate.so
2021-08-04 12:00:51 +01:00
AIWintermuteAI
41a09a3b67 added issue template 2021-07-22 18:37:38 +08:00
AIWintermuteAI
81e0f0879d
automation 2021-07-21 15:21:38 +08:00
HinTak
d841b2a0fb
Merge branch 'respeaker:master' into v5.9 2021-07-04 16:42:56 +01:00
Hin-Tak Leung
f9427ea449 remove reference to removed option "--compat-kernel" 2021-07-03 07:54:34 +01:00
AIWintermuteAI
efa999f0f3 added image and information about tech support scope 2021-06-30 03:35:28 +01:00
AIWintermuteAI
d688a02f14 simplified and updated README after merge 2021-06-29 06:51:27 +01:00
Hin-Tak Leung
a1a51f8aab v5.12: symmetric_rates renamed symmetric_rate
commit fa31a2c787aeaf61d02b2a57bd9765ca5e67d949
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri Jan 15 13:56:30 2021 +0900

    ASoC: soc-dai.h: remove symmetric_rates/samplebits

    All drivers are using new name.
    Let's remove old one.

commit f14654ddf2e982537ab476d392a87fcbf90374c3
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri Jan 15 13:52:54 2021 +0900

    ASoC: sync parameter naming : rate / sample_bits

    snd_pcm_runtime / snd_soc_dai / snd_soc_dai_driver / snd_soc_dai_link
    have related parameter which is similar but not same naming.
2021-05-31 19:17:06 +01:00
pcmulder
31d750c981 Added g++ to ubuntu-prerequisite.sh
On a fresh install I was missing g++ to run the buildme part. I propose we add it for future users.
2021-05-27 22:05:01 +01:00
Hin-Tak Leung
c8d97904ce adjusting back-to-v4.19.diff to recent changes 2021-04-27 15:57:01 +01:00
Hin-Tak Leung
c5f3836dd8 missed one simple_priv_to_card() to seeed_priv_to_card() earlier 2021-04-27 15:48:33 +01:00
Hin-Tak Leung
19067f3333 Second/Alternative change to correct for 5.5+ change in trigger order
The idea is the same as the previous attempt: calls ac101_trigger() just
before set_clock(1).

https://github.com/respeaker/seeed-voicecard/issues/290
    6mics / linear 4 mics: fails to record against v5.10 kernel
https://github.com/raspberrypi/linux/issues/4279
    [regression] alsa system call blocks on record between 5.4.83 and 5.5.19

In v5.5,

commit 4378f1fbe924054a09ff0d4e39e1a581b9245252
Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date:   Fri Sep 27 10:16:46 2019 +0300

    ASoC: soc-pcm: Use different sequence for start/stop trigger

    On stream stop currently we stop the DMA first followed by the CPU DAI.
    This can cause underflow (playback) or overflow (capture) on the DAI side
    as the DMA is no longer feeding data while the DAI is still active.
    It can be observed easily if the DAI side does not have FIFO (or it is
    disabled) to survive the time while the DMA is stopped, but still can
    happen on relatively slow CPUs when relatively high sampling rate is used:
    the FIFO is drained between the time the DMA is stopped and the DAI is
    stopped.

    It can only fixed by using different sequence within trigger for 'stop' and
    'start':
    case SNDRV_PCM_TRIGGER_START:
    case SNDRV_PCM_TRIGGER_RESUME:
    case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
            Trigger order: dai_link, DMA, CPU DAI then the codec

    case SNDRV_PCM_TRIGGER_STOP:
    case SNDRV_PCM_TRIGGER_SUSPEND:
    case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
            Trigger order: codec, CPU DAI, DMA then dai_link

    Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
    Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
    Link: https://lore.kernel.org/r/20190927071646.22319-1-peter.ujfalusi@ti.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2021-04-27 02:49:25 +01:00
Hin-Tak Leung
5793cf6bf0 Revert "Operational change to correct for 5.5+ change in trigger order; REVISIT!"
This reverts commit e553d4f851.
2021-04-27 02:49:08 +01:00
Hin-Tak Leung
ffcdafb798 adjust back-to-v5.4.diff for recent code changes 2021-04-25 00:13:42 +01:00
Hin-Tak Leung
e553d4f851 Operational change to correct for 5.5+ change in trigger order; REVISIT!
Need to revisit, and do in a different way.

https://github.com/respeaker/seeed-voicecard/issues/290
    6mics / linear 4 mics: fails to record against v5.10 kernel
https://github.com/raspberrypi/linux/issues/4279
    [regression] alsa system call blocks on record between 5.4.83 and 5.5.19

In v5.5,

commit 4378f1fbe924054a09ff0d4e39e1a581b9245252
Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date:   Fri Sep 27 10:16:46 2019 +0300

    ASoC: soc-pcm: Use different sequence for start/stop trigger

    On stream stop currently we stop the DMA first followed by the CPU DAI.
    This can cause underflow (playback) or overflow (capture) on the DAI side
    as the DMA is no longer feeding data while the DAI is still active.
    It can be observed easily if the DAI side does not have FIFO (or it is
    disabled) to survive the time while the DMA is stopped, but still can
    happen on relatively slow CPUs when relatively high sampling rate is used:
    the FIFO is drained between the time the DMA is stopped and the DAI is
    stopped.

    It can only fixed by using different sequence within trigger for 'stop' and
    'start':
    case SNDRV_PCM_TRIGGER_START:
    case SNDRV_PCM_TRIGGER_RESUME:
    case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
            Trigger order: dai_link, DMA, CPU DAI then the codec

    case SNDRV_PCM_TRIGGER_STOP:
    case SNDRV_PCM_TRIGGER_SUSPEND:
    case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
            Trigger order: codec, CPU DAI, DMA then dai_link

    Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
    Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
    Link: https://lore.kernel.org/r/20190927071646.22319-1-peter.ujfalusi@ti.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
2021-04-25 00:13:42 +01:00
Hin-Tak Leung
de70691526 v5.7: this code was added with 5.7 - "for_each_rtd_components"
The correct incantation is:

git log 95cfc0a0aaf575207152dd7601e782702565a6f1 ^v5.7
2021-04-25 00:13:42 +01:00
Hin-Tak Leung
1774a54301 Additional debug code to where the *_trigger()'s finish. 2021-04-25 00:13:42 +01:00
Hin-Tak Leung
af484de3af v4.17: replace codec to component
https://www.alsa-project.org/pipermail/alsa-devel/2018-January/thread.html#131069

https://www.alsa-project.org/pipermail/alsa-devel/2018-January/131070.html
[alsa-devel] [PATCH v2 00/39] ASoC: replace platform/codec component   Kuninori Morimoto

https://www.alsa-project.org/pipermail/alsa-devel/2018-January/131111.html
[alsa-devel] [PATCH v2 000/186] ASoC: replace codec component   Kuninori Morimoto
2021-04-25 00:13:42 +01:00
Hin-Tak Leung
9796ad49ff Additional debug statement 2021-04-25 00:13:42 +01:00
Hin-Tak Leung
43b6034266 Breaking the spinlock into two halves, and possible fix to spinlock issue 2021-04-25 00:13:42 +01:00
Hin-Tak Leung
eab694c170 Not writing dtoverlay=seeed-*mic-voicecard to /boot/config.txt
It is easier for debugging, and easier for switching cards around, too.
2021-04-25 00:13:42 +01:00
Hin-Tak Leung
fdd67ea2c4 Move call to asoc_simple_canonicalize_platform() later to match upstream - likely does not matter.
commit fe7ed4dec2e6289eab81dd18c0d613c0851d85a1
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Jan 21 16:40:59 2019 +0900

    ASoC: simple-card: rename to asoc_simple_card_canonicalize_platform()

    Current simple-card is using asoc_simple_card_canonicalize_dailink().
    Its naming is "dailink", but is for "platform".
    We already have asoc_simple_card_canonicalize_cpu() for "cpu",
    let's follow same naming rule.
    It never return error, so, void function is better idea.

    Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Signed-off-by: Mark Brown <broonie@kernel.org>
2021-04-25 00:13:28 +01:00
Hin-Tak Leung
f8d47b5c64 2nd parameter of asoc_simple_init_dai_link_params() not used 2021-04-24 20:50:05 +01:00
Hin-Tak Leung
47d09dba0e v5.6: codec2codec DAI links
commit 95cfc0a0aaf575207152dd7601e782702565a6f1
Author: Samuel Holland <samuel@sholland.org>
Date:   Wed Mar 4 23:11:43 2020 -0600

    ASoC: simple-card: Add support for codec2codec DAI links

    Following the example in cb2cf0de1174 ("ASoC: soc-core: care Codec <->
    Codec case by non_legacy_dai_naming"), determine if a DAI link contains
    only codec DAIs by examining the non_legacy_dai_naming flag in each
    DAI's component.

    For now, we assume there is only one or a small set of valid PCM stream
    parameters, so num_params == 1 is good enough. We also assume that the
    same params are valid for all supported streams. params is set to the
    subset of parameters common among all DAIs, and then the existing code
    automatically chooses the highest quality of the remaining values when
    the link is brought up.
2021-04-24 20:49:53 +01:00
Hin-Tak Leung
d692927067 adjust asoc_simple_debug_info() for seeed priv structures 2021-04-24 20:49:36 +01:00
Hin-Tak Leung
14317817f8 v5.1 "ASoC: simple-card-utils: add asoc_simple_debug_info()"
commit 0580dde59438686d60762b6da9229ebec693b94f
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:54:42 2019 +0900

    ASoC: simple-card-utils: add asoc_simple_debug_info()

    Current simple-card-utils has dev_dbg(), but people want to
    add #define DEBUG at simple-card/audio-graph, not simple-card-utils.
    And, people want to get all information.
    This patch adds new asoc_simple_debug_info() to indicates information.
2021-04-24 20:49:19 +01:00
Hin-Tak Leung
3ba6aec5bb adjust v4.19 backport patch to "fix silly mistake in "v5.8: ..."" 2021-04-11 22:59:11 +01:00
Hin-Tak Leung
8b2094fc23 libasound_module_pcm_ac108.so is no longer installed, so libasound2-plugins shouldn't be needed 2021-04-08 21:07:35 +01:00
Hin-Tak Leung
c84b644247 adjust v5.4 backport patch to "fix silly mistake in "v5.8: ..."" 2021-04-08 18:07:20 +01:00
Hin-Tak Leung
8e1c59be7e fix silly mistake in "v5.8: struct snd_soc_dai->active replaced by snd_soc_dai_active(snd_soc_dai)" 2021-04-08 04:01:13 +01:00
Hin-Tak Leung
f289f5586e backport patch for 5.8 2021-04-07 21:48:15 +01:00
Hin-Tak Leung
3ad10c131c remove non-coding changes in back-to-v4.19.diff 2021-04-01 00:48:07 +01:00
Hin-Tak Leung
cbb5e082f2 hook up backport patches with dkms 2021-04-01 00:41:04 +01:00
Hin-Tak Leung
43532cfada rename to v5.4, since 5.4 is LTS 2021-04-01 00:40:13 +01:00
Hin-Tak Leung
eea6066d70 generating backport-patch with "git diff origin/v5.9..origin/v4.19" 2021-04-01 00:31:04 +01:00
Hin-Tak Leung
44d47226dc generating backport-patch with "git diff origin/v5.9..origin/v5.5" 2021-04-01 00:30:34 +01:00
Hin-Tak Leung
50dbe24b78 v5.9: snd_soc_component_read32() merged into snd_soc_component_read()
commit 39853b1438bf9b07349c8c44b48f6c2eda6f8840
Merge: d6fea46e086b 5b554b0a29ce
Author: Mark Brown <broonie@kernel.org>
Date:   Mon Jun 22 15:36:06 2020 +0100

    Merge series "ASoC: merge snd_soc_component_read() and snd_soc_component_read32()" from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

$ git diff d6fea46e086b...5b554b0a29ce

commit 5b554b0a29ce9610e3c237c77a1f76db87454b72
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Tue Jun 16 14:21:55 2020 +0900

    ASoC: remove snd_soc_component_read32()

    No driver is using snd_soc_component_read32() anymore.
    This patch removes it.
2020-11-27 00:12:31 +00:00
Hin-Tak Leung
ebcf755c1a v5.9: .digital_mute merged into .mute_stream with adjustments
Reference:

commit e2978c45e5ed3bab7f69477b882ef588185b30cc
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri Jul 17 09:21:54 2020 +0900

    ASoC: soc-dai: remove .digital_mute

    All drivers are now using .mute_stream.
    Let's remove .digital_mute.

commit 22e9b54307987787efa0ee534aa9e31982ec1161
Merge: dc9584c5a3b8 a0234d0e6014
Author: Mark Brown <broonie@kernel.org>
Date:   Fri Jul 17 14:47:04 2020 +0100

    Merge series "ASoC: merge .digital_mute() into .mute_stream()" from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

    These are v4 digital_mute() patch which adjusts
    to atmel which had conflict on v3.

    v3 -> v4
            - tidyup for atmel which had conflict

$ git diff dc9584c5a3b8...a0234d0e6014

commit bdd0c277d9846977ec3f175341d4e7475ed26ef7
Merge: d235b2823698 50891431aaad
Author: Mark Brown <broonie@kernel.org>
Date:   Thu Jul 16 23:51:51 2020 +0100

    Merge series "ASoC: merge .digital_mute() into .mute_stream()" from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

    These are v3 patch-set.
    ALSA SoC has 2 mute callbacks (= .digital_mute(), .mute_stream()).
    But the difference between these 2 are very small.
            .digital_mute() is for Playback
            .mute_stream()  is for Playback/Capture

    This patch-set adds new .no_capture_mute flag and emulate
    .digital_mute() by .mute_stream().

    v2 -> v3
            - uses "xxx_mute_stream" for .mute_stream naming
              if it was better
            - removed verbose Cc email address

$ git diff d235b2823698...50891431aaad

commit 350d993510115e3d9e78f1b3359bff7b68e88418
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Thu Jul 9 10:55:41 2020 +0900

    ASoC: soc-dai.c: add .no_capture_mute support
2020-11-27 00:07:47 +00:00
15 changed files with 1060 additions and 314 deletions

259
README.md
View file

@ -1,247 +1,20 @@
# seeed-voicecard # seeed-voicecard
[![Join the chat at https://gitter.im/seeed-voicecard/Lobby](https://badges.gitter.im/seeed-voicecard/Lobby.svg)](https://gitter.im/seeed-voicecard/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) The drivers for [ReSpeaker Mic Hat](https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT-p-2874.html), [ReSpeaker 4 Mic Array](https://www.seeedstudio.com/ReSpeaker-4-Mic-Array-for-Raspberry-Pi-p-2941.html), [6-Mics Circular Array Kit](), and [4-Mics Linear Array Kit]() for Raspberry Pi.
The drivers of [ReSpeaker Mic Hat](https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT-p-2874.html),[ReSpeaker 4 Mic Array](https://www.seeedstudio.com/ReSpeaker-4-Mic-Array-for-Raspberry-Pi-p-2941.html),[6-Mics Circular Array Kit](), and [4-Mics Linear Array Kit]() for Raspberry Pi.
### Install seeed-voicecard ### Install seeed-voicecard
Get the seeed voice card source code. and install all linux kernel drivers Get the seeed voice card source code and install all linux kernel drivers
```bash ```bash
git clone https://github.com/respeaker/seeed-voicecard git clone https://github.com/HinTak/seeed-voicecard
cd seeed-voicecard cd seeed-voicecard
sudo ./install.sh sudo ./install.sh
sudo reboot sudo reboot
``` ```
It may probably happen that the driver won't compile with the latest kernel when raspbian rolls out new patches to the kernel. If so, please try `sudo ./install.sh --compat-kernel` which uses an older kernel but ensures that the driver can work. ## ReSpeaker Documentation
## ReSpeaker Mic Hat Up to date documentation for reSpeaker products can be found in [Seeed Studio Wiki](https://wiki.seeedstudio.com/ReSpeaker/)!
![](https://files.seeedstudio.com/wiki/ReSpeakerProductGuide/img/Raspberry_Pi_Mic_Array_Solutions.png)
[![](https://github.com/SeeedDocument/MIC_HATv1.0_for_raspberrypi/blob/master/img/mic_hatv1.0.png?raw=true)](https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT-p-2874.html)
While the upstream wm8960 codec is not currently supported by current Pi kernel builds, upstream wm8960 has some bugs, we had fixed it. we must it build manually.
Check that the sound card name matches the source code seeed-voicecard.
```bash
#for ReSpeaker 2-mic
pi@raspberrypi:~/seeed-voicecard $ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
Subdevices: 8/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
card 0: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: seeed2micvoicec [seeed-2mic-voicecard], device 0: bcm2835-i2s-wm8960-hifi wm8960-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
pi@raspberrypi:~/seeed-voicecard $ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: seeed2micvoicec [seeed-2mic-voicecard], device 0: bcm2835-i2s-wm8960-hifi wm8960-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
pi@raspberrypi:~/seeed-voicecard $
```
If you want to change the alsa settings, You can use `sudo alsactl --file=/etc/voicecard/wm8960_asound.state store` to save it.
#### Next step
Go to https://github.com/respeaker/mic_hat to build voice enabled projects with Google Assistant SDK or Alexa Voice Service.
## ReSpeaker 4 Mic Array
[![](https://github.com/SeeedDocument/ReSpeaker-4-Mic-Array-for-Raspberry-Pi/blob/master/img/features.png?raw=true)](https://www.seeedstudio.com/ReSpeaker-4-Mic-Array-for-Raspberry-Pi-p-2941.html)
The 4 Mic Array uses ac108 which includes 4 ADCs, we also write ac108 rapberry pi linux kernel driver.
Check that the sound card name matches the source code seeed-voicecard.
```bash
#for ReSpeaker 4 Mic Array
pi@raspberrypi:~ $ arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
playback
capture
dmixed
array
ac108
default:CARD=seeed4micvoicec
seeed-4mic-voicecard,
Default Audio Device
sysdefault:CARD=seeed4micvoicec
seeed-4mic-voicecard,
Default Audio Device
dmix:CARD=seeed4micvoicec,DEV=0
seeed-4mic-voicecard,
Direct sample mixing device
dsnoop:CARD=seeed4micvoicec,DEV=0
seeed-4mic-voicecard,
Direct sample snooping device
hw:CARD=seeed4micvoicec,DEV=0
seeed-4mic-voicecard,
Direct hardware device without any conversions
plughw:CARD=seeed4micvoicec,DEV=0
seeed-4mic-voicecard,
Hardware device with all software conversions
pi@raspberrypi:~ $
```
If you want to change the alsa settings, You can use `sudo alsactl --file=/etc/voicecard/ac108_asound.state store` to save it.
## 6-Mics Circular Array Kit
[![](https://user-images.githubusercontent.com/3901856/37268348-6adef768-2600-11e8-8861-588b1c3ea142.png)]()
The 6 Mics Circular Array Kit uses ac108 x 2 / ac101 x 1 / micphones x 6, includes 8 ADCs and 2 DACs.
The driver is implemented with 8 input channels & 8 output channels.
>**The first 6 input channel are MIC recording data,
the rest 2 input channel are echo channel of playback
The first 2 output channel are playing data, the rest 6 output channel are dummy**
Check that the sound card name matches the source code seeed-voicecard.
```bash
#for 6 Mic Circular Array
pi@raspberrypi:~ $ arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
default
playback
dmixed
ac108
multiapps
ac101
sysdefault:CARD=seeed8micvoicec
seeed-8mic-voicecard,
Default Audio Device
dmix:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Direct sample mixing device
dsnoop:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Direct sample snooping device
hw:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Direct hardware device without any conversions
plughw:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Hardware device with all software conversions
pi@raspberrypi:~ $ aplay -L
null
Discard all samples (playback) or generate zero samples (capture)
default
playback
dmixed
ac108
multiapps
ac101
sysdefault:CARD=ALSA
bcm2835 ALSA, bcm2835 ALSA
Default Audio Device
dmix:CARD=ALSA,DEV=0
bcm2835 ALSA, bcm2835 ALSA
Direct sample mixing device
dmix:CARD=ALSA,DEV=1
bcm2835 ALSA, bcm2835 IEC958/HDMI
Direct sample mixing device
dsnoop:CARD=ALSA,DEV=0
bcm2835 ALSA, bcm2835 ALSA
Direct sample snooping device
dsnoop:CARD=ALSA,DEV=1
bcm2835 ALSA, bcm2835 IEC958/HDMI
Direct sample snooping device
hw:CARD=ALSA,DEV=0
bcm2835 ALSA, bcm2835 ALSA
Direct hardware device without any conversions
hw:CARD=ALSA,DEV=1
bcm2835 ALSA, bcm2835 IEC958/HDMI
Direct hardware device without any conversions
plughw:CARD=ALSA,DEV=0
bcm2835 ALSA, bcm2835 ALSA
Hardware device with all software conversions
plughw:CARD=ALSA,DEV=1
bcm2835 ALSA, bcm2835 IEC958/HDMI
Hardware device with all software conversions
sysdefault:CARD=seeed8micvoicec
seeed-8mic-voicecard,
Default Audio Device
dmix:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Direct sample mixing device
dsnoop:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Direct sample snooping device
hw:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Direct hardware device without any conversions
plughw:CARD=seeed8micvoicec,DEV=0
seeed-8mic-voicecard,
Hardware device with all software conversions
```
## 4-Mics Linear Array Kit
[![](https://user-images.githubusercontent.com/3901856/37194106-a0ccebce-23a7-11e8-88c5-ec611e44ec49.png)]()
In contrast to 6-Mics Circular Array Kit for Raspberry Pi,
the difference is only first 4 input channels are valid capture data.
### Usage:
```bash
#Query sound card number
# The sound card number used as arecord/aplay argument,
# ( like '-D hw:N' and '-D plughw:N', where N is the number )
# could be found by command:
aplay -l
#or
arecord -l
# Find the line in the command output which near below form:
card 1: seeed2micvoicec [seeed-2mic-voicecard], device 0: ...
# The number between first word `card` and char `:` is the Sound Card Number, here it's 1.
```
```bash
#for ReSpeaker 2-mic
#It will capture sound an playback on hw:1
arecord -f cd -Dhw:1 | aplay -Dhw:1
```
```bash
#for ReSpeaker 4-mic
#It will capture sound on AC108 and save as a.wav
arecord -Dac108 -f S32_LE -r 16000 -c 4 a.wav
```
```bash
#for 6-Mics Circular Array Kit and 4-Mics Linear Array Kit
#It will capture sound on AC108 and save as a.wav
arecord -Dac108 -f S32_LE -r 16000 -c 8 a.wav
#Take care of that the captured mic audio is on the first 6 channels
#It will play a mono channel sound file mono_to_play.wav
#The file to play must be mono channel or else the speaker output nothing.
aplay -D plughw:1,0 mono_to_play.wav
#Doing capture && playback the same time
arecord -D hw:1,0 -f S32_LE -r 16000 -c 8 to_be_record.wav &
#mono_to_play.wav is a mono channel wave file to play
aplay -D plughw:1,0 -r 16000 mono_to_play.wav
```
**Note: Limit for developer using 6-Mics Circular Array Kit(or 4-Mics Linear Array Kit) doing capture & playback the same time:
1. capture must be start first, or else the capture channels will possibly be disorder.
2. playback output channels must fill with 8 same channels data or 4 same stereo channels data, or else the speaker or headphone will output nothing possibly.**
### Coherence ### Coherence
@ -271,13 +44,21 @@ Thank you!
------------------------------------------------------ ------------------------------------------------------
``` ```
Enjoy ! Enjoy !
### FAQ ### Technical support
For hardware testing purposes we made a Rasperry Pi OS 5.10.17-v7l+ 32-bit image with reSpeaker drivers pre-installed, which you can download by clicking on [this link](https://files.seeedstudio.com/linux/Raspberry%20Pi%204%20reSpeaker/2021-05-07-raspios-buster-armhf-lite-respeaker.img.xz).
We provide official support for using reSpeaker with the following OS:
- 32-bit Raspberry Pi OS
- 64-bit Raspberry Pi OS
And following hardware platforms:
- Raspberry Pi 3 (all models), Raspberry Pi 4 (all models)
Anything beyond the scope of official support is considered to be community supported. Support for other OS/hardware platforms can be added, provided MOQ requirements can be met.
If you have a technical problem when using reSpeaker with one of the officially supported platforms/OS, feel free to create an issue on Github. For general questions or suggestions, please use [Seeed forum](https://forum.seeedstudio.com/c/products/respeaker/15).
When you encounter any installation and use problems when you start your ReSpeaker Pi hat, please use the following image for testing. We have installed seeed-voicecard based on the latest PI image, which can be used by burning it directly on SD. If this still cannot solve your problem, you can ask in the issue. We will try our best to solve your problem.
<p style="text-align:center"><a href="https://v2.fangcloud.com/share/7395fd138a1cab496fd4792fe5" target="_blank"><img src="https://github.com/SeeedDocument/Respeaker_V2/raw/master/img/efangyun.png" width="200" height="40" border=0 /></a></p>

16
ac101.c
View file

@ -955,10 +955,10 @@ void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai
AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n", AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n",
snd_pcm_stream_str(substream), snd_pcm_stream_str(substream),
codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE], codec_dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, codec_dai->stream[SNDRV_PCM_STREAM_CAPTURE].active,
snd_soc_dai_active(codec_dai)); snd_soc_dai_active(codec_dai));
if (snd_soc_dai_active(codec_dai)) { if (!snd_soc_dai_active(codec_dai)) {
ac10x->aif1_clken = 1; ac10x->aif1_clken = 1;
ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0); ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
} else { } else {
@ -1080,7 +1080,7 @@ int ac101_hw_params(struct snd_pcm_substream *substream,
freq_out = _FREQ_24_576K; freq_out = _FREQ_24_576K;
for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) { for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
if (codec_aif1_fs[i].samp_rate == params_rate(params)) { if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
if (codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && dmic_used && codec_aif1_fs[i].samp_rate == 44100) { if (codec_dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), (0x4<<AIF1_FS)); ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), (0x4<<AIF1_FS));
} else { } else {
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS)); ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS));
@ -1237,7 +1237,7 @@ int ac101_audio_startup(struct snd_pcm_substream *substream,
} }
#if _MASTER_MULTI_CODEC == _MASTER_AC101 #if _MASTER_MULTI_CODEC == _MASTER_AC101
static int ac101_set_clock(int y_start_n_stop) { static int ac101_set_clock(int y_start_n_stop, struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) {
int r; int r;
if (y_start_n_stop) { if (y_start_n_stop) {
@ -1258,6 +1258,7 @@ int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec); struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
int ret = 0; int ret = 0;
unsigned long flags;
AC101_DBG("stream=%s cmd=%d\n", AC101_DBG("stream=%s cmd=%d\n",
snd_pcm_stream_str(substream), snd_pcm_stream_str(substream),
@ -1268,6 +1269,7 @@ int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
#if _MASTER_MULTI_CODEC == _MASTER_AC101 #if _MASTER_MULTI_CODEC == _MASTER_AC101
spin_lock_irqsave(&ac10x->lock, flags);
if (ac10x->aif1_clken == 0){ if (ac10x->aif1_clken == 0){
/* /*
* enable aif1clk, it' here due to reduce time between 'AC108 Sysclk Enable' and 'AC101 Sysclk Enable' * enable aif1clk, it' here due to reduce time between 'AC108 Sysclk Enable' and 'AC101 Sysclk Enable'
@ -1277,15 +1279,21 @@ int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
ret = ret || ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_AIF1), (0x1<<MOD_CLK_AIF1)); ret = ret || ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_AIF1), (0x1<<MOD_CLK_AIF1));
ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1), (0x1<<MOD_RESET_AIF1)); ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1), (0x1<<MOD_RESET_AIF1));
} }
spin_unlock_irqrestore(&ac10x->lock, flags);
ac101_set_clock(1, substream, cmd, dai);
#endif #endif
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ac101_set_clock(0, NULL, 0, NULL);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
} }
AC101_DBG("stream=%s cmd=%d;finished %d\n",
snd_pcm_stream_str(substream),
cmd, ret);
return ret; return ret;
} }

68
ac108.c
View file

@ -653,7 +653,7 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__, dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__,
snd_pcm_stream_str(substream), snd_pcm_stream_str(substream),
dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]); dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
if (ac10x->i2c101) { if (ac10x->i2c101) {
ret = ac101_hw_params(substream, params, dai); ret = ac101_hw_params(substream, params, dai);
@ -664,8 +664,8 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
} }
} }
if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]) if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active)
|| (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream_active[SNDRV_PCM_STREAM_CAPTURE])) { || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream[SNDRV_PCM_STREAM_CAPTURE].active)) {
/* not configure hw_param twice */ /* not configure hw_param twice */
/* return 0; */ /* return 0; */
} }
@ -991,7 +991,7 @@ static int ac108_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) {
/* /*
* due to miss channels order in cpu_dai, we meed defer the clock starting. * due to miss channels order in cpu_dai, we meed defer the clock starting.
*/ */
static int ac108_set_clock(int y_start_n_stop) { static int ac108_set_clock(int y_start_n_stop, struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) {
u8 reg; u8 reg;
int ret = 0; int ret = 0;
@ -999,6 +999,9 @@ static int ac108_set_clock(int y_start_n_stop) {
/* spin_lock move to machine trigger */ /* spin_lock move to machine trigger */
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
ac101_trigger(substream, cmd, dai);
}
if (y_start_n_stop && ac10x->sysclk_en == 0) { if (y_start_n_stop && ac10x->sysclk_en == 0) {
/* enable lrck clock */ /* enable lrck clock */
ac10x_read(I2S_CTRL, &reg, ac10x->i2cmap[_MASTER_INDEX]); ac10x_read(I2S_CTRL, &reg, ac10x->i2cmap[_MASTER_INDEX]);
@ -1058,39 +1061,33 @@ static int ac108_trigger(struct snd_pcm_substream *substream, int cmd,
snd_pcm_stream_str(substream), snd_pcm_stream_str(substream),
cmd); cmd);
spin_lock_irqsave(&ac10x->lock, flags);
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
ac101_trigger(substream, cmd, dai);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
goto __ret;
}
}
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
spin_lock_irqsave(&ac10x->lock, flags);
/* disable global clock if lrck disabled */ /* disable global clock if lrck disabled */
ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]); ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
if ((r & (0x01 << BCLK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) { if ((r & (0x01 << BCLK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) {
/* disable global clock */ /* disable global clock */
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x0 << TXEN | 0x0 << GEN, ac10x); ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x0 << TXEN | 0x0 << GEN, ac10x);
} }
spin_unlock_irqrestore(&ac10x->lock, flags);
/* delayed clock starting, move to machine trigger() */ ac108_set_clock(1, substream, cmd, dai);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ac108_set_clock(0, substream, cmd, dai);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
} }
__ret: dev_dbg(dai->dev, "%s() stream=%s cmd=%d; finished %d\n",
spin_unlock_irqrestore(&ac10x->lock, flags); __FUNCTION__,
snd_pcm_stream_str(substream),
cmd, ret);
return ret; return ret;
} }
@ -1124,7 +1121,7 @@ void ac108_aif_shutdown(struct snd_pcm_substream *substream,
} }
} }
int ac108_aif_mute(struct snd_soc_dai *dai, int mute) { int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int direction) {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec); struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
@ -1145,12 +1142,13 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
.hw_params = ac108_hw_params, .hw_params = ac108_hw_params,
.prepare = ac108_prepare, .prepare = ac108_prepare,
.trigger = ac108_trigger, .trigger = ac108_trigger,
.digital_mute = ac108_aif_mute, .mute_stream = ac108_aif_mute,
/*DAI format configuration*/ /*DAI format configuration*/
.set_fmt = ac108_set_fmt, .set_fmt = ac108_set_fmt,
// .hw_free = ac108_hw_free, // .hw_free = ac108_hw_free,
.no_capture_mute = 1,
}; };
static struct snd_soc_dai_driver ac108_dai0 = { static struct snd_soc_dai_driver ac108_dai0 = {
@ -1324,6 +1322,11 @@ static struct snd_soc_codec_driver ac10x_soc_codec_driver = {
.set_bias_level = ac108_set_bias_level, .set_bias_level = ac108_set_bias_level,
.read = ac108_codec_read, .read = ac108_codec_read,
.write = ac108_codec_write, .write = ac108_codec_write,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
#endif
}; };
static ssize_t ac108_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { static ssize_t ac108_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
@ -1404,7 +1407,15 @@ static const struct regmap_config ac108_regmap = {
.max_register = 0xDF, .max_register = 0xDF,
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
static int ac108_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) { static const struct i2c_device_id ac108_i2c_id[] = {
{ "ac108_0", 0 },
{ "ac108_1", 1 },
{ "ac108_2", 2 },
{ "ac108_3", 3 },
{ "ac101", AC101_I2C_ID },
{ }
};
static int ac108_i2c_probe(struct i2c_client *i2c) {
struct device_node *np = i2c->dev.of_node; struct device_node *np = i2c->dev.of_node;
unsigned int val = 0; unsigned int val = 0;
int ret = 0, index; int ret = 0, index;
@ -1417,11 +1428,11 @@ static int ac108_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *i
} }
} }
index = (int)i2c_id->driver_data; index = (int)i2c_match_id(ac108_i2c_id, i2c)->driver_data;
if (index == AC101_I2C_ID) { if (index == AC101_I2C_ID) {
ac10x->i2c101 = i2c; ac10x->i2c101 = i2c;
i2c_set_clientdata(i2c, ac10x); i2c_set_clientdata(i2c, ac10x);
ret = ac101_probe(i2c, i2c_id); ret = ac101_probe(i2c, i2c_match_id(ac108_i2c_id, i2c));
if (ret) { if (ret) {
ac10x->i2c101 = NULL; ac10x->i2c101 = NULL;
return ret; return ret;
@ -1487,7 +1498,7 @@ __ret:
return ret; return ret;
} }
static int ac108_i2c_remove(struct i2c_client *i2c) { static void ac108_i2c_remove(struct i2c_client *i2c) {
if (ac10x->codec != NULL) { if (ac10x->codec != NULL) {
snd_soc_unregister_codec(&ac10x->i2c[_MASTER_INDEX]->dev); snd_soc_unregister_codec(&ac10x->i2c[_MASTER_INDEX]->dev);
ac10x->codec = NULL; ac10x->codec = NULL;
@ -1512,17 +1523,8 @@ __ret:
kfree(ac10x); kfree(ac10x);
ac10x = NULL; ac10x = NULL;
} }
return 0;
} }
static const struct i2c_device_id ac108_i2c_id[] = {
{ "ac108_0", 0 },
{ "ac108_1", 1 },
{ "ac108_2", 2 },
{ "ac108_3", 3 },
{ "ac101", AC101_I2C_ID },
{ }
};
MODULE_DEVICE_TABLE(i2c, ac108_i2c_id); MODULE_DEVICE_TABLE(i2c, ac108_i2c_id);
static const struct of_device_id ac108_of_match[] = { static const struct of_device_id ac108_of_match[] = {

View file

@ -119,7 +119,7 @@ void ac101_shutdown(struct i2c_client *i2c);
int ac101_remove(struct i2c_client *i2c); int ac101_remove(struct i2c_client *i2c);
/* seeed voice card export */ /* seeed voice card export */
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int)); int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int, struct snd_pcm_substream *, int, struct snd_soc_dai *));
int ac10x_fill_regcache(struct device* dev, struct regmap* map); int ac10x_fill_regcache(struct device* dev, struct regmap* map);

View file

@ -6,4 +6,10 @@ BUILT_MODULE_NAME[2]="snd-soc-seeed-voicecard"
DEST_MODULE_LOCATION[0]="/kernel/sound/soc/codecs" DEST_MODULE_LOCATION[0]="/kernel/sound/soc/codecs"
DEST_MODULE_LOCATION[1]="/kernel/sound/soc/codecs" DEST_MODULE_LOCATION[1]="/kernel/sound/soc/codecs"
DEST_MODULE_LOCATION[2]="/kernel/sound/soc/bcm" DEST_MODULE_LOCATION[2]="/kernel/sound/soc/bcm"
PATCH[0]="back-to-v4.19.diff"
PATCH[1]="back-to-v5.4.diff"
PATCH[2]="back-to-v5.8.diff"
PATCH_MATCH[0]="^4\.19\.*"
PATCH_MATCH[1]="^5\.4\.*"
PATCH_MATCH[2]="^5\.8\.*"
AUTOINSTALL="yes" AUTOINSTALL="yes"

View file

@ -67,8 +67,10 @@ function get_kernel_version() {
[ -z "$_VER_RUN" ] && { [ -z "$_VER_RUN" ] && {
ZIMAGE=/boot/kernel.img ZIMAGE=/boot/kernel.img
[ -f /boot/firmware/vmlinuz ] && ZIMAGE=/boot/firmware/vmlinuz [ -f /boot/firmware/vmlinuz ] && ZIMAGE=/boot/firmware/vmlinuz
# 64-bit-only kernel package
[ ! -f /boot/kernel.img ] && [ -f /boot/kernel8.img ] && ZIMAGE=/boot/kernel8.img
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1) IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | strings | awk '{ print $3; }') _VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | LC_ALL=C sed -e 's/^.*Linux/Linux/' | strings | awk '{ print $3; }')
} }
echo "$_VER_RUN" echo "$_VER_RUN"
return 0 return 0
@ -76,11 +78,11 @@ function get_kernel_version() {
function check_kernel_headers() { function check_kernel_headers() {
VER_RUN=$(get_kernel_version) VER_RUN=$(get_kernel_version)
VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^-]+/build" | awk -F'/' '{ print $4; }') VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
[ "X$VER_RUN" == "X$VER_HDR" ] && { [ "X$VER_RUN" == "X$VER_HDR" ] && {
return 0 return 0
} }
VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[[:print:]]+/build" | awk -F'/' '{ print $4; }') VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
[ "X$VER_RUN" == "X$VER_HDR" ] && { [ "X$VER_RUN" == "X$VER_HDR" ] && {
return 0 return 0
} }
@ -106,6 +108,8 @@ if [[ $? -eq 0 ]]; then
apt update -y apt update -y
# Raspbian kernel packages # Raspbian kernel packages
apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel
# Recent Raspbian has 64-bit kernel on 32-bit userspace
apt-get -y install gcc-aarch64-linux-gnu
# Ubuntu kernel packages # Ubuntu kernel packages
apt-get -y install linux-raspi linux-headers-raspi linux-image-raspi apt-get -y install linux-raspi linux-headers-raspi linux-image-raspi
apt-get -y install dkms git i2c-tools libasound2-plugins apt-get -y install dkms git i2c-tools libasound2-plugins
@ -177,6 +181,7 @@ grep -q "^snd-soc-wm8960$" /etc/modules || \
#set dtoverlays #set dtoverlays
CONFIG=/boot/config.txt CONFIG=/boot/config.txt
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt [ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
sed -i -e 's:#dtparam=i2c_arm=on:dtparam=i2c_arm=on:g' $CONFIG || true sed -i -e 's:#dtparam=i2c_arm=on:dtparam=i2c_arm=on:g' $CONFIG || true

454
patches/back-to-v4.19.diff Normal file
View file

@ -0,0 +1,454 @@
diff --git a/ac101.c b/ac101.c
index 23837a7..41c15f3 100644
--- a/ac101.c
+++ b/ac101.c
@@ -955,10 +955,10 @@ void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai
AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n",
snd_pcm_stream_str(substream),
- codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE],
- snd_soc_dai_active(codec_dai));
+ codec_dai->playback_active, codec_dai->capture_active,
+ codec_dai->active);
- if (!snd_soc_dai_active(codec_dai)) {
+ if (!codec_dai->active) {
ac10x->aif1_clken = 1;
ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
} else {
@@ -1080,7 +1080,7 @@ int ac101_hw_params(struct snd_pcm_substream *substream,
freq_out = _FREQ_24_576K;
for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
- if (codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
+ if (codec_dai->capture_active && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), (0x4<<AIF1_FS));
} else {
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS));
diff --git a/ac108.c b/ac108.c
index d5dd12d..0a8c462 100644
--- a/ac108.c
+++ b/ac108.c
@@ -653,7 +653,7 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__,
snd_pcm_stream_str(substream),
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
+ dai->playback_active, dai->capture_active);
if (ac10x->i2c101) {
ret = ac101_hw_params(substream, params, dai);
@@ -664,8 +664,8 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
}
}
- if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK])
- || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream_active[SNDRV_PCM_STREAM_CAPTURE])) {
+ if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->playback_active)
+ || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->capture_active)) {
/* not configure hw_param twice */
/* return 0; */
}
@@ -810,9 +810,6 @@ static int ac108_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int fr
struct ac10x_priv *ac10x = snd_soc_dai_get_drvdata(dai);
- if (freq != 24000000 || clk_id != SYSCLK_SRC_PLL)
- dev_warn(dai->dev, "ac108_set_sysclk freq = %d clk = %d\n", freq, clk_id);
-
freq = 24000000;
clk_id = SYSCLK_SRC_PLL;
@@ -1124,7 +1121,7 @@ void ac108_aif_shutdown(struct snd_pcm_substream *substream,
}
}
-int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int direction) {
+int ac108_aif_mute(struct snd_soc_dai *dai, int mute) {
struct snd_soc_codec *codec = dai->codec;
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
@@ -1145,13 +1142,12 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
.hw_params = ac108_hw_params,
.prepare = ac108_prepare,
.trigger = ac108_trigger,
- .mute_stream = ac108_aif_mute,
+ .digital_mute = ac108_aif_mute,
/*DAI format configuration*/
.set_fmt = ac108_set_fmt,
// .hw_free = ac108_hw_free,
- .no_capture_mute = 1,
};
static struct snd_soc_dai_driver ac108_dai0 = {
diff --git a/seeed-voicecard.c b/seeed-voicecard.c
index b90af93..af6db74 100644
--- a/seeed-voicecard.c
+++ b/seeed-voicecard.c
@@ -28,8 +28,6 @@
#include <sound/simple_card_utils.h>
#include "ac10x.h"
-#define LINUX_VERSION_IS_GEQ(x1,x2,x3) (LINUX_VERSION_CODE >= KERNEL_VERSION(x1,x2,x3))
-
/*
* single codec:
* 0 - allow multi codec
@@ -42,9 +40,6 @@ struct seeed_card_data {
struct seeed_dai_props {
struct asoc_simple_dai cpu_dai;
struct asoc_simple_dai codec_dai;
- struct snd_soc_dai_link_component cpus; /* single cpu */
- struct snd_soc_dai_link_component codecs; /* single codec */
- struct snd_soc_dai_link_component platforms;
unsigned int mclk_fs;
} *dai_props;
unsigned int mclk_fs;
@@ -97,16 +92,16 @@ static int seeed_voice_card_startup(struct snd_pcm_substream *substream)
if (ret)
clk_disable_unprepare(dai_props->cpu_dai.clk);
- if (asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min) {
- priv->channels_playback_default = asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min;
+ if (rtd->cpu_dai->driver->playback.channels_min) {
+ priv->channels_playback_default = rtd->cpu_dai->driver->playback.channels_min;
}
- if (asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min) {
- priv->channels_capture_default = asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min;
+ if (rtd->cpu_dai->driver->capture.channels_min) {
+ priv->channels_capture_default = rtd->cpu_dai->driver->capture.channels_min;
}
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_override;
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_override;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_override;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_override;
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_override;
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_override;
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_override;
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_override;
return ret;
}
@@ -118,10 +113,10 @@ static void seeed_voice_card_shutdown(struct snd_pcm_substream *substream)
struct seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_default;
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_default;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_default;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_default;
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_default;
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_default;
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_default;
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_default;
clk_disable_unprepare(dai_props->cpu_dai.clk);
@@ -132,8 +127,8 @@ static int seeed_voice_card_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
- struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
@@ -197,7 +192,7 @@ static void work_cb_codec_clk(struct work_struct *work)
static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_dai *dai = rtd->codec_dai;
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
#if CONFIG_AC10X_TRIG_LOCK
unsigned long flags;
@@ -206,7 +201,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
+ dai->playback_active, dai->capture_active);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -228,7 +223,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* capture channel resync, if overrun */
- if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (dai->capture_active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
break;
}
@@ -248,7 +243,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE], ret);
+ dai->playback_active, dai->capture_active, ret);
return ret;
}
@@ -387,8 +382,8 @@ static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd)
static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
- struct snd_soc_dai *codec = asoc_rtd_to_codec(rtd, 0);
- struct snd_soc_dai *cpu = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec = rtd->codec_dai;
+ struct snd_soc_dai *cpu = rtd->cpu_dai;
struct seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
int ret;
@@ -453,19 +448,20 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
goto dai_link_of_err;
}
- ret = asoc_simple_parse_daifmt(dev, node, codec,
+ ret = asoc_simple_card_parse_daifmt(dev, node, codec,
prefix, &dai_link->dai_fmt);
if (ret < 0)
goto dai_link_of_err;
of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);
- ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
+ ret = asoc_simple_card_parse_cpu(cpu, dai_link,
+ DAI, CELL, &single_cpu);
if (ret < 0)
goto dai_link_of_err;
#if _SINGLE_CODEC
- ret = asoc_simple_parse_codec(codec, dai_link);
+ ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL);
if (ret < 0)
goto dai_link_of_err;
#else
@@ -477,7 +473,7 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
dev_dbg(dev, "dai_link num_codecs = %d\n", dai_link->num_codecs);
#endif
- ret = asoc_simple_parse_platform(plat, dai_link);
+ ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
if (ret < 0)
goto dai_link_of_err;
@@ -502,7 +498,7 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,10,0)
ret = asoc_simple_card_parse_clk_cpu(cpu, dai_link, cpu_dai);
#else
- ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
+ ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
#endif
if (ret < 0)
goto dai_link_of_err;
@@ -510,16 +506,16 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,10,0)
ret = asoc_simple_card_parse_clk_codec(codec, dai_link, codec_dai);
#else
- ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai);
+ ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai);
#endif
if (ret < 0)
goto dai_link_of_err;
- ret = asoc_simple_set_dailink_name(dev, dai_link,
+ ret = asoc_simple_card_set_dailink_name(dev, dai_link,
"%s-%s",
- dai_link->cpus->dai_name,
+ dai_link->cpu_dai_name,
#if _SINGLE_CODEC
- dai_link->codecs->dai_name
+ dai_link->codec_dai_name
#else
dai_link->codecs[0].dai_name
#endif
@@ -533,19 +529,21 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt);
dev_dbg(dev, "\tcpu : %s / %d\n",
- dai_link->cpus->dai_name,
+ dai_link->cpu_dai_name,
dai_props->cpu_dai.sysclk);
dev_dbg(dev, "\tcodec : %s / %d\n",
#if _SINGLE_CODEC
- dai_link->codecs->dai_name,
+ dai_link->codec_dai_name,
#else
dai_link->codecs[0].dai_name,
#endif
dai_props->codec_dai.sysclk);
- asoc_simple_canonicalize_cpu(dai_link, single_cpu);
+ asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);
#if _SINGLE_CODEC
- asoc_simple_canonicalize_platform(dai_link);
+ ret = asoc_simple_card_canonicalize_dailink(dai_link);
+ if (ret < 0)
+ goto dai_link_of_err;
#endif
dai_link_of_err:
@@ -578,7 +576,7 @@ static int seeed_voice_card_parse_aux_devs(struct device_node *node,
aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
if (!aux_node)
return -EINVAL;
- priv->snd_card.aux_dev[i].dlc.of_node = aux_node;
+ priv->snd_card.aux_dev[i].codec_of_node = aux_node;
}
priv->snd_card.num_aux_devs = n;
@@ -638,7 +636,7 @@ static int seeed_voice_card_parse_of(struct device_node *node,
goto card_parse_end;
}
- ret = asoc_simple_parse_card_name(&priv->snd_card, PREFIX);
+ ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
if (ret < 0)
goto card_parse_end;
@@ -743,7 +741,7 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
struct seeed_dai_props *dai_props;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
- int num, ret, i;
+ int num, ret;
/* Get the number of DAI links */
if (np && of_get_child_by_name(np, PREFIX "dai-link"))
@@ -761,25 +759,6 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
if (!dai_props || !dai_link)
return -ENOMEM;
- /*
- * Use snd_soc_dai_link_component instead of legacy style
- * It is codec only. but cpu/platform will be supported in the future.
- * see
- * soc-core.c :: snd_soc_init_multicodec()
- *
- * "platform" might be removed
- * see
- * simple-card-utils.c :: asoc_simple_canonicalize_platform()
- */
- for (i = 0; i < num; i++) {
- dai_link[i].cpus = &dai_props[i].cpus;
- dai_link[i].num_cpus = 1;
- dai_link[i].codecs = &dai_props[i].codecs;
- dai_link[i].num_codecs = 1;
- dai_link[i].platforms = &dai_props[i].platforms;
- dai_link[i].num_platforms = 1;
- }
-
priv->dai_props = dai_props;
priv->dai_link = dai_link;
@@ -798,9 +777,6 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
}
} else {
struct seeed_card_info *cinfo;
- struct snd_soc_dai_link_component *cpus;
- struct snd_soc_dai_link_component *codecs;
- struct snd_soc_dai_link_component *platform;
cinfo = dev->platform_data;
if (!cinfo) {
@@ -817,19 +793,13 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
return -EINVAL;
}
- cpus = dai_link->cpus;
- cpus->dai_name = cinfo->cpu_dai.name;
-
- codecs = dai_link->codecs;
- codecs->name = cinfo->codec;
- codecs->dai_name = cinfo->codec_dai.name;
-
- platform = dai_link->platforms;
- platform->name = cinfo->platform;
-
priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name;
dai_link->name = cinfo->name;
dai_link->stream_name = cinfo->name;
+ dai_link->platform_name = cinfo->platform;
+ dai_link->codec_name = cinfo->codec;
+ dai_link->cpu_dai_name = cinfo->cpu_dai.name;
+ dai_link->codec_dai_name = cinfo->codec_dai.name;
dai_link->dai_fmt = cinfo->daifmt;
dai_link->init = seeed_voice_card_dai_init;
memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
@@ -853,7 +823,7 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
return ret;
err:
- asoc_simple_clean_reference(&priv->snd_card);
+ asoc_simple_card_clean_reference(&priv->snd_card);
return ret;
}
@@ -865,7 +835,7 @@ static int seeed_voice_card_remove(struct platform_device *pdev)
if (cancel_work_sync(&priv->work_codec_clk) != 0) {
}
- return asoc_simple_clean_reference(card);
+ return asoc_simple_card_clean_reference(card);
}
static const struct of_device_id seeed_voice_of_match[] = {
diff --git a/sound-compatible-4.18.h b/sound-compatible-4.18.h
index 550b3a7..6c1a014 100644
--- a/sound-compatible-4.18.h
+++ b/sound-compatible-4.18.h
@@ -16,6 +16,10 @@
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
+#ifndef __has_attribute
+# define __has_attribute(x) __GCC4_has_attribute_##x
+# define __GCC4_has_attribute___fallthrough__ 0
+#endif
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
@@ -31,11 +35,7 @@
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
-#define snd_soc_read snd_soc_component_read
-#else
#define snd_soc_read snd_soc_component_read32
-#endif
#define snd_soc_register_codec devm_snd_soc_register_component
#define snd_soc_unregister_codec snd_soc_unregister_component
#define snd_soc_update_bits snd_soc_component_update_bits
diff --git a/wm8960.c b/wm8960.c
index 465c6dc..34d4dad 100644
--- a/wm8960.c
+++ b/wm8960.c
@@ -796,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
+static int wm8960_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
@@ -1236,12 +1236,11 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
static const struct snd_soc_dai_ops wm8960_dai_ops = {
.hw_params = wm8960_hw_params,
.hw_free = wm8960_hw_free,
- .mute_stream = wm8960_mute,
+ .digital_mute = wm8960_mute,
.set_fmt = wm8960_set_dai_fmt,
.set_clkdiv = wm8960_set_dai_clkdiv,
.set_pll = wm8960_set_dai_pll,
.set_sysclk = wm8960_set_dai_sysclk,
- .no_capture_mute = 1,
};
static struct snd_soc_dai_driver wm8960_dai = {

245
patches/back-to-v5.4.diff Normal file
View file

@ -0,0 +1,245 @@
diff --git a/ac101.c b/ac101.c
index be9b1d8..343f030 100644
--- a/ac101.c
+++ b/ac101.c
@@ -955,10 +955,10 @@ void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai
AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n",
snd_pcm_stream_str(substream),
- codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE],
- snd_soc_dai_active(codec_dai));
+ codec_dai->playback_active, codec_dai->capture_active,
+ codec_dai->active);
- if (!snd_soc_dai_active(codec_dai)) {
+ if (!codec_dai->active) {
ac10x->aif1_clken = 1;
ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
} else {
@@ -1080,7 +1080,7 @@ int ac101_hw_params(struct snd_pcm_substream *substream,
freq_out = _FREQ_24_576K;
for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
- if (codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
+ if (codec_dai->capture_active && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), (0x4<<AIF1_FS));
} else {
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS));
diff --git a/ac108.c b/ac108.c
index 4663df0..12ab27b 100644
--- a/ac108.c
+++ b/ac108.c
@@ -653,7 +653,7 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__,
snd_pcm_stream_str(substream),
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
+ dai->playback_active, dai->capture_active);
if (ac10x->i2c101) {
ret = ac101_hw_params(substream, params, dai);
@@ -664,8 +664,8 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
}
}
- if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK])
- || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream_active[SNDRV_PCM_STREAM_CAPTURE])) {
+ if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->playback_active)
+ || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->capture_active)) {
/* not configure hw_param twice */
/* return 0; */
}
@@ -1124,7 +1124,7 @@ void ac108_aif_shutdown(struct snd_pcm_substream *substream,
}
}
-int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int direction) {
+int ac108_aif_mute(struct snd_soc_dai *dai, int mute) {
struct snd_soc_codec *codec = dai->codec;
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
@@ -1145,13 +1145,12 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
.hw_params = ac108_hw_params,
.prepare = ac108_prepare,
.trigger = ac108_trigger,
- .mute_stream = ac108_aif_mute,
+ .digital_mute = ac108_aif_mute,
/*DAI format configuration*/
.set_fmt = ac108_set_fmt,
// .hw_free = ac108_hw_free,
- .no_capture_mute = 1,
};
static struct snd_soc_dai_driver ac108_dai0 = {
diff --git a/seeed-voicecard.c b/seeed-voicecard.c
index c6d9048..43535aa 100644
--- a/seeed-voicecard.c
+++ b/seeed-voicecard.c
@@ -96,16 +96,16 @@ static int seeed_voice_card_startup(struct snd_pcm_substream *substream)
if (ret)
clk_disable_unprepare(dai_props->cpu_dai.clk);
- if (asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min) {
- priv->channels_playback_default = asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min;
+ if (rtd->cpu_dai->driver->playback.channels_min) {
+ priv->channels_playback_default = rtd->cpu_dai->driver->playback.channels_min;
}
- if (asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min) {
- priv->channels_capture_default = asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min;
+ if (rtd->cpu_dai->driver->capture.channels_min) {
+ priv->channels_capture_default = rtd->cpu_dai->driver->capture.channels_min;
}
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_override;
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_override;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_override;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_override;
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_override;
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_override;
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_override;
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_override;
return ret;
}
@@ -117,10 +117,10 @@ static void seeed_voice_card_shutdown(struct snd_pcm_substream *substream)
struct seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_default;
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_default;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_default;
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_default;
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_default;
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_default;
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_default;
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_default;
clk_disable_unprepare(dai_props->cpu_dai.clk);
@@ -131,8 +131,8 @@ static int seeed_voice_card_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
- struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
@@ -196,7 +196,7 @@ static void work_cb_codec_clk(struct work_struct *work)
static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_dai *dai = rtd->codec_dai;
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
#if CONFIG_AC10X_TRIG_LOCK
unsigned long flags;
@@ -205,7 +205,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
+ dai->playback_active, dai->capture_active);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -227,7 +227,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* capture channel resync, if overrun */
- if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (dai->capture_active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
break;
}
@@ -252,7 +247,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE], ret);
+ dai->playback_active, dai->capture_active, ret);
return ret;
}
@@ -337,8 +337,8 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai,
static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
- struct snd_soc_dai *codec = asoc_rtd_to_codec(rtd, 0);
- struct snd_soc_dai *cpu = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec = rtd->codec_dai;
+ struct snd_soc_dai *cpu = rtd->cpu_dai;
struct seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
int ret;
@@ -636,11 +636,11 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
* Use snd_soc_dai_link_component instead of legacy style
* It is codec only. but cpu/platform will be supported in the future.
* see
- * soc-core.c :: snd_soc_init_multicodec()
+ * soc-core.c :: snd_soc_init_multicodec()
*
* "platform" might be removed
* see
- * simple-card-utils.c :: asoc_simple_canonicalize_platform()
+ * simple-card-utils.c :: asoc_simple_canonicalize_platform()
*/
for (i = 0; i < num; i++) {
dai_link[i].cpus = &dai_props[i].cpus;
diff --git a/sound-compatible-4.18.h b/sound-compatible-4.18.h
index 080325b..eefa7de 100644
--- a/sound-compatible-4.18.h
+++ b/sound-compatible-4.18.h
@@ -16,6 +16,10 @@
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
+#ifndef __has_attribute
+# define __has_attribute(x) __GCC4_has_attribute_##x
+# define __GCC4_has_attribute___fallthrough__ 0
+#endif
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
@@ -31,11 +35,7 @@
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
-#define snd_soc_read snd_soc_component_read
-#else
#define snd_soc_read snd_soc_component_read32
-#endif
#define snd_soc_register_codec devm_snd_soc_register_component
#define snd_soc_unregister_codec snd_soc_unregister_component
#define snd_soc_update_bits snd_soc_component_update_bits
diff --git a/wm8960.c b/wm8960.c
index 465c6dc..34d4dad 100644
--- a/wm8960.c
+++ b/wm8960.c
@@ -796,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
+static int wm8960_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
@@ -1236,12 +1236,11 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
static const struct snd_soc_dai_ops wm8960_dai_ops = {
.hw_params = wm8960_hw_params,
.hw_free = wm8960_hw_free,
- .mute_stream = wm8960_mute,
+ .digital_mute = wm8960_mute,
.set_fmt = wm8960_set_dai_fmt,
.set_clkdiv = wm8960_set_dai_clkdiv,
.set_pll = wm8960_set_dai_pll,
.set_sysclk = wm8960_set_dai_sysclk,
- .no_capture_mute = 1,
};
static struct snd_soc_dai_driver wm8960_dai = {

71
patches/back-to-v5.8.diff Normal file
View file

@ -0,0 +1,71 @@
diff --git a/ac108.c b/ac108.c
index 4663df0..67edeae 100644
--- a/ac108.c
+++ b/ac108.c
@@ -1124,7 +1124,7 @@ void ac108_aif_shutdown(struct snd_pcm_substream *substream,
}
}
-int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int direction) {
+int ac108_aif_mute(struct snd_soc_dai *dai, int mute) {
struct snd_soc_codec *codec = dai->codec;
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
@@ -1145,13 +1145,12 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
.hw_params = ac108_hw_params,
.prepare = ac108_prepare,
.trigger = ac108_trigger,
- .mute_stream = ac108_aif_mute,
+ .digital_mute = ac108_aif_mute,
/*DAI format configuration*/
.set_fmt = ac108_set_fmt,
// .hw_free = ac108_hw_free,
- .no_capture_mute = 1,
};
static struct snd_soc_dai_driver ac108_dai0 = {
diff --git a/sound-compatible-4.18.h b/sound-compatible-4.18.h
index 080325b..faed848 100644
--- a/sound-compatible-4.18.h
+++ b/sound-compatible-4.18.h
@@ -31,11 +31,7 @@
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
-#define snd_soc_read snd_soc_component_read
-#else
#define snd_soc_read snd_soc_component_read32
-#endif
#define snd_soc_register_codec devm_snd_soc_register_component
#define snd_soc_unregister_codec snd_soc_unregister_component
#define snd_soc_update_bits snd_soc_component_update_bits
diff --git a/wm8960.c b/wm8960.c
index 465c6dc..34d4dad 100644
--- a/wm8960.c
+++ b/wm8960.c
@@ -796,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
+static int wm8960_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
@@ -1236,12 +1236,11 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
static const struct snd_soc_dai_ops wm8960_dai_ops = {
.hw_params = wm8960_hw_params,
.hw_free = wm8960_hw_free,
- .mute_stream = wm8960_mute,
+ .digital_mute = wm8960_mute,
.set_fmt = wm8960_set_dai_fmt,
.set_clkdiv = wm8960_set_dai_clkdiv,
.set_pll = wm8960_set_dai_pll,
.set_sysclk = wm8960_set_dai_sysclk,
- .no_capture_mute = 1,
};
static struct snd_soc_dai_driver wm8960_dai = {

View file

@ -42,7 +42,9 @@ function get_kernel_version() {
[ -z "$_VER_RUN" ] && { [ -z "$_VER_RUN" ] && {
ZIMAGE=/boot/kernel.img ZIMAGE=/boot/kernel.img
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1) IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) | zcat | grep -a -m1 "Linux version" | strings | awk '{ print $3; }') # 64-bit-only kernel package
[ ! -f /boot/kernel.img ] && [ -f /boot/kernel8.img ] && ZIMAGE=/boot/kernel8.img
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | LC_ALL=C sed -e 's/^.*Linux/Linux/' | strings | awk '{ print $3; }')
} }
echo "$_VER_RUN" echo "$_VER_RUN"
return 0 return 0
@ -130,10 +132,10 @@ if [ "$overlay" ]; then
if [[ "$kernel_ver" =~ ^4\.19.*$ || "$kernel_ver" =~ ^5\.*$ ]]; then if [[ "$kernel_ver" =~ ^4\.19.*$ || "$kernel_ver" =~ ^5\.*$ ]]; then
for i in $RPI_HATS; do for i in $RPI_HATS; do
if [ "$i" == "$overlay" ]; then if [ "$i" == "$overlay" ]; then
do_overlay $overlay 0 /bin/true #do_overlay $overlay 0
else else
echo Uninstall $i ... echo Uninstall $i ...
do_overlay $i 1 /bin/true #do_overlay $i 1
fi fi
done done
fi fi

View file

@ -30,6 +30,20 @@
#define LINUX_VERSION_IS_GEQ(x1,x2,x3) (LINUX_VERSION_CODE >= KERNEL_VERSION(x1,x2,x3)) #define LINUX_VERSION_IS_GEQ(x1,x2,x3) (LINUX_VERSION_CODE >= KERNEL_VERSION(x1,x2,x3))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus)
#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs)
#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \
asoc_simple_parse_dai(node, dai_link->cpus, is_single_link)
#define asoc_simple_parse_codec(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->codecs, NULL)
#define asoc_simple_parse_platform(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->platforms, NULL)
#endif
/* /*
* single codec: * single codec:
* 0 - allow multi codec * 0 - allow multi codec
@ -72,6 +86,7 @@ struct seeed_card_info {
struct asoc_simple_dai codec_dai; struct asoc_simple_dai codec_dai;
}; };
#define seeed_priv_to_card(priv) (&(priv)->snd_card)
#define seeed_priv_to_dev(priv) ((priv)->snd_card.dev) #define seeed_priv_to_dev(priv) ((priv)->snd_card.dev)
#define seeed_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) #define seeed_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
#define seeed_priv_to_props(priv, i) ((priv)->dai_props + (i)) #define seeed_priv_to_props(priv, i) ((priv)->dai_props + (i))
@ -162,9 +177,9 @@ err:
} }
#define _SET_CLOCK_CNT 2 #define _SET_CLOCK_CNT 2
static int (* _set_clock[_SET_CLOCK_CNT])(int y_start_n_stop); static int (* _set_clock[_SET_CLOCK_CNT])(int y_start_n_stop, struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai);
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int)) { int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int, struct snd_pcm_substream *, int, struct snd_soc_dai *)) {
if (! _set_clock[stream]) { if (! _set_clock[stream]) {
_set_clock[stream] = set_clock; _set_clock[stream] = set_clock;
} }
@ -181,10 +196,10 @@ static void work_cb_codec_clk(struct work_struct *work)
int r = 0; int r = 0;
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) { if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) {
r = r || _set_clock[SNDRV_PCM_STREAM_CAPTURE](0); r = r || _set_clock[SNDRV_PCM_STREAM_CAPTURE](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
} }
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) { if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) {
r = r || _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0); r = r || _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
} }
if (r && priv->try_stop++ < TRY_STOP_MAX) { if (r && priv->try_stop++ < TRY_STOP_MAX) {
@ -205,7 +220,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n", dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd, __FUNCTION__, snd_pcm_stream_str(substream), cmd,
dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]); dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
@ -216,8 +231,8 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
/* I know it will degrades performance, but I have no choice */ /* I know it will degrades performance, but I have no choice */
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
#endif #endif
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](1); // if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](1, substream, cmd, dai);
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](1); // if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](1, substream, cmd, dai);
#if CONFIG_AC10X_TRIG_LOCK #if CONFIG_AC10X_TRIG_LOCK
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
#endif #endif
@ -227,7 +242,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* capture channel resync, if overrun */ /* capture channel resync, if overrun */
if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
break; break;
} }
@ -237,14 +252,18 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
if (0 != schedule_work(&priv->work_codec_clk)) { if (0 != schedule_work(&priv->work_codec_clk)) {
} }
} else { } else {
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](0); // if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0); // if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
} }
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
} }
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active, ret);
return ret; return ret;
} }
@ -292,7 +311,7 @@ static int asoc_simple_parse_dai(struct device_node *node,
* 2) user need to rebind Sound Card everytime * 2) user need to rebind Sound Card everytime
* if he unbinded CPU or Codec. * if he unbinded CPU or Codec.
*/ */
ret = snd_soc_of_get_dai_name(node, &dlc->dai_name); ret = snd_soc_of_get_dai_name(node, &dlc->dai_name, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -334,6 +353,62 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai,
return 0; return 0;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
static inline int asoc_simple_component_is_codec(struct snd_soc_component *component)
{
return component->driver->endianness;
}
static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_component *component;
struct snd_soc_pcm_stream *params;
struct snd_pcm_hardware hw;
int i, ret, stream;
/* Only Codecs */
for_each_rtd_components(rtd, i, component) {
if (!asoc_simple_component_is_codec(component))
return 0;
}
/* Assumes the capabilities are the same for all supported streams */
for (stream = 0; stream < 2; stream++) {
ret = snd_soc_runtime_calc_hw(rtd, &hw, stream);
if (ret == 0)
break;
}
if (ret < 0) {
dev_err(rtd->dev, "simple-card: no valid dai_link params\n");
return ret;
}
params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
params->formats = hw.formats;
params->rates = hw.rates;
params->rate_min = hw.rate_min;
params->rate_max = hw.rate_max;
params->channels_min = hw.channels_min;
params->channels_max = hw.channels_max;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
dai_link->c2c_params = params;
dai_link->num_c2c_params = 1;
#else
/* apparently this goes back to 5.6.x */
dai_link->params = params;
dai_link->num_params = 1;
#endif
return 0;
}
#endif
static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
@ -351,6 +426,13 @@ static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0) if (ret < 0)
return ret; return ret;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
ret = asoc_simple_init_dai_link_params(rtd);
if (ret < 0)
return ret;
#endif
dev_dbg(rtd->card->dev, "codec \"%s\" mapping to cpu \"%s\"\n", codec->name, cpu->name);
return 0; return 0;
} }
@ -458,10 +540,6 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
if (ret < 0) if (ret < 0)
goto dai_link_of_err; goto dai_link_of_err;
#if _SINGLE_CODEC
asoc_simple_canonicalize_platform(dai_link);
#endif
ret = asoc_simple_set_dailink_name(dev, dai_link, ret = asoc_simple_set_dailink_name(dev, dai_link,
"%s-%s", "%s-%s",
dai_link->cpus->dai_name, dai_link->cpus->dai_name,
@ -490,7 +568,17 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
#endif #endif
dai_props->codec_dai.sysclk); dai_props->codec_dai.sysclk);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu);
#if _SINGLE_CODEC
asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus);
#endif
#else
asoc_simple_canonicalize_cpu(dai_link, single_cpu); asoc_simple_canonicalize_cpu(dai_link, single_cpu);
#if _SINGLE_CODEC
asoc_simple_canonicalize_platform(dai_link);
#endif
#endif
dai_link_of_err: dai_link_of_err:
of_node_put(cpu); of_node_put(cpu);
@ -607,6 +695,79 @@ card_parse_end:
return ret; return ret;
} }
#ifdef DEBUG
inline void seeed_debug_dai(struct seeed_card_data *priv,
char *name,
struct asoc_simple_dai *dai)
{
struct device *dev = seeed_priv_to_dev(priv);
if (dai->name)
dev_dbg(dev, "%s dai name = %s\n",
name, dai->name);
if (dai->sysclk)
dev_dbg(dev, "%s sysclk = %d\n",
name, dai->sysclk);
dev_dbg(dev, "%s direction = %s\n",
name, dai->clk_direction ? "OUT" : "IN");
if (dai->slots)
dev_dbg(dev, "%s slots = %d\n", name, dai->slots);
if (dai->slot_width)
dev_dbg(dev, "%s slot width = %d\n", name, dai->slot_width);
if (dai->tx_slot_mask)
dev_dbg(dev, "%s tx slot mask = %d\n", name, dai->tx_slot_mask);
if (dai->rx_slot_mask)
dev_dbg(dev, "%s rx slot mask = %d\n", name, dai->rx_slot_mask);
if (dai->clk)
dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk));
}
inline void seeed_debug_info(struct seeed_card_data *priv)
{
struct snd_soc_card *card = seeed_priv_to_card(priv);
struct device *dev = seeed_priv_to_dev(priv);
int i;
if (card->name)
dev_dbg(dev, "Card Name: %s\n", card->name);
for (i = 0; i < card->num_links; i++) {
struct seeed_dai_props *props = seeed_priv_to_props(priv, i);
struct snd_soc_dai_link *link = seeed_priv_to_link(priv, i);
dev_dbg(dev, "DAI%d\n", i);
seeed_debug_dai(priv, "cpu", &props->cpu_dai);
seeed_debug_dai(priv, "codec", &props->codec_dai);
if (link->name)
dev_dbg(dev, "dai name = %s\n", link->name);
dev_dbg(dev, "dai format = %04x\n", link->dai_fmt);
/*
if (props->adata.convert_rate)
dev_dbg(dev, "convert_rate = %d\n",
props->adata.convert_rate);
if (props->adata.convert_channels)
dev_dbg(dev, "convert_channels = %d\n",
props->adata.convert_channels);
if (props->codec_conf && props->codec_conf->name_prefix)
dev_dbg(dev, "name prefix = %s\n",
props->codec_conf->name_prefix);
*/
if (props->mclk_fs)
dev_dbg(dev, "mclk-fs = %d\n",
props->mclk_fs);
}
}
#else
#define seeed_debug_info(priv)
#endif /* DEBUG */
static int seeed_voice_card_probe(struct platform_device *pdev) static int seeed_voice_card_probe(struct platform_device *pdev)
{ {
struct seeed_card_data *priv; struct seeed_card_data *priv;
@ -717,6 +878,8 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
INIT_WORK(&priv->work_codec_clk, work_cb_codec_clk); INIT_WORK(&priv->work_codec_clk, work_cb_codec_clk);
seeed_debug_info(priv);
ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
if (ret >= 0) if (ret >= 0)
return ret; return ret;
@ -734,7 +897,9 @@ static int seeed_voice_card_remove(struct platform_device *pdev)
if (cancel_work_sync(&priv->work_codec_clk) != 0) { if (cancel_work_sync(&priv->work_codec_clk) != 0) {
} }
return asoc_simple_clean_reference(card); asoc_simple_clean_reference(card);
return 0;
} }
static const struct of_device_id seeed_voice_of_match[] = { static const struct of_device_id seeed_voice_of_match[] = {

View file

@ -9,7 +9,7 @@
#include <linux/version.h> #include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)
#define __NO_SND_SOC_CODEC_DRV 1 #define __NO_SND_SOC_CODEC_DRV 1
#else #else
#define __NO_SND_SOC_CODEC_DRV 0 #define __NO_SND_SOC_CODEC_DRV 0
@ -31,8 +31,12 @@
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm #define snd_soc_codec_get_dapm snd_soc_component_get_dapm
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level #define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component #define snd_soc_kcontrol_codec snd_soc_kcontrol_component
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
#define snd_soc_read snd_soc_component_read
#else
#define snd_soc_read snd_soc_component_read32 #define snd_soc_read snd_soc_component_read32
#define snd_soc_register_codec snd_soc_register_component #endif
#define snd_soc_register_codec devm_snd_soc_register_component
#define snd_soc_unregister_codec snd_soc_unregister_component #define snd_soc_unregister_codec snd_soc_unregister_component
#define snd_soc_update_bits snd_soc_component_update_bits #define snd_soc_update_bits snd_soc_component_update_bits
#define snd_soc_write snd_soc_component_write #define snd_soc_write snd_soc_component_write

View file

@ -13,7 +13,7 @@
# #
# This derived from my command history on ubuntu 20.04.1 .YMMV # This derived from my command history on ubuntu 20.04.1 .YMMV
sudo apt install -y git gcc make alsa-utils cmake sudo apt install -y git gcc g++ make alsa-utils cmake
git clone git://github.com/raspberrypi/userland.git git clone git://github.com/raspberrypi/userland.git
pushd userland/ pushd userland/

View file

@ -14,6 +14,7 @@ fi
uname_r=$(uname -r) uname_r=$(uname -r)
CONFIG=/boot/config.txt CONFIG=/boot/config.txt
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt [ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
get_overlay() { get_overlay() {

View file

@ -796,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int wm8960_mute(struct snd_soc_dai *dai, int mute) static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
@ -1236,11 +1236,12 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
static const struct snd_soc_dai_ops wm8960_dai_ops = { static const struct snd_soc_dai_ops wm8960_dai_ops = {
.hw_params = wm8960_hw_params, .hw_params = wm8960_hw_params,
.hw_free = wm8960_hw_free, .hw_free = wm8960_hw_free,
.digital_mute = wm8960_mute, .mute_stream = wm8960_mute,
.set_fmt = wm8960_set_dai_fmt, .set_fmt = wm8960_set_dai_fmt,
.set_clkdiv = wm8960_set_dai_clkdiv, .set_clkdiv = wm8960_set_dai_clkdiv,
.set_pll = wm8960_set_dai_pll, .set_pll = wm8960_set_dai_pll,
.set_sysclk = wm8960_set_dai_sysclk, .set_sysclk = wm8960_set_dai_sysclk,
.no_capture_mute = 1,
}; };
static struct snd_soc_dai_driver wm8960_dai = { static struct snd_soc_dai_driver wm8960_dai = {
@ -1258,7 +1259,11 @@ static struct snd_soc_dai_driver wm8960_dai = {
.rates = WM8960_RATES, .rates = WM8960_RATES,
.formats = WM8960_FORMATS,}, .formats = WM8960_FORMATS,},
.ops = &wm8960_dai_ops, .ops = &wm8960_dai_ops,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
.symmetric_rate = 1,
#else
.symmetric_rates = 1, .symmetric_rates = 1,
#endif
}; };
static int wm8960_probe(struct snd_soc_codec *codec) static int wm8960_probe(struct snd_soc_codec *codec)
@ -1286,7 +1291,6 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
.idle_bias_on = 1, .idle_bias_on = 1,
.use_pmdown_time = 1, .use_pmdown_time = 1,
.endianness = 1, .endianness = 1,
.non_legacy_dai_naming = 1,
#endif #endif
}; };
@ -1314,8 +1318,7 @@ static void wm8960_set_pdata_from_of(struct i2c_client *i2c,
pdata->shared_lrclk = true; pdata->shared_lrclk = true;
} }
static int wm8960_i2c_probe(struct i2c_client *i2c, static int wm8960_i2c_probe(struct i2c_client *i2c)
const struct i2c_device_id *id)
{ {
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev); struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8960_priv *wm8960; struct wm8960_priv *wm8960;
@ -1380,10 +1383,9 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
static int wm8960_i2c_remove(struct i2c_client *client) static void wm8960_i2c_remove(struct i2c_client *client)
{ {
snd_soc_unregister_codec(&client->dev); snd_soc_unregister_codec(&client->dev);
return 0;
} }
static const struct i2c_device_id wm8960_i2c_id[] = { static const struct i2c_device_id wm8960_i2c_id[] = {