1. 程式人生 > >Android底層開發之音訊輸入通道的軟硬體分析

Android底層開發之音訊輸入通道的軟硬體分析

Android底層開發之音訊輸入通道的軟硬體分析

        我們都知道耳機Mic整合在一直的那種四段耳機Mic插頭是Android裝置上比較常用。但是也會有分開的情況,比較如果在普通的PC機中裝Android系統,那麼就是這種情況。所以就有必要對音訊輸入通道的軟體硬體進行統一的分析一下,接下來分析一個例項。

        該裝置的硬體連線為:基於3157的模擬開關實現的 通道切換。

 

        裝置是完全靠硬體實現的,那麼就沒有軟體的什麼工作了。但是這並不是一個理想的實現方法,真下的實現方法應該是所有的Mic都是並行的,每個Mic通道都有一個使能管腳。讓系統來控制讓哪個Mic作為輸入。其實

rk616 audio程式碼中是有切換的程式碼的:

static int rk616_capture_path_put(struct snd_kcontrol *kcontrol,

                struct snd_ctl_elem_value *ucontrol)

{

        struct rk616_codec_priv *rk616 = rk616_priv;

        long int pre_path;

        if (!rk616) {

                printk("%s : rk616_priv is NULL\n", __func__);

                return -EINVAL;

        }

        if (rk616->capture_path == ucontrol->value.integer.value[0]){

                DBG("%s : capture_path is not changed!\n", __func__);

                return 0;

        }

        pre_path = rk616->capture_path;

        rk616->capture_path = ucontrol->value.integer.value[0];

        DBG("%s : set capture_path %ld, pre_path %ld\n", __func__,

                rk616->capture_path, pre_path);

        switch (rk616->capture_path) {

        case MIC_OFF:

                if (pre_path != MIC_OFF)

                        rk616_codec_power_down(RK616_CODEC_CAPTURE);

                break;

        case Main_Mic:

                if (pre_path == MIC_OFF)

                        rk616_codec_power_up(RK616_CODEC_CAPTURE);

#ifdef RK616_HPMIC_FROM_LINEIN

                snd_soc_write(codec, 0x848, 0x06); //MIXINL power up and unmute, MININL from MICMUX, MICMUX from BST_L

#endif

                rk616_set_gpio(RK616_CODEC_SET_MIC,GPIO_HIGH);

                break;

        case Hands_Free_Mic:

                if (pre_path == MIC_OFF)

                        rk616_codec_power_up(RK616_CODEC_CAPTURE);

#ifdef RK616_HPMIC_FROM_LINEIN

                snd_soc_write(codec, 0x848, 0x03); //MIXINL power up and unmute, MININL from MICMUX, MICMUX from IN3L

#endif

                rk616_set_gpio(RK616_CODEC_SET_MIC, GPIO_LOW);

                break;

        case BT_Sco_Mic:

                break;

        default:

                return -EINVAL;

        }

        return 0;

}

        硬體實現時會有這樣的問題,在使用BT SCO做為輸入時,Main Mic或者Hands Mic也會輸入。

如果需要可以這樣實現:

@@ -796,6 +796,7 @@ static struct rk616_platform_data rk616_pdata = {

        .hdmi_irq = RK30_PIN2_PD6,

        .spk_ctl_gpio = RK30_PIN2_PD7,

        .hp_ctl_gpio = INVALID_GPIO,

+       .mic_sel_gpio = RK30_PIN0_PD5,

 };

 #endif

切換Capture MIC PathRK30_PIN0_PD5的電平會隨之改變。

        我認為Mic輸入的理想處理方法是:

 

        文字說明:所有Mic通道都是並行的,且保留一個使能管腳,CPU可以自由控制各個通道的通斷。

        任何在硬體上進行通道調節都是畫蛇添足

        Android針對單獨的Mic 3.5mm jack目前還沒有準確的處理方式,因為在WiredAccessoryManager.java所示的支援的方式中還沒有針對單獨的Mic 3.5mm jack。也就是說核心檢測到什麼單獨的Mic插入也不知道如何告知Android系統,也或者是告知也無用。

耳機+Mic   BIT_HEADSET = (1 << 0);

耳機-Mic   BIT_HEADSET_NO_MIC = (1 << 1);

其它       BIT_USB_HEADSET_ANLG = (1 << 2);

其它       BIT_USB_HEADSET_DGTL = (1 << 3);

其它       BIT_HDMI_AUDIO = (1 << 4);

 

      使用分體式耳機表示是這樣的:

 

        只插入Mic,不插入耳機。

        我所說的 支援不完善 是指就算你核心確定硬體上插入的僅僅是一個獨立的Mic,那麼也不知道在/sys/class/switch/h2w/state中填寫一個什麼樣的數字來表示這種狀態