[alsa-devel] Difference between substream->dma_buffer and substream->runtime->dma_buffer_p?
The snd_pcm_substream structure has a snd_dma_buffer structure. snd_dma_buffer looks like this:
struct snd_dma_buffer { struct snd_dma_device dev; /* device type */ unsigned char *area; /* virtual pointer */ dma_addr_t addr; /* physical address */ size_t bytes; /* buffer size in bytes */ void *private_data; /* private for allocator; don't touch */ };
snd_pcm_substream also has a snd_pcm_runtime structure, which looks like this:
struct snd_pcm_runtime { ...
/* -- DMA -- */ unsigned char *dma_area; /* DMA area */ dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ size_t dma_bytes; /* size of DMA area */
struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
Why the redundancy? Not only does snd_pcm_runtime have dma_area, dma_addr, and dma_bytes, but it also has a pointer to a dns_dma_buffer structure, which also has this information!
So given a snd_pcm_substream structure, you can obtain the physical address of the DMA buffer three ways:
substream->dma_buffer.addr substream->runtime->dma_addr substream->runtime->dma_buffer_p->addr
When will these three variable contain different values? If the answer is never, then why do they all exist?
I think this like static and dynamic allocation of buffers.
if it allocated at device driver insertion time then it stored in substream entry.
And this can be used by both playback and capture
If it allocated at runtime then it is stored in runtime entry. And you can have different buffers for both playback and capture.
if no substream is open then runtime structure pointer will be NULL.
Nobin
On 6/15/07, Timur Tabi timur@freescale.com wrote:
The snd_pcm_substream structure has a snd_dma_buffer structure. snd_dma_buffer looks like this:
struct snd_dma_buffer { struct snd_dma_device dev; /* device type */ unsigned char *area; /* virtual pointer */ dma_addr_t addr; /* physical address */ size_t bytes; /* buffer size in bytes */ void *private_data; /* private for allocator; don't touch */ };
snd_pcm_substream also has a snd_pcm_runtime structure, which looks like this:
struct snd_pcm_runtime { ...
/* -- DMA -- */ unsigned char *dma_area; /* DMA area */ dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ size_t dma_bytes; /* size of DMA area */ struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
Why the redundancy? Not only does snd_pcm_runtime have dma_area, dma_addr, and dma_bytes, but it also has a pointer to a dns_dma_buffer structure, which also has this information!
So given a snd_pcm_substream structure, you can obtain the physical address of the DMA buffer three ways:
substream->dma_buffer.addr substream->runtime->dma_addr substream->runtime->dma_buffer_p->addr
When will these three variable contain different values? If the answer is never, then why do they all exist?
-- Timur Tabi Linux Kernel Developer @ Freescale _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
At Thu, 14 Jun 2007 17:47:58 -0500, Timur Tabi wrote:
The snd_pcm_substream structure has a snd_dma_buffer structure. snd_dma_buffer looks like this:
struct snd_dma_buffer { struct snd_dma_device dev; /* device type */ unsigned char *area; /* virtual pointer */ dma_addr_t addr; /* physical address */ size_t bytes; /* buffer size in bytes */ void *private_data; /* private for allocator; don't touch */ };
snd_pcm_substream also has a snd_pcm_runtime structure, which looks like this:
struct snd_pcm_runtime { ...
/* -- DMA -- */ unsigned char *dma_area; /* DMA area */ dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ size_t dma_bytes; /* size of DMA area */
struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
Why the redundancy? Not only does snd_pcm_runtime have dma_area, dma_addr, and dma_bytes, but it also has a pointer to a dns_dma_buffer structure, which also has this information!
So given a snd_pcm_substream structure, you can obtain the physical address of the DMA buffer three ways:
substream->dma_buffer.addr substream->runtime->dma_addr substream->runtime->dma_buffer_p->addr
Some historical reasons. The struct snd_dma_buffer was introduced much later than the definition of struct snd_pcm. Since many drivers and core parts use runtime->dma_addr and runtime->dma_area, it was easier to copy the struct dma_buffer members.
When will these three variable contain different values? If the answer is never, then why do they all exist?
substream->dma_buffer is _not_ mandatory to be filled. It's a field to keep the buffer pool (buffer pre-allocation) information. But this area isn't necessarily to be the buffer actually used. When a bigger buffer is required, the PCM core may allocate it dynamically (and thus runtime->dma_addr points to a different address than pre-allocated area).
Also, some drivers don't need buffer pre-allocation but rather have fixed buffers. In such a case, substream->dma_buffer is uninitialized, and dma_buffer_p is also NULL.
Hence, referring substream->dma_buffer from the driver is wrong in general. Ditto for runtime->dma_buffer_p. Don't touch / look at them in the driver code. The driver code needs to take care of only runtime->dma_addr and runtime->dma_area if needed.
Takashi
participants (3)
-
Nobin Mathew
-
Takashi Iwai
-
Timur Tabi