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 of allocating the chip record.
          As mentioned above, you can pass the extra-data-length
	  to the 5th argument of snd_card_new(), i.e.
          
  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                     sizeof(struct mychip), &card);
            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.
          After allocating a card instance via
          snd_card_new() (with
          0 on the 4th arg), call
          kzalloc(). 
          
  struct snd_card *card;
  struct mychip *chip;
  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                     0, &card);
  .....
  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.