Sophie

Sophie

distrib > CentOS > 6 > i386 > by-pkgid > cf93d8a8acdcc6fe2225039da0502495 > files > 4149

kernel-doc-2.6.32-131.17.1.el6.centos.plus.noarch.rpm

<?xml version="1.0" encoding="ANSI_X3.4-1968" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968" /><title>Operators</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2" /><link rel="home" href="index.html" title="Writing an ALSA Driver" /><link rel="up" href="ch05.html" title="Chapter&#160;5.&#160;PCM Interface" /><link rel="prev" href="ch05s05.html" title="Runtime Pointer - The Chest of PCM Information" /><link rel="next" href="ch05s07.html" title="Interrupt Handler" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Operators</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch05s05.html">Prev</a>&#160;</td><th width="60%" align="center">Chapter&#160;5.&#160;PCM Interface</th><td width="20%" align="right">&#160;<a accesskey="n" href="ch05s07.html">Next</a></td></tr></table><hr /></div><div class="section" title="Operators"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="pcm-interface-operators"></a>Operators</h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-open-callback">open callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-close-callback">close callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-ioctl-callback">ioctl callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-hw-params-callback">hw_params callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-hw-free-callback">hw_free callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-prepare-callback">prepare callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-trigger-callback">trigger callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-pointer-callback">pointer callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-copy-silence">copy and silence callbacks</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-ack">ack callback</a></span></dt><dt><span class="section"><a href="ch05s06.html#pcm-interface-operators-page-callback">page callback</a></span></dt></dl></div><p>
        OK, now let me give details about each pcm callback
      (<em class="parameter"><code>ops</code></em>). In general, every callback must
      return 0 if successful, or a negative error number
      such as <code class="constant">-EINVAL</code>. To choose an appropriate
      error number, it is advised to check what value other parts of
      the kernel return when the same kind of request fails.
      </p><p>
        The callback function takes at least the argument with
        <span class="structname">snd_pcm_substream</span> pointer. To retrieve
        the chip record from the given substream instance, you can use the
        following macro. 

        </p><div class="informalexample"><pre class="programlisting">

  int xxx() {
          struct mychip *chip = snd_pcm_substream_chip(substream);
          ....
  }

          </pre></div><p>

	The macro reads <code class="constant">substream-&gt;private_data</code>,
	which is a copy of <code class="constant">pcm-&gt;private_data</code>.
	You can override the former if you need to assign different data
	records per PCM substream.  For example, the cmi8330 driver assigns
	different private_data for playback and capture directions,
	because it uses two different codecs (SB- and AD-compatible) for
	different directions.
      </p><div class="section" title="open callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-open-callback"></a>open callback</h3></div></div></div><p>
          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_open(struct snd_pcm_substream *substream);

            </pre></div><p>

          This is called when a pcm substream is opened.
        </p><p>
          At least, here you have to initialize the runtime-&gt;hw
          record. Typically, this is done by like this: 

          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_open(struct snd_pcm_substream *substream)
  {
          struct mychip *chip = snd_pcm_substream_chip(substream);
          struct snd_pcm_runtime *runtime = substream-&gt;runtime;

          runtime-&gt;hw = snd_mychip_playback_hw;
          return 0;
  }

            </pre></div><p>

          where <em class="parameter"><code>snd_mychip_playback_hw</code></em> is the
          pre-defined hardware description.
	</p><p>
	You can allocate a private data in this callback, as described
	in <a class="link" href="ch05s05.html#pcm-interface-runtime-private" title="Private Data"><em class="citetitle">
	Private Data</em></a> section.
	</p><p>
	If the hardware configuration needs more constraints, set the
	hardware constraints here, too.
	See <a class="link" href="ch05s09.html" title="Constraints"><em class="citetitle">
	Constraints</em></a> for more details.
	</p></div><div class="section" title="close callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-close-callback"></a>close callback</h3></div></div></div><p>
          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_close(struct snd_pcm_substream *substream);

            </pre></div><p>

          Obviously, this is called when a pcm substream is closed.
        </p><p>
          Any private instance for a pcm substream allocated in the
          open callback will be released here. 

          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_close(struct snd_pcm_substream *substream)
  {
          ....
          kfree(substream-&gt;runtime-&gt;private_data);
          ....
  }

            </pre></div><p>
        </p></div><div class="section" title="ioctl callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-ioctl-callback"></a>ioctl callback</h3></div></div></div><p>
          This is used for any special call to pcm ioctls. But
        usually you can pass a generic ioctl callback, 
        <code class="function">snd_pcm_lib_ioctl</code>.
        </p></div><div class="section" title="hw_params callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-hw-params-callback"></a>hw_params callback</h3></div></div></div><p>
          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
                               struct snd_pcm_hw_params *hw_params);

            </pre></div><p>
        </p><p>
          This is called when the hardware parameter
        (<em class="structfield"><code>hw_params</code></em>) is set
        up by the application, 
        that is, once when the buffer size, the period size, the
        format, etc. are defined for the pcm substream. 
        </p><p>
          Many hardware setups should be done in this callback,
        including the allocation of buffers. 
        </p><p>
          Parameters to be initialized are retrieved by
          <code class="function">params_xxx()</code> macros. To allocate
          buffer, you can call a helper function, 

          </p><div class="informalexample"><pre class="programlisting">

  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));

            </pre></div><p>

          <code class="function">snd_pcm_lib_malloc_pages()</code> is available
	  only when the DMA buffers have been pre-allocated.
	  See the section <a class="link" href="ch11.html#buffer-and-memory-buffer-types" title="Buffer Types"><em class="citetitle">
	  Buffer Types</em></a> for more details.
        </p><p>
          Note that this and <em class="structfield"><code>prepare</code></em> callbacks
        may be called multiple times per initialization.
        For example, the OSS emulation may
        call these callbacks at each change via its ioctl. 
        </p><p>
          Thus, you need to be careful not to allocate the same buffers
        many times, which will lead to memory leaks!  Calling the
        helper function above many times is OK. It will release the
        previous buffer automatically when it was already allocated. 
        </p><p>
          Another note is that this callback is non-atomic
        (schedulable). This is important, because the
        <em class="structfield"><code>trigger</code></em> callback 
        is atomic (non-schedulable). That is, mutexes or any
        schedule-related functions are not available in
        <em class="structfield"><code>trigger</code></em> callback.
	Please see the subsection
	<a class="link" href="ch05s08.html" title="Atomicity"><em class="citetitle">
	Atomicity</em></a> for details.
        </p></div><div class="section" title="hw_free callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-hw-free-callback"></a>hw_free callback</h3></div></div></div><p>
          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_hw_free(struct snd_pcm_substream *substream);

            </pre></div><p>
        </p><p>
          This is called to release the resources allocated via
          <em class="structfield"><code>hw_params</code></em>. For example, releasing the
          buffer via 
          <code class="function">snd_pcm_lib_malloc_pages()</code> is done by
          calling the following: 

          </p><div class="informalexample"><pre class="programlisting">

  snd_pcm_lib_free_pages(substream);

            </pre></div><p>
        </p><p>
          This function is always called before the close callback is called.
          Also, the callback may be called multiple times, too.
          Keep track whether the resource was already released. 
        </p></div><div class="section" title="prepare callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-prepare-callback"></a>prepare callback</h3></div></div></div><p>
          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_prepare(struct snd_pcm_substream *substream);

            </pre></div><p>
        </p><p>
          This callback is called when the pcm is
        <span class="quote">&#8220;<span class="quote">prepared</span>&#8221;</span>. You can set the format type, sample
        rate, etc. here. The difference from
        <em class="structfield"><code>hw_params</code></em> is that the 
        <em class="structfield"><code>prepare</code></em> callback will be called each
        time 
        <code class="function">snd_pcm_prepare()</code> is called, i.e. when
        recovering after underruns, etc. 
        </p><p>
	Note that this callback is now non-atomic.
	You can use schedule-related functions safely in this callback.
        </p><p>
          In this and the following callbacks, you can refer to the
        values via the runtime record,
        substream-&gt;runtime.
        For example, to get the current
        rate, format or channels, access to
        runtime-&gt;rate,
        runtime-&gt;format or
        runtime-&gt;channels, respectively. 
        The physical address of the allocated buffer is set to
	runtime-&gt;dma_area.  The buffer and period sizes are
	in runtime-&gt;buffer_size and runtime-&gt;period_size,
	respectively.
        </p><p>
          Be careful that this callback will be called many times at
        each setup, too. 
        </p></div><div class="section" title="trigger callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-trigger-callback"></a>trigger callback</h3></div></div></div><p>
          </p><div class="informalexample"><pre class="programlisting">

  static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);

            </pre></div><p>

          This is called when the pcm is started, stopped or paused.
        </p><p>
          Which action is specified in the second argument,
          <code class="constant">SNDRV_PCM_TRIGGER_XXX</code> in
          <code class="filename">&lt;sound/pcm.h&gt;</code>. At least,
          the <code class="constant">START</code> and <code class="constant">STOP</code>
          commands must be defined in this callback. 

          </p><div class="informalexample"><pre class="programlisting">

  switch (cmd) {
  case SNDRV_PCM_TRIGGER_START:
          /* do something to start the PCM engine */
          break;
  case SNDRV_PCM_TRIGGER_STOP:
          /* do something to stop the PCM engine */
          break;
  default:
          return -EINVAL;
  }

            </pre></div><p>
        </p><p>
          When the pcm supports the pause operation (given in the info
        field of the hardware table), the <code class="constant">PAUSE_PUSE</code>
        and <code class="constant">PAUSE_RELEASE</code> commands must be
        handled here, too. The former is the command to pause the pcm,
        and the latter to restart the pcm again. 
        </p><p>
          When the pcm supports the suspend/resume operation,
	regardless of full or partial suspend/resume support,
        the <code class="constant">SUSPEND</code> and <code class="constant">RESUME</code>
        commands must be handled, too.
        These commands are issued when the power-management status is
        changed.  Obviously, the <code class="constant">SUSPEND</code> and
        <code class="constant">RESUME</code> commands
        suspend and resume the pcm substream, and usually, they
        are identical to the <code class="constant">STOP</code> and
        <code class="constant">START</code> commands, respectively.
	  See the <a class="link" href="ch13.html" title="Chapter&#160;13.&#160;Power Management"><em class="citetitle">
	Power Management</em></a> section for details.
        </p><p>
          As mentioned, this callback is atomic.  You cannot call
	  functions which may sleep.
	  The trigger callback should be as minimal as possible,
	  just really triggering the DMA.  The other stuff should be
	  initialized hw_params and prepare callbacks properly
	  beforehand.
        </p></div><div class="section" title="pointer callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-pointer-callback"></a>pointer callback</h3></div></div></div><p>
          </p><div class="informalexample"><pre class="programlisting">

  static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)

            </pre></div><p>

          This callback is called when the PCM middle layer inquires
        the current hardware position on the buffer. The position must
        be returned in frames,
        ranging from 0 to buffer_size - 1.
        </p><p>
          This is called usually from the buffer-update routine in the
        pcm middle layer, which is invoked when
        <code class="function">snd_pcm_period_elapsed()</code> is called in the
        interrupt routine. Then the pcm middle layer updates the
        position and calculates the available space, and wakes up the
        sleeping poll threads, etc. 
        </p><p>
          This callback is also atomic.
        </p></div><div class="section" title="copy and silence callbacks"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-copy-silence"></a>copy and silence callbacks</h3></div></div></div><p>
          These callbacks are not mandatory, and can be omitted in
        most cases. These callbacks are used when the hardware buffer
        cannot be in the normal memory space. Some chips have their
        own buffer on the hardware which is not mappable. In such a
        case, you have to transfer the data manually from the memory
        buffer to the hardware buffer. Or, if the buffer is
        non-contiguous on both physical and virtual memory spaces,
        these callbacks must be defined, too. 
        </p><p>
          If these two callbacks are defined, copy and set-silence
        operations are done by them. The detailed will be described in
        the later section <a class="link" href="ch11.html" title="Chapter&#160;11.&#160;Buffer and Memory Management"><em class="citetitle">Buffer and Memory
        Management</em></a>. 
        </p></div><div class="section" title="ack callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-ack"></a>ack callback</h3></div></div></div><p>
          This callback is also not mandatory. This callback is called
        when the appl_ptr is updated in read or write operations.
        Some drivers like emu10k1-fx and cs46xx need to track the
	current appl_ptr for the internal buffer, and this callback
	is useful only for such a purpose.
	</p><p>
	  This callback is atomic.
	</p></div><div class="section" title="page callback"><div class="titlepage"><div><div><h3 class="title"><a id="pcm-interface-operators-page-callback"></a>page callback</h3></div></div></div><p>
          This callback is optional too. This callback is used
        mainly for non-contiguous buffers. The mmap calls this
        callback to get the page address. Some examples will be
        explained in the later section <a class="link" href="ch11.html" title="Chapter&#160;11.&#160;Buffer and Memory Management"><em class="citetitle">Buffer and Memory
        Management</em></a>, too. 
        </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch05s05.html">Prev</a>&#160;</td><td width="20%" align="center"><a accesskey="u" href="ch05.html">Up</a></td><td width="40%" align="right">&#160;<a accesskey="n" href="ch05s07.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Runtime Pointer - The Chest of PCM Information&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&#160;Interrupt Handler</td></tr></table></div></body></html>