All of lore.kernel.org
 help / color / mirror / Atom feed
* Help needed. (long)
@ 2003-05-19  9:40 Eliot Blennerhassett
  2003-05-19 16:10 ` PCI problem Giuliano Pochini
  2003-05-19 16:34 ` Help needed. (long) Takashi Iwai
  0 siblings, 2 replies; 5+ messages in thread
From: Eliot Blennerhassett @ 2003-05-19  9:40 UTC (permalink / raw)
  To: alsa-devel; +Cc: eliot

Greetings,

(Aside: I still can only post to this list via a web mailer, so apologies if the
formatting is messed up. Still looking for a way to find out what is wrong with
my POP mailer.
Also I'd like to attach a file, but I cant...)

Whereas I have pressed the reset button for the Nth time,
Whereas I have little experience in driver writing,
Whereas I am going around in circles,

Therefore, I have resolved to swallow my pride and subject my code to the
scrutiny of my superiors (in terms of ALSA driver knowledge at least...)

If there is someone out there who can answer the following questions, and is
also interested and able in developing the driver further in exchange for an
AudioScience card (6114, 6122, or 5111)please let me know.

1) Am I understanding this correctly?
I see this kind of sequence:
prepare
copy
copy
copy
trigger(start)

(driver calls period_elapsed)
pointer
copy
pointer
pointer
copy
pointer
pointer
pointer
trigger(stop)


The middle-layer expects that the pointer will be increasing (modulo the buffer
size).
It expects that it should have increased by (at least) the period every time
snd_pcm_period_elapsed is called.

When the middle-layer enters the draining state, the copy callback isn't called
any more.
What is supposed to happen to the pointer now, and how many more times is
period_elapsed expected to be called?

I ask because on our cards when data runs out, the 'pointer' stops moving.
When this happens, and I don't call period_elapsed, then aplay hangs for a while
before erroring out - "failed to exit drained state"

==========================

What I am basically trying to do is translate the following into the PCM
playback part of an ALSA driver.

<code>
wHE = HPI_OutStreamGetInfoEx( phSubSys, pOS->hOutStream,
                               &wState, &dwBufferSize,
                              &dwBytesToPlay, &dwSamplesPlayed, NULL);

Data.dwpbData = (HW32)&dataBuffer;

while((dwBytesToPlay<(dwBufferSize-BLOCK_SIZE)))
{
   dwBytesRead=read_some_data(&dataBuffer);
   Data.dwDataSize = dwBytesRead;
   wHE = HPI_OutStreamWrite( phSubSys, pOS->hOutStream, &Data);
   wHE = HPI_OutStreamGetInfo( phSubSys, pOS->hOutStream,
                                &wState, &dwBufferSize, &dwBytesToPlay);

}
</code>

Notes:
wXxxx is 16 bit data, dwXxxx is 32 bit.

wState: STOPPED, PLAYING, DRAINED=ran out of data.
dwBufferSize typically 500K to 1Mbyte
Data is a struct that contains a pointer to data buffer, size of data, and
format info.

Our cards have no interrupts, and no DMA (...yet. The next one probably will) so
they must be polled.

Based on the dummy driver, I am using a timer to do the polling.
So far, it does play audio, but often crashes or locks the machine solid with a
kernel panic.
I need help with the subtleties, and any tips on how to debug this kind of
problem ;-)

 static void snd_card_asihpi_pcm_timer_function(unsigned long data)
 {
 	snd_card_asihpi_pcm_t *dpcm = snd_magic_cast(snd_card_asihpi_pcm_t, (void
*)data, return);
 	snd_pcm_runtime_t *runtime = dpcm->substream->runtime;

 	unsigned int pos;
 	int delta;
 	HW16            wState,err;
 	HW32            dwBufferSize;
 	HW32            dwDataToPlay;
 	HW32            dwSamplesPlayed;

 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
 	spin_lock_irq(&dpcm->lock);

 	err= HPI_OutStreamGetInfoEx(phSubSys,dpcm->hStream,
 				    &wState,
 				    &dwBufferSize,
 				    &dwDataToPlay,
 				    &dwSamplesPlayed,
 				    NULL);
 	HPI_HandleError( err );
 	//	if ((wState== HPI_STATE_DRAINED))
 	//    snd_pcm_stop(dpcm->substream, SNDRV_PCM_STATE_SETUP);

 	pos  =  frames_to_bytes(runtime, dwSamplesPlayed);
 	pos %= dpcm->pcm_size;
 	delta = pos - dpcm->pcm_buf_pos;
 	dpcm->pcm_buf_pos = pos;
  	if (delta < 0) delta +=  dpcm->pcm_size;

  	dpcm->pcm_irq_pos += delta;

 	if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
 		dpcm->pcm_irq_pos %= dpcm->pcm_count;
 		snd_pcm_period_elapsed(dpcm->substream);
 	}

 	spin_unlock_irq(&dpcm->lock);
 }

