A10+Android4.0 音频驱动
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
A10+Android4.0 音频驱动 linux-3.0目录 make ARCH=arm menuconfig 进到内核配置界面,可以看到 知道我们的配置项名字,然后进 目录 :\lichee\linux-3.0\sound\soc 看Kconfig文件,可以看到 它只是打开了下面有关sun4i这个芯片的其他音频项。 所以,A10内置CODEC的驱动主要是在 \lichee\linux-3.0\sound\soc\sun4i sun4i-codec.c文件 sun4i_codec_probe 入口函数 kernel 层寄存器设置 在Kernel层定义了供amixer命令设置的内容。Kernel层寄存器设置分多种类型。 设备初始化函数sun4i_codec_probe中包含注册控制接口: snd_chip_codec_mixer_new()它添加控制接口 if ((err = snd_ctl_add(card, snd_ctl_new1(&codec_snd_controls_b_c[idx],clnt))) < 0) {return err; } 控制接口control对于许多开关(switch)和调节器(slider)而言应用相当广泛,它能从用户空间被存取。control的最主要用 途是mixer,所有的mixer 元素基于control 内核API 实现,在ALSA 中,control 用snd_kcontrol结构体描述(Y:\lichee\linux-3.0\sound\core\control.c)。 创建一个control,调用snd_ctl_add()和snd_ctl_new1()这两个函数来完成,这两个函数的原型为: int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol); struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,void *private_data); snd_ctl_new1()函数用于创建一个snd_kcontrol 并返回其指针,snd_ctl_add()函数用于将创建的snd_kcontrol 添加到对应的card 中。 A10的android4.0系统里,创建一个control控制各通道静音开关和音量大小,如下 static const struct snd_kcontrol_new codec_snd_controls_b_c[] = { //FOR B C VERSION CODEC_SINGLE("Master Playback Volume", SUN4I_DAC_ACTL,0,0x3f,0), CODEC_SINGLE("layback Switch", SUN4I_DAC_ACTL,6,1,0),//全局输出开关 CODEC_SINGLE("Capture Volume",SUN4I_ADC_ACTL,20,7,0),//录音音量 CODEC_SINGLE("Fm Volume",SUN4I_DAC_ACTL,23,7,0),//Fm 音量 CODEC_SINGLE("Line Volume",SUN4I_DAC_ACTL,26,1,0),//Line音量 CODEC_SINGLE("MicL Volume",SUN4I_ADC_ACTL,25,3,0),//mic左音量 CODEC_SINGLE("MicR Volume",SUN4I_ADC_ACTL,23,3,0),//mic右音量 CODEC_SINGLE("FmL Switch",SUN4I_DAC_ACTL,17,1,0),//Fm左开关 CODEC_SINGLE("FmR Switch",SUN4I_DAC_ACTL,16,1,0),//Fm右开关 CODEC_SINGLE("LineL Switch",SUN4I_DAC_ACTL,19,1,0),//Line左开关 CODEC_SINGLE("LineR Switch",SUN4I_DAC_ACTL,18,1,0),//Line右开关 CODEC_SINGLE("Ldac Left Mixer",SUN4I_DAC_ACTL,15,1,0), CODEC_SINGLE("Rdac Right Mixer",SUN4I_DAC_ACTL,14,1,0), CODEC_SINGLE("Ldac Right Mixer",SUN4I_DAC_ACTL,13,1,0), CODEC_SINGLE("Mic Input Mux",SUN4I_DAC_ACTL,9,15,0),//from bit 9 to bit 12.Mic(麦克风)输入静音 CODEC_SINGLE("ADC Input Mux",SUN4I_ADC_ACTL,17,7,0),//ADC输入静音 }; 创建一个新的control 至少需要实现snd_kcontrol_new 中的info()、get()和put()这3 个成员函数 数组codec_snd_controls_b_c[]内容单值元素 SOC_SINGLE()的 info()、get()、put()成员函数分别为: snd_soc_info_volsw ()、snd_soc_get_volsw ()和snd_soc_put_volsw (); 看原型定义 上面的数据就是分别代表这些意思的 (1) iface 字段定义了control 的类型,形式为SNDRV_CTL_ELEM_IFACE_XXX,通常是MIXER,对于不属于mixer的全局控制,使用CARD。如果关联于某类设 备,则使用HWDEP、 PCM、RAWMIDI、TIMER 或SEQUENCER。 (2)name 是名称标识字符串,control 的名称非常重要,因为control 的作用由名称来区分。 对于名称相同的control,则使用index 区分。name 定义的标准是“SOURCE DIRECTION FUNCTION”即“源、方向、功能” SOURCE 定义了control 的源,如“Master”“PCM““CD”和“Line”等, 例如上面表格,第三个 CODEC_SINGLE("Capture Volume",SUN4I_ADC_ACTL,20,7,0),//录音音量 它定义了name 是"Capture Volume" iface 和 name 可以通过上层输入amixer命令获取,如下: # # amixer controls numid=30,iface=MIXER,name=‘Capture Volume’ (3)info()函数用于获得该control 的详细信息,该函数必须填充传递给它的第二个参数。(4)get()函数用于得到control 的目前值并返回用户空间。 (5)put()函数用于从用户空间写入值,如果值被改变,该函数返回1,否则返回0;如果发生错误,该函数返回错误码。 get()和put()的第二个参数的类型为snd_ctl_elem_value。snd_ctl_elem_value结构体的内部也包含一个 由integer、integer64、enumerated 等组成的值联合体,它的具体类型依赖于control 的类型和info()函数。 对于get()和put()函数而言,如果control 有多于一个元素,即count>1,则每个元素都需要被返回或写入。在使用amixer命令配置声卡时都会调用到get()和put()函数。 get()和put()函数中讲判断设置值与原有值,判断是否配置寄存器。 连接平板到PC上,adb shell cd /dev/snd ls -l 可以看到 分别解释如下
通话相关的语音通路切换原理、震动接口目录:andorid4.0/hardware/libhardware_legacy/audio/AudioHardwareInterface.cpp 注册电话相关的接口 在status_t AudioHardwareBase::setMode(int mode)里调用 1、拨号调用到中间层的 android4.\frameworks\base\core\jni\android_media_AudioSystem.cpp android_media_AudioSystem_setPhoneState()函数 2、android4.0\frameworks\base\media\libmedia\AudioSystem.cpp AudioSystem::setPhoneState(state) get_audio_policy_service(); ---导入"media.audio_policy"服务 它是在 Service_manager.c (y:\android4.0\frameworks\base\cmds\servicemanager)这里实例化了 libmedia--AudioSystem.cpp -----setMode(2)... 进如到RIL的HW层 3、 调用 \android4.0\device\softwinner\common\hardware\audio audio_hw.c文件 ----> select_mode() 函数 两种情况 1)当打电话时 AudioSystem.cpp -----setMode(2) 则这里in_call=0 select_output_device() -> AUDIO_MODE_IN_CALL 的值是0x02 选择了 if ((adev->devices & AUDIO_DEVICE_OUT_ALL) == AUDIO_DEVICE_OUT_SPEAKER) { LOGE("select_mode() AUDIO_DEVICE_OUT_SPEAKER "); adev->devices = AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_IN_BUILTIN_MIC; } 2)当挂断电话时 AudioSystem.cpp -----setMode(0) 则这里in_call=1 ril_interface.c audio_hw.c文件 ----> select_output_device() //---全部静音 if (adev->mode == AUDIO_MODE_IN_CALL) { for (channel = 0; channel < 2; channel++) mixer_ctl_set_value(adev->mixer_ctls.voice_ul_volume, channel, 0); } 解析音频设备的功能,例如有没有蓝牙,或是在耳机上,还是走喇叭等 headset_on = adev->devices & AUDIO_DEVICE_OUT_WIRED_HEADSET; headphone_on = adev->devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; speaker_on = adev->devices & AUDIO_DEVICE_OUT_SPEAKER; earpiece_on = adev->devices & AUDIO_DEVICE_OUT_EARPIECE; bt_on = adev->devices & AUDIO_DEVICE_OUT_ALL_SCO; 进到 E/audio_hw_primary( 87): Entering IN_CALL state, in_call=0 E/audio_hw_primary( 87): Opening modem PCMs E/audio_hw_primary( 87): cannot open PCM modem DL stream: cannot set hw params: Invalid argument 2、挂机调用到中间层的 A、MIC送话到3G模组 PREG1 ---MIC1 输入放大 PREG1EN 0x28【29】=enable PREG1 0x28【25:26】= 00-0db 01-35db 10-38db 11 -41db MIC1OUT MIC1NEN 0x28[12] Mic1outn 1=enable ------------------------------------------------------------------------- //for Mic1out out put stream to the 3G module //MIC1OUT = enable 0X28[12] = 1 mixer_ctl_set_value(adev->mixer_ctls.Mic_Input_Mux, 0,0);//--0X10[9:12] = 0000 mixer_ctl_set_value(adev->mixer_ctls.Mic1out_Switch, 0,1);//--0X28[12] = 1 Mic1out = enable mixer_ctl_set_value(adev->mixer_ctls.MicL_Volume, 0,0);//--0X28[25:26] = 0x0 0db mixer_ctl_set_value(adev->mixer_ctls.MIC1_amplifier, 0,1);//-- 0x28【29】=enable MIC amplifier mixer_ctl_set_value(adev->mixer_ctls.MIC2_amplifier, 0,0);//-- mixer_ctl_set_value(adev->mixer_ctls.VMIC_Switch, 0,1);//-- 0x28[27] VMICEN 1= VMIC pin voltage enable ------------------------------------------------------------------------- B、3G模组送话到A10 Linein --adc --DAC --pa 0X10 DACAREN [31] Internal DAC Analog Right channel Enable DACAREN [30] Internal DAC Analog Left channel Enable MIXEN[29] Analog Output MP Enable LDACLMIXS[15] Left DAC to left output MP Mute 1=not mute RDACRMIXS[14] Right DAC to right output MP Mute LDACRMIXS[13] Left DAC to right output MP Mute LINEIN -->MP -->A 打开功放 gpio_write_one_pin_value(gpio_pa_shutdown, 1, "audio_pa_ctrl"); 关闭功放 gpio_write_one_pin_value(gpio_pa_shutdown, 0, "audio_pa_ctrl"); 电话呼入: RINGING ... LOGO如下 select_output_device()-> //--------------------------------------- 呼入与呼出,就是呼入在接通的时候,设了寄存器后,多了一个 [ 2359.420000] [audio codec] snd_sun4icard_playback_open [ 2359.430000] [audio codec] sun4i_codec_pcm_hw_params [ 2359.480000] snd_sun4i_codec_prepare,841 ,substream->stream = 0,->rate=48000 [ 2359.480000] [audio codec] codec_play_open [ 2359.490000] [audio codec] codec_play_start [ 2361.670000] [audio codec] codec_play_stop [ 2361.680000] [audio codec] snd_sun4icard_playback_close 这是因为多了这一个操作,后面的codec_play_stop 和snd_sun4icard_playback_close,关闭了功放的电。造成了呼入时没有声音。 接听电话流程 android4.0\packages\apps\phone\src\com\android\phone\InCallScreen.java internalAnswerCall() -->answerCall() packages/apps/phone/src/com/android/phone/PhoneUtils.java answerCall()函数 在 X:\sumeipai\android4.0\device\softwinner\common\hardware\audio audio_hw.c 控制驱动的接口 static int adev_open(const hw_module_t* module, const char* name, {} X:\sumeipai\lichee\linux-3.0\sound\soc\sun4i sun4i-codec.c 写对应的接口static const struct snd_kcontrol_new codec_snd_controls_b_c[] = { } 设置默认输入/出 |
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:22 天前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献6条内容
所有评论(0)