--- zzzz-none-000/linux-3.10.107/sound/soc/ux500/mop500_ab8500.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/sound/soc/ux500/mop500_ab8500.c 2021-02-04 17:41:59.000000000 +0000 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ #include "ux500_pcm.h" #include "ux500_msp_dai.h" +#include "mop500_ab8500.h" #include "../codecs/ab8500-codec.h" #define TX_SLOT_MONO 0x0008 @@ -43,6 +45,12 @@ static unsigned int tx_slots = DEF_TX_SLOTS; static unsigned int rx_slots = DEF_RX_SLOTS; +/* Configuration consistency parameters */ +static DEFINE_MUTEX(mop500_ab8500_params_lock); +static unsigned long mop500_ab8500_usage; +static int mop500_ab8500_rate; +static int mop500_ab8500_channels; + /* Clocks */ static const char * const enum_mclk[] = { "SYSCLK", @@ -125,9 +133,9 @@ static int mclk_input_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); struct mop500_ab8500_drvdata *drvdata = - snd_soc_card_get_drvdata(codec->card); + snd_soc_card_get_drvdata(card); ucontrol->value.enumerated.item[0] = drvdata->mclk_sel; @@ -137,9 +145,9 @@ static int mclk_input_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); struct mop500_ab8500_drvdata *drvdata = - snd_soc_card_get_drvdata(codec->card); + snd_soc_card_get_drvdata(card); unsigned int val = ucontrol->value.enumerated.item[0]; if (val > (unsigned int)MCLK_ULPCLK) @@ -160,16 +168,6 @@ SOC_ENUM_EXT("Master Clock Select", soc_enum_mclk, mclk_input_control_get, mclk_input_control_put), - /* Digital interface - Clocks */ - SOC_SINGLE("Digital Interface Master Generator Switch", - AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENMASTGEN, - 1, 0), - SOC_SINGLE("Digital Interface 0 Bit-clock Switch", - AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK0, - 1, 0), - SOC_SINGLE("Digital Interface 1 Bit-clock Switch", - AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK1, - 1, 0), SOC_DAPM_PIN_SWITCH("Headset Left"), SOC_DAPM_PIN_SWITCH("Headset Right"), SOC_DAPM_PIN_SWITCH("Earpiece"), @@ -193,7 +191,7 @@ /* ASoC */ -int mop500_ab8500_startup(struct snd_pcm_substream *substream) +static int mop500_ab8500_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -202,7 +200,7 @@ snd_soc_card_get_drvdata(rtd->card)); } -void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) +static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct device *dev = rtd->card->dev; @@ -216,7 +214,7 @@ rx_slots = DEF_RX_SLOTS; } -int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, +static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -240,6 +238,21 @@ substream->name, substream->number); + /* Ensure configuration consistency between DAIs */ + mutex_lock(&mop500_ab8500_params_lock); + if (mop500_ab8500_usage) { + if (mop500_ab8500_rate != params_rate(params) || + mop500_ab8500_channels != params_channels(params)) { + mutex_unlock(&mop500_ab8500_params_lock); + return -EBUSY; + } + } else { + mop500_ab8500_rate = params_rate(params); + mop500_ab8500_channels = params_channels(params); + } + __set_bit(cpu_dai->id, &mop500_ab8500_usage); + mutex_unlock(&mop500_ab8500_params_lock); + channels = params_channels(params); switch (params_format(params)) { @@ -277,21 +290,9 @@ SND_SOC_DAIFMT_GATED; } - ret = snd_soc_dai_set_fmt(codec_dai, fmt); - if (ret < 0) { - dev_err(dev, - "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", - __func__, ret); + ret = snd_soc_runtime_set_dai_fmt(rtd, fmt); + if (ret) return ret; - } - - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); - if (ret < 0) { - dev_err(dev, - "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n", - __func__, ret); - return ret; - } /* Setup TDM-slots */ @@ -338,9 +339,22 @@ return 0; } +static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + + mutex_lock(&mop500_ab8500_params_lock); + __clear_bit(cpu_dai->id, &mop500_ab8500_usage); + mutex_unlock(&mop500_ab8500_params_lock); + + return 0; +} + struct snd_soc_ops mop500_ab8500_ops[] = { { .hw_params = mop500_ab8500_hw_params, + .hw_free = mop500_ab8500_hw_free, .startup = mop500_ab8500_startup, .shutdown = mop500_ab8500_shutdown, } @@ -348,7 +362,7 @@ int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &rtd->card->dapm; struct device *dev = rtd->card->dev; struct mop500_ab8500_drvdata *drvdata; int ret; @@ -358,6 +372,10 @@ /* Create driver private-data struct */ drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata), GFP_KERNEL); + + if (!drvdata) + return -ENOMEM; + snd_soc_card_set_drvdata(rtd->card, drvdata); /* Setup clocks */ @@ -385,7 +403,7 @@ drvdata->mclk_sel = MCLK_ULPCLK; /* Add controls */ - ret = snd_soc_add_codec_controls(codec, mop500_ab8500_ctrls, + ret = snd_soc_add_card_controls(rtd->card, mop500_ab8500_ctrls, ARRAY_SIZE(mop500_ab8500_ctrls)); if (ret < 0) { pr_err("%s: Failed to add machine-controls (%d)!\n", @@ -393,23 +411,23 @@ return ret; } - ret = snd_soc_dapm_disable_pin(&codec->dapm, "Earpiece"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Left"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Right"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Left"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Right"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 1"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 2"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 1"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 2"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Left"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Right"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 1"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 2"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 3"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 4"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 5"); - ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 6"); + ret = snd_soc_dapm_disable_pin(dapm, "Earpiece"); + ret |= snd_soc_dapm_disable_pin(dapm, "Speaker Left"); + ret |= snd_soc_dapm_disable_pin(dapm, "Speaker Right"); + ret |= snd_soc_dapm_disable_pin(dapm, "LineOut Left"); + ret |= snd_soc_dapm_disable_pin(dapm, "LineOut Right"); + ret |= snd_soc_dapm_disable_pin(dapm, "Vibra 1"); + ret |= snd_soc_dapm_disable_pin(dapm, "Vibra 2"); + ret |= snd_soc_dapm_disable_pin(dapm, "Mic 1"); + ret |= snd_soc_dapm_disable_pin(dapm, "Mic 2"); + ret |= snd_soc_dapm_disable_pin(dapm, "LineIn Left"); + ret |= snd_soc_dapm_disable_pin(dapm, "LineIn Right"); + ret |= snd_soc_dapm_disable_pin(dapm, "DMic 1"); + ret |= snd_soc_dapm_disable_pin(dapm, "DMic 2"); + ret |= snd_soc_dapm_disable_pin(dapm, "DMic 3"); + ret |= snd_soc_dapm_disable_pin(dapm, "DMic 4"); + ret |= snd_soc_dapm_disable_pin(dapm, "DMic 5"); + ret |= snd_soc_dapm_disable_pin(dapm, "DMic 6"); return ret; }