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 11. Buffer and Memory Management"><link rel="prev" href="buffer-and-memory.html" title="Chapter 11. 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> </td><th width="60%" align="center">Chapter 11. Buffer and Memory Management</th><td width="20%" align="right"> <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> </td><td width="20%" align="center"><a accesskey="u" href="buffer-and-memory.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="buffer-and-memory-non-contiguous.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 11. Buffer and Memory Management </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Non-Contiguous Buffers</td></tr></table></div></body></html> 134