android soundrecorder之二 应用层到HAL实现

来源:互联网 发布:nas 文件拷贝 软件 编辑:程序博客网 时间:2024/04/30 19:27

转载请标注原文地址:http://blog.csdn.net/uranus_wm/article/details/12748559

前一篇文章介绍了linux alsa初始化的过程,并根据dai_link创建了设备节点,提供给上层应用作为访问接口

这篇文章主要介绍下android soundrecorder从应用层到HAL层的代码框架

后面一片文章重点介绍linux部分,然后说明一下音频数据在内存中的流向和一些相关的调试方法

首先还是看图:

更正说明:tinyalsa访问设备节点应该是/dev/snd/pcmCxDxp, /dev/snd/pcmCxDxc和/dev/snd/controlCx,画图时没有确认造成笔误

这个框图大致把soundrecorder从app到framework到HAL的类图画了出来

有些子类父类继承关系没有表示出来,从soundrecorder到AudioRecord基本就是一条线下来

我也没有详细去看代码,stagefright这一块很庞大,实现了多种mime格式的编解码

音频数据生成文件保存在sd卡中应该是在MPEG4Writer这里完成的,这个没有细看

我们重点看下AudioSystem,AudioPolicyService,AudioFlinger和AudioHardware这块。

以open_record()和get_input()这两个方法为例我们看下这几个类之间的调用关系

从AudioRecord.cpp开始,文件位置:frameworks\base\media\libmedia\AudioRecord.cpp

[cpp] view plaincopyprint?
  1. status_t AudioRecord::openRecord_l( 
  2.         uint32_t sampleRate, 
  3.         uint32_t format, 
  4.         uint32_t channelMask, 
  5.         int frameCount, 
  6.         uint32_t flags, 
  7.         audio_io_handle_t input) 
  8.     status_t status; 
  9.     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 
  10.     sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input, 
  11.                                                        sampleRate, format, 
  12.                                                        channelMask, 
  13.                                                        frameCount, 
  14.                                                        ((uint16_t)flags) << 16, 
  15.                                                        &mSessionId, 
  16.                                                        &status); 
  17. ... 
  18. audio_io_handle_t AudioRecord::getInput_l() 
  19.     mInput = AudioSystem::getInput(mInputSource, 
  20.                                 mCblk->sampleRate, 
  21.                                 mFormat, 
  22.                                 mChannelMask, 
  23.                                 (audio_in_acoustics_t)mFlags, 
  24.                                 mSessionId); 
  25.     return mInput; 

可以看到openRecord_l()直接用AudioSystem这个静态类获取AudioFlinger这个service

[cpp] view plaincopyprint?
  1. const sp<IAudioFlinger>& AudioSystem::get_audio_flinger() 
  2.     Mutex::Autolock _l(gLock); 
  3.     if (gAudioFlinger.get() == 0) { 
  4.         sp<IServiceManager> sm = defaultServiceManager(); 
  5.         sp<IBinder> binder; 
  6.         do
  7.             binder = sm->getService(String16("media.audio_flinger")); 
  8.         } while(true); 
  9.         if (gAudioFlingerClient == NULL) { 
  10.             gAudioFlingerClient = new AudioFlingerClient(); 
  11.         }  
  12.         binder->linkToDeath(gAudioFlingerClient); 
  13.         gAudioFlinger = interface_cast<IAudioFlinger>(binder); 
  14.         gAudioFlinger->registerClient(gAudioFlingerClient); 
  15.     } 
  16.     return gAudioFlinger; 

这里我碰到个问题,get_audio_flinger从ServiceManager获取audio_flinger service,但是我找了半天没有找到add这个service的地方

找到的朋友可以提醒我一下

另外一个getInput_l(),这是一个通路选择的方法,android也用一个service来维护:AudioPolicyService

这个Service对应一个虚拟的硬件设备,由audio_policy_hal提供接口访问,这么做我估计是为了结构上比较清晰,但是代码看起来就有点绕了

从上面类图来看getInput_l()的调用过程:

从AudioSystem->AudioPolicyService->audio_policy_hal->AudioPolicyManagerBase->AudioPolicyCompatClient->AudioPolicyService->AudioFlinger

