Skip to contentSkip to conversation

emu10k1: add interval timer support

PATCH In review Lee Revell 4 participants 35 messages Sep 17, 2004 – Nov 10, 2004

lore
Share & tools
lore

Lee Revell

author
#0 lore raw

PATCH 1/1 emu10k1: add interval timer support

This patch adds the necessary functions to support the emu10k1's interval timer. The interval timer is the mechanism used by every other known emu10k1 driver to generate the period interrupts for playback. These are ported from the OSS driver.

The card record, emu, maintains a linked list of timers, each containing a pointer to a playback substream. The open callback would install a timer and the prepare callback would enable it; when the timer interrupt fires, we walk the list of timers and call snd_pcm_period_elapsed for any substreams whose timer has expired. Supported intervals are 4-1024 sample periods. The timer's tick rate is fixed at one sample period at 48KHZ, so you have to correct if using a different sample rate.

This patch does *not* change the behavior of the driver; it just adds the necessary functions to install, uninstall, enable, disable, and set the timer. This is the first step to eliminating the extra voice; that will be posted separately when it has been fully tested.

Lee

--

Index: alsa/alsa-kernel/include/emu10k1.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/include/emu10k1.h,v retrieving revision 1.45

alsa-kernel/include/emu10k1.h +29 -0
diff -u -r1.45 emu10k1.h
@@ -779,6 +779,7 @@
 typedef struct _snd_emu10k1 emu10k1_t;
 typedef struct _snd_emu10k1_voice emu10k1_voice_t;
 typedef struct _snd_emu10k1_pcm emu10k1_pcm_t;
+typedef struct _snd_emu10k1_timer emu10k1_timer_t;
 
 typedef enum {
 	EMU10K1_PCM,
@@ -811,6 +812,7 @@
 	snd_pcm_substream_t *substream;
 	emu10k1_voice_t *voices[2];
 	emu10k1_voice_t *extra;
+	emu10k1_timer_t *timer;
 	unsigned short running;
 	unsigned short first_ptr;
 	snd_util_memblk_t *memblk;
@@ -1004,6 +1006,21 @@
 	emu10k1_midi_t midi2; /* for audigy */
 
 	unsigned int efx_voices_mask[2];
+
+	struct list_head	timers;
+	unsigned short		timer_delay;
+	spinlock_t		timer_lock;
+
+};
+
+struct _snd_emu10k1_timer 
+{
+	struct list_head list;
+	snd_pcm_substream_t *substream;
+	unsigned char state; 
+	unsigned short count;		/* current number of interrupts */
+	unsigned short count_max;	/* number of interrupts needed to call snd_pcm_period_elapsed */
+	unsigned short delay;           /* timer delay */
 };
 
 int snd_emu10k1_create(snd_card_t * card,
@@ -1077,6 +1095,18 @@
 int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
 					      snd_emu10k1_fx8010_irq_t *irq);
 
