Android 音訊驅動分析--A10
阿新 • • 發佈:2018-12-31
A10+Android4.0 音訊驅動(樹莓派II 原始碼)
linux-3.0目錄
make ARCH=arm menuconfig
進到核心配置介面,可以看到
知道我們的配置項名字,然後進
目錄 :\lichee\linux-3.0\sound\soc
看Kconfig檔案,可以看到
所以,A10內建CODEC的驅動主要是在
\lichee\linux-3.0\sound\soc\sun4i
sun4i-codec.c檔案
sun4i_codec_probe 入口函式
return err;
}
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"
(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
註冊電話相關的介面
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[] = {
}
設定預設輸入/出
linux-3.0目錄
make ARCH=arm menuconfig
進到核心配置介面,可以看到
知道我們的配置項名字,然後進
目錄 :\lichee\linux-3.0\sound\soc
看Kconfig檔案,可以看到
-
config SOUND_SUN4I
-
tristate "SOUND driver for sun4i"
-
depends on ARCH_SUN4I
-
help
-
SOUND driver for sun4i
-
if SOUND_SUN4I
-
source "sound/soc/sun4i/Kconfig"
-
source "sound/soc/sun4i/hdmiaudio/Kconfig"
-
source "sound/soc/sun4i/spdif/Kconfig"
-
source "sound/soc/sun4i/i2s/Kconfig"
- endif
所以,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 ();
看原型定義
-
#define CODEC_SINGLE(xname, reg, shift, max, invert)\
-
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
-
.info = snd_codec_info_volsw, .get = snd_codec_get_volsw,\
-
.put = snd_codec_put_volsw,\
-
.private_value = CODEC_SINGLE_VALUE(reg, shift, max, invert)
- }
(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
可以看到
-
[email protected]:/dev/snd # ls -l
-
ls -l
-
crw-rw---- system audio 116, 0 2012-05-04 14:40 controlC0
-
crw-rw---- system audio 116, 32 2012-05-04 14:40 controlC1
-
crwxrwxrwx system system 116, 24 2012-05-04 14:40 pcmC0D0c
-
crwxrwxrwx system system 116, 16 2012-05-04 14:40 pcmC0D0p
-
crw-rw---- system audio 116, 48 2012-05-04 14:40 pcmC1D0p
- crw-rw---- system audio 116, 33 2012-05-04 14:40 timer
- controlC0 –> 用於音效卡的控制,例如通道選擇,混音,麥克風的控制等
- controlC1 -> 用於音效卡的控制,例如通道選擇,混音,麥克風的控制等
- pcmC1D0p –> 用於播放的pcm裝置
- pcmC0D0c –〉 用於錄音的pcm裝置
- pcmC0D0p –〉 用於播放的pcm裝置
-
timer –〉 定時器
-
#define SNDRV_DEV_TYPE_RANGE_SIZE 0x1000
-
typedef int __bitwise snd_device_type_t;
-
#define SNDRV_DEV_TOPLEVEL ((__force snd_device_type_t) 0)
-
#define SNDRV_DEV_CONTROL ((__force snd_device_type_t) 1)
-
#define SNDRV_DEV_LOWLEVEL_PRE ((__force snd_device_type_t) 2)
-
#define SNDRV_DEV_LOWLEVEL_NORMAL ((__force snd_device_type_t) 0x1000)
-
#define SNDRV_DEV_PCM ((__force snd_device_type_t) 0x1001)
-
#define SNDRV_DEV_RAWMIDI ((__force snd_device_type_t) 0x1002)
-
#define SNDRV_DEV_TIMER ((__force snd_device_type_t) 0x1003)
-
#define SNDRV_DEV_SEQUENCER ((__force snd_device_type_t) 0x1004)
-
#define SNDRV_DEV_HWDEP ((__force snd_device_type_t) 0x1005)
-
#define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006)
-
#define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007)
-
#define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008)
-
#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009)
- #define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000)
通話相關的語音通路切換原理、震動介面目錄:andorid4.0/hardware/libhardware_legacy/audio/AudioHardwareInterface.cpp
註冊電話相關的介面
-
static const char* routingModeStrings[] =
-
{
-
"OUT OF RANGE",
-
"INVALID",
-
"CURRENT",
-
"NORMAL",
-
"RINGTONE",
-
"IN_CALL",
-
"IN_COMMUNICATION"
-
};
-
static const char* displayMode(int mode)
-
{
-
if ((mode < AudioSystem::MODE_INVALID) || (mode >= AudioSystem::NUM_MODES))
-
return routingModeStrings[0];
-
return routingModeStrings[mode+3];
- }
-
status_t AudioHardwareBase::setMode(int mode)
-
{
-
#if LOG_ROUTING_CALLS
-
LOGD("setMode(%s)", displayMode(mode));
-
#endif
-
if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
-
return BAD_VALUE;
-
if (mMode == mode)
-
return ALREADY_EXISTS;
-
mMode = mode;
-
return NO_ERROR;
- }
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()函式
-
static boolean answerCall(Call ringing) {
-
log("answerCall(" + ringing + ")...");
-
final PhoneApp app = PhoneApp.getInstance();
-
app.getRinger().stopRing(); //-------我認為主要是因為在關鈴聲的時候,呼叫了
- codec_play_stop ,把 "audio_pa_ctrl"拉低了,所以沒有聲音輸出
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[] = {
}
設定預設輸入/出
-
/* These are values that never change */
-
struct route_setting defaults[] = {
-
// open dacpas
-
{
-
.ctl_name = MIXER_PLAYBACK_DACPAS,
-
.intval = 1,
-
},
-
{
-
.ctl_name = MIXER_PLAYBACK_PAMUTE_SWITCH,
-
.intval = 1,
-
},
-
// close capture
-
{
-
.ctl_name = MIXER_MIC2_AMPLIFIER_ENABLE,
-
.intval = 0,
-
},
-
{
-
.ctl_name = MIXER_ADCL_ENABLE,
-
.intval = 0,
-
},
-
{
-
.ctl_name = MIXER_ADCR_ENABLE,
-
.intval = 0,
-
},
-
{
-
.ctl_name = MIXER_MIC1_GAIN_VOLUME,
-
.intval = 0,
-
},
-
// to do ......
-
{
-
.ctl_name = MIXER_VMIC_ENABLE, // for ear phone dectect
-
.intval = 1,
-
},
-
{
-
.ctl_name = MIXER_MIC1_AMPLIFIER_ENABLE,
-
.intval = 1,
-
},
-
{
-
.ctl_name = NULL,
-
},
-
};