[cpp] view plaincopyprint?
  1. 文件位置:frameworks\base\media\libmedia\AudioSystem.cpp 
  2.  
  3. audio_io_handle_t AudioSystem::getInput(int inputSource, 
  4.                                     uint32_t samplingRate, 
  5.                                     uint32_t format, 
  6.                                     uint32_t channels, 
  7.                                     audio_in_acoustics_t acoustics, 
  8.                                     int sessionId) 
  9.     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); 
  10.     if (aps == 0) return 0; 
  11.     return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId); 
  12.  
  13. 文件位置:frameworks\base\services\audioflinger\AudioPolicyService.cpp 
  14.  
  15. audio_io_handle_t AudioPolicyService::getInput(int inputSource, 
  16.                                     uint32_t samplingRate, 
  17.                                     uint32_t format, 
  18.                                     uint32_t channels, 
  19.                                     audio_in_acoustics_t acoustics, 
  20.                                     int audioSession) 
  21.     if (mpAudioPolicy == NULL) { 
  22.         return 0; 
  23.     } 
  24.     Mutex::Autolock _l(mLock); 
  25.     audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate, 
  26.                                                        format, channels, acoustics); 
  27.  
  28.  
  29. 文件位置:hardware\libhardware_legacy\audio\audio_policy_hal.cpp 
  30.  
  31. static audio_io_handle_t ap_get_input(struct audio_policy *pol,int inputSource, 
  32.                                       uint32_t sampling_rate, 
  33.                                       uint32_t format, 
  34.                                       uint32_t channels, 
  35.                                       audio_in_acoustics_t acoustics) 
  36.     struct legacy_audio_policy *lap = to_lap(pol); 
  37.     return lap->apm->getInput(inputSource, sampling_rate, format, channels, 
  38.                               (AudioSystem::audio_in_acoustics)acoustics); 
  39.  
  40. 文件位置:hardware\libhardware_legacy\audio\AudioPolicyManagerBase.cpp 
  41.  
  42. audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource, 
  43.                                     uint32_t samplingRate, 
  44.                                     uint32_t format, 
  45.                                     uint32_t channels, 
  46.                                     AudioSystem::audio_in_acoustics acoustics) 
  47.     input = mpClientInterface->openInput(&inputDesc->mDevice, 
  48.                                     &inputDesc->mSamplingRate, 
  49.                                     &inputDesc->mFormat, 
  50.                                     &inputDesc->mChannels, 
  51.                                     inputDesc->mAcoustics); 
  52.  
  53.  
  54. 文件位置:hardware\libhardware_legacy\audio\AudioPolicyCompatClient.cpp 
  55.  
  56. audio_io_handle_t AudioPolicyCompatClient::openOutput(uint32_t *pDevices, 
  57.                                 uint32_t *pSamplingRate, 
  58.                                 uint32_t *pFormat, 
  59.                                 uint32_t *pChannels, 
  60.                                 uint32_t *pLatencyMs, 
  61.                                 AudioSystem::output_flags flags) 
  62.     return mServiceOps->open_output(mService, pDevices, pSamplingRate, pFormat, 
  63.                                     pChannels, pLatencyMs, 
  64.                                     (audio_policy_output_flags_t)flags); 
  65.  
  66. static audio_io_handle_t aps_open_input(void *service, 
  67.                                             uint32_t *pDevices, 
  68.                                             uint32_t *pSamplingRate, 
  69.                                             uint32_t *pFormat, 
  70.                                             uint32_t *pChannels, 
  71.                                             uint32_t acoustics) 
  72.     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 
  73.     return af->openInput(pDevices, pSamplingRate, pFormat, pChannels, 
  74.                          acoustics); 

其关键就是AudioPolicyService将一个aps_ops结构体一层层传给AudioPolicyCompatClient,最后又调回到AudioPolicyService,这个地方有点绕

[cpp] view plaincopyprint?
  1. namespace
  2.     struct audio_policy_service_ops aps_ops = { 
  3.         open_output           : aps_open_output, 
  4.         open_duplicate_output : aps_open_dup_output, 
  5.         close_output          : aps_close_output, 
  6.         suspend_output        : aps_suspend_output, 
  7.         restore_output        : aps_restore_output, 
  8.         open_input            : aps_open_input, 
  9.         close_input           : aps_close_input, 
  10.         set_stream_volume     : aps_set_stream_volume, 
  11.         set_stream_output     : aps_set_stream_output, 
  12.         set_parameters        : aps_set_parameters, 
  13.         get_parameters        : aps_get_parameters, 
  14.         start_tone            : aps_start_tone, 
  15.         stop_tone             : aps_stop_tone, 
  16.         set_voice_volume      : aps_set_voice_volume, 
  17.         move_effects          : aps_move_effects, 
  18.     }; 
  19. }; // namespace <unnamed> 

