MusicPlayerDaemon / MPD

Music Player Daemon
https://www.musicpd.org/
GNU General Public License v2.0
2.19k stars 350 forks source link

Hardware Mixer not working with HifiBerry DAC2 HD #1579

Open fatg3erman opened 2 years ago

fatg3erman commented 2 years ago

Bug report

Describe the bug

I'm using a HifiBerry DAC2 HD on a Raspberry Pi 3B+ running Raspberry Pi OS.

uname -a
Linux music 5.15.32-v7+ #1538 SMP Thu Mar 31 19:38:48 BST 2022 armv7l GNU/Linux

MPD's hardware mixer only controls the Left Channel, or sometimes sets both channels to zero, depending on the number I send to setvol.

aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: sndrpihifiberry [snd_rpi_hifiberry_dacplushd], device 0: HiFiBerry DAC+ HD HiFi pcm179x-hifi-0 [HiFiBerry DAC+ HD HiFi pcm179x-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
hw:CARD=sndrpihifiberry,DEV=0
    snd_rpi_hifiberry_dacplushd, HiFiBerry DAC+ HD HiFi pcm179x-hifi-0
    Direct hardware device without any conversions
plughw:CARD=sndrpihifiberry,DEV=0
    snd_rpi_hifiberry_dacplushd, HiFiBerry DAC+ HD HiFi pcm179x-hifi-0
    Hardware device with all software conversions
default:CARD=sndrpihifiberry
    snd_rpi_hifiberry_dacplushd, HiFiBerry DAC+ HD HiFi pcm179x-hifi-0
    Default Audio Device
sysdefault:CARD=sndrpihifiberry
    snd_rpi_hifiberry_dacplushd, HiFiBerry DAC+ HD HiFi pcm179x-hifi-0
    Default Audio Device
dmix:CARD=sndrpihifiberry,DEV=0
    snd_rpi_hifiberry_dacplushd, HiFiBerry DAC+ HD HiFi pcm179x-hifi-0
    Direct sample mixing device
amixer
Simple mixer control 'DAC',0
  Capabilities: pvolume
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 240
  Mono:
  Front Left: Playback 226 [94%] [-7.00dB]
  Front Right: Playback 226 [94%] [-7.00dB]
Simple mixer control 'DAC Invert Output',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'DAC Rolloff Filter',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]

Expected Behavior

MPD should set the volume of both left and right channels to the value I specify. I've tested with other clients that use alsa hardware mixers (snapclient and mopidy-alsamixer) and they both work correctly.

Actual Behavior

Let's say I start with the mixer set to maximum on both channels. setvol 50 sets the volume of both channels to 0. Then do setvol [any value other than 100] - nothing happens. Then do setvol 100 sets the Left channel to 100 and leaves the Right channel unchanged.

Version

Music Player Daemon 0.22.6 (0.22.6)
Copyright 2003-2007 Warren Dukes <warren.dukes@gmail.com>
Copyright 2008-2018 Max Kellermann <max.kellermann@gmail.com>
This is free software; see the source for copying conditions.  There is NO
warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Database plugins:
 simple proxy upnp

Storage plugins:
 local smbclient udisks nfs curl

Neighbor plugins:
 smbclient upnp udisks

