[alsa-devel] mapping externally allocated Scatter Gather DMA buffers
Manu Abraham
abraham.manu at gmail.com
Wed Nov 10 07:29:09 CET 2010
On Tue, Nov 9, 2010 at 8:04 PM, Jaroslav Kysela <perex at perex.cz> wrote:
> On Tue, 9 Nov 2010, Manu Abraham wrote:
>
>> On Tue, Nov 9, 2010 at 6:21 PM, Jaroslav Kysela <perex at perex.cz> wrote:
>>>
>>> On Tue, 9 Nov 2010, Manu Abraham wrote:
>>>
>>>> On Tue, Nov 9, 2010 at 5:31 PM, Jaroslav Kysela <perex at perex.cz> wrote:
>>>>>
>>>>> On Tue, 9 Nov 2010, Manu Abraham wrote:
>>>>>
>>>>>> testbox ~ # arecord -Dhw:2,0
>>>>>> Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
>>>>>
>>>>>> Any idea, why saa7231_hw_params is not getting invoked ?
>>>>>
>>>>> Your hw probably does not support directly 8-bit sample at 8000Hz, one
>>>>> channel. Use 'plughw:2,0' device instead 'hw:2,0' to let alsa-lib do
>>>>> all
>>>>> stream format conversions.
>>>>
>>>> That didn't make any difference at all.
>>>
>>> Check your code. You probably created wrong hw_ops, looking to your code:
>>>
>>> .buffer_bytes_max = 512 * 4096,
>>> .period_bytes_min = 8192,
>>> .period_bytes_max = 8192,
>>> .periods_min = 8192,
>>> .periods_max = 8192,
>>>
>>> It's definitely an empty configuration space.
>>>
>>> You have buffer_bytes_max 2097152, but restricted number of periods to
>>> 8192
>>> and period_bytes to 8192.
>>>
>>> 8192 * 8192 = 67108864 which is not less than 2097152 (and I'm not
>>> counting
>>> the bytes for channels and formats). Bingo, the ALSA PCM code does not
>>> know
>>> what to configure.
>>>
>>> Decrease periods_min and probably also periods_max.
>>>
>>
>> oh ! The error message was really a weird one. I can say that the
>> hardware can do 192 audio frames in an interrupt, whatever the frame
>> size is. So, what periods and period_bytes should I describe in the
>> configuration ?
>
> You cannot describe this using hw_ops. Leave period bytes in good range (192
> - 1536?), periods (2-1024?) and add something like this to the open
> callback:
>
> err = snd_pcm_hw_constraint_minmax(runtime,
> SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
> 192, 192);
>
> Note the difference between SNDRV_PCM_HW_PARAM_PERIOD_SIZE and
> SNDRV_PCM_HW_PARAM_PERIOD_BYTES.
>
Ok, thanks.
I modified it to look thus ...
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 = 2,
.channels_max = 2,
.buffer_bytes_max = 512 * 4096,
.period_bytes_min = 192,
.period_bytes_max = 1536,
.periods_min = 2,
.periods_max = 1024,
};
static int saa7231_capture_open(struct snd_pcm_substream *pcm)
{
struct saa7231_audio *audio = snd_pcm_substream_chip(pcm);
struct snd_pcm_runtime *rt = pcm->runtime;
struct saa7231_dev *saa7231 = audio->saa7231;
int err;
dprintk(SAA7231_DEBUG, 1, "()");
rt->hw = saa7231_capture_info;
snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
&hw_constraint_rates);
err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
if (err < 0) {
dprintk(SAA7231_ERROR, 1, "snd_pcm_hw_constraint_integer() failed.
ret=%d", err);
return err;
}
err = snd_pcm_hw_constraint_minmax(rt,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 192, 192);
if (err < 0) {
dprintk(SAA7231_ERROR, 1, "snd_pcm_hw_constraint_minmax() failed.
ret=%d", err);
return err;
}
return 0;
}
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 saa7231_dmabuf *buffer;
struct saa7231_stream *stream;
struct saa7231_dmabuf *dmabuf;
struct page **ptable;
void *vma;
void *dma_area;
int i, j, pages, bytes, periods, bufsiz;
dprintk(SAA7231_DEBUG, 1, "DEBUG: ()");
periods = params_periods(params);
bytes = params_period_bytes(params);
bufsiz = periods * bytes;
dprintk(SAA7231_DEBUG, 1, "bufsiz=%d periods=%d bytes=%d",
bufsiz,
periods,
bytes);
pages = bufsiz / PAGE_SIZE;
/* enable stream */
stream = saa7231_stream_init(saa7231, AUDIO_CAPTURE, ADAPTER_INT, 0, 512);
if (!stream) {
dprintk(SAA7231_ERROR, 1, "ERROR: Registering stream");
return -ENOMEM;
}
audio->stream = stream;
buffer = stream->dmabuf;
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);
return 0;
}
testbox ~ # arecord -Dplughw:2,0
Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
ALSA lib pcm_mmap.c:369:(snd_pcm_mmap) mmap failed: Invalid argument
arecord: set_params:1041: Unable to install hw params:
ACCESS: RW_INTERLEAVED
FORMAT: U8
SUBFORMAT: STD
SAMPLE_BITS: 8
FRAME_BITS: 8
CHANNELS: 1
RATE: 8000
PERIOD_TIME: 6000
PERIOD_SIZE: 48
PERIOD_BYTES: 48
PERIODS: 83
BUFFER_TIME: 498000
BUFFER_SIZE: 3984
BUFFER_BYTES: 3984
TICK_TIME: 0
[ 819.928438] saa7231_capture_open (0): ()
[ 819.945466] saa7231_hw_params (0): DEBUG: ()
[ 819.945470] saa7231_hw_params (0): bufsiz=31872 periods=83 bytes=384
[ 819.945472] saa7231_stream_init (0): DEBUG: Initializing Stream
with MODE=0x01
[ 819.945475] saa7231_xs2dtl_init (0): XS2DTL engine Initializing .....
[ 819.945477] saa7231_xs2dtl_init (0): Allocated 8 XS2DTL Buffer @0xf47b6000
[ 819.945479] saa7231_xs2dtl_init (0): Allocating DMA Buffers ...
[ 819.945481] saa7231_xs2dtl_init (0): Allocating DMA buffer:0 @0xf47b6000..
[ 819.945492] saa7231_allocate_ptable (0): Virtual 0xf3bb7000 to Phys
0x33bb7000 mapped page
[ 819.945598] saa7231_dmabuf_sgalloc (0): Virtual contiguous 2097152
byte region with 512 4k pages
...
...
bufsiz=31872 periods=83 bytes=384
Now, I wonder what a period really is. I guess I lack the basics here
.. A basic explanation to the context,
would be quite helpful.
Best Regards,
Manu
More information about the Alsa-devel
mailing list