回过头我们还是看AudioFlinger.cpp这个文件,其内部包含好几个子类

class MixerThread是一个混音器,他可以将多个音频OutputTrack和InputTrack混合到一起,像正在播放的mp3是一个OutputTrack,录音是一个InputTrack

class DirectOutputThread是指不经过混音,直接输出的thread

class RecordThread就是我们soundRecorder用到的thread

class PlaybackThread支持混音输出的thread

AudioFlinger还是增加音效,功能很强,由于我调试的时间也短,还没能完全涉及到!

AudioFlinger之所以可以实现音频数据的输入输出是因为audio_hw_hal提供了硬件抽象层接口:

文件位置:hardware\libhardware_legacy\audio\audio_hw_hal.cpp

[cpp] view plaincopyprint?
  1. static int legacy_adev_open(const hw_module_t* module,const char* name, 
  2.                             hw_device_t** device) 
  3.     struct legacy_audio_device *ladev; 
  4.     int ret; 
  5.     ladev = (struct legacy_audio_device *)calloc(1,sizeof(*ladev)); 
  6.     if (!ladev) 
  7.         return -ENOMEM; 
  8.  
  9.     ladev->device.common.tag = HARDWARE_DEVICE_TAG; 
  10.     ladev->device.common.version = 0; 
  11.     ladev->device.common.module = const_cast<hw_module_t*>(module); 
  12.     ladev->device.common.close = legacy_adev_close; 
  13.     ladev->device.get_supported_devices = adev_get_supported_devices; 
  14.     ladev->device.init_check = adev_init_check; 
  15.     ladev->device.set_voice_volume = adev_set_voice_volume; 
  16.     ladev->device.set_master_volume = adev_set_master_volume; 
  17.     ladev->device.set_mode = adev_set_mode; 
  18.     ladev->device.set_mic_mute = adev_set_mic_mute; 
  19.     ladev->device.get_mic_mute = adev_get_mic_mute; 
  20.     ladev->device.set_parameters = adev_set_parameters; 
  21.     ladev->device.get_parameters = adev_get_parameters; 
  22.     ladev->device.get_input_buffer_size = adev_get_input_buffer_size; 
  23.     ladev->device.open_output_stream = adev_open_output_stream; 
  24.     ladev->device.close_output_stream = adev_close_output_stream; 
  25.     ladev->device.open_input_stream = adev_open_input_stream; 
  26.     ladev->device.close_input_stream = adev_close_input_stream; 
  27.     ladev->device.dump = adev_dump; 
  28.  
  29.     ladev->hwif = createAudioHardware(); 
  30.     if (!ladev->hwif) { 
  31.         ret = -EIO; 
  32.         goto err_create_audio_hw; 
  33.     } 
  34.  
  35.     *device = &ladev->device.common; 
  36.  
  37.     return 0; 
  38. static struct hw_module_methods_t legacy_audio_module_methods = { 
  39.         open: legacy_adev_open 
  40. }; 
  41.  
  42. struct legacy_audio_module HAL_MODULE_INFO_SYM = { 
  43.     module: { 
  44.         common: { 
  45.             tag: HARDWARE_MODULE_TAG, 
  46.             version_major: 1, 
  47.             version_minor: 0, 
  48.             id: AUDIO_HARDWARE_MODULE_ID, 
  49.             name: "LEGACY Audio HW HAL"
  50.             author: "The Android Open Source Project"
  51.             methods: &legacy_audio_module_methods, 
  52.             dso : NULL, 
  53.             reserved : {0}, 
  54.         }, 
  55.     }, 
  56. }; 

不同的平台都有自己的AudioHardware具体实现

借用一本android培训书籍的框图看下AudioHardware的层级架构,作者好像是韩超


可以看到对于输入流和输出流,从JAVA层到HAL层都有一个对应的子类来负责

在AudioHardware里面录音用到的就是AudioStreamIn,如下面这个方法:

