All of lore.kernel.org
 help / color / mirror / Atom feed
* pointer callback in pcm
@ 2006-03-09 22:21 Adrian McMenamin
  2006-03-10  0:53 ` Lee Revell
  0 siblings, 1 reply; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-09 22:21 UTC (permalink / raw)
  To: alsa-devel

The documentation states:

"This callback is called when the PCM middle layer inquires the current
hardware position on the buffer."


Does that mean the position the hardware is at (in its ring buffer in my
case) or does it mean the position we are at in the dma buffer.

ie I have a 128k DMA buffer which transfers samples into the 32k
hardware memory buffer. Which position am I meant to be reporting?



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-09 22:21 pointer callback in pcm Adrian McMenamin
@ 2006-03-10  0:53 ` Lee Revell
  2006-03-10 19:51   ` Adrian McMenamin
  0 siblings, 1 reply; 19+ messages in thread
From: Lee Revell @ 2006-03-10  0:53 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: alsa-devel

On Thu, 2006-03-09 at 22:21 +0000, Adrian McMenamin wrote:
> The documentation states:
> 
> "This callback is called when the PCM middle layer inquires the current
> hardware position on the buffer."
> 
> 
> Does that mean the position the hardware is at (in its ring buffer in my
> case) or does it mean the position we are at in the dma buffer.
> 
> ie I have a 128k DMA buffer which transfers samples into the 32k
> hardware memory buffer. Which position am I meant to be reporting?
> 

The DMA buffer should be the same size as the hardware buffer, so the
positions should be the same.

The pointer callback should return the position of sample that the
hardware is currently playing.

Lee



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-10  0:53 ` Lee Revell
@ 2006-03-10 19:51   ` Adrian McMenamin
  2006-03-10 20:16     ` Takashi Iwai
  2006-03-11 11:16     ` James Courtier-Dutton
  0 siblings, 2 replies; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-10 19:51 UTC (permalink / raw)
  To: Lee Revell; +Cc: alsa-devel

On Thu, 2006-03-09 at 19:53 -0500, Lee Revell wrote:
> On Thu, 2006-03-09 at 22:21 +0000, Adrian McMenamin wrote:
> > The documentation states:
> > 
> > "This callback is called when the PCM middle layer inquires the current
> > hardware position on the buffer."
> > 
> > 
> > Does that mean the position the hardware is at (in its ring buffer in my
> > case) or does it mean the position we are at in the dma buffer.
> > 
> > ie I have a 128k DMA buffer which transfers samples into the 32k
> > hardware memory buffer. Which position am I meant to be reporting?
> > 
> 
> The DMA buffer should be the same size as the hardware buffer, so the
> positions should be the same.
> 
> The pointer callback should return the position of sample that the
> hardware is currently playing.
> 
Thanks. I am sure I am driving you round the twist now, but that (both
buffers being the same size) was a key piece of information I was
unaware of. There are several pints in it if you are ever around in
North London :)

But my basic problem remains - my buffer is 8 periods long and I get to
hear them over and over again :( - nothing new is ever fed into the DMA
buffer and so nothing new therefore ever gets fed into the hardware
buffer.

I start the process by transferring a whole eight periods worth into the
hardware buffer is that a mistake? Should I always be feeding in one
period at a time only?



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-10 19:51   ` Adrian McMenamin
@ 2006-03-10 20:16     ` Takashi Iwai
  2006-03-10 20:21       ` Adrian McMenamin
  2006-03-10 20:23       ` Lee Revell
  2006-03-11 11:16     ` James Courtier-Dutton
  1 sibling, 2 replies; 19+ messages in thread
From: Takashi Iwai @ 2006-03-10 20:16 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: Lee Revell, alsa-devel

At Fri, 10 Mar 2006 19:51:01 +0000,
Adrian McMenamin wrote:
> 
> On Thu, 2006-03-09 at 19:53 -0500, Lee Revell wrote:
> > On Thu, 2006-03-09 at 22:21 +0000, Adrian McMenamin wrote:
> > > The documentation states:
> > > 
> > > "This callback is called when the PCM middle layer inquires the current
> > > hardware position on the buffer."
> > > 
> > > 
> > > Does that mean the position the hardware is at (in its ring buffer in my
> > > case) or does it mean the position we are at in the dma buffer.
> > > 
> > > ie I have a 128k DMA buffer which transfers samples into the 32k
> > > hardware memory buffer. Which position am I meant to be reporting?
> > > 
> > 
> > The DMA buffer should be the same size as the hardware buffer, so the
> > positions should be the same.
> > 
> > The pointer callback should return the position of sample that the
> > hardware is currently playing.
> > 
> Thanks. I am sure I am driving you round the twist now, but that (both
> buffers being the same size) was a key piece of information I was
> unaware of. There are several pints in it if you are ever around in
> North London :)
> 
> But my basic problem remains - my buffer is 8 periods long and I get to
> hear them over and over again :( - nothing new is ever fed into the DMA
> buffer and so nothing new therefore ever gets fed into the hardware
> buffer.
> 
> I start the process by transferring a whole eight periods worth into the
> hardware buffer is that a mistake? Should I always be feeding in one
> period at a time only?

Hm, I've not checked your code and thread due to lack of my free time
for ALSA recently, but the symptom above sounds like you implemented
copy callback but still using mmap.

The copy callback is designed basically only for read/write transfer.
In the mmap mode, of course, such read/write transfer is eliminated,
and no copy action occurs.

Thus, first try not to set MMAP flag and let alsa-lib use the
traditional read/write method.

Some hardwares have actually separate h/w buffer and the memory
buffer (s/w buffer).  Even with such hardwares, mmap can be
implemented.  Instead of DMA transfer by hardware, the driver copies
data between h/w and s/w buffers on demand, namely, before starting
the stream (in trigger callback) and when each period is consumed (via
ack callback).

There are userful functions for such a case, found in pcm-indirect.h.
They are used emu10k1 FX mode and cs46xx.


HTH,

Takashi


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-10 20:16     ` Takashi Iwai
@ 2006-03-10 20:21       ` Adrian McMenamin
  2006-03-10 20:23       ` Lee Revell
  1 sibling, 0 replies; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-10 20:21 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Lee Revell, alsa-devel

On Fri, 2006-03-10 at 21:16 +0100, Takashi Iwai wrote:

> 
> Hm, I've not checked your code and thread due to lack of my free time
> for ALSA recently, but the symptom above sounds like you implemented
> copy callback but still using mmap.
> 

No, I'm not using copy or mmap (the code is at
http://newgolddream.dyndns.info/cgi-bin/cvsweb these days)


> The copy callback is designed basically only for read/write transfer.
> In the mmap mode, of course, such read/write transfer is eliminated,
> and no copy action occurs.
> 
> Thus, first try not to set MMAP flag and let alsa-lib use the
> traditional read/write method.
> 
> Some hardwares have actually separate h/w buffer and the memory
> buffer (s/w buffer).  Even with such hardwares, mmap can be
> implemented.  Instead of DMA transfer by hardware, the driver copies
> data between h/w and s/w buffers on demand, namely, before starting
> the stream (in trigger callback) and when each period is consumed (via
> ack callback).


This is quite like my device - but I know nothing about the ack device


> 
> There are userful functions for such a case, found in pcm-indirect.h.
> They are used emu10k1 FX mode and cs46xx.
> 

I'll look

> 
> HTH,
> 
> Takashi



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-10 20:16     ` Takashi Iwai
  2006-03-10 20:21       ` Adrian McMenamin
@ 2006-03-10 20:23       ` Lee Revell
  1 sibling, 0 replies; 19+ messages in thread
From: Lee Revell @ 2006-03-10 20:23 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Adrian McMenamin, alsa-devel

On Fri, 2006-03-10 at 21:16 +0100, Takashi Iwai wrote:
> Some hardwares have actually separate h/w buffer and the memory
> buffer (s/w buffer).  Even with such hardwares, mmap can be
> implemented.  Instead of DMA transfer by hardware, the driver copies
> data between h/w and s/w buffers on demand, namely, before starting
> the stream (in trigger callback) and when each period is consumed (via
> ack callback).
> 
> There are userful functions for such a case, found in pcm-indirect.h.
> They are used emu10k1 FX mode and cs46xx.
> 

Adrian has a weird case - his hardware *does* have DMA but it must be
reprogrammed every period.  So no copying is required in the driver.

The driver guide assumes that once the DMA is started, it will
repeatedly fill the buffer until we tell it to stop.

So, I thought that the DMA could be programmed in the copy callback each
period.  But maybe this should go in the ack callback.

Lee



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-10 19:51   ` Adrian McMenamin
  2006-03-10 20:16     ` Takashi Iwai
@ 2006-03-11 11:16     ` James Courtier-Dutton
  2006-03-11 11:27       ` Adrian McMenamin
  1 sibling, 1 reply; 19+ messages in thread
From: James Courtier-Dutton @ 2006-03-11 11:16 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: Lee Revell, alsa-devel

Adrian,

Here is a quick summary of what I think you have been saying.
1) Your hardware has min and max periods set to 8.
2) Your hardware can do DMA, but not periodic DMA.   <- This is really 
the crux of the problem.
3) You wish to use DMA.
4) Unknown:  What triggers the audio interrupt? It should be triggered 
once each period is completed.

