alsa driver--card

https://www.kernel.org/doc/html/v4.11/sound/kernel-api/writing-an-alsa-driver.html

1.创建声卡

snd_card是对声卡硬件抽象出来的结构体,几乎所有与声音相关的逻辑设备都是在snd_card的管理之下,声卡驱动的第一个动作通常就是创建一个snd_card结构体。

我们可以通过调用snd_card_new来创建一个snd_card结构体。

struct snd_card *card;
int err;
err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);

/**
* snd_card_new - create and initialize a soundcard structure
* @parent: the parent device object
* @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
* @xid: card identification (ASCII string)
* @module: top level module for locking
* @extra_size: allocate this extra size after the main soundcard structure
* @card_ret: the pointer to store the created card instance
*/
int snd_card_new(struct device *parent, int idx, const char *xid, struct module *module, int extra_size, struct snd_card **card_ret)

这里extra_size是为card->private_data分配的内存大小。通常private_data保存chip-specifc data.

2.创建声卡的芯片专用数据

 chip-specific data包含I/O port address, its resource pointer, or the irq number等信息。

有两种方法可以来分配chip specific data.

1).通过snd_card_new实现:

struct mychip {
          struct snd_card *card;
          ....
  };
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                     sizeof(struct mychip), &card);
struct mychip *chip = card->private_data;
chip->card = card;

在snd_card_new中分配chip。并将chip和card关联起来。card结构中的private_data就是chip,chip中又包含card。

2).通过snd_device_new来将chip作为一个低阶device注册到card上。

在snd_device_new中指定extra_size为0.

  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);
  chip->card = card;
static struct snd_device_ops ops = {
          .dev_free =        snd_mychip_dev_free,
  };
  ....
  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);   
  static int snd_mychip_dev_free(struct snd_device *device)
  {
          return snd_mychip_free(device->device_data);
  }

/**
* snd_device_new - create an ALSA device component
* @card: the card instance
* @type: the device type, SNDRV_DEV_XXX
* @device_data: the data pointer of this device
* @ops: the operator table
*/
int snd_device_new(struct snd_card *card, enum snd_device_type type,
void *device_data, struct snd_device_ops *ops)

 snd_device_new不为芯片专用数据device_data分配空间,因此在调用之前,必须为芯片专用分配空间,在ops的dev_free中定义析构函数对芯片专用数据进行析构。dev_free会在调用snd_card_free时自动调用。对于用户自定义的 device, type可以使用SNDRV_DEV_LOWLEVEL。

snd_mychip_dev_free() 是用来free前面kzmalloc的空间。

 3.设置声卡驱动名字和声卡名字。

strcpy(card->driver, "My Chip");
strcpy(card->shortname, "My Own Chip 123");
sprintf(card->longname, "%s at 0x%lx irq %i",
          card->shortname, chip->ioport, chip->irq);
 4.创建声卡功能部件,如PCM,mixer, MIDI
.每一种部件的创建最终会调用snd_device_new()来生成一个snd_device实例,并把该实例链接到snd_card的devices链表中。

通常,alsa-driver的已经提供了一些常用的部件的创建函数,而不必直接调用snd_device_new(),比如: snd_pcm_new()

5.注册声卡

err = snd_card_register(card);
  if (err < 0) {
          snd_card_free(card);
          return err;
  }

 具体声卡创建的例子可参考sound/sparc/amd9730.c   

 

 



posted @ 2016-12-19 18:59  fellow_jing  阅读(1294)  评论(0编辑  收藏  举报