Decoders plugins:
 [mad] mp3 mp2
 [mpg123] mp3
 [vorbis] ogg oga
 [oggflac] ogg oga
 [flac] flac
 [opus] opus ogg oga
 [sndfile] wav aiff aif au snd paf iff svx sf voc w64 pvf xi htk caf sd2
 [audiofile] wav au aiff aif
 [dsdiff] dff
 [dsf] dsf
 [hybrid_dsd] m4a
 [faad] aac
 [mpcdec] mpc
 [wavpack] wv
 [modplug] 669 amf ams dbm dfm dsm far it med mdl mod mtm mt2 okt s3m stm ult umx xm
 [mikmod] amf dsm far gdm imf it med mod mtm s3m stm stx ult uni xm
 [sidplay] sid mus str prg P00
 [wildmidi] mid
 [fluidsynth] mid
 [adplug] amd d00 hsc laa rad raw sa2
 [ffmpeg] 16sv 3g2 3gp 4xm 8svx aa3 aac ac3 adx afc aif aifc aiff al alaw amr anim apc ape asf atrac au aud avi avm2 avs bap bfi c93 cak cin cmv cpk daud dct divx dts dv dvd dxa eac3 film flac flc fli fll flx flv g726 gsm gxf iss m1v m2v m2t m2ts m4a m4b m4v mad mj2 mjpeg mjpg mka mkv mlp mm mmf mov mp+ mp1 mp2 mp3 mp4 mpc mpeg mpg mpga mpp mpu mve mvi mxf nc nsv nut nuv oga ogm ogv ogx oma ogg omg opus psp pva qcp qt r3d ra ram rl2 rm rmvb roq rpl rvc shn smk snd sol son spx str swf tak tgi tgq tgv thp ts tsp tta xa xvid uv uv2 vb vid vob voc vp6 vmd wav webm wma wmv wsaud wsvga wv wve rtp:// rtsp:// rtsps://
 [gme] ay gbs gym hes kss nsf nsfe sap spc vgm vgz
 [pcm]

Filters:
 libsamplerate soxr

Tag plugins:
 id3tag

Output plugins:
 shout null fifo sndio pipe alsa ao oss openal pulse jack httpd recorder

Encoder plugins:
 null vorbis opus lame wave flac

Archive plugins:
 [bz2] bz2
 [zzip] zip
 [iso] iso

Input plugins:
 file io_uring archive alsa tidal qobuz curl ffmpeg smbclient nfs mms cdio_paranoia

Playlist plugins:
 extm3u m3u pls xspf asx rss soundcloud flac cue embcue

Protocols:
 file:// alsa:// cdda:// ftp:// ftps:// gopher:// hls+http:// hls+https:// http:// https:// mms:// mmsh:// mmst:// mmsu:// nfs:// qobuz:// rtmp:// rtmps:// rtmpt:// rtmpts:// rtp:// rtsp:// rtsps:// scp:// sftp:// smb:// srtp:// tidal://

Other features:
 avahi dbus udisks epoll icu inotify ipv6 systemd tcp un

Configuration

audio_output {
        type            "alsa"
        name            "HiFiBerry"
        device          "hw:0,0"
        mixer_type      "hardware"      # optional
        mixer_control   "DAC"           # optional
        mixer_index     "0"             # optional
}

Log

There doesn't appear to be anything useful in the log

Jul 21 12:50 : client: [0] process command "setvol 50"
Jul 21 12:50 : client: [0] command returned 0
Jul 21 12:50 : client: [0] process command "setvol 100"
Jul 21 12:50 : client: [0] command returned 0
Jul 21 12:50 : client: [0] process command "setvol 20"
Jul 21 12:50 : client: [0] command returned 0
MaxKellermann commented 2 years ago

Sorry, I can't help with that, because I don't have a HifiBerry, and none of my cards reproduces this problem.

HolyMacarony commented 2 years ago

