Gentoo Linux ALSA 指南
ALSA Main Page
Linux音频驱动之二:声卡的创建
Android深入浅出之Audio 第一部分 AudioTrack分析
Android深入浅出之Audio 第二部分 AudioFlinger分析
Android深入浅出之Audio第三部分Audio Policy[1]
audio系统主要分为以下几个层次:
1.media库提供的Audio系统本地部分接口
2.AudioFlinger作为Audio系统的中间层
3.Audio的硬件抽象层提供底层支持
4.Audio通过JNI和java框架提供给上层
以上各个层次抽象成:放音(Track)和录音(Recorder)两个部分。
Java Audio Class(java 框架层) -> Audio JNI(Audio 本地API) -> libmedia -->libaudioflinger.so -->AudioHardwareInterface? --> libaudio.so --> alsa以上的Audio 各个层次都使用一个管理类,和输入输出两个类来表示整个系统。各个层次的目录为:
1 Java 层:frameworks/base/media/java/android/media
2 JNI部分:frameworks/base/core/jni
3 libmedia:frameworks/base/media/libmedia
4 AudioFlinger:frameworks/base/libs/audioflinger
5 AudioHardwareInterface(硬件接口层):hardware/alsa_sound
6 底层:ALSA
在Android中,使用ALSA的api编写了libaudio.so
简介 A card record is the headquarters of the soundcard.这个结构体管理包括PCM、MIDI、mixers、synthesizer在内的声卡设备,并且保存有声卡的ID、声卡的名字(strings)、proc文件、PM以及热插拔管理。
1、 在文件intelmid.c中,下半部分是一个SPI总线的初始化部分,注册一个名为DRIVER_NAME("pmic_audio"@intelmid.h),结构体为snd_intelmad_driver的SPI设备。
2、 然后,通过snd_intelmad_driver中的probe函数。
1> 初始化指向snd_intelmad结构体的指针intelmaddata;
2> 并创建了一个声卡设备:snd_card_create(card_index, card_id, THIS_MODULE, 0, &card);------struct snd_card *card;
3> snd_intelmad_sst_register(intelmaddata);注册一个sst_card,时期能够调用SST的API;
4> 初始化PCM实例、mixer和jack;
5> INIT_WORK(&intelmaddata->mad_jack_msg.wq,sst_process_mad_jack_detection);intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");
6> snd_intelmad_register_irq(intelmaddata);
7> snd_intelmad_create(intelmaddata, card);------snd_device_new(card, SNDRV_DEV_LOWLEVEL, intelmaddata, &ops);(attach the components (devices) to the card instance.)
8> 关联与注册声卡设备nd_card_set_dev(card, &spi->dev);snd_card_register(card);
程序说明:
ALSA driver for Intel MID sound card chipset #include "intelmid_snd_control.h" #include "intelmid.h" #include "intelmid_ctrl.h" module_param : card_index,card_id int sst_card_vendor_id; 结构体: struct snd_pcm_hardware snd_intelmad_stream:info:interleaved PCM格式,双声道,支持PAUSE,RESUME,MMAP,两个OSS参数,PCM子流支持同步 .formats .rates .rate_min .rate_max .channels_min .channels_max(单声道或者双声道) .buffer_bytes_max (MAX_BUFFER 128*1024) .periodxxxx //The “period” is a term that corresponds to a fragment in the OSS world. The period defines the size at which a PCM interrupt is generated. //This size strongly depends on the hardware. Generally, the smaller period size will give you more interrupts, that is, more controls. //In the case of capture, this size defines the input latency. On the other hand, the whole buffer size defines the output latency for the playback direction. struct snd_pcm_ops snd_intelmad_playback_ops 与 snd_intelmad_capture_ops 当创建PCM实例后(snd_pcm_new(),一般使用一个函数来调用这个),要将PCM子流与其对应的操作关联起来,上面这两个结构体就是做这个用的。 本程序结构: 本程序是一个SPI结构: static struct spi_driver snd_intelmad_driver = { .driver = { .name = DRIVER_NAME, .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = snd_intelmad_probe, .remove = __devexit_p(snd_intelmad_remove), }; /*This function is called when the device is initialized(在注册的时候就调用了)*/ snd_intelmad_probe->snd_card_create 填充intelmaddata结构体 snd_intelmad_sst_register snd_intelmad_pcm snd_intelmad_jack snd_intelmad_mixer INIT_WORK snd_intelmad_register_irq snd_intelmad_create snd_card_set_dev: 1、snd_intelmad_sst_register: 从芯片读vendor_id, 处理intelmaddata->sstdrv_ops(module_name, vendor_id, scard_ops),通过各个函数初始化sstdrv_ops所有成员 scard_ops:这个结构体与实际的vendor_id对应的数据结构相连:intelmaddata->sstdrv_ops->scard_ops = intelmad_vendor_ops[sst_card_vendor_id]; 假如vendor_id为2则通过intelmid_ctrl.c的结构体intelmad_vendor_ops映射到intelmid_v2_control.c上文件最后的结构体snd_pmic_ops_nc中。 /* registering with SST driver to get access to SST APIs to use */ intelmaddata->pmic_status为未初始化状态 2、snd_intelmad_pcm: set up pcm params and functions snd_pcm_new(card, name, i, PLAYBACK_COUNT, CAPTURE_COUNT, &pcm):PCM实例的构造函数:第一个参数指定将要构造的实例,第二个参数是ID字符串,第三个参数是PCM的index 第四个和第五个参数是playback和capture的个数, 第六个参数是&pcm /* setup the ops for playback and capture streams */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_intelmad_playback_ops);固定形式,将pcm和后面的结构体相关联,该结构体执行相对的操作 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_intelmad_capture_ops); /* setup private data which can be retrieved when required */ /* allocate dma pages for ALSA stream operations */ 3、snd_intelmad_jack:to setup jack settings of the card[Google: ALSA JACK] 4、snd_intelmad_mixer ret_val = snd_ctl_add(card, snd_ctl_new1(&snd_intelmad_controls[idx], intelmaddata));创建一个声卡控制接口 工作队列: 本驱动程序结构使用到了linux中的中断上半部和下半部的应用,使用了工作队列: snd_intelmad_probe-->INIT_WORK(&intelmaddata->mad_jack_msg.wq, sst_process_mad_jack_detection); intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");创建自己的工作队列 snd_intelmad_intr_handler-->queue_work(intelmaddata->mad_jack_wq, &intelmaddata->mad_jack_msg.wq); 工作队列通过vendor_id来调用相应的工作的函数:这里是sst_mad_jackdetection_nec(intsts,intelmaddata);根据当前工作状态的标记intsts进行相应的操作。 然后载调用函数sst_mad_send_jack_report(struct snd_jack *jack, int buttonpressevent , int status) ALSA: snd_intelmad_pcm_trigger:This function is called whenever an a stream activity is invoked
Driver for Langwell IPC1
部分audio寄存器自己尝试使用默认与auto配置就好