Hi,
Had some amount of success, but not completely functional yet.
at the moment, I do get a overrun (at least that's what arecord claims). In fact after opening due to audio capture I do get the first interrupt, but before the next interrupt arrives, arecord closes the device and reopens the device (from the logs, I do see that the device is being continuously opened and closed for each of those mentioned overruns ?).
Eventually the device always ends up with an interrupt showing data with the first 4 pages.
Any idea, why arecord keeps opening and closing for each overrun ?
Thanks, Manu
testbox v4l # arecord -D plughw:2,0 --format S16_LE --rate=32000 -c 2
/tmp/test.wav
Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 32000 Hz, Stereo overrun!!! (at least 0.005 ms long) overrun!!! (at least 0.002 ms long) overrun!!! (at least 0.002 ms long) overrun!!! (at least 0.003 ms long) overrun!!! (at least 0.003 ms long) overrun!!! (at least 0.001 ms long) overrun!!! (at least 0.002 ms long) overrun!!! (at least 0.001 ms long) overrun!!! (at least 0.001 ms long) overrun!!! (at least 0.001 ms long) overrun!!! (at least 0.001 ms long) overrun!!! (at least 0.001 ms long)
testbox v4l # cat /var/log/messages |grep evhandler Dec 15 23:33:26 testbox kernel: [22380.791159] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.807889] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.824799] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.840634] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.856821] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.872661] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.888827] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.904667] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 Dec 15 23:33:26 testbox kernel: [22380.920849] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6
[22395.146703] saa7231_irq_handler (0): status=0x800 vector=43 event=43 handler:f83d63a6 [22395.146716] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 [22395.146734] saa7231_capture_pointer (0): DEBUG:() [22395.146737] saa7231_capture_trigger (0): Trying to STOP stream, cmd=0
[22395.146780] saa7231_capture_prepare (0): () [22395.146783] saa7231_capture_prepare (0): Trying to Acquire stream with 4096 lines per stream buffer [22395.146786] saa7231_xs2dtl_acquire (0): Activating clock .. mode=0x01, port_id=0x06 [22395.146788] saa7231_activate_clocks (0): DEBUG: Activating Clock for Mode=0x01, port=0x06 [22395.146793] saa7231_activate_clocks (0): INFO: tmIActivateSystemUseCase noticed active use case! [22395.146806] saa7231_init_ptables (0): DEBUG: Initializing PORT:6 DMA_CH:7 with 8 Buffers [22395.157028] saa7231_capture_trigger (0): Trying to START stream, cmd=1 [22395.157031] saa7231_xs2dtl_run (0): module=0x124000 Run [22395.162525] saa7231_irq_handler (0): status=0x800 vector=43 event=43 handler:f83d63a6 [22395.162537] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 [22395.162551] saa7231_capture_pointer (0): DEBUG:() [22395.162553] saa7231_capture_trigger (0): Trying to STOP stream, cmd=0
[22395.162586] saa7231_capture_prepare (0): () [22395.162588] saa7231_capture_prepare (0): Trying to Acquire stream with 4096 lines per stream buffer [22395.162591] saa7231_xs2dtl_acquire (0): Activating clock .. mode=0x01, port_id=0x06 [22395.162593] saa7231_activate_clocks (0): DEBUG: Activating Clock for Mode=0x01, port=0x06 [22395.162598] saa7231_activate_clocks (0): INFO: tmIActivateSystemUseCase noticed active use case! [22395.162611] saa7231_init_ptables (0): DEBUG: Initializing PORT:6 DMA_CH:7 with 8 Buffers [22395.173028] saa7231_capture_trigger (0): Trying to START stream, cmd=1 [22395.173032] saa7231_xs2dtl_run (0): module=0x124000 Run [22395.178682] saa7231_irq_handler (0): status=0x800 vector=43 event=43 handler:f83d63a6 [22395.178695] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 [22395.178714] saa7231_capture_pointer (0): DEBUG:() [22395.178716] saa7231_capture_trigger (0): Trying to STOP stream, cmd=0
[22395.178759] saa7231_capture_prepare (0): () [22395.178762] saa7231_capture_prepare (0): Trying to Acquire stream with 4096 lines per stream buffer [22395.178765] saa7231_xs2dtl_acquire (0): Activating clock .. mode=0x01, port_id=0x06 [22395.178767] saa7231_activate_clocks (0): DEBUG: Activating Clock for Mode=0x01, port=0x06 [22395.178772] saa7231_activate_clocks (0): INFO: tmIActivateSystemUseCase noticed active use case! [22395.178785] saa7231_init_ptables (0): DEBUG: Initializing PORT:6 DMA_CH:7 with 8 Buffers [22395.189028] saa7231_capture_trigger (0): Trying to START stream, cmd=1 [22395.189030] saa7231_xs2dtl_run (0): module=0x124000 Run [22395.194864] saa7231_irq_handler (0): status=0x800 vector=43 event=43 handler:f83d63a6 [22395.194877] saa7231_audio_evhandler (0): DEBUG: got buffer with index:1 port:6 [22395.194893] saa7231_capture_pointer (0): DEBUG:() [22395.194896] saa7231_capture_trigger (0): Trying to STOP stream, cmd=0
[22395.194932] saa7231_capture_prepare (0): () [22395.194934] saa7231_capture_prepare (0): Trying to Acquire stream with 4096 lines per stream buffer [22395.194937] saa7231_xs2dtl_acquire (0): Activating clock .. mode=0x01, port_id=0x06 [22395.194939] saa7231_activate_clocks (0): DEBUG: Activating Clock for Mode=0x01, port=0x06 [22395.194944] saa7231_activate_clocks (0): INFO: tmIActivateSystemUseCase noticed active use case! [22395.194957] saa7231_init_ptables (0): DEBUG: Initializing PORT:6 DMA_CH:7 with 8 Buffers [22395.206170] saa7231_hw_free (0): DEBUG: Removing IRQ event .. [22395.206174] saa7231_remove_irqevent (0): Removing IRQ Event:43 ...... [22395.206176] saa7231_remove_irqevent (0): IRQ Event 43 <AS2D_AVIS> removed [22395.206202] saa7231_hw_free (0): DEBUG: Removing IRQ event .. [22395.206242] saa7231_remove_irqevent (0): Removing IRQ Event:43 ...... [22395.206244] saa7231_capture_close (0): DEBUG: Closing stream
static struct snd_pcm_hardware saa7231_capture_info = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
.formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),
.rates = SNDRV_PCM_RATE_32000,
.rate_min = 32000, .rate_max = 48000,
.channels_min = 1, .channels_max = 2,
.buffer_bytes_max = XS2D_BUFFERS * PAGE_SIZE * 512,
.period_bytes_min = 4096, .period_bytes_max = 2097152,
.periods_min = 8, .periods_max = 4096, };
static int saa7231_audio_evhandler(struct saa7231_dev *saa7231, int vector) { struct saa7231_audio *audio = saa7231->audio; struct saa7231_stream *stream = audio->stream;
int index = 0, err = 0;
if (stream->ops.get_buffer) { err = stream->ops.get_buffer(stream, &index); if (err) dprintk(SAA7231_ERROR, 1, "ERROR: get_buffer failed, err=%d", err);
dprintk(SAA7231_DEBUG, 1, "DEBUG: got buffer with index:%d port:%d", index, stream->port_id); } audio->index = index; queue_work(saa7231->wq, &audio->irq_pending_work); return 0; }
static void saa7231_audio_irq_work(struct work_struct *work) { struct saa7231_audio *audio = container_of(work, struct saa7231_audio, irq_pending_work);
snd_pcm_period_elapsed(audio->pcm); }
static snd_pcm_uframes_t saa7231_capture_pointer(struct snd_pcm_substream *pcm) { struct saa7231_audio *audio = snd_pcm_substream_chip(pcm); struct saa7231_dev *saa7231 = audio->saa7231; struct snd_pcm_runtime *rt = pcm->runtime;
dprintk(SAA7231_DEBUG, 1, "DEBUG:()"); return bytes_to_frames(rt, audio->index * audio->pages * PAGE_SIZE); }
static int saa7231_hw_params(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params) { struct saa7231_audio *audio = snd_pcm_substream_chip(pcm); struct saa7231_dev *saa7231 = audio->saa7231; struct snd_pcm_runtime *rt = pcm->runtime;
struct saa7231_dmabuf *buffer; struct saa7231_stream *stream; struct avis_audio *decoder; struct avis_audio_ops *ops; struct audio_config config;
struct saa7231_dmabuf *dmabuf; struct page **ptable;
void *mem; void *dma_area;
int ret, i, j, pages, bytes, periods, bufsiz, idx;
#define MAX_ENTRIES_PER_PAGE (PAGE_SIZE / 8) #define PAGES_PER_XS2D(__pages) (__pages / XS2D_BUFFERS) #define BUFSIZE_PER_XS2D(__size) (__size / XS2D_BUFFERS)
dprintk(SAA7231_DEBUG, 1, "DEBUG: ()");
periods = params_periods(params); bytes = params_period_bytes(params); bufsiz = params_buffer_bytes(params); pages = snd_sgbuf_aligned_pages(bufsiz);
audio->bufsize = bufsiz; audio->periods = periods; audio->bytes = bytes; audio->pages = pages;
dprintk(SAA7231_DEBUG, 1, "bufsiz=%d periods=%d bytes=%d pages=%d", bufsiz, periods, bytes, pages);
/* enable stream */ /* initializing 8 buffer with "pages" pages each .. */ stream = saa7231_stream_init(saa7231, AUDIO_CAPTURE, ADAPTER_INT, 0, (pages / XS2D_BUFFERS)); if (!stream) { dprintk(SAA7231_ERROR, 1, "ERROR: Registering stream"); ret = -ENOMEM; goto err; } audio->stream = stream; buffer = stream->dmabuf; mutex_lock(&saa7231->dev_lock);
saa7231_add_irqevent(saa7231, 43, SAA7231_EDGE_RISING, saa7231_audio_evhandler, "AS2D_AVIS"); dprintk(SAA7231_DEBUG, 1, "Mapping %d buffers with %d pages each", XS2D_BUFFERS, PAGES_PER_XS2D(pages));
dprintk(SAA7231_DEBUG, 1, "Page Table array size=%d", pages); ptable = kzalloc((sizeof (struct page) * pages), GFP_KERNEL); if (!ptable) { dprintk(SAA7231_ERROR, 1, "ERROR: No memory to allocate virtual map"); ret = -ENOMEM; goto err; } audio->ptable = ptable; idx = 0;
for (i = 0; i < XS2D_BUFFERS; i ++) { dmabuf = &buffer[i]; mem = dmabuf->vmalloc; for (j = 0; j < PAGES_PER_XS2D(pages); j++) { BUG_ON(idx > pages); dprintk(SAA7231_DEBUG, 1, "Mapping Page:%d from XS2D_BUFFER:%d to PTA Offset:%d", j, i, idx); ptable[idx] = virt_to_page(mem); mem += PAGE_SIZE; idx += 1; } }
dma_area = vmap(ptable, pages, VM_MAP, PAGE_KERNEL); rt->dma_area = dma_area; rt->dma_bytes = pages * PAGE_SIZE; rt->dma_addr = 0;
config.srate = SRATE_32k; /* default sample rate */ config.source = AUDIOSRC_CVBS1; /* default source */ config.l_volume = VOL_MAX; config.r_volume = VOL_MAX;
ret = saa7231_audio_attach(stream, &config); if (ret) { dprintk(SAA7231_ERROR, 1, "Audio decoder attach failed, err=%d", ret); goto err; }
decoder = stream->adec; ops = &decoder->ops;
decoder->port = AUDIOPORT_DAC1;
if (ops->powerup) { ret = ops->powerup(stream); if (ret) { dprintk(SAA7231_ERROR, 1, "Failed to power up, err=%d", ret); ret = -EIO; goto err; } }
if (ops->open) { ret = ops->open(stream); if (ret) { dprintk(SAA7231_ERROR, 1, "Failed to open stream, err=%d", ret); return -EIO; } }
if (ops->ena_port) { ret = ops->ena_port(stream, AUDIOPORT_SPDIF, 1); if (ret) { dprintk(SAA7231_ERROR, 1, "Failed to enable port, err=%d", ret); return -EIO; } }
if (ops->set_src) { ret = ops->set_src(stream, AUDIOSRC_CVBS1); if (ret) { dprintk(SAA7231_ERROR, 1, "Failed to enable source, err=%d", ret); return -EIO; } }
err: mutex_unlock(&saa7231->dev_lock); return ret; }
On Fri, Nov 12, 2010 at 1:35 PM, Jaroslav Kysela perex@perex.cz wrote:
On Fri, 12 Nov 2010, Manu Abraham wrote:
On Thu, Nov 11, 2010 at 6:04 PM, Manu Abraham abraham.manu@gmail.com wrote:
On Thu, Nov 11, 2010 at 4:00 PM, Jaroslav Kysela perex@perex.cz wrote:
On Thu, 11 Nov 2010, Manu Abraham wrote:
On Wed, Nov 10, 2010 at 11:35 PM, Jaroslav Kysela perex@perex.cz wrote:
I adapted the whole thing to make the buffersize divided amongst the XS2D_BUFFERS (8):
Probably yes.
I hope the mapping of the buffers is okay ? It looks thus, now ..
From information you sent me about hw privately, I think that the period_bytes must be 4096 or multiple of this value with minumum count of periods 8 (or multiple of 8). Otherwise you get a non-continuous memory area (the hw uses only portion of system memory page, thus there'll be gaps). The problem is that we have MMAP_COMPLEX mode, but no application can handle (does not implement) this mmap mode and I'm not sure, if we can even describe the DMA buffer size layout for this case for your specific hw.
I would use:
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4096);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS, 8);
And define periods_min = 8 (max to multiple 8 - choose your max limit) and period_bytes_min to 4096 (max to multiple 4096 - choose your max limit).
Note that -EIO means that your driver does not called snd_pcm_period_elapsed() and/or the pointer callback returns wrong position to the audio ring buffer.
Ok, modified it, also added in code to acquire the stream, It's a bit more complete now. The crazy part that I do see now, is that I see an inconsistent lock state with the hda_intel driver which is the soundcard on my system. But I don't understand why the locking on it has to become inconsistent on loading this driver.
Ok, I found the reason: I was passing a single page for the page_table, which I guess corrupted the whole stack !!
Eventually, I fixed the same. but ran into another issue ? Should trigger not sleep or something that way ? Currently, I see the issue as follows in the log, but if the ops->run() callback is commented out I don't get that weird message/error about lock states.
Now, ops->run(), ie xs2dtl_run() is called with other other streams, such as an MPEG stream, where it doesn't show any issues.
Any idea, why uncommenting ops->run() produces that message ? Should trigger not sleep ? Confused ...
Trigger must be fast without any sleeping. Only fast spinlocks are allowed. If you need sleep, just activate a tasklet and do the start job in the tasklet or a thread.
Jaroslav
Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.