+/* interval timer */
+void snd_emu10k1_timer_install(emu10k1_t *emu, emu10k1_timer_t *timer, unsigned short delay);
+void snd_emu10k1_timer_uninstall(emu10k1_t *emu, emu10k1_timer_t *timer);
+void snd_emu10k1_timer_enable(emu10k1_t *emu, emu10k1_timer_t *timer);
+void snd_emu10k1_timer_disable(emu10k1_t *emu, emu10k1_timer_t *timer);
+void snd_emu10k1_timer_set(emu10k1_t *emu, unsigned short delay);
+
+#define TIMER_STOPPED 			0xffff 
+#define TIMER_STATE_INSTALLED 		0x01
+#define TIMER_STATE_ACTIVE		0x02
+#define TIMER_STATE_UNINSTALLED 	0x04
+
 #endif /* __KERNEL__ */
 
 /*

Index: alsa/alsa-kernel/pci/emu10k1/io.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/emu10k1/io.c,v retrieving revision 1.7

alsa-kernel/pci/emu10k1/io.c +150 -0

153 lines not on this page · raw message

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#1 lore raw
Quoted 4 lines · Lee Revell

This patch adds the necessary functions to support the emu10k1's interval timer. The interval timer is the mechanism used by every other known emu10k1 driver to generate the period interrupts for playback. These are ported from the OSS driver.

1) please, make snd_emu10k1_timer_set() function inlined
2) use atomic bitops for timer->state and make also enable/disable functions inlined
3) I don't like so much proposed scheduling as I stated in my previous e-mails; you cannot guarantee the right period boundary acknowledge at all - there will be always some additional delay when more than one stream is activated
4) the more appropriate place for the card's timer is timer API
5) multichannel PCM should be created rather trying to do ugly things with timer

Jaroslav

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#2 lore raw
Quoted 5 lines · Jaroslav Kysela

On Fri, 17 Sep 2004, Lee Revell wrote:
3) I don't like so much proposed scheduling as I stated in my previous e-mails; you cannot guarantee the right period boundary acknowledge at all - there will be always some additional delay when more than one stream is activated

OK, I think I see your point. The channel loop interrupts give you 32/64 separate interrupt sources, where the timer interrupt is monolithic, and won't work well with multiple streams using different period sizes.

Quoted 2 lines

5) multichannel PCM should be created rather trying to do ugly things with timer

This is my current project. I almost have it working, but I have a few questions.

I am using kX ASIO as a reference for how multichannel PCM should work.

Quoted 1 line

From the application's point of view, this looks like 16 mono channels.

In the mixer, for each of the 16 ASIO channels you have 4/8 drop down boxes to set the FX send destinations and 4/8 sliders to set the send amounts. By default ASIO 1 goes to FXBus channel 0, 2 goes to FXBus 1, etc. Multiple applications can open the same ASIO channel and the driver will allocate additional voices with the same send routing.

I think that the ALSA equivalent would be to have another device with channels_min=channels_max=1, and 16 substreams for which the routing would be controlled with the mixer; if multiple applications open the same substream we would allocate another voice. You would call snd_pcm_period_elapsed for each of these streams in the handler for the EFX capture interrupt. All applications using this device must use the same period size settings, as in the Windows driver, the only setting in the ASIO control panel is the latency aka buffer size.

You would then use an .asoundrc plugin that would look like a 16 channel PCM device, and would consist of 16 mono channels, hw:x,x,0 through hw:x,x,15.

I am not sure of a few things. Does it matter whether I use INTERLEAVED or NONINTERLEAVED, since the device only supports mono streams? Also, since all capture and playback streams for this device will be updated in the same interrupt handler, would it be best to use the linked substreams feature of ALSA, or do this manually with list_for_each?

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#3 lore raw

At Tue, 21 Sep 2004 15:36:42 -0400,

Quoted 18 lines · Lee Revell

I am using kX ASIO as a reference for how multichannel PCM should work. From the application's point of view, this looks like 16 mono channels. In the mixer, for each of the 16 ASIO channels you have 4/8 drop down boxes to set the FX send destinations and 4/8 sliders to set the send amounts. By default ASIO 1 goes to FXBus channel 0, 2 goes to FXBus 1, etc. Multiple applications can open the same ASIO channel and the driver will allocate additional voices with the same send routing.

I think that the ALSA equivalent would be to have another device with channels_min=channels_max=1, and 16 substreams for which the routing would be controlled with the mixer; if multiple applications open the same substream we would allocate another voice. You would call snd_pcm_period_elapsed for each of these streams in the handler for the EFX capture interrupt. All applications using this device must use the same period size settings, as in the Windows driver, the only setting in the ASIO control panel is the latency aka buffer size.

Quoted 3 lines

You would then use an .asoundrc plugin that would look like a 16 channel PCM device, and would consist of 16 mono channels, hw:x,x,0 through hw:x,x,15.

Maybe I didn't get your point, but why not simply provide a 16-channel non-interleaved device?

Quoted 2 lines

I am not sure of a few things. Does it matter whether I use INTERLEAVED or NONINTERLEAVED, since the device only supports mono streams?

No, it shouldn't.

Quoted 4 lines

Also,
since all capture and playback streams for this device will be updated in the same interrupt handler, would it be best to use the linked substreams feature of ALSA, or do this manually with list_for_each?

The interrupt handling of linked substreams are not in the linked way. The linked streams are provided for the synchronized start (and stop). The update must be done independently. So, the correct implementation is the latter, list_for_each in the irq handler, regardless of the linked state.

Takashi

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#4 lore raw
Quoted 6 lines · Takashi Iwai
Quoted 3 lines

You would then use an .asoundrc plugin that would look like a 16 channel PCM device, and would consist of 16 mono channels, hw:x,x,0 through hw:x,x,15.

Maybe I didn't get your point, but why not simply provide a 16-channel non-interleaved device?

Yes, I agree here with Takashi.

Jaroslav

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#5 lore raw
In reply to Takashi Iwai
Quoted 20 lines · Takashi Iwai

At Tue, 21 Sep 2004 15:36:42 -0400,

Quoted 18 lines · Lee Revell

I am using kX ASIO as a reference for how multichannel PCM should work. From the application's point of view, this looks like 16 mono channels. In the mixer, for each of the 16 ASIO channels you have 4/8 drop down boxes to set the FX send destinations and 4/8 sliders to set the send amounts. By default ASIO 1 goes to FXBus channel 0, 2 goes to FXBus 1, etc. Multiple applications can open the same ASIO channel and the driver will allocate additional voices with the same send routing.

I think that the ALSA equivalent would be to have another device with channels_min=channels_max=1, and 16 substreams for which the routing would be controlled with the mixer; if multiple applications open the same substream we would allocate another voice. You would call snd_pcm_period_elapsed for each of these streams in the handler for the EFX capture interrupt. All applications using this device must use the same period size settings, as in the Windows driver, the only setting in the ASIO control panel is the latency aka buffer size.

Quoted 7 lines
Quoted 3 lines

You would then use an .asoundrc plugin that would look like a 16 channel PCM device, and would consist of 16 mono channels, hw:x,x,0 through hw:x,x,15.

Maybe I didn't get your point, but why not simply provide a 16-channel non-interleaved device?

Several reasons. With the kX driver, if I am using a ReWire host like Ableton Live, and I want to use an app that is not ReWire capable, I would have the app output to two extra ASIO channels, say 10 and 11, and Live can use these as inputs like any other physical input. Live would then output to ASIO 1/2 (front), ASIO 3/4 (rear), and ASIO 5/6 (headphones/prelisten). It seems like the best way to do this in ALSA is to have the driver support a bunch of mono channels and use alsalib plugins to make multichannel devices out of these.

How would I open only channels 10 and 11 with one app and 1-6 with another using a single 16 channel device?

Also, it seemed like it would be easier to handle mmap with a bunch of mono streams, but maybe I don't understand the mmap completely. The OSS driver for example does not support mmap for multichannel PCM.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#6 lore raw

At Wed, 22 Sep 2004 11:01:11 -0400,

Quoted 39 lines · Lee Revell
Quoted 20 lines · Takashi Iwai

At Tue, 21 Sep 2004 15:36:42 -0400,

Quoted 18 lines · Lee Revell

I am using kX ASIO as a reference for how multichannel PCM should work. From the application's point of view, this looks like 16 mono channels. In the mixer, for each of the 16 ASIO channels you have 4/8 drop down boxes to set the FX send destinations and 4/8 sliders to set the send amounts. By default ASIO 1 goes to FXBus channel 0, 2 goes to FXBus 1, etc. Multiple applications can open the same ASIO channel and the driver will allocate additional voices with the same send routing.

I think that the ALSA equivalent would be to have another device with channels_min=channels_max=1, and 16 substreams for which the routing would be controlled with the mixer; if multiple applications open the same substream we would allocate another voice. You would call snd_pcm_period_elapsed for each of these streams in the handler for the EFX capture interrupt. All applications using this device must use the same period size settings, as in the Windows driver, the only setting in the ASIO control panel is the latency aka buffer size.

Quoted 7 lines
Quoted 3 lines

You would then use an .asoundrc plugin that would look like a 16 channel PCM device, and would consist of 16 mono channels, hw:x,x,0 through hw:x,x,15.

Maybe I didn't get your point, but why not simply provide a 16-channel non-interleaved device?

Several reasons. With the kX driver, if I am using a ReWire host like Ableton Live, and I want to use an app that is not ReWire capable, I would have the app output to two extra ASIO channels, say 10 and 11, and Live can use these as inputs like any other physical input. Live would then output to ASIO 1/2 (front), ASIO 3/4 (rear), and ASIO 5/6 (headphones/prelisten). It seems like the best way to do this in ALSA is to have the driver support a bunch of mono channels and use alsalib plugins to make multichannel devices out of these.

Quoted 2 lines

How would I open only channels 10 and 11 with one app and 1-6 with another using a single 16 channel device?

It's doable to implement the multi-channel non-interleaved PCM with multi open. But even in this case, we provide eventually 16 substreams, so perhaps providing 16 mono substreams would be easier to implement (at least for the kernel driver).

Regarding the efficiency (latency), there will be no difference between the multi-channel and multi-substream implementations. In the latter case, we can use linked substreams, as you already mentioned.

Quoted 3 lines

Also, it seemed like it would be easier to handle mmap with a bunch of mono streams, but maybe I don't understand the mmap completely. The OSS driver for example does not support mmap for multichannel PCM.

This doesn't matter on ALSA. The mmap of a multi-channel non-interleaved substream is handled as well as a normal substream. The snd_pcm_mmap_begin() and commit() hide the difference well.

Takashi

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#7 lore raw
Quoted 8 lines · Takashi Iwai
Quoted 2 lines

How would I open only channels 10 and 11 with one app and 1-6 with another using a single 16 channel device?

It's doable to implement the multi-channel non-interleaved PCM with multi open. But even in this case, we provide eventually 16 substreams, so perhaps providing 16 mono substreams would be easier to implement (at least for the kernel driver).

Quoted 4 lines

Regarding the efficiency (latency), there will be no difference between the multi-channel and multi-substream implementations. In the latter case, we can use linked substreams, as you already mentioned.

I don't understand much the requirement. If you want to use other ALSA (legacy) applications, you can reroute them to appropriate FX bus only. The controls are already available.

The multichannel PCM should be best only for multichannel recording / playback. You're trying to desing a new API which does not make much sense.

Jaroslav

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#8 lore raw
Quoted 15 lines · Takashi Iwai
Quoted 9 lines
Quoted 3 lines

How would I open only channels 10 and 11 with one app and 1-6 with another using a single 16 channel device?

It's doable to implement the multi-channel non-interleaved PCM with multi open. But even in this case, we provide eventually 16 substreams, so perhaps providing 16 mono substreams would be easier to implement (at least for the kernel driver).

Quoted 4 lines

Regarding the efficiency (latency), there will be no difference between the multi-channel and multi-substream implementations. In the latter case, we can use linked substreams, as you already mentioned.

Quoted 7 lines

I don't understand much the requirement. If you want to use other ALSA (legacy) applications, you can reroute them to appropriate FX bus only. The controls are already available.

The multichannel PCM should be best only for multichannel recording / playback. You're trying to desing a new API which does not make much sense.

more to the point, perhaps, is that the very first implementation of the RME Hammerfall (digi9652) driver that i did took lee's approach and when we measured it, there was a very definite performance hit. having to call the "elapsed" function for every mono stream added measurable overhead. when we collapsed it back to a single non-interleaved, 26 channel device, it was significantly more efficient.

if the "multi" PCM device/plugin works this would be a far preferable way to implement the multichannel PCM device on this card, IMHO.

--p

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#9 lore raw

At Fri, 24 Sep 2004 10:53:55 -0400,

Quoted 24 lines · Paul Davis
Quoted 16 lines · Takashi Iwai
Quoted 9 lines
Quoted 3 lines

How would I open only channels 10 and 11 with one app and 1-6 with another using a single 16 channel device?

It's doable to implement the multi-channel non-interleaved PCM with multi open. But even in this case, we provide eventually 16 substreams, so perhaps providing 16 mono substreams would be easier to implement (at least for the kernel driver).

Quoted 4 lines

Regarding the efficiency (latency), there will be no difference between the multi-channel and multi-substream implementations. In the latter case, we can use linked substreams, as you already mentioned.

Quoted 7 lines

I don't understand much the requirement. If you want to use other ALSA (legacy) applications, you can reroute them to appropriate FX bus only. The controls are already available.

The multichannel PCM should be best only for multichannel recording / playback. You're trying to desing a new API which does not make much sense.

Quoted 7 lines

more to the point, perhaps, is that the very first implementation of the RME Hammerfall (digi9652) driver that i did took lee's approach and when we measured it, there was a very definite performance hit. having to call the "elapsed" function for every mono stream added measurable overhead. when we collapsed it back to a single non-interleaved, 26 channel device, it was significantly more efficient.

It's a good point. If you use the timer-style irq, the perfomance decrease would be smaller, though, because you don't (can't) get irqs per PCM stream. However, the overhead must still exist.

Takashi

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#10 lore raw
Quoted 11 lines
Quoted 7 lines

more to the point, perhaps, is that the very first implementation of the RME Hammerfall (digi9652) driver that i did took lee's approach and when we measured it, there was a very definite performance hit. having to call the "elapsed" function for every mono stream added measurable overhead. when we collapsed it back to a single non-interleaved, 26 channel device, it was significantly more efficient.

It's a good point. If you use the timer-style irq, the perfomance decrease would be smaller, though, because you don't (can't) get irqs per PCM stream. However, the overhead must still exist.

it was the same with the digi9652 - one interrupt source per card card, but the elapsed callback had to be made to each stream.

--p

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#11 lore raw

At Fri, 24 Sep 2004 11:26:15 -0400,

Quoted 9 lines · Paul Davis
Quoted 9 lines
Quoted 8 lines

more to the point, perhaps, is that the very first implementation of the RME Hammerfall (digi9652) driver that i did took lee's approach and when we measured it, there was a very definite performance hit. having to call the "elapsed" function for every mono stream added measurable overhead. when we collapsed it back to a single non-interleaved, 26 channel device, it was significantly more efficient.

Quoted 6 lines
Quoted 3 lines

It's a good point. If you use the timer-style irq, the perfomance decrease would be smaller, though, because you don't (can't) get irqs per PCM stream. However, the overhead must still exist.

it was the same with the digi9652 - one interrupt source per card card, but the elapsed callback had to be made to each stream.

OK, then is it the overhead of kernel/user switches?
If we use multi mono streams, poll is called N times. I can imagine this would hit performance loss.

Other possibility is the overhead of the task done in snd_pcm_period_elapsed(). But if this really hits, we have to eliminate it.

Takashi

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#12 lore raw

emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

In reply to Takashi Iwai
Quoted 34 lines · Takashi Iwai

At Fri, 24 Sep 2004 10:53:55 -0400,

Quoted 24 lines · Paul Davis
Quoted 16 lines · Takashi Iwai
Quoted 9 lines
Quoted 3 lines

How would I open only channels 10 and 11 with one app and 1-6 with another using a single 16 channel device?

It's doable to implement the multi-channel non-interleaved PCM with multi open. But even in this case, we provide eventually 16 substreams, so perhaps providing 16 mono substreams would be easier to implement (at least for the kernel driver).

Quoted 4 lines

Regarding the efficiency (latency), there will be no difference between the multi-channel and multi-substream implementations. In the latter case, we can use linked substreams, as you already mentioned.

Quoted 7 lines

I don't understand much the requirement. If you want to use other ALSA (legacy) applications, you can reroute them to appropriate FX bus only. The controls are already available.

The multichannel PCM should be best only for multichannel recording / playback. You're trying to desing a new API which does not make much sense.

Quoted 7 lines

more to the point, perhaps, is that the very first implementation of the RME Hammerfall (digi9652) driver that i did took lee's approach and when we measured it, there was a very definite performance hit. having to call the "elapsed" function for every mono stream added measurable overhead. when we collapsed it back to a single non-interleaved, 26 channel device, it was significantly more efficient.

Quoted 4 lines

It's a good point. If you use the timer-style irq, the perfomance decrease would be smaller, though, because you don't (can't) get irqs per PCM stream. However, the overhead must still exist.

While certainly easier to implement in the driver, the problem with a single 16 channel device is that it wastes voices. In the example of a non-ReWire compliant app (which is the same as working around a non-JACK aware app), you would have to use 16 voices for each open, even if the device will only use 2 of the channels.

The current driver does support something like this, via the FX send routing controls for playback streams. Really the only difference here is that instead of using an extra voice for the timer like the current driver, you would call the elapsed function in the EFX capture interrupt handler. I actually looked at the RME drivers and it would work in a similar way; a single interrupt source for the full-duplex device. The timer interrupt will probably not be used at all; Jaroslav has convinced me the extra voice is the best solution for regular PCM playback (system sounds and whatnot).

It is more efficient to use a single 16 channel non-interleaved device if, as in the case of JACK, only one app will be using the device and it will use all channels. Individual mono streams become more efficient as the channel count gets lower.

Quoted 1 line

From reading the changelogs of the kX drivers, and reading some posts

that the author made in the forums, it looks like they originally used a single 16 channel device, then later moved to individual mono streams as in my proposal. For example their driver originally did not support multiple open, because they probably just grabbed 16 voices at startup. Also with kX ASIO you can lower the CPU load by only opening as many playback channels as you will use, because with multiple mono channels the amount of work you do in the interrupt handler is proportional to the number of channels.

Anyway I will probably start with whatever is easier to get working. This will actually not be a huge patch, and I certainly don't want to design a new API. I am just running through some more complex use cases that I know work on Windows to verify I am on the right track.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#13 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 4 lines

It is more efficient to use a single 16 channel non-interleaved device if, as in the case of JACK, only one app will be using the device and it will use all channels. Individual mono streams become more efficient as the channel count gets lower.

this is a reasonable point.

Quoted 4 lines

Also with kX ASIO you can lower the CPU load by only opening as many playback channels as you will use, because with multiple mono channels the amount of work you do in the interrupt handler is proportional to the number of channels.

maybe so with kX ASIO, but this not true of ALSA. the work done by the interrupt handler is proportional to the number of open streams, not channels. a 26 channel device consumes the same number of cycles at interrupt time as a single channel device.

the only thing that goes is required down with the channel count is the bus bandwidth utilized. the CPU cycles used will depend on the mixer configuration etc (i.e. do you have to silence the unused channel buffers each time, or can you just mute them) ...

--p

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#14 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 10 lines · Paul Davis
Quoted 4 lines

Also with kX ASIO you can lower the CPU load by only opening as many playback channels as you will use, because with multiple mono channels the amount of work you do in the interrupt handler is proportional to the number of channels.

maybe so with kX ASIO, but this not true of ALSA. the work done by the interrupt handler is proportional to the number of open streams, not channels. a 26 channel device consumes the same number of cycles at interrupt time as a single channel device.

Quoted 4 lines

the only thing that goes is required down with the channel count is the bus bandwidth utilized. the CPU cycles used will depend on the mixer configuration etc (i.e. do you have to silence the unused channel buffers each time, or can you just mute them) ...

OK, makes sense. Maybe the kX driver behaves this way because of the way ASIO calls the process callback from the interrupt handler.

Anyway, using a few more voices than necessary is not as much of an issue. The only important use of multiple open with this device is to work around a non-JACK aware app by having it output to the FX bus. It seems that the single 16 channel device will be easier to implement, so I am going to start with that, and the initial implementation will not support multiple open for playback.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#15 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

In reply to Paul Davis
Quoted 7 lines · Paul Davis
Quoted 4 lines

It is more efficient to use a single 16 channel non-interleaved device if, as in the case of JACK, only one app will be using the device and it will use all channels. Individual mono streams become more efficient as the channel count gets lower.

this is a reasonable point.

OK, thanks everyone for your help. I now have the basic device working. At least, it compiles and I can open it...

I noticed the RME drivers use an interesting hack, of checking whether the playback and capture device are open by the same PID. My device will require something similar, as it also requires the same period size in both directions. Would you recommend using the same method, or is there a "better" way? Seems like this will work fine for jack, which is the targeted user anyway.

With ASIO, I think this problem is solved by some kind of system wide hook. If I use different ASIO apps, each will have a button in the config that opens the system-wide ASIO control panel widget where I can set the buffer size; changing it will change it for all apps. Some handle this better than others; some will hiccup and some will have to have their audio engine restarted.

Maybe ALSA should implement a system-wide method to set properties like this that apply to playback and capture devices. Or maybe this is better handled with a hardware specific app.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#16 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

In reply to Lee Revell
Quoted 4 lines · Lee Revell

Anyway I will probably start with whatever is easier to get working. This will actually not be a huge patch, and I certainly don't want to design a new API. I am just running through some more complex use cases that I know work on Windows to verify I am on the right track.

OK, hopefully I am on the right track.

Here's a normal stereo interleaved pcm being opened. The L and R voices have the same start and end addresses because it's interleaved, and the extra voice is silent, it loops generating the period interrupts. Here 16 periods per buffer are used.

init voice - master 1 extra 1 start_addr 0x1000 end_addr 0x2000 init voice - master 1 extra 0 start_addr 0x1000 end_addr 0x11000 init voice - master 0 extra 0 start_addr 0x1000 end_addr 0x11000

Here is the multichannel device being opened. I split the buffer up into 16 chunks, and allocate a voice for each:

pcm_channel_alloc: voices=16
in snd_emu10k1_efx_playback_prepare - start_addr 0x1000 end_addr 0x11000 init voice - master 1 extra 0 start_addr 0x1000 end_addr 0x2000 init voice - master 1 extra 0 start_addr 0x2000 end_addr 0x3000 init voice - master 1 extra 0 start_addr 0x3000 end_addr 0x4000

Unable to handle kernel NULL pointer dereference at virtual address 00000010
 printing eip:

Looks good, until it Oops'es. This is because currently the voice allocator only handles one or two voices at a time, it blows up as soon as I go to initialize the third voice. I am working on this.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#17 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 3 lines · Lee Revell

Looks good, until it Oops'es. This is because currently the voice allocator only handles one or two voices at a time, it blows up as soon as I go to initialize the third voice. I am working on this.

OK, I fixed the voice allocator to handle multichannel PCM. Now it looks like the prepare callback is being called over and over in a loop.

Here is the debug output from the prepare callback:

in snd_emu10k1_efx_playback_prepare - start_addr 0x1000 end_addr 0x11000 init voice - master 1 extra 0 start_addr 0x1000 end_addr 0x2000 init voice - master 1 extra 0 start_addr 0x2000 end_addr 0x3000 init voice - master 1 extra 0 start_addr 0x3000 end_addr 0x4000 init voice - master 1 extra 0 start_addr 0x4000 end_addr 0x5000 init voice - master 1 extra 0 start_addr 0x5000 end_addr 0x6000 init voice - master 1 extra 0 start_addr 0x6000 end_addr 0x7000 init voice - master 1 extra 0 start_addr 0x7000 end_addr 0x8000 init voice - master 1 extra 0 start_addr 0x8000 end_addr 0x9000 init voice - master 1 extra 0 start_addr 0x9000 end_addr 0xa000 init voice - master 1 extra 0 start_addr 0xa000 end_addr 0xb000 init voice - master 1 extra 0 start_addr 0xb000 end_addr 0xc000 init voice - master 1 extra 0 start_addr 0xc000 end_addr 0xd000 init voice - master 1 extra 0 start_addr 0xd000 end_addr 0xe000 init voice - master 1 extra 0 start_addr 0xe000 end_addr 0xf000 init voice - master 1 extra 0 start_addr 0xf000 end_addr 0x10000 init voice - master 1 extra 0 start_addr 0x10000 end_addr 0x11000 in snd_emu10k1_efx_playback_prepare - start_addr 0x1000 end_addr 0x11000 init voice - master 1 extra 0 start_addr 0x1000 end_addr 0x2000 init voice - master 1 extra 0 start_addr 0x2000 end_addr 0x3000

When I start jack, the above repeats endlessly.

Here is the prepare callback:

static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream)

{
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
        emu10k1_pcm_t *epcm = runtime->private_data;
        unsigned int start_addr, end_addr;

        start_addr = epcm->start_addr;
        end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
        printk("in snd_emu10k1_efx_playback_prepare - start_addr 0x%x end_addr 0x%x\n", start_addr,end_addr);

        /*
         * now we need to divide the buffer into 16 chunks and initialize
         * 16 voices to make the noninterleaved 16 channel stream
         */
        unsigned int channel_size;
        int i;
        channel_size = ( end_addr - start_addr ) / 16;
        for (i = 0; i < 16; i++) {
            snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[i],
                                   start_addr, start_addr+channel_size);
            start_addr += channel_size;
        }
   
        return 0;
}

