Compare commits

...

367 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
Hin-Tak Leung
484c03d4c8 Merge branch 'v5.7' into v5.8 2020-10-04 19:17:42 +01:00
Hin-Tak Leung
a79b7d94a5 Merge branch 'v5.5' into v5.7 2020-10-04 19:17:19 +01:00
turmary
87f42ed64d Add: document about "query sound card number" 2020-10-04 19:15:39 +01:00
Hin-Tak Leung
379f791b3c Not a merge - just marking not-interested
Merge branch 'rel-v5.5' of git://github.com/respeaker/seeed-voicecard into v5.5
2020-10-04 19:14:30 +01:00
turmary
8cce4e8ffa Add: document about "query sound card number" 2020-09-30 15:04:47 +08:00
turmary
ac2bf5f638 Move: dkms module removing to the position before kernel update 2020-09-30 10:39:23 +08:00
Hin-Tak Leung
4b7559b320 Not a merge - just marking not-interested
Merge branch 'rel-v5.5' of git://github.com/respeaker/seeed-voicecard into v5.5
2020-09-29 22:35:57 +01:00
turmary
526d0ddef9 Add: error message if old kernel package install failed 2020-09-29 11:07:29 +08:00
turmary
6fb0c63581 Add: unload codec driver when uninstall 2020-09-29 11:06:23 +08:00
turmary
06e054aa06 Move: volume name in state configuration 2020-09-29 00:20:39 +08:00
turmary
1a7fbee50e Move: volume widget name to ALSA tradition style 2020-09-29 00:20:39 +08:00
turmary
7e635f5d57 Remove: debug only or wrong widget 2020-09-29 00:20:38 +08:00
turmary
7461921407 Add: clear title for each install/uninstall steps 2020-09-29 00:20:38 +08:00
Hin-Tak Leung
794d7a3527 Merge branch 'v5.7' into v5.8 2020-09-28 17:11:24 +01:00
Hin-Tak Leung
c206a43374 Merge branch 'v5.5' into v5.7 2020-09-28 17:11:03 +01:00
Hin-Tak Leung
e0f9a554fc stop systemd service before diabling in uninstall, taken from upstream c1c2e5ca 2020-09-28 17:02:11 +01:00
Hin-Tak Leung
e85006b775 Not a merge - just marking not-interested
Merge branch 'rel-v5.5' of git://github.com/respeaker/seeed-voicecard into v5.5
2020-09-28 16:56:01 +01:00
Hin-Tak Leung
921ac8fba5 Following Standard ALSA Control Names convention
See kernel documentation, e.g. v5.5:Documentation/sound/designs/control-names.rst

Fixes https://github.com/respeaker/seeed-voicecard/issues/247
2020-09-28 16:38:30 +01:00
turmary
30ceb546fa Move: volume name in state configuration 2020-09-28 18:14:32 +08:00
turmary
e1110617b2 Move: volume name widget to ALSA tradition 2020-09-28 18:04:40 +08:00
turmary
a891e0260e Remove: debug only or wrong widget 2020-09-28 18:03:18 +08:00
turmary
c1c2e5ca56 Add: clear title for each install/uninstall steps 2020-09-28 08:45:45 +01:00
turmary
f1a46d63cc Add: service message direct to standard output and also /var/log/seeed-voicecard.log 2020-09-28 08:44:56 +01:00
Hin-Tak Leung
2e8586d547 Not a merge - just marking not-interested
Merge branch 'rel-v5.5' of git://github.com/respeaker/seeed-voicecard into v5.5
2020-09-27 18:19:25 +01:00
Hin-Tak Leung
ac1dddeaed Not a merge - just marking not-interested
Merge branch 'master' of git://github.com/respeaker/seeed-voicecard into v5.5
2020-09-27 18:18:08 +01:00
turmary
6a30a3efc6 Remove: useless dd message in get_kernel_version() 2020-09-27 18:12:57 +01:00
Andre Marschalek
84247b0037 Update seeed-voicecard to avoid systemd error messages because of failed service start
systemctl restart seeed-voicecard.service
Job for seeed-voicecard.service failed because the control process exited with error code.
See "systemctl status seeed-voicecard.service" and "journalctl -xe" for details.
2020-09-27 11:16:06 +01:00
Andre Marschalek
9bb3afb358 Update seeed-voicecard
to avoid systemd error messages because of failed service start

systemctl restart seeed-voicecard.service
Job for seeed-voicecard.service failed because the control process exited with error code.
See "systemctl status seeed-voicecard.service" and "journalctl -xe" for details.
2020-09-27 18:11:31 +08:00
turmary
2baddde5ba Fix: install ubuntu kernel only if debian kernel install failed 2020-09-27 11:03:03 +01:00
turmary
b5def1af8e Add: script option --keep-kernel to not change current kernel 2020-09-27 11:01:51 +01:00
turmary
0abc6ed072 Add: checking current directory when installing 2020-09-27 11:00:37 +01:00
turmary
30216a9c7c Add: probing kernel postfix automatically for dkms 2020-09-27 09:15:41 +01:00
turmary
6af23967a5 Add: prevent install package again in download_install_debpkg() 2020-09-27 09:14:54 +01:00
turmary
74620fbdbf Remove: useless dd message in get_kernel_version() 2020-09-27 09:13:55 +01:00
turmary
4cec9e73df Fix: probing architecture when installing specific package 2020-09-27 09:12:35 +01:00
turmary
957b1298d5 Add: more convenience error message about /boot free space 2020-09-27 08:09:25 +01:00
KillingJacky
901b451bd5 add an cmd line option for choosing compile with compatible kernel; clean up more when uninstalling 2020-09-27 06:49:19 +01:00
Psycho
b83519eb82 English correction 2020-09-27 06:49:19 +01:00
turmary
1372794704 Revert "Don't force kernel downgrade"
This reverts commit 30276c80bc.
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
19cfed5bd7 Adding missing shebang
This script has no bash-ism, so /bin/sh (dash on Debian/Ubuntu) is fine.
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
6875869cb2 emit warning for calling ac108_set_sysclk() with unexpected arguments
Don't know why Seeed Studio staff did not put it in.

Conflicts:
	ac108.c
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
9285159a7d Apparently, snd_soc_dai_set_bclk_ratio should be used where snd_soc_dai_set_tdm_slot is.
See, for example,

commit b78b30e32a19f1ac79c26e0a3e9f7bc7385a02a2
Author: j-schambacher <joerg@i2audio.com>
Date:   Tue May 19 13:56:17 2020 +0200

    Switch to snd_soc_dai_set_bclk_ratio
    Replaces obsolete function snd_soc_dai_set_tdm_slot
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
90144a2f2e updating for Ubuntu location of dkms-generated kernel modules 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
cbd6da78fc updating non-standard PATH for Ubuntu in uninstall.sh 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
cf98b67079 rebuilt dtbo on current Raspbian 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
c4c112dcaf relocating fixed-clock entry, based on upstream advice
See upstream -
https://github.com/raspberrypi/documentation/issues/1671
https://github.com/raspberrypi/documentation/pull/1673

Quoted here:

* Only Device Tree nodes at the top level of the tree and children of
  a bus node will be probed. For nodes added at run-time there is the
  further limitation that the bus must register for notifications of
  the addition and removal of children. However, there are exceptions
  that break this rule and cause confusion: the kernel explicitly
  scans the entire tree for some device types - clocks and interrupt
  controller being the two main ones - in order to (for clocks)
  initialise them early and/or (for interrupt controllers) in a
  particular order. This search mechanism only happens during booting
  and so doesn't work for nodes added by an overlay at run-time. It is
  therefore recommended for overlays to place fixed-clock nodes in the
  root of the tree unless it is guaranteed that the overlay will not
  be used at run-time.
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
9722cb01e4 Revert "temporary work-around for not being able to read sysclk from dts for ac10x"
This reverts commit 138d22226e.
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
f4f303f9bd Use pr_warn() for recoverable errors, not pr_info() 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
de23c61210 Use pr_info() for just routine information, not pr_warn() 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
cca7bbfe2a comment about Raspberry Pi 4 having two HDMI ports
The if-endif block below around the amixer call fixes
https://github.com/respeaker/seeed-voicecard/issues/239
https://github.com/respeaker/seeed-voicecard/issues/240
https://github.com/respeaker/seeed-voicecard/issues/243
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
5ca9ab45df Use logic from raspi-config to determine if bcm2835 routing option exists or not
The snd_bcm2835.enable_compat_alsa option:

    enable_compat_alsa:Enables ALSA compatibility virtual audio device (bool)

is off these days, since the beginning of 2020 apparently.

Reference:

    raspi-config (20200120) buster; urgency=medium

      * Add audio switching for discrete internal ALSA devices

     -- Simon Long <simon@raspberrypi.org>  Mon, 20 Jan 2020 11:38:37 +0000
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
8c25d81890 update check_kernel_headers() for Ubuntu header packages 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
f47375e54d Add reference to Ubuntu kernel package names
Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net>
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
1f7323417b temporary work-around for not being able to read sysclk from dts for ac10x
The "sysclk = 24000000" value is supposed to come from the "clock-frequency"
field of ac108_mclk / ac10x_mclk, but somehow it isn't on 5.4 (vs 4.19). This
is a temporary work-around. For some strange unknown reasons, this affects
only the square 4-mic device, but not the linear 4-mic nor the 6-mics device.
The other two devices have two ac108's, and seem to work fine without it.

In v4.19:
seeed_voice_card_probe [snd_soc_seeed_voicecard]
 -> devm_snd_soc_register_card [snd_soc_core]
 -> snd_soc_register_card [snd_soc_core]
 -> seeed_voice_card_dai_init [snd_soc_seeed_voicecard]
 -> asoc_simple_card_init_dai [snd_soc_simple_card_utils]
 -> snd_soc_dai_set_sysclk [snd_soc_core]
 -> ac108_set_sysclk [snd_soc_ac108]

In 5.4:
seeed_voice_card_probe [snd_soc_seeed_voicecard]
 -> devm_snd_soc_register_card [snd_soc_core]
 -> snd_soc_register_card [snd_soc_core]
 -> snd_soc_instantiate_card [snd_soc_core]
 -> seeed_voice_card_dai_init [snd_soc_seeed_voicecard]
 -> asoc_simple_init_dai.part.0 [snd_soc_seeed_voicecard]
 -> snd_soc_dai_set_sysclk [snd_soc_core]
 -> ac108_set_sysclk [snd_soc_ac108]

Which results in the "ac108_set_sysclk  :24000000" kernel message.

Note the extra snd_soc_instantiate_card(), and the copied/renamed
asoc_simple_init_dai() - it became static and not-available to other drivers
in v5.x.

See https://github.com/respeaker/seeed-voicecard/issues/246
2020-09-27 05:09:34 +01:00
Hin-Tak Leung
e82e6fde67 make the config un-install directory configurable, for Ubuntu 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
cd899a83d5 make the overlay un-install directory configurable, for Ubuntu 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
e750de0ecc Allow kernel images to be elsewhere - Ubuntu kernel is not at Raspbian location 2020-09-27 05:09:34 +01:00
Hin-Tak Leung
efaa210d79 Merge branch 'v5.7' into v5.8 2020-09-26 23:08:22 +01:00
Hin-Tak Leung
e6e5240922 Merge branch 'v5.5' into v5.7 2020-09-26 23:08:00 +01:00
Hin-Tak Leung
8ea751c4e9 Adding missing shebang
This script has no bash-ism, so /bin/sh (dash on Debian/Ubuntu) is fine.
2020-09-18 01:06:57 +01:00
Hin-Tak Leung
e2529f9eee Merge branch 'v5.7' into v5.8 2020-09-14 14:56:27 +01:00
Hin-Tak Leung
6aff6e0b33 Merge branch 'v5.5' into v5.7 2020-09-14 14:55:59 +01:00
Hin-Tak Leung
bb09e9d24b emit warning for calling ac108_set_sysclk() with unexpected arguments
Don't know why Seeed Studio staff did not put it in.

Conflicts:
	ac108.c
2020-09-14 14:49:22 +01:00
Hin-Tak Leung
edddb2fbe4 Apparently, snd_soc_dai_set_bclk_ratio should be used where snd_soc_dai_set_tdm_slot is.
See, for example,

commit b78b30e32a19f1ac79c26e0a3e9f7bc7385a02a2
Author: j-schambacher <joerg@i2audio.com>
Date:   Tue May 19 13:56:17 2020 +0200

    Switch to snd_soc_dai_set_bclk_ratio
    Replaces obsolete function snd_soc_dai_set_tdm_slot
2020-09-14 14:48:18 +01:00
Hin-Tak Leung
655d7fe57b updating for Ubuntu location of dkms-generated kernel modules 2020-09-14 14:47:08 +01:00
Hin-Tak Leung
d64e994982 updating non-standard PATH for Ubuntu in uninstall.sh 2020-09-14 14:46:45 +01:00
Hin-Tak Leung
673305fc4e rebuilt dtbo on current Raspbian 2020-09-14 14:46:10 +01:00
Hin-Tak Leung
47d97e7bd5 relocating fixed-clock entry, based on upstream advice
See upstream -
https://github.com/raspberrypi/documentation/issues/1671
https://github.com/raspberrypi/documentation/pull/1673

Quoted here:

* Only Device Tree nodes at the top level of the tree and children of
  a bus node will be probed. For nodes added at run-time there is the
  further limitation that the bus must register for notifications of
  the addition and removal of children. However, there are exceptions
  that break this rule and cause confusion: the kernel explicitly
  scans the entire tree for some device types - clocks and interrupt
  controller being the two main ones - in order to (for clocks)
  initialise them early and/or (for interrupt controllers) in a
  particular order. This search mechanism only happens during booting
  and so doesn't work for nodes added by an overlay at run-time. It is
  therefore recommended for overlays to place fixed-clock nodes in the
  root of the tree unless it is guaranteed that the overlay will not
  be used at run-time.
2020-09-14 14:41:47 +01:00
Hin-Tak Leung
955707d944 Revert "temporary work-around for not being able to read sysclk from dts for ac10x"
This reverts commit 138d22226e.
2020-09-14 14:26:40 +01:00
Hin-Tak Leung
cf2a5fe807 Use pr_warn() for recoverable errors, not pr_info() 2020-09-13 18:24:25 +01:00
Hin-Tak Leung
471f88b337 Use pr_info() for just routine information, not pr_warn() 2020-09-13 18:18:30 +01:00
Hin-Tak Leung
d5b71a009d Merge branch 'v5.7' into v5.8 2020-09-12 00:30:16 +01:00
Hin-Tak Leung
bccf557d62 Merge branch 'v5.5' into v5.7 2020-09-12 00:29:40 +01:00
Hin-Tak Leung
a5095cd7b2 comment about Raspberry Pi 4 having two HDMI ports
The if-endif block below around the amixer call fixes
https://github.com/respeaker/seeed-voicecard/issues/239
https://github.com/respeaker/seeed-voicecard/issues/240
https://github.com/respeaker/seeed-voicecard/issues/243
2020-09-10 23:21:45 +01:00
Hin-Tak Leung
bcdc10e193 Merge branch 'v5.7' into v5.8 2020-09-09 03:34:47 +01:00
Hin-Tak Leung
ebb9a9d82a Merge branch 'v5.5' into v5.7 2020-09-09 03:34:14 +01:00
Hin-Tak Leung
783eff8779 Use logic from raspi-config to determine if bcm2835 routing option exists or not
The snd_bcm2835.enable_compat_alsa option:

    enable_compat_alsa:Enables ALSA compatibility virtual audio device (bool)

is off these days, since the beginning of 2020 apparently.

Reference:

    raspi-config (20200120) buster; urgency=medium

      * Add audio switching for discrete internal ALSA devices

     -- Simon Long <simon@raspberrypi.org>  Mon, 20 Jan 2020 11:38:37 +0000
2020-09-09 03:32:10 +01:00
Hin-Tak Leung
ec5fc9d9b8 Merge remote-tracking branch 'origin/v5.7' into v5.8 2020-09-04 23:52:34 +01:00
Hin-Tak Leung
bb1422182b Merge remote-tracking branch 'origin/v5.5' into v5.7 2020-09-04 23:50:14 +01:00
Hin-Tak Leung
f2b2516426 update check_kernel_headers() for Ubuntu header packages 2020-09-04 23:47:28 +01:00
Hin-Tak Leung
e26006d40c Add reference to Ubuntu kernel package names
Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net>
2020-09-04 23:47:18 +01:00
Hin-Tak Leung
138d22226e temporary work-around for not being able to read sysclk from dts for ac10x
The "sysclk = 24000000" value is supposed to come from the "clock-frequency"
field of ac108_mclk / ac10x_mclk, but somehow it isn't on 5.4 (vs 4.19). This
is a temporary work-around. For some strange unknown reasons, this affects
only the square 4-mic device, but not the linear 4-mic nor the 6-mics device.
The other two devices have two ac108's, and seem to work fine without it.

In v4.19:
seeed_voice_card_probe [snd_soc_seeed_voicecard]
 -> devm_snd_soc_register_card [snd_soc_core]
 -> snd_soc_register_card [snd_soc_core]
 -> seeed_voice_card_dai_init [snd_soc_seeed_voicecard]
 -> asoc_simple_card_init_dai [snd_soc_simple_card_utils]
 -> snd_soc_dai_set_sysclk [snd_soc_core]
 -> ac108_set_sysclk [snd_soc_ac108]

In 5.4:
seeed_voice_card_probe [snd_soc_seeed_voicecard]
 -> devm_snd_soc_register_card [snd_soc_core]
 -> snd_soc_register_card [snd_soc_core]
 -> snd_soc_instantiate_card [snd_soc_core]
 -> seeed_voice_card_dai_init [snd_soc_seeed_voicecard]
 -> asoc_simple_init_dai.part.0 [snd_soc_seeed_voicecard]
 -> snd_soc_dai_set_sysclk [snd_soc_core]
 -> ac108_set_sysclk [snd_soc_ac108]

Which results in the "ac108_set_sysclk  :24000000" kernel message.

Note the extra snd_soc_instantiate_card(), and the copied/renamed
asoc_simple_init_dai() - it became static and not-available to other drivers
in v5.x.

See https://github.com/respeaker/seeed-voicecard/issues/246
2020-09-04 20:44:32 +01:00
Hin-Tak Leung
a24da444df v5.8: snd_soc_pcm_runtime->cpu_dai/codec_dai/cpu_dais/codec_dais removed
perl -pi -e 's/rtd->cpu_dai/asoc_rtd_to_cpu\(rtd, 0\)/' seeed-voicecard.c
perl -pi -e 's/rtd->codec_dai/asoc_rtd_to_codec\(rtd, 0\)/' seeed-voicecard.c

commit 1729025b04b9f242dca37f50dba8dd3705eb1ea1
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Mar 30 10:48:27 2020 +0900

    ASoC: soc-core: remove cpu_dai/codec_dai/cpu_dais/codec_dais

    No-one is using cpu_dai/codec_dai/cpu_dais/codec_dais.
    Let's remove these from snd_soc_pcm_runtime

commit c2233a266178f8937cc26a84cd7672334b5424b7
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Mar 30 10:47:37 2020 +0900

    ASoC: soc: use asoc_rtd_to_cpu() / asoc_rtd_to_codec() macro for DAI pointer
2020-08-30 19:20:19 +01:00
Hin-Tak Leung
c3adcde556 v5.8: struct snd_soc_dai->active replaced by snd_soc_dai_active(snd_soc_dai)
commit 0812a08ac8d054efc6cf2895d3b0e82c8731f8e9
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri May 15 09:48:02 2020 +0900

    ASoC: cleanup dai / component active code

    No one is using dai->active, snd_soc_component_is_active().
    Let's remove these.

commit efffd9b344adbf813e3ae6f6136df80000bf2833
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri May 15 09:46:37 2020 +0900

    ASoC: soc-dai: add snd_soc_dai_active()

    Current snd_soc_dai_action() is updating
    dai->stream_active for Playback/Capture (A),
    dai->active        for DAI (B)

            void snd_soc_dai_action(struct snd_soc_dai *dai,
                                    int stream, int action)
            {
    (A)             dai->stream_active[stream]      += action;
    (B)             dai->active                     += action;
                    dai->component->active          += action;
            }

    But, these are very verbose, because we can calculate
    DAI active from stream_active.

    This patch adds snd_soc_dai_active() which calculate
    DAI active from DAI stream_active.
2020-08-30 19:19:57 +01:00
Hin-Tak Leung
1452d85e0f Merge branch 'v5.5' into v5.7 2020-08-27 13:17:54 +01:00
Hin-Tak Leung
329c8090ea make the config un-install directory configurable, for Ubuntu 2020-08-27 13:17:20 +01:00
Hin-Tak Leung
53c0db449b make the overlay un-install directory configurable, for Ubuntu 2020-08-27 13:15:03 +01:00
Hin-Tak Leung
89f8a76646 Allow kernel images to be elsewhere - Ubuntu kernel is not at Raspbian location 2020-08-24 12:04:38 +01:00
Hin-Tak Leung
39c134f430 Merge branch 'v5.5' into v5.7 2020-08-24 11:00:38 +01:00
Hin-Tak Leung
17944791bb Merge git://github.com/respeaker/seeed-voicecard into v5.5
This is not a merge - just to note that we don't care about those two
changes upstream.
2020-08-24 10:58:42 +01:00
Hin-Tak Leung
df68ab22d6 Merge remote-tracking branch 'origin/v5.5' into v5.7 2020-08-23 20:43:08 +01:00
Hin-Tak Leung
88aae48c41 adding new ubuntu-prerequisite.sh script
notes and typo
2020-08-23 20:37:52 +01:00
Hin-Tak Leung
6bcd4cad2f /opt/vc/bin is not on standard $PATH on Ubuntu 2020-08-23 20:37:20 +01:00
Hin-Tak Leung
7f88e11fd0 adding advice to run ./ubuntu-prerequisite.sh in install.sh 2020-08-23 20:37:07 +01:00
Hin-Tak Leung
60e90d6fae Ubuntu kernels is not at /boot/kernel.img. Revisit for Raspbian
check running kernel agree with installed kernel, and ask the user to reboot before continue

Ubuntu kernels are not installed at /boot/kernel.img
2020-08-23 20:35:44 +01:00
Hin-Tak Leung
5cefec4cca make the config file configurable, for Ubuntu 2020-08-23 20:34:32 +01:00
Hin-Tak Leung
1f9c1464ab make the overlay install directory configurable, for Ubuntu 2020-08-23 20:34:25 +01:00
Hin-Tak Leung
71f01070d8 spelling 2020-08-21 16:27:08 +01:00
Psycho
19d1e6eb88 English correction 2020-08-20 08:16:13 +08:00
Hin-Tak Leung
07dc49259a remove "-c 1" and also protect with test for older kernel / alsa
The "-c 1" was simply wrong. The default (-c 0) sound device of
older kernel / alsa has a numid=3 selector for auto vs headphone vs hdmi .
Newer kernel simply has multiple devices. Also, headphone is -c 0 .

$ amixer contents
numid=2,iface=MIXER,name='Headphone Playback Switch'
  ; type=BOOLEAN,access=rw------,values=1
  : values=on
numid=1,iface=MIXER,name='Headphone Playback Volume'
  ; type=INTEGER,access=rw---R--,values=1,min=-10239,max=400,step=0
  : values=-2000
  | dBscale-min=-102.39dB,step=0.01dB,mute=1

TODO: For now, broadly dividing by kernel v4.x vs v5.x is good enough, but
it would be nice to find out when / which kernel /alsa this is relevant.

closes https://github.com/respeaker/seeed-voicecard/issues/240
2020-08-18 23:30:21 +01:00
Hin-Tak Leung
d8775ccb93 Use pr_info() for regular information 2020-08-18 08:22:32 +01:00
Hin-Tak Leung
c3ddbb521d likely v5 kernels behave like late 4.x, regarding dynamic dtoverlay; untested, and possibly revisit. 2020-08-18 08:22:19 +01:00
Hin-Tak Leung
1456785779 Merge remote-tracking branch 'origin/v5.5' into v5.7 2020-08-09 10:07:09 +01:00
Hin-Tak Leung
02eccbcd55 mask amixer failures - some user have different numbered / multiple audio devices 2020-08-09 10:06:21 +01:00
Hin-Tak Leung
131ee8187d Merge branch 'v5.7' into v5.7 2020-08-05 06:26:08 +01:00
Hin-Tak Leung
ed615d2318 Merge remote-tracking branch 'origin/v5.5' into v5.7 2020-08-05 06:20:32 +01:00
Hin-Tak Leung
2cc009619e Merge branch 'ubuntu' into v5.5 2020-08-05 06:10:37 +01:00
Hin-Tak Leung
aaf0cc2c61 move files in place, to capture hhuysqt <1020988872@qq.com>'s ubuntu-porting work
git rm seeed-voicecard.c
git mv seeed-voicecard-v5.3.c seeed-voicecard.c
2020-08-05 06:07:36 +01:00
Hin-Tak Leung
a6db04e724 Merge branch 'wrong-initialization-fix' into v5.5
Conflicts:
	seeed-voicecard.c
2020-08-05 05:59:37 +01:00
Hin-Tak Leung
0be1de9750 Revert previous over-zealous "rename asoc_simple_card_xxx() to asoc_simple_()"
Two of them should not have been changed, as they were protected and intended
for older kernels.
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
fcbc3b6d6b copy asoc_simple_card_init_dai() from v5.7:sound/soc/generic/simple-card-utils.c
It was made private in v5.2:

commit ad934ca8010843482d61fda46786449a9bc99e10
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:55:52 2019 +0900

    ASoC: simple-card-utils: share asoc_simple_dai_init()
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
c2b419c286 Revert "asoc_simple_card_init_dai is not exported, but asoc_simple_dai_init is, and does more"
This reverts commit de22f92298.

That commit was wrong: seeed_priv_to_props() is not identical to simple_priv_props().

Conflicts:
	seeed-voicecard.c
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
ed094dece5 v5.2: comments
The init code was extracted into asoc_simple_card_init_priv(), with
additional comments.