Now, here is what the ALSA model assumes:
1) hardware period sizes are exactly the same size as the memory mapped 
DMA pages.
2) snd_period_ellapsed() is called at periodic intervals dependent on 
where the ADC is playing samples.
3) If the copy callback is NULL, ALSA assumes the DMA has already completed.
4) If the copy callback is not NULL, ALSA calls it, but when the copy 
callback returns, the copy has been completed.
5) The pointer callback is then called that should return the position 
of the ADC in frames (not bytes) within the audio buffer.

So, if you wish to use DMA, you should be calling snd_period_ellapsed() 
only after the DMA has completed, alternatively, the copy() callback 
should only return after the DMA transaction has completed, but I don't 
know if delaying the copy() return is allowed.
Can you get it to interrupt on each DMA completion?

I would recommend you trying to do the following:
1) Discover when the ADC has played the entire period.
2) start the DMA transfer.
3) At the DMA transfer complete interrrupt, call period_ellapsed().

So, the problem might be how to discover that the ADC has played the 
entire period.
You might have to use some sort of timer based polling to discover this.

James


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 11:16     ` James Courtier-Dutton
@ 2006-03-11 11:27       ` Adrian McMenamin
  2006-03-11 15:42         ` James Courtier-Dutton
  0 siblings, 1 reply; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-11 11:27 UTC (permalink / raw)
  To: James Courtier-Dutton, Lee Revell, Alsa-devel

On Sat, 2006-03-11 at 11:16 +0000, James Courtier-Dutton wrote:
> Adrian,
> 
> Here is a quick summary of what I think you have been saying.
> 1) Your hardware has min and max periods set to 8.
> 2) Your hardware can do DMA, but not periodic DMA.   <- This is really 
> the crux of the problem.
> 3) You wish to use DMA.

I really need to because transfers between the sound memory and the main
memory are very slow otherwise. When I wrote the OSS driver for this a
few years ago I simply copied stuff over, but it would effectively lock
the machine up at high sample rates.

> 4) Unknown:  What triggers the audio interrupt? It should be triggered 
> once each period is completed.


This is done by the ARM7 spu that controls the sound output. I write the
"firmware" for that so I have written some code that puts an IRQ on the
SH4 (main CPU) bus every time a period has been played out.

> 
> Now, here is what the ALSA model assumes:
> 1) hardware period sizes are exactly the same size as the memory mapped 
> DMA pages.

I wasn't aware of that but I think I've done that anyway (4k period
size)

> 2) snd_period_ellapsed() is called at periodic intervals dependent on 
> where the ADC is playing samples.
> 3) If the copy callback is NULL, ALSA assumes the DMA has already completed.
> 4) If the copy callback is not NULL, ALSA calls it, but when the copy 
> callback returns, the copy has been completed.

I haven't got a copy callback - should I write one?


> 5) The pointer callback is then called that should return the position 
> of the ADC in frames (not bytes) within the audio buffer.
> 
> So, if you wish to use DMA, you should be calling snd_period_ellapsed() 
> only after the DMA has completed, alternatively, the copy() callback 
> should only return after the DMA transaction has completed, but I don't 
> know if delaying the copy() return is allowed.
> Can you get it to interrupt on each DMA completion?
> 

In theory yes, but nobody seems have managed to reverse that bit of the
spu function effectively yet, so I'd have to use polling on the progress
of the transfer.


> I would recommend you trying to do the following:
> 1) Discover when the ADC has played the entire period.
> 2) start the DMA transfer.
> 3) At the DMA transfer complete interrrupt, call period_ellapsed().
> 
> So, the problem might be how to discover that the ADC has played the 
> entire period.

I've got that covered (see above).

How do I start? I am copying over 8 periods via DMA on the trigger, is
that ok? (These are all I ever hear getting played). What about the ack
callback that was recommended to me yesterday?

> You might have to use some sort of timer based polling to discover this.
> 
> James



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 11:27       ` Adrian McMenamin
@ 2006-03-11 15:42         ` James Courtier-Dutton
  2006-03-11 15:53           ` Adrian McMenamin
  2006-03-11 17:30           ` Adrian McMenamin
  0 siblings, 2 replies; 19+ messages in thread
From: James Courtier-Dutton @ 2006-03-11 15:42 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: Lee Revell, Alsa-devel

Adrian McMenamin wrote:
> On Sat, 2006-03-11 at 11:16 +0000, James Courtier-Dutton wrote:
>   
>> Adrian,
>>
>> Here is a quick summary of what I think you have been saying.
>> 1) Your hardware has min and max periods set to 8.
>> 2) Your hardware can do DMA, but not periodic DMA.   <- This is really 
>> the crux of the problem.
>> 3) You wish to use DMA.
>>     
>
> I really need to because transfers between the sound memory and the main
> memory are very slow otherwise. When I wrote the OSS driver for this a
> few years ago I simply copied stuff over, but it would effectively lock
> the machine up at high sample rates.
>   
The "problem" is that the DMA is not periodic, DMA itself is not the 
problem.
>   
>> 4) Unknown:  What triggers the audio interrupt? It should be triggered 
>> once each period is completed.
>>     
>
>
> This is done by the ARM7 spu that controls the sound output. I write the
> "firmware" for that so I have written some code that puts an IRQ on the
> SH4 (main CPU) bus every time a period has been played out.
>   
Can you get the "firmware" to initiate the DMA transfer, and then only 
IRQ the SH4 when the DMA completes?
>   
>> Now, here is what the ALSA model assumes:
>> 1) hardware period sizes are exactly the same size as the memory mapped 
>> DMA pages.
>>     
>
> I wasn't aware of that but I think I've done that anyway (4k period
> size)
>
>   
>> 2) snd_period_ellapsed() is called at periodic intervals dependent on 
>> where the ADC is playing samples.
>> 3) If the copy callback is NULL, ALSA assumes the DMA has already completed.
>> 4) If the copy callback is not NULL, ALSA calls it, but when the copy 
>> callback returns, the copy has been completed.
>>     
>
> I haven't got a copy callback - should I write one?
>   
You have to write one, but the ack() callback is probably more suitable 
in your case, if the period_ellapsed is called without the audio samples 
already being in main memory. (i.e. after the DMA is complete)
>   
>> 5) The pointer callback is then called that should return the position 
>> of the ADC in frames (not bytes) within the audio buffer.
>>
>> So, if you wish to use DMA, you should be calling snd_period_ellapsed() 
>> only after the DMA has completed, alternatively, the copy() callback 
>> should only return after the DMA transaction has completed, but I don't 
>> know if delaying the copy() return is allowed.
>> Can you get it to interrupt on each DMA completion?
>>
>>     
>
> In theory yes, but nobody seems have managed to reverse that bit of the
> spu function effectively yet, so I'd have to use polling on the progress
> of the transfer.
>   
>
>   
>> I would recommend you trying to do the following:
>> 1) Discover when the ADC has played the entire period.
>> 2) start the DMA transfer.
>> 3) At the DMA transfer complete interrrupt, call period_ellapsed().
>>
>> So, the problem might be how to discover that the ADC has played the 
>> entire period.
>>     
>
> I've got that covered (see above).
>
> How do I start? I am copying over 8 periods via DMA on the trigger, is
> that ok? (These are all I ever hear getting played). What about the ack
> callback that was recommended to me yesterday?
>
>   
>> You might have to use some sort of timer based polling to discover this.
>>
>> James
>>     

Some questions:
1) How does the main CPU discover the hardware pointer of the current 
ADC position? Needed for the pointer() callback.
2) Can you start and stop the samples being played?

Initialisation:
1) Wait for the application to fill 8 periods.  (you can simulate other 
periods models later if you wish. e.g You could simulate 2 periods to 
the application, even though you have 8 in hardware.)
2) The application will then call trigger to start playing the samples 
in the buffer.

I would recommend you try the following in the audio interrupt:
1) receive audio interrupt
2) start DMA transfer of one period.
    Which period you copy is the important bit here. At this point the 
hardware will have played 1 period, so you replace the period that has 
just played, not the period that is about to be played.
3) call snd_period_elapsed()
4) poll for DMA complete in the ack() callback.
5) period_elapsed will in turn call the pointer() callback.

James




-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 15:42         ` James Courtier-Dutton
@ 2006-03-11 15:53           ` Adrian McMenamin
  2006-03-11 17:30           ` Adrian McMenamin
  1 sibling, 0 replies; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-11 15:53 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: Lee Revell, Alsa-devel

