Linux ALSA sound card Driver II: the creation of a sound card __linux

Source: Internet
Author: User
Tags goto

Statement: This Bo content by Http://blog.csdn.net/droidphone Original, reproduced please indicate the source, thank you. 1. struct Snd_card

What's 1.1 snd_card?

Snd_card can be said to be the entire ALSA audio-driven top-level of a structure, the entire sound card software logic structure began in the structure, almost all the sound-related logic devices are under the management of Snd_card, the sound card driver's first action is usually to create a snd_card structure. Because of this, in this section, we also start from struct Cnd_card.

Definition of 1.2 . Snd_card

The definition of Snd_card is in the header file: include/sound/core.h[C-sharp] View plain copy/* main structure for soundcard */      struct  snd_card {       int number;          /* number of soundcard  (index to                                    snd_cards)  */           char id[16];            /*  id string of this card */       char driver[16];         /* driver name */        char shortname[32];     /* short name of this  soundcard */       char longname[80];      /* name  of this soundcard */       char mixername[80];      /* mixer name */       char  components[128];       /* card components delimited  with                                   space */        struct module *module;      /*  top-level module */          void *private_data;      /* private data for soundcard */        void  (*private_free)   (struct snd_card *card); /* callback for freeing of                                    private data */        struct list_head devices;   /* devices */           unsigned int last_numid;    /*  last used numeric ID */       struct rw_semaphore  controls_rwsem; /* controls list lock */        rwlock_t ctl_files_rwlock;  /* ctl_files list lock */        int controls_count;     /* count of all  controls */       INT USER_CTL_COUNT;     /* COUNT OF  all user controls */       struct list_head  controls;  /* all controls for this card */        struct list_head ctl_files; /* active control files */           struct snd_info_entry *proc_root;   /*  root for soundcard specific files */       struct  snd_info_entry *proc_id; /* the card id */        struct proc_dir_entry *proc_root_link;  /* number link to real  id */          struct list_head files_list;     /* all files associated to this card */       struct  snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown                                    state */        spinlock_t files_lock;      /* lock the  files for this card */       int shutdown;            /* this card is going down  */       int free_on_last_close;     /*  free in context of file_release */       wait_queue_head _t shutdown_sleep;       struct device *dev;     /*  device assigned to this card */   #ifndef  CONFIG_SYSFS_DEPRECATED        struct device *card_dev;    /* cardX  object for sysfs */   #endif      #ifdef  CONFIG_PM        unsigned int power_state;   /* power state */        struct mutex power_lock;    /* power  lock */       wait_queue_head_t power_sleep;   #endif       #if  defined (config_snd_mixer_oss)  | |  defined (config_snd_mixer_oss_module)        struct snd_mixer_oss * mixer_oss;       int mixer_oss_change_count;   #endif   };   struct List_head devices     Record the list of all logical devices under the sound card struct List_head controls    record the list void *private_data    of all control units under the sound card          sound card Private data, you can specify the size of the data by parameter when creating a sound card2. The sound card establishment process

2.1.1. The first step is to create an instance of Snd_card

[C-sharp] view plain copy struct Snd_card *card;   int err;   .... err = Snd_card_create (index, ID, this_module, 0, &card); Index An integer value, the number ID string for the sound card, and the identifier for the sound card The fourth parameter determines the size of the private data that needs to be allocated at the same time when the Snd_card instance is created, and the pointer to the data is eventually assigned to the Snd_ca RD's Private_data data member card returns a pointer to the Snd_card instance that was created

2.1.2. Step Two, create a chip-specific data for your sound card

The private data for the sound card is used primarily for storing some resource information about the sound card, such as interrupting resources, IO resources, DMA resources, and so on. There are two ways to create: By using the fourth argument in Snd_card_create () in the previous step, let Snd_card_create create[C-sharp]View plain copy//struct mychip for Saving private Data Err = Snd_card_create (index, ID, this_module, sizeof (struct   mychip), &card);   Remove struct mychip from private_data *chip = card->private_data; Create yourself:[C-sharp] View Plain Copy struct mychip {       struct snd_card *card;        ....  };   struct snd_card *card;   struct mychip *chip;      chip = kzalloc (sizeof (*chip),  gfp_kernel) ;   ......   err = snd_card_create (Index[dev], id[dev], this_module,  0, &card);  //  Special data record Snd_card instance    chip->card = card;    .....  

Then, register the chip's proprietary data as a lower-order device for the sound card: [C-sharp] view plain copy static int snd_mychip_dev_free ( Struct snd_device *device)    {       return snd_mychip_ Free (device->device_data);  }      static struct snd_device_ops  ops = {       .dev_free = snd_mychip_dev_free,  };    ....   snd_device_new (card, sndrv_dev_lowlevel, chip, &ops);   

registering as a low order device is primarily designed to automatically release the memory used by the chip-specific data when the sound card is logged off.  2.1.3. Step three, set the ID and name of the driver [c-sharp] view plain copy 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);

