123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726 |
- /* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * 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.
- *
- */
- #include <linux/clk.h>
- #include <linux/err.h>
- #include <linux/gpio.h>
- #include <linux/mfd/pmic8058.h>
- #include <linux/mfd/pmic8901.h>
- #include <linux/platform_device.h>
- #include <linux/regulator/consumer.h>
- #include <linux/delay.h>
- #include <mach/mpp.h>
- #include <sound/core.h>
- #include <sound/soc.h>
- #include <sound/soc-dapm.h>
- #include <sound/soc-dsp.h>
- #include <sound/pcm.h>
- #include <asm/mach-types.h>
- #include "msm-pcm-routing.h"
- #include "../codecs/wm8903.h"
- #define MSM_GPIO_CLASS_D0_EN 80
- #define MSM_GPIO_CLASS_D1_EN 81
- #define MSM_CDC_MIC_I2S_MCLK 108
- static int msm8660_spk_func;
- static int msm8660_headset_func;
- static int msm8660_headphone_func;
- static struct clk *mic_bit_clk;
- static struct clk *spkr_osr_clk;
- static struct clk *spkr_bit_clk;
- static struct clk *wm8903_mclk;
- static int rx_hw_param_status;
- static int tx_hw_param_status;
- /* Platform specific logic */
- enum {
- GET_ERR,
- SET_ERR,
- ENABLE_ERR,
- NONE
- };
- enum {
- FUNC_OFF,
- FUNC_ON,
- };
- static struct wm8903_vdd {
- struct regulator *reg_id;
- const char *name;
- u32 voltage;
- } wm8903_vdds[] = {
- { NULL, "8058_l16", 1800000 },
- { NULL, "8058_l0", 1200000 },
- { NULL, "8058_s3", 1800000 },
- };
- static void classd_amp_pwr(int enable)
- {
- int rc;
- pr_debug("%s, enable = %d\n", __func__, enable);
- if (enable) {
- /* currently external PA isn't used for LINEOUTL */
- rc = gpio_request(MSM_GPIO_CLASS_D0_EN, "CLASSD0_EN");
- if (rc) {
- pr_err("%s: spkr PA gpio %d request failed\n",
- __func__, MSM_GPIO_CLASS_D0_EN);
- return;
- }
- gpio_direction_output(MSM_GPIO_CLASS_D0_EN, 1);
- gpio_set_value_cansleep(MSM_GPIO_CLASS_D0_EN, 1);
- rc = gpio_request(MSM_GPIO_CLASS_D1_EN, "CLASSD1_EN");
- if (rc) {
- pr_err("%s: spkr PA gpio %d request failed\n",
- __func__, MSM_GPIO_CLASS_D1_EN);
- return;
- }
- gpio_direction_output(MSM_GPIO_CLASS_D1_EN, 1);
- gpio_set_value_cansleep(MSM_GPIO_CLASS_D1_EN, 1);
- } else {
- gpio_set_value_cansleep(MSM_GPIO_CLASS_D0_EN, 0);
- gpio_free(MSM_GPIO_CLASS_D0_EN);
- gpio_set_value_cansleep(MSM_GPIO_CLASS_D1_EN, 0);
- gpio_free(MSM_GPIO_CLASS_D1_EN);
- }
- }
- static void extern_poweramp_on(void)
- {
- pr_debug("%s: enable stereo spkr amp\n", __func__);
- classd_amp_pwr(1);
- }
- static void extern_poweramp_off(void)
- {
- pr_debug("%s: disable stereo spkr amp\n", __func__);
- classd_amp_pwr(0);
- }
- static int msm8660_wm8903_powerup(void)
- {
- int rc = 0, index, stage = NONE;
- struct wm8903_vdd *vdd = NULL;
- for (index = 0; index < ARRAY_SIZE(wm8903_vdds); index++) {
- vdd = &wm8903_vdds[index];
- vdd->reg_id = regulator_get(NULL, vdd->name);
- if (IS_ERR(vdd->reg_id)) {
- pr_err("%s: Unable to get %s\n", __func__, vdd->name);
- stage = GET_ERR;
- rc = -ENODEV;
- break;
- }
- rc = regulator_set_voltage(vdd->reg_id,
- vdd->voltage, vdd->voltage);
- if (rc) {
- pr_err("%s: unable to set %s voltage to %dV\n",
- __func__, vdd->name, vdd->voltage);
- stage = SET_ERR;
- break;
- }
- rc = regulator_enable(vdd->reg_id);
- if (rc) {
- pr_err("%s:failed to enable %s\n", __func__, vdd->name);
- stage = ENABLE_ERR;
- break;
- }
- }
- if (index != ARRAY_SIZE(wm8903_vdds)) {
- if (stage != GET_ERR) {
- vdd = &wm8903_vdds[index];
- regulator_put(vdd->reg_id);
- vdd->reg_id = NULL;
- }
- while (index--) {
- vdd = &wm8903_vdds[index];
- regulator_disable(vdd->reg_id);
- regulator_put(vdd->reg_id);
- vdd->reg_id = NULL;
- }
- }
- return rc;
- }
- static void msm8660_wm8903_powerdown(void)
- {
- int index = ARRAY_SIZE(wm8903_vdds);
- struct wm8903_vdd *vdd = NULL;
- while (index--) {
- vdd = &wm8903_vdds[index];
- if (vdd->reg_id) {
- regulator_disable(vdd->reg_id);
- regulator_put(vdd->reg_id);
- }
- }
- }
- static int msm8660_wm8903_enable_mclk(int enable)
- {
- int ret = 0;
- if (enable) {
- ret = gpio_request(MSM_CDC_MIC_I2S_MCLK, "I2S_Clock");
- if (ret != 0) {
- pr_err("%s: failed to request GPIO\n", __func__);
- return ret;
- }
- wm8903_mclk = clk_get_sys(NULL, "i2s_mic_osr_clk");
- if (IS_ERR(wm8903_mclk)) {
- pr_err("Failed to get i2s_mic_osr_clk\n");
- gpio_free(MSM_CDC_MIC_I2S_MCLK);
- return IS_ERR(wm8903_mclk);
- }
- /* Master clock OSR 256 */
- clk_set_rate(wm8903_mclk, 48000 * 256);
- ret = clk_prepare_enable(wm8903_mclk);
- if (ret != 0) {
- pr_err("Unable to enable i2s_mic_osr_clk\n");
- gpio_free(MSM_CDC_MIC_I2S_MCLK);
- clk_put(wm8903_mclk);
- return ret;
- }
- } else {
- if (wm8903_mclk) {
- clk_disable_unprepare(wm8903_mclk);
- clk_put(wm8903_mclk);
- gpio_free(MSM_CDC_MIC_I2S_MCLK);
- wm8903_mclk = NULL;
- }
- }
- return ret;
- }
- static int msm8660_wm8903_prepare(void)
- {
- int ret = 0;
- ret = msm8660_wm8903_powerup();
- if (ret) {
- pr_err("Unable to powerup wm8903\n");
- return ret;
- }
- ret = msm8660_wm8903_enable_mclk(1);
- if (ret) {
- pr_err("Unable to enable mclk to wm8903\n");
- return ret;
- }
- return ret;
- }
- static void msm8660_wm8903_unprepare(void)
- {
- msm8660_wm8903_powerdown();
- msm8660_wm8903_enable_mclk(0);
- }
- static int msm8660_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
- {
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int rate = params_rate(params), ret = 0;
- pr_debug("Enter %s rate = %d\n", __func__, rate);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (rx_hw_param_status)
- return 0;
- /* wm8903 run @ LRC*256 */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, rate * 256,
- SND_SOC_CLOCK_IN);
- snd_soc_dai_digital_mute(codec_dai, 0);
- if (ret < 0) {
- pr_err("can't set rx codec clk configuration\n");
- return ret;
- }
- clk_set_rate(wm8903_mclk, rate * 256);
- /* set as slave mode CPU */
- clk_set_rate(spkr_bit_clk, 0);
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
- rx_hw_param_status++;
- } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- if (tx_hw_param_status)
- return 0;
- clk_set_rate(wm8903_mclk, rate * 256);
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, rate * 256,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- pr_err("can't set tx codec clk configuration\n");
- return ret;
- }
- clk_set_rate(mic_bit_clk, 0);
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
- tx_hw_param_status++;
- }
- return 0;
- }
- static int msm8660_i2s_startup(struct snd_pcm_substream *substream)
- {
- int ret = 0;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- pr_debug("Enter %s\n", __func__);
- /* ON Dragonboard, I2S between wm8903 and CPU is shared by
- * CODEC_SPEAKER and CODEC_MIC therefore CPU only can operate
- * as input SLAVE mode.
- */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* config WM8903 in Mater mode */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBM_CFM |
- SND_SOC_DAIFMT_I2S);
- if (ret != 0) {
- pr_err("codec_dai set_fmt error\n");
- return ret;
- }
- /* config CPU in SLAVE mode */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
- if (ret != 0) {
- pr_err("cpu_dai set_fmt error\n");
- return ret;
- }
- spkr_osr_clk = clk_get_sys(NULL, "i2s_spkr_osr_clk");
- if (IS_ERR(spkr_osr_clk)) {
- pr_err("Failed to get i2s_spkr_osr_clk\n");
- return PTR_ERR(spkr_osr_clk);
- }
- clk_set_rate(spkr_osr_clk, 48000 * 256);
- ret = clk_prepare_enable(spkr_osr_clk);
- if (ret != 0) {
- pr_err("Unable to enable i2s_spkr_osr_clk\n");
- clk_put(spkr_osr_clk);
- return ret;
- }
- spkr_bit_clk = clk_get_sys(NULL, "i2s_spkr_bit_clk");
- if (IS_ERR(spkr_bit_clk)) {
- pr_err("Failed to get i2s_spkr_bit_clk\n");
- clk_disable_unprepare(spkr_osr_clk);
- clk_put(spkr_osr_clk);
- return PTR_ERR(spkr_bit_clk);
- }
- clk_set_rate(spkr_bit_clk, 0);
- ret = clk_prepare_enable(spkr_bit_clk);
- if (ret != 0) {
- pr_err("Unable to enable i2s_spkr_bit_clk\n");
- clk_disable_unprepare(spkr_osr_clk);
- clk_put(spkr_osr_clk);
- clk_put(spkr_bit_clk);
- return ret;
- }
- } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- /* config WM8903 in Mater mode */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBM_CFM |
- SND_SOC_DAIFMT_I2S);
- if (ret != 0) {
- pr_err("codec_dai set_fmt error\n");
- return ret;
- }
- /* config CPU in SLAVE mode */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
- if (ret != 0) {
- pr_err("codec_dai set_fmt error\n");
- return ret;
- }
- mic_bit_clk = clk_get_sys(NULL, "i2s_mic_bit_clk");
- if (IS_ERR(mic_bit_clk)) {
- pr_err("Failed to get i2s_mic_bit_clk\n");
- return PTR_ERR(mic_bit_clk);
- }
- clk_set_rate(mic_bit_clk, 0);
- ret = clk_prepare_enable(mic_bit_clk);
- if (ret != 0) {
- pr_err("Unable to enable i2s_mic_bit_clk\n");
- clk_put(mic_bit_clk);
- return ret;
- }
- }
- return ret;
- }
- static void msm8660_i2s_shutdown(struct snd_pcm_substream *substream)
- {
- pr_debug("Enter %s\n", __func__);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
- substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- tx_hw_param_status = 0;
- rx_hw_param_status = 0;
- if (spkr_bit_clk) {
- clk_disable_unprepare(spkr_bit_clk);
- clk_put(spkr_bit_clk);
- spkr_bit_clk = NULL;
- }
- if (spkr_osr_clk) {
- clk_disable_unprepare(spkr_osr_clk);
- clk_put(spkr_osr_clk);
- spkr_osr_clk = NULL;
- }
- if (mic_bit_clk) {
- clk_disable_unprepare(mic_bit_clk);
- clk_put(mic_bit_clk);
- mic_bit_clk = NULL;
- }
- }
- }
- static void msm8660_ext_control(struct snd_soc_codec *codec)
- {
- /* set the enpoints to their new connetion states */
- if (msm8660_spk_func == FUNC_ON)
- snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
- else
- snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
- /* set the enpoints to their new connetion states */
- if (msm8660_headset_func == FUNC_ON)
- snd_soc_dapm_enable_pin(&codec->dapm, "Headset Jack");
- else
- snd_soc_dapm_disable_pin(&codec->dapm, "Headset Jack");
- /* set the enpoints to their new connetion states */
- if (msm8660_headphone_func == FUNC_ON)
- snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
- else
- snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
- /* signal a DAPM event */
- snd_soc_dapm_sync(&codec->dapm);
- }
- static int msm8660_get_spk(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- ucontrol->value.integer.value[0] = msm8660_spk_func;
- return 0;
- }
- static int msm8660_set_spk(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- pr_debug("%s()\n", __func__);
- if (msm8660_spk_func == ucontrol->value.integer.value[0])
- return 0;
- msm8660_spk_func = ucontrol->value.integer.value[0];
- msm8660_ext_control(codec);
- return 1;
- }
- static int msm8660_get_hs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- ucontrol->value.integer.value[0] = msm8660_headset_func;
- return 0;
- }
- static int msm8660_set_hs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- pr_debug("%s()\n", __func__);
- if (msm8660_headset_func == ucontrol->value.integer.value[0])
- return 0;
- msm8660_headset_func = ucontrol->value.integer.value[0];
- msm8660_ext_control(codec);
- return 1;
- }
- static int msm8660_get_hph(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- ucontrol->value.integer.value[0] = msm8660_headphone_func;
- return 0;
- }
- static int msm8660_set_hph(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- pr_debug("%s()\n", __func__);
- if (msm8660_headphone_func == ucontrol->value.integer.value[0])
- return 0;
- msm8660_headphone_func = ucontrol->value.integer.value[0];
- msm8660_ext_control(codec);
- return 1;
- }
- static int msm8660_spkramp_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *k, int event)
- {
- if (SND_SOC_DAPM_EVENT_ON(event))
- extern_poweramp_on();
- else
- extern_poweramp_off();
- return 0;
- }
- static struct snd_soc_ops machine_ops = {
- .startup = msm8660_i2s_startup,
- .shutdown = msm8660_i2s_shutdown,
- .hw_params = msm8660_i2s_hw_params,
- };
- static const struct snd_soc_dapm_widget msm8660_dapm_widgets[] = {
- SND_SOC_DAPM_SPK("Ext Spk", msm8660_spkramp_event),
- SND_SOC_DAPM_MIC("Headset Jack", NULL),
- SND_SOC_DAPM_MIC("Headphone Jack", NULL),
- /* to fix a bug in wm8903.c, where audio doesn't function
- * after suspend/resume
- */
- SND_SOC_DAPM_SUPPLY("CLK_SYS_ENA", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0),
- };
- static const struct snd_soc_dapm_route audio_map[] = {
- /* Match with wm8903 codec line out pin */
- {"Ext Spk", NULL, "LINEOUTL"},
- {"Ext Spk", NULL, "LINEOUTR"},
- /* Headset connects to IN3L with Bias */
- {"IN3L", NULL, "Mic Bias"},
- {"Mic Bias", NULL, "Headset Jack"},
- /* Headphone connects to IN3R with Bias */
- {"IN3R", NULL, "Mic Bias"},
- {"Mic Bias", NULL, "Headphone Jack"},
- {"ADCL", NULL, "CLK_SYS_ENA"},
- {"ADCR", NULL, "CLK_SYS_ENA"},
- {"DACL", NULL, "CLK_SYS_ENA"},
- {"DACR", NULL, "CLK_SYS_ENA"},
- };
- static const char *cmn_status[] = {"Off", "On"};
- static const struct soc_enum msm8660_enum[] = {
- SOC_ENUM_SINGLE_EXT(2, cmn_status),
- };
- static const struct snd_kcontrol_new wm8903_msm8660_controls[] = {
- SOC_ENUM_EXT("Speaker Function", msm8660_enum[0], msm8660_get_spk,
- msm8660_set_spk),
- SOC_ENUM_EXT("Headset Function", msm8660_enum[0], msm8660_get_hs,
- msm8660_set_hs),
- SOC_ENUM_EXT("Headphone Function", msm8660_enum[0], msm8660_get_hph,
- msm8660_set_hph),
- };
- static int msm8660_audrx_init(struct snd_soc_pcm_runtime *rtd)
- {
- struct snd_soc_codec *codec = rtd->codec;
- int err;
- snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
- snd_soc_dapm_enable_pin(&codec->dapm, "CLK_SYS_ENA");
- err = snd_soc_add_controls(codec, wm8903_msm8660_controls,
- ARRAY_SIZE(wm8903_msm8660_controls));
- if (err < 0)
- return err;
- snd_soc_dapm_new_controls(&codec->dapm, msm8660_dapm_widgets,
- ARRAY_SIZE(msm8660_dapm_widgets));
- snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_sync(&codec->dapm);
- return 0;
- }
- static int pri_i2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
- struct snd_pcm_hw_params *params)
- {
- struct snd_interval *rate = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_RATE);
- rate->min = rate->max = 48000;
- return 0;
- }
- /*
- * LPA Needs only RX BE DAI links.
- * Hence define seperate BE list for lpa
- */
- static const char *lpa_mm_be[] = {
- LPASS_BE_PRI_I2S_RX,
- };
- static struct snd_soc_dsp_link lpa_fe_media = {
- .supported_be = lpa_mm_be,
- .num_be = ARRAY_SIZE(lpa_mm_be),
- .fe_playback_channels = 2,
- .fe_capture_channels = 1,
- .trigger = {
- SND_SOC_DSP_TRIGGER_POST,
- SND_SOC_DSP_TRIGGER_POST
- },
- };
- static const char *mm1_be[] = {
- LPASS_BE_PRI_I2S_RX,
- LPASS_BE_PRI_I2S_TX,
- LPASS_BE_HDMI,
- };
- static struct snd_soc_dsp_link fe_media = {
- .supported_be = mm1_be,
- .num_be = ARRAY_SIZE(mm1_be),
- .fe_playback_channels = 2,
- .fe_capture_channels = 1,
- .trigger = {
- SND_SOC_DSP_TRIGGER_POST, SND_SOC_DSP_TRIGGER_POST},
- };
- /* Digital audio interface glue - connects codec <---> CPU */
- static struct snd_soc_dai_link msm8660_dai[] = {
- /* FrontEnd DAI Links */
- {
- .name = "MSM8660 Media",
- .stream_name = "MultiMedia",
- .cpu_dai_name = "MultiMedia1",
- .platform_name = "msm-pcm-dsp",
- .dynamic = 1,
- .dsp_link = &fe_media,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
- },
- {
- .name = "MSM8660 Media2",
- .stream_name = "MultiMedia2",
- .cpu_dai_name = "MultiMedia2",
- .platform_name = "msm-pcm-dsp",
- .dynamic = 1,
- .dsp_link = &fe_media,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
- },
- /* Backend DAI Links */
- {
- .name = LPASS_BE_PRI_I2S_RX,
- .stream_name = "Primary I2S Playback",
- .cpu_dai_name = "msm-dai-q6.0",
- .platform_name = "msm-pcm-routing",
- .codec_name = "wm8903-codec.3-001a",
- .codec_dai_name = "wm8903-hifi",
- .no_pcm = 1,
- .be_hw_params_fixup = pri_i2s_be_hw_params_fixup,
- .ops = &machine_ops,
- .init = &msm8660_audrx_init,
- .be_id = MSM_BACKEND_DAI_PRI_I2S_RX
- },
- {
- .name = LPASS_BE_PRI_I2S_TX,
- .stream_name = "Primary I2S Capture",
- .cpu_dai_name = "msm-dai-q6.1",
- .platform_name = "msm-pcm-routing",
- .codec_name = "wm8903-codec.3-001a",
- .codec_dai_name = "wm8903-hifi",
- .no_pcm = 1,
- .ops = &machine_ops,
- .be_hw_params_fixup = pri_i2s_be_hw_params_fixup,
- .be_id = MSM_BACKEND_DAI_PRI_I2S_TX
- },
- /* LPA frontend DAI link*/
- {
- .name = "MSM8660 LPA",
- .stream_name = "LPA",
- .cpu_dai_name = "MultiMedia3",
- .platform_name = "msm-pcm-lpa",
- .dynamic = 1,
- .dsp_link = &lpa_fe_media,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
- },
- /* HDMI backend DAI link */
- {
- .name = LPASS_BE_HDMI,
- .stream_name = "HDMI Playback",
- .cpu_dai_name = "msm-dai-q6.8",
- .platform_name = "msm-pcm-routing",
- .codec_name = "msm-stub-codec.1",
- .codec_dai_name = "msm-stub-rx",
- .no_codec = 1,
- .no_pcm = 1,
- .be_hw_params_fixup = pri_i2s_be_hw_params_fixup,
- .be_id = MSM_BACKEND_DAI_HDMI_RX
- },
- };
- struct snd_soc_card snd_soc_card_msm8660 = {
- .name = "msm8660-snd-card",
- .dai_link = msm8660_dai,
- .num_links = ARRAY_SIZE(msm8660_dai),
- };
- static struct platform_device *msm_snd_device;
- static int __init msm_audio_init(void)
- {
- int ret = 0;
- if (machine_is_msm8x60_dragon()) {
- /* wm8903 audio codec needs to power up and mclk existing
- before it's probed */
- ret = msm8660_wm8903_prepare();
- if (ret) {
- pr_err("failed to prepare wm8903 audio codec\n");
- return ret;
- }
- msm_snd_device = platform_device_alloc("soc-audio", 0);
- if (!msm_snd_device) {
- pr_err("Platform device allocation failed\n");
- msm8660_wm8903_unprepare();
- return -ENOMEM;
- }
- platform_set_drvdata(msm_snd_device, &snd_soc_card_msm8660);
- ret = platform_device_add(msm_snd_device);
- if (ret) {
- platform_device_put(msm_snd_device);
- msm8660_wm8903_unprepare();
- return ret;
- }
- }
- return ret;
- }
- module_init(msm_audio_init);
- static void __exit msm_audio_exit(void)
- {
- msm8660_wm8903_unprepare();
- platform_device_unregister(msm_snd_device);
- }
- module_exit(msm_audio_exit);
- MODULE_DESCRIPTION("ALSA SoC MSM8660");
- MODULE_LICENSE("GPL v2");
|