I am still missing parts of the driver, like the interrupt handler. But it seems like the prepare callback should not loop this way. Am I doing something wrong?

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#18 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 7 lines · Lee Revell

OK, I fixed the voice allocator to handle multichannel PCM. Now it looks like the prepare callback is being called over and over in a loop.

I am still missing parts of the driver, like the interrupt handler. But it seems like the prepare callback should not loop this way. Am I doing something wrong?

Never mind, I answered my own question - because I don't have an interrupt handler yet jackd keeps restarting the stream when it gets woken up by the capture interrupt and sees that nothing has happened on the playback side.

So, jackd opens the 16 channel device correctly. But speaker-test doesn't seem to work. I tried it like this:

rlrevell@mindpipe:~$ speaker-test -c 16 -D hw:0,3

speaker-test 1.0.5

Playback device is hw:0,3
Stream parameters are 48000Hz, S16_LE, 16 channels Sine wave rate is 440.0000Hz
Access type not available for playback: Invalid argument Setting of hwparams failed: Invalid argument

But, you can see in the logs that it does not even try to open the pcm. Is there a hardcoded limit of how many channels speaker-test supports?

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#19 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

In reply to Lee Revell
Quoted 2 lines

OK, I fixed the voice allocator to handle multichannel PCM. Now it looks like the prepare callback is being called over and over in a loop.

