Chip-Specific Data

The chip-specific information, e.g. the i/o port address, its resource pointer, or the irq number, is stored in the chip-specific record.

  struct mychip {
          ....
  };
          

In general, there are two ways to allocate the chip record.

1. Allocating via snd_card_new().

As mentioned above, you can pass the extra-data-length to the 4th argument of snd_card_new(), i.e.

  card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct mychip));
            

whether struct mychip is the type of the chip record.

In return, the allocated record can be accessed as

  struct mychip *chip = card->private_data;
            

With this method, you don't have to allocate twice. The record is released together with the card instance.

2. Allocating an extra device.

After allocating a card instance via snd_card_new() (with NULL on the 4th arg), call kzalloc().

  struct snd_card *card;
  struct mychip *chip;
  card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
  .....
  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
            

The chip record should have the field to hold the card pointer at least,

  struct mychip {
          struct snd_card *card;
          ....
  };
            

Then, set the card pointer in the returned chip instance.

  chip->card = card;
            

Next, initialize the fields, and register this chip record as a low-level device with a specified ops,

  static struct snd_device_ops ops = {
          .dev_free =        snd_mychip_dev_free,
  };
  ....
  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
            

snd_mychip_dev_free() is the device-destructor function, which will call the real destructor.

  static int snd_mychip_dev_free(struct snd_device *device)
  {
          return snd_mychip_free(device->device_data);
  }
            

where snd_mychip_free() is the real destructor.