diff options
Diffstat (limited to 'sound/soc/sprd/vbc-r2p0-sprd-codec-v4.h')
| -rwxr-xr-x | sound/soc/sprd/vbc-r2p0-sprd-codec-v4.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/sound/soc/sprd/vbc-r2p0-sprd-codec-v4.h b/sound/soc/sprd/vbc-r2p0-sprd-codec-v4.h new file mode 100755 index 00000000..a2f26a0a --- /dev/null +++ b/sound/soc/sprd/vbc-r2p0-sprd-codec-v4.h @@ -0,0 +1,218 @@ +/* + * sound/soc/sprd/vbc-r2p0-sprd-codec-v4.h + * + * Copyright (C) 2013 SpreadTrum Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +static const struct snd_kcontrol_new vbc_r2p0_codec_controls[] = { + BOARD_CODEC_FUNC("Speaker Function", BOARD_FUNC_SPKL), + BOARD_CODEC_FUNC("Speaker2 Function", BOARD_FUNC_SPKR), + BOARD_CODEC_FUNC("Earpiece Function", BOARD_FUNC_EAR), + BOARD_CODEC_FUNC("HeadPhone Function", BOARD_FUNC_HP), + BOARD_CODEC_FUNC("Line Function", BOARD_FUNC_LINE), + BOARD_CODEC_FUNC("Mic Function", BOARD_FUNC_MIC), + BOARD_CODEC_FUNC("Aux Mic Function", BOARD_FUNC_AUXMIC), + BOARD_CODEC_FUNC("HP Mic Function", BOARD_FUNC_HP_MIC), + BOARD_CODEC_FUNC("DMic Function", BOARD_FUNC_DMIC), + BOARD_CODEC_FUNC("DMic1 Function", BOARD_FUNC_DMIC1), + BOARD_CODEC_FUNC("Digital FM Function", BOARD_FUNC_DFM), + + BOARD_CODEC_MUTE("Speaker Mute", BOARD_FUNC_SPKL), + BOARD_CODEC_MUTE("Speaker2 Mute", BOARD_FUNC_SPKR), + BOARD_CODEC_MUTE("Earpiece Mute", BOARD_FUNC_EAR), + BOARD_CODEC_MUTE("HeadPhone Mute", BOARD_FUNC_HP), +}; + +/* board supported audio map */ +static const struct snd_soc_dapm_route vbc_r2p0_codec_map[] = { + {"HeadPhone Jack", NULL, "HEAD_P_L"}, + {"HeadPhone Jack", NULL, "HEAD_P_R"}, + {"Ext Spk", NULL, "AOL"}, + {"Ext Spk2", NULL, "AOR"}, + {"Ext Ear", NULL, "EAR"}, + {"MIC", NULL, "Mic Jack"}, + {"AUXMIC", NULL, "Aux Mic Jack"}, + {"HPMIC", NULL, "HP Mic Jack"}, + {"AIL", NULL, "Line Jack"}, + {"AIR", NULL, "Line Jack"}, + {"DMIC", NULL, "DMic Jack"}, + {"DMIC1", NULL, "DMic1 Jack"}, + + {"inter HP PA", NULL, "HP PA"}, + {"inter Spk PA", NULL, "Spk PA"}, + + /* VBC -- SPRD-CODEC */ + {"Aud input", NULL, "AD Clk"}, + {"Aud1 input", NULL, "AD Clk"}, + + {"Aud input", NULL, "Digital ADCL Switch"}, + {"Aud input", NULL, "Digital ADCR Switch"}, + + {"Aud1 input", NULL, "Digital ADC1L Switch"}, + {"Aud1 input", NULL, "Digital ADC1R Switch"}, + +}; + +extern struct sprd_dfm_priv dfm; +static int dfm_rate(struct snd_pcm_hw_params *params) +{ + +#ifdef CONFIG_SND_SOC_VBC_SRC_SAMPLE_RATE + dfm.hw_rate = CONFIG_SND_SOC_VBC_SRC_SAMPLE_RATE; +#else + dfm.hw_rate = params_rate(params); +#endif + + if (dfm.hw_rate == 8000) + dfm.sample_rate = 8000; + else { +#ifdef CONFIG_SND_SOC_SPRD_VBC_SRC_OPEN + dfm.sample_rate = 44100; +#else + dfm.sample_rate = params_rate(params); +#endif + } + sp_asoc_pr_dbg("%s: hw_rate:%d, sample_rate:%d \n", + __func__, dfm.hw_rate, dfm.sample_rate); + + if (dfm.hw_rate != dfm.sample_rate) { + struct snd_interval *rate = + hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval dfm_rates; + dfm_rates.min = dfm.sample_rate; + dfm_rates.max = dfm.sample_rate; + dfm_rates.openmin = dfm_rates.openmax = 0; + dfm_rates.integer = 0; + + return snd_interval_refine(rate, &dfm_rates); + } + return 0; +} + +static int dfm_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + + sp_asoc_pr_dbg("%s \n", __func__); + dfm_rate(params); + return 0; +} + +static const struct snd_soc_ops dfm_ops = { + .hw_params = dfm_params, +}; + +static struct snd_soc_dai_link vbc_r2p0_codec_dai[] = { + { + .name = "vbc(r2)-codec(v4)-ap", + .stream_name = "HiFi", + + .codec_name = "sprd-codec", + .platform_name = "sprd-pcm-audio", + .cpu_dai_name = "vbc-r2p0", + .codec_dai_name = "sprd-codec-i2s", + .ignore_suspend = 1, + }, +#ifdef CONFIG_SND_SOC_SPRD_VAUDIO + { + .name = "vbc(r2)-codec(v4)-dsp", + .stream_name = "Voice", + + .codec_name = "sprd-codec", + .platform_name = "sprd-pcm-audio", + .cpu_dai_name = "vaudio", + .codec_dai_name = "sprd-codec-vaudio", + .ignore_suspend = 1, + }, +#endif + { + .name = "aux-captrue", + .stream_name = "AuxRecord", + + .codec_name = "sprd-codec", + .platform_name = "sprd-pcm-audio", + .cpu_dai_name = "vbc-r2p0-ad23", + .codec_dai_name = "codec-i2s-ext", + .ignore_suspend = 1, + }, +#ifdef CONFIG_SND_SOC_SPRD_VAUDIO + { + .name = "aux-dsp-captrue", + .stream_name = "AuxDSPCaptrue", + + .codec_name = "sprd-codec", + .platform_name = "sprd-pcm-audio", + .cpu_dai_name = "vaudio-ad23", + .codec_dai_name = "codec-vaudio-ext", + .ignore_suspend = 1, + }, +#endif + { + .name = "vbc(r2)-dfm", + .stream_name = "Dfm", + + .codec_name = "sprd-codec", + .platform_name = "sprd-pcm-audio", + .cpu_dai_name = "vbc-dfm", + .codec_dai_name = "sprd-codec-fm", + .ops = &dfm_ops, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_card vbc_r2p0_codec_card = { + .name = "sprdphone", + .dai_link = vbc_r2p0_codec_dai, + .num_links = ARRAY_SIZE(vbc_r2p0_codec_dai), + .owner = THIS_MODULE, + + .controls = vbc_r2p0_codec_controls, + .num_controls = ARRAY_SIZE(vbc_r2p0_codec_controls), + .dapm_widgets = sprd_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sprd_codec_dapm_widgets), + .dapm_routes = vbc_r2p0_codec_map, + .num_dapm_routes = ARRAY_SIZE(vbc_r2p0_codec_map), + .late_probe = board_late_probe, +}; + +static int vbc_r2p0_codec_probe(struct platform_device *pdev) +{ + return sprd_asoc_probe(pdev, &vbc_r2p0_codec_card); +} + +#ifdef CONFIG_OF +static const struct of_device_id vbc_r2p0_codec_of_match[] = { + {.compatible = "sprd,vbc-r2p0-sprd-codec",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, vbc_r2p0_codec_of_match); +#endif + +static struct platform_driver vbc_r2p0_codec_driver = { + .driver = { + .name = "vbc-r2p0-sprd-codec", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = of_match_ptr(vbc_r2p0_codec_of_match), + }, + .probe = vbc_r2p0_codec_probe, + .remove = sprd_asoc_remove, + .shutdown = sprd_asoc_shutdown, +}; + +static int __init vbc_r2p0_codec_init(void) +{ + return platform_driver_register(&vbc_r2p0_codec_driver); +} + +late_initcall_sync(vbc_r2p0_codec_init); |