[ ... ]

Quoted 3 lines

I am still missing parts of the driver, like the interrupt handler. But it seems like the prepare callback should not loop this way. Am I doing something wrong?

i would finish the driver before getting too deeply into this. the interrupt handler is sorta-kinda important :)

jack has other ways of detecting timeouts, for example, and it may be really calling the prepare callback many times.

--p

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#20 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 12 lines · Paul Davis
Quoted 2 lines

OK, I fixed the voice allocator to handle multichannel PCM. Now it looks like the prepare callback is being called over and over in a loop.

   [ ... ]
Quoted 3 lines

I am still missing parts of the driver, like the interrupt handler. But it seems like the prepare callback should not loop this way. Am I doing something wrong?

i would finish the driver before getting too deeply into this. the interrupt handler is sorta-kinda important :)

Yes, I just wanted to make sure I have the easy parts right, rather than posting a huge patch and saying 'it doesn't work, anyone know why'. Anyway I think I have got it.

Thanks,

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#21 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

In reply to Paul Davis
Quoted 9 lines · Paul Davis
Quoted 2 lines

OK, I fixed the voice allocator to handle multichannel PCM. Now it looks like the prepare callback is being called over and over in a loop.

   [ ... ]
Quoted 3 lines

I am still missing parts of the driver, like the interrupt handler. But it seems like the prepare callback should not loop this way. Am I doing something wrong?

The interrupt handler fortunately was a one liner. All I have left is the pointer callback and it should work.

I am really amazed at how much better ALSA is than OSS now. Most of the code in the OSS driver is not needed in the ALSA driver because the middle layer is so powerful.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#22 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 6 lines · Lee Revell
Quoted 5 lines · Paul Davis
Quoted 2 lines

OK, I fixed the voice allocator to handle multichannel PCM. Now it looks like the prepare callback is being called over and over in a loop.

   [ ... ]
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines

I am still missing parts of the driver, like the interrupt handler. But it seems like the prepare callback should not loop this way. Am I doing something wrong?

The interrupt handler fortunately was a one liner. All I have left is the pointer callback and it should work.

OK, I have the basic driver working, but I think I am doing something wrong somewhere. Jack can open the device but the watchdog thread times it out, and it looks like the prepare callback is being called over and over. However the hardware pointer looks correct:

ptr = 0x84c, ccca_start_addr = 0x803c
ptr = 0x10, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
ptr = 0xc2f, ccca_start_addr = 0x803c
ptr = 0x3f3, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
in snd_emu10k1_efx_playback_prepare - start_addr 0x1000 end_addr 0x11000 init voice - master 1 extra 0 start_addr 0x800 end_addr 0x1000 init voice - master 1 extra 0 start_addr 0x1000 end_addr 0x1800 init voice - master 1 extra 0 start_addr 0x1800 end_addr 0x2000 init voice - master 1 extra 0 start_addr 0x2000 end_addr 0x2800 init voice - master 1 extra 0 start_addr 0x2800 end_addr 0x3000 init voice - master 1 extra 0 start_addr 0x3000 end_addr 0x3800 init voice - master 1 extra 0 start_addr 0x3800 end_addr 0x4000 init voice - master 1 extra 0 start_addr 0x4000 end_addr 0x4800 init voice - master 1 extra 0 start_addr 0x4800 end_addr 0x5000 init voice - master 1 extra 0 start_addr 0x5000 end_addr 0x5800 init voice - master 1 extra 0 start_addr 0x5800 end_addr 0x6000 init voice - master 1 extra 0 start_addr 0x6000 end_addr 0x6800 init voice - master 1 extra 0 start_addr 0x6800 end_addr 0x7000 init voice - master 1 extra 0 start_addr 0x7000 end_addr 0x7800 init voice - master 1 extra 0 start_addr 0x7800 end_addr 0x8000 init voice - master 1 extra 0 start_addr 0x8000 end_addr 0x8800 ptr = 0x84d, ccca_start_addr = 0x803c
ptr = 0x11, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
ptr = 0xc2f, ccca_start_addr = 0x803c
ptr = 0x3f3, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
in snd_emu10k1_efx_playback_prepare - start_addr 0x1000 end_addr 0x11000 init voice - master 1 extra 0 start_addr 0x800 end_addr 0x1000