For me this is a problem too. I tried it in moode audio and there is no way to get hardware mixer working it seems :(

hifiberry commented 2 years ago

@MaxKellermann : I had a look at this here. The "DAC" mixer control is a stereo control, but it seems that mpd handles it as a mono control setting only the left channel. I'm not sure if mpd in general is able to use a stereo volume control - is it?

I'm happy to help you debugging and fixing this. Just let me know what kind of support you need.

mightyoakbob commented 2 years ago

@MaxKellermann: Is there anything I can do to persuade you to have a look at this for us? I can't speak for them but talking to HiFiBerry, I got the impression they may well lend you a DAC2 HD if that would facilitate your expert help. I would be very grateful.

Thank you.

Bob.

roizcorp commented 1 year ago

It is not MPD problem, it is the HiFiBerry assholes that release a product and not making sure it works properly with its main target software. Moreover, MPD is open source they could have contributed the code that fix it. But they just refer you to MPD github - douchebags

meszarosa commented 1 year ago

Hi,

I have an ES9038Q2M based DAC, and the problem occur on my end as well. I use a slightly custom driver; based on i-sabre-codec/i-sabre-q2m. (similar to Hifiberry driver).

The interesting phenomenon on my config is:

Stange thing: If I control the volume from the ALSA interface directly from console using 'amixer sset', then the hardware volume is always correct!


I tracked it down on the I2C bus using a logic analyzer, and found, that ALSA commands perform the following actions (as normal): Vol1Reg : Read old value / Write new value Vol2Reg : Read old value / Write new value

example logic analyzer log: 2023-01-23 15:02:36.416874+00:00: R, Volume 1 (0xf) DATA:0x20 2023-01-23 15:02:36.417320+00:00: R, Volume 2 (0x10) DATA:0x20 2023-01-23 15:02:36.417777+00:00: R, Volume 1 (0xf) DATA:0x20 2023-01-23 15:02:36.418205+00:00: R, Volume 2 (0x10) DATA:0x20 2023-01-23 15:02:36.418641+00:00: R, Volume 1 (0xf) DATA:0x20 2023-01-23 15:02:36.419069+00:00: W, Volume 1 (0xf) DATA:0x10 2023-01-23 15:02:36.419385+00:00: R, Volume 2 (0x10) DATA:0x20 2023-01-23 15:02:36.419837+00:00: R, Volume 1 (0xf) DATA:0x10 2023-01-23 15:02:36.420267+00:00: R, Volume 2 (0x10) DATA:0x20 2023-01-23 15:02:36.420707+00:00: R, Volume 1 (0xf) DATA:0x10 2023-01-23 15:02:36.421133+00:00: R, Volume 2 (0x10) DATA:0x20 2023-01-23 15:02:36.421578+00:00: R, Volume 1 (0xf) DATA:0x10 2023-01-23 15:02:36.422353+00:00: R, Volume 2 (0x10) DATA:0x20 2023-01-23 15:02:36.422788+00:00: W, Volume 2 (0x10) DATA:0x10 2023-01-23 15:02:36.423219+00:00: R, Volume 1 (0xf) DATA:0x10 2023-01-23 15:02:36.423655+00:00: R, Volume 2 (0x10) DATA:0x10

However, mpc console (mpc volume command) sends the following actions on I2C: (Apparently mpc sets only one side most of the times, but sometime I get valid values in both registers: but that's the rarest case. Most of the time I get 0xff in the registers, as shown below: which means total silence...)

Vol1Reg : Read old value / Write new value / Read new value / Write '0xff' Vol2Reg: Read old value / Write new value / Read new value / Write '0xff'.

example logic analyzer log: 2023-02-02 08:13:19.268154+00:00: R, Volume 1 (0xf) DATA:0xff 2023-02-02 08:13:19.268590+00:00: R, Volume 2 (0x10) DATA:0xff 2023-02-02 08:13:19.269034+00:00: R, Volume 1 (0xf) DATA:0xff 2023-02-02 08:13:19.269464+00:00: W, Volume 1 (0xf) DATA:0x2 2023-02-02 08:13:19.269782+00:00: R, Volume 2 (0x10) DATA:0xff 2023-02-02 08:13:19.270235+00:00: R, Volume 1 (0xf) DATA:0x2 2023-02-02 08:13:19.270673+00:00: R, Volume 2 (0x10) DATA:0xff 2023-02-02 08:13:19.271191+00:00: R, Volume 1 (0xf) DATA:0x2 2023-02-02 08:13:19.271617+00:00: R, Volume 2 (0x10) DATA:0xff 2023-02-02 08:13:19.272066+00:00: R, Volume 1 (0xf) DATA:0x2 2023-02-02 08:13:19.272492+00:00: W, Volume 1 (0xf) DATA:0xff 2023-02-02 08:13:19.272809+00:00: R, Volume 2 (0x10) DATA:0xff 2023-02-02 08:13:19.273273+00:00: R, Volume 1 (0xf) DATA:0xff 2023-02-02 08:13:19.273720+00:00: R, Volume 2 (0x10) DATA:0xff

However, I was not successful tracking down the source of the problem. My assumption : it's not based on ALSA driver level. Either some configuration is bad, or the MPD volume control has some strange setting, and this MPD volume control invalidates somehow immediately a newly written volume value in the HW register.

At my setup, the problem occurs ONLY with hardware volume control. I use ALSA in 'direct hw' output mode.

Is there any suspected DAC device-driver property, which could cause a such issue in MPD???? (sorry, I'm not familiar with MPD source-code.)

meszarosa commented 1 year ago

Further experience:

When there is no sound, then mpd reports back volume level below 50, even if I set volume to 100 by command. (There is correlation, if I decrease the set volume from 100, and if there is no sound, then the reported volume by mpd is also a decreasing number below 50).

As I've logged in my previous post: I've seen clear correlation: if the I2C bus transfer was 0xff towards the volume registers (means total silence), then mpd reporting volume was a number below 50. If there was any sound coming from the DAC (means I2C transfer was successful ), then the mpd reported volume was approximately doubled, so in the range of 90-100.

I hope it helps identifying the problem source.

meszarosa commented 1 year ago

DATE: 2023.02.12. 14:40 TESTER: meszarosa

TESTBED: RPI-3B Linux raspberrypi 5.15.84-v7+ #1613 SMP Thu Jan 5 11:59:48 GMT 2023 armv7l GNU/Linux Stock MPD 0.23.12 compiled from sources and stock RaspiOS Lite latest 2022-09-22 with APT upgrade applied.

BUG DESCRIPTION: https://github.com/MusicPlayerDaemon/MPD/issues/1579

============== TESTCASE A: Problem reproduced. HW volume control does not work. Logs: delay_in_setvol_log.tar

NOTE: audiocard device driver includes a 2ms delay setting the volume registers: this way it's mimicking the I2C bus transfer delay times. (the 2ms delay is included in the vol_set /vol_get functions, see APPENDIX B)

##############

============== TESTCASE B: Problem is not appearing. Normal Function. Logs: no_delay_in_setvol_log.tar

NOTE: audiocard device driver does not have significant delay setting the volume registers: (the 2ms delay is commented out from the vol_set /vol_get functions, see APPENDIX B)

############## APPENDIX: ############## A) Device Driver Environment, Codec control registration: ...using R_EXT_TLV structure, to be able to have a custom get/set function.

/ Control assignment/ static const struct snd_kcontrol_new hifibunny3_codec_controls[] = { SOC_DOUBLE_R_EXT_TLV("Digital Playback Volume", ES9038Q2M_VOLUME1, ES9038Q2M_VOLUME2, 0, 255, 1, hifibunny3_vol_get, hifibunny3_vol_set, volume_tlv), }

B) Individual volume_set, volume_get functions:

/***/ / Volume Control / / Test functions for EXT volume control / / 2m delay can be added (compile time), to simulate I2C transaction time. / for testing purposes, the volume values are stored in a global variable /* (g_left_val, g_right_val) respectively. /***/ / NOTE: kernel messages will include call-sequence log with timestamps, as indicated by the 'printk' function below. /

static int hifibunny3_vol_get(struct snd_kcontrol kcontrol, struct snd_ctl_elem_value ucontrol) { u64 tstamp; tstamp = ktime_get_ns(); //mdelay(2); // Modelling I2C transaction time with 2ms of delay. ucontrol->value.integer.value[0] = g_left_val; ucontrol->value.integer.value[1] = g_right_val; printk("G..hifibunny3_vol_get(TS:%lld): LEFT:%d, RIGHT:%d.\n", tstamp, g_left_val, g_right_val); return 0; }

static int hifibunny3_vol_set(struct snd_kcontrol kcontrol, struct snd_ctl_elem_value ucontrol) { u64 tstamp; tstamp = ktime_get_ns(); g_left_val = ucontrol->value.integer.value[0]; g_right_val = ucontrol->value.integer.value[1]; //mdelay(2); // Modelling I2C transaction time with 2ms of delay. printk(".S.hifibunny3_vol_set(TS:%lld): LEFT:%d, RIGHT:%d.\n", tstamp, g_left_val, g_right_val); return 1; }

====================================== MPD_Issue_1579_logs.zip