static snd_pcm_uframes_t snd_card_asihpi_playback_pointer(snd_pcm_substream_t *
substream)
{
	snd_pcm_runtime_t *runtime = substream->runtime;
	snd_card_asihpi_pcm_t *dpcm = snd_magic_cast(snd_card_asihpi_pcm_t,
runtime->private_data, return -ENXIO);

    snd_printd(KERN_INFO "playback pointer\n");

	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
}


static int snd_card_asihpi_playback_copy(
					 snd_pcm_substream_t *substream, int channel,
					 snd_pcm_uframes_t pos,
					 void *src,
					 snd_pcm_uframes_t count)
{
    snd_pcm_runtime_t *runtime = substream->runtime;
    snd_card_asihpi_pcm_t *dpcm = snd_magic_cast(snd_card_asihpi_pcm_t,
runtime->private_data, return -ENXIO);
    HW16 err;
    unsigned int len;

    len = frames_to_bytes(runtime, count);

    if (copy_from_user(runtime->dma_area, src, len))
		return -EFAULT;

    dpcm->Data.dwDataSize = len;
    dpcm->Data.dwpbData = (HW32)runtime->dma_area;

    err = HPI_OutStreamWrite(phSubSys,dpcm->hStream,&dpcm->Data);
    return 0;
}


Is this an appropriate way to structure the driver?
If not, then how?

Thanks for wading through...

Eliot Blennerhassett
www.audioscience.com

Eliot Blennerhassett
AudioScience Inc.
--
Junk footer beyond this point. Read at your own risk.


-------------------------------------------------------------
Sign up for ICQmail at http://www.icq.com/icqmail/signup.html


-------------------------------------------------------
This SF.net email is sponsored by: If flattening out C++ or Java
code to make your application fit in a relational database is painful, 
don't do it! Check out ObjectStore. Now part of Progress Software.
http://www.objectstore.net/sourceforge

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

* PCI problem
  2003-05-19  9:40 Help needed. (long) Eliot Blennerhassett
@ 2003-05-19 16:10 ` Giuliano Pochini
  2003-05-20  9:01   ` Takashi Iwai
  2003-05-19 16:34 ` Help needed. (long) Takashi Iwai
  1 sibling, 1 reply; 5+ messages in thread
From: Giuliano Pochini @ 2003-05-19 16:10 UTC (permalink / raw)
  To: alsa-devel


I would like some hints on this problem. When I load the module
the machine hangs solid or it works fine depending on which
PCI bus slot the card is. Initializations completes if the card
is in a slot that shares IRQ with something (ethernet IIRC). The
card doesn't send IRQs during init.
When I try to play something the box crashed badly:

>Start Transport
>uhci ac00 host system error, PCI problem?
>uhci ac00 host controller process error, something bad happened.
>uhci ac00 host controller halted. Very bad.

:( Any ideas ?

I don't own that card, I just reported what a betatester told
me. The card works fine under windos. Another person has the
same card and no problems.


Bye.



-------------------------------------------------------
This SF.net email is sponsored by: If flattening out C++ or Java
code to make your application fit in a relational database is painful, 
don't do it! Check out ObjectStore. Now part of Progress Software.
http://www.objectstore.net/sourceforge

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

* Re: Help needed. (long)
  2003-05-19  9:40 Help needed. (long) Eliot Blennerhassett
  2003-05-19 16:10 ` PCI problem Giuliano Pochini