[cpp] view plaincopyprint?
  1. status_t AudioHardware::AudioStreamInALSA::getNextBuffer(struct resampler_buffer *buffer) 
  2.     if (mInputFramesIn == 0) { 
  3.         TRACE_DRIVER_IN(DRV_PCM_READ) 
  4.         mReadStatus = pcm_read(mPcm,(void*) mInputBuf, AUDIO_HW_IN_PERIOD_SZ * frameSize()); 
  5.         TRACE_DRIVER_OUT 
  6.         if (mReadStatus != 0) { 
  7.             buffer->raw = NULL; 
  8.             buffer->frame_count = 0; 
  9.             return mReadStatus; 
  10.         } 
  11.         mInputFramesIn = AUDIO_HW_IN_PERIOD_SZ; 
  12.     } 
  13.     buffer->frame_count = (buffer->frame_count > mInputFramesIn) ? mInputFramesIn:buffer->frame_count; 
  14.     buffer->i16 = mInputBuf + (AUDIO_HW_IN_PERIOD_SZ - mInputFramesIn) * mChannelCount; 
  15.  
  16.     return mReadStatus; 

这里有个pcm_read()函数就是google为了调用linux alsa提供的文件接口专门写得一个适配层,命名为tinyalsa

从AudioHardware到tinyalsa主要完成的任务就是:

  1. 设置当前系统音频模式:通话模式,录音模式还是播放模式
  2. 配置dapm通路:即main_mic还是aux_mic,spreaker还是receiver还是headset,aif1还是aif2或者aif.x
  3. 音效,音量等参数配置
  4. 读取输入的pcm数据和传送输出的pcm数据

android4.0上面AudioSystem代码基本完善,我们调试一个codec主要的工作就三点:

  1. bsp配置如i2c,micbias配置
  2. kernel dai_link实现和snd_pcm_hardware的注册
  3. 代码量最大的就是这里dapm的配置

我这里给出wolfson wm8994在4412上面的一些配置表,经过测试工作正常

dapm全称是dynamic audio power management,其主要作用就是配置codec内部的muxer和mixer,已实现路径的切换

具体来讲需要一个单独的章节,这里先贴代码:

