[alsa-devel] iec958 switch uneffective while playing ac3 stream

Dominique Dumont domi at komarr.grenoble.hp.com
Tue Apr 3 10:43:14 CEST 2007


Takashi Iwai <tiwai at 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

-- 
Dominique Dumont 
"Delivering successful solutions requires giving people what they
need, not what they want." Kurt Bittner


More information about the Alsa-devel mailing list