On Sat, 2006-03-11 at 15:42 +0000, James Courtier-Dutton wrote:

> >>     
> 
> Some questions:
> 1) How does the main CPU discover the hardware pointer of the current 
> ADC position? Needed for the pointer() callback.

Reads a value in a register in the ARM7/SPU memory - simple proceedure


> 2) Can you start and stop the samples being played?
> 

Yes - by poking a value into a different register

> Initialisation:
> 1) Wait for the application to fill 8 periods.  (you can simulate other 
> periods models later if you wish. e.g You could simulate 2 periods to 
> the application, even though you have 8 in hardware.)
> 2) The application will then call trigger to start playing the samples 
> in the buffer.
> 

Not sure I understand this! How can my kernel code know what the
application has done?


> I would recommend you try the following in the audio interrupt:
> 1) receive audio interrupt
> 2) start DMA transfer of one period.
>     Which period you copy is the important bit here. At this point the 
> hardware will have played 1 period, so you replace the period that has 
> just played, not the period that is about to be played.


I do this already. the problem is that the buffer contents never change
- ie when I replay period 0 after it has played I am just replacing it
with exactly the same sample as was there in the first place - nothing
new gets sucked in from userspace

> 3) call snd_period_elapsed()
> 4) poll for DMA complete in the ack() callback.

