<?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>Full Code Example</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 5. PCM Interface" /><link rel="prev" href="ch05.html" title="Chapter 5. PCM Interface" /><link rel="next" href="ch05s03.html" title="Constructor" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Full Code Example</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch05.html">Prev</a> </td><th width="60%" align="center">Chapter 5. PCM Interface</th><td width="20%" align="right"> <a accesskey="n" href="ch05s03.html">Next</a></td></tr></table><hr /></div><div class="section" title="Full Code Example"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="pcm-interface-example"></a>Full Code Example</h2></div></div></div><p> The example code below does not include any hardware access routines but shows only the skeleton, how to build up the PCM interfaces. </p><div class="example"><a id="id2946143"></a><p class="title"><b>Example 5.1. PCM Example Code</b></p><div class="example-contents"><pre class="programlisting"> #include <sound/pcm.h> .... /* hardware definition */ static struct snd_pcm_hardware snd_mychip_playback_hw = { .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, .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, .rate_max = 48000, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = 32768, .period_bytes_min = 4096, .period_bytes_max = 32768, .periods_min = 1, .periods_max = 1024, }; /* hardware definition */ static struct snd_pcm_hardware snd_mychip_capture_hw = { .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, .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, .rate_max = 48000, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = 32768, .period_bytes_min = 4096, .period_bytes_max = 32768, .periods_min = 1, .periods_max = 1024, }; /* open callback */ static int snd_mychip_playback_open(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; runtime->hw = snd_mychip_playback_hw; /* more hardware-initialization will be done here */ .... return 0; } /* close callback */ static int snd_mychip_playback_close(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); /* the hardware-specific codes will be here */ .... return 0; } /* open callback */ static int snd_mychip_capture_open(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; runtime->hw = snd_mychip_capture_hw; /* more hardware-initialization will be done here */ .... return 0; } /* close callback */ static int snd_mychip_capture_close(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); /* the hardware-specific codes will be here */ .... return 0; } /* hw_params callback */ static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } /* hw_free callback */ static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream) { return snd_pcm_lib_free_pages(substream); } /* prepare callback */ static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; /* set up the hardware with the current configuration * for example... */ mychip_set_sample_format(chip, runtime->format); mychip_set_sample_rate(chip, runtime->rate); mychip_set_channels(chip, runtime->channels); mychip_set_dma_setup(chip, runtime->dma_addr, chip->buffer_size, chip->period_size); return 0; } /* trigger callback */ static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { 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; } } /* pointer callback */ static snd_pcm_uframes_t snd_mychip_pcm_pointer(struct snd_pcm_substream *substream) { struct mychip *chip = snd_pcm_substream_chip(substream); unsigned int current_ptr; /* get the current hardware pointer */ current_ptr = mychip_get_hw_pointer(chip); return current_ptr; } /* operators */ static struct snd_pcm_ops snd_mychip_playback_ops = { .open = snd_mychip_playback_open, .close = snd_mychip_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_mychip_pcm_hw_params, .hw_free = snd_mychip_pcm_hw_free, .prepare = snd_mychip_pcm_prepare, .trigger = snd_mychip_pcm_trigger, .pointer = snd_mychip_pcm_pointer, }; /* operators */ static struct snd_pcm_ops snd_mychip_capture_ops = { .open = snd_mychip_capture_open, .close = snd_mychip_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_mychip_pcm_hw_params, .hw_free = snd_mychip_pcm_hw_free, .prepare = snd_mychip_pcm_prepare, .trigger = snd_mychip_pcm_trigger, .pointer = snd_mychip_pcm_pointer, }; /* * definitions of capture are omitted here... */ /* create a pcm device */ static int __devinit snd_mychip_new_pcm(struct mychip *chip) { struct snd_pcm *pcm; int err; err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm); if (err < 0) return err; pcm->private_data = chip; strcpy(pcm->name, "My Chip"); chip->pcm = pcm; /* set operators */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mychip_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mychip_capture_ops); /* pre-allocation of buffers */ /* NOTE: this may fail */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 64*1024); return 0; } </pre></div></div><p><br class="example-break" /> </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch05.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ch05.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch05s03.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 5. PCM Interface </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Constructor</td></tr></table></div></body></html>