1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>External Hardware Buffers</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="Writing an ALSA Driver"><link rel="up" href="buffer-and-memory.html" title="Chapter&#160;11.&#160;Buffer and Memory Management"><link rel="prev" href="buffer-and-memory.html" title="Chapter&#160;11.&#160;Buffer and Memory Management"><link rel="next" href="buffer-and-memory-non-contiguous.html" title="Non-Contiguous Buffers"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">External Hardware Buffers</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="buffer-and-memory.html">Prev</a>&#160;</td><th width="60%" align="center">Chapter&#160;11.&#160;Buffer and Memory Management</th><td width="20%" align="right">&#160;<a accesskey="n" href="buffer-and-memory-non-contiguous.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="buffer-and-memory-external-hardware"></a>External Hardware Buffers</h2></div></div></div><p>
2        Some chips have their own hardware buffers and the DMA
3      transfer from the host memory is not available. In such a case,
4      you need to either 1) copy/set the audio data directly to the
5      external hardware buffer, or 2) make an intermediate buffer and
6      copy/set the data from it to the external hardware buffer in
7      interrupts (or in tasklets, preferably).
8      </p><p>
9        The first case works fine if the external hardware buffer is large
10      enough.  This method doesn't need any extra buffers and thus is
11      more effective. You need to define the
12      <em class="structfield"><code>copy</code></em> and
13      <em class="structfield"><code>silence</code></em> callbacks for 
14      the data transfer. However, there is a drawback: it cannot
15      be mmapped. The examples are GUS's GF1 PCM or emu8000's
16      wavetable PCM. 
17      </p><p>
18        The second case allows for mmap on the buffer, although you have
19      to handle an interrupt or a tasklet to transfer the data
20      from the intermediate buffer to the hardware buffer. You can find an
21      example in the vxpocket driver. 
22      </p><p>
23        Another case is when the chip uses a PCI memory-map
24      region for the buffer instead of the host memory. In this case,
25      mmap is available only on certain architectures like the Intel one.
26      In non-mmap mode, the data cannot be transferred as in the normal
27      way. Thus you need to define the <em class="structfield"><code>copy</code></em> and
28      <em class="structfield"><code>silence</code></em> callbacks as well, 
29      as in the cases above. The examples are found in
30      <code class="filename">rme32.c</code> and <code class="filename">rme96.c</code>. 
31      </p><p>
32        The implementation of the <em class="structfield"><code>copy</code></em> and
33        <em class="structfield"><code>silence</code></em> callbacks depends upon 
34        whether the hardware supports interleaved or non-interleaved
35        samples. The <em class="structfield"><code>copy</code></em> callback is
36        defined like below, a bit 
37        differently depending whether the direction is playback or
38        capture: 
39
40        </p><div class="informalexample"><pre class="programlisting">
41
42  static int playback_copy(struct snd_pcm_substream *substream, int channel,
43               snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
44  static int capture_copy(struct snd_pcm_substream *substream, int channel,
45               snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
46
47          </pre></div><p>
48      </p><p>
49        In the case of interleaved samples, the second argument
50      (<em class="parameter"><code>channel</code></em>) is not used. The third argument
51      (<em class="parameter"><code>pos</code></em>) points the 
52      current position offset in frames. 
53      </p><p>
54        The meaning of the fourth argument is different between
55      playback and capture. For playback, it holds the source data
56      pointer, and for capture, it's the destination data pointer. 
57      </p><p>
58        The last argument is the number of frames to be copied.
59      </p><p>
60        What you have to do in this callback is again different
61        between playback and capture directions. In the
62        playback case, you copy the given amount of data
63        (<em class="parameter"><code>count</code></em>) at the specified pointer
64        (<em class="parameter"><code>src</code></em>) to the specified offset
65        (<em class="parameter"><code>pos</code></em>) on the hardware buffer. When
66        coded like memcpy-like way, the copy would be like: 
67
68        </p><div class="informalexample"><pre class="programlisting">
69
70  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
71            frames_to_bytes(runtime, count));
72
73          </pre></div><p>
74      </p><p>
75        For the capture direction, you copy the given amount of
76        data (<em class="parameter"><code>count</code></em>) at the specified offset
77        (<em class="parameter"><code>pos</code></em>) on the hardware buffer to the
78        specified pointer (<em class="parameter"><code>dst</code></em>). 
79
80        </p><div class="informalexample"><pre class="programlisting">
81
82  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
83            frames_to_bytes(runtime, count));
84
85          </pre></div><p>
86
87        Note that both the position and the amount of data are given
88      in frames. 
89      </p><p>
90        In the case of non-interleaved samples, the implementation
91      will be a bit more complicated. 
92      </p><p>
93        You need to check the channel argument, and if it's -1, copy
94      the whole channels. Otherwise, you have to copy only the
95      specified channel. Please check
96      <code class="filename">isa/gus/gus_pcm.c</code> as an example. 
97      </p><p>
98        The <em class="structfield"><code>silence</code></em> callback is also
99        implemented in a similar way. 
100
101        </p><div class="informalexample"><pre class="programlisting">
102
103  static int silence(struct snd_pcm_substream *substream, int channel,
104                     snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
105
106          </pre></div><p>
107      </p><p>
108        The meanings of arguments are the same as in the
109      <em class="structfield"><code>copy</code></em> 
110      callback, although there is no <em class="parameter"><code>src/dst</code></em>
111      argument. In the case of interleaved samples, the channel
112      argument has no meaning, as well as on
113      <em class="structfield"><code>copy</code></em> callback.  
114      </p><p>
115        The role of <em class="structfield"><code>silence</code></em> callback is to
116        set the given amount 
117        (<em class="parameter"><code>count</code></em>) of silence data at the
118        specified offset (<em class="parameter"><code>pos</code></em>) on the hardware
119        buffer. Suppose that the data format is signed (that is, the
120        silent-data is 0), and the implementation using a memset-like
121        function would be like: 
122
123        </p><div class="informalexample"><pre class="programlisting">
124
125  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0,
126            frames_to_bytes(runtime, count));
127
128          </pre></div><p>
129      </p><p>
130        In the case of non-interleaved samples, again, the
131      implementation becomes a bit more complicated. See, for example,
132      <code class="filename">isa/gus/gus_pcm.c</code>. 
133      </p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="buffer-and-memory.html">Prev</a>&#160;</td><td width="20%" align="center"><a accesskey="u" href="buffer-and-memory.html">Up</a></td><td width="40%" align="right">&#160;<a accesskey="n" href="buffer-and-memory-non-contiguous.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&#160;11.&#160;Buffer and Memory Management&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&#160;Non-Contiguous Buffers</td></tr></table></div></body></html>
134