Waveshare WM8960

I did manage to get these out-of-tree kernel modules built in containers so that they can be deployed via CI/CD.
But then life and summer came in the way. I’m away from dev machine for a few weeks, but will share when I am back if you are interested.

unit-test what? :stuck_out_tongue:
The motivation behind my rewrite of the build system was to modularise it for ease of development, DRY, and so it can run in containers. Since my normal machines are all Windoze boxes, I build all my images via CircleCI… But, AFAIK the official Voumio images aren’t build by a CI/CD, and runs on Volumio’s servers to include the myVolumio closed source stuff.

When Volumio decides to moves away from Jessie, we should be able to switch the default branch and archive the old stuff, so others don’t spend time as you did.There is some history at [Proposal] Make build system more modular · Issue #413 · volumio/Build · GitHub if you are interested.

It looks like you alsa configuration is wrong and is looking for a MAX98357A instead of the wm8960soundcard ?

pcm.!default {
    type             copy
    slave.pcm       "volumio"

pcm.volumio {
    type             copy
    slave.pcm       "volumioOutput"

# There is always a plug before the hardware to be safe
pcm.volumioOutput {
    type plug
    slave.pcm "volumioHw"

pcm.volumioHw {
    type hw
    card "MAX98357A"

Thank you very much for pointing it out. I educated myself to merge the asound.conf with the vender-provided one. The following works beautifully with speaker-test -Dvolumio:

pcm.!default {
    type             copy
    slave.pcm       "volumio"

pcm.volumio {
    type             copy
    slave.pcm       "volumioOutput"

# There is always a plug before the hardware to be safe
pcm.volumioOutput {
    type plug
    slave.pcm "volumioHw"

pcm.volumioHw {
    type copy
    slave.pcm "wm8960"

defaults.pcm.rate_converter "samplerate"

pcm.wm8960 {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"

pcm.playback {
    type plug
    slave.pcm "dmixed"

pcm.capture {
    type plug
    slave.pcm "array"

pcm.dmixed {
    type dmix
    slave.pcm "hw:wm8960soundcard"
    ipc_key 555555

pcm.array {
    type dsnoop
    slave {
        pcm "hw:wm8960soundcard"
        channels 2
    ipc_key 666666

However I’m not feeling good from SW management/engineering aspect, and just as I expected, it would be overriden whenever I change the Audio Output Device in Web Interface.

[Edit] Figured out when the config file is overriden. However it doesn’t seem like to be the case. May you again show me where is the configuration maintained in Volumio backend?

This configuration is normally propagated by the DACS.json file, and should match your definition as per the aplay output…

card 1: wm8960soundcard [wm8960-soundcard], device 0: bcm2835-i2s-wm8960-hifi wm8960-hifi-0 [bcm2835-i2s-wm8960-hifi wm8960-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

From a quick glance at your PR, you might have to update the line you have, as it is for the older v2 version of Volumio.

"name":"Waveshare - WM8960",

For the modular Alsa, you need a few more keys in the DAC entry - have a look at Merge ALSA pipeline into buster development by timothyjward · Pull Request #2040 · volumio/Volumio2 · GitHub for more details. Oh and of-course, the back-end code for Buster tree is not master…
Help from Volumio community for a new feature - #29 by ashthespy might also be helpful to figure out the mapping of id, name etc.

Thanks again for the pointers. I’ve figured out the proper json string to wm8960 DAC:

"name":"Waveshare - WM8960",

However in the current index.js it wouldn’t touch overlay if modules has assigned values. I’d propose to separate modules and overlay control logics such as:

  if (modules) {
    this.config.set('i2s_id', id);
  if (overlay) {
    if (script) {
      self.hotAddI2SDAC({'overlay': overlay, 'script': script});
    } else {
      self.hotAddI2SDAC({'overlay': overlay});
    this.config.set('i2s_id', overlay);

[Edit] Volumio2 PR and Build PR are up for discussion.

@hftsai256 Does the upstream wm8960-soundcard overlay not work properly for this board?

I could be wrong, but from a quick look at the commits in wm8960.c, it looks like the clock fixes are now in the upstream codec as well?

I believe it would work, even though the one upstream is slightly different. A quick diff shows:

$ diff -bBw ${rpi-linux}/wm8960-soundcard-overlay.dts ${WM8960-Audio-HAT/wm8960-soundcard.dts
< // Definitions for Waveshare WM8960 https://github.com/waveshare/WM8960-Audio-HAT
< 	compatible = "brcm,bcm2835";
>     compatible = "brcm,bcm2708";
>         master = <0>,"=2!3";

AFAIK master override is not doing anything, and bcm2835/bcm2708 are basically the same thing with different packaging.

Looks like the one merged into upstream would detect the proper clock of the device… it is kinda out of my scope to figure out if it works, but my gut tends to believe it.

Unfortunately my wm8960 hat seems to be broken – SW/FW still works, but not sound output from speaker terminal nor headphone jack.

[EDIT] I can confirm that the card is detectable/accessible with upstream overlay dtbo and upstream (fixed) kernel module snd-soc-wm8960.ko only.

With that being said, I was thinking about: being a targeted OS distribution, wouldn’t it make sense to build our own kernel with all in-tree codecs enabled? I can recall there’s an “rpi update” phase during the build to push kernel to version 5.4.83+, and I wonder if we could put in a customized .config file for it.


This is being done for x86, and the other arm platforms, but for the pi, we try and keep the upstream vanilla kernel.

I’m surprised that PR in the pi repo didn’t enable the kernel module. Oversight? They normally update the kernel config as well from what I recall…

I poked around and was trying to figure out the “no sound” problem on my board while waiting reposes from the issue filed upstream. Turns out in addition to kernel modules (which the two PRs mentioned above have it implemented properly), wm8960_asound.state from official repo has to be applied with a refresh (alsactl nrestore).

Just few minutes ago the issue was responded and the module will be in future kernel builds (yay). Let’s defer implementation details to Github PR thread.

OK, I was able to configure Waveshare WM8960 with the latest Volumio OS build on Raspberry Pi

I have RPI Zero W and made the following steps:

  1. Clean install Volumio OS (Volumio-3.198-2022-01-24-pi.img)

  2. Initial network setup

  3. Enable SSH

  4. Add string to dacs.json
    nano /volumio/app/plugins/system_controller/i2s_dacs/dacs.json
    {"id":"wm8960-soundcard","name":"Waveshare - WM8960","overlay":"wm8960-soundcard,i2s-mmap","alsanum":"1","alsacard":"wm8960soundcard","mixer":"Playback","modules":["i2c-dev","snd-soc-wm8960","snd-soc-wm8960-soundcard"],"script":"","i2c_address":"1a","needsreboot":"yes"}

  5. sudo volumio kernelsource

  6. git clone https://github.com/waveshare/WM8960-Audio-HAT.git

  7. cd WM8960-Audio-HAT

  8. sudo ./install.sh

  9. Select Audio Output:

  • I2S DAC > OFF
  • Output Device > wm8960-soundcard

installation doesn’t work for me…

Building module:

cleaning build area…

make -j1 KERNELRELEASE=5.10.90+ -C /lib/modules/5.10.90+/build M=/var/lib/dkms/wm8960-soundcard/1.0/build…(bad exit status: 2)

Error! Bad return status for module build on kernel: 5.10.90+ (armv6l)

Consult /var/lib/dkms/wm8960-soundcard/1.0/build/make.log for more information.

Created symlink /etc/systemd/system/sysinit.target.wants/wm8960-soundcard.service → /lib/systemd/system/wm8960-soundcard.service.

DKMS make.log for wm8960-soundcard-1.0 for kernel 5.10.90+ (armv6l)
Sun Aug 28 20:05:00 UTC 2022
make: Entering directory ‘/usr/src/rpi-linux’
CC [M] /var/lib/dkms/wm8960-soundcard/1.0/build/wm8960.o
/var/lib/dkms/wm8960-soundcard/1.0/build/wm8960.c:1390:3: error: ‘struct snd_soc_dai_driver’ has no member named ‘symmetric_rate’; did you mean ‘symmetric_rates’?
.symmetric_rate = 1,
/var/lib/dkms/wm8960-soundcard/1.0/build/wm8960.c:1390:20: warning: initialization of ‘const struct snd_soc_cdai_ops *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
.symmetric_rate = 1,
/var/lib/dkms/wm8960-soundcard/1.0/build/wm8960.c:1390:20: note: (near initialization for ‘wm8960_dai.cops’)
make[1]: *** [scripts/Makefile.build:280: /var/lib/dkms/wm8960-soundcard/1.0/build/wm8960.o] Error 1
make: *** [Makefile:1825: /var/lib/dkms/wm8960-soundcard/1.0/build] Error 2
make: Leaving directory ‘/usr/src/rpi-linux’


There are 2 versions the .git is for 4.9
And the one without the git should be 5.0 and higher…

Read the part of FAQ

I have higher than 5.0 and had used the normal command :-/


volumio@volumio:~$ uname -a
Linux volumio 5.10.90+ #1512 Thu Jan 13 16:32:12 GMT 2022 armv6l GNU/Linux


I would say start over fresh install and change line 6. To the 5.0
Version maybe that works. (I don’t have the card so i can’t test for you.)

no luck there… I think the kernel version is too new… only works with older 5 versions I guess

Can you try to help Simon with this?

What we still can try that i find a link to that older version for you
Maybe that will install it without problems and try to update from there.
It’s a long shot but maybe that works.

Let me know if you want to give that a try.

my dac still works with the volumio 2 version. Only I never can update it to 3… so I guess I have to leave it like that. Unless you have another solution.

Hey ash do you know maybe a solution for this one?