This is something I am not doing now but it's easy to do if somewhat
processor intensive. Can the ack callback sleep?

> 5) period_elapsed will in turn call the pointer() callback.
> 
> James
> 



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 15:42         ` James Courtier-Dutton
  2006-03-11 15:53           ` Adrian McMenamin
@ 2006-03-11 17:30           ` Adrian McMenamin
  2006-03-11 18:47             ` James Courtier-Dutton
  1 sibling, 1 reply; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-11 17:30 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: Lee Revell, Alsa-devel

On Sat, 2006-03-11 at 15:42 +0000, James Courtier-Dutton wrote:


> 2) start DMA transfer of one period.
>     Which period you copy is the important bit here. At this point the 
> hardware will have played 1 period, so you replace the period that has 
> just played, not the period that is about to be played.

I am just sitting down to write this code now, but where in the dma
buffer should I look for this period. The relevant code at the moment
looks like this:

dma_xfer(0, runtime->dma_area + (0x1000 * dreamcastcard->clicks),
0x11000 + (0x1000 * dreamcastcard->clicks), 0x1000, 5);


(clicks is always equal to the period that has just played out ie the
code does this

Get interrupt
Reset interrupt flag on ARM7 side
dma transfer
clicks++
if (clicks == 8) clicks = 0
call pcm_elapsed
return with acknowledge interrupt


The hardware buffer begins at 0x11000 in the ARM7 space and each period
is 0x1000 in size - but I am rather assuming you can rely on the DMA
buffer (8 periods long) being filled up at 8 period intervals -is that
right?



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 17:30           ` Adrian McMenamin
@ 2006-03-11 18:47             ` James Courtier-Dutton
  2006-03-11 19:08               ` Adrian McMenamin
  2006-03-11 19:26               ` Adrian McMenamin
  0 siblings, 2 replies; 19+ messages in thread
From: James Courtier-Dutton @ 2006-03-11 18:47 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: Lee Revell, Alsa-devel

Adrian McMenamin wrote:
> On Sat, 2006-03-11 at 15:42 +0000, James Courtier-Dutton wrote:
>
>
>   
>> 2) start DMA transfer of one period.
>>     Which period you copy is the important bit here. At this point the 
>> hardware will have played 1 period, so you replace the period that has 
>> just played, not the period that is about to be played.
>>     
>
> I am just sitting down to write this code now, but where in the dma
> buffer should I look for this period. The relevant code at the moment
> looks like this:
>
> dma_xfer(0, runtime->dma_area + (0x1000 * dreamcastcard->clicks),
> 0x11000 + (0x1000 * dreamcastcard->clicks), 0x1000, 5);
>
>
> (clicks is always equal to the period that has just played out ie the
> code does this
>
> Get interrupt
> Reset interrupt flag on ARM7 side
> dma transfer
> clicks++
> if (clicks == 8) clicks = 0
> call pcm_elapsed
> return with acknowledge interrupt
>
>
> The hardware buffer begins at 0x11000 in the ARM7 space and each period
> is 0x1000 in size - but I am rather assuming you can rely on the DMA
> buffer (8 periods long) being filled up at 8 period intervals -is that
> right?
>
>
>   
Ok, I looked at the code now, and there are a few things that need fixing.
1)

static snd_pcm_hardware_t snd_pcm_aica_playback_hw = {

	.info = 		(SNDRV_PCM_INFO_NONINTERLEAVED),
	.formats = 		(SNDRV_PCM_FMTBIT_S8|SNDRV_PCM_FMTBIT_U8|SNDRV_PCM_FMTBIT_S16_LE|SNDRV_PCM_FMTBIT_IMA_ADPCM),
	.rates =		SNDRV_PCM_RATE_8000_48000,
        .rate_min =         	8000,
        .rate_max =         	48000,
        .channels_min =     	1,
        .channels_max =     	1,
        .buffer_bytes_max = 	32768,
        .period_bytes_min = 	4096,
        .period_bytes_max = 	4096,
        .periods_min =      	1,
        .periods_max =      	8,
};

If the card can only do 8 periods, make .periods_min = 8,
Can the card handle all these formats and rates in hardware.
Is it really only a mono sound channel?
You will need to set the .buffer_bytes_min as well.


2)
static snd_pcm_uframes_t snd_aicapcm_pcm_pointer(snd_pcm_substream_t 
*substream)

{
	return readl(0xa0810004 + 4);
}

What sort of values should this return during playback?
Add a printk to log some of them.
The value should be in "frames" and not "bytes"
Use the ALSA function bytes_to_frames(runtime, value) to automatically 
do the adjustments from bytes to frames.
If the returned value is just period number, then you will have to 
multiply it up to the "frames" scale.
In case you missed it in the docs. "Frames" are units of samples 
equivalent to all the bytes needed to play one PCM sample in all channels.
E.g. 16 bit Stereo sound takes 4 bytes per sample for all channels. This 
equals 1 frame.
16 bit mono takes 2 bytes per sample for all channels. This equals 1 frame.


James



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 18:47             ` James Courtier-Dutton
@ 2006-03-11 19:08               ` Adrian McMenamin
  2006-03-11 19:15                 ` James Courtier-Dutton
  2006-03-11 19:26               ` Adrian McMenamin
  1 sibling, 1 reply; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-11 19:08 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: Lee Revell, Alsa-devel

On Sat, 2006-03-11 at 18:47 +0000, James Courtier-Dutton wrote:
> Adrian McMenamin wrote:
> > On Sat, 2006-03-11 at 15:42 +0000, James Courtier-Dutton wrote:
> >
> >
> >   
> >> 2) start DMA transfer of one period.
> >>     Which period you copy is the important bit here. At this point the 
> >> hardware will have played 1 period, so you replace the period that has 
> >> just played, not the period that is about to be played.
> >>     
> >
> > I am just sitting down to write this code now, but where in the dma
> > buffer should I look for this period. The relevant code at the moment
> > looks like this:
> >
> > dma_xfer(0, runtime->dma_area + (0x1000 * dreamcastcard->clicks),
> > 0x11000 + (0x1000 * dreamcastcard->clicks), 0x1000, 5);
> >
> >
> > (clicks is always equal to the period that has just played out ie the
> > code does this
> >
> > Get interrupt
> > Reset interrupt flag on ARM7 side
> > dma transfer
> > clicks++
> > if (clicks == 8) clicks = 0
> > call pcm_elapsed
> > return with acknowledge interrupt
> >
> >
> > The hardware buffer begins at 0x11000 in the ARM7 space and each period
> > is 0x1000 in size - but I am rather assuming you can rely on the DMA
> > buffer (8 periods long) being filled up at 8 period intervals -is that
> > right?
> >
> >
> >   
> Ok, I looked at the code now, and there are a few things that need fixing.
> 1)
> 
> static snd_pcm_hardware_t snd_pcm_aica_playback_hw = {
> 
> 	.info = 		(SNDRV_PCM_INFO_NONINTERLEAVED),
> 	.formats = 		(SNDRV_PCM_FMTBIT_S8|SNDRV_PCM_FMTBIT_U8|SNDRV_PCM_FMTBIT_S16_LE|SNDRV_PCM_FMTBIT_IMA_ADPCM),
> 	.rates =		SNDRV_PCM_RATE_8000_48000,
>         .rate_min =         	8000,
>         .rate_max =         	48000,
>         .channels_min =     	1,
>         .channels_max =     	1,
>         .buffer_bytes_max = 	32768,
>         .period_bytes_min = 	4096,
>         .period_bytes_max = 	4096,
>         .periods_min =      	1,
>         .periods_max =      	8,
> };
> 
> If the card can only do 8 periods, make .periods_min = 8,

OK, will do


> Can the card handle all these formats and rates in hardware.

yes

> Is it really only a mono sound channel?

no, but the stereo separation stuff is a second order task - getting it
to play mono is a necessary first step :) To play stereo I need two
channels with one panned to the left and the other to the right (I can
set that up in the "firmware") and that means writing sep code in SH4
and two dma transfers

> You will need to set the .buffer_bytes_min as well.
> 

To what value? 1 or 32768?

> 
> 2)
> static snd_pcm_uframes_t snd_aicapcm_pcm_pointer(snd_pcm_substream_t 
> *substream)
> 
> {
> 	return readl(0xa0810004 + 4);
> }
> 
> What sort of values should this return during playback?
> Add a printk to log some of them.
> The value should be in "frames" and not "bytes"