[cpp] view plaincopyprint?
  1. typedef struct AudioMixer_tag { 
  2.     const char *ctl; 
  3.     const int   val; 
  4. } AudioMixer; 
  5.  
  6. const AudioMixer device_out_SPK[] = { 
  7. #if defined (USES_I2S_AUDIO) || defined (USES_PCM_AUDIO) 
  8. /*AIF1 to DAC1*/ 
  9.     {"DAC1L Mixer AIF1.1 Switch", 1},// "OFF", "ON" 
  10.     {"DAC1R Mixer AIF1.1 Switch", 1},// "OFF", "ON" 
  11.     {"DAC1 Switch", 1}, // "OFF OFF", "ON ON" 
  12.     {"DAC1 Volume", 96}, //[0,1..96]:[MUTE,-71.62db..0db] 0610h_0611h 
  13. /*DAC1 to SPK*/ 
  14.     {"SPKL DAC1 Switch", 1}, // "OFF", "ON" 
  15.     {"SPKL DAC1 Volume", 1},// [0..1]:[-3db..0db] 0022h 
  16.     {"SPKR DAC1 Switch", 1}, // "OFF", "ON" 
  17.     {"SPKR DAC1 Volume", 1},// [0..1]:[-3db..0db] 0023h 
  18.     {"Speaker Mixer Volume", 3}, // [0..3]:[MUTE,-12db,-6db,0db] 0022h_0023h 
  19.     {"Speaker Volume", 63},// [0..63]:[-57db..+6db] 0026h_0027h 
  20.     {"SPKL Boost SPKL Switch", 1}, // "OFF OFF", "ON ON" 
  21.     {"SPKR Boost SPKR Switch", 1},// "OFF OFF", "ON ON" 
  22.     {"Speaker Boost Volume", 7}, // [0..7]:[0db..+12db] 0025h 
  23. /*DAC1 to Headphone*/ 
  24.     {"Right Headphone Mux", 1}, // "Mixer","DAC" 
  25.     {"Left Headphone Mux", 1}, // "Mixer","DAC" 
  26.     {"Headphone Switch", 1}, // "HP MUTE","UNMUTE" 
  27. #elif defined(USES_SPDIF_AUDIO) 
  28. #endif 
  29.     {NULL, NULL} 
  30. }; 
  31. const AudioMixer device_out_RING_SPK[] = { 
  32. /*AIF1 to DAC1*/ 
  33.     {"DAC1L Mixer AIF1.1 Switch", 1},// "OFF", "ON" 
  34.     {"DAC1R Mixer AIF1.1 Switch", 1},// "OFF", "ON" 
  35.     {"DAC1 Switch", 1}, // "OFF OFF", "ON ON" 
  36.     {"DAC1 Volume", 96}, //[0,1..96]:[MUTE,-71.62db..0db] 0610h_0611h 
  37. /*DAC1 to SPK*/ 
  38.     {"SPKL DAC1 Switch", 1}, // "OFF", "ON" 
  39.     {"SPKL DAC1 Volume", 1},// [0..1]:[-3db..0db] 0022h 
  40.     {"SPKR DAC1 Switch", 1}, // "OFF", "ON" 
  41.     {"SPKR DAC1 Volume", 1},// [0..1]:[-3db..0db] 0023h 
  42.     {"Speaker Mixer Volume", 3}, // [0..3]:[MUTE,-12db,-6db,0db] 0022h_0023h 
  43.     {"Speaker Volume", 63},// [0..63]:[-57db..+6db] 0026h_0027h 
  44.     {"SPKL Boost SPKL Switch", 1}, // "OFF OFF", "ON ON" 
  45.     {"SPKR Boost SPKR Switch", 1},// "OFF OFF", "ON ON" 
  46.     {"Speaker Boost Volume", 7}, // [0..7]:[0db..+12db] 0025h 
  47.     {NULL, NULL} 
  48. }; 
  49.  
  50. const AudioMixer device_voice_RCV[] = {  
  51. #if defined (USES_I2S_AUDIO) || defined (USES_PCM_AUDIO) 
  52. //Main_MIC(IN1L N_VMID) to MIXIN to ADC to DAC2 Mixer to AIF2(ADCDAT2) 
  53. //Main_MIC(IN1L N_VMID) to MIXINL 
  54.     {"IN1L PGA IN1LN Switch", 1}, //OFF,IN1LN 
  55.     {"IN1L PGA IN1LP Switch", 1},//VMID,IN1LP 
  56.     {"IN1L Switch", 1}, //[0..1]:[MUTE..UNMUTE] ,0018h:b7 
  57.     {"IN1L Volume", 12}, //[1..31]:[-16.5db..+30db],0018h 
  58.     {"MIXINL IN1L Switch", 1}, 
  59.     {"MIXINL IN1L Volume",1},//[0..1]:[0db..+30db]],0029h 
  60. /*ADCL to AIF2ADC*/ 
  61.     {"ADCL Mux", 0}, //ADC,DMIC 
  62.     {"Left Sidetone", 0}, //_D__DMIC1,DMIC2 
  63.     {"AIF2DAC2L Mixer Left Sidetone Switch", 1},//,0604h 
  64.     //{"AIF2DAC2R Mixer Left Sidetone Switch", 1}, //,0605h 
  65.     {"DAC2 Left Sidetone Volume", 12}, //[0..12]:[-36db..0db],0603h 
  66.     {"DAC2 Right Sidetone Volume", 12},//[0..12]:[-36db..0db],0603h 
  67.     //////{"AIF2DAC2L Mixer AIF2 Switch", 1}, //,0604h ////////////////++ test 
  68.     //////{"AIF2DAC2R Mixer AIF2 Switch", 1}, //,0604h ////////////////++ test 
  69.     {"AIF2ADCL Source", 0},//Left,Right 
  70.     //{"AIF2ADCR Source", 0}, //Left,Right 
  71.     {"AIF2ADC Mux", 0}, //AIF2ADCDAT,AIF3DACDAT 
  72.     //{"AIF2ADC Volume", 119}, //[0,1..119]:[MUTE,-71.625db..+17.625db],0500h_0501h default:C0 eq 0db 
  73.     {"DAC2 Switch", 1}, //[0..1]:[UNMUTE..MUTE] 0612h_0613h 
  74.     {"DAC2 Volume", 96}, //[0,1..96]:[MUTE,-71.62db..0db] 0612h_0613h 
  75.  
  76. //BB_in AIF2DAC(DACDAT2) to DAC1_R to MIXOUTL_R to SPKMIXL_R to SPK 
  77. /*MIXIN to MIXOUT for mic to hp test*/ 
  78.     //{"Left Output Mixer Left Input Switch", 1}, // "OFF", "ON" ,002dh ///////////////+ 
  79.     //{"Right Output Mixer Left Input Switch", 1}, // "OFF", "ON" ,002eh //////////////+ 
  80. /*ADCL to DAC1 for sidetone*/ 
  81.     {"DAC1L Mixer Left Sidetone Switch", 1}, 
  82.     {"DAC1R Mixer Left Sidetone Switch", 1}, 
  83.     {"DAC1 Left Sidetone Volume", 0}, //[0..12]:[-36db..0db],0603h 
  84.     {"DAC1 Right Sidetone Volume", 0},//[0..12]:[-36db..0db],0603h 
  85. /*AIF2DAC to DAC1*/ 
  86.     {"AIF2DAC Mux", 0}, // AIF2DACDAT,AIF3DACDAT 
  87.     {"DAC1L Mixer AIF2 Switch", 1},// "OFF", "ON" ,0601h 
  88.     {"DAC1R Mixer AIF2 Switch", 1}, // "OFF", "ON" ,0602h 
  89.     {"DAC1 Switch", 1}, // "OFF OFF", "ON ON" 
  90. /*DAC1 to HP*/ 
  91.     {"Left Output Mixer DAC Switch", 1},// "OFF OFF", "ON ON" 
  92.     {"Right Output Mixer DAC Switch", 1},// "OFF OFF", "ON ON" 
  93.     {"Output Switch", 1},// "OFF OFF", "ON ON" 
  94.      
  95.     {"Right Headphone Mux", 0},// "Mixer","DAC" 
  96.     {"Left Headphone Mux", 0},  // "Mixer","DAC" 
  97.     {"Headphone Switch", 1},// "HP MUTE","UNMUTE" 
  98. #elif defined(USES_SPDIF_AUDIO) 
  99. #endif 
  100.     {NULL, NULL} 
  101. }; 
  102. const AudioMixer device_input_Main_Mic[] = { 
  103. #if defined (USES_I2S_AUDIO) || defined (USES_PCM_AUDIO) 
  104. //Main_MIC(IN1L N_VMID) to MIXIN to ADC to DAC2 Mixer to AIF2(ADCDAT2) 
  105. //Main_MIC(IN1L N_VMID) to MIXINL 
  106.     {"IN1L PGA IN1LN Switch", 1}, //OFF,IN1LN 
  107.     {"IN1L PGA IN1LP Switch", 1},//VMID,IN1LP 
  108.     {"IN1L Switch", 1}, //[0..1]:[MUTE..UNMUTE] ,0018h:b7 
  109.     {"IN1L Volume", 12}, //[1..31]:[-16.5db..+30db],0018h 
  110.     {"MIXINL IN1L Switch", 1}, 
  111.     {"MIXINL IN1L Volume",1},//[0..1]:[0db..+30db]],0029h 
  112. /*ADCL to AIF1ADC*/ 
  113.     {"ADCL Mux", 0}, //ADC,DMIC 
  114.     {"AIF1ADCL Source", 0}, //Left,Right 
  115.     {"AIF1ADCR Source", 0},//Left,Right 
  116.     {"AIF1ADC1 Volume", 119}, //[0,1..119]:[MUTE,-71.625db..+17.625db],0400h_0401h default:C0 eq 0db 
  117.     {"AIF1ADC1L DRC Switch",1}, 
  118.     {"AIF1ADC1R DRC Switch",1}, 
  119.     {"AIF1ADC1L Mixer ADC/DMIC Switch",1}, 
  120.     {"AIF1ADC1R Mixer ADC/DMIC Switch",1}, 
  121. #elif defined(USES_SPDIF_AUDIO) 
  122. #endif 
  123.     {NULL, NULL} 
  124. }; 

