top of page

Zynq-7000 Audio with WM8960 in PetaLinux

Writer's picture: rehsdrehsd

Updated: 20 minutes ago

I am hoping to get audio support for my custom Zynq-7000 development board. After a little digging into options, I am currently focusing on the WM8960 CODEC. In this blog post, I will share my progress; I will update this post as I have updates, so check back.


I previously researched a simple PWM solution like that in the Digilent Arty Z7. I also researched a Cirrus CS5343 + CS4344 CODEC solution, packaged in the Digilent Pmod I2S2. Unfortunately, I struggled to find PetaLinux drivers and support resources to get these to work in PetaLinux.


My initial objective is to get audio output using the aplay utility in PetaLinux 2024.2. I am using my custom Zynq-7000 board (see Xilinx XC7Z020-1CLG484I (Zynq-7000 SoC, Artix-7 FPGA)). For the WM8960, I am trying to get the Waveshare WM8960 Audio HAT working (see WM8960 Audio HAT - Waveshare Wiki).


I have found these two blogs to be helpful as I've gotten into this:


So here's the mess I have right now:


My main FPGA board has a couple of expansion ports. The right port is connected to a PCB that simply takes the signals to pin headers. Using those headers, I am connecting a Waveshare WM8960 Audio HAT. Below are the key sections of the HAT schematic.



One modification I made to the HAT is to connect the I2S_MCLK signal to an unused pin, ID_SD (27), on the pin header. This will allow me to get the MCLK from the 24 MHz oscillator and bring it into my block design in Vivado.


Here is my current Vivado block design:



The relevant portion of my constraints file:

The pullups on the two I2C lines are required.


I am using PetaLinux 2024.2. I am working on a user module to create a custom sound card driver for my setup. I started with Yuhei Horibe's example.


In the PetaLinux image, I have created ~/.asoundrc with these contents:

pcm.!default {
    type hw
    card 0
}
ctl.!default {
    type hw
    card 0
}

I have added ALSA support to PetaLinux. I did not add the xlnx_pl_snd_card.c driver (• SND_SOC_XILINX_PL_SND_CARD), as I am using my custom driver instead.


Latest Status

I am able to load the driver and see the sound card in PetaLinux (aplay, alsamixer, speaker-test). For now, I am manually loading the driver with one of the following:

  • insmod /lib/modules/6.6.40-xilinx-g2b7f6f70a62a/updates/wm8960-snddrv.ko

  • modprobe wm8960-snddrv


Ways I testing / troubleshooting:

  • I2C

    • i2cdetect -l

    • i2cdetect -r "xiic-i2c 41600000.i2c" 0x1a 0x1a

    • i2cget -y -f 2 0x1a 0x00

    • i2cset -y -f 2 0x1a 0x00 0x55

  • Logs

    • dmesg | grep snd

    • dmesg | grep sound

    • dmesg | grep audio

    • dmesg | grep i2c

    • dmesg | grep rehsd

  • aplay -l

  • speaker-test

  • aplay /usr/bin/rehsd/sample.wav

  • alsamixer

  • arecord -l

  • Oscilloscope

    • I2C lines

    • I2S lines

  • dtsi review

    • a. Generate dtsi from Vivado hardware

      • /xilinx/Vitis/2024.2/bin/xsct

      • sdtgen set_dt_param -dir sdt_out -xsa ~/petalinux20242/rehsdZynq/rehsdZynq_BD_wrapper.xsa

      • sdtgen generate_sdt


I am currently running into a write error.

speaker-test -c 2 

speaker-test 1.2.11 
Playback device is default 
Stream parameters are 48000Hz, S16_LE, 2 channels 
Using 16 octaves of pink noise 
Rate set to 48000Hz (requested 48000Hz) 
Buffer size range from 96 to 76800 
Period size range from 48 to 12800 
Periods = 4 was set 
period_size = 12000 was set 
buffer_size = 48000 0 - 
Front Left 

Write error: -5
Input/output error 
xrun_recovery failed: -5,
Input/output error 
Transfer failed: Input/output error

Using an oscilloscope, I am seeing I2C traffic, but I am not seeing I2S traffic. I expect this is related to improper configuration of the WM8960 codec.





Update - 27 January 2025

I have updated the Vivado design. I am bringing in MCLK 24MHz from the WM8960 board into the Zynq-7000 board and then using the I2S Transmitter IP block to generate the other I2S clocks (which go back to the WM8960 board). From what I can tell, clocks are all working now. I have also done a bunch of updates to the custom sound driver and am thinking it's close to where it needs to be. I am still getting the -5 Write Error. I am not seeing any traffic on the I2S data out (DAC) line. My next step is to take another run at the Vivado design, separating the I2S supporting components from other existing components I had in Vivado. I'll post an update video after I get through that. I posted updated Vivado block design PDF, dtsi, and sound driver code files to FPGA/PetaLinux 2024.2 Audio/update 2025-01-27 at main · rehsd/FPGA.


Update - 05 February 2025

I now have audio output working! See the video below and corresponding content on my GitHub.








I grabbed another I/O expansion board and setup a "fly wire free" version for the WM8960. This feels so much better, and I don't need to worry about accidentally disconnecting wires. This I/O board includes headers for SPI (previous YouTube video) and additional headers for yet-to-be-used Zynq-7000 I/O pins.



More to come!



Additional Notes

  • I see Waveshare has a simpler board available, too. I have ordered one of these to try out. For this specific audio project, this board looks to be a better option. It doesn't have unecessary header pins and gives easy access to mclk -- input or output. WM8960 Audio Board - Waveshare Wiki

  • WM8960 supported formats

    • SNDRV_PCM_FMTBIT_S16_LE (Signed Little Endian)

    • SNDRV_PCM_FMTBIT_S20_3LE

    • SNDRV_PCM_FMTBIT_S24_LE

    • SNDRV_PCM_FMTBIT_S32_LE





Additional Info



57 views0 comments

Recent Posts

See All
bottom of page