afe 高通_高通ASOC中的machine驱动

ASoC被分为Machine、Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的代码,再次引用上一节的内容:Machine驱动负责处理机器特有的一些控件和音频事件(例如,当播放音频时,需要先行打开一个放大器);单独的Platform和Codec驱动是不能工作的,它必须由Machine驱动把它们结合在一起才能完成整个设备的音频处理工作。

ASoC的一切都从Machine驱动开始,包括声卡的注册,绑定Platform和Codec驱动等等;(linux内核版本为3.10.28)

1. 注册Platform driver:

ASoC把声卡注册为Platform Device:

static int msm8x16_asoc_machine_probe(struct platform_device *pdev)

{

struct snd_soc_card *card;

struct msm8916_asoc_mach_data *pdata = NULL;

struct pinctrl *pinctrl;

const char *card_dev_id = "qcom,msm-snd-card-id";

const char *codec_type = "qcom,msm-codec-type";

const char *hs_micbias_type = "qcom,msm-hs-micbias-type";

const char *ext_pa = "qcom,msm-ext-pa";

const char *mclk = "qcom,msm-mclk-freq";

const char *spk_ext_pa = "qcom,msm-spk-ext-pa";

const char *ptr = NULL;

const char *type = NULL;

const char *ext_pa_str = NULL;

int num_strings;

int ret, id, i;

pr_err("'msm8x16_asoc_machine_probe ......");

pdata = devm_kzalloc(&pdev->dev,

sizeof(struct msm8916_asoc_mach_data), GFP_KERNEL);

if (!pdata) {

dev_err(&pdev->dev, "Can't allocate msm8x16_asoc_mach_data\n");

ret = -ENOMEM;

goto err1;

}

pdata->vaddr_gpio_mux_spkr_ctl =

ioremap(LPASS_CSR_GP_IO_MUX_SPKR_CTL , );

if (!pdata->vaddr_gpio_mux_spkr_ctl) {

pr_err("%s ioremap failure for addr %x",

__func__, LPASS_CSR_GP_IO_MUX_SPKR_CTL);

ret = -ENOMEM;

goto err;

}

pdata->vaddr_gpio_mux_mic_ctl =

ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL , );

if (!pdata->vaddr_gpio_mux_mic_ctl) {

pr_err("%s ioremap failure for addr %x",

__func__, LPASS_CSR_GP_IO_MUX_MIC_CTL);

ret = -ENOMEM;

goto err;

}

pdata->vaddr_gpio_mux_pcm_ctl =

ioremap(LPASS_CSR_GP_LPAIF_PRI_PCM_PRI_MODE_MUXSEL, );

if (!pdata->vaddr_gpio_mux_pcm_ctl) {

pr_err("%s ioremap failure for addr %x",

__func__,

LPASS_CSR_GP_LPAIF_PRI_PCM_PRI_MODE_MUXSEL);

ret = -ENOMEM;

goto err;

}

ret = of_property_read_u32(pdev->dev.of_node, card_dev_id, &id);

if (ret) {

dev_err(&pdev->dev,

"%s: missing %s in dt node\n", __func__, card_dev_id);

goto err;

}

pdev->id = id;

if (!pdev->dev.of_node) {

dev_err(&pdev->dev, "No platform supplied from device tree\n");

ret = -EINVAL;

goto err;

}

ret = of_property_read_u32(pdev->dev.of_node, mclk, &id);

if (ret) {

dev_err(&pdev->dev,

"%s: missing %s in dt node\n", __func__, mclk);

id = DEFAULT_MCLK_RATE;

}

pdata->mclk_freq = id;

pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node,

spk_ext_pa, );

if (pdata->spk_ext_pa_gpio < ) {

dev_dbg(&pdev->dev,

"%s: missing %s in dt node\n", __func__, spk_ext_pa);

} else {

if (gpio_is_valid(pdata->spk_ext_pa_gpio)) {

ret = gpio_request(pdata->spk_ext_pa_gpio, "spk_ext_pa_gpio");

if(ret) {

pr_err("spk ext pa gpio request failed");

goto err;

}

ret = gpio_direction_output(pdata->spk_ext_pa_gpio, );

if(ret) {

pr_err("set_direction for spk ext pa gpio failed\n");

goto err;

}

} else {

pr_err("%s: Invaild external_speaker gpio: %d", __func__, pdata->spk_ext_pa_gpio);

ret = -EINVAL;

goto err;

}

}

