轉載於:http://blog.csdn.net/xiaokala_2011/article/details/8187927
做過高通平臺的msm7X27,msm7x27a,qrd8x25的audio驅動工作,關於android的audio流程網上可以查到很多內容,就總結下調試audio遇到的問題吧
這是整個audio tx,rx的流程。包括voice的,很清晰
一。關於耳機檢測及耳機按鍵檢測的問題
耳機插拔檢測是靠一個GPIO管腳檢測,有上拉電阻到vbat,沒有插耳機爲高電平,插入之後變低電平,報中斷
對應的gpio配置code在hs_gpio_cfg_s.c, 詳見數組hsi_gpio_info
關於OTHC,在qcom網站找到的解釋是這樣的
The one-touch headset detection feature is supported through the HSET_BIAS pin. The internal hardware in this device performs actions
based on the amount of current being drawn by the headset microphone. The HSET_BIAS output functions like a traditional microphone
bias except that it has some additional features to support one-touch headset detection.
而事實上,這幾個平臺都不是OTHC的。
msm7X27,msm7x27a平臺的耳機按鍵檢測是adc讀取值進行判斷的,qrd8625我們是利用micbias的電流進行判斷的
相關耳機插拔代碼及鍵值上報code見hs_othc.c
二。關於audio部分
1。多媒體音量的調節
如果是提高聲音,可以調整index值,降低音量的話,對計算出來的volume進行衰減就可以了
例如:衰減
if((stream == AudioSystem::MUSIC) && (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET))
{
volume = volume *0.30903;
}
android2.3跟android4.0volume的計算方式有差別,android2.3不管是哪種模式哪種媒體流用的是同一種計算方法,而android4.0有分開處理,默認的情況下,音量的曲線都不是很好,音量低部分變化不明顯,可以調整db/step
如在android4.0上
#if 0
const AudioPolicyManagerBase::VolumeCurvePoint
AudioPolicyManagerBase::sDefaultMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
{1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
};
#else
const AudioPolicyManagerBase::VolumeCurvePoint
AudioPolicyManagerBase::sDefaultMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
{1, -30.0f}, {20, -24.0f}, {60, -12.0f}, {100, 0.0f}
};
#endif
這是對media音量進行的調整,基本上是均勻變化的。基本思想就是,例如0.0f-(-12.0f)/100-60=(-12.0f)-(-24.0f)/60-20約等於-24.0f-(-30.f)/20-1
關於android音量控制,audioservice.java裏定義了每種媒體流的音量等級
For example:
/** @hide Maximum volume index values for audio streams */
/* private int[] MAX_STREAM_VOLUME = new int[] {
7, // STREAM_SYSTEM
7, // STREAM_RING
15, // STREAM_MUSIC
7, // STREAM_ALARM
7, // STREAM_NOTIFICATION
15, // STREAM_BLUETOOTH_SCO
7, // STREAM_SYSTEM_ENFORCED
15, // STREAM_DTMF
15 // STREAM_TTS
};*/
在audiomanager.java裏設定每種媒體流默認音量級別
For example
/** @hide Default volume index values for audio streams*/
/* private int[]DEFAULT_STREAM_VALUE = new int[] {
7, // STREAM_SYSTEM
7, // STREAM_RING
15, // STREAM_MUSIC
7, // STREAM_ALARM
7, // STREAM_NOTIFICATION
15, // STREAM_BLUETOOTH_SCO
7, // STREAM_SYSTEM_ENFORCED
15, // STREAM_DTMF
15 // STREAM_TTS
};*/
2. adjust peaker ---ringtone or media
可以調節MBADRC 的band改變頻響,這個調節的過程由硬件完成,硬件會給audiofilter.csv文件
The AudioFilter.csv file can be parsed in AudioHardware.cpp. The tuning parameters are pushed down to the ADSP when there is a device change.
1: Speaker,
2: Handset,
3: Headset
3。連接藍牙耳機,notification會斷續,播ringtone的時候,speaker聲音會斷續,not smoothly
將a2dpUsedForSonification()改爲false,聲音就不會從藍牙耳機裏播放。產生這種斷續現象的原因,在播放notification or ringtone的時候,藍牙跟speaker設備會同時打開,即使對於來電鈴音來說藍牙耳機會播放自己的提示音,但code裏還是會把這個設備打開,藍牙工作的時候需要喚醒,當聲音開始播放的時候,藍牙跟藍牙耳機的通信不是立刻建立。當播來電鈴聲的時候,來電鈴聲的數據會送到藍牙協議棧,但是這部分數據卻沒有送到藍牙耳機播放,是怎麼處理的不清楚,但是會影響到speaker播放ringtone
4. C網來電,拒接,鈴聲突然變大
The audio is played at 48KHz sample-rate so ringtone is also played 48KHz.
On CDMA call, vocder is acquired during the ringtone playback so ringtone is played at 8KHz sample-rate.
This issue is presented on only CDMA call.
To avoid this issue, need to undifne "FEATURE_RX_VOICE_OVER_HOST_PCM" in custXXXXX.h file(=AMSS side).
5.點擊開始錄像,開始提示音響後會有茲茲聲
playback跟capture動作切換造成
status_t AudioHardware::AudioStreamInMSM72xx::standby()
{
//mHardware->clearCurDevice();
//mHardware->doRouting(this);
mHardware->doRouting(NULL);
}
二。voice部分
1。關於藍牙打電話
由於qrd8625這個項目外掛了一個modem,着實被藍牙打電話折騰夠嗆,初期評估瞭解的情況不足也是導致調試時間花費比較多的原因
首先高通的默認code是主芯片做pcm的master,提供時鐘,而外掛的modem pcm口只能做slave,不能做master,那麼就需要將BT PCM做master,這樣才行進行通信,簡直爲難死人。提case給高通,確認BT可以做master後,開始着手調試。看到BT相關文件的那些tag啊,都要崩潰了。還好經過有一個周吧,把pcm的主時鐘給搞出來了,高通主芯片配成slave模式是有文檔的,這個可以參照80_VH558_1_D_AUX_PCM_MSM72xxA_MSM75xxA_MSM76xx_MSM7x27.pdf文檔去配。
其實BT做master也很容易配。改的很簡單,只是當時tag跟代碼裏對不上,用的藍牙芯片是WCN2243
文件vender\qcom\proprietary\bt\hci_qcomm_init\btqsoncnvmtags.c
static bt_qsoc_cfg_cst_element_type bt_qsoc_cfg_tag_44_bha_b0[] = \
{
0x2C, 0x01, 0x2C, 0x29,
0x2F, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
0xFF, 0x10, 0x02, 0x02, 0x01, 0x00, 0x14, 0x01,
0x06, 0x28, 0xA0, 0x62, 0x03, 0x64, 0x01, 0x01,
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0,
0xFF, 0x10, 0x02, 0x01, 0x00, 0x14, 0x01, 0x02,
0x03
};
要是改成master,需要將0x10改成0x00,這個是配置BT PCM是做master還是slave的寄存器,0x50這個寄存器,0x01代表的時鐘是25.6khz,這個詳見spec了,然後0x50就是2048khz,這個就是pcm工作的時鐘,幀同步信號是0xFF這個寄存器,FF代表了256分頻,正好是8k,幀同步信號跟pcm數據的採樣率一致。
接着就開始建立通話部分調試,上行有聲音,下行沒有聲音,需要將主芯片的PCM口四根線PCM_CLK,PCM_ASYNC,PCM_IN,PCM_OUT配成高阻態,高阻態的配置只需要配成gpio無拉輸入狀態即可。
2。藍牙打電話後手機完全沒有聲音
EVDO藍牙打電話後,掛斷電話手機完全沒有聲音,這個問題產生的原因就是BT PCMmaster,主芯片PCM slave造成的,再掛斷電話時有個提示音沒有播出來。從log看是申請不到內存,其實是能看到obtainBuffer timed out (is the CPU pegged?)這句log,後來高通給了patch,是在audio_out.c文件做的修改
將audio_write()函數中的進程睡眠喚醒方式做了修改
rc = wait_event_interruptible(audio->wait,
(frame->used == 0) || (audio->stopped));
改成
rc = wait_event_interruptible_timeout(audio->wait,
(frame->used == 0) || (audio->stopped),
msecs_to_jiffies(2000));
3.主micbias,hp micbias都是可以在AP側發rpc到cp請求使能or dis功能
主micbias enable/disable
adie_codec_write (ADIE_CODEC_EN3_R,
ADIE_CODEC_EN3_EN_MICBIAS_M,
ADIE_CODEC_EN3_MICBIAS_ENA_V/ADIE_CODEC_EN3_MICBIAS_DIS_V);
hp micbias,有這樣幾種狀態可以選擇
typedef enum
{
/**
* Headset module off
*/
PM_HSED_ENABLE_OFF,
/**
* enabled if TCXO signal is high
*/
PM_HSED_ENABLE_TCXO,
/**
* enabled if PWM or TCXO signal is high
*/
PM_HSED_ENABLE_PWM_TCXO,
/**
* enabled always
*/
PM_HSED_ENABLE_ALWAYS,
/**
* Invalid selection, used for range checking in PMIC APIs
*/
PM_HSED_ENABLE_TYPE__INVALID
}pm_hsed_enable_type;
4。錄音聲音小的問題
一是提高錄的聲音,二是提高播的聲音,但是調整播放相關的增益會影響其他音頻的輸出,最好能提高錄的聲音
在android4.0+qrd8625上可以這樣修改
可以增大codectxgain,tx volume
增大codectxgain
1 在vocdata.c
voc_data_codec_gain_ctrl_type* voc_data_get_codec_gain()
{
....
if (voc_check_in_call())
{
voc_data_codec_gain.codec_st_gain = voc_data_pcm_cal_ptr->codec_st_gain;
}
else
{
+ voc_data_codec_gain.codec_tx_gain =設置新的gain
#if defined(T_MSM7x27A) || defined(T_MSM7x25A)
if (voc_data_codec_inuse == VOC_CODEC_STEREO_HEADSET) {
// Hack for power measurement
voc_data_codec_gain.codec_rx_gain = VOC_DATA_UNITY_GAIN;
}
.....
}
增大tx volume
1 在vocproc.c
vocproc_state_return_type vocproc_state_active (void)
{
....
+if(!voc_check_in_call())
+ vocproc_set_volume_normal();
return (VOCPROC_STATE_SUCCESS);
}
2
extern vocproc_status_type vocproc_set_volume()
{
...
if( voc_check_in_call() == FALSE ) {
vocproc_vol.tx_comfort_noise_ena = QDSP_COMFORT_NOISE_DIS_V ;
+ vocproc_vol.tx_vol=設置新的gain
}
}
5。打開PGA通路
早期的FM通路是這樣走的,qrd8625平臺外掛modem電話免提模式是這樣做的
ADIE register configurations are located in ...\services\adsp\msmaud.h
To enable AUX_PGA loopback, you should logical OR the existing register values with the following for the specific audio path that you are working with.
ADIE_CODEC_EN5_R/*0x39*/, MSMAUD_ADIE_CODEC_EN5_ENABLE_BANDGAP_AUXPGA_LR/*0x0C*/, \
ADIE_CODEC_C7B_R/*0x43*/, MSMAUD_ADIE_CODEC_C7B_AUX_PGA_RXP_L_R/*0x2F*/, \
#define MSMAUD_ADIE_CODEC_C7B_AUX_PGA_RXP_L_R \
( MSMAUD_ADIE_CODEC_C7B_INIT | \
ADIE_CODEC_C7B_AUX_PGA_RXP_L_SEL_V | \
ADIE_CODEC_C7B_AUX_PGA_RXP_R_SEL_V | \
ADIE_CODEC_C7B_AUX_PGA_RXM_L_SEL_V | \
ADIE_CODEC_C7B_AUX_PGA_RXM_R_SEL_V | \
ADIE_CODEC_C7B_AUX_PGA_VOCM_LOCAL_V )
ADIE_CODEC_C10_R/*0x46*/, /*must be configured for whatever output you're going through. See the description for CODEC_C10 in the Software Interface Manual for your target*/
ADIE_CODEC_C10_R, (ADIE_CODEC_C10_HPH_L_ADD_LINEI_L_ENA_V \
| ADIE_CODEC_C10_HPH_R_ADD_LINEI_R_ENA_V)
可以參考芯片sepc關於codec寄存器的配置說明