[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