ret = of_property_read_string(pdev->dev.of_node, codec_type, &ptr);

if (ret) {

dev_err(&pdev->dev,

"%s: missing %s in dt node\n", __func__, codec_type);

goto err;

}

if (pdev->id >= MAX_SND_CARDS) {

dev_err(&pdev->dev, "Sound Card parsed is wrong, id=%d\n",

pdev->id);

ret = -EINVAL;

goto err;

}

if (!strcmp(ptr, "external")) {

dev_info(&pdev->dev, "external codec is configured\n");

pdata->codec_type = ;

/*Populate external codec TLMM configs*/

ret = populate_ext_snd_card_dt_data(pdev);

if (ret < ) {

dev_err(&pdev->dev, "error finding the DT\n"

"params ret=%d\n", ret);

goto err;

}

card = populate_ext_snd_card_dailinks(pdev);

if (!card) {

dev_err(&pdev->dev, "%s: Card uninitialized\n",

__func__);

ret = -EPROBE_DEFER;

goto err;

}

} else {

card = populate_ext_snd_card_dailinks(pdev);

if (!card) {

dev_err(&pdev->dev, "%s: Card uninitialized\n",

__func__);

ret = -EPROBE_DEFER;

goto err;

}

dev_info(&pdev->dev, "default codec configured\n");

pdata->codec_type = ;

num_strings = of_property_count_strings(pdev->dev.of_node,

ext_pa);

if (num_strings < ) {

dev_err(&pdev->dev,

"%s: missing %s in dt node or length is incorrect\n",

__func__, ext_pa);

goto err;

}

for (i = ; i < num_strings; i++) {

ret = of_property_read_string_index(pdev->dev.of_node,

ext_pa, i, &ext_pa_str);

if (ret) {

dev_err(&pdev->dev,

"%s:of read string %s i %d error %d\n",

__func__, ext_pa, i, ret);

goto err;

}

if (!strcmp(ext_pa_str, "primary"))

pdata->ext_pa = (pdata->ext_pa | PRI_MI2S_ID);

else if (!strcmp(ext_pa_str, "secondary"))

pdata->ext_pa = (pdata->ext_pa | SEC_MI2S_ID);

else if (!strcmp(ext_pa_str, "tertiary"))

pdata->ext_pa = (pdata->ext_pa | TER_MI2S_ID);

else if (!strcmp(ext_pa_str, "quaternary"))

pdata->ext_pa = (pdata->ext_pa | QUAT_MI2S_ID);

}

pr_debug("%s: ext_pa = %d\n", __func__, pdata->ext_pa);

pinctrl = devm_pinctrl_get(&pdev->dev);

if (IS_ERR(pinctrl)) {

pr_err("%s: Unable to get pinctrl handle\n",

__func__);

return -EINVAL;

}

pinctrl_info.pinctrl = pinctrl;

ret = get_cdc_gpio_lines(pinctrl, pdata->ext_pa);

if (ret < ) {

pr_err("%s: failed to ger the codec gpio's %d\n",

__func__, ret);

goto err;

}

}

ret = of_property_read_string(pdev->dev.of_node,

hs_micbias_type, &type);

if (ret) {

dev_err(&pdev->dev, "%s: missing %s in dt node\n",

__func__, hs_micbias_type);

goto err;

}

if (!strcmp(type, "external")) {

dev_dbg(&pdev->dev, "Headset is using external micbias\n");

mbhc_cfg.hs_ext_micbias = true;

} else {

dev_dbg(&pdev->dev, "Headset is using internal micbias\n");

mbhc_cfg.hs_ext_micbias = false;

}

/* initialize the mclk */

pdata->digital_cdc_clk.i2s_cfg_minor_version =

AFE_API_VERSION_I2S_CONFIG;

pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;