commit 65a5056b21202eff7f54243e587183f4bb6ed352
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:56:26 2019 +0900

    ASoC: simple-card-utils: share asoc_simple_card_init_priv()

    The difference between simple-card / audio-graph are just using
    OF graph style, or not. In other words, other things should be same.
    This means, simple-card/audio-graph common functions should be
    implemented at simple-card-utils, and its own functions should be
    implemented at each files.

    Current simple-card / audio-graph are initializing each priv,
    but it is same operation.
    This patch adds new asoc_simple_card_init_priv() and initialize
    priv by same operation.
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
51966603da v5.3: support snd_soc_dai_link_component style for cpu
commit f107294c6422e772773b53dbf802186175b6289e
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Thu Jun 6 13:07:35 2019 +0900

    ASoC: simple-card: support snd_soc_dai_link_component style for cpu

    ASoC supports modern style dai_link (= snd_soc_dai_link_component) for
    CPU. legacy style dai_link (= cpu_dai_name, cpu_name, cpu_of_node) are
    no longer needed.
    This patch switches to modern style.
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
6afe18224a v5.1: add .num_platform for dai_link
commit 910fdcabedd2354d161b1beab6ad7dc7e859651d
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Jan 21 09:32:32 2019 +0900

    ASoC: soc-core: add .num_platform for dai_link

    Current snd_soc_dai_link is starting to use snd_soc_dai_link_component
    (= modern) style for Platform, but it is still assuming single Platform
    so far. We will need to have multi Platform support in the not far
    future.

    Currently only simple card is using it as sound card driver,
    and other drivers are converted to it from legacy style by
    snd_soc_init_platform().
    To avoid future problem of multi Platform support, let's add
    num_platforms before it is too late.

    In the same time, to make it same naming mothed, "platform" should
    be "platforms". This patch fixup it too.
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
953fa50f4f v4.20: support snd_soc_dai_link_component style for platform
commit e58f41e41185c6906bd11c73c4e76aa5fc3ea685
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri Aug 31 03:10:33 2018 +0000

    ASoC: simple-card: support snd_soc_dai_link_component style for platform

    Current ASoC is supporting snd_soc_dai_link_component for binding,
    it is more useful than current legacy style.
    Currently only codec is supporting it as multicodec (= codecs).
    CPU will support multi style in the future.
    We want to have it on Platform too in the future.

    If all Codec/CPU/Platform are replaced into snd_soc_dai_link_component
    style, we can remove legacy complex style.
    This patch supports snd_soc_dai_link_component style
    for simple-card for platform.
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
4396e4f834 v4.20: support snd_soc_dai_link_component style for codec
commit 710af9196ce614ee02185c2ec55e617a71843183
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri Aug 31 03:08:24 2018 +0000

    ASoC: simple-card: support snd_soc_dai_link_component style for codec

    Current ASoC is supporting snd_soc_dai_link_component for binding,
    it is more useful than current legacy style.
    Currently only codec is supporting it as multicodec (= codecs).
    CPU will support multi style in the future.
    We want to have it on Platform too in the future.

    If all Codec/CPU/Platform are replaced into snd_soc_dai_link_component
    style, we can remove legacy complex style.
    This patch supports snd_soc_dai_link_component style
    for simple-card for codec.
2020-08-05 05:45:31 +01:00
Hin-Tak Leung
26754b0821 Revert previous over-zealous "rename asoc_simple_card_xxx() to asoc_simple_()"
Two of them should not have been changed, as they were protected and intended
for older kernels.
2020-08-05 05:26:01 +01:00
Hin-Tak Leung
af8668ff97 copy asoc_simple_card_init_dai() from v5.7:sound/soc/generic/simple-card-utils.c
It was made private in v5.2:

commit ad934ca8010843482d61fda46786449a9bc99e10
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:55:52 2019 +0900

    ASoC: simple-card-utils: share asoc_simple_dai_init()
2020-08-05 04:54:46 +01:00
Hin-Tak Leung
2d08bb0b35 Revert "asoc_simple_card_init_dai is not exported, but asoc_simple_dai_init is, and does more"
This reverts commit de22f92298.

That commit was wrong: seeed_priv_to_props() is not identical to simple_priv_props().

Conflicts:
	seeed-voicecard.c
2020-08-05 04:54:46 +01:00
Hin-Tak Leung
c2f81c1f23 v5.2: comments
The init code was extracted into asoc_simple_card_init_priv(), with
additional comments.

commit 65a5056b21202eff7f54243e587183f4bb6ed352
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:56:26 2019 +0900

    ASoC: simple-card-utils: share asoc_simple_card_init_priv()

    The difference between simple-card / audio-graph are just using
    OF graph style, or not. In other words, other things should be same.
    This means, simple-card/audio-graph common functions should be
    implemented at simple-card-utils, and its own functions should be
    implemented at each files.

    Current simple-card / audio-graph are initializing each priv,
    but it is same operation.
    This patch adds new asoc_simple_card_init_priv() and initialize
    priv by same operation.
2020-08-05 04:54:38 +01:00
Hin-Tak Leung
63fa92db39 v5.3: support snd_soc_dai_link_component style for cpu
commit f107294c6422e772773b53dbf802186175b6289e
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Thu Jun 6 13:07:35 2019 +0900

    ASoC: simple-card: support snd_soc_dai_link_component style for cpu

    ASoC supports modern style dai_link (= snd_soc_dai_link_component) for
    CPU. legacy style dai_link (= cpu_dai_name, cpu_name, cpu_of_node) are
    no longer needed.
    This patch switches to modern style.
2020-08-05 02:37:32 +01:00
Hin-Tak Leung
d2c0f1b5c9 v5.1: add .num_platform for dai_link
commit 910fdcabedd2354d161b1beab6ad7dc7e859651d
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Jan 21 09:32:32 2019 +0900

    ASoC: soc-core: add .num_platform for dai_link

    Current snd_soc_dai_link is starting to use snd_soc_dai_link_component
    (= modern) style for Platform, but it is still assuming single Platform
    so far. We will need to have multi Platform support in the not far
    future.

    Currently only simple card is using it as sound card driver,
    and other drivers are converted to it from legacy style by
    snd_soc_init_platform().
    To avoid future problem of multi Platform support, let's add
    num_platforms before it is too late.

    In the same time, to make it same naming mothed, "platform" should
    be "platforms". This patch fixup it too.
2020-08-05 02:18:23 +01:00
Hin-Tak Leung
775005d865 v4.20: support snd_soc_dai_link_component style for platform
commit e58f41e41185c6906bd11c73c4e76aa5fc3ea685
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri Aug 31 03:10:33 2018 +0000

    ASoC: simple-card: support snd_soc_dai_link_component style for platform

    Current ASoC is supporting snd_soc_dai_link_component for binding,
    it is more useful than current legacy style.
    Currently only codec is supporting it as multicodec (= codecs).
    CPU will support multi style in the future.
    We want to have it on Platform too in the future.

    If all Codec/CPU/Platform are replaced into snd_soc_dai_link_component
    style, we can remove legacy complex style.
    This patch supports snd_soc_dai_link_component style
    for simple-card for platform.
2020-08-05 02:07:32 +01:00
Hin-Tak Leung
8c80018c3e v4.20: support snd_soc_dai_link_component style for codec
commit 710af9196ce614ee02185c2ec55e617a71843183
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Fri Aug 31 03:08:24 2018 +0000

    ASoC: simple-card: support snd_soc_dai_link_component style for codec

    Current ASoC is supporting snd_soc_dai_link_component for binding,
    it is more useful than current legacy style.
    Currently only codec is supporting it as multicodec (= codecs).
    CPU will support multi style in the future.
    We want to have it on Platform too in the future.

    If all Codec/CPU/Platform are replaced into snd_soc_dai_link_component
    style, we can remove legacy complex style.
    This patch supports snd_soc_dai_link_component style
    for simple-card for codec.
2020-08-05 01:42:57 +01:00
Hin-Tak Leung
076d12f7fb Revert partial-fix, in preparation for proper fix.
Revert "Fix dai_link->cpus etc used without backing storage."

This reverts commit 97146337cb.
2020-08-05 01:24:35 +01:00
Baozhu Zuo
c0f1dfa8bb Please use the 4.19 kernel first, 5.4 kernel support is still under development. 2020-08-03 09:07:51 +08:00
Hin-Tak Leung
67f7942cfd Merge remote-tracking branch 'origin/v5.5' into v5.7 2020-07-30 10:09:42 +01:00
HinTak
86c198d7dc
Merge pull request #4 from rotdrop/feature/support-ubuntu-server
Support ubuntu-server with /boot/firmware/overlays
2020-07-30 10:05:21 +01:00
HinTak
1d4abfa41d
Merge pull request #3 from rotdrop/bugfix/uninitialized-cpu-codec-platform
Fix dai_link->cpus etc used without backing storage.
2020-07-30 10:03:23 +01:00
Claus-Justus Heine
f52ed1b363 Support ubuntu-server with /boot/firmware/overlays 2020-07-29 22:26:34 +02:00
Claus-Justus Heine
97146337cb Fix dai_link->cpus etc used without backing storage. 2020-07-29 18:57:37 +02:00
Hin-Tak Leung
1046e30108 Merge remote-tracking branch 'upstream/master' into v5.5
Conflicts:
	install.sh
2020-07-25 05:37:50 +01:00
Hin-Tak Leung
97fd3f2eab Merge remote-tracking branch 'upstream/master' into v5.7
Conflicts:
	install.sh
2020-07-25 05:34:36 +01:00
Hin-Tak Leung
60d2a5129d Adjust for v5.7, "ASoC: soc-pcm: merge playback/cature_active into stream_active"
perl -pi -e 's(->capture_active)(->stream_active\[SNDRV_PCM_STREAM_CAPTURE\])g' *.c
perl -pi -e 's(->playback_active)(->stream_active\[SNDRV_PCM_STREAM_PLAYBACK\])g' *.c

commit 0f6011fd79a2fb92cb80177fd6bdc8aac3a3cd93
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Mon Feb 17 17:28:15 2020 +0900

    ASoC: soc-pcm: merge playback/cature_active into stream_active

    DAI has playback_active and capture_active to care usage count.
    OTOH, we have SNDRV_PCM_STREAM_PLAYBACK/CAPTURE.
    But because of this kind of implementation mismatch,
    ALSA SoC has many verbose code.

    To solve this issue, this patch merge playback_active/capture_active
    into stream_active[2];
2020-07-25 05:22:34 +01:00
Jack Shao
6b4133b5f0
Merge pull request #224 from HinTak/suppress-fallthrough-warning
Suppress fallthrough warning
2020-04-28 09:59:04 +08:00
Hin-Tak Leung
0ed11aa9a4 compatibility - fallthrough' pseudo keyword was introduced in v5.4
commit 294f69e662d1570703e9b56e95be37a9fd3afba5
Author: Joe Perches <joe@perches.com>
Date:   Sat Oct 5 09:46:42 2019 -0700

    compiler_attributes.h: Add 'fallthrough' pseudo keyword for switch/case use
2020-04-27 21:30:34 +01:00
Hin-Tak Leung
2e1940bb0f compatibility - fallthrough' pseudo keyword was introduced in v5.4
commit 294f69e662d1570703e9b56e95be37a9fd3afba5
Author: Joe Perches <joe@perches.com>
Date:   Sat Oct 5 09:46:42 2019 -0700

    compiler_attributes.h: Add 'fallthrough' pseudo keyword for switch/case use
2020-04-27 21:17:56 +01:00
Jack Shao
6c6dfaa7d3
Merge pull request #225 from KillingJacky/master
remove the default kernel downgrade
2020-04-27 15:26:35 +08:00
KillingJacky
468b40eee5 fix typo 2020-04-27 08:19:50 +01:00
Jack Shao
07a6c4659e
update README.md explaining the cmd line option --compat-kernel 2020-04-27 15:16:05 +08:00
KillingJacky
ad4d66d3f7 add an cmd line option for choosing compile with compatible kernel; clean up more when uninstalling 2020-04-27 07:58:47 +01:00
Hin-Tak Leung
add12477e9 use the kernel's way of suppressing fallthrough
See include/linux/compiler_attributes.h:

/*
 * Add the pseudo keyword 'fallthrough' so case statement blocks
 * must end with any of these keywords:
 *   break;
 *   fallthrough;
 *   goto <label>;
 *   return [expression];
 *
 *  gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes
 */
-if __has_attribute(__fallthrough__)
- define fallthrough                    __attribute__((__fallthrough__))
-else
- define fallthrough                    do {} while (0)  /* fallthrough */
-endif
2020-04-27 01:10:51 +01:00
Hin-Tak Leung
74d65bfcbd use the kernel's way of suppressing fallthrough
See include/linux/compiler_attributes.h:

/*
 * Add the pseudo keyword 'fallthrough' so case statement blocks
 * must end with any of these keywords:
 *   break;
 *   fallthrough;
 *   goto <label>;
 *   return [expression];
 *
 *  gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes
 */
-if __has_attribute(__fallthrough__)
- define fallthrough                    __attribute__((__fallthrough__))
-else
- define fallthrough                    do {} while (0)  /* fallthrough */
-endif
2020-04-27 01:07:51 +01:00
Hin-Tak Leung
deed034f31 suppress another "this statement may fall through" warning
The whole warning is quite long but looks like this:

  CC [M]  seeed-voicecard/ac108.o
In file included from ./include/linux/printk.h:331,
                 from ./include/linux/kernel.h:15,
                 from ./include/linux/list.h:9,
                 from ./include/linux/module.h:12,
                 from seeed-voicecard/ac108.c:15:
seeed-voicecard/ac108.c: In function ‘ac108_set_fmt’:
./include/linux/dynamic_debug.h:122:52: warning: this statement may fall through [-Wimplicit-fallthrough=]
  122 | #define __dynamic_func_call(id, fmt, func, ...) do { \
      |                                                    ^
./include/linux/dynamic_debug.h:143:2: note: in expansion of macro ‘__dynamic_func_call’
  143 |  __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
      |  ^~~~~~~~~~~~~~~~~~~
