Takashi Iwai tiwai@suse.de writes:
Hm, I thought AC3 should have worked as it is. A possible problem is in the case that other apps already occupied the stream. Currently, the digital output is automatically assigned together when an analog output is opened. This is because most of users want to output the "audio" data to SPDIF output without hustle if they have a receiver. When trying to open the dedicated SPDIF for AC3, then it fails because the digital stream was already opened by the process for analog streams.
Yes, we've discussed this issue a while ago. In this case, the symptom is: the application cannot open the hardware device.
Or, it's simply some missing setup by apps. The app sending the non-audio streams like AC3 over SPDIF is supposed to set up the IEC958 status bits appropriately at opening the stream. The IEC958 bits can be passed via arguments for the "spdif" (or "iec958") PCM. For example, ac3dec in alsa-tools openes like
plug:iec958:{AES0 0x.. AES1 0x..... AES3 0x..}
where the hex numbers represent status bits. These numbers can be shown via iecset utility with -x option. So, you can check via iecset whether the parameters are set up properly when you start an app accessing SPDIF.
All iec settings are good.
Here's what I found while doing some tests with this setup:
$ cat /proc/asound/cards 0 [Live ]: EMU10K1 - SB Live 5.1 Dell OEM [SB0220] SB Live 5.1 Dell OEM [SB0220] (rev.10, serial:0x80661102) at 0xb800, irq 50 1 [SB ]: HDA-Intel - HDA ATI SB HDA ATI SB at 0xffef4000 irq 217
First here's the basic test case which does not work:
- reload alsa driver - launch 'ac3dec -c 1 -C some_file.ac3'
Here are the traces (I've hacked hda_codec.c and hda_intel.c to provide more infos) without the boot sequence :
- switch iec958 on alsamixer off:
Apr 1 17:16:54 gandalf kernel: snd_hda_spdif_out_switch_put: val 280 change 1 spdif_ctls 281 Apr 1 17:16:54 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm 80 Apr 1 17:16:54 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 300 parm b080
- switch iec958 on alsamixer on:
Apr 1 17:17:01 gandalf kernel: snd_hda_spdif_out_switch_put: val 281 change 1 spdif_ctls 280 Apr 1 17:17:01 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm 81 Apr 1 17:17:01 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 300 parm b000
- ac3 play with ac3dec -c1
Apr 1 17:17:10 gandalf kernel: snd_hda_spdif_out_switch_put: val 2b1 change 1 spdif_ctls 2b1
---> This verb set the correct spdif bit (and switch iec958 on): Apr 1 17:17:10 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm b1
Apr 1 17:17:10 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70e parm 2 Apr 1 17:17:10 gandalf kernel: snd_hda_spdif_out_switch_put: val 2b1 change 0 spdif_ctls 2b1 Apr 1 17:17:10 gandalf kernel: snd_hda_calc_stream_format: format 2, iec958 BE 0, iec958 LE 0 Apr 1 17:17:10 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/../../alsa-kernel/pci/hda/hda_intel.c:1163: azx_pcm_prepare: bufsize=0x10000, fragsize=0x800, format=0x11 Apr 1 17:17:10 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x5, channel=0, format=0x11 Apr 1 17:17:10 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 50 Apr 1 17:17:10 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 11 Apr 1 17:17:10 gandalf kernel: hda-intel: Invalid position buffer, using LPIB read method instead.
ac3 stop
Apr 1 17:17:17 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x0, channel=0, format=0x0 Apr 1 17:17:17 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 0 Apr 1 17:17:17 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 0 Apr 1 17:17:17 gandalf kernel: snd_hda_spdif_out_switch_put: val 281 change 1 spdif_ctls 281 Apr 1 17:17:17 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm 81 Apr 1 17:17:17 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70e parm 2 Apr 1 17:17:17 gandalf kernel: snd_hda_spdif_out_switch_put: val 281 change 0 spdif_ctls 281 Apr 1 17:17:17 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x0, channel=0, format=0x0 Apr 1 17:17:17 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 0 Apr 1 17:17:17 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 0
At this point the amp refuses to decode and does not display the FS rate.
Now I done some test with the workaround Dag mentioned. Here'is what works: - switch iec958 off - play 44Hz on hw1,1 (works also with 48KHz) - switch iec958 on (optional) - play ac3
And here are the trace:
- iec958 off
Mar 30 18:40:23 gandalf kernel: snd_hda_spdif_out_switch_put: val 280 change 1 spdif_ctls 281 Mar 30 18:40:23 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm 80 Mar 30 18:40:23 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 300 parm b080
- start play 44.1KHz audio (you'll note that iec958 is not switched on there)
Mar 30 18:40:49 gandalf kernel: snd_hda_calc_stream_format: format 2, iec958 BE 0, iec958 LE 0 Mar 30 18:40:49 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/../../alsa-kernel/pci/hda/hda_intel.c:1163: azx_pcm_prepare: bufsize=0x10000, fragsize=0x4000, format=0x4011
---> Format 0x4011 is indeed 44,1Khz, 16bits 2 channels : Mar 30 18:40:49 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x5, channel=0, format=0x4011 Mar 30 18:40:49 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 50 Mar 30 18:40:49 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 4011 Mar 30 18:40:49 gandalf kernel: hda-intel: Invalid position buffer, using LPIB read method instead.
stop 44.1. audio
Mar 30 18:40:54 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x0, channel=0, format=0x0 Mar 30 18:40:54 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 0 Mar 30 18:40:54 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 0 Mar 30 18:40:54 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x0, channel=0, format=0x0 Mar 30 18:40:54 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 0 Mar 30 18:40:54 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 0
[ Why is the format now set twice ?? ]
iec958 on
Mar 30 18:40:59 gandalf kernel: snd_hda_spdif_out_switch_put: val 281 change 1 spdif_ctls 280 Mar 30 18:40:59 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm 81 Mar 30 18:40:59 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 300 parm b000
play ac3
---> first with iec958 on (set digi converter) Mar 30 18:41:51 gandalf kernel: snd_hda_spdif_out_switch_put: val 2b1 change 1 spdif_ctls 2b1 Mar 30 18:41:51 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm b1 Mar 30 18:41:51 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70e parm 2 Mar 30 18:41:51 gandalf kernel: snd_hda_spdif_out_switch_put: val 2b1 change 0 spdif_ctls 2b1 ---> then set the stream format Mar 30 18:41:51 gandalf kernel: snd_hda_calc_stream_format: format 2, iec958 BE 0, iec958 LE 0 Mar 30 18:41:51 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/../../alsa-kernel/pci/hda/hda_intel.c:1163: azx_pcm_prepare: bufsize=0x10000, fragsize=0x800, format=0x11 Mar 30 18:41:51 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x5, channel=0, format=0x11 Mar 30 18:41:51 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 50 Mar 30 18:41:51 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 11 Mar 30 18:41:51 gandalf kernel: snd_hda_calc_stream_format: format 2, iec958 BE 0, iec958 LE 0 ---> stream format is set twice (???) Mar 30 18:41:51 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/../../alsa-kernel/pci/hda/hda_intel.c:1163: azx_pcm_prepare: bufsize=0x10000, fragsize=0x800, format=0x11 Mar 30 18:41:51 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x5, channel=0, format=0x11 Mar 30 18:41:51 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 50 Mar 30 18:41:51 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 11
stop ac3
Mar 30 18:42:30 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x0, channel=0, format=0x0 Mar 30 18:42:30 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 0 Mar 30 18:42:30 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 0 Mar 30 18:42:30 gandalf kernel: snd_hda_spdif_out_switch_put: val 281 change 1 spdif_ctls 281 Mar 30 18:42:30 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70d parm 81 Mar 30 18:42:30 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 70e parm 2 Mar 30 18:42:30 gandalf kernel: snd_hda_spdif_out_switch_put: val 281 change 0 spdif_ctls 281 Mar 30 18:42:30 gandalf kernel: ALSA /home/domi/freeware/alsa-stuff/alsa-driver-1.0.14rc3/pci/hda/hda_codec.c:633: hda_codec_setup_stream: NID=0x6, stream=0x0, channel=0, format=0x0 Mar 30 18:42:30 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 706 parm 0 Mar 30 18:42:30 gandalf kernel: snd_hda_codec_write: nid 6 direct 0 verb 200 parm 0
At this point, I think there's a problem with the fact that playing ac3 stream is done with: - set digi converter - then set the stream format.
If the stream format is not valid when the digi converter is set up, there's a chance that the digi converter goes belly up.
I reckon that setting the stream *then* the digi converter would be safer.
I've not yet tested this theory.
Cheers