...

init voice - master 1 extra 0 start_addr 0x8000 end_addr 0x8800 ptr = 0x84d, ccca_start_addr = 0x803c
ptr = 0x11, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
ptr = 0xc2f, ccca_start_addr = 0x803c
ptr = 0x3f3, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
in snd_emu10k1_efx_playback_prepare - start_addr 0x1000 end_addr 0x11000 init voice - master 1 extra 0 start_addr 0x800 end_addr 0x1000

...

init voice - master 1 extra 0 start_addr 0x8000 end_addr 0x8800 ptr = 0x84c, ccca_start_addr = 0x803c
ptr = 0x10, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
ptr = 0xc2f, ccca_start_addr = 0x803c
ptr = 0x3f3, buffer_size = 0x800, period_size = 0x400
in capture efx irq handler, updating playback stream
in snd_emu10k1_efx_playback_prepare - start_addr 0x1000 end_addr 0x11000 init voice - master 1 extra 0 start_addr 0x800 end_addr 0x1000

...

init voice - master 1 extra 0 start_addr 0x8000 end_addr 0x8800 ptr = 0x84e, ccca_start_addr = 0x803c
ptr = 0x12, buffer_size = 0x800, period_size = 0x400 in capture efx irq handler, updating playback stream ptr = 0xc2c, ccca_start_addr = 0x803c
ptr = 0x3f0, buffer_size = 0x800, period_size = 0x400 in capture efx irq handler, updating playback stream

The jitter is about the same as with the extra voice method, 0-3 samples. However it looks like with every other interrupt it resets the stream.

Do I need to post the code to debug this further?

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#23 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

In reply to Lee Revell
Quoted 5 lines · Lee Revell

While certainly easier to implement in the driver, the problem with a single 16 channel device is that it wastes voices. In the example of a non-ReWire compliant app (which is the same as working around a non-JACK aware app), you would have to use 16 voices for each open, even if the device will only use 2 of the channels.

No, read carefully my messages:

- legacy applications will use standard device
- multichannel applications will use one (or more) multichannel device

Then you need an application like ReWire which will touch / modify the universal controls to reroute channels from bloth multichannel and legacy application to appropriate FX bus.

Everybody will be happy with minimal count of extended voices.

Jaroslav

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#24 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 8 lines · Jaroslav Kysela
Quoted 5 lines · Lee Revell

While certainly easier to implement in the driver, the problem with a single 16 channel device is that it wastes voices. In the example of a non-ReWire compliant app (which is the same as working around a non-JACK aware app), you would have to use 16 voices for each open, even if the device will only use 2 of the channels.

Quoted 5 lines