每一行的{}里面有两个值,用“,”分开,实际上前一个值是有两部分组成,分别是“dest ctrl+control ctrl”,省略了src ctrl;后一个值通常是数字

注意这里的数字1不是true的意思,而是当前route里面的第几个的意思,是个index值,这个需要在wm8994驱动里面取对应查找

再说说AudioHardare

文件位置:\device\samsung\smdk_common\lib_audio\AudioHardware.cpp

重点关注下下面这些函数,当然函数很多,还得自己慢慢看代码

[cpp] view plaincopyprint?
  1. struct mixer *AudioHardware::openMixer_l() 
  2.     LOGV("openMixer_l() mMixerOpenCnt: %d", mMixerOpenCnt); 
  3.     if (mMixerOpenCnt++ == 0) { 
  4.         if (mMixer != NULL) { 
  5.             LOGE("openMixer_l() mMixerOpenCnt == 0 and mMixer == %p\n", mMixer); 
  6.             mMixerOpenCnt--; 
  7.             return NULL; 
  8.         } 
  9.         TRACE_DRIVER_IN(DRV_MIXER_OPEN) 
  10.         mMixer = mixer_open(0); 
  11.         TRACE_DRIVER_OUT 
  12.         if (mMixer == NULL) { 
  13.             LOGE("openMixer_l() cannot open mixer"); 
  14.             mMixerOpenCnt--; 
  15.             return NULL; 
  16.         } 
  17.     } 
  18.     return mMixer; 
  19.  
  20. struct pcm *AudioHardware::openPcmOut_l() 
  21.     LOGD("openPcmOut_l() mPcmOpenCnt: %d", mPcmOpenCnt); 
  22.     if (mPcmOpenCnt++ == 0) { 
  23.         if (mPcm != NULL) { 
  24.             LOGE("openPcmOut_l() mPcmOpenCnt == 0 and mPcm == %p\n", mPcm); 
  25.             mPcmOpenCnt--; 
  26.             return NULL; 
  27.         } 
  28.         unsigned flags = PCM_OUT; 
  29.  
  30.         struct pcm_config config = { 
  31.             channels : 2, 
  32.             rate : AUDIO_HW_OUT_SAMPLERATE, 
  33.             period_size : AUDIO_HW_OUT_PERIOD_SZ, 
  34.             period_count : AUDIO_HW_OUT_PERIOD_CNT, 
  35.             format : PCM_FORMAT_S16_LE, 
  36.             start_threshold : 0, 
  37.             stop_threshold : 0, 
  38.             silence_threshold : 0, 
  39.         }; 
  40.  
  41.         TRACE_DRIVER_IN(DRV_PCM_OPEN) 
  42. #if defined(USES_PCM_AUDIO) || defined(USES_SPDIF_AUDIO) 
  43.         mPcm = pcm_open(0, 0, flags, &config); 
  44. #elif defined(USES_I2S_AUDIO) 
  45.         mPcm = pcm_open(0, 1, flags, &config); 
  46. #endif 
  47.         TRACE_DRIVER_OUT 
  48.         if (!pcm_is_ready(mPcm)) { 
  49.             LOGE("openPcmOut_l() cannot open pcm_out driver: %s\n", pcm_get_error(mPcm)); 
  50.             TRACE_DRIVER_IN(DRV_PCM_CLOSE) 
  51.             pcm_close(mPcm); 
  52.             TRACE_DRIVER_OUT 
  53.             mPcmOpenCnt--; 
  54.             mPcm = NULL; 
  55.         } 
  56.     } 
  57.     return mPcm; 
  58.  
  59. const AudioMixer *AudioHardware::getInputRouteFromDevice(uint32_t device) 
  60.     if (mMicMute) { 
  61.         return device_input_MIC_OFF; 
  62.     } 
  63.  
  64.     switch (device) { 
  65.     case AudioSystem::DEVICE_IN_BUILTIN_MIC: 
  66.         return device_input_Main_Mic; 
  67.     case AudioSystem::DEVICE_IN_WIRED_HEADSET: 
  68.         return device_input_Hands_Free_Mic; 
  69.     case AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET: 
  70.         return device_input_BT_Sco_Mic; 
  71.     default
  72.         return device_input_MIC_OFF; 
  73.     } 
  74.  
  75. status_t AudioHardware::setMode(int mode) 
  76.     sp<AudioStreamOutALSA> spOut; 
  77.     sp<AudioStreamInALSA> spIn; 
  78.     status_t status; 
  79.  
  80.     // Mutex acquisition order is always out -> in -> hw 
  81.     AutoMutex lock(mLock); 
  82.  
  83.     spOut = mOutput; 
  84.     // spOut is not 0 here only if the output is active 
  85.  
  86.     spIn = getActiveInput_l(); 
  87.     while (spIn != 0) { 
  88.         int cnt = spIn->prepareLock(); 
  89.         mLock.unlock(); 
  90.         spIn->lock(); 
  91.         mLock.lock(); 
  92.         // make sure that another thread did not change input state while the 
  93.         // mutex is released 
  94.         if ((spIn == getActiveInput_l()) && (cnt == spIn->standbyCnt())) { 
  95.             break
  96.         } 
  97.         spIn->unlock(); 
  98.         spIn = getActiveInput_l(); 
  99.     } 
  100.     // spIn is not 0 here only if the input is active 
  101.  
  102.     int prevMode = mMode; 
  103.     status = AudioHardwareBase::setMode(mode); 
  104.     LOGV("setMode() : new %d, old %d", mMode, prevMode); 
  105.     if (status == NO_ERROR) { 
  106.         bool modeNeedsCPActive = mMode == AudioSystem::MODE_IN_CALL || 
  107.                                     mMode == AudioSystem::MODE_RINGTONE; 
  108.         // activate call clock in radio when entering in call or ringtone mode 
  109.         if (modeNeedsCPActive) 
  110.         { 
  111.             if ((!mActivatedCP) && (mSecRilLibHandle) && (connectRILDIfRequired() == OK)) { 
  112.                 setCallClockSync(mRilClient, SOUND_CLOCK_START); 
  113.                 mActivatedCP = true
  114.             } 
  115.         } 
  116.  
  117.         if (mMode == AudioSystem::MODE_IN_CALL && !mInCallAudioMode) { 
  118.             if (spOut != 0) { 
  119.                 LOGV("setMode() in call force output standby"); 
  120.                 spOut->doStandby_l(); 
  121.             } 
  122.             if (spIn != 0) { 
  123.                 LOGV("setMode() in call force input standby"); 
  124.                 spIn->doStandby_l(); 
  125.             } 
  126.  
  127.             LOGV("setMode() openPcmOut_l()"); 
  128.             openPcmOut_l(); 
  129.             openMixer_l(); 
  130.             setInputSource_l(AUDIO_SOURCE_DEFAULT); 
  131.             setVoiceVolume_l(mVoiceVol); 
  132.             mInCallAudioMode = true
  133.         } 
  134.         if (mMode != AudioSystem::MODE_IN_CALL && mInCallAudioMode) { 
  135.             setInputSource_l(mInputSource); 
  136.             if (mMixer != NULL) { 
  137.                 TRACE_DRIVER_IN(DRV_MIXER_GET) 
  138.                 struct mixer_ctl *ctl= mixer_get_ctl_by_name(mMixer,"Playback Path"); 
  139.                 TRACE_DRIVER_OUT 
  140.                 if (ctl != NULL) { 
  141.                     LOGV("setMode() reset Playback Path to RCV"); 
  142.                     TRACE_DRIVER_IN(DRV_MIXER_SEL) 
  143.                     mixer_ctl_set_enum_by_string(ctl, "RCV"); 
  144.                     TRACE_DRIVER_OUT 
  145.                 } 
  146.             } 
  147.             LOGV("setMode() closePcmOut_l()"); 
  148.             closeMixer_l(); 
  149.             closePcmOut_l(); 
  150.  
  151.             if (spOut != 0) { 
  152.                 LOGV("setMode() off call force output standby"); 
  153.                 spOut->doStandby_l(); 
  154.             } 
  155.             if (spIn != 0) { 
  156.                 LOGV("setMode() off call force input standby"); 
  157.                 spIn->doStandby_l(); 
  158.             } 
  159.  
  160.             mInCallAudioMode = false
  161.         } 
  162.  
  163.         if (!modeNeedsCPActive) { 
  164.             if(mActivatedCP) 
  165.                 mActivatedCP = false
  166.         } 
  167.     } 
  168.  
  169.     return status; 