The Snd_card driver field holds the ID string of the chip, and the alsa-lib of the user space uses the string, so the ID must be guaranteed to be unique. The ShortName field is used more for printing information, and the LongName field appears in/proc/asound/cards.

2.1.4. Step Fourth, create a functional part of the sound card (logical device), such as Pcm,mixer,midi

At this point you can create a variety of functional parts of the sound card, but also remember the beginning of the snd_card structure of the Devices field. The creation of each part will eventually invoke Snd_device_new () to generate a Snd_device instance and link the instance to the Snd_card devices list.

In general, Alsa-driver has already provided some common creation functions for parts without having to call Snd_device_new () directly, such as:

PCM----Snd_pcm_new ()

Rawmidi--Snd_rawmidi_new ()

Control--Snd_ctl_create ()

TIMER--Snd_timer_new ()

INFO--Snd_card_proc_new ()

JACK--Snd_jack_new ()

2.1.5. step Fifth, register your sound card

[C-sharp] view plain Copy err = snd_card_register (card);       if (Err < 0) {Snd_card_free (card);   return err; }


2.2. A practical example

I posted some of the/SOUND/ARM/PXA2XX-AC97.C code:[CPP] View Plain copy static int __devinit pxa2xx_ac97_probe (Struct platform_device *dev)    {       struct snd_card *card;        struct snd_ac97_bus *ac97_bus;       struct snd_ac97_ template ac97_template;       int ret;        pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;           if  (dev->id >= 0)  {            dev_err (&dev->dev,  "pxa2xx has only one ac97 port./n");            ret = -ENXIO;            goto err_dev;       }  ////(1)    &NBSp;   ret = snd_card_create (sndrv_default_idx1, sndrv_default_str1,                      This_module, 0, &card);       if  (ret < 0)             goto err;           card->dev = &dev->dev;  ////(3)////        strncpy (card->driver, dev->dev.driver->name, sizeof (card->driver));      ////(4)////       ret = pxa2xx_pcm_new (card, &pxa2xx_ AC97_PCM_CLIENT,&NBSP;&AMP;PXA2XX_AC97_PCM);       if  (ret)            goto err;  ////(2)////        ret = pxa2xx_ac97_hw_probe (Dev);       if  (ret)             goto err;     ////(4)////        ret = snd_ac97_bus (card, 0, &pxa2xx_ac97_ops, null, & Ac97_bus);       if  (ret)             goto err_remove;       memset (&ac97_template, 0,  sizeof (ac97_template));       ret = snd_ac97_mixer (ac97_bus, & AC97_TEMPLATE,&NBSP;&AMP;PXA2XX_AC97_AC97);       if  (ret)             goto err_remove;  ////(3)////        snprintf (card->shortname, sizeof (card->shortname),              '%s ',  snd_ac97_get_short_name (pxa2xx_ac97_ac97);        snprintf (card->longname, sizeof (card->longname),              "%s  (%s)",  dev->dev.driver->name, card->mixername);           if  (pdata && pdata->codec_pdata[0])             snd_ac97_dev_add_pdata (ac97_bus->codec[0],  Pdata->codec_pdata[0]);       snd_card_set_dev (Card, &dev->dev);   ////(5)////       ret = snd_card_register (card);        if  (ret == 0)  {            platform_set_drvdata (dev, card);            return 0; &nbsp     }      err_remove:   &NBSP;&NBSP;&NBSP;&NBSP;PXA2XX_AC97_HW _remove (Dev);   err:       if  (card)             snd_card_free (card);   err_dev:        return ret;  }      Static int __devexit pxa2xx_ac97_remove ( Struct platform_device *dev)    {       struct snd_card  *card = platform_get_drvdata (Dev);          if  ( Card)  {           snd_card_free (card);            platform_set_drvdata (dev, null);            pxa2xx_ac97_hw_remove (Dev);       }          return 0;  }      static struct  platform_driver pxa2xx_ac97_driver = {       .probe       = pxa2xx_ac97_probe,       .remove      = __devexit_p (pxa2xx_ac97_remove),       .driver      = {           .name   =   "pxa2xx-ac97&

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.