./include/linux/dynamic_debug.h:157:2: note: in expansion of macro ‘_dynamic_func_call’
  157 |  _dynamic_func_call(fmt,__dynamic_dev_dbg,   \
      |  ^~~~~~~~~~~~~~~~~~
./include/linux/device.h:1795:2: note: in expansion of macro ‘dynamic_dev_dbg’
 1795 |  dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
      |  ^~~~~~~~~~~~~~~
seeed-voicecard/ac108.c:866:4: note: in expansion of macro ‘dev_dbg’
  866 |    dev_dbg(dai->dev, "used as slave when AC101 is master\n");
      |    ^~~~~~~
seeed-voicecard/ac108.c:868:2: note: here
  868 |  case SND_SOC_DAIFMT_CBS_CFS:    /*AC108 Slave*/
      |  ^~~~
2020-04-27 00:15:00 +01:00
Hin-Tak Leung
2563020e29 suppress "this statement may fall through" warning
The semi-colon is needed, to prevent the comment being parsed as part of the "if {...}" statement.

The warning looks like this:

seeed-voicecard/wm8960.c: In function ‘wm8960_hw_params’:
seeed-voicecard/wm8960.c:752:6: warning: this statement may fall through [-Wimplicit-fallthrough=]
  752 |   if ((iface & 0x3) != 0) {
      |      ^
seeed-voicecard/wm8960.c:757:2: note: here
  757 |  default:
      |  ^~~~~~~
2020-04-27 00:14:47 +01:00
Hin-Tak Leung
30276c80bc Don't force kernel downgrade
Revert "Fix: try to use a specific version kernel & headers"

This reverts commit ae32476755.

Conflicts:
	install.sh
2020-04-26 23:47:45 +01:00
Hin-Tak Leung
82c8d1024a suppress another "this statement may fall through" warning
The whole warning is quite long but looks like this:

  CC [M]  seeed-voicecard/ac108.o
In file included from ./include/linux/printk.h:331,
                 from ./include/linux/kernel.h:15,
                 from ./include/linux/list.h:9,
                 from ./include/linux/module.h:12,
                 from seeed-voicecard/ac108.c:15:
seeed-voicecard/ac108.c: In function ‘ac108_set_fmt’:
./include/linux/dynamic_debug.h:122:52: warning: this statement may fall through [-Wimplicit-fallthrough=]
  122 | #define __dynamic_func_call(id, fmt, func, ...) do { \
      |                                                    ^
./include/linux/dynamic_debug.h:143:2: note: in expansion of macro ‘__dynamic_func_call’
  143 |  __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
      |  ^~~~~~~~~~~~~~~~~~~
./include/linux/dynamic_debug.h:157:2: note: in expansion of macro ‘_dynamic_func_call’
  157 |  _dynamic_func_call(fmt,__dynamic_dev_dbg,   \
      |  ^~~~~~~~~~~~~~~~~~
./include/linux/device.h:1795:2: note: in expansion of macro ‘dynamic_dev_dbg’
 1795 |  dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
      |  ^~~~~~~~~~~~~~~
seeed-voicecard/ac108.c:866:4: note: in expansion of macro ‘dev_dbg’
  866 |    dev_dbg(dai->dev, "used as slave when AC101 is master\n");
      |    ^~~~~~~
seeed-voicecard/ac108.c:868:2: note: here
  868 |  case SND_SOC_DAIFMT_CBS_CFS:    /*AC108 Slave*/
      |  ^~~~
2020-04-26 23:39:25 +01:00
Hin-Tak Leung
476378c156 suppress "this statement may fall through" warning
The semi-colon is needed, to prevent the comment being parsed as part of the "if {...}" statement.

The warning looks like this:

seeed-voicecard/wm8960.c: In function ‘wm8960_hw_params’:
seeed-voicecard/wm8960.c:752:6: warning: this statement may fall through [-Wimplicit-fallthrough=]
  752 |   if ((iface & 0x3) != 0) {
      |      ^
seeed-voicecard/wm8960.c:757:2: note: here
  757 |  default:
      |  ^~~~~~~
2020-04-26 23:27:54 +01:00
Hin-Tak Leung
4c15036368 copy asoc_simple_card_parse_dai() from v5.4:sound/soc/generic/simple-card.c
Towards the end of the series in asoc-v5.2:

commit 8f7f298a333761a528e103cda3b42f3a416ad1ee
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:56:36 2019 +0900

    ASoC: simple-card-utils: separate asoc_simple_card_parse_dai()

    The difference between simple-card / audio-graph are just using
    OF graph style, or not. In other words, other things should be same.
    This means, simple-card/audio-graph common functions should be
    implemented at simple-card-utils, and its own functions should be
    implemented at each files.

    Current simple-card / audio-graph are using
    asoc_simple_card_parse_dai() which is different implementation.
    But, these are implemanted at simple-card-utils.
    It should be implemanted at each files.
    This patch separate these into each files.

$ git log --format=oneline 0580dde59438686d60762b6da9229ebec693b94f^..ad11e59f52d6fc75037ac3cb66dc711b83c1bbf8
ad11e59f52d6fc75037ac3cb66dc711b83c1bbf8 ASoC: simple-card-utils: rename asoc_simple_card_xxx() to asoc_simple_()
8f7f298a333761a528e103cda3b42f3a416ad1ee ASoC: simple-card-utils: separate asoc_simple_card_parse_dai()
65a5056b21202eff7f54243e587183f4bb6ed352 ASoC: simple-card-utils: share asoc_simple_card_init_priv()
629f75440a68220a78aef9d8569831824890c47d ASoC: simple-card-utils: share asoc_simple_be_hw_params_fixup()
ad934ca8010843482d61fda46786449a9bc99e10 ASoC: simple-card-utils: share asoc_simple_dai_init()
f48dcbb6d47d870cf3a03f453c923dd262158c66 ASoC: simple-card-utils: share asoc_simple_hw_param()
686911b46fb5a08df142fe22b6c06dc6fbd3ba65 ASoC: simple-card-utils: share asoc_simple_shutdown()
f38df5bf0c9cb905fa9d5abc86c3a00128cdbba5 ASoC: simple-card-utils: share asoc_simple_startup()
e59289cda8dec0153fa396864c8ba8092ec3b80d ASoC: simple_card_utils: share common priv for simple-card/audio-graph
0580dde59438686d60762b6da9229ebec693b94f ASoC: simple-card-utils: add asoc_simple_debug_info()
2020-04-26 22:48:50 +01:00
Hin-Tak Leung
cb9bf1c913 adjust for changes in aux_dev
In 5.4:

commit a48b561d873d1d9fda55782d275eff94ec647863
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Thu Aug 8 14:54:39 2019 +0900

    ASoC: soc-core: remove legacy style of aux_dev
2020-04-24 05:13:41 +01:00
Hin-Tak Leung
37a37a6d16 adjust for modern style dai_link
In v5.3:

commit f107294c6422e772773b53dbf802186175b6289e
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Thu Jun 6 13:07:35 2019 +0900

    ASoC: simple-card: support snd_soc_dai_link_component style for cpu
2020-04-24 04:58:58 +01:00
Hin-Tak Leung
de22f92298 asoc_simple_card_init_dai is not exported, but asoc_simple_dai_init is, and does more
In v5.2:

commit ad934ca8010843482d61fda46786449a9bc99e10
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:55:52 2019 +0900

    ASoC: simple-card-utils: share asoc_simple_dai_init()
2020-04-24 04:33:49 +01:00
Hin-Tak Leung
72d3c9e2f6 DAI and CELL not used in macros.
In v5.2:

commit 8f7f298a333761a528e103cda3b42f3a416ad1ee
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:56:36 2019 +0900

    ASoC: simple-card-utils: separate asoc_simple_card_parse_dai()
2020-04-24 04:03:19 +01:00
Hin-Tak Leung
b9272dcee8 asoc_simple_card_canonicalize_platform returns void, and always successful
In v5.1:

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.
2020-04-24 03:50:41 +01:00
Hin-Tak Leung
61022875b3 asoc_simple_canonicalize_dailink() to asoc_simple_canonicalize_platform()
In v5.1:

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()
2020-04-24 03:43:13 +01:00
Hin-Tak Leung
41c71f1b45 rename asoc_simple_card_xxx() to asoc_simple_()
First appeared in v5.2:

commit ad11e59f52d6fc75037ac3cb66dc711b83c1bbf8
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date:   Wed Mar 20 13:56:50 2019 +0900

    ASoC: simple-card-utils: rename asoc_simple_card_xxx() to asoc_simple_()
2020-04-24 03:35:45 +01:00
Hin-Tak Leung
8c5ffaeed3 LINUX_VERSION_IS_GEQ macro from Linux kernel backports package 2020-04-24 02:27:58 +01:00
hhuysqt
920ef83b63 Add: compatible to linux kernel 5.3.0 or higher 2020-03-30 12:23:36 +08:00
HinTak
48463b9a50 Correct typo
Fix typo in comment.
2020-03-30 09:01:36 +08:00
mxklb
2da704e872 Check for enough space on /boot volume (check #209) 2020-02-15 16:38:04 +08:00
HinTak
d6f808b278 fix typo 2020-01-29 14:32:30 +08:00
SamhithPottem
873580cfd5 Update install.sh (#182) to --force-yes install 2019-10-23 11:16:55 +08:00
turmary
ae32476755 Fix: try to use a specific version kernel & headers 2019-10-22 15:59:07 +01:00
Baozhu Zuo
277aeacb81
The latest kernel of raspberry PI is unstable, so do this anyway to make sure the driver loads correctly 2019-07-25 19:39:07 +08:00
Baozhu Zuo
08f0d96d68
raspberry pi 4 use the v7l+ suffix as the kernel identifier 2019-07-25 19:30:04 +08:00
turmary
da5f90473b Fix: removing asound.conf when detecting i2c addresses 2019-05-22 10:39:09 +08:00
turmary
0ea5d2bd98 Fix: dtoverlay on Linux v4.19 failed in phandle insertion 2019-05-21 12:18:25 +08:00
Baozhu Zuo
c7026a4048
remove sleep , accelerate the seeed-voicecard service startup 2019-04-17 14:58:21 +08:00
Baozhu Zuo
11e9db79b5
remove sleep , accelerate the seeed-voicecard service startup 2019-04-17 14:58:07 +08:00
turmary
90d2673610 Add: kernel headers checking after action rpi-update 2019-04-16 09:34:10 +08:00
Norbert Preining
09728d1c82 allow installation in qemu
Currently, installation is only supported on real hardware, but not
running in QEMU. Change the check to make sure the necessary
directories and programs are available instead of bailing out
on non-Raspberry archs.
2019-03-30 14:19:47 +08:00
respeaker
b98fce84e0 Add: compatible to linux-4.18 or higher 2019-03-14 03:13:25 +00:00
Pernat1y
6c6b9ab7de Install packages for Arch Linux 2019-01-28 09:23:40 +08:00
Pernat1y
27b6cdf252 Make grep searches more precise 2019-01-28 09:23:40 +08:00
Baozhu Zuo
f5b82b6b7d
Merge pull request #123 from baorepo/patch-1
test hardware mic phase position
2018-12-25 09:37:27 +08:00
Baozhu Zuo
5744fd1bbb
test hardware mic phase position
baozhu@bz:/tmp$ python wave_test.py record.wav 
2
['448.8125', '446.65625', '-0.1875', '330.8125', '448.375', '450.59375', '451.0']
['448.78125', '448.5625', '-0.1875', '-0.125', '448.3125', '-0.125', '-450.78125']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.0625', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.25']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.25']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.25']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.25']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '0.21875']
['0.0', '0.0', '0.0', '-0.09375', '-0.09375', '-0.09375', '-0.96875']
['0.03125', '0.0', '-0.0625', '-0.09375', '-0.0625', '-0.09375', '-23.0625']
['0.0', '0.0', '-0.0625', '-0.09375', '-0.0625', '-0.09375', '-23.125']
done
48000
2018-12-25 09:36:27 +08:00
turmary
95f4fe0688 Fix: remove spin lock in machine trigger 2018-11-27 09:47:44 +00:00
turmary
3392bf394b Fix: try to stop aif clock in thread environment 2018-11-07 18:33:55 -10:00
turmary
0965139ead Optimize: simplify AC101 debug message 2018-11-07 15:29:06 -10:00
Jack Shao
be0812c70b update: more convenient way to apply udev rules 2018-10-11 17:54:51 +08:00
KillingJacky
dfc7b404a5 change asound.state for 4mic array, lower down PGA to reduce static noise 2018-09-29 14:49:19 +08:00
Baozhu Zuo
deeddaabb4
seeed-voicecard: if the board detect seeed-voicecard then resetup asound.conf and asound.state 2018-09-29 14:36:01 +08:00
Yihui Xiong
bfe6978ef4 update 6 mic gain controls 2018-08-06 06:32:46 +00:00
Yihui Xiong
67b4504964
Update asound_6mic.conf 2018-08-01 18:54:25 +08:00
Baozhu Zuo
bca16c68c4
Update README.md 2018-07-30 15:51:18 +08:00
Baozhu Zuo
ab0b28d08f
Update README.md 2018-07-30 15:44:47 +08:00
Baozhu Zuo
a73335b8d0
Merge pull request #92 from respeaker/dev
Dev
2018-07-26 08:58:15 +08:00
Baozhu Zuo
58c6233325 use sound card id 2018-07-24 11:39:01 +08:00
Baozhu Zuo
f85c98c4e0 4mic doesnt have output interface, delete it 2018-07-24 11:38:38 +08:00
Baozhu Zuo
7009515ec9 use link to replase copy operation 2018-07-24 11:31:21 +08:00
Baozhu Zuo
8c499c2268 create git repo to manage voicecard configs 2018-07-24 11:30:22 +08:00
Baozhu Zuo
9a9f4368b4 use card id to identify cards 2018-07-24 11:28:55 +08:00
Baozhu Zuo
3d56af9d3c
Merge pull request #78 from respeaker/pulse
Merge seeed-voicecard pulseaudio settings
2018-05-30 10:46:42 +08:00
jerryyip
3074de1f86 init 2018-05-30 10:36:10 +08:00
jerryyip
33ddbd39d3 init pulse setting 2018-05-29 19:15:32 +08:00
Peter.Yang
983d4834bb Optimize: doc about software pcm ac101 2018-05-21 09:52:38 +00:00
turmary
a8d0a23583 Fix: ac101 i2c accessing is too often. 2018-05-21 03:33:46 +00:00
Peter.Yang
ccac09b842 Fix: reset ac101/ac108 chips after fill cache 2018-05-11 07:37:53 +00:00
turmary
0548a6d0a3 Fix: close work_switch when codec removeing 2018-04-24 04:28:14 +00:00
Peter.Yang
d0d9107c91 Move: simple-audio-card -> seeed-voicecard, module removing & inserting again supported 2018-04-04 09:36:18 +00:00
Peter.Yang
d660a92d73 Add: headset detection for 6-Mics Circular Array Kit and 4-Mics Linear Array Kit 2018-04-02 08:43:20 +00:00
Peter.Yang
8211f4c000 Fix: 4MIC recording by portaudio & pyaudio 2018-04-02 07:59:17 +00:00
Baozhu Zuo
86329f0719 Fix 2mic hat install failed 2018-03-30 03:21:40 +00:00
Peter.Yang
031bbb3a1a Fix: simple-card adapt to kernel version 4.9 & 4.14 2018-03-30 02:37:57 +00:00
Peter.Yang
80e0478c91 Update: doc about limit for doing capture & playback the same time 2018-03-29 08:29:55 +00:00
Peter.Yang
860d38fc47 Fix: i2c access fail when AC108 as master, support make DEBUG=1 2018-03-27 03:13:53 +00:00
Peter.Yang
1901914b56 Fix: limit of capture starting first. 2018-03-24 12:22:02 +00:00
Peter.Yang
7e1f29af35 Fix: clear the "PuPu" noise again after ac101 as Master 2018-03-24 11:05:46 +00:00
Peter.Yang
d3d95d0296 Fix: i2c access fail & channels miss order 2018-03-24 10:01:33 +00:00
Peter.Yang
22f495491a Fix: ac101 as master, ac108 pll source from ac101 bclk 2018-03-23 03:25:52 +00:00
Peter.Yang
235485652b Optimize: names & disable sample rate 96K 2018-03-13 08:30:43 +00:00
Peter.Yang
9dce807fb7 Fix: clear the "PuPu" noise at the very beginning of playback 2018-03-13 03:40:16 +00:00
Peter.Yang
d6744a76d2 Update: coherence picture 2018-03-12 10:05:37 +00:00
Peter.Yang
829ae64abe Add: Doc & tools about coherence 2018-03-12 06:39:43 +00:00
Peter.Yang
a98c728f33 Add: Doc pictures of 6-mics circular array kit/4-mics linear array kit 2018-03-09 06:47:06 +00:00
Peter.Yang
6b6552bf9c Move: ac101 pll clock source set to bclk if it's slave mode 2018-03-07 06:34:33 +00:00
Peter.Yang
cff392127f Fix: ac101 noise import by PLL frequncy deviation 2018-03-06 09:37:14 +00:00
Peter.Yang
0d30a1599d Add: Doc for 6-Mics Circular Array Kit & 4-Mics Linear Array Kit 2018-03-02 09:28:01 +00:00
Peter.Yang
0f5ff56d1e Add: append plug for 4mic pcm ac108 2018-02-27 09:12:42 +00:00
Peter.Yang
b8f9bb38fd Move: register access from i2c_master_XXX to regmap_XXX 2018-02-27 09:05:55 +00:00
Peter.Yang
2f31ac4ea4 Fix: ac101 stereo widgets get/put interface 2018-02-27 02:58:10 +00:00
Peter.Yang
00d123836f Fix: channels widgets order for 6mic 2018-02-25 09:51:37 +00:00
Peter.Yang
d225c664d7 Fix: asound configuration for pcm ac108 2018-02-25 02:42:50 +00:00
Baozhu Zuo
b462e8a724 fix i2c cannt auto load on raspbian lite os 2018-02-16 16:01:47 +08:00
Peter.Yang
e2266a2791 Fix: service configuration error for asound.conf 2018-02-11 14:29:10 +00:00
Peter.Yang
12d155f6ea Add: 4mic OK after merge 2018-02-10 08:57:30 +00:00
peter.yang
1c1643003f Merge tracking branch 'install' to probe drivers by appliation. 2018-02-10 15:18:47 +08:00
peter.yang
18eec1abfa Merge: ac108 & ac101 as single codec module 2018-02-10 15:16:01 +08:00
peter.yang
fa4b566d9a Move: rename ac108 -> ac10x 2018-02-10 11:36:18 +08:00
peter.yang
560008e8fd Remove: not used code 2018-02-07 17:35:12 +08:00
peter.yang
cf52966d00 Add: multi codec support in simple-card 2018-02-07 14:02:45 +08:00
peter.yang
edb5a1da65 Merge: ac108 work for 4mic & 8mic 2018-02-05 10:45:55 +08:00
Baozhu Zuo
3fdc0c4345
Update README.md 2018-02-01 16:52:35 +08:00
Baozhu Zuo
3a0a0e8b57
Update README.md 2018-02-01 16:42:49 +08:00
Baozhu Zuo
f49d896613 update readme add dkms version 2018-02-01 16:07:26 +08:00
Baozhu Zuo
73ff8fe114 add seeed-voicecard manger service 2018-02-01 16:07:02 +08:00
Baozhu Zuo
8b84b891cd use seeed-voicecard service to manager all the card
Changes to be committed:
	modified:   install.sh
	modified:   uninstall.sh
2018-02-01 16:04:31 +08:00
Baozhu Zuo
7170b7fcb2 change dmix to plughw to playback 2018-02-01 15:57:45 +08:00
peter.yang
add8afa699 Add: capturing & playing in Audacity is OK 2018-01-30 19:19:13 +08:00
peter.yang
995c17c160 Add: export start-clock interface in ac101 to simple-card 2018-01-30 19:12:47 +08:00
peter.yang
10e0f12b16 Fix: master device same as codec device 2018-01-30 19:07:57 +08:00
peter.yang
d8b60f1116 Bugfix: crash due to device probing order 2018-01-29 19:14:28 +08:00
peter.yang
780db6f6ab Add: speaker out is OK 2018-01-26 11:08:09 +08:00
peter.yang
b032c0664d Add: ac101 dsp_a mode, tdm enabled, 8 slot, 32bit OK 2018-01-24 20:18:58 +08:00
peter.yang
56da9a526c Bugfix: AC101 miss channels order in cpu_dai, channel map IN(0,1,2,3,4,5,6,7)->OUT(2,3,4,5,6,7,0,1) 2018-01-23 16:46:15 +08:00
peter.yang
c3367740d5 Remove: widgets and routes isnt for volume controlling 2018-01-23 16:19:00 +08:00
peter.yang
156697545a Remove: switch detecting 2018-01-22 16:08:32 +08:00
peter.yang
aec1941ae1 Add: ac101 dsp_a mode, playing 2 in 8 channels OK 2018-01-19 19:25:15 +08:00
peter.yang
7aae0e3353 add original ac101 reference driver 2018-01-12 16:37:28 +08:00
root
188be2636f Fix: API name to DECLARE_TLV_DB_RANGE 2017-12-15 07:47:08 +00:00
peter.yang
a62c615114 Add capturing volume controls 2017-11-29 09:17:52 +00:00
peter.yang
0cb24e58d2 Fix: pcm playback & capture stream can work together,
all with 8 channels.
2017-11-23 10:15:59 +00:00
peter.yang
07b67878dc Add 2 channels playback stream 2017-11-22 09:05:22 +00:00
peter.yang
5607fed986 override channels in dts setting 2017-11-22 07:33:59 +00:00
peter.yang
878027066d Bugfix: miss channels order in cpu_dai 2017-11-20 01:22:28 +00:00
peter.yang
5028a91201 pcm format 8 channels, using two ac108 chips 2017-11-16 06:57:55 +00:00
peter.yang
7f4b5849a7 pcm format 4 channels: no need ac108_plugin 2017-11-10 09:00:23 +00:00
peter.yang
3fd4021f45 Add original RPI simple-card driver 2017-11-10 08:52:24 +00:00
Baozhu Zuo
b9d9cde471 Merge pull request #12 from Lance0312/create-alsa-lib
Copy shared library using install -D
2017-10-24 22:17:58 +08:00
Lance Chen
8094f7c3ab
Copy shared library using install -D
/usr/lib/arm-linux-gnueabihf/alsa-lib/ might not exist
2017-10-24 21:42:24 +08:00
Baozhu Zuo
3fed3fdc8a asound.conf is different between 2mic and 4mic 2017-10-18 15:51:54 +08:00
Baozhu Zuo
9e6b2472e3 Merge pull request #11 from respeaker/dev
merge dev branch
2017-10-09 15:02:08 +08:00
Baozhu Zuo
76a0140513 remove ac108 debug macro 2017-10-09 15:00:40 +08:00
Baozhu Zuo
12bac6756a remove debug message, increase ac108 buf size 2017-10-09 14:58:35 +08:00
Baozhu Zuo
b28887adab add ac108_help to makefile 2017-10-09 14:57:05 +08:00
Baozhu Zuo
125e5188e5 use two channel transfer 4 channels, rate should be double 2017-10-09 14:56:26 +08:00
Baozhu Zuo
3c4fc91f89 use the real rate value config clocking 2017-10-09 11:14:27 +08:00
Baozhu Zuo
932d2ab1c5 add some helper function 2017-09-30 16:01:18 +08:00
Baozhu Zuo
f362cdd383 enable chosen single channel 2017-09-30 16:00:07 +08:00
Baozhu Zuo
6a0b216dbf enable High Pass Filter 2017-09-30 15:58:30 +08:00
Yihui Xiong
b142dc56fc Update README.md 2017-09-28 21:26:48 -05:00
Yihui Xiong
cde3b55c1f Update README.md 2017-09-28 21:21:47 -05:00
Baozhu Zuo
9884e01dfd Update README.md 2017-09-27 11:18:27 +08:00
Baozhu Zuo
5863e7d3ac add uninstall.sh script 2017-09-27 03:14:19 +00:00
Baozhu Zuo
0aae7a6ea6 miss 4 channels, set clock fixed 2017-09-26 15:11:21 +00:00
Baozhu Zuo
51fbe557f3 fix cannt get uname_r 2017-09-22 18:12:17 +08:00
Baozhu Zuo
41fbb892b9 Merge pull request #8 from yexiaobo-seeedstudio/master
update readme and highlight syntax
2017-09-18 14:58:34 +08:00
Xiaobo
7fdad37206 update readme and highlight syntax 2017-09-18 14:31:53 +08:00
Baozhu Zuo
5baa9289cf ac108_plugin version 1: only support channel=4 2017-09-18 09:40:50 +08:00
Baozhu Zuo
45932231a7 Create LICENSE 2017-09-15 10:14:31 +08:00
Baozhu Zuo
cc6185e587 update readme 2017-09-15 10:04:29 +08:00
Baozhu Zuo
d454f0df21 optimize some options 2017-09-15 02:01:53 +00:00
Baozhu Zuo
af15d8c5a0 Merge pull request #7 from respeaker/dev
merage dev branch
2017-09-14 20:24:05 +08:00
Baozhu Zuo
eee3db3733 update readme 2017-09-14 20:22:02 +08:00
Baozhu Zuo
baaecb8b7d update ac108_asound.state asound.conf 2017-09-14 20:14:10 +08:00
Baozhu Zuo
9a97f5033f change some dtparam to dtoverlay 2017-09-14 20:03:17 +08:00
Baozhu Zuo
b4c2dba036 optmize some selections 2017-09-14 11:37:50 +00:00
Baozhu Zuo
1d7ef19938 only allow one card 2017-09-14 10:39:38 +00:00
Baozhu Zuo
32d80ed5a4 change the install dir 2017-09-14 09:26:20 +00:00
Baozhu Zuo
448f135c53 install 2mic or 4mic 2017-09-14 09:26:04 +00:00
Baozhu Zuo
c6d4885aeb merage ac108_asound.conf and wm8960_asound.conf together 2017-09-14 08:45:38 +00:00
Baozhu Zuo
d764c26a2d install libasound_module_pcm_ac108.so 2017-09-14 08:44:40 +00:00
Baozhu Zuo
5b49bfb4ec add respeaker 4mic audio card driver 2017-09-14 08:29:26 +00:00
53 changed files with 10101 additions and 136 deletions

674
LICENSE Normal file
View file

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View file

@ -1,11 +1,52 @@
obj-m := wm8960.o
#
# Peter Yang <turmary@126.com>
# Copyright (c) 2019 Seeed Studio
#
# MIT License
#
uname_r=$(shell uname -r)
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language
ifneq ($(KERNELRELEASE),)
# $(warning KERNELVERSION=$(KERNELVERSION))
snd-soc-wm8960-objs := wm8960.o
snd-soc-ac108-objs := ac108.o ac101.o
snd-soc-seeed-voicecard-objs := seeed-voicecard.o
obj-m += snd-soc-wm8960.o
obj-m += snd-soc-ac108.o
obj-m += snd-soc-seeed-voicecard.o
ifdef DEBUG
ifneq ($(DEBUG),0)
ccflags-y += -DDEBUG -DAC101_DEBG
endif
endif
else
DEST := /lib/modules/$(uname_r)/kernel
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
make -C /lib/modules/$(uname_r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
make -C /lib/modules/$(uname_r)/build M=$(PWD) clean
install:
sudo cp wm8960.ko /lib/modules/$(shell uname -r)
sudo cp snd-soc-ac108.ko ${DEST}/sound/soc/codecs/
sudo cp snd-soc-wm8960.ko ${DEST}/sound/soc/codecs/
sudo cp snd-soc-seeed-voicecard.ko ${DEST}/sound/soc/bcm/
sudo depmod -a
.PHONY: all clean install
endif

View file

@ -1,59 +1,64 @@
# 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.
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.
Get the seeed voice card source code.
```
git clone https://github.com/respeaker/seeed-voicecard
### Install seeed-voicecard
Get the seeed voice card source code and install all linux kernel drivers
```bash
git clone https://github.com/HinTak/seeed-voicecard
cd seeed-voicecard
sudo ./install.sh
reboot
sudo reboot
```
## ReSpeaker Documentation
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)
### Coherence
Estimate the magnitude squared coherence using Welchs method.
![4-mics-linear-array-kit coherence](https://user-images.githubusercontent.com/3901856/37277486-beb1dd96-261f-11e8-898b-84405bfc7cea.png)
Note: 'CO 1-2' means the coherence between channel 1 and channel 2.
```bash
# How to get the coherence of the captured audio(a.wav for example).
sudo apt install python-numpy python-scipy python-matplotlib
python tools/coherence.py a.wav
# Requirement of the input audio file:
- format: WAV(Microsoft) signed 16-bit PCM
- channels: >=2
```
Check that the sound card name matches the source code seeed-voicecard.
### uninstall seeed-voicecard
If you want to upgrade the driver , you need uninstall the driver first.
```
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: seeedvoicecard [seeed-voicecard], device 0: bcm2835-i2s-wm8960-hifi wm8960-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
pi@raspberrypi:~/seeed-voicecard$
pi@raspberrypi:~/seeed-voicecard $ sudo ./uninstall.sh
...
------------------------------------------------------
Please reboot your raspberry pi to apply all settings
Thank you!
------------------------------------------------------
```
Next apply the alsa controls setting
```
sudo alsactl --file=asound.state restore
```
If you want to change the alsa settings, You can use `sudo alsactl --file=asound.state store` to save it.
Test:
```
arecord -f cd -Dhw:1 | aplay -Dhw:1
```
### with Google Assistant
if you run the assistant but the playback is speed up considerably, try to configure alsa:
```
sudo cp asound.conf /etc/asound.conf
```
If the alsa configuration doesn't solve the issue, try to use pulseaudio. See [#4](https://github.com/respeaker/seeed-voicecard/issues/4)
Enjoy !
### 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).

1701
ac101.c Normal file

File diff suppressed because it is too large Load diff

432
ac101_regs.h Normal file
View file

@ -0,0 +1,432 @@
/*
* ac101_regs.h
*
* (C) Copyright 2017-2018
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
*
* PeterYang <linsheng.yang@seeed.cc>
*
* (C) Copyright 2010-2017
* Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
* huangxin <huangxin@reuuimllatech.com>
*
* some simple description for this code
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*/
#ifndef __AC101_REGS_H__
#define __AC101_REGS_H__
/*pll source*/
#define AC101_MCLK1 1
#define AC101_MCLK2 2
#define AC101_BCLK1 3
#define AC101_BCLK2 4
#define AIF1_CLK 1
#define AIF2_CLK 2
#define CHIP_AUDIO_RST 0x0
#define PLL_CTRL1 0x1
#define PLL_CTRL2 0x2
#define SYSCLK_CTRL 0x3
#define MOD_CLK_ENA 0x4
#define MOD_RST_CTRL 0x5
#define AIF_SR_CTRL 0x6
#define AIF1_CLK_CTRL 0x10
#define AIF1_ADCDAT_CTRL 0x11
#define AIF1_DACDAT_CTRL 0x12
#define AIF1_MXR_SRC 0x13
#define AIF1_VOL_CTRL1 0x14
#define AIF1_VOL_CTRL2 0x15
#define AIF1_VOL_CTRL3 0x16
#define AIF1_VOL_CTRL4 0x17
#define AIF1_MXR_GAIN 0x18
#define AIF1_RXD_CTRL 0x19
#define ADC_DIG_CTRL 0x40
#define ADC_VOL_CTRL 0x41
#define ADC_DBG_CTRL 0x42
#define HMIC_CTRL1 0x44
#define HMIC_CTRL2 0x45
#define HMIC_STS 0x46
#define DAC_DIG_CTRL 0x48
#define DAC_VOL_CTRL 0x49
#define DAC_DBG_CTRL 0x4a
#define DAC_MXR_SRC 0x4c
#define DAC_MXR_GAIN 0x4d
#define ADC_APC_CTRL 0x50
#define ADC_SRC 0x51
#define ADC_SRCBST_CTRL 0x52
#define OMIXER_DACA_CTRL 0x53
#define OMIXER_SR 0x54
#define OMIXER_BST1_CTRL 0x55
#define HPOUT_CTRL 0x56
#define ESPKOUT_CTRL 0x57
#define SPKOUT_CTRL 0x58
#define LOUT_CTRL 0x59
#define ADDA_TUNE1 0x5a
#define ADDA_TUNE2 0x5b
#define ADDA_TUNE3 0x5c
#define HPOUT_STR 0x5d
/*CHIP_AUDIO_RST*/
#define AC101_CHIP_ID 0x0101
/*PLL_CTRL1*/
#define DPLL_DAC_BIAS 14
#define PLL_POSTDIV_M 8
#define CLOSE_LOOP 6
#define INT 0
/*PLL_CTRL2*/
#define PLL_EN 15
#define PLL_LOCK_STATUS 14
#define PLL_PREDIV_NI 4
#define PLL_POSTDIV_NF 0
/*SYSCLK_CTRL*/
#define PLLCLK_ENA 15
#define PLLCLK_SRC 12
#define AIF1CLK_ENA 11
#define AIF1CLK_SRC 8
#define AIF2CLK_ENA 7
#define AIF2CLK_SRC 4
#define SYSCLK_ENA 3
#define SYSCLK_SRC 0
/*MOD_CLK_ENA*/
#define MOD_CLK_AIF1 15
#define MOD_CLK_AIF2 14
#define MOD_CLK_AIF3 13
#define MOD_CLK_SRC1 11
#define MOD_CLK_SRC2 10
#define MOD_CLK_HPF_AGC 7
#define MOD_CLK_HPF_DRC 6
#define MOD_CLK_ADC_DIG 3
#define MOD_CLK_DAC_DIG 2
/*MOD_RST_CTRL*/
#define MOD_RESET_CTL 0
#define MOD_RESET_AIF1 15
#define MOD_RESET_AIF2 14
#define MOD_RESET_AIF3 13
#define MOD_RESET_SRC1 11
#define MOD_RESET_SRC2 10
#define MOD_RESET_HPF_AGC 7
#define MOD_RESET_HPF_DRC 6
#define MOD_RESET_ADC_DIG 3
#define MOD_RESET_DAC_DIG 2
/*AIF_SR_CTRL*/
#define AIF1_FS 12 //AIF1 Sample Rate
#define AIF2_FS 8 //AIF2 Sample Rate
#define SRC1_ENA 3
#define SRC1_SRC 2
#define SRC2_ENA 1
#define SRC2_SRC 0
/*AIF1LCK_CTRL*/
#define AIF1_MSTR_MOD 15
#define AIF1_BCLK_INV 14
#define AIF1_LRCK_INV 13
#define AIF1_BCLK_DIV 9
#define AIF1_LRCK_DIV 6
#define AIF1_WORK_SIZ 4
#define AIF1_DATA_FMT 2
#define DSP_MONO_PCM 1
#define AIF1_TDMM_ENA 0
/*AIF1_ADCDAT_CTRL*/
#define AIF1_AD0L_ENA 15
#define AIF1_AD0R_ENA 14
#define AIF1_AD1L_ENA 13
#define AIF1_AD1R_ENA 12
#define AIF1_AD0L_SRC 10
#define AIF1_AD0R_SRC 8
#define AIF1_AD1L_SRC 6
#define AIF1_AD1R_SRC 4
#define AIF1_ADCP_ENA 3
#define AIF1_ADUL_ENA 2
#define AIF1_SLOT_SIZ 0
/*AIF1_DACDAT_CTRL*/
#define AIF1_DA0L_ENA 15
#define AIF1_DA0R_ENA 14
#define AIF1_DA1L_ENA 13
#define AIF1_DA1R_ENA 12
#define AIF1_DA0L_SRC 10
#define AIF1_DA0R_SRC 8
#define AIF1_DA1L_SRC 6
#define AIF1_DA1R_SRC 4
#define AIF1_DACP_ENA 3
#define AIF1_DAUL_ENA 2
#define AIF1_SLOT_SIZ 0
/*AIF1_MXR_SRC*/
#define AIF1_AD0L_AIF1_DA0L_MXR 15
#define AIF1_AD0L_AIF2_DACL_MXR 14
#define AIF1_AD0L_ADCL_MXR 13
#define AIF1_AD0L_AIF2_DACR_MXR 12
#define AIF1_AD0R_AIF1_DA0R_MXR 11
#define AIF1_AD0R_AIF2_DACR_MXR 10
#define AIF1_AD0R_ADCR_MXR 9
#define AIF1_AD0R_AIF2_DACL_MXR 8
#define AIF1_AD1L_AIF2_DACL_MXR 7
#define AIF1_AD1L_ADCL_MXR 6
#define AIF1_AD1L_MXR_SRC 6
#define AIF1_AD1R_AIF2_DACR_MXR 3
#define AIF1_AD1R_ADCR_MXR 2
#define AIF1_AD1R_MXR_SRC 2
/*AIF1_VOL_CTRL1*/
#define AIF1_AD0L_VOL 8
#define AIF1_AD0R_VOL 0
/*AIF1_VOL_CTRL2*/
#define AIF1_AD1L_VOL 8
#define AIF1_AD1R_VOL 0
/*AIF1_VOL_CTRL3*/
#define AIF1_DA0L_VOL 8
#define AIF1_DA0R_VOL 0
/*AIF1_VOL_CTRL4*/
#define AIF1_DA1L_VOL 8
#define AIF1_DA1R_VOL 0
/*AIF1_MXR_GAIN*/
#define AIF1_AD0L_MXR_GAIN 12
#define AIF1_AD0R_MXR_GAIN 8
#define AIF1_AD1L_MXR_GAIN 6
#define AIF1_AD1R_MXR_GAIN 2
/*AIF1_RXD_CTRL*/
#define AIF1_N_DATA_DISCARD 8
/*ADC_DIG_CTRL*/
#define ENAD 15
#define ENDM 14
#define ADFIR32 13
#define ADOUT_DTS 2
#define ADOUT_DLY 1
/*ADC_VOL_CTRL*/
#define ADC_VOL_L 8
#define ADC_VOL_R 0
/*ADC_DBG_CTRL*/
#define ADSW 15
#define DMIC_CLK_PIN_CTRL 12
/*HMIC_CTRL1*/
#define HMIC_M 12
#define HMIC_N 8
#define HMIC_DATA_IRQ_MODE 7
#define HMIC_TH1_HYSTERESIS 5
#define HMIC_PULLOUT_IRQ 4
#define HMIC_PLUGIN_IRQ 3
#define HMIC_KEYUP_IRQ 2
#define HMIC_KEYDOWN_IRQ 1
#define HMIC_DATA_IRQ_EN 0
/*HMIC_CTRL2*/
#define HMIC_SAMPLE_SELECT 14
#define HMIC_TH2_HYSTERESIS 13
#define HMIC_TH2 8
#define HMIC_SF 6
#define KEYUP_CLEAR 5
#define HMIC_TH1 0
/*HMIC_STS*/
#define HMIC_DATA 8
#define GET_HMIC_DATA(r) (((r) >> HMIC_DATA) & 0x1F)
#define HMIC_PULLOUT_PEND 4
#define HMIC_PLUGIN_PEND 3
#define HMIC_KEYUP_PEND 2
#define HMKC_KEYDOWN_PEND 1
#define HMIC_DATA_PEND 0
#define HMIC_PEND_ALL (0x1F)
/*DAC_DIG_CTRL*/
#define ENDA 15
#define ENHPF 14
#define DAFIR32 13
#define MODQU 8
/*DAC_VOL_CTRL*/
#define DAC_VOL_L 8
#define DAC_VOL_R 0
/*DAC_DBG_CTRL*/
#define DASW 15
#define ENDWA_N 14
#define DAC_MOD_DBG 13
#define DAC_PTN_SEL 6
#define DVC 0
/*DAC_MXR_SRC*/
#define DACL_MXR_AIF1_DA0L 15
#define DACL_MXR_AIF1_DA1L 14
#define DACL_MXR_AIF2_DACL 13
#define DACL_MXR_ADCL 12
#define DACL_MXR_SRC 12
#define DACR_MXR_AIF1_DA0R 11
#define DACR_MXR_AIF1_DA1R 10
#define DACR_MXR_AIF2_DACR 9
#define DACR_MXR_ADCR 8
#define DACR_MXR_SRC 8
/*DAC_MXR_GAIN*/
#define DACL_MXR_GAIN 12
#define DACR_MXR_GAIN 8
/*ADC_APC_CTRL*/
#define ADCREN 15
#define ADCRG 12
#define ADCLEN 11
#define ADCLG 8
#define MBIASEN 7
#define MMIC_BIAS_CHOP_EN 6
#define MMIC_BIAS_CHOP_CKS 4
#define HBIASMOD 2
#define HBIASEN 1
#define HBIASADCEN 0
/*ADC_SRC*/
#define RADCMIXMUTEMIC1BOOST (13)
#define RADCMIXMUTEMIC2BOOST (12)
#define RADCMIXMUTELINEINLR (11)
#define RADCMIXMUTELINEINR (10)
#define RADCMIXMUTEAUXINR (9)
#define RADCMIXMUTEROUTPUT (8)
#define RADCMIXMUTELOUTPUT (7)
#define LADCMIXMUTEMIC1BOOST (6)
#define LADCMIXMUTEMIC2BOOST (5)
#define LADCMIXMUTELINEINLR (4)
#define LADCMIXMUTELINEINL (3)
#define LADCMIXMUTEAUXINL (2)
#define LADCMIXMUTELOUTPUT (1)
#define LADCMIXMUTEROUTPUT (0)
/*ADC_SRCBST_CTRL*/
#define MIC1AMPEN 15
#define ADC_MIC1G 12
#define MIC2AMPEN 11
#define ADC_MIC2G 8
#define MIC2SLT 7
#define LINEIN_PREG 4
#define AUXI_PREG 0
/*OMIXER_DACA_CTRL*/
#define DACAREN 15
#define DACALEN 14
#define RMIXEN 13
#define LMIXEN 12
#define HPOUTPUTENABLE 8
/*OMIXER_SR*/
#define RMIXMUTEMIC1BOOST (13)
#define RMIXMUTEMIC2BOOST (12)
#define RMIXMUTELINEINLR (11)
#define RMIXMUTELINEINR (10)
#define RMIXMUTEAUXINR (9)
#define RMIXMUTEDACR (8)
#define RMIXMUTEDACL (7)
#define LMIXMUTEMIC1BOOST (6)
#define LMIXMUTEMIC2BOOST (5)
#define LMIXMUTELINEINLR (4)
#define LMIXMUTELINEINL (3)
#define LMIXMUTEAUXINL (2)
#define LMIXMUTEDACL (1)
#define LMIXMUTEDACR (0)
/*OMIXER_BST1_CTRL*/
#define BIASVOLTAGE 12
#define AXG 9
#define OMIXER_MIC1G 6
#define OMIXER_MIC2G 3
#define LINEING 0
/*HPOUT_CTRL*/
#define RHPS 15
#define LHPS 14
#define RHPPA_MUTE 13
#define LHPPA_MUTE 12
#define HPPA_EN 11
#define HP_VOL 4
#define HPPA_DEL 2
#define HPPA_IS 0
/*ESPKOUT_CTRL*/
#define EAR_RAMP_TIME 11
#define ESPA_OUT_CURRENT 9
#define ESPSR 7
#define ESPPA_MUTE 6
#define ESPPA_EN 5
#define ESP_VOL 0
/*SPKOUT_CTRL*/
#define HPCALICKS 13
#define RSPKS 12
#define RSPKINVEN 11
#define RSPK_EN 9
#define LSPKS 8
#define LSPKINVEN 7
#define LSPK_EN 5
#define SPK_VOL 0
/*LOUT_CTRL*/
#define LINEOUTG 5
#define LINEOUTEN 4
#define LINEOUTS0 3
#define LINEOUTS1 2
#define LINEOUTS2 1
#define LINEOUTS3 0
/*ADDA_TUNE1*/
#define CURRENT_TEST_SELECT 14
#define BIHE_CTRL 12
#define DITHER 11
#define DITHER_CLK 9
#define ZERO_CROSSOVER_EN 8
#define ZERO_CROSSOVER_TIME 7
#define EAR_SPEED_SELECT 6
#define REF_CHOPPEN_CKS 4
#define OPMIC_BIAS_CUR 0
/*ADDA_TUNE2*/
#define OPDAC_BIAS_CUR 14
#define OPDRV_BIAS_CUR 12
#define OPMIX_BIAS_CUR 10
#define OPEAR_BIAS_CUR 8
#define OPVR_BIAS_CUR 6
#define OPAAF_BIAS_CUR 4
#define OPADC1_BIAS_CUR 2
#define OPADC2_BIAS_CUR 0
/*ADDA_TUNE3*/
#define LDOEN 15
#define LDO_SEL 12
#define BIASCALIVERIFY 11
#define BIASMODE 10
#define BIASCALIDATA 9
#define OSCS 1
#define OSCEN 0
/*HPOUT_STR*/
#define HPVL_SOFT_MOD 14
#define HPVL_STEP_CTRL 8
#define DACA_CHND_ENA 7
#define HPPA_MXRD_ENA 6
#define HPVL_CTRL_OUT 0
#endif//__AC101_REGS_H__

1554
ac108.c Normal file

File diff suppressed because it is too large Load diff

774
ac108.h Executable file
View file

@ -0,0 +1,774 @@
/*
* ac108.h -- ac108 ALSA Soc Audio driver
*
* Author: panjunwen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef _AC108_H
#define _AC108_H
/*** AC108 Codec Register Define***/
//Chip Reset
#define CHIP_RST 0x00
#define CHIP_RST_VAL 0x12
//Power Control
#define PWR_CTRL1 0x01
#define PWR_CTRL2 0x02
#define PWR_CTRL3 0x03
#define PWR_CTRL4 0x04
#define PWR_CTRL5 0x05
#define PWR_CTRL6 0x06
#define PWR_CTRL7 0x07
#define PWR_CTRL8 0x08
#define PWR_CTRL9 0x09
//PLL Configure Control
#define PLL_CTRL1 0x10
#define PLL_CTRL2 0x11
#define PLL_CTRL3 0x12
#define PLL_CTRL4 0x13
#define PLL_CTRL5 0x14
#define PLL_CTRL6 0x16
#define PLL_CTRL7 0x17
#define PLL_LOCK_CTRL 0x18
//System Clock Control
#define SYSCLK_CTRL 0x20
#define MOD_CLK_EN 0x21
#define MOD_RST_CTRL 0x22
#define DSM_CLK_CTRL 0x25
//I2S Common Control
#define I2S_CTRL 0x30
#define I2S_BCLK_CTRL 0x31
#define I2S_LRCK_CTRL1 0x32
#define I2S_LRCK_CTRL2 0x33
#define I2S_FMT_CTRL1 0x34
#define I2S_FMT_CTRL2 0x35
#define I2S_FMT_CTRL3 0x36
//I2S TX1 Control
#define I2S_TX1_CTRL1 0x38
#define I2S_TX1_CTRL2 0x39
#define I2S_TX1_CTRL3 0x3A
#define I2S_TX1_CHMP_CTRL1 0x3C
#define I2S_TX1_CHMP_CTRL2 0x3D
#define I2S_TX1_CHMP_CTRL3 0x3E
#define I2S_TX1_CHMP_CTRL4 0x3F
//I2S TX2 Control
#define I2S_TX2_CTRL1 0x40
#define I2S_TX2_CTRL2 0x41
#define I2S_TX2_CTRL3 0x42
#define I2S_TX2_CHMP_CTRL1 0x44
#define I2S_TX2_CHMP_CTRL2 0x45
#define I2S_TX2_CHMP_CTRL3 0x46
#define I2S_TX2_CHMP_CTRL4 0x47
//I2S RX1 Control
#define I2S_RX1_CTRL1 0x50
#define I2S_RX1_CHMP_CTRL1 0x54
#define I2S_RX1_CHMP_CTRL2 0x55
#define I2S_RX1_CHMP_CTRL3 0x56
#define I2S_RX1_CHMP_CTRL4 0x57
//I2S Loopback Debug
#define I2S_LPB_DEBUG 0x58
//ADC Common Control
#define ADC_SPRC 0x60
#define ADC_DIG_EN 0x61
#define DMIC_EN 0x62
#define ADC_DSR 0x63
#define ADC_FIR 0x64
#define ADC_DDT_CTRL 0x65
//HPF Control
#define HPF_EN 0x66
#define HPF_COEF_REGH1 0x67
#define HPF_COEF_REGH2 0x68
#define HPF_COEF_REGL1 0x69
#define HPF_COEF_REGL2 0x6A
#define HPF_GAIN_REGH1 0x6B
#define HPF_GAIN_REGH2 0x6C
#define HPF_GAIN_REGL1 0x6D
#define HPF_GAIN_REGL2 0x6E
//ADC Digital Channel Volume Control
#define ADC1_DVOL_CTRL 0x70
#define ADC2_DVOL_CTRL 0x71
#define ADC3_DVOL_CTRL 0x72
#define ADC4_DVOL_CTRL 0x73
//ADC Digital Mixer Source and Gain Control
#define ADC1_DMIX_SRC 0x76
#define ADC2_DMIX_SRC 0x77
#define ADC3_DMIX_SRC 0x78
#define ADC4_DMIX_SRC 0x79
//ADC Digital Debug Control
#define ADC_DIG_DEBUG 0x7F
//I2S Pad Drive Control
#define I2S_DAT_PADDRV_CTRL 0x80
#define I2S_CLK_PADDRV_CTRL 0x81
//Analog PGA Control
#define ANA_PGA1_CTRL 0x90
#define ANA_PGA2_CTRL 0x91
#define ANA_PGA3_CTRL 0x92
#define ANA_PGA4_CTRL 0x93
//MIC Offset Control
#define MIC_OFFSET_CTRL1 0x96
#define MIC_OFFSET_CTRL2 0x97
#define MIC1_OFFSET_STATU1 0x98
#define MIC1_OFFSET_STATU2 0x99
#define MIC2_OFFSET_STATU1 0x9A
#define MIC2_OFFSET_STATU2 0x9B
#define MIC3_OFFSET_STATU1 0x9C
#define MIC3_OFFSET_STATU2 0x9D
#define MIC4_OFFSET_STATU1 0x9E
#define MIC4_OFFSET_STATU2 0x9F
//ADC1 Analog Control
#define ANA_ADC1_CTRL1 0xA0
#define ANA_ADC1_CTRL2 0xA1
#define ANA_ADC1_CTRL3 0xA2
#define ANA_ADC1_CTRL4 0xA3
#define ANA_ADC1_CTRL5 0xA4
#define ANA_ADC1_CTRL6 0xA5
#define ANA_ADC1_CTRL7 0xA6
//ADC2 Analog Control
#define ANA_ADC2_CTRL1 0xA7
#define ANA_ADC2_CTRL2 0xA8
#define ANA_ADC2_CTRL3 0xA9
#define ANA_ADC2_CTRL4 0xAA
#define ANA_ADC2_CTRL5 0xAB
#define ANA_ADC2_CTRL6 0xAC
#define ANA_ADC2_CTRL7 0xAD
//ADC3 Analog Control
#define ANA_ADC3_CTRL1 0xAE
#define ANA_ADC3_CTRL2 0xAF
#define ANA_ADC3_CTRL3 0xB0
#define ANA_ADC3_CTRL4 0xB1
#define ANA_ADC3_CTRL5 0xB2
#define ANA_ADC3_CTRL6 0xB3
#define ANA_ADC3_CTRL7 0xB4
//ADC4 Analog Control
#define ANA_ADC4_CTRL1 0xB5
#define ANA_ADC4_CTRL2 0xB6
#define ANA_ADC4_CTRL3 0xB7
#define ANA_ADC4_CTRL4 0xB8
#define ANA_ADC4_CTRL5 0xB9
#define ANA_ADC4_CTRL6 0xBA
#define ANA_ADC4_CTRL7 0xBB
//GPIO Configure
#define GPIO_CFG1 0xC0
#define GPIO_CFG2 0xC1
#define GPIO_DAT 0xC2
#define GPIO_DRV 0xC3
#define GPIO_PULL 0xC4
#define GPIO_INT_CFG 0xC5
#define GPIO_INT_EN 0xC6
#define GPIO_INT_STATUS 0xC7
//Misc
#define BGTC_DAT 0xD1
#define BGVC_DAT 0xD2
#define PRNG_CLK_CTRL 0xDF
/*** AC108 Codec Register Bit Define***/
/*PWR_CTRL1*/
#define CP12_CTRL 4
#define CP12_SENSE_SELECT 3
/*PWR_CTRL2*/
#define CP12_SENSE_FILT 6
#define CP12_COMP_FF_EN 3
#define CP12_FORCE_ENABLE 2
#define CP12_FORCE_RSTB 1
/*PWR_CTRL3*/
#define LDO33DIG_CTRL 0
/*PWR_CTRL6*/
#define LDO33ANA_2XHDRM 2
#define LDO33ANA_ENABLE 0
/*PWR_CTRL7*/
#define VREF_SEL 3
#define VREF_FASTSTART_ENABLE 1
#define VREF_ENABLE 0
/*PWR_CTRL9*/
#define VREFP_FASTSTART_ENABLE 7
#define VREFP_RESCTRL 5
#define VREFP_LPMODE 4
#define IGEN_TRIM 1
#define VREFP_ENABLE 0
/*PLL_CTRL1*/
#define PLL_IBIAS 4
#define PLL_NDET 3
#define PLL_LOCKED_STATUS 2
#define PLL_COM_EN 1
#define PLL_EN 0
/*PLL_CTRL2*/
#define PLL_PREDIV2 5
#define PLL_PREDIV1 0
/*PLL_CTRL3*/
#define PLL_LOOPDIV_MSB 0
/*PLL_CTRL4*/
#define PLL_LOOPDIV_LSB 0
/*PLL_CTRL5*/
#define PLL_POSTDIV2 5
#define PLL_POSTDIV1 0
/*PLL_CTRL6*/
#define PLL_LDO 6
#define PLL_CP 0
/*PLL_CTRL7*/
#define PLL_CAP 6
#define PLL_RES 4
#define PLL_TEST_EN 0
/*PLL_LOCK_CTRL*/
#define LOCK_LEVEL1 2
#define LOCK_LEVEL2 1
#define PLL_LOCK_EN 0
/*SYSCLK_CTRL*/
#define PLLCLK_EN 7
#define PLLCLK_SRC 4
#define SYSCLK_SRC 3
#define SYSCLK_EN 0
/*MOD_CLK_EN & MOD_RST_CTRL*/
#define I2S 7
#define ADC_DIGITAL 4
#define MIC_OFFSET_CALIBRATION 1
#define ADC_ANALOG 0
/*DSM_CLK_CTRL*/
#define MIC_OFFSET_DIV 4
#define DSM_CLK_SEL 0
/*I2S_CTRL*/
#define BCLK_IOEN 7
#define LRCK_IOEN 6
#define SDO2_EN 5
#define SDO1_EN 4
#define TXEN 2
#define RXEN 1
#define GEN 0
/*I2S_BCLK_CTRL*/
#define EDGE_TRANSFER 5
#define BCLK_POLARITY 4
#define BCLKDIV 0
/*I2S_LRCK_CTRL1*/
#define LRCK_POLARITY 4
#define LRCK_PERIODH 0
/*I2S_LRCK_CTRL2*/
#define LRCK_PERIODL 0
/*I2S_FMT_CTRL1*/
#define ENCD_SEL 6
#define MODE_SEL 4
#define TX2_OFFSET 3
#define TX1_OFFSET 2
#define TX_SLOT_HIZ 1
#define TX_STATE 0
/*I2S_FMT_CTRL2*/
#define SLOT_WIDTH_SEL 4
#define SAMPLE_RESOLUTION 0
/*I2S_FMT_CTRL3*/
#define TX_MLS 7
#define SEXT 5
#define OUT2_MUTE 4
#define OUT1_MUTE 3
#define LRCK_WIDTH 2
#define TX_PDM 0
/*I2S_TX1_CTRL1*/
#define TX1_CHSEL 0
/*I2S_TX1_CTRL2*/
#define TX1_CH8_EN 7
#define TX1_CH7_EN 6
#define TX1_CH6_EN 5
#define TX1_CH5_EN 4
#define TX1_CH4_EN 3
#define TX1_CH3_EN 2
#define TX1_CH2_EN 1
#define TX1_CH1_EN 0
/*I2S_TX1_CTRL3*/
#define TX1_CH16_EN 7
#define TX1_CH15_EN 6
#define TX1_CH14_EN 5
#define TX1_CH13_EN 4
#define TX1_CH12_EN 3
#define TX1_CH11_EN 2
#define TX1_CH10_EN 1
#define TX1_CH9_EN 0
/*I2S_TX1_CHMP_CTRL1*/
#define TX1_CH4_MAP 6
#define TX1_CH3_MAP 4
#define TX1_CH2_MAP 2
#define TX1_CH1_MAP 0
/*I2S_TX1_CHMP_CTRL2*/
#define TX1_CH8_MAP 6
#define TX1_CH7_MAP 4
#define TX1_CH6_MAP 2
#define TX1_CH5_MAP 0
/*I2S_TX1_CHMP_CTRL3*/
#define TX1_CH12_MAP 6
#define TX1_CH11_MAP 4
#define TX1_CH10_MAP 2
#define TX1_CH9_MAP 0
/*I2S_TX1_CHMP_CTRL4*/
#define TX1_CH16_MAP 6
#define TX1_CH15_MAP 4
#define TX1_CH14_MAP 2
#define TX1_CH13_MAP 0
/*I2S_TX2_CTRL1*/
#define TX2_CHSEL 0
/*I2S_TX2_CHMP_CTRL1*/
#define TX2_CH4_MAP 6
#define TX2_CH3_MAP 4
#define TX2_CH2_MAP 2
#define TX2_CH1_MAP 0
/*I2S_TX2_CHMP_CTRL2*/
#define TX2_CH8_MAP 6
#define TX2_CH7_MAP 4
#define TX2_CH6_MAP 2
#define TX2_CH5_MAP 0
/*I2S_TX2_CHMP_CTRL3*/
#define TX2_CH12_MAP 6
#define TX2_CH11_MAP 4
#define TX2_CH10_MAP 2
#define TX2_CH9_MAP 0
/*I2S_TX2_CHMP_CTRL4*/
#define TX2_CH16_MAP 6
#define TX2_CH15_MAP 4
#define TX2_CH14_MAP 2
#define TX2_CH13_MAP 0
/*I2S_RX1_CTRL1*/
#define RX1_CHSEL 0
/*I2S_RX1_CHMP_CTRL1*/
#define RX1_CH4_MAP 6
#define RX1_CH3_MAP 4
#define RX1_CH2_MAP 2
#define RX1_CH1_MAP 0
/*I2S_RX1_CHMP_CTRL2*/
#define RX1_CH8_MAP 6
#define RX1_CH7_MAP 4
#define RX1_CH6_MAP 2
#define RX1_CH5_MAP 0
/*I2S_RX1_CHMP_CTRL3*/
#define RX1_CH12_MAP 6
#define RX1_CH11_MAP 4
#define RX1_CH10_MAP 2
#define RX1_CH9_MAP 0
/*I2S_RX1_CHMP_CTRL4*/
#define RX1_CH16_MAP 6
#define RX1_CH15_MAP 4
#define RX1_CH14_MAP 2
#define RX1_CH13_MAP 0
/*I2S_LPB_DEBUG*/
#define I2S_LPB_DEBUG_EN 0
/*ADC_SPRC*/
#define ADC_FS_I2S1 0
/*ADC_DIG_EN*/
#define DG_EN 4
#define ENAD4 3
#define ENAD3 2
#define ENAD2 1
#define ENAD1 0
/*DMIC_EN*/
#define DMIC2_EN 1
#define DMIC1_EN 0
/*ADC_DSR*/
#define DIG_ADC4_SRS 6
#define DIG_ADC3_SRS 4
#define DIG_ADC2_SRS 2
#define DIG_ADC1_SRS 0
/*ADC_DDT_CTRL*/
#define ADOUT_DLY_EN 2
#define ADOUT_DTS 0
/*HPF_EN*/
#define DIG_ADC4_HPF_EN 3
#define DIG_ADC3_HPF_EN 2
#define DIG_ADC2_HPF_EN 1
#define DIG_ADC1_HPF_EN 0
/*ADC1_DMIX_SRC*/
#define ADC1_ADC4_DMXL_GC 7
#define ADC1_ADC3_DMXL_GC 6
#define ADC1_ADC2_DMXL_GC 5
#define ADC1_ADC1_DMXL_GC 4
#define ADC1_ADC4_DMXL_SRC 3
#define ADC1_ADC3_DMXL_SRC 2
#define ADC1_ADC2_DMXL_SRC 1
#define ADC1_ADC1_DMXL_SRC 0
/*ADC2_DMIX_SRC*/
#define ADC2_ADC4_DMXL_GC 7
#define ADC2_ADC3_DMXL_GC 6
#define ADC2_ADC2_DMXL_GC 5
#define ADC2_ADC1_DMXL_GC 4
#define ADC2_ADC4_DMXL_SRC 3
#define ADC2_ADC3_DMXL_SRC 2
#define ADC2_ADC2_DMXL_SRC 1
#define ADC2_ADC1_DMXL_SRC 0
/*ADC3_DMIX_SRC*/
#define ADC3_ADC4_DMXL_GC 7
#define ADC3_ADC3_DMXL_GC 6
#define ADC3_ADC2_DMXL_GC 5
#define ADC3_ADC1_DMXL_GC 4
#define ADC3_ADC4_DMXL_SRC 3
#define ADC3_ADC3_DMXL_SRC 2
#define ADC3_ADC2_DMXL_SRC 1
#define ADC3_ADC1_DMXL_SRC 0
/*ADC4_DMIX_SRC*/
#define ADC4_ADC4_DMXL_GC 7
#define ADC4_ADC3_DMXL_GC 6
#define ADC4_ADC2_DMXL_GC 5
#define ADC4_ADC1_DMXL_GC 4
#define ADC4_ADC4_DMXL_SRC 3
#define ADC4_ADC3_DMXL_SRC 2
#define ADC4_ADC2_DMXL_SRC 1
#define ADC4_ADC1_DMXL_SRC 0
/*ADC_DIG_DEBUG*/
#define ADC_PTN_SEL 0
/*I2S_DAT_PADDRV_CTRL*/
#define TX2_DAT_DRV 4
#define TX1_DAT_DRV 0
/*I2S_CLK_PADDRV_CTRL*/
#define LRCK_DRV 4
#define BCLK_DRV 0
/*ANA_PGA1_CTRL*/
#define ADC1_ANALOG_PGA 1
#define ADC1_ANALOG_PGA_STEP 0
/*ANA_PGA2_CTRL*/
#define ADC2_ANALOG_PGA 1
#define ADC2_ANALOG_PGA_STEP 0
/*ANA_PGA3_CTRL*/
#define ADC3_ANALOG_PGA 1
#define ADC3_ANALOG_PGA_STEP 0
/*ANA_PGA4_CTRL*/
#define ADC4_ANALOG_PGA 1
#define ADC4_ANALOG_PGA_STEP 0
/*MIC_OFFSET_CTRL1*/
#define MIC_OFFSET_CAL_EN4 3
#define MIC_OFFSET_CAL_EN3 2
#define MIC_OFFSET_CAL_EN2 1
#define MIC_OFFSET_CAL_EN1 0
/*MIC_OFFSET_CTRL2*/
#define MIC_OFFSET_CAL_GAIN 3
#define MIC_OFFSET_CAL_CHANNEL 1
#define MIC_OFFSET_CAL_EN_ONCE 0
/*MIC1_OFFSET_STATU1*/
#define MIC1_OFFSET_CAL_DONE 7
#define MIC1_OFFSET_CAL_RUN_STA 6
#define MIC1_OFFSET_MSB 0
/*MIC1_OFFSET_STATU2*/
#define MIC1_OFFSET_LSB 0
/*MIC2_OFFSET_STATU1*/
#define MIC2_OFFSET_CAL_DONE 7
#define MIC2_OFFSET_CAL_RUN_STA 6
#define MIC2_OFFSET_MSB 0
/*MIC2_OFFSET_STATU2*/
#define MIC2_OFFSET_LSB 0
/*MIC3_OFFSET_STATU1*/
#define MIC3_OFFSET_CAL_DONE 7
#define MIC3_OFFSET_CAL_RUN_STA 6
#define MIC3_OFFSET_MSB 0
/*MIC3_OFFSET_STATU2*/
#define MIC3_OFFSET_LSB 0
/*MIC4_OFFSET_STATU1*/
#define MIC4_OFFSET_CAL_DONE 7
#define MIC4_OFFSET_CAL_RUN_STA 6
#define MIC4_OFFSET_MSB 0
/*MIC4_OFFSET_STATU2*/
#define MIC4_OFFSET_LSB 0
/*ANA_ADC1_CTRL1*/
#define ADC1_PGA_BYPASS 7
#define ADC1_PGA_BYP_RCM 6
#define ADC1_PGA_CTRL_RCM 4
#define ADC1_PGA_MUTE 3
#define ADC1_DSM_ENABLE 2
#define ADC1_PGA_ENABLE 1
#define ADC1_MICBIAS_EN 0
/*ANA_ADC1_CTRL3*/
#define ADC1_ANA_CAL_EN 5
#define ADC1_SEL_OUT_EDGE 3
#define ADC1_DSM_DISABLE 2
#define ADC1_VREFP_DISABLE 1
#define ADC1_AAF_DISABLE 0
/*ANA_ADC1_CTRL6*/
#define PGA_CTRL_TC 6
#define PGA_CTRL_RC 4
#define PGA_CTRL_I_LIN 2
#define PGA_CTRL_I_IN 0
/*ANA_ADC1_CTRL7*/
#define PGA_CTRL_HI_Z 7
#define PGA_CTRL_SHORT_RF 6
#define PGA_CTRL_VCM_VG 4
#define PGA_CTRL_VCM_IN 0
/*ANA_ADC2_CTRL1*/
#define ADC2_PGA_BYPASS 7
#define ADC2_PGA_BYP_RCM 6
#define ADC2_PGA_CTRL_RCM 4
#define ADC2_PGA_MUTE 3
#define ADC2_DSM_ENABLE 2
#define ADC2_PGA_ENABLE 1
#define ADC2_MICBIAS_EN 0
/*ANA_ADC2_CTRL3*/
#define ADC2_ANA_CAL_EN 5
#define ADC2_SEL_OUT_EDGE 3
#define ADC2_DSM_DISABLE 2
#define ADC2_VREFP_DISABLE 1
#define ADC2_AAF_DISABLE 0
/*ANA_ADC2_CTRL6*/
#define PGA_CTRL_IBOOST 7
#define PGA_CTRL_IQCTRL 6
#define PGA_CTRL_OABIAS 4
#define PGA_CTRL_CMLP_DIS 3
#define PGA_CTRL_PDB_RIN 2
#define PGA_CTRL_PEAKDET 0
/*ANA_ADC2_CTRL7*/
#define AAF_LPMODE_EN 7
#define AAF_STG2_IB_SEL 4
#define AAFDSM_IB_DIV2 3
#define AAF_STG1_IB_SEL 0
/*ANA_ADC3_CTRL1*/
#define ADC3_PGA_BYPASS 7
#define ADC3_PGA_BYP_RCM 6
#define ADC3_PGA_CTRL_RCM 4
#define ADC3_PGA_MUTE 3
#define ADC3_DSM_ENABLE 2
#define ADC3_PGA_ENABLE 1
#define ADC3_MICBIAS_EN 0
/*ANA_ADC3_CTRL3*/
#define ADC3_ANA_CAL_EN 5
#define ADC3_INVERT_CLK 4
#define ADC3_SEL_OUT_EDGE 3
#define ADC3_DSM_DISABLE 2
#define ADC3_VREFP_DISABLE 1
#define ADC3_AAF_DISABLE 0
/*ANA_ADC3_CTRL7*/
#define DSM_COMP_IB_SEL 6
#define DSM_OTA_CTRL 4
#define DSM_LPMODE 3
#define DSM_OTA_IB_SEL 0
/*ANA_ADC4_CTRL1*/
#define ADC4_PGA_BYPASS 7
#define ADC4_PGA_BYP_RCM 6
#define ADC4_PGA_CTRL_RCM 4
#define ADC4_PGA_MUTE 3
#define ADC4_DSM_ENABLE 2
#define ADC4_PGA_ENABLE 1
#define ADC4_MICBIAS_EN 0
/*ANA_ADC4_CTRL3*/
#define ADC4_ANA_CAL_EN 5
#define ADC4_SEL_OUT_EDGE 3
#define ADC4_DSM_DISABLE 2
#define ADC4_VREFP_DISABLE 1
#define ADC4_AAF_DISABLE 0
/*ANA_ADC4_CTRL6*/
#define DSM_DEMOFF 5
#define DSM_EN_DITHER 4
#define DSM_VREFP_LPMODE 2
#define DSM_VREFP_OUTCTRL 0
/*ANA_ADC4_CTRL7*/
#define CK8M_EN 5
#define OSC_EN 4
#define ADC4_CLK_GATING 3
#define ADC3_CLK_GATING 2
#define ADC2_CLK_GATING 1
#define ADC1_CLK_GATING 0
/*GPIO_CFG1*/
#define GPIO2_SELECT 4
#define GPIO1_SELECT 0
/*GPIO_CFG2*/
#define GPIO4_SELECT 4
#define GPIO3_SELECT 0
/*GPIO_DAT*///order???
#define GPIO4_DAT 3
#define GPIO3_DAT 2
#define GPIO2_DAT 1
#define GPIO1_DAT 0
/*GPIO_DRV*/
#define GPIO4_DRV 6
#define GPIO3_DRV 4
#define GPIO2_DRV 2
#define GPIO1_DRV 0
/*GPIO_PULL*/
#define GPIO4_PULL 6
#define GPIO3_PULL 4
#define GPIO2_PULL 2
#define GPIO1_PULL 0
/*GPIO_INT_CFG*/
#define GPIO4_EINT_CFG 6
#define GPIO3_EINT_CFG 4
#define GPIO2_EINT_CFG 2
#define GPIO1_EINT_CFG 0
/*GPIO_INT_EN*///order???
#define GPIO4_EINT_EN 3
#define GPIO3_EINT_EN 2
#define GPIO2_EINT_EN 1
#define GPIO1_EINT_EN 0
/*GPIO_INT_STATUS*///order???
#define GPIO4_EINT_STA 3
#define GPIO3_EINT_STA 2
#define GPIO2_EINT_STA 1
#define GPIO1_EINT_STA 0
/*PRNG_CLK_CTRL*/
#define PRNG_CLK_EN 1
#define PRNG_CLK_POS 0
/*** Some Config Value ***/
//[SYSCLK_CTRL]: PLLCLK_SRC
#define PLLCLK_SRC_MCLK 0
#define PLLCLK_SRC_BCLK 1
#define PLLCLK_SRC_GPIO2 2
#define PLLCLK_SRC_GPIO3 3
//[SYSCLK_CTRL]: SYSCLK_SRC
#define SYSCLK_SRC_MCLK 0
#define SYSCLK_SRC_PLL 1
//I2S BCLK POLARITY Control
#define BCLK_NORMAL_DRIVE_N_SAMPLE_P 0
#define BCLK_INVERT_DRIVE_P_SAMPLE_N 1
//I2S LRCK POLARITY Control
#define LRCK_LEFT_LOW_RIGHT_HIGH 0
#define LRCK_LEFT_HIGH_RIGHT_LOW 1
//I2S Format Selection
#define PCM_FORMAT 0
#define LEFT_JUSTIFIED_FORMAT 1
#define RIGHT_JUSTIFIED_FORMAT 2
//I2S data protocol types
#define IS_ENCODING_MODE 0
#endif

367
ac108_6mic.state Normal file
View file

@ -0,0 +1,367 @@
state.ALSA {
control.1 {
iface MIXER
name 'PCM Playback Volume'
value 400
comment {
access 'read write'
type INTEGER
count 1
range '-10239 - 400'
dbmin -9999999
dbmax 400
dbvalue.0 400
}
}
control.2 {
iface MIXER
name 'PCM Playback Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.3 {
iface MIXER
name 'PCM Playback Route'
value 1
comment {
access 'read write'
type INTEGER
count 1
range '0 - 2'
}
}
control.4 {
iface PCM
name 'IEC958 Playback Default'
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read write'
type IEC958
count 1
}
}
control.5 {
iface PCM
name 'IEC958 Playback Con Mask'
value '0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access read
type IEC958
count 1
}
}
control.6 {
iface PCM
name 'IEC958 Playback PCM Stream'
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read write inactive'
type IEC958
count 1
}
}
}
state.seeed8micvoicec {
control.1 {
iface MIXER
name 'CH1 digital volume'
value 208
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 3675
}
}
control.2 {
iface MIXER
name 'CH2 digital volume'
value 208
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 3675
}
}
control.3 {
iface MIXER
name 'CH3 digital volume'
value 208
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 3675
}
}
control.4 {
iface MIXER
name 'CH4 digital volume'
value 208
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 3675
}
}
control.5 {
iface MIXER
name 'ADC1 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.6 {
iface MIXER
name 'ADC2 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.7 {
iface MIXER
name 'ADC3 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.8 {
iface MIXER
name 'ADC4 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.9 {
iface MIXER
name 'CH5 digital volume'
value 208
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 3675
}
}
control.10 {
iface MIXER
name 'CH6 digital volume'
value 208
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 3675
}
}
control.11 {
iface MIXER
name 'CH7 digital volume'
value 198
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 2925
}
}
control.12 {
iface MIXER
name 'CH8 digital volume'
value 198
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 2925
}
}
control.13 {
iface MIXER
name 'ADC5 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.14 {
iface MIXER
name 'ADC6 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.15 {
iface MIXER
name 'ADC7 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.16 {
iface MIXER
name 'ADC8 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.17 {
iface MIXER
name 'DAC volume'
value.0 0
value.1 0
comment {
access 'read write'
type INTEGER
count 2
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 -11925
dbvalue.1 -11925
}
}
control.18 {
iface MIXER
name 'DAC mixer gain'
value.0 0
value.1 0
comment {
access 'read write'
type INTEGER
count 2
range '0 - 15'
dbmin -600
dbmax 8400
dbvalue.0 -600
dbvalue.1 -600
}
}
control.19 {
iface MIXER
name 'digital volume'
value 51
comment {
access 'read write'
type INTEGER
count 1
range '0 - 63'
dbmin -7308
dbmax 0
dbvalue.0 -1392
}
}
control.20 {
iface MIXER
name 'Speaker Playback Volume'
value 25
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin -4800
dbmax -150
dbvalue.0 -1050
}
}
control.21 {
iface MIXER
name 'Headphone Playback Volume'
value 52
comment {
access 'read write'
type INTEGER
count 1
range '0 - 63'
dbmin -6300
dbmax 0
dbvalue.0 -1100
}
}
}

181
ac108_asound.state Normal file
View file

@ -0,0 +1,181 @@
state.ALSA {
control.1 {
iface MIXER
name 'PCM Playback Volume'
value 400
comment {
access 'read write'
type INTEGER
count 1
range '-10239 - 400'
dbmin -9999999
dbmax 400
dbvalue.0 400
}
}
control.2 {
iface MIXER
name 'PCM Playback Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.3 {
iface MIXER
name 'PCM Playback Route'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 2'
}
}
control.4 {
iface PCM
name 'IEC958 Playback Default'
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read write'
type IEC958
count 1
}
}
control.5 {
iface PCM
name 'IEC958 Playback Con Mask'
value '0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access read
type IEC958
count 1
}
}
control.6 {
iface PCM
name 'IEC958 Playback PCM Stream'
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read write inactive'
type IEC958
count 1
}
}
}
state.seeed4micvoicec {
control.1 {
iface MIXER
name 'CH1 digital volume'
value 222
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 4725
}
}
control.2 {
iface MIXER
name 'CH2 digital volume'
value 222
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 4725
}
}
control.3 {
iface MIXER
name 'CH3 digital volume'
value 222
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 4725
}
}
control.4 {
iface MIXER
name 'CH4 digital volume'
value 222
comment {
access 'read write'
type INTEGER
count 1
range '0 - 255'
dbmin -11925
dbmax 7200
dbvalue.0 4725
}
}
control.5 {
iface MIXER
name 'ADC1 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.6 {
iface MIXER
name 'ADC2 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.7 {
iface MIXER
name 'ADC3 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
control.8 {
iface MIXER
name 'ADC4 PGA gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
dbmin 0
dbmax 3100
dbvalue.0 0
}
}
}

58
ac108_plugin/Makefile Normal file
View file

@ -0,0 +1,58 @@
# Quiet (set to @ for a quite compile)
Q ?= @
#Q ?=
# Build Tools
CC := gcc
CFLAGS += -I. -Wall -funroll-loops -ffast-math -fPIC -DPIC -O0 -g
LD := gcc
LDFLAGS += -Wall -shared -lasound
SND_PCM_OBJECTS = pcm_ac108.o ac108_help.o
SND_PCM_LIBS =
SND_PCM_BIN = libasound_module_pcm_ac108.so
#SND_CTL_OBJECTS = ctl_ac108.o ladspa_utils.o
#SND_CTL_LIBS =
#SND_CTL_BIN = libasound_module_ctl_ac108.so
MULTIARCH:=$(shell gcc --print-multiarch)
LIBDIR = lib/$(MULTIARCH)
.PHONY: all clean dep load_default
all: Makefile $(SND_PCM_BIN) $(SND_CTL_BIN)
dep:
@echo DEP $@
$(Q)for i in *.c; do $(CC) -MM $(CFLAGS) "$${i}" ; done > makefile.dep
-include makefile.dep
$(SND_PCM_BIN): $(SND_PCM_OBJECTS)
@echo LD $@
$(Q)$(LD) $(LDFLAGS) $(SND_PCM_LIBS) $(SND_PCM_OBJECTS) -o $(SND_PCM_BIN)
#$(SND_CTL_BIN): $(SND_CTL_OBJECTS)
# @echo LD $@
# $(Q)$(LD) $(LDFLAGS) $(SND_CTL_LIBS) $(SND_CTL_OBJECTS) -o $(SND_CTL_BIN)
%.o: %.c
@echo GCC $<
$(Q)$(CC) -c $(CFLAGS) $(CPPFLAGS) $<
clean:
@echo Cleaning...
$(Q)rm -vf *.o *.so
install: all
@echo Installing...
$(Q)mkdir -p ${DESTDIR}/usr/$(LIBDIR)/alsa-lib/
$(Q)install -m 644 $(SND_PCM_BIN) ${DESTDIR}/usr/$(LIBDIR)/alsa-lib/
#$(Q)install -m 644 $(SND_CTL_BIN) ${DESTDIR}/usr/$(LIBDIR)/alsa-lib/
uninstall:
@echo Un-installing...
$(Q)rm ${DESTDIR}/usr/lib/alsa-lib/$(SND_PCM_BIN)
#$(Q)rm ${DESTDIR}/usr/lib/alsa-lib/$(SND_CTL_BIN)

5
ac108_plugin/README.md Normal file
View file

@ -0,0 +1,5 @@
#seeed-4mic-voicecard alsa plugin
```
sudo apt install libasound2-dev
make && sudo make install
```

77
ac108_plugin/ac108_help.c Normal file
View file

@ -0,0 +1,77 @@
#include "ac108_help.h"
void generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase)
{
snd_pcm_format_t format = SND_PCM_FORMAT_S32; /* sample format */
unsigned int rate = 16000; /* stream rate */
unsigned int channels = 4; /* count of channels */
unsigned int buffer_time = 500000; /* ring buffer length in us */
unsigned int period_time = 100000; /* period time in us */
double freq = 160; /* sinusoidal wave frequency in Hz */
int verbose = 0; /* verbose flag */
int resample = 1; /* enable alsa-lib resampling */
int period_event = 0; /* produce poll event after each period */
static double max_phase = 2. * M_PI;
double phase = *_phase;
double step = max_phase*freq/(double)rate;
unsigned char *samples[channels];
int steps[channels];
unsigned int chn;
int format_bits = snd_pcm_format_width(format);
unsigned int maxval = (1 << (format_bits - 1)) - 1;
int bps = format_bits / 8; /* bytes per sample */
int phys_bps = snd_pcm_format_physical_width(format) / 8;
int big_endian = snd_pcm_format_big_endian(format) == 1;
int to_unsigned = snd_pcm_format_unsigned(format) == 1;
int is_float = (format == SND_PCM_FORMAT_FLOAT_LE ||
format == SND_PCM_FORMAT_FLOAT_BE);
/* verify and prepare the contents of areas */
for (chn = 0; chn < channels; chn++) {
if ((areas[chn].first % 8) != 0) {
printf("areas[%i].first == %i, aborting...\n", chn, areas[chn].first);
exit(EXIT_FAILURE);
}
samples[chn] = /*(signed short *)*/(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
if ((areas[chn].step % 16) != 0) {
printf("areas[%i].step == %i, aborting...\n", chn, areas[chn].step);
exit(EXIT_FAILURE);
}
steps[chn] = areas[chn].step / 8;
samples[chn] += offset * steps[chn];
}
/* fill the channel areas */
while (count-- > 0) {
union {
float f;
int i;
} fval;
int res, i;
if (is_float) {
fval.f = sin(phase);
res = fval.i;
} else
res = sin(phase) * maxval;
if (to_unsigned)
res ^= 1U << (format_bits - 1);
for (chn = 0; chn < channels; chn++) {
/* Generate data in native endian format */
if (big_endian) {
for (i = 0; i < bps; i++)
*(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff;
} else {
for (i = 0; i < bps; i++)
*(samples[chn] + i) = (res >> i * 8) & 0xff;
}
samples[chn] += steps[chn];
}
phase += step;
if (phase >= max_phase)
phase -= max_phase;
}
*_phase = phase;
}

11
ac108_plugin/ac108_help.h Normal file
View file

@ -0,0 +1,11 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
#include <alsa/pcm_external.h>
#include <alsa/pcm_plugin.h>
#include <math.h>
void generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase);

Binary file not shown.

536
ac108_plugin/pcm_ac108.c Normal file
View file

@ -0,0 +1,536 @@
//https://github.com/HazouPH/android_device_motorola_smi-plus/blob/48029b4afc307c73181b108a5b0155b9f20856ca/smi-modules/alsa-lib_module_voice/pcm_voice.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
#include <alsa/pcm_external.h>
#include <alsa/pcm_plugin.h>
#include "ac108_help.h"
#include <math.h>
#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0]))
#define AC108_FRAME_SIZE 40960
struct ac108_t {
snd_pcm_ioplug_t io;
snd_pcm_t *pcm;
snd_pcm_hw_params_t *hw_params;
unsigned int last_size;
unsigned int ptr;
unsigned int latency; // Delay in usec
unsigned int bufferSize; // Size of sample buffer
};
static unsigned char capture_buf[AC108_FRAME_SIZE];
/* set up the fixed parameters of pcm PCM hw_parmas */
static int ac108_slave_hw_params_half(struct ac108_t *capture, unsigned int rate,snd_pcm_format_t format) {
int err;
snd_pcm_uframes_t bufferSize = capture->bufferSize;
unsigned int latency = capture->latency;
unsigned int buffer_time = 0;
unsigned int period_time = 0;
if ((err = snd_pcm_hw_params_malloc(&capture->hw_params)) < 0) return err;
if ((err = snd_pcm_hw_params_any(capture->pcm, capture->hw_params)) < 0) {
SNDERR("Cannot get pcm hw_params");
goto out;
}
if ((err = snd_pcm_hw_params_set_access(capture->pcm, capture->hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
SNDERR("Cannot set pcm access RW_INTERLEAVED");
goto out;
}
if ((err = snd_pcm_hw_params_set_channels(capture->pcm, capture->hw_params, 2)) < 0) {
SNDERR("Cannot set pcm channels 2");
goto out;
}
if ((err = snd_pcm_hw_params_set_format(capture->pcm, capture->hw_params,
format)) < 0) {
SNDERR("Cannot set pcm format");
goto out;
}
if ((err = snd_pcm_hw_params_set_rate(capture->pcm, capture->hw_params, rate, 0)) < 0) {
SNDERR("Cannot set pcm rate %d", rate);
goto out;
}
err = snd_pcm_hw_params_get_buffer_time_max(capture->hw_params,
&buffer_time, 0);
if (buffer_time > 80000)
buffer_time = 80000;
period_time = buffer_time / 4;
err = snd_pcm_hw_params_set_period_time_near(capture->pcm, capture->hw_params,
&period_time, 0);
if (err < 0) {
SNDERR("Unable to set_period_time_near");
goto out;
}
err = snd_pcm_hw_params_set_buffer_time_near(capture->pcm, capture->hw_params,
&buffer_time, 0);
if (err < 0) {
SNDERR("Unable to set_buffer_time_near");
goto out;
}
capture->bufferSize = bufferSize;
capture->latency = latency;
return 0;
out:
free(capture->hw_params);
capture->hw_params = NULL;
return err;
}
/*
* start and stop callbacks - just trigger pcm PCM
*/
static int ac108_start(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
if(!capture->pcm) {
SNDERR( "pcm is lost\n");
}
return snd_pcm_start(capture->pcm);
}
static int ac108_stop(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
return snd_pcm_drop(capture->pcm);
}
/*
* pointer callback
*
* Calculate the current position from the delay of pcm PCM
*/
static snd_pcm_sframes_t ac108_pointer(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
int size;
assert(capture);
size = snd_pcm_avail(capture->pcm);
if (size < 0)
return size;
size = size/2;
if (size > capture->last_size) {
capture->ptr += size - capture->last_size;
capture->ptr %= io->buffer_size;
}
//fprintf(stderr, "%s :%d %d %d %d %d %d\n", __func__,capture->ptr ,capture->last_size,size, io->buffer_size,io->appl_ptr, io->hw_ptr);
capture->last_size = size;
return capture->ptr;
}
/*
* transfer callback
*/
static snd_pcm_sframes_t ac108_transfer(snd_pcm_ioplug_t *io,
const snd_pcm_channel_area_t *dst_areas,
snd_pcm_uframes_t dst_offset,
snd_pcm_uframes_t size) {
struct ac108_t *capture = io->private_data;
int chn;
unsigned char *dst_samples[io->channels];
int dst_steps[io->channels];
int bps = snd_pcm_format_width(io->format) / 8; /* bytes per sample */
int i;
int count = 0;
int err = 0;
unsigned char *src_buf;
unsigned char src_data[4][4];
memset(capture_buf,0,AC108_FRAME_SIZE);
if(snd_pcm_avail(capture->pcm) > size*2){
if ((err = snd_pcm_readi (capture->pcm, capture_buf, size*2)) != size*2) {
SNDERR("read from audio interface failed %ld %d %s!\n",size,err,snd_strerror (err));
exit(EXIT_FAILURE);
size = 0 ;
}
}else{
size = 0;
}
#if 1
/* verify and prepare the contents of areas */
for (chn = 0; chn < io->channels; chn++) {
if ((dst_areas[chn].first % 8) != 0) {
SNDERR("dst_areas[%i].first == %i, aborting...\n", chn, dst_areas[chn].first);
exit(EXIT_FAILURE);
}
dst_samples[chn] = /*(signed short *)*/(((unsigned char *)dst_areas[chn].addr) + (dst_areas[chn].first / 8));
if ((dst_areas[chn].step % 16) != 0) {
SNDERR("dst_areas[%i].step == %i, aborting...\n", chn, dst_areas[chn].step);
exit(EXIT_FAILURE);
}
dst_steps[chn] = dst_areas[chn].step / 8;
dst_samples[chn] += dst_offset * dst_steps[chn];
}
#endif
// for(i = 0; i < size*2*bps;i++){
// fprintf(stderr,"%x ",capture_buf[i]);
// if(i%4 == 0)
// fprintf(stderr,"\n");
// }
//generate_sine(dst_areas, dst_offset,size, &count);
src_buf = capture_buf;
#if 1
while(count < size){
for(chn = 0; chn < 4; chn++){
for (i = 0; i < bps; i++){
src_data[chn][i] = src_buf[i];
}
src_buf += bps ;
}
for(chn = 0; chn < io->channels; chn++){
for (i = 0; i < bps; i++){
*(dst_samples[chn] + i) = src_data[chn][i];
//fprintf(stderr,"%x ",*(dst_samples[chn] + i));
}
//fprintf(stderr,"\n");
dst_samples[chn] += dst_steps[chn];
}
count++;
}
#endif
capture->last_size -= size;
return size;
}
/*
* poll-related callbacks - just pass to pcm PCM
*/
static int ac108_poll_descriptors_count(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
return snd_pcm_poll_descriptors_count(capture->pcm);
}
static int ac108_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfd,
unsigned int space) {
struct ac108_t *capture = io->private_data;
return snd_pcm_poll_descriptors(capture->pcm, pfd, space);
}
static int ac108_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd,
unsigned int nfds, unsigned short *revents) {
struct ac108_t *capture = io->private_data;
return snd_pcm_poll_descriptors_revents(capture->pcm, pfd, nfds, revents);
}
/*
* close callback
*/
static int ac108_close(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
if (capture->pcm)
snd_pcm_close(capture->pcm);
return 0;
}
static int setSoftwareParams(struct ac108_t *capture) {
snd_pcm_sw_params_t *softwareParams;
int err;
snd_pcm_uframes_t bufferSize = 0;
snd_pcm_uframes_t periodSize = 0;
snd_pcm_uframes_t startThreshold, stopThreshold;
snd_pcm_sw_params_alloca(&softwareParams);
// Get the current software parameters
err = snd_pcm_sw_params_current(capture->pcm, softwareParams);
if (err < 0) {
SNDERR("Unable to get software parameters: %s", snd_strerror(err));
goto done;
}
// Configure ALSA to start the transfer when the buffer is almost full.
snd_pcm_get_params(capture->pcm, &bufferSize, &periodSize);
startThreshold = 1;
stopThreshold = bufferSize;
err = snd_pcm_sw_params_set_start_threshold(capture->pcm, softwareParams,
startThreshold);
if (err < 0) {
SNDERR("Unable to set start threshold to %lu frames: %s",
startThreshold, snd_strerror(err));
goto done;
}
err = snd_pcm_sw_params_set_stop_threshold(capture->pcm, softwareParams,
stopThreshold);
if (err < 0) {
SNDERR("Unable to set stop threshold to %lu frames: %s",
stopThreshold, snd_strerror(err));
goto done;
}
// Allow the transfer to start when at least periodSize samples can be
// processed.
err = snd_pcm_sw_params_set_avail_min(capture->pcm, softwareParams,
periodSize);
if (err < 0) {
SNDERR("Unable to configure available minimum to %lu: %s",
periodSize, snd_strerror(err));
goto done;
}
// Commit the software parameters back to the device.
err = snd_pcm_sw_params(capture->pcm, softwareParams);
if (err < 0)
SNDERR("Unable to configure software parameters: %s",snd_strerror(err));
return 0;
done:
snd_pcm_sw_params_free(softwareParams);
return err;
}
/*
* hw_params callback
*
* Set up pcm PCM according to the current parameters
*/
static int ac108_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) {
struct ac108_t *capture = io->private_data;
snd_pcm_uframes_t period_size;
snd_pcm_uframes_t buffer_size;
int err;
if (!capture->hw_params) {
err = ac108_slave_hw_params_half(capture, 2*io->rate,io->format);
if (err < 0) {
SNDERR("ac108_slave_hw_params_half error\n");
return err;
}
}
period_size = io->period_size;
if ((err = snd_pcm_hw_params_set_period_size_near(capture->pcm, capture->hw_params,
&period_size, NULL)) < 0) {
SNDERR("Cannot set pcm period size %ld", period_size);
return err;
}
buffer_size = io->buffer_size;
if ((err = snd_pcm_hw_params_set_buffer_size_near(capture->pcm, capture->hw_params,
&buffer_size)) < 0) {
SNDERR("Cannot set pcm buffer size %ld", buffer_size);
return err;
}
if ((err = snd_pcm_hw_params(capture->pcm, capture->hw_params)) < 0) {
SNDERR("Cannot set pcm hw_params");
return err;
}
setSoftwareParams(capture);
return 0;
}
/*
* hw_free callback
*/
static int ac108_hw_free(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
free(capture->hw_params);
capture->hw_params = NULL;
return snd_pcm_hw_free(capture->pcm);
}
static int ac108_prepare(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
capture->ptr = 0;
capture->last_size =0;
return snd_pcm_prepare(capture->pcm);
}
static int ac108_drain(snd_pcm_ioplug_t *io) {
struct ac108_t *capture = io->private_data;
return snd_pcm_drain(capture->pcm);
}
#if 0
static int ac108_sw_params(snd_pcm_ioplug_t *io, snd_pcm_sw_params_t *params) {
return 0;
}
#endif
static int ac108_delay(snd_pcm_ioplug_t * io, snd_pcm_sframes_t * delayp){
return 0;
}
/*
* callback table
*/
static snd_pcm_ioplug_callback_t a108_ops = {
.start = ac108_start,
.stop = ac108_stop,
.pointer = ac108_pointer,
.transfer = ac108_transfer,
.poll_descriptors_count = ac108_poll_descriptors_count,
.poll_descriptors = ac108_poll_descriptors,
.poll_revents = ac108_poll_revents,
.close = ac108_close,
.hw_params = ac108_hw_params,
.hw_free = ac108_hw_free,
// .sw_params = ac108_sw_params,
.prepare = ac108_prepare,
.drain = ac108_drain,
.delay = ac108_delay,
};
static int ac108_set_hw_constraint(struct ac108_t *capture) {
static unsigned int accesses[] = {
SND_PCM_ACCESS_RW_INTERLEAVED
};
unsigned int formats[] = { SND_PCM_FORMAT_S32,
SND_PCM_FORMAT_S16 };
unsigned int rates[] = {
8000,
16000,
32000,
44100,
48000,
96000
};
int err;
err = snd_pcm_ioplug_set_param_list(&capture->io,
SND_PCM_IOPLUG_HW_ACCESS,
ARRAY_SIZE(accesses),
accesses);
if (err < 0){
SNDERR("ioplug cannot set ac108 hw access");
return err;
}
if ((err = snd_pcm_ioplug_set_param_list(&capture->io, SND_PCM_IOPLUG_HW_FORMAT,
ARRAY_SIZE(formats), formats)) < 0 ||
(err = snd_pcm_ioplug_set_param_minmax(&capture->io, SND_PCM_IOPLUG_HW_CHANNELS,
1, 4)) < 0 ||
(err = snd_pcm_ioplug_set_param_list(&capture->io, SND_PCM_IOPLUG_HW_RATE,
ARRAY_SIZE(rates), rates)) < 0)
{
SNDERR("ioplug cannot set ac108 format channel rate!");
return err;
}
err = snd_pcm_ioplug_set_param_minmax(&capture->io,SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1, 4 * 1024 * 1024);
if (err < 0){
SNDERR("ioplug cannot set ac108 hw buffer bytes");
return err;
}
err = snd_pcm_ioplug_set_param_minmax(&capture->io,SND_PCM_IOPLUG_HW_PERIOD_BYTES,
128, 2 * 1024 * 1024);
if (err < 0) {
SNDERR("ioplug cannot set ac108 hw period bytes");
return err;
}
err = snd_pcm_ioplug_set_param_minmax(&capture->io, SND_PCM_IOPLUG_HW_PERIODS,3, 1024);
if (err < 0) {
SNDERR("ioplug cannot set ac108 hw periods");
return err;
}
return 0;
}
/*
* Main entry point
*/
SND_PCM_PLUGIN_DEFINE_FUNC(ac108) {
snd_config_iterator_t i, next;
int err;
const char *pcm_string = NULL;
struct ac108_t *capture;
int channels;
if (stream != SND_PCM_STREAM_CAPTURE) {
SNDERR("a108 is only for capture");
return -EINVAL;
}
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
if (snd_config_get_id(n, &id) < 0) continue;
if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || strcmp(id, "hint") == 0) continue;
if (strcmp(id, "slavepcm") == 0) {
if (snd_config_get_string(n, &pcm_string) < 0) {
SNDERR("ac108 slavepcm must be a string");
return -EINVAL;
}
continue;
}
if (strcmp(id, "channels") == 0) {
long val;
if (snd_config_get_integer(n, &val) < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
channels = val;
if (channels != 2 && channels != 4 && channels != 6) {
SNDERR("channels must be 2, 4 or 6");
return -EINVAL;
}
continue;
}
}
capture = calloc(1, sizeof(*capture));
if (!capture) {
SNDERR("cannot allocate");
return -ENOMEM;
}
err = snd_pcm_open(&capture->pcm, pcm_string, stream, mode);
if (err < 0) goto error;
//SND_PCM_NONBLOCK
capture->io.version = SND_PCM_IOPLUG_VERSION;
capture->io.name = "AC108 decode Plugin";
capture->io.mmap_rw = 0;
capture->io.callback = &a108_ops;
capture->io.private_data = capture;
err = snd_pcm_ioplug_create(&capture->io, name, stream, mode);
if (err < 0) goto error;
if ((err = ac108_set_hw_constraint(capture)) < 0) {
snd_pcm_ioplug_delete(&capture->io);
return err;
}
*pcmp = capture->io.pcm;
return 0;
error:
if (capture->pcm) snd_pcm_close(capture->pcm);
free(capture);
return err;
}
SND_PCM_PLUGIN_SYMBOL(ac108);

126
ac10x.h Normal file
View file

@ -0,0 +1,126 @@
/*
* ac10x.h
*
* (C) Copyright 2017-2018
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
*
* PeterYang <linsheng.yang@seeed.cc>
*
* (C) Copyright 2010-2017
* Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
* huangxin <huangxin@reuuimllatech.com>
*
* some simple description for this code
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*/
#ifndef __AC10X_H__
#define __AC10X_H__
#define AC101_I2C_ID 4
#define _MASTER_AC108 0
#define _MASTER_AC101 1
#define _MASTER_MULTI_CODEC _MASTER_AC101
/* enable headset detecting & headset button pressing */
#define CONFIG_AC101_SWITCH_DETECT
/* obsolete */
#define CONFIG_AC10X_TRIG_LOCK 0
#ifdef AC101_DEBG
#define AC101_DBG(format,args...) printk("[AC101] %s() L%d " format, __func__, __LINE__, ##args)
#else
#define AC101_DBG(...)
#endif
#include "sound-compatible-4.18.h"
#ifdef CONFIG_AC101_SWITCH_DETECT
enum headphone_mode_u {
HEADPHONE_IDLE,
FOUR_HEADPHONE_PLUGIN,
THREE_HEADPHONE_PLUGIN,
};
#endif
struct ac10x_priv {
struct i2c_client *i2c[4];
struct regmap* i2cmap[4];
int codec_cnt;
unsigned sysclk;
#define _FREQ_24_576K 24576000
#define _FREQ_22_579K 22579200
unsigned mclk; /* master clock or aif_clock/aclk */
int clk_id;
unsigned char i2s_mode;
unsigned char data_protocol;
struct delayed_work dlywork;
int tdm_chips_cnt;
int sysclk_en;
/* member for ac101 .begin */
struct snd_soc_codec *codec;
struct i2c_client *i2c101;
struct regmap* regmap101;
struct mutex dac_mutex;
u8 dac_enable;
spinlock_t lock;
u8 aif1_clken;
struct work_struct codec_resume;
struct gpio_desc* gpiod_spk_amp_gate;
#ifdef CONFIG_AC101_SWITCH_DETECT
struct gpio_desc* gpiod_irq;
long irq;
volatile int irq_cntr;
volatile int pullout_cntr;
volatile int state;
enum headphone_mode_u mode;
struct work_struct work_switch;
struct work_struct work_clear_irq;
struct input_dev* inpdev;
#endif
/* member for ac101 .end */
};
/* AC101 DAI operations */
int ac101_audio_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai);
void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai);
int ac101_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt);
int ac101_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *codec_dai);
int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai);
int ac101_aif_mute(struct snd_soc_dai *codec_dai, int mute);
/* codec driver specific */
int ac101_codec_probe(struct snd_soc_codec *codec);
int ac101_codec_remove(struct snd_soc_codec *codec);
int ac101_codec_suspend(struct snd_soc_codec *codec);
int ac101_codec_resume(struct snd_soc_codec *codec);
int ac101_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level);
/* i2c device specific */
int ac101_probe(struct i2c_client *i2c, const struct i2c_device_id *id);
void ac101_shutdown(struct i2c_client *i2c);
int ac101_remove(struct i2c_client *i2c);
/* seeed voice card export */
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);
#endif//__AC10X_H__

View file

@ -1,6 +1,10 @@
# The IPC key of dmix or dsnoop plugin must be unique
# If 555555 or 666666 is used by other processes, use another one
# use samplerate to resample as speexdsp resample is bad
defaults.pcm.rate_converter "samplerate"
pcm.!default {
type asym
playback.pcm "playback"
@ -19,14 +23,14 @@ pcm.capture {
pcm.dmixed {
type dmix
slave.pcm "hw:0,0"
slave.pcm "hw:seeed2micvoicec"
ipc_key 555555
}
pcm.array {
type dsnoop
slave {
pcm "hw:0,0"
pcm "hw:seeed2micvoicec"
channels 2
}
ipc_key 666666

33
asound_4mic.conf Normal file
View file

@ -0,0 +1,33 @@
# The IPC key of dmix or dsnoop plugin must be unique
# If 555555 or 666666 is used by other processes, use another one
# use samplerate to resample as speexdsp resample is bad
defaults.pcm.rate_converter "samplerate"
pcm.!default {
type asym
playback.pcm "playback"
capture.pcm "ac108"
}
pcm.playback {
type plug
slave.pcm "hw:ALSA"
}
# pcm.dmixed {
# type dmix
# slave.pcm "hw:0,0"
# ipc_key 555555
# }
pcm.ac108 {
type plug
slave.pcm "hw:seeed4micvoicec"
}
# pcm.multiapps {
# type dsnoop
# ac108-slavepcm "hw:1,0"
# ipc_key 666666
# }

90
asound_6mic.conf Normal file
View file

@ -0,0 +1,90 @@
# The IPC key of dmix or dsnoop plugin must be unique
# If 555555 or 666666 is used by other processes, use another one
# use samplerate to resample as speexdsp resample is broken
defaults.pcm.rate_converter "samplerate"
pcm.!default {
type asym
playback.pcm "dmixer"
capture.pcm "ac108"
}
pcm.ac108 {
type plug
slave {
rate 48000
format S32_LE
pcm "hw:seeed8micvoicec"
}
}
# pcm.multiapps {
# type plug
# slave.pcm {
# type dsnoop
# slave {
# rate 48000
# format S32_LE
# pcm "hw:seeed8micvoicec"
# }
# ipc_key 666666
# }
# }
pcm.dmixer {
type plug
slave {
pcm {
type dmix
ipc_key 555555
slave {
pcm "hw:seeed8micvoicec"
format S32_LE
channels 8
}
bindings {
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
}
}
channels 8
format S32_LE
rate 48000
}
ttable.0.0 1
ttable.1.1 1
ttable.0.2 1
ttable.1.3 1
ttable.0.4 1
ttable.1.5 1
ttable.0.6 1
ttable.1.7 1
}
pcm.ac101 {
type plug
slave {
pcm "hw:seeed8micvoicec"
channels 8
format S32_LE
rate 48000
}
ttable.0.0 1
ttable.1.1 1
ttable.0.2 1
ttable.1.3 1
ttable.0.4 1
ttable.1.5 1
ttable.0.6 1
ttable.1.7 1
}

View file

@ -1,4 +1,10 @@
dtoverlay -r seeed-voicecard
dtc -@ -I dts -O dtb -o seeed-voicecard.dtbo seeed-voicecard-overlay.dts
cp seeed-voicecard.dtbo /boot/overlays
dtoverlay seeed-voicecard
#!/bin/sh
#dtoverlay -r seeed-2mic-voicecard
DTC_FLAGS="-b 0 -Wno-unit_address_vs_reg -I dts -O dtb"
dtc -@ $DTC_FLAGS -o seeed-2mic-voicecard.dtbo seeed-2mic-voicecard-overlay.dts
dtc -@ $DTC_FLAGS -o seeed-4mic-voicecard.dtbo seeed-4mic-voicecard-overlay.dts
dtc -@ $DTC_FLAGS -o seeed-8mic-voicecard.dtbo seeed-8mic-voicecard-overlay.dts
# cp *.dtbo /boot/overlays
# dtoverlay seeed-2mic-voicecard

View file

@ -1,5 +1,15 @@
PACKAGE_NAME="seeed-voicecard"
PACKAGE_VERSION="0.1"
BUILT_MODULE_NAME[0]="wm8960"
PACKAGE_VERSION="0.3"
BUILT_MODULE_NAME[0]="snd-soc-wm8960"
BUILT_MODULE_NAME[1]="snd-soc-ac108"
BUILT_MODULE_NAME[2]="snd-soc-seeed-voicecard"
DEST_MODULE_LOCATION[0]="/kernel/sound/soc/codecs"
DEST_MODULE_LOCATION[1]="/kernel/sound/soc/codecs"
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"

View file

@ -5,22 +5,134 @@ if [[ $EUID -ne 0 ]]; then
exit 1
fi
# Check for enough space on /boot volume
boot_line=$(df -h | grep /boot | head -n 1)
if [ "x${boot_line}" = "x" ]; then
echo "Warning: /boot volume not found .."
else
boot_space=$(echo $boot_line | awk '{print $4;}')
free_space=$(echo "${boot_space%?}")
unit="${boot_space: -1}"
if [[ "$unit" = "K" ]]; then
echo "Error: Not enough space left ($boot_space) on /boot"
exit 1
elif [[ "$unit" = "M" ]]; then
if [ "$free_space" -lt "25" ]; then
echo "Error: Not enough space left ($boot_space) on /boot"
exit 1
fi
fi
fi
ver="0.1"
#
# make sure that we are on something ARM/Raspberry related
# either a bare metal Raspberry or a qemu session with
# Raspberry stuff available
# - check for /boot/overlays
# - dtparam and dtoverlay is available
errorFound=0
OVERLAYS=/boot/overlays
[ -d /boot/firmware/overlays ] && OVERLAYS=/boot/firmware/overlays
if [ ! -d $OVERLAYS ] ; then
echo "$OVERLAYS not found or not a directory" 1>&2
errorFound=1
fi
# should we also check for alsactl and amixer used in seeed-voicecard?
PATH=$PATH:/opt/vc/bin
for cmd in dtparam dtoverlay ; do
if ! which $cmd &>/dev/null ; then
echo "$cmd not found" 1>&2
echo "You may need to run ./ubuntu-prerequisite.sh"
errorFound=1
fi
done
if [ $errorFound = 1 ] ; then
echo "Errors found, exiting." 1>&2
exit 1
fi
ver="0.3"
uname_r=$(uname -r)
# we create a dir with this version to ensure that 'dkms remove' won't delete
# the sources during kernel updates
marker="0.0.0"
apt update
apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel
apt-get -y install dkms
_VER_RUN=
function get_kernel_version() {
local ZIMAGE IMG_OFFSET
_VER_RUN=""
[ -z "$_VER_RUN" ] && {
ZIMAGE=/boot/kernel.img
[ -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)
_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"
return 0
}
function check_kernel_headers() {
VER_RUN=$(get_kernel_version)
VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
[ "X$VER_RUN" == "X$VER_HDR" ] && {
return 0
}
VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
[ "X$VER_RUN" == "X$VER_HDR" ] && {
return 0
}
# echo RUN=$VER_RUN HDR=$VER_HDR
echo " !!! Your kernel version is $VER_RUN"
echo " Not found *** corresponding *** kernel headers with apt-get."
echo " This may occur if you have ran 'rpi-update'."
echo " Choose *** y *** will revert the kernel to version $VER_HDR then continue."
echo " Choose *** N *** will exit without this driver support, by default."
read -p "Would you like to proceed? (y/N)" -n 1 -r -s
echo
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
exit 1;
fi
apt-get -y --reinstall install raspberrypi-kernel
}
# update and install required packages
which apt &>/dev/null
if [[ $? -eq 0 ]]; then
apt update -y
# Raspbian kernel packages
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
apt-get -y install linux-raspi linux-headers-raspi linux-image-raspi
apt-get -y install dkms git i2c-tools libasound2-plugins
# rpi-update checker
check_kernel_headers
fi
# Arch Linux
which pacman &>/dev/null
if [[ $? -eq 0 ]]; then
pacman -Syu --needed git gcc automake make dkms linux-raspberrypi-headers i2c-tools
fi
# locate currently installed kernels (may be different to running kernel if
# it's just been updated)
kernels=$(ls /lib/modules | sed "s/^/-k /")
base_ver=$(get_kernel_version)
base_ver=${base_ver%%[-+]*}
#kernels="${base_ver}+ ${base_ver}-v7+ ${base_ver}-v7l+"
kernels=$(uname -r)
function install_module {
local _i
src=$1
mod=$2
@ -29,13 +141,19 @@ function install_module {
fi
if [[ -e /usr/src/$mod-$ver || -e /var/lib/dkms/$mod/$ver ]]; then
dkms remove -m $mod -v $ver --all
dkms remove --force -m $mod -v $ver --all
rm -rf /usr/src/$mod-$ver
fi
mkdir -p /usr/src/$mod-$ver
cp -a $src/* /usr/src/$mod-$ver/
dkms add -m $mod -v $ver
dkms build $kernels -m $mod -v $ver && dkms install $kernels -m $mod -v $ver
for _i in $kernels; do
dkms build -k $_i -m $mod -v $ver && {
dkms install --force -k $_i -m $mod -v $ver
}
done
mkdir -p /var/lib/dkms/$mod/$ver/$marker
}
@ -43,23 +161,61 @@ function install_module {
install_module "./" "seeed-voicecard"
(
cp seeed-voicecard.dtbo /boot/overlays
cp asound.state /var/lib/alsa/asound.state
)
# install dtbos
cp seeed-2mic-voicecard.dtbo $OVERLAYS
cp seeed-4mic-voicecard.dtbo $OVERLAYS
cp seeed-8mic-voicecard.dtbo $OVERLAYS
echo 'wm8960' | sudo tee --append /etc/modules > /dev/null
#install alsa plugins
# no need this plugin now
# install -D ac108_plugin/libasound_module_pcm_ac108.so /usr/lib/arm-linux-gnueabihf/alsa-lib/
rm -f /usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_ac108.so
sed -i \
-e "s/^dtparam=audio=on/#\0/" \
-e "s/^#\(dtparam=i2s=on\)/\1/" \
/boot/config.txt
grep -q "dtoverlay=i2s-mmap" /boot/config.txt || \
echo "dtoverlay=i2s-mmap" >> /boot/config.txt
grep -q "dtoverlay=seeed-voicecard" /boot/config.txt || \
echo "dtoverlay=seeed-voicecard" >> /boot/config.txt
grep -q "dtparam=i2s=on" /boot/config.txt || \
echo "dtparam=i2s=on" >> /boot/config.txt
#set kernel modules
grep -q "^snd-soc-seeed-voicecard$" /etc/modules || \
echo "snd-soc-seeed-voicecard" >> /etc/modules
grep -q "^snd-soc-ac108$" /etc/modules || \
echo "snd-soc-ac108" >> /etc/modules
grep -q "^snd-soc-wm8960$" /etc/modules || \
echo "snd-soc-wm8960" >> /etc/modules
#set dtoverlays
CONFIG=/boot/config.txt
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.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
grep -q "^dtoverlay=i2s-mmap$" $CONFIG || \
echo "dtoverlay=i2s-mmap" >> $CONFIG
grep -q "^dtparam=i2s=on$" $CONFIG || \
echo "dtparam=i2s=on" >> $CONFIG
#install config files
mkdir /etc/voicecard || true
cp *.conf /etc/voicecard
cp *.state /etc/voicecard
#create git repo
git_email=$(git config --global --get user.email)
git_name=$(git config --global --get user.name)
if [ "x${git_email}" == "x" ] || [ "x${git_name}" == "x" ] ; then
echo "setup git config"
git config --global user.email "respeaker@seeed.cc"
git config --global user.name "respeaker"
fi
echo "git init"
git --git-dir=/etc/voicecard/.git init
echo "git add --all"
git --git-dir=/etc/voicecard/.git --work-tree=/etc/voicecard/ add --all
echo "git commit -m \"origin configures\""
git --git-dir=/etc/voicecard/.git --work-tree=/etc/voicecard/ commit -m "origin configures"
cp seeed-voicecard /usr/bin/
cp seeed-voicecard.service /lib/systemd/system/
systemctl enable seeed-voicecard.service
systemctl start seeed-voicecard
echo "------------------------------------------------------"
echo "Please reboot your raspberry pi to apply all settings"

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

@ -0,0 +1,8 @@
SUBSYSTEM!="sound", GOTO="seeedvoicecard_end"
ACTION!="change", GOTO="seeedvoicecard_end"
KERNEL!="card*", GOTO="seeedvoicecard_end"
ATTR{id}=="seeed4micvoicec",ENV{PULSE_PROFILE_SET}="seeed-voicecard-4mic.conf"
ATTR{id}=="seeed8micvoicec",ENV{PULSE_PROFILE_SET}="seeed-voicecard-8mic.conf"
LABEL="seeedvoicecard_end"

251
pulseaudio/README.md Normal file
View file

@ -0,0 +1,251 @@
# PulseAudio Configuration for seeed-voicecard
Follow this guide if you want to use your seeed-voicecard as a default source/sink of pulseaudio.
### Prerequisites
1. Download PulseAudio
```
sudo apt install -y pulseaudio
```
2. PulseAudio Profiles
```
cd seeed-voicecard/pulseaudio
sudo cp pulse_config_4mic/seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voicecard-4mic.conf
sudo cp pulse_config_6mic/seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voicecard-8mic.conf
```
3. Add `udev` Rules
During the system start, when the card "seeed4micvoicec" is detected, the PULSE_PROFILE_SET variable will be set in the udev database, and PulseAudio will be forced to use `seeed-voicecard-4mic.conf`. Similarly, if the card "seeed8micvoicec" is detected, PulseAudio will be forced to use `seeed-voicecard-8mic.conf`.
```
sudo cp 91-seeedvoicecard.rules /etc/udev/rules.d/91-seeedvoicecard.rules
```
### ReSpeaker 4 Mic Array
<!--
1. Download pulseaudio
```
sudo apt install pulseaudio
```
2. First, you need to write [a profile for pulse](https://www.freedesktop.org/wiki/Software/PulseAudio/Backends/ALSA/Profiles/)
```
cd seeed-voicecard
cd pulseaudio
cd pulse_config_4mic
sudo cp seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/
```
3. Edit `udev rules`
During the system start, when the card "seeed4micvoicec" is detected, the PULSE_PROFILE_SET variable will be set in the udev database, and PulseAudio will be forced to use `seeed-voicecard.conf`.
```
# have a look at /lib/udev/rules.d/90-pulseaudio.rules
sudo vim /lib/udev/rules.d/90-pulseaudio.rules
# add the following lines at about line 87(behind the setting for some laptops and before the line GOTO="pulseaudio_end")
# Seeed Voicecard
ATTR{id}=="seeed4micvoicec",ATTR{number}=="1",ENV{PULSE_PROFILE_SET}="seeed-voicecard.conf"
```
![](./udev_rules_4mic.png)
The value of `ATTR{number}` can be found with:
```
udevadm info -a -p /sys/class/sound/card0/
# or udevadm info -a -p /sys/class/sound/card1/
```
For example, in Raspberry Pi, we can find `ATTR{id}=="seeed4micvoicec"` and `ATTR{number}=="1"` with command `udevadm info -a -p /sys/class/sound/card1/`:
```
pi@raspberrypi:~ $ udevadm info -a -p /sys/class/sound/card1/
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/platform/soc/soc:sound/sound/card1':
KERNEL=="card1"
SUBSYSTEM=="sound"
DRIVER==""
ATTR{id}=="seeed4micvoicec"
ATTR{number}=="1"
looking at parent device '/devices/platform/soc/soc:sound':
KERNELS=="soc:sound"
SUBSYSTEMS=="platform"
DRIVERS=="seeed-voicecard"
ATTRS{driver_override}=="(null)"
looking at parent device '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS==""
ATTRS{driver_override}=="(null)"
looking at parent device '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
``` -->
1. config `default.pa` and `daemon.conf`
```
sudo cp pulse_config_4mic/default.pa /etc/pulse/
sudo cp pulse_config_4mic/daemon.conf /etc/pulse/
```
2. reboot raspberry pi and check
```
sudo reboot
pulseaudio --start # start pulse at first
pactl info # check the setting
Server String: /run/user/1000/pulse/native
Library Protocol Version: 32
Server Protocol Version: 32
Is Local: yes
Client Index: 18
Tile Size: 65496
User Name: pi
Host Name: raspberrypi
Server Name: pulseaudio
Server Version: 10.0
Default Sample Specification: s16le 4ch 96000Hz
Default Channel Map: front-left,front-center,front-right,rear-center
Default Sink: alsa_output.platform-soc_audio.analog-stereo
Default Source: alsa_input.platform-soc_sound.seeed-source
Cookie: 3b12:70b3
```
### 6-Mics Circular Array Kit and 4-Mics Linear Array
<!--
1. Download pulseaudio
```
sudo apt install pulseaudio
```
2. First, you need to write [a profile for pulse](https://www.freedesktop.org/wiki/Software/PulseAudio/Backends/ALSA/Profiles/)
```
cd seeed-voicecard
cd pulseaudio
cd pulse_config_6mic
sudo cp seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/
```
3. Edit `udev rules`
During the system start, when the card "seeed8micvoicec" is detected, the PULSE_PROFILE_SET variable will be set in the udev database, and PulseAudio will be forced to use `seeed-voicecard.conf`.
```
# have a look at /lib/udev/rules.d/90-pulseaudio.rules
sudo vim /lib/udev/rules.d/90-pulseaudio.rules
# add the following lines at about line 87(behind the setting for some laptops and before the line GOTO="pulseaudio_end")
# Seeed Voicecard
ATTR{id}=="seeed8micvoicec",ATTR{number}=="1",ENV{PULSE_PROFILE_SET}="seeed-voicecard.conf"
```
![](./udev_rules_6mic.png)
The value of `ATTR{number}` can be found with:
```
udevadm info -a -p /sys/class/sound/card0/
# or udevadm info -a -p /sys/class/sound/card1/
```
For example, in Raspberry Pi, we can find `ATTR{id}=="seeed8micvoicec"` and `ATTR{number}=="1"` with command `udevadm info -a -p /sys/class/sound/card1/`:
```
pi@raspberrypi:~ $ udevadm info -a -p /sys/class/sound/card1/
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/platform/soc/soc:sound/sound/card1':
KERNEL=="card1"
SUBSYSTEM=="sound"
DRIVER==""
ATTR{id}=="seeed8micvoicec"
ATTR{number}=="1"
looking at parent device '/devices/platform/soc/soc:sound':
KERNELS=="soc:sound"
SUBSYSTEMS=="platform"
DRIVERS=="seeed-voicecard"
ATTRS{driver_override}=="(null)"
looking at parent device '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS==""
ATTRS{driver_override}=="(null)"
looking at parent device '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
``` -->
1. config `default.pa` and `daemon.conf`
```
sudo cp pulse_config_6mic/default.pa /etc/pulse/
sudo cp pulse_config_6mic/daemon.conf /etc/pulse/
```
2. reboot raspberry pi and check
```
sudo reboot
pulseaudio --start # start pulse at first
pactl info # check the setting
# The output should be like this
# You could see the default sink is seeed-2ch and default source is seeed-8ch
pi@raspberrypi:~ $ pactl info
Server String: /run/user/1000/pulse/native
Library Protocol Version: 32
Server Protocol Version: 32
Is Local: yes
Client Index: 6
Tile Size: 65496
User Name: pi
Host Name: raspberrypi
Server Name: pulseaudio
Server Version: 10.0
Default Sample Specification: s32le 8ch 96000Hz
Default Channel Map: front-left,front-left-of-center,front-center,front-right,front-right-of-center,rear-center,aux0,aux1
Default Sink: alsa_output.platform-soc_sound.seeed-2ch
Default Source: alsa_input.platform-soc_sound.seeed-8ch
Cookie: 3523:e5af
```
### FAQ
1. Default Sink/Source not right
Make sure there is no any other daemon or using the audio device. Then check profile and udev rules.
`pacmd list-sinks` and `pacmd list-sources` can be used to show the avaiable sinks/sources, after pulseaudio is started.
2. Can't start PulseAudio
Check `default.pa` and `daemon.conf`
3. How to get PulseAudio started automatically
Normally the PulseAudio server is started automatically. If you want to disable it, you can set `autospawn = no` in `~/.config/pulse/client.conf` or `/etc/pulse/client.conf`.
[Click this for more details](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Running/).
4. Why the default sample rate is 96000? What if my audio's sample rate is not the same as the default?
For the other sample rate audio, PulseAudio will resample it into 96K, which means that if your audio's sample rate is lower than 96K, it will get smoothing.

View file

@ -0,0 +1,87 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for
## more information. Default values are commented out. Use either ; or # for
## commenting.
; daemonize = no
; fail = yes
; allow-module-loading = yes
; allow-exit = yes
; use-pid-file = yes
; system-instance = no
; local-server-type = user
; enable-shm = yes
; enable-memfd = yes
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
; lock-memory = no
; cpu-limit = no
; high-priority = yes
; nice-level = -11
; realtime-scheduling = yes
; realtime-priority = 5
; exit-idle-time = 20
; scache-idle-time = 20
; dl-search-path = (depends on architecture)
; load-default-script-file = yes
; default-script-file = /etc/pulse/default.pa
; log-target = auto
; log-level = notice
; log-meta = no
; log-time = no
; log-backtrace = 0
; resample-method = speex-float-1
; enable-remixing = yes
; enable-lfe-remixing = no
; lfe-crossover-freq = 0
; flat-volumes = yes
; rlimit-fsize = -1
; rlimit-data = -1
; rlimit-stack = -1
; rlimit-core = -1
; rlimit-as = -1
; rlimit-rss = -1
; rlimit-nproc = -1
; rlimit-nofile = 256
; rlimit-memlock = -1
; rlimit-locks = -1
; rlimit-sigpending = -1
; rlimit-msgqueue = -1
; rlimit-nice = 31
; rlimit-rtprio = 9
; rlimit-rttime = 200000
default-sample-format = s16le
default-sample-rate = 96000
; alternate-sample-rate = 48000
default-sample-channels = 4
; default-channel-map = front-left,front-right
; default-fragments = 4
; default-fragment-size-msec = 25
; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
; deferred-volume-extra-delay-usec = 0

View file

@ -0,0 +1,144 @@
#!/usr/bin/pulseaudio -nF
#
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
# This startup script is used only if PulseAudio is started per-user
# (i.e. not in system mode)
.fail
### Automatically restore the volume of streams and devices
load-module module-device-restore
load-module module-stream-restore
load-module module-card-restore
### Automatically augment property information from .desktop files
### stored in /usr/share/application
load-module module-augment-properties
### Should be after module-*-restore but before module-*-detect
load-module module-switch-on-port-available
### Load audio drivers statically
### (it's probably better to not load these drivers manually, but instead
### use module-udev-detect -- see below -- for doing this automatically)
#load-module module-alsa-sink device="hw:1,0" channels=8 rate=48000 format=s32le
#load-module module-alsa-source device="hw:1,0" channels=8 rate=48000 format=s32le
#load-module module-oss device="/dev/dsp" sink_name=output source_name=input
#load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
#load-module module-null-sink
#load-module module-pipe-sink
### Automatically load driver modules depending on the hardware available
.ifexists module-udev-detect.so
load-module module-udev-detect
#channels=8 rate=48000 format=s32le
.else
### Use the static hardware detection module (for systems that lack udev support)
load-module module-detect
.endif
### Automatically connect sink and source if JACK server is present
.ifexists module-jackdbus-detect.so
.nofail
load-module module-jackdbus-detect channels=2
.fail
.endif
### Automatically load driver modules for Bluetooth hardware
.ifexists module-bluetooth-policy.so
load-module module-bluetooth-policy
.endif
.ifexists module-bluetooth-discover.so
load-module module-bluetooth-discover
.endif
### Load several protocols
.ifexists module-esound-protocol-unix.so
load-module module-esound-protocol-unix
.endif
load-module module-native-protocol-unix
### Network access (may be configured with paprefs, so leave this commented
### here if you plan to use paprefs)
#load-module module-esound-protocol-tcp
#load-module module-native-protocol-tcp
#load-module module-zeroconf-publish
### Load the RTP receiver module (also configured via paprefs, see above)
#load-module module-rtp-recv
### Load the RTP sender module (also configured via paprefs, see above)
#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
#load-module module-rtp-send source=rtp.monitor
### Load additional modules from GConf settings. This can be configured with the paprefs tool.
### Please keep in mind that the modules configured by paprefs might conflict with manually
### loaded modules.
.ifexists module-gconf.so
.nofail
load-module module-gconf
.fail
.endif
### Automatically restore the default sink/source when changed by the user
### during runtime
### NOTE: This should be loaded as early as possible so that subsequent modules
### that look up the default sink/source get the right value
load-module module-default-device-restore
### Automatically move streams to the default sink if the sink they are
### connected to dies, similar for sources
load-module module-rescue-streams
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
### Honour intended role device property
load-module module-intended-roles
### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle
### If autoexit on idle is enabled we want to make sure we only quit
### when no local session needs us anymore.
.ifexists module-console-kit.so
load-module module-console-kit
.endif
.ifexists module-systemd-login.so
load-module module-systemd-login
.endif
### Enable positioned event sounds
load-module module-position-event-sounds
### Cork music/video streams when a phone stream is active
load-module module-role-cork
### Modules to allow autoloading of filters (such as echo cancellation)
### on demand. module-filter-heuristics tries to determine what filters
### make sense, and module-filter-apply does the heavy-lifting of
### loading modules and rerouting streams.
load-module module-filter-heuristics
load-module module-filter-apply
### Make some devices default
#set-default-sink output
#set-default-source input
set-default-source alsa_input.platform-soc_sound.seeed-source
set-default-sink alsa_output.platform-soc_sound.seeed-sink

View file

@ -0,0 +1,17 @@
# /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voicecard.conf
[General]
auto-profiles = no
[Mapping seeed-source]
device-strings = hw:%f
channel-map = front-left,front-right,rear-left,rear-right
exact-channels = false
fallback = yes
paths-input = seeed-source
priority = 3
direction = input
[Profile input:seeed-source]
input-mappings = seeed-source
priority = 5
skip-probe = yes

View file

@ -0,0 +1,87 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for
## more information. Default values are commented out. Use either ; or # for
## commenting.
; daemonize = no
; fail = yes
; allow-module-loading = yes
; allow-exit = yes
; use-pid-file = yes
; system-instance = no
; local-server-type = user
; enable-shm = yes
; enable-memfd = yes
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
; lock-memory = no
; cpu-limit = no
; high-priority = yes
; nice-level = -11
; realtime-scheduling = yes
; realtime-priority = 5
; exit-idle-time = 20
; scache-idle-time = 20
; dl-search-path = (depends on architecture)
; load-default-script-file = yes
; default-script-file = /etc/pulse/default.pa
; log-target = auto
; log-level = notice
; log-meta = no
; log-time = no
; log-backtrace = 0
; resample-method = speex-float-1
; enable-remixing = yes
; enable-lfe-remixing = no
; lfe-crossover-freq = 0
; flat-volumes = yes
; rlimit-fsize = -1
; rlimit-data = -1
; rlimit-stack = -1
; rlimit-core = -1
; rlimit-as = -1
; rlimit-rss = -1
; rlimit-nproc = -1
; rlimit-nofile = 256
; rlimit-memlock = -1
; rlimit-locks = -1
; rlimit-sigpending = -1
; rlimit-msgqueue = -1
; rlimit-nice = 31
; rlimit-rtprio = 9
; rlimit-rttime = 200000
default-sample-format = s32le
default-sample-rate = 96000
; alternate-sample-rate = 48000
default-sample-channels = 8
; default-channel-map = front-left,front-right
; default-fragments = 4
; default-fragment-size-msec = 25
; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
; deferred-volume-extra-delay-usec = 0

View file

@ -0,0 +1,143 @@
#!/usr/bin/pulseaudio -nF
#
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
# This startup script is used only if PulseAudio is started per-user
# (i.e. not in system mode)
.fail
### Automatically restore the volume of streams and devices
load-module module-device-restore
load-module module-stream-restore
load-module module-card-restore
### Automatically augment property information from .desktop files
### stored in /usr/share/application
load-module module-augment-properties
### Should be after module-*-restore but before module-*-detect
load-module module-switch-on-port-available
### Load audio drivers statically
### (it's probably better to not load these drivers manually, but instead
### use module-udev-detect -- see below -- for doing this automatically)
#load-module module-alsa-sink device="hw:1,0" channels=8 rate=48000 format=s32le
#load-module module-alsa-source device="hw:1,0" channels=8 rate=48000 format=s32le
#load-module module-oss device="/dev/dsp" sink_name=output source_name=input
#load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
#load-module module-null-sink
#load-module module-pipe-sink
### Automatically load driver modules depending on the hardware available
.ifexists module-udev-detect.so
load-module module-udev-detect
#channels=8 rate=48000 format=s32le
.else
### Use the static hardware detection module (for systems that lack udev support)
load-module module-detect
.endif
### Automatically connect sink and source if JACK server is present
.ifexists module-jackdbus-detect.so
.nofail
load-module module-jackdbus-detect channels=2
.fail
.endif
### Automatically load driver modules for Bluetooth hardware
.ifexists module-bluetooth-policy.so
load-module module-bluetooth-policy
.endif
.ifexists module-bluetooth-discover.so
load-module module-bluetooth-discover
.endif
### Load several protocols
.ifexists module-esound-protocol-unix.so
load-module module-esound-protocol-unix
.endif
load-module module-native-protocol-unix
### Network access (may be configured with paprefs, so leave this commented
### here if you plan to use paprefs)
#load-module module-esound-protocol-tcp
#load-module module-native-protocol-tcp
#load-module module-zeroconf-publish
### Load the RTP receiver module (also configured via paprefs, see above)
#load-module module-rtp-recv
### Load the RTP sender module (also configured via paprefs, see above)
#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
#load-module module-rtp-send source=rtp.monitor
### Load additional modules from GConf settings. This can be configured with the paprefs tool.
### Please keep in mind that the modules configured by paprefs might conflict with manually
### loaded modules.
.ifexists module-gconf.so
.nofail
load-module module-gconf
.fail
.endif
### Automatically restore the default sink/source when changed by the user
### during runtime
### NOTE: This should be loaded as early as possible so that subsequent modules
### that look up the default sink/source get the right value
load-module module-default-device-restore
### Automatically move streams to the default sink if the sink they are
### connected to dies, similar for sources
load-module module-rescue-streams
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
### Honour intended role device property
load-module module-intended-roles
### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle
### If autoexit on idle is enabled we want to make sure we only quit
### when no local session needs us anymore.
.ifexists module-console-kit.so
load-module module-console-kit
.endif
.ifexists module-systemd-login.so
load-module module-systemd-login
.endif
### Enable positioned event sounds
load-module module-position-event-sounds
### Cork music/video streams when a phone stream is active
load-module module-role-cork
### Modules to allow autoloading of filters (such as echo cancellation)
### on demand. module-filter-heuristics tries to determine what filters
### make sense, and module-filter-apply does the heavy-lifting of
### loading modules and rerouting streams.
load-module module-filter-heuristics
load-module module-filter-apply
### Make some devices default
#set-default-sink output
#set-default-source input
set-default-source alsa_input.platform-soc_sound.seeed-8ch
set-default-sink alsa_output.platform-soc_sound.seeed-2ch

View file

@ -0,0 +1,34 @@
# /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voiced.conf
[General]
auto-profiles = no
[Mapping seeed-8ch]
device-strings = hw:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
exact-channels = false
fallback = yes
paths-input = seeed-8ch
priority = 3
direction = input
[Mapping seeed-2ch]
device-strings = hw:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
exact-channels = false
exact-channels = false
fallback = yes
paths-output = seeed-2ch
direction = output
priority = 2
[Profile output:seeed-2ch+input:seeed-8ch]
output-mappings = seeed-2ch
input-mappings = seeed-8ch
priority = 100
skip-probe = yes
[Profile output:seeed-2ch]
output-mappings = seeed-2ch
priority = 4
skip-probe = yes
[Profile input:seeed-8ch]
input-mappings = seeed-8ch
priority = 5
skip-probe = yes

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

View file

@ -38,49 +38,13 @@
};
};
fragment@3 {
target = <&sound>;
master_overlay: __dormant__ {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "seeed-voicecard";
simple-audio-card,bitclock-master = <&dailink0_master>;
simple-audio-card,frame-master = <&dailink0_master>;
status = "okay";
simple-audio-card,widgets =
"Microphone", "Mic Jack",
"Line", "Line In",
"Line", "Line Out",
"Speaker", "Speaker",
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"Headphone Jack", "HP_L",
"Headphone Jack", "HP_R",
"Speaker", "SPK_LP",
"Speaker", "SPK_LN",
"LINPUT1", "Mic Jack",
"LINPUT3", "Mic Jack",
"RINPUT1", "Mic Jack",
"RINPUT2", "Mic Jack";
simple-audio-card,cpu {
sound-dai = <&i2s>;
};
dailink0_master: simple-audio-card,codec {
sound-dai = <&wm8960>;
clocks = <&wm8960_mclk>;
clock-names = "mclk";
};
};
};
fragment@4 {
target = <&sound>;
slave_overlay: __overlay__ {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "seeed-voicecard";
simple-audio-card,name = "seeed-2mic-voicecard";
status = "okay";
simple-audio-card,widgets =
"Microphone", "Mic Jack",
@ -114,8 +78,7 @@
};
__overrides__ {
alsaname = <&master_overlay>,"simple-audio-card,name",
<&slave_overlay>,"simple-audio-card,name";
alsaname = <&slave_overlay>,"simple-audio-card,name";
compatible = <&wm8960>,"compatible";
master = <0>,"=2!3";
};

BIN
seeed-2mic-voicecard.dtbo Normal file

Binary file not shown.

View file

@ -0,0 +1,75 @@
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2708";
fragment@0 {
target = <&i2s>;
__overlay__ {
#sound-dai-cells = <0>;
status = "okay";
};
};
fragment@1 {
target-path = "/";
__overlay__ {
ac108_mclk: codec-mclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
};
};
};
fragment@2 {
target = <&i2c1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
ac108_a: ac108@3b{
compatible = "x-power,ac108_0";
reg = <0x3b>;
#sound-dai-cells = <0>;
data-protocol = <0>;
};
};
};
fragment@3 {
target = <&sound>;
sound_overlay: __overlay__ {
compatible = "seeed-voicecard";
seeed-voice-card,format = "dsp_a";
seeed-voice-card,name = "seeed-4mic-voicecard";
status = "okay";
seeed-voice-card,bitclock-master = <&codec_dai>;
seeed-voice-card,frame-master = <&codec_dai>;
seeed-voice-card,channels-playback-override = <4>;
seeed-voice-card,channels-capture-override = <4>;
cpu_dai: seeed-voice-card,cpu {
sound-dai = <&i2s>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <32>;
dai-tdm-slot-tx-mask = <1 1 0 0>;
dai-tdm-slot-rx-mask = <1 1 0 0>;
};
codec_dai: seeed-voice-card,codec {
sound-dai = <&ac108_a>;
clocks = <&ac108_mclk>;
};
};
};
__overrides__ {
card-name = <&sound_overlay>,"seeed-voice-card,name";
};
};

BIN
seeed-4mic-voicecard.dtbo Normal file

Binary file not shown.

View file

@ -0,0 +1,118 @@
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2708";
fragment@0 {
target = <&i2s>;
__overlay__ {
#sound-dai-cells = <0>;
status = "okay";
};
};
fragment@1 {
target-path = "/";
__overlay__ {
ac10x_mclk: codec-mclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
};
};
};
fragment@2 {
target = <&gpio>;
__overlay__ {
spk_amp_pins: spk_pins {
brcm,pins = <17 22>;
brcm,function = <1 0>; /* out in */
brcm,pull = <0 0>; /* - - */
};
gpclk0_pins: gpclk0_pins {
brcm,pins = <4>;
brcm,function = <4>; /* alt func 0 */
brcm,pull = <0>; /* - */
};
};
};
fragment@3 {
target = <&i2c1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
ac101: ac101@1a{
compatible = "x-power,ac101";
pinctrl-names = "default";
pinctrl-0 = <&spk_amp_pins &gpclk0_pins>;
spk-amp-switch-gpios = <&gpio 17 0>;
switch-irq-gpios = <&gpio 22 0>;
reg = <0x1a>;
#sound-dai-cells = <0>;
};
ac108_a: ac108@35{
compatible = "x-power,ac108_0";
reg = <0x35>;
#sound-dai-cells = <0>;
data-protocol = <0>;
tdm-chips-count = <2>;
};
ac108_b: ac108@3b{
compatible = "x-power,ac108_1";
reg = <0x3b>;
#sound-dai-cells = <0>;
data-protocol = <0>;
tdm-chips-count = <2>;
};
};
};
fragment@4 {
target = <&sound>;
sound_overlay: __overlay__ {
compatible = "seeed-voicecard";
seeed-voice-card,name = "seeed-8mic-voicecard";
seeed-voice-card,channels-playback-override = <8>;
seeed-voice-card,channels-capture-override = <8>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
seeed-voice-card,dai-link@0 {
format = "dsp_a";
bitclock-master = <&codec0_dai>;
frame-master = <&codec0_dai>;
/* bitclock-inversion; */
/* frame-inversion; */
reg = <0>;
cpu {
sound-dai = <&i2s>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <32>;
dai-tdm-slot-tx-mask = <1 1 0 0>;
dai-tdm-slot-rx-mask = <1 1 0 0>;
};
codec0_dai: codec {
sound-dai = <&ac108_a>;
clocks = <&ac10x_mclk>;
system-clock-id = <1>;
};
};
};
};
__overrides__ {
card-name = <&sound_overlay>,"seeed-voice-card,name";
};
};

BIN
seeed-8mic-voicecard.dtbo Normal file

Binary file not shown.

163
seeed-voicecard Executable file
View file

@ -0,0 +1,163 @@
#!/bin/bash
#
# Copyright (c) 2018 Baozhu Zuo <zuobaozhu@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
set -x
#exec 1>/var/log/$(basename $0).log 2>&1
export PATH=$PATH:/opt/vc/bin
OVERLAYS=/boot/overlays
[ -d /boot/firmware/overlays ] && OVERLAYS=/boot/firmware/overlays
#enable i2c interface
dtparam -d $OVERLAYS i2c_arm=on
modprobe i2c-dev
#enable spi interface
dtparam -d $OVERLAYS spi=on
_VER_RUN=
function get_kernel_version() {
local ZIMAGE IMG_OFFSET
_VER_RUN=""
[ -z "$_VER_RUN" ] && {
ZIMAGE=/boot/kernel.img
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
# 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"
return 0
}
CONFIG=/boot/config.txt
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
get_overlay() {
ov=$1
if grep -q -E "^dtoverlay=$ov" $CONFIG; then
echo 0
else
echo 1
fi
}
do_overlay() {
ov=$1
RET=$2
DEFAULT=--defaultno
CURRENT=0
if [ $(get_overlay $ov) -eq 0 ]; then
DEFAULT=
CURRENT=1
fi
if [ $RET -eq $CURRENT ]; then
ASK_TO_REBOOT=1
fi
if [ $RET -eq 0 ]; then
sed $CONFIG -i -e "s/^#dtoverlay=$ov/dtoverlay=$ov/"
if ! grep -q -E "^dtoverlay=$ov" $CONFIG; then
printf "dtoverlay=$ov\n" >> $CONFIG
fi
STATUS=enabled
elif [ $RET -eq 1 ]; then
sed $CONFIG -i -e "s/^dtoverlay=$ov/#dtoverlay=$ov/"
STATUS=disabled
else
return $RET
fi
}
is_1a=$(i2cdetect -y 1 0x1a 0x1a | egrep "(1a|UU)" | awk '{print $2}')
is_35=$(i2cdetect -y 1 0x35 0x35 | egrep "(35|UU)" | awk '{print $2}')
is_3b=$(i2cdetect -y 1 0x3b 0x3b | egrep "(3b|UU)" | awk '{print $2}')
RPI_HATS="seeed-2mic-voicecard seeed-4mic-voicecard seeed-8mic-voicecard"
overlay=""
if [ "x${is_1a}" != "x" ] && [ "x${is_35}" == "x" ] ; then
echo "install 2mic"
overlay=seeed-2mic-voicecard
asound_conf=/etc/voicecard/asound_2mic.conf
asound_state=/etc/voicecard/wm8960_asound.state
fi
if [ "x${is_3b}" != "x" ] && [ "x${is_35}" == "x" ] ; then
echo "install 4mic"
overlay=seeed-4mic-voicecard
asound_conf=/etc/voicecard/asound_4mic.conf
asound_state=/etc/voicecard/ac108_asound.state
fi
if [ "x${is_3b}" != "x" ] && [ "x${is_35}" != "x" ] ; then
echo "install 6mic"
overlay=seeed-8mic-voicecard
asound_conf=/etc/voicecard/asound_6mic.conf
asound_state=/etc/voicecard/ac108_6mic.state
fi
if [ "$overlay" ]; then
echo Install $overlay ...
# Remove old configuration
rm /etc/asound.conf
rm /var/lib/alsa/asound.state
kernel_ver=$(uname -r) # get_kernel_version)
# echo kernel_ver=$kernel_ver
# TODO: dynamic dtoverlay Bug of v4.19.x
# no DT node phandle inserted.
if [[ "$kernel_ver" =~ ^4\.19.*$ || "$kernel_ver" =~ ^5\.*$ ]]; then
for i in $RPI_HATS; do
if [ "$i" == "$overlay" ]; then
/bin/true #do_overlay $overlay 0
else
echo Uninstall $i ...
/bin/true #do_overlay $i 1
fi
done
fi
#make sure the driver loads correctly
dtoverlay -d $OVERLAYS $overlay || true
echo "create $overlay asound configure file"
ln -s $asound_conf /etc/asound.conf
echo "create $overlay asound status file"
ln -s $asound_state /var/lib/alsa/asound.state
fi
alsactl restore
#Force 3.5mm ('headphone') jack
# The Raspberry Pi 4, released on 24th Jun 2019, has two HDMI ports,
# and can drive two displays with audios for two users simultaneously,
# in a "multiseat" configuration. The earlier single virtual ALSA
# option for re-directing audio playback between headphone jack and HDMI
# via a 'Routing' mixer setting was turned off eventually to allow
# simultaneous usage of all 3 playback devices.
if aplay -l | grep -q "bcm2835 ALSA"; then
amixer cset numid=3 1 || true
fi

926
seeed-voicecard.c Normal file
View file

@ -0,0 +1,926 @@
/*
* SEEED voice card
*
* (C) Copyright 2017-2018
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
*
* base on ASoC simple sound card support
*
* Copyright (C) 2012 Renesas Solutions Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/* #undef DEBUG */
#include <linux/version.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#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))
#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:
* 0 - allow multi codec
* 1 - yes
*/
#define _SINGLE_CODEC 1
struct seeed_card_data {
struct snd_soc_card snd_card;
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;
unsigned channels_playback_default;
unsigned channels_playback_override;
unsigned channels_capture_default;
unsigned channels_capture_override;
struct snd_soc_dai_link *dai_link;
#if CONFIG_AC10X_TRIG_LOCK
spinlock_t lock;
#endif
struct work_struct work_codec_clk;
#define TRY_STOP_MAX 3
int try_stop;
};
struct seeed_card_info {
const char *name;
const char *card;
const char *codec;
const char *platform;
unsigned int daifmt;
struct asoc_simple_dai cpu_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_link(priv, i) ((priv)->snd_card.dai_link + (i))
#define seeed_priv_to_props(priv, i) ((priv)->dai_props + (i))
#define DAI "sound-dai"
#define CELL "#sound-dai-cells"
#define PREFIX "seeed-voice-card,"
static int seeed_voice_card_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
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);
int ret;
ret = clk_prepare_enable(dai_props->cpu_dai.clk);
if (ret)
return ret;
ret = clk_prepare_enable(dai_props->codec_dai.clk);
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 (asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min) {
priv->channels_capture_default = asoc_rtd_to_cpu(rtd, 0)->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;
return ret;
}
static void seeed_voice_card_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
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);
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;
clk_disable_unprepare(dai_props->cpu_dai.clk);
clk_disable_unprepare(dai_props->codec_dai.clk);
}
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 seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
unsigned int mclk, mclk_fs = 0;
int ret = 0;
if (priv->mclk_fs)
mclk_fs = priv->mclk_fs;
else if (dai_props->mclk_fs)
mclk_fs = dai_props->mclk_fs;
if (mclk_fs) {
mclk = params_rate(params) * mclk_fs;
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
SND_SOC_CLOCK_IN);
if (ret && ret != -ENOTSUPP)
goto err;
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
SND_SOC_CLOCK_OUT);
if (ret && ret != -ENOTSUPP)
goto err;
}
return 0;
err:
return ret;
}
#define _SET_CLOCK_CNT 2
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, struct snd_pcm_substream *, int, struct snd_soc_dai *)) {
if (! _set_clock[stream]) {
_set_clock[stream] = set_clock;
}
return 0;
}
EXPORT_SYMBOL(seeed_voice_card_register_set_clock);
/*
* work_cb_codec_clk: clear audio codec inner clock.
*/
static void work_cb_codec_clk(struct work_struct *work)
{
struct seeed_card_data *priv = container_of(work, struct seeed_card_data, work_codec_clk);
int r = 0;
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) {
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]) {
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 (0 != schedule_work(&priv->work_codec_clk)) {}
}
return;
}
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 seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
#if CONFIG_AC10X_TRIG_LOCK
unsigned long flags;
#endif
int ret = 0;
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (cancel_work_sync(&priv->work_codec_clk) != 0) {}
#if CONFIG_AC10X_TRIG_LOCK
/* I know it will degrades performance, but I have no choice */
spin_lock_irqsave(&priv->lock, flags);
#endif
// 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, substream, cmd, dai);
#if CONFIG_AC10X_TRIG_LOCK
spin_unlock_irqrestore(&priv->lock, flags);
#endif
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* capture channel resync, if overrun */
if (dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
break;
}
/* interrupt environment */
if (in_irq() || in_nmi() || in_serving_softirq()) {
priv->try_stop = 0;
if (0 != schedule_work(&priv->work_codec_clk)) {
}
} else {
// 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, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
}
break;
default:
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;
}
static struct snd_soc_ops seeed_voice_card_ops = {
.startup = seeed_voice_card_startup,
.shutdown = seeed_voice_card_shutdown,
.hw_params = seeed_voice_card_hw_params,
.trigger = seeed_voice_card_trigger,
};
static int asoc_simple_parse_dai(struct device_node *node,
struct snd_soc_dai_link_component *dlc,
int *is_single_link)
{
struct of_phandle_args args;
int ret;
if (!node)
return 0;
/*
* Get node via "sound-dai = <&phandle port>"
* it will be used as xxx_of_node on soc_bind_dai_link()
*/
ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
if (ret)
return ret;
/*
* FIXME
*
* Here, dlc->dai_name is pointer to CPU/Codec DAI name.
* If user unbinded CPU or Codec driver, but not for Sound Card,
* dlc->dai_name is keeping unbinded CPU or Codec
* driver's pointer.
*
* If user re-bind CPU or Codec driver again, ALSA SoC will try
* to rebind Card via snd_soc_try_rebind_card(), but because of
* above reason, it might can't bind Sound Card.
* Because Sound Card is pointing to released dai_name pointer.
*
* To avoid this rebind Card issue,
* 1) It needs to alloc memory to keep dai_name eventhough
* CPU or Codec driver was unbinded, or
* 2) user need to rebind Sound Card everytime
* if he unbinded CPU or Codec.
*/
ret = snd_soc_of_get_dai_name(node, &dlc->dai_name, 0);
if (ret < 0)
return ret;
dlc->of_node = args.np;
if (is_single_link)
*is_single_link = !args.args_count;
return 0;
}
static int asoc_simple_init_dai(struct snd_soc_dai *dai,
struct asoc_simple_dai *simple_dai)
{
int ret;
if (!simple_dai)
return 0;
if (simple_dai->sysclk) {
ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk,
simple_dai->clk_direction);
if (ret && ret != -ENOTSUPP) {
dev_err(dai->dev, "simple-card: set_sysclk error\n");
return ret;
}
}
if (simple_dai->slots) {
ret = snd_soc_dai_set_bclk_ratio(dai,
simple_dai->slots *
simple_dai->slot_width);
if (ret && ret != -ENOTSUPP) {
dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
return ret;
}
}
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)
{
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 seeed_dai_props *dai_props =
seeed_priv_to_props(priv, rtd->num);
int ret;
ret = asoc_simple_init_dai(codec, &dai_props->codec_dai);
if (ret < 0)
return ret;
ret = asoc_simple_init_dai(cpu, &dai_props->cpu_dai);
if (ret < 0)
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;
}
static int seeed_voice_card_dai_link_of(struct device_node *node,
struct seeed_card_data *priv,
int idx,
bool is_top_level_node)
{
struct device *dev = seeed_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link = seeed_priv_to_link(priv, idx);
struct seeed_dai_props *dai_props = seeed_priv_to_props(priv, idx);
struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
struct device_node *cpu = NULL;
struct device_node *plat = NULL;
struct device_node *codec = NULL;
char prop[128];
char *prefix = "";
int ret, single_cpu;
/* For single DAI link & old style of DT node */
if (is_top_level_node)
prefix = PREFIX;
snprintf(prop, sizeof(prop), "%scpu", prefix);
cpu = of_get_child_by_name(node, prop);
if (!cpu) {
ret = -EINVAL;
dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
goto dai_link_of_err;
}
snprintf(prop, sizeof(prop), "%splat", prefix);
plat = of_get_child_by_name(node, prop);
snprintf(prop, sizeof(prop), "%scodec", prefix);
codec = of_get_child_by_name(node, prop);
if (!codec) {
ret = -EINVAL;
dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
goto dai_link_of_err;
}
ret = asoc_simple_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);
if (ret < 0)
goto dai_link_of_err;
#if _SINGLE_CODEC
ret = asoc_simple_parse_codec(codec, dai_link);
if (ret < 0)
goto dai_link_of_err;
#else
ret = snd_soc_of_get_dai_link_codecs(dev, codec, dai_link);
if (ret < 0) {
dev_err(dev, "parse codec info error %d\n", ret);
goto dai_link_of_err;
}
dev_dbg(dev, "dai_link num_codecs = %d\n", dai_link->num_codecs);
#endif
ret = asoc_simple_parse_platform(plat, dai_link);
if (ret < 0)
goto dai_link_of_err;
ret = snd_soc_of_parse_tdm_slot(cpu, &cpu_dai->tx_slot_mask,
&cpu_dai->rx_slot_mask,
&cpu_dai->slots,
&cpu_dai->slot_width);
dev_dbg(dev, "cpu_dai : slot,width,tx,rx = %d,%d,%d,%d\n",
cpu_dai->slots, cpu_dai->slot_width,
cpu_dai->tx_slot_mask, cpu_dai->rx_slot_mask
);
if (ret < 0)
goto dai_link_of_err;
ret = snd_soc_of_parse_tdm_slot(codec, &codec_dai->tx_slot_mask,
&codec_dai->rx_slot_mask,
&codec_dai->slots,
&codec_dai->slot_width);
if (ret < 0)
goto dai_link_of_err;
#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);
#endif
if (ret < 0)
goto dai_link_of_err;
#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);
#endif
if (ret < 0)
goto dai_link_of_err;
ret = asoc_simple_set_dailink_name(dev, dai_link,
"%s-%s",
dai_link->cpus->dai_name,
#if _SINGLE_CODEC
dai_link->codecs->dai_name
#else
dai_link->codecs[0].dai_name
#endif
);
if (ret < 0)
goto dai_link_of_err;
dai_link->ops = &seeed_voice_card_ops;
dai_link->init = seeed_voice_card_dai_init;
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_props->cpu_dai.sysclk);
dev_dbg(dev, "\tcodec : %s / %d\n",
#if _SINGLE_CODEC
dai_link->codecs->dai_name,
#else
dai_link->codecs[0].dai_name,
#endif
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);
#if _SINGLE_CODEC
asoc_simple_canonicalize_platform(dai_link);
#endif
#endif
dai_link_of_err:
of_node_put(cpu);
of_node_put(codec);
return ret;
}
static int seeed_voice_card_parse_aux_devs(struct device_node *node,
struct seeed_card_data *priv)
{
struct device *dev = seeed_priv_to_dev(priv);
struct device_node *aux_node;
int i, n, len;
if (!of_find_property(node, PREFIX "aux-devs", &len))
return 0; /* Ok to have no aux-devs */
n = len / sizeof(__be32);
if (n <= 0)
return -EINVAL;
priv->snd_card.aux_dev = devm_kzalloc(dev,
n * sizeof(*priv->snd_card.aux_dev), GFP_KERNEL);
if (!priv->snd_card.aux_dev)
return -ENOMEM;
for (i = 0; i < n; i++) {
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.num_aux_devs = n;
return 0;
}
static int seeed_voice_card_parse_of(struct device_node *node,
struct seeed_card_data *priv)
{
struct device *dev = seeed_priv_to_dev(priv);
struct device_node *dai_link;
int ret;
if (!node)
return -EINVAL;
dai_link = of_get_child_by_name(node, PREFIX "dai-link");
/* The off-codec widgets */
if (of_property_read_bool(node, PREFIX "widgets")) {
ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card,
PREFIX "widgets");
if (ret)
goto card_parse_end;
}
/* DAPM routes */
if (of_property_read_bool(node, PREFIX "routing")) {
ret = snd_soc_of_parse_audio_routing(&priv->snd_card,
PREFIX "routing");
if (ret)
goto card_parse_end;
}
/* Factor to mclk, used in hw_params() */
of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);
/* Single/Muti DAI link(s) & New style of DT node */
if (dai_link) {
struct device_node *np = NULL;
int i = 0;
for_each_child_of_node(node, np) {
dev_dbg(dev, "\tlink %d:\n", i);
ret = seeed_voice_card_dai_link_of(np, priv,
i, false);
if (ret < 0) {
of_node_put(np);
goto card_parse_end;
}
i++;
}
} else {
/* For single DAI link & old style of DT node */
ret = seeed_voice_card_dai_link_of(node, priv, 0, true);
if (ret < 0)
goto card_parse_end;
}
ret = asoc_simple_parse_card_name(&priv->snd_card, PREFIX);
if (ret < 0)
goto card_parse_end;
ret = seeed_voice_card_parse_aux_devs(node, priv);
priv->channels_playback_default = 0;
priv->channels_playback_override = 2;
priv->channels_capture_default = 0;
priv->channels_capture_override = 2;
of_property_read_u32(node, PREFIX "channels-playback-default",
&priv->channels_playback_default);
of_property_read_u32(node, PREFIX "channels-playback-override",
&priv->channels_playback_override);
of_property_read_u32(node, PREFIX "channels-capture-default",
&priv->channels_capture_default);
of_property_read_u32(node, PREFIX "channels-capture-override",
&priv->channels_capture_override);
card_parse_end:
of_node_put(dai_link);
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)
{
struct seeed_card_data *priv;
struct snd_soc_dai_link *dai_link;
struct seeed_dai_props *dai_props;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
int num, ret, i;
/* Get the number of DAI links */
if (np && of_get_child_by_name(np, PREFIX "dai-link"))
num = of_get_child_count(np);
else
num = 1;
/* Allocate the private data and the DAI link array */
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
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;
/* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE;
priv->snd_card.dev = dev;
priv->snd_card.dai_link = priv->dai_link;
priv->snd_card.num_links = num;
if (np && of_device_is_available(np)) {
ret = seeed_voice_card_parse_of(np, priv);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "parse error %d\n", ret);
goto err;
}
} 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) {
dev_err(dev, "no info for seeed-voice-card\n");
return -EINVAL;
}
if (!cinfo->name ||
!cinfo->codec_dai.name ||
!cinfo->codec ||
!cinfo->platform ||
!cinfo->cpu_dai.name) {
dev_err(dev, "insufficient seeed_voice_card_info settings\n");
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->dai_fmt = cinfo->daifmt;
dai_link->init = seeed_voice_card_dai_init;
memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
sizeof(priv->dai_props->cpu_dai));
memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
sizeof(priv->dai_props->codec_dai));
}
snd_soc_card_set_drvdata(&priv->snd_card, priv);
#if CONFIG_AC10X_TRIG_LOCK
spin_lock_init(&priv->lock);
#endif
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);
if (ret >= 0)
return ret;
err:
asoc_simple_clean_reference(&priv->snd_card);
return ret;
}
static int seeed_voice_card_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct seeed_card_data *priv = snd_soc_card_get_drvdata(card);
if (cancel_work_sync(&priv->work_codec_clk) != 0) {
}
asoc_simple_clean_reference(card);
return 0;
}
static const struct of_device_id seeed_voice_of_match[] = {
{ .compatible = "seeed-voicecard", },
{},
};
MODULE_DEVICE_TABLE(of, seeed_voice_of_match);
static struct platform_driver seeed_voice_card = {
.driver = {
.name = "seeed-voicecard",
.pm = &snd_soc_pm_ops,
.of_match_table = seeed_voice_of_match,
},
.probe = seeed_voice_card_probe,
.remove = seeed_voice_card_remove,
};
module_platform_driver(seeed_voice_card);
MODULE_ALIAS("platform:seeed-voice-card");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("ASoC SEEED Voice Card");
MODULE_AUTHOR("PeterYang<linsheng.yang@seeed.cc>");

Binary file not shown.

12
seeed-voicecard.service Normal file
View file

@ -0,0 +1,12 @@
[Unit]
Description=Seeed Voicecard service
After=alsa-restore.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/seeed-voicecard
User=root
[Install]
WantedBy=sysinit.target

47
sound-compatible-4.18.h Normal file
View file

@ -0,0 +1,47 @@
/*
* (C) Copyright 2017-2018
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
*
* PeterYang <linsheng.yang@seeed.cc>
*/
#ifndef __SOUND_COMPATIBLE_4_18_H__
#define __SOUND_COMPATIBLE_4_18_H__
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)
#define __NO_SND_SOC_CODEC_DRV 1
#else
#define __NO_SND_SOC_CODEC_DRV 0
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0) /* fallthrough */
#endif
#endif
#if __NO_SND_SOC_CODEC_DRV
#define codec component
#define snd_soc_codec snd_soc_component
#define snd_soc_codec_driver snd_soc_component_driver
#define snd_soc_codec_get_drvdata snd_soc_component_get_drvdata
#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
#define snd_soc_write snd_soc_component_write
#define snd_soc_add_codec_controls snd_soc_add_component_controls
#endif
#endif//__SOUND_COMPATIBLE_4_18_H__

44
tools/coherence.py Normal file
View file

@ -0,0 +1,44 @@
"""
Estimate the magnitude squared coherence estimate,
- requirements
sudo apt install python-numpy python-scipy python-matplotlib
"""
import sys
import wave
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
if len(sys.argv) < 2:
print('Usage: python {} audio.wav'.format(sys.argv[0]))
sys.exit(1)
wav = wave.open(sys.argv[1], 'rb')
channels = wav.getnchannels()
frames = wav.readframes(wav.getnframes())
fs = wav.getframerate()
wav.close()
print("channels: %d" % channels)
print("rate : %d" % fs)
print("frames : %d" % wav.getnframes())
array = np.fromstring(frames, dtype='int16')
ch0 = array[0::channels]
fig, ax = plt.subplots()
for ch in range(1, channels):
f, c = signal.coherence(ch0, array[ch::channels], fs, nperseg=1024)
ax.semilogy(f, c, label="CO 1-%d" % (ch + 1))
legend = ax.legend(loc='lower right', shadow=True, fontsize='small')
plt.xlabel('frequency [Hz]')
plt.ylabel('Coherence')
plt.show()

83
tools/phase_test.py Normal file
View file

@ -0,0 +1,83 @@
import sys
import wave
import numpy as np
if len(sys.argv) != 2:
print('Usage: {} multi.wav'.format(sys.argv[0]))
sys.exit(1)
multi = wave.open(sys.argv[1], 'rb')
rate = multi.getframerate()
channels = multi.getnchannels()
if channels <= 1:
sys.exit(1)
N = rate
window = np.hanning(N)
interp = 4*8
max_offset = int(rate * 0.1 / 340 * interp)
def gcc_phat(sig, refsig, fs=1, max_tau=None, interp=16):
'''
This function computes the offset between the signal sig and the reference signal refsig
using the Generalized Cross Correlation - Phase Transform (GCC-PHAT)method.
'''
# make sure the length for the FFT is larger or equal than len(sig) + len(refsig)
n = sig.shape[0] + refsig.shape[0]
# Generalized Cross Correlation Phase Transform
SIG = np.fft.rfft(sig, n=n)
REFSIG = np.fft.rfft(refsig, n=n)
R = SIG * np.conj(REFSIG)
#R /= np.abs(R)
cc = np.fft.irfft(R, n=(interp * n))
max_shift = int(interp * n / 2)
if max_tau:
max_shift = np.minimum(int(interp * fs * max_tau), max_shift)
cc = np.concatenate((cc[-max_shift:], cc[:max_shift+1]))
# find max cross correlation index
shift = np.argmax(np.abs(cc)) - max_shift
tau = shift / float(interp * fs)
return tau, cc
print(multi.getsampwidth())
while True:
data = multi.readframes(N)
if len(data) != multi.getsampwidth() * N * channels:
print("done")
break
if multi.getsampwidth() == 2:
data = np.fromstring(data, dtype='int16')
else:
data = np.fromstring(data, dtype='int32')
ref_buf = data[0::channels]
offsets = []
for ch in range(1, channels):
sig_buf = data[ch::channels]
tau, _ = gcc_phat(sig_buf * window, ref_buf * window, fs=1, max_tau=max_offset, interp=interp)
# tau, _ = gcc_phat(sig_buf, ref_buf, fs=rate, max_tau=1)
offsets.append(tau)
print(offsets)
print(multi.getframerate())
multi.close()

37
ubuntu-prerequisite.sh Executable file
View file

@ -0,0 +1,37 @@
#!/bin/bash
# Copyright (c) Hin-Tak Leung 2020
#
# Overview:
# This script compiles and install the Broadcom VideoCore tools,
# configure the dynamic loader for the non-standard library location,
# and update the loader cache.
#
# A few steps explicitly requires root privilege, which are
# marked with "sudo". The rest is just checking for duplicate/previous
# action.
#
# This derived from my command history on ubuntu 20.04.1 .YMMV
sudo apt install -y git gcc g++ make alsa-utils cmake
git clone git://github.com/raspberrypi/userland.git
pushd userland/
arch=$(uname -m)
if [[ "$arch" =~ aarch64 ]]; then
./buildme --aarch64
else
./buildme
fi
# ./buildme already includes "sudo make install" at the end
popd
# matches Raspbian's location:
if [ ! -f /etc/ld.so.conf.d/00-vmcs.conf ] ; then
echo "/opt/vc/lib" | sudo tee -a /etc/ld.so.conf.d/00-vmcs.conf
sudo ldconfig -v
else
echo "/etc/ld.so.conf.d/00-vmcs.conf exists - no need to update ld.cache!"
fi

100
uninstall.sh Executable file
View file

@ -0,0 +1,100 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root (use sudo)" 1>&2
exit 1
fi
is_Raspberry=$(cat /proc/device-tree/model | awk '{print $1}')
if [ "x${is_Raspberry}" != "xRaspberry" ] ; then
echo "Sorry, this drivers only works on raspberry pi"
exit 1
fi
uname_r=$(uname -r)
CONFIG=/boot/config.txt
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
get_overlay() {
ov=$1
if grep -q -E "^dtoverlay=$ov" $CONFIG; then
echo 0
else
echo 1
fi
}
do_overlay() {
ov=$1
RET=$2
DEFAULT=--defaultno
CURRENT=0
if [ $(get_overlay $ov) -eq 0 ]; then
DEFAULT=
CURRENT=1
fi
if [ $RET -eq $CURRENT ]; then
ASK_TO_REBOOT=1
fi
if [ $RET -eq 0 ]; then
sed $CONFIG -i -e "s/^#dtoverlay=$ov/dtoverlay=$ov/"
if ! grep -q -E "^dtoverlay=$ov" $CONFIG; then
printf "dtoverlay=$ov\n" >> $CONFIG
fi
STATUS=enabled
elif [ $RET -eq 1 ]; then
sed $CONFIG -i -e "s/^dtoverlay=$ov/#dtoverlay=$ov/"
STATUS=disabled
else
return $RET
fi
}
RPI_HATS="seeed-2mic-voicecard seeed-4mic-voicecard seeed-8mic-voicecard"
PATH=$PATH:/opt/vc/bin
echo "remove dtbos"
for i in $RPI_HATS; do
dtoverlay -r $i
done
OVERLAYS=/boot/overlays
[ -d /boot/firmware/overlays ] && OVERLAYS=/boot/firmware/overlays
rm ${OVERLAYS}/seeed-2mic-voicecard.dtbo || true
rm ${OVERLAYS}/seeed-4mic-voicecard.dtbo || true
rm ${OVERLAYS}/seeed-8mic-voicecard.dtbo || true
echo "remove alsa configs"
rm -rf /etc/voicecard/ || true
echo "disabled seeed-voicecard.service "
systemctl stop seeed-voicecard.service
systemctl disable seeed-voicecard.service
echo "remove seeed-voicecard"
rm /usr/bin/seeed-voicecard || true
rm /lib/systemd/system/seeed-voicecard.service || true
echo "remove dkms"
rm -rf /var/lib/dkms/seeed-voicecard || true
echo "remove kernel modules"
rm /lib/modules/*/kernel/sound/soc/codecs/snd-soc-wm8960.ko || true
rm /lib/modules/*/kernel/sound/soc/codecs/snd-soc-ac108.ko || true
rm /lib/modules/*/kernel/sound/soc/bcm/snd-soc-seeed-voicecard.ko || true
rm /lib/modules/*/updates/dkms/snd-soc-wm8960.ko || true
rm /lib/modules/*/updates/dkms/snd-soc-ac108.ko || true
rm /lib/modules/*/updates/dkms/snd-soc-seeed-voicecard.ko || true
echo "remove $CONFIG configuration"
for i in $RPI_HATS; do
echo Uninstall $i ...
do_overlay $i 1
done
echo "------------------------------------------------------"
echo "Please reboot your raspberry pi to apply all settings"
echo "Thank you!"
echo "------------------------------------------------------"

View file

@ -25,6 +25,7 @@
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/wm8960.h>
#include "sound-compatible-4.18.h"
#include "wm8960.h"
@ -226,11 +227,12 @@ static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1);
static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(micboost_tlv,
static const DECLARE_TLV_DB_RANGE(micboost_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0),
2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0),
);
static const struct snd_kcontrol_new wm8960_snd_controls[] = {
SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
0, 63, 0, inpga_tlv),
@ -506,7 +508,11 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
* list each time to find the desired power state do so now
* and save the result.
*/
#if __NO_SND_SOC_CODEC_DRV
list_for_each_entry(w, &codec->card->widgets, list) {
#else
list_for_each_entry(w, &codec->component.card->widgets, list) {
#endif
if (w->dapm != dapm)
continue;
if (strcmp(w->name, "LOUT1 PGA") == 0)
@ -747,6 +753,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
iface |= 0x000c;
break;
}
fallthrough;
default:
dev_err(codec->dev, "unsupported width %d\n",
params_width(params));
@ -789,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)
static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
{
struct snd_soc_codec *codec = dai->codec;
@ -1229,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 = {
.hw_params = wm8960_hw_params,
.hw_free = wm8960_hw_free,
.digital_mute = wm8960_mute,
.mute_stream = 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 = {
@ -1251,7 +1259,11 @@ static struct snd_soc_dai_driver wm8960_dai = {
.rates = WM8960_RATES,
.formats = WM8960_FORMATS,},
.ops = &wm8960_dai_ops,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
.symmetric_rate = 1,
#else
.symmetric_rates = 1,
#endif
};
static int wm8960_probe(struct snd_soc_codec *codec)
@ -1274,7 +1286,12 @@ static int wm8960_probe(struct snd_soc_codec *codec)
static const struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
.probe = wm8960_probe,
.set_bias_level = wm8960_set_bias_level,
.suspend_bias_off = true,
.suspend_bias_off = true,
#if __NO_SND_SOC_CODEC_DRV
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
#endif
};
static const struct regmap_config wm8960_regmap = {
@ -1301,8 +1318,7 @@ static void wm8960_set_pdata_from_of(struct i2c_client *i2c,
pdata->shared_lrclk = true;
}
static int wm8960_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
static int wm8960_i2c_probe(struct i2c_client *i2c)
{
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8960_priv *wm8960;
@ -1367,10 +1383,9 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
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);
return 0;
}
static const struct i2c_device_id wm8960_i2c_id[] = {

BIN
wm8960.ko

Binary file not shown.

View file

@ -2,7 +2,7 @@ state.ALSA {
control.1 {
iface MIXER
name 'PCM Playback Volume'
value -1995
value -1994
comment {
access 'read write'
type INTEGER
@ -10,7 +10,7 @@ state.ALSA {
range '-10239 - 400'
dbmin -9999999
dbmax 400
dbvalue.0 -1995
dbvalue.0 -1994
}
}
control.2 {
@ -65,12 +65,12 @@ state.ALSA {
}
}
}
state.seeedvoicecard {
state.seeed2micvoicec {
control.1 {
iface MIXER
name 'Capture Volume'
value.0 63
value.1 63
value.0 39
value.1 39
comment {
access 'read write'
type INTEGER
@ -78,8 +78,8 @@ state.seeedvoicecard {
range '0 - 63'
dbmin -1725
dbmax 3000
dbvalue.0 3000
dbvalue.1 3000
dbvalue.0 1200
dbvalue.1 1200
}
}
control.2 {