特别是setMode这个函数,涉及到整个音频系统的状态,一定要搞清楚

然后就是mixer的设置,还好wolfson在驱动里面实现了debugfs,可以在tty控制台输出

# mount-t debugfs none /d

打开debugfs,然后进入codec对应目录:


通过cat codec_reg可以查看wm8994所有寄存器,还可以实时修改,修改立刻生效

进入dapm目录可以查看所有mixer,我们配置的dapm必须在这里有值出现,否则不识别

我们可以cat每个mixer,查看其状态:

注意当前SPKL状态为OFF,表示其不在开启的route通路上,或者说你希望开启的包含SPKL的route还没有开启

你需要检查这个route是否完整,音频信号在route里面通过就像能电流在电线内部一样,必须要有输入输出,分支也必须是环路

关于dapm后面再说,这里补充一个要点,就是AudioHardware里面pcm_open()时写的那个config:

[cpp] view plaincopyprint?
  1. struct pcm_config config = { 
  2.     channels : 2, 
  3.     rate : AUDIO_HW_OUT_SAMPLERATE, 
  4.     period_size : AUDIO_HW_OUT_PERIOD_SZ, 
  5.     period_count : AUDIO_HW_OUT_PERIOD_CNT, 
  6.     format : PCM_FORMAT_S16_LE, 
  7.     start_threshold : 0, 
  8.     stop_threshold : 0, 
  9.     silence_threshold : 0, 
  10. }; 

我在最开始调试的时候在这里浪费了很多时间,关键就在这个config值得配置上,它和codec_dai,cpu_dai和snd_pcm_hardware都有关系

需要仔细检查,这个在snd_pcm_open的时候会做一系列rules检查,下一章我再重点讲一下!

更多0

 

0 0
原创粉丝点击