@ 2003-05-19 16:34 ` Takashi Iwai
  2003-05-20  8:56   ` Takashi Iwai
  1 sibling, 1 reply; 5+ messages in thread
From: Takashi Iwai @ 2003-05-19 16:34 UTC (permalink / raw)
  To: Eliot Blennerhassett; +Cc: alsa-devel, eliot

At Mon, 19 May 2003 02:40:08 -0700 (PDT),
Eliot Blennerhassett wrote:
> 
> Greetings,
> 
> (Aside: I still can only post to this list via a web mailer, so apologies if the
> formatting is messed up. Still looking for a way to find out what is wrong with
> my POP mailer.
> Also I'd like to attach a file, but I cant...)
> 
> Whereas I have pressed the reset button for the Nth time,
> Whereas I have little experience in driver writing,
> Whereas I am going around in circles,
> 
> Therefore, I have resolved to swallow my pride and subject my code to the
> scrutiny of my superiors (in terms of ALSA driver knowledge at least...)
> 
> If there is someone out there who can answer the following questions, and is
> also interested and able in developing the driver further in exchange for an
> AudioScience card (6114, 6122, or 5111)please let me know.
> 
> 1) Am I understanding this correctly?
> I see this kind of sequence:
> prepare
> copy
> copy
> copy
> trigger(start)
> 
> (driver calls period_elapsed)
> pointer
> copy
> pointer
> pointer
> copy
> pointer
> pointer
> pointer
> trigger(stop)
> 
> 
> The middle-layer expects that the pointer will be increasing (modulo the buffer
> size).
> It expects that it should have increased by (at least) the period every time
> snd_pcm_period_elapsed is called.

yes.  in other words, snd_pcm_period_elapsed() is called after the
period size or more size is consumed since the last call of
snd_pcm_period_elapsed().

> When the middle-layer enters the draining state, the copy callback isn't called
> any more.
> What is supposed to happen to the pointer now, and how many more times is
> period_elapsed expected to be called?
 
the pointer should return the currently played buffer-position.
(or, at least, the lastly-processed period-position if no accurate
 positioing is supported by the hardware.)

copy callback is an alternative to copy_from/to_user().  thus, copy
callback is independent on the state of DAC/ADC.

the drain function waits for all pending periods on the buffer are
processed.  that is, you have to call period_elapsed() at most
[pending buffer size / period size] times.

> I ask because on our cards when data runs out, the 'pointer' stops moving.
> When this happens, and I don't call period_elapsed, then aplay hangs for a while
> before erroring out - "failed to exit drained state"

it might depend on the implementation of pointer callback...
let us see...

> ==========================
> 
> What I am basically trying to do is translate the following into the PCM
> playback part of an ALSA driver.
> 
> <code>
> wHE = HPI_OutStreamGetInfoEx( phSubSys, pOS->hOutStream,
>                                &wState, &dwBufferSize,
>                               &dwBytesToPlay, &dwSamplesPlayed, NULL);
> 
> Data.dwpbData = (HW32)&dataBuffer;
> 
> while((dwBytesToPlay<(dwBufferSize-BLOCK_SIZE)))
> {
>    dwBytesRead=read_some_data(&dataBuffer);
>    Data.dwDataSize = dwBytesRead;
>    wHE = HPI_OutStreamWrite( phSubSys, pOS->hOutStream, &Data);
>    wHE = HPI_OutStreamGetInfo( phSubSys, pOS->hOutStream,
>                                 &wState, &dwBufferSize, &dwBytesToPlay);
> 
> }
> </code>
> 
> Notes:
> wXxxx is 16 bit data, dwXxxx is 32 bit.
> 
> wState: STOPPED, PLAYING, DRAINED=ran out of data.
> dwBufferSize typically 500K to 1Mbyte
> Data is a struct that contains a pointer to data buffer, size of data, and
> format info.
> 
> Our cards have no interrupts, and no DMA (...yet. The next one probably will) so
> they must be polled.

hmm, no interrupts at all?

> Based on the dummy driver, I am using a timer to do the polling.
> So far, it does play audio, but often crashes or locks the machine solid with a
> kernel panic.

perhaps the interrupt takes too long time?
for a pseudo-DMA transfer, tasklet may be a better choice.

> I need help with the subtleties, and any tips on how to debug this kind of
> problem ;-)
> 
>  static void snd_card_asihpi_pcm_timer_function(unsigned long data)
>  {
>  	snd_card_asihpi_pcm_t *dpcm = snd_magic_cast(snd_card_asihpi_pcm_t, (void
> *)data, return);
>  	snd_pcm_runtime_t *runtime = dpcm->substream->runtime;
> 
>  	unsigned int pos;
>  	int delta;
>  	HW16            wState,err;
>  	HW32            dwBufferSize;
>  	HW32            dwDataToPlay;
>  	HW32            dwSamplesPlayed;
> 
>  	dpcm->timer.expires = 1 + jiffies;
>  	add_timer(&dpcm->timer);
>  	spin_lock_irq(&dpcm->lock);
> 
>  	err= HPI_OutStreamGetInfoEx(phSubSys,dpcm->hStream,
>  				    &wState,
>  				    &dwBufferSize,
>  				    &dwDataToPlay,
>  				    &dwSamplesPlayed,
>  				    NULL);
>  	HPI_HandleError( err );
>  	//	if ((wState== HPI_STATE_DRAINED))
>  	//    snd_pcm_stop(dpcm->substream, SNDRV_PCM_STATE_SETUP);
> 
>  	pos  =  frames_to_bytes(runtime, dwSamplesPlayed);
>  	pos %= dpcm->pcm_size;
>  	delta = pos - dpcm->pcm_buf_pos;
>  	dpcm->pcm_buf_pos = pos;
>   	if (delta < 0) delta +=  dpcm->pcm_size;
> 
>   	dpcm->pcm_irq_pos += delta;
> 
>  	if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
>  		dpcm->pcm_irq_pos %= dpcm->pcm_count;
>  		snd_pcm_period_elapsed(dpcm->substream);
>  	}
> 
>  	spin_unlock_irq(&dpcm->lock);
>  }
> 
> static snd_pcm_uframes_t snd_card_asihpi_playback_pointer(snd_pcm_substream_t *
> substream)
> {
> 	snd_pcm_runtime_t *runtime = substream->runtime;
> 	snd_card_asihpi_pcm_t *dpcm = snd_magic_cast(snd_card_asihpi_pcm_t,
> runtime->private_data, return -ENXIO);
> 
>     snd_printd(KERN_INFO "playback pointer\n");
> 
> 	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
> }
> 
> 
> static int snd_card_asihpi_playback_copy(
> 					 snd_pcm_substream_t *substream, int channel,
> 					 snd_pcm_uframes_t pos,
> 					 void *src,
> 					 snd_pcm_uframes_t count)
> {
>     snd_pcm_runtime_t *runtime = substream->runtime;
>     snd_card_asihpi_pcm_t *dpcm = snd_magic_cast(snd_card_asihpi_pcm_t,
> runtime->private_data, return -ENXIO);
>     HW16 err;
>     unsigned int len;
> 
>     len = frames_to_bytes(runtime, count);
> 
>     if (copy_from_user(runtime->dma_area, src, len))
> 		return -EFAULT;
> 
>     dpcm->Data.dwDataSize = len;
>     dpcm->Data.dwpbData = (HW32)runtime->dma_area;
> 
>     err = HPI_OutStreamWrite(phSubSys,dpcm->hStream,&dpcm->Data);
>     return 0;
> }
> 
> 
> Is this an appropriate way to structure the driver?

the code avoe looks ok for me.

is the timer callback called after trigger(stop) is called, too?
if it's called, the pointer callback must increase (as long as
dwSamplesPlayed increases)...



Takashi


-------------------------------------------------------
This SF.net email is sponsored by: If flattening out C++ or Java
code to make your application fit in a relational database is painful, 
don't do it! Check out ObjectStore. Now part of Progress Software.
http://www.objectstore.net/sourceforge

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

* Re: Help needed. (long)
  2003-05-19 16:34 ` Help needed. (long) Takashi Iwai
@ 2003-05-20  8:56   ` Takashi Iwai
  0 siblings, 0 replies; 5+ messages in thread
From: Takashi Iwai @ 2003-05-20  8:56 UTC (permalink / raw)
  To: Eliot Blennerhassett; +Cc: alsa-devel, eliot

Hi,

just checking the mail again, and i have a question now...

At Mon, 19 May 2003 18:34:42 +0200,
I wrote:
> 
> > static int snd_card_asihpi_playback_copy(
> > 					 snd_pcm_substream_t *substream, int channel,
> > 					 snd_pcm_uframes_t pos,
> > 					 void *src,
> > 					 snd_pcm_uframes_t count)
> > {
> >     snd_pcm_runtime_t *runtime = substream->runtime;
> >     snd_card_asihpi_pcm_t *dpcm = snd_magic_cast(snd_card_asihpi_pcm_t,
> > runtime->private_data, return -ENXIO);
> >     HW16 err;
> >     unsigned int len;
> > 
> >     len = frames_to_bytes(runtime, count);
> > 
> >     if (copy_from_user(runtime->dma_area, src, len))
> > 		return -EFAULT;
> > 
> >     dpcm->Data.dwDataSize = len;
> >     dpcm->Data.dwpbData = (HW32)runtime->dma_area;
> > 
> >     err = HPI_OutStreamWrite(phSubSys,dpcm->hStream,&dpcm->Data);
> >     return 0;
> > }

what does HPI_OutStreamWrite() do?
does it copy the data onto the hardware buffer only?

if this function itself plays the role of sample playback (aka DMA),
the function should be called not in the copy callback but in the
other code path.

as mentioned in my last mail, copy callback is provided as an
alternative to copy_from_user().  it's supposed to do a job only as a
transfer method between the user-space and the hardware device.
that means, the samples must be audible after the trigger callback is
called.


Takashi


-------------------------------------------------------
This SF.net email is sponsored by: ObjectStore.
If flattening out C++ or Java code to make your application fit in a
relational database is painful, don't do it! Check out ObjectStore.
Now part of Progress Software. http://www.objectstore.net/sourceforge

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

* Re: PCI problem
  2003-05-19 16:10 ` PCI problem Giuliano Pochini
@ 2003-05-20  9:01   ` Takashi Iwai
  0 siblings, 0 replies; 5+ messages in thread
From: Takashi Iwai @ 2003-05-20  9:01 UTC (permalink / raw)
  To: Giuliano Pochini; +Cc: alsa-devel

At Mon, 19 May 2003 18:10:29 +0200 (CEST),
Giuliano Pochini wrote:
> 
> 
> I would like some hints on this problem. When I load the module
> the machine hangs solid or it works fine depending on which
> PCI bus slot the card is. Initializations completes if the card
> is in a slot that shares IRQ with something (ethernet IIRC). The
> card doesn't send IRQs during init.

the irq handler of your driver receives too many unknown interrupts
from other devices constantly?
this might be the reason of hang up, too.


Takashi


-------------------------------------------------------
This SF.net email is sponsored by: ObjectStore.
If flattening out C++ or Java code to make your application fit in a
relational database is painful, don't do it! Check out ObjectStore.
Now part of Progress Software. http://www.objectstore.net/sourceforge

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

end of thread, other threads:[~2003-05-20  9:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-05-19  9:40 Help needed. (long) Eliot Blennerhassett
2003-05-19 16:10 ` PCI problem Giuliano Pochini
2003-05-20  9:01   ` Takashi Iwai
2003-05-19 16:34 ` Help needed. (long) Takashi Iwai
2003-05-20  8:56   ` Takashi Iwai

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.