It should be doing all that anyway - it returns the numbers of samples
(ie frames) played in the chosen (in ARM7 code) channel - and as all
this is mono that ought to work unchanged for now, but I will check it
as you suggest.

> Use the ALSA function bytes_to_frames(runtime, value) to automatically 
> do the adjustments from bytes to frames.
> If the returned value is just period number, then you will have to 
> multiply it up to the "frames" scale.
> In case you missed it in the docs. "Frames" are units of samples 
> equivalent to all the bytes needed to play one PCM sample in all channels.
> E.g. 16 bit Stereo sound takes 4 bytes per sample for all channels. This 
> equals 1 frame.
> 16 bit mono takes 2 bytes per sample for all channels. This equals 1 frame.
> 
> 
> James
> 
> 
> 
> -------------------------------------------------------
> This SF.Net email is sponsored by xPML, a groundbreaking scripting language
> that extends applications into web and mobile media. Attend the live webcast
> and join the prime developer group breaking into this new coding territory!
> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/alsa-devel



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 19:08               ` Adrian McMenamin
@ 2006-03-11 19:15                 ` James Courtier-Dutton
  2006-03-11 19:18                   ` Adrian McMenamin
  0 siblings, 1 reply; 19+ messages in thread
From: James Courtier-Dutton @ 2006-03-11 19:15 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: Lee Revell, Alsa-devel

Adrian McMenamin wrote:
>> You will need to set the .buffer_bytes_min as well.
>>
>>     
>
> To what value? 1 or 32768?
>
>   
32768
>> 2)
>> static snd_pcm_uframes_t snd_aicapcm_pcm_pointer(snd_pcm_substream_t 
>> *substream)
>>
>> {
>> 	return readl(0xa0810004 + 4);
>> }
>>
>> What sort of values should this return during playback?
>> Add a printk to log some of them.
>> The value should be in "frames" and not "bytes"
>>     
>
> It should be doing all that anyway - it returns the numbers of samples
> (ie frames) played in the chosen (in ARM7 code) channel - and as all
> this is mono that ought to work unchanged for now, but I will check it
> as you suggest.
>   
Ok, that is not what is needed.
The value returned should be the position of the ADC in the hardware's 
ring buffer in units of frames.
Not the cumulative number of samples played.
E.g. If the buffer is 32768 frames long, the returned value should only 
have a value from 0 to 32767
Once it gets to 32767, it should then role over to 0 again.

James



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 19:15                 ` James Courtier-Dutton
@ 2006-03-11 19:18                   ` Adrian McMenamin
  2006-03-11 19:37                     ` James Courtier-Dutton
  0 siblings, 1 reply; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-11 19:18 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: Lee Revell, Alsa-devel

On Sat, 2006-03-11 at 19:15 +0000, James Courtier-Dutton wrote:

> >   
> Ok, that is not what is needed.
> The value returned should be the position of the ADC in the hardware's 
> ring buffer in units of frames.
> Not the cumulative number of samples played.
> E.g. If the buffer is 32768 frames long, the returned value should only 
> have a value from 0 to 32767
> Once it gets to 32767, it should then role over to 0 again.
> 
Yes, that's what I meant :) Sorry if I wasn't clear enough.



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 18:47             ` James Courtier-Dutton
  2006-03-11 19:08               ` Adrian McMenamin
@ 2006-03-11 19:26               ` Adrian McMenamin
  2006-03-11 19:35                 ` James Courtier-Dutton
  1 sibling, 1 reply; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-11 19:26 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: Lee Revell, Alsa-devel

On Sat, 2006-03-11 at 18:47 +0000, James Courtier-Dutton wrote:

> 

> You will need to set the .buffer_bytes_min as well.

Are you sure this exists? I get a compiler error



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 19:26               ` Adrian McMenamin
@ 2006-03-11 19:35                 ` James Courtier-Dutton
  0 siblings, 0 replies; 19+ messages in thread
From: James Courtier-Dutton @ 2006-03-11 19:35 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: Lee Revell, Alsa-devel

Adrian McMenamin wrote:
> On Sat, 2006-03-11 at 18:47 +0000, James Courtier-Dutton wrote:
>
>   
>
>   
>> You will need to set the .buffer_bytes_min as well.
>>     
>
> Are you sure this exists? I get a compiler error
>
>
>   
Sorry, my mistake.



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 19:18                   ` Adrian McMenamin
@ 2006-03-11 19:37                     ` James Courtier-Dutton
  2006-03-11 19:55                       ` Adrian McMenamin
  0 siblings, 1 reply; 19+ messages in thread
From: James Courtier-Dutton @ 2006-03-11 19:37 UTC (permalink / raw)
  To: Adrian McMenamin; +Cc: Lee Revell, Alsa-devel

Adrian McMenamin wrote:
> On Sat, 2006-03-11 at 19:15 +0000, James Courtier-Dutton wrote:
>
>   
>>>   
>>>       
>> Ok, that is not what is needed.
>> The value returned should be the position of the ADC in the hardware's 
>> ring buffer in units of frames.
>> Not the cumulative number of samples played.
>> E.g. If the buffer is 32768 frames long, the returned value should only 
>> have a value from 0 to 32767
>> Once it gets to 32767, it should then role over to 0 again.
>>
>>     
> Yes, that's what I meant :) Sorry if I wasn't clear enough.
>   
Which application are you using to test.
Have you tried "speaker-test"

James



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: pointer callback in pcm
  2006-03-11 19:37                     ` James Courtier-Dutton
@ 2006-03-11 19:55                       ` Adrian McMenamin
  0 siblings, 0 replies; 19+ messages in thread
From: Adrian McMenamin @ 2006-03-11 19:55 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: Lee Revell, Alsa-devel

On Sat, 2006-03-11 at 19:37 +0000, James Courtier-Dutton wrote:
> Adrian McMenamin wrote:
> > On Sat, 2006-03-11 at 19:15 +0000, James Courtier-Dutton wrote:
> >
> >   
> >>>   
> >>>       
> >> Ok, that is not what is needed.
> >> The value returned should be the position of the ADC in the hardware's 
> >> ring buffer in units of frames.
> >> Not the cumulative number of samples played.
> >> E.g. If the buffer is 32768 frames long, the returned value should only 
> >> have a value from 0 to 32767
> >> Once it gets to 32767, it should then role over to 0 again.
> >>
> >>     
> > Yes, that's what I meant :) Sorry if I wasn't clear enough.
> >   
> Which application are you using to test.
> Have you tried "speaker-test"

I cannot get aplay to work so I am just do cat somefile.wav > /dev/dsp

As I couldn't get the ack callback to work I have just rewritten the
interrupt handler as below:

static irqreturn_t aica_period_elapsed(int irq, void *dev_id, struct
pt_regs *regs)
{
	int transferred;
	snd_pcm_runtime_t *runtime;
	if (dev_id != dreamcastcard) return IRQ_NONE;
	/* clear the interrupt on the ARM side */
	spu_memset(0x28BC, 0x20, 4);
	runtime = (((snd_card_aica_t *)dev_id)->substream)->runtime;
	dma_xfer(0, runtime->dma_area + (0x1000 * dreamcastcard->clicks),
0x11000 + (0x1000 * dreamcastcard->clicks), 0x1000, 5);
	do {
		mdelay(1);
		transferred = get_dma_residue(0);
		snd_printk("Transfer reports 0x%X\n", transferred);
	}
	while (transferred < 0x1000);

	snd_pcm_period_elapsed(((snd_card_aica_t *)dev_id)->substream);
	dreamcastcard->clicks++;
	if (dreamcastcard->clicks == 8) dreamcastcard->clicks = 0;
	snd_printk("Clicks is %d\n", dreamcastcard->clicks);	
	return IRQ_HANDLED;
}


which shows the transfers work (the rate is about 12 Mb/s so it's fast)
but still just plays the same stuff over and over in an endless loop :(



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2006-03-11 19:55 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-09 22:21 pointer callback in pcm Adrian McMenamin
2006-03-10  0:53 ` Lee Revell
2006-03-10 19:51   ` Adrian McMenamin
2006-03-10 20:16     ` Takashi Iwai
2006-03-10 20:21       ` Adrian McMenamin
2006-03-10 20:23       ` Lee Revell
2006-03-11 11:16     ` James Courtier-Dutton
2006-03-11 11:27       ` Adrian McMenamin
2006-03-11 15:42         ` James Courtier-Dutton
2006-03-11 15:53           ` Adrian McMenamin
2006-03-11 17:30           ` Adrian McMenamin
2006-03-11 18:47             ` James Courtier-Dutton
2006-03-11 19:08               ` Adrian McMenamin
2006-03-11 19:15                 ` James Courtier-Dutton
2006-03-11 19:18                   ` Adrian McMenamin
2006-03-11 19:37                     ` James Courtier-Dutton
2006-03-11 19:55                       ` Adrian McMenamin
2006-03-11 19:26               ` Adrian McMenamin
2006-03-11 19:35                 ` James Courtier-Dutton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.