Constructor

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;