All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Eliot Blennerhassett <bigblen@icqmail.com>
Cc: alsa-devel@lists.sourceforge.net, eliot@blennerhassett.gen.nz
Subject: Re: Help needed. (long)
Date: Mon, 19 May 2003 18:34:42 +0200	[thread overview]
Message-ID: <s5hvfw6dhel.wl@alsa2.suse.de> (raw)
In-Reply-To: <20030519024010.3367.h002.c012.wm@mail.icqmail.com.criticalpath.net>

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

  parent reply	other threads:[~2003-05-19 16:34 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Takashi Iwai [this message]
2003-05-20  8:56   ` Help needed. (long) Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5hvfw6dhel.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=bigblen@icqmail.com \
    --cc=eliot@blennerhassett.gen.nz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.