No, read carefully my messages:

- legacy applications will use standard device
- multichannel applications will use one (or more) multichannel device

I think I understand you. This is how I have written the driver. I'll post a patch as soon as the code is cleaned up.

Quoted 3 lines

Then you need an application like ReWire which will touch / modify the universal controls to reroute channels from bloth multichannel and legacy application to appropriate FX bus.

Yes, the mixer support is an issue I have not addressed yet. It will also require ld10k1 and some additional DSP code; since the EFX device captures the outputs and not the FX buses you need to connect FX buses (or physical inputs) to the outputs that are selected with the "EFX voices mask" control.

Quoted 3 lines

Everybody will be happy with minimal count of extended voices.

Yes, I agree. Right now I have the first 16 voices reserved for the multichannel device. For the default playback device voice allocation starts at 16.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

#25 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 3 lines · Lee Revell

Yes, I agree. Right now I have the first 16 voices reserved for the multichannel device. For the default playback device voice allocation starts at 16.

I would prefer dynamic voice allocations.

Jaroslav

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#26 lore raw

Re: emu10k1 multichannel playback design (was Re: [PATCH] emu10k1: add interval timer support)

Quoted 8 lines · Jaroslav Kysela
Quoted 3 lines · Lee Revell

Yes, I agree. Right now I have the first 16 voices reserved for the multichannel device. For the default playback device voice allocation starts at 16.

I would prefer dynamic voice allocations.

So would I. This setup is just for testing. It will allocate voices dynamically when it's finished.

Lee

-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

author
#27 lore raw
In reply to Jaroslav Kysela
Quoted 7 lines · Jaroslav Kysela
Quoted 4 lines · Lee Revell

This patch adds the necessary functions to support the emu10k1's interval timer. The interval timer is the mechanism used by every other known emu10k1 driver to generate the period interrupts for playback. These are ported from the OSS driver.

Quoted 10 lines

1) please, make snd_emu10k1_timer_set() function inlined
2) use atomic bitops for timer->state and make also enable/disable functions inlined
3) I don't like so much proposed scheduling as I stated in my previous e-mails; you cannot guarantee the right period boundary acknowledge at all - there will be always some additional delay when more than one stream is activated
4) the more appropriate place for the card's timer is timer API
5) multichannel PCM should be created rather trying to do ugly things with timer

OK I converted this code to use the ALSA timer API. This seems to work fine, I can access the timer from userspace. However there does not seem to be an existing example of a driver that uses the ALSA timer API internally; all the drivers that use the interval timer internally for PCM period interrupts have open coded timer handling. AFAICT the ALSA timer API should be OK for this purpose as well. Is this correct?

I am going to use the interval timer for multichannel PCM playback. This works by allocating 16 voices, setting loop stop on all of them, then setting the timer. In the first timer interrupt we clear loop stop on all the voices with one PCI write, then re-arm the timer, and set the PCM running; we now have 16 voices in perfect sync. Subsequent timer interrupts just call snd_pcm_period_elapsed.

The above scheme could also work with an extra voice for timing but would be uglier. Since the multichannel device does not have to support multiple open, and only 48KHZ playback, the timer seems to be a much cleaner solution. Regular PCM playback will continue to use the extra voice.

Signature · 9 lines
Lee Revell <[email protected]>



-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE
LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
author
#28 lore raw

PATCH 1/1 emu10k1: add interval timer support

Quoted 1 line · Lee Revell

OK I converted this code to use the ALSA timer API.

Here is the patch against ALSA CVS. I tested it with the ALSA from kernel 2.6.9-rc3-mm3 because CVS does not build currently.

alsa-kernel/pci/emu10k1/emu10k1.c +6 -0
diff -Nru alsa-orig/alsa-kernel/pci/emu10k1/emu10k1.c alsa/alsa-kernel/pci/emu10k1/emu10k1.c
@@ -124,6 +124,12 @@
 		snd_card_free(card);
 		return err;
 	}
+	
+	if ((err = snd_emu10k1_timer(emu, 0)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
 	if (emu->audigy) {
 		if ((err = snd_emu10k1_audigy_midi(emu)) < 0) {
 			snd_card_free(card);
alsa-kernel/pci/emu10k1/irq.c +2 -2
diff -Nru alsa-orig/alsa-kernel/pci/emu10k1/irq.c alsa/alsa-kernel/pci/emu10k1/irq.c
@@ -112,8 +112,8 @@
 			status &= ~(IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2);
 		}
 		if (status & IPR_INTERVALTIMER) {
-			if (emu->timer_interrupt)
-				emu->timer_interrupt(emu);
+			if (emu->timer)
+				snd_timer_interrupt(emu->timer, emu->timer->sticks);
 			else
 				snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB);
 			status &= ~IPR_INTERVALTIMER;
alsa-kernel/pci/emu10k1/timer.c +99 -0

99 lines not on this page · raw message

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click

author
#29 lore raw
Quoted 3 lines · Lee Revell
Quoted 1 line · Lee Revell

OK I converted this code to use the ALSA timer API.

I left this out:

and the patch is missing a chunk:

alsa-kernel/pci/emu10k1/Makefile +1 -1
@@ -5,7 +5,7 @@
 
 snd-emu10k1-objs := emu10k1.o emu10k1_main.o \
 		    irq.o memory.o voice.o emumpu401.o emupcm.o io.o \
-		    emuproc.o emumixer.o emufx.o
+		    emuproc.o emumixer.o emufx.o timer.o
 snd-emu10k1-synth-objs := emu10k1_synth.o emu10k1_callback.o emu10k1_patch.o
 
 #

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click

#30 lore raw
In reply to Lee Revell

At Wed, 03 Nov 2004 16:24:41 -0500,

Quoted 6 lines · Lee Revell
Quoted 1 line · Lee Revell

OK I converted this code to use the ALSA timer API.

Here is the patch against ALSA CVS. I tested it with the ALSA from kernel 2.6.9-rc3-mm3 because CVS does not build currently.

The patch to include/emu10k1.h is missing, too.
Could you give it?

Takashi

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click

author
#31 lore raw
Quoted 13 lines · Takashi Iwai

At Wed, 03 Nov 2004 16:24:41 -0500,

Quoted 6 lines · Lee Revell
Quoted 1 line · Lee Revell

OK I converted this code to use the ALSA timer API.

Here is the patch against ALSA CVS. I tested it with the ALSA from kernel 2.6.9-rc3-mm3 because CVS does not build currently.

The patch to include/emu10k1.h is missing, too.
Could you give it?

Sorry, here it is.

Index: alsa-kernel/include/emu10k1.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/include/emu10k1.h,v retrieving revision 1.49

include/emu10k1.h +4 -0
diff -u -r1.49 emu10k1.h
@@ -31,6 +31,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/util_mem.h>
 #include <sound/pcm-indirect.h>
+#include <sound/timer.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
 
@@ -1000,6 +1001,8 @@
 	snd_pcm_substream_t *pcm_capture_mic_substream;
 	snd_pcm_substream_t *pcm_capture_efx_substream;
 
+	snd_timer_t *timer;
+
 	emu10k1_midi_t midi;
 	emu10k1_midi_t midi2; /* for audigy */
 
@@ -1019,6 +1022,7 @@
 int snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
 int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
 int snd_emu10k1_mixer(emu10k1_t * emu);
+int snd_emu10k1_timer(emu10k1_t * emu, int device);
 int snd_emu10k1_fx8010_new(emu10k1_t *emu, int device, snd_hwdep_t ** rhwdep);
 
 irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs);

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click

#32 lore raw

At Tue, 09 Nov 2004 23:32:52 -0500,

Quoted 11 lines · Lee Revell
Quoted 9 lines · Takashi Iwai

At Wed, 03 Nov 2004 16:24:41 -0500,

Quoted 6 lines · Lee Revell
Quoted 1 line · Lee Revell

OK I converted this code to use the ALSA timer API.

Here is the patch against ALSA CVS. I tested it with the ALSA from kernel 2.6.9-rc3-mm3 because CVS does not build currently.

Quoted 6 lines
Quoted 4 lines

The patch to include/emu10k1.h is missing, too.
Could you give it?

Sorry, here it is.

Thanks, the patch was applied to CVS.

Takashi

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click

#33 lore raw
In reply to Lee Revell
Quoted 6 lines · Lee Revell

OK I converted this code to use the ALSA timer API. This seems to work fine, I can access the timer from userspace. However there does not seem to be an existing example of a driver that uses the ALSA timer API internally; all the drivers that use the interval timer internally for PCM period interrupts have open coded timer handling. AFAICT the ALSA timer API should be OK for this purpose as well. Is this correct?

Yes, you can use ALSA timers from kernel space as well.

Quoted 6 lines

I am going to use the interval timer for multichannel PCM playback. This works by allocating 16 voices, setting loop stop on all of them, then setting the timer. In the first timer interrupt we clear loop stop on all the voices with one PCI write, then re-arm the timer, and set the PCM running; we now have 16 voices in perfect sync. Subsequent timer interrupts just call snd_pcm_period_elapsed.

If timer must be re-armed in the interrupt handler, then you have a problem - time shifting when the timer ack interrupt is delayed. So you must do a time correction.

Quoted 5 lines

The above scheme could also work with an extra voice for timing but would be uglier. Since the multichannel device does not have to support multiple open, and only 48KHZ playback, the timer seems to be a much cleaner solution. Regular PCM playback will continue to use the extra voice.

The only one drawback is the possible delay at stream start (up to one period).

Jaroslav

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click

author
#34 lore raw
Quoted 11 lines · Jaroslav Kysela
Quoted 6 lines · Lee Revell

OK I converted this code to use the ALSA timer API. This seems to work fine, I can access the timer from userspace. However there does not seem to be an existing example of a driver that uses the ALSA timer API internally; all the drivers that use the interval timer internally for PCM period interrupts have open coded timer handling. AFAICT the ALSA timer API should be OK for this purpose as well. Is this correct?

Yes, you can use ALSA timers from kernel space as well.

OK. It looks like the only current example is in the sequencer. But this should be good enough.

Quoted 11 lines
Quoted 6 lines

I am going to use the interval timer for multichannel PCM playback. This works by allocating 16 voices, setting loop stop on all of them, then setting the timer. In the first timer interrupt we clear loop stop on all the voices with one PCI write, then re-arm the timer, and set the PCM running; we now have 16 voices in perfect sync. Subsequent timer interrupts just call snd_pcm_period_elapsed.

If timer must be re-armed in the interrupt handler, then you have a problem - time shifting when the timer ack interrupt is delayed. So you must do a time correction.

I was planning to use the emu10k1's wallclock timer for this.

Quoted 8 lines
Quoted 5 lines

The above scheme could also work with an extra voice for timing but would be uglier. Since the multichannel device does not have to support multiple open, and only 48KHZ playback, the timer seems to be a much cleaner solution. Regular PCM playback will continue to use the extra voice.

The only one drawback is the possible delay at stream start (up to one period).

Should not be a problem as this device is intended for use by JACK.

I did notice that alsa-lib/test/timer.c looks like it misses the first tick about half the time:

rlrevell@mindpipe:~/cvs$ ~/cvs/alsa-T3/alsa-lib/test/timer class 2, sclass 0, card 0, device 0, subdevice 0
Using timer class 2, slave class 0, card 0, device 0, subdevice 0
Timer info:
  slave = no
  card = 0
  id = 'EMU10K1'
  name = 'EMU10K1 timer'
  average resolution = 20833
Using 960 tick(s)
STATUS:
  resolution = 20833
  lost = 0
  overrun = 0
  queue = 0
TIMER: resolution = 20833ns, ticks = 1920 <--
TIMER: resolution = 20833ns, ticks = 960
TIMER: resolution = 20833ns, ticks = 960

...

Using 960 tick(s)
STATUS:
resolution = 20833
lost = 0
overrun = 0
queue = 0
TIMER: resolution = 20833ns, ticks = 960 <--
TIMER: resolution = 20833ns, ticks = 960
TIMER: resolution = 20833ns, ticks = 960

The header file mentions that when the emu10k1's timer rate is changed you must allow 1024 sample periods before the new rate is accurate. It looks like SNDRV_TIMER_HW_FIRST is the answer, but this did not have any effect.

Signature · 9 lines
Lee Revell <[email protected]>



-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE
LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click