pdata->digital_cdc_clk.clk_root = ;

pdata->digital_cdc_clk.reserved = ;

/* initialize the digital codec core clk */

pdata->digital_cdc_core_clk.clk_set_minor_version =

AFE_API_VERSION_I2S_CONFIG;

pdata->digital_cdc_core_clk.clk_id =

Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE;

pdata->digital_cdc_core_clk.clk_freq_in_hz =

pdata->mclk_freq;

pdata->digital_cdc_core_clk.clk_attri =

Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;

pdata->digital_cdc_core_clk.clk_root =

Q6AFE_LPASS_CLK_ROOT_DEFAULT;

pdata->digital_cdc_core_clk.enable = ;

/* Initialize loopback mode to false */

pdata->lb_mode = false;

msm8x16_setup_hs_jack(pdev, pdata);

msm8x16_dt_parse_cap_info(pdev, pdata);

card->dev = &pdev->dev;

platform_set_drvdata(pdev, card);

snd_soc_card_set_drvdata(card, pdata);

ret = snd_soc_of_parse_card_name(card, "qcom,model");

if (ret)

goto err;

/* initialize timer */

INIT_DELAYED_WORK(&pdata->disable_mclk_work, disable_mclk);

mutex_init(&pdata->cdc_mclk_mutex);

atomic_set(&pdata->mclk_rsc_ref, );

atomic_set(&pdata->mclk_enabled, false);

atomic_set(&quat_mi2s_clk_ref, );

atomic_set(&auxpcm_mi2s_clk_ref, );

ret = snd_soc_of_parse_audio_routing(card,

"qcom,audio-routing");

if (ret)

goto err;

ret = msm8x16_populate_dai_link_component_of_node(card);

if (ret) {

ret = -EPROBE_DEFER;

goto err;

}

ret = snd_soc_register_card(card);

if (ret) {

dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",

ret);

goto err;

}

ret = core_get_adsp_ver();

if (ret < ) {

ret = -EPROBE_DEFER;

dev_info(&pdev->dev, "%s: Get adsp version failed (%d)\n",

__func__, ret);

goto err;

}

return ;

err:

if (pdata->vaddr_gpio_mux_spkr_ctl)

iounmap(pdata->vaddr_gpio_mux_spkr_ctl);

if (pdata->vaddr_gpio_mux_mic_ctl)

iounmap(pdata->vaddr_gpio_mux_mic_ctl);

if (pdata->vaddr_gpio_mux_pcm_ctl)

iounmap(pdata->vaddr_gpio_mux_pcm_ctl);

if(gpio_is_valid(pdata->spk_ext_pa_gpio))

gpio_free(pdata->spk_ext_pa_gpio);

devm_kfree(&pdev->dev, pdata);

err1:

return ret;

}

probe函数

DTS:

sound {

compatible = "qcom,msm8x16-audio-codec";

qcom,model = "msm8x16-skui-snd-card";

qcom,msm-snd-card-id = <>;

qcom,msm-ext-pa = "secondary";//"primary";

qcom,msm-codec-type = "internal";

qcom,msm-mbhc-hphl-swh = <>;

qcom,msm-mbhc-gnd-swh = <>;

qcom,msm-hs-micbias-type = "internal";

qcom,audio-routing =

"RX_BIAS", "MCLK",

"SPK_RX_BIAS", "MCLK",

"INT_LDO_H", "MCLK",

"MIC BIAS Internal1", "Handset Mic",

"MIC BIAS Internal2", "Headset Mic",

"MIC BIAS Internal1", "Secondary Mic",

"AMIC1", "MIC BIAS Internal1",

"AMIC2", "MIC BIAS Internal2",

"AMIC3", "MIC BIAS Internal1";

pinctrl-names = "cdc_lines_act",

"cdc_lines_sus",

"cdc_lines_sec_ext_act",

"cdc_lines_sec_ext_sus";

pinctrl- = ;

pinctrl- = ;

pinctrl- = ;

pinctrl- = ;

};

通过与DTS匹配,开始分析:

(1)、获取card的id:

ret = of_property_read_u32(pdev->dev.of_node, card_dev_id, &

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值