PXA310音频(4)

来源:互联网 发布:投影机画面测试软件 编辑:程序博客网 时间:2024/04/28 21:13

 

上面已经创建了codec 结构

接下来就要 register pcms 了。

  snd_soc_new_pcms

首先创建snd_card

snd_card_new 位于sound/core/init.c

创建和初试化一个snd_card  结构体

struct snd_card *snd_card_new(int idx, const char *xid,

                                              struct module *module, int extra_size)

{

               struct snd_card *card;

               int err;

               if (extra_size < 0)

                              extra_size = 0;

               card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);

               if (card == NULL)

                              return NULL;

   分配了结构体

               if (xid) {

                              if (!snd_info_check_reserved_words(xid))

                                             goto __error;

                              strlcpy(card->id, xid, sizeof(card->id));

               }

               err = 0;

               mutex_lock(&snd_card_mutex);

               if (idx < 0) {

                              int idx2;

                              for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)

                                             /* idx == -1 == 0xffff means: take any free slot */

                                             if (~snd_cards_lock & idx & 1<<idx2) {

                                                            idx = idx2;

                                                            if (idx >= snd_ecards_limit)

                                                                           snd_ecards_limit = idx + 1;

                                                            break;

                                             }

               } else {

                               if (idx < snd_ecards_limit) {

                                             if (snd_cards_lock & (1 << idx))

                                                            err = -EBUSY;      /* invalid */

                              } else {

                                             if (idx < SNDRV_CARDS)

                                                            snd_ecards_limit = idx + 1; /* increase the limit */

                                             else

                                                            err = -ENODEV;

                              }

               }

注意上面的按位与操作

理论上可以有32snd_card,找空闲的snd_card,如果能找到就说明是成功的

               if (idx < 0 || err < 0) {

                              mutex_unlock(&snd_card_mutex);

                              snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d/n",

                                              idx, snd_ecards_limit - 1, err);

                              goto __error;

               }

               snd_cards_lock |= 1 << idx;                          /* lock it */

           将选card锁上

               mutex_unlock(&snd_card_mutex);

               card->number = idx;

               card->module = module;

               INIT_LIST_HEAD(&card->devices);

               init_rwsem(&card->controls_rwsem);

               rwlock_init(&card->ctl_files_rwlock);

               INIT_LIST_HEAD(&card->controls);

               INIT_LIST_HEAD(&card->ctl_files);

               spin_lock_init(&card->files_lock);

               init_waitqueue_head(&card->shutdown_sleep);

#ifdef CONFIG_PM

               mutex_init(&card->power_lock);

               init_waitqueue_head(&card->power_sleep);

#endif

               /* the control interface cannot be accessed from the user space until */

               /* snd_cards_bitmask and snd_cards are set with snd_card_register */

               if ((err = snd_ctl_create(card)) < 0) {

                              snd_printd("unable to register control minors/n");

                              goto __error;

               }

snd_card 进行

               if ((err = snd_info_card_create(card)) < 0) {

                              snd_printd("unable to create card info/n");

                              goto __error_ctl;

               }

分配了一个声音控制设置串到snd_carddevice链表中去

这个控制设备提供了一些方法

               static struct snd_device_ops ops = {

                              .dev_free = snd_ctl_dev_free,

                              .dev_register =   snd_ctl_dev_register,

                              .dev_disconnect = snd_ctl_dev_disconnect,

               };

关注一下提供的注册方法,这个在后面会被调用

static int snd_ctl_dev_register(struct snd_device *device)

{

               struct snd_card *card = device->device_data;

               int err, cardnum;

               char name[16];

 

               snd_assert(card != NULL, return -ENXIO);

               cardnum = card->number;

               snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);

               sprintf(name, "controlC%i", cardnum);

               if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,

                                                                   &snd_ctl_f_ops, card, name)) < 0)

                              return err;

               return 0;

}

接下来要进行真正的注册

int snd_register_device_for_dev(int type, struct snd_card *card, int dev,

                                                            const struct file_operations *f_ops,

                                                            void *private_data,

                                                            const char *name, struct device *device)

{

               int minor;

               struct snd_minor *preg;

               snd_assert(name, return -EINVAL);

               preg = kmalloc(sizeof *preg, GFP_KERNEL);

               if (preg == NULL)

                              return -ENOMEM;

               preg->type = type;

               preg->card = card ? card->number : -1;

               preg->device = dev;

               preg->f_ops = f_ops;

               preg->private_data = private_data;

               mutex_lock(&sound_mutex);

#ifdef CONFIG_SND_DYNAMIC_MINORS

               minor = snd_find_free_minor();

#else

               minor = snd_kernel_minor(type, card, dev);

               if (minor >= 0 && snd_minors[minor])

                              minor = -EBUSY;

#endif

               if (minor < 0) {

                              mutex_unlock(&sound_mutex);

                              kfree(preg);

                              return minor;

               }

               snd_minors[minor] = preg;

sound.c 中维护了如下数组

static struct snd_minor *snd_minors[SNDRV_OS_MINORS];

上面的代码 首先创建了一个snd_minor,封装了相应的方法和数据

               preg->dev = device_create(sound_class, device, MKDEV(major, minor),

                                                              "%s", name);

               if (preg->dev)

                              dev_set_drvdata(preg->dev, private_data);

       接下来真正的创建这个设备

               mutex_unlock(&sound_mutex);

               return 0;

}

               if (extra_size > 0)

                              card->private_data = (char *)card + sizeof(struct snd_card);

               return card;

 

      __error_ctl:

               snd_device_free_all(card, SNDRV_DEV_CMD_PRE);

      __error:

               kfree(card);

               return NULL;

}

不过,register的时机还没有到,当前只是创建了一个控制设备结构体,将他串到了card上。

接着在proc 文件系统中创建card节点了

Card 有了 pcm呢?

Pcm的创建根据dai接口的数量来创建,pxa310 中有2dai

也就是调用2soc_new_pcm

首先分配runtime结构  snd_soc_pcm_runtime

Cpu dai的类型就ac97  i2s pcm

分配一个snd_pcm_t 结构体

snd_pcm_t 下的播放流和采集流下的子流设置各种方法

接下来调用 platformpcm_new方法 ,预先分配dmabuffer

到这里我们已经创建了2pcm

然后我们为card添加了一些控制设备

注册的时候将card上的所有设备一起注册了

以上就是probe 中操作的大致内容

 

 

 

 

 

 

 

 

原创粉丝点击