Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android下調試聲卡驅動之Machine部分

android下調試聲卡驅動之Machine部分

編輯:關於Android編程

本文介紹的代碼是在CPU(imx6)和Codec(wm8960)上做的調試並且Codec做主模式,在“概述篇”中提到Codec部分、

Platform部分代碼由設備原廠提供和系統提供,所以我們在聲卡調試中需要做的只有Machine部分,其他代碼在需要的情況下略做微

調即可,調試過程中還要注意在BSP文件裡配置好I2S(SSI和AUD復用)。

1、imx_hifi_hw_params函數介紹

static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
				     struct snd_pcm_hw_params *params)
{

	/* 設置Codec與CPU音頻數據通信格式為I2S,BLCK不反轉,Codec為主模式*/
	dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
		SND_SOC_DAIFMT_CBM_CFM;

	/*  set codec DAI configuration */
	ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
    if( ret < 0 ){
        printk( "%s: Codec DAI configuration error, %d\n", __func__, ret );
        return ret;
    }

	/*  set i.MX active slot mask */
	snd_soc_dai_set_tdm_slot(cpu_dai,
			channels == 1 ? 0xfffffffe : 0xfffffffc,
			channels == 1 ? 0xfffffffe : 0xfffffffc,
			2, 32);
	/* 設置CPU與Codec音頻數據通信格式為I2S,BLCK不反轉,CPU為從模式*/
	dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
		SND_SOC_DAIFMT_CBM_CFM;

	/*  set cpu DAI configuration */
	ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
    if( ret < 0 ){
        printk( "%s: AP DAI configuration error, %d\n", __func__, ret );
        return ret;
    }

	sample_rate = params_rate(params);
	switch (sample_rate) {
       case 44100:
        if (channels == 1) { // 根據通道數配置相關時鐘頻率(1:代表單通道)
            /* Mono mode */
            dacdiv = WM8960_DAC_DIV_2; /* 22.05 KHz */
            bclk = WM8960_BCLK_DIV_16;
        }
        else {
            /* Stereo Mode */
            dacdiv =WM8960_DAC_DIV_1; // 44.1 KHz,為設置采樣頻率(LRCK),配置Codec寄存器的值
            bclk = WM8960_BCLK_DIV_4; // 為設置BCLK頻率,配置Codec寄存器的值
			dclk = WM8960_DCLK_DIV_16;// 為設置D類放大器時鐘頻率,配置Codec寄存器的值
		}
        sysclk_div = WM8960_SYSCLK_DIV_2; // 為設置Codec的系統時鐘頻率,配置Codec寄存器的值
        pll_out = 11289600; // 設定PLL的頻率值
        break;
      default:
        printk("do not support this sample frequency");
        return -EINVAL;
    }

    /* 設置Codec的PLL頻率:11289600*/
	ret=snd_soc_dai_set_pll(codec_dai,1,0,priv->sysclk/2,pll_out);
    if( ret < 0 ){
        printk( "%s: AP codec pll error, %d\n", __func__, ret );
        return ret;
    }
	/* 設置Codec的系統時鐘:11289600*/
    ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_SYSCLKDIV, sysclk_div );
    if( ret < 0 ){
        printk( "%s: Codec SYSCLKDIV setting error, %d\n", __func__, ret );
        return ret;
    }
	/* 設置采樣頻率(LRCK)的時鐘,lrckclk= sysclk/1*256=44100 */
    ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_DACDIV, dacdiv);
    if( ret < 0 ){
        printk( "%s: Codec DACDIV setting error, %d\n", __func__, ret );
        return ret;
    }
	/* 設置D類放大器時鐘頻率:dclk= sysclk/16 */
	ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_DCLKDIV,dclk);
	if( ret < 0 ){
		printk( "%s: Codec DCLKDIV setting error, %d\n", __func__, ret );
		return ret;
	}
	/* 設置BCLK類放大器時鐘頻率:bitclk=sysclk/4 = 2822400 */
	ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_BCLKDIV, bclk); 
	if( ret < 0 ){
	printk( "%s: Codec WM8960_BCLKDIV setting error, %d\n", __func__, ret );
	return ret;
    }

    return 0;
}

2、snd_soc_dai_link結構體介紹

platform 連接 codec 與 cpu 的驅動時,需要通過內核函數結構體snd_soc_dai_link來設置兩邊的接口。

static struct snd_soc_dai_link imx_dai[] = {
	{
		.name = "HiFi",
		.stream_name = "HiFi",
		.codec_dai_name	= "wm8960-hifi",
		.codec_name	= "wm8960.1-001a", 
		/* wm8960.1-001a代表的是用I2C1來控制codec,其I2C地址為0x1a;I2CX, X代表的是0,1,2,開始 */
		.cpu_dai_name	= "imx-ssi.1",  
		/* 
		 * 代表的是同一個聲卡中的第一個設備與SSI1相連;I2SX X代表0,1,2;ssi.1代表SSI1。
		 * IMX6中的SSI接口有3對可以接著路I2S;三路SSI可以每路SSI 單獨作為一個聲卡,
		 * 也可以是一個聲卡包含多個設備; 
		 */
		.platform_name	= "imx-pcm-audio.1",
		/* 代表的連接接口與SSI來對應,用哪路SSI,其後面的數字就是幾。 */
		.init		= imx_wm8960_init,
		.ops		= &imx_hifi_ops,
	},
};

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved