A pcm instance is allocated by the snd_pcm_new()
function. It would be better to create a constructor for pcm,
namely,
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; .... return 0; }
The snd_pcm_new()
function takes four
arguments. The first argument is the card pointer to which this
pcm is assigned, and the second is the ID string.
The third argument (index
, 0 in the
above) is the index of this new pcm. It begins from zero. If
you create more than one pcm instances, specify the
different numbers in this argument. For example,
index
= 1 for the second PCM device.
The fourth and fifth arguments are the number of substreams for playback and capture, respectively. Here 1 is used for both arguments. When no playback or capture substreams are available, pass 0 to the corresponding argument.
If a chip supports multiple playbacks or captures, you can specify more numbers, but they must be handled properly in open/close, etc. callbacks. When you need to know which substream you are referring to, then it can be obtained from struct snd_pcm_substream data passed to each callback as follows:
struct snd_pcm_substream *substream; int index = substream->number;
After the pcm is created, you need to set operators for each pcm stream.
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);
The operators are defined typically like this:
static struct snd_pcm_ops snd_mychip_playback_ops = { .open = snd_mychip_pcm_open, .close = snd_mychip_pcm_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, };
All the callbacks are described in the Operators subsection.
After setting the operators, you probably will want to pre-allocate the buffer. For the pre-allocation, simply call the following:
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
It will allocate a buffer up to 64kB as default. Buffer management details will be described in the later section Buffer and Memory Management.
Additionally, you can set some extra information for this pcm
in pcm->info_flags.
The available values are defined as
SNDRV_PCM_INFO_XXX
in
<sound/asound.h>
, which is used for
the hardware definition (described later). When your soundchip
supports only half-duplex, specify like this:
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;