diff options
Diffstat (limited to 'sound/soc/codecs/cs42xx8.c')
| -rw-r--r-- | sound/soc/codecs/cs42xx8.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 9c44b6283b8f..12fe9b3e2525 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver * * Copyright (C) 2014 Freescale Semiconductor, Inc. * * Author: Nicolin Chen <Guangyu.Chen@freescale.com> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. */ #include <linux/clk.h> @@ -43,6 +40,7 @@ struct cs42xx8_priv { struct clk *clk; bool slave_mode; + bool is_tdm_mode; unsigned long sysclk; u32 tx_channels; struct gpio_desc *gpiod_reset; @@ -217,6 +215,8 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); u32 val; + cs42xx8->is_tdm_mode = false; + /* Set DAI format */ switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_LEFT_J: @@ -230,6 +230,7 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, break; case SND_SOC_DAIFMT_DSP_A: val = CS42XX8_INTF_DAC_DIF_TDM | CS42XX8_INTF_ADC_DIF_TDM; + cs42xx8->is_tdm_mode = true; break; default: dev_err(component->dev, "unsupported dai format\n"); @@ -242,10 +243,10 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, /* Set master/slave audio interface */ switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: cs42xx8->slave_mode = true; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: cs42xx8->slave_mode = false; break; default: @@ -253,6 +254,11 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } + if (cs42xx8->is_tdm_mode && !cs42xx8->slave_mode) { + dev_err(component->dev, "TDM mode is supported only in slave mode\n"); + return -EINVAL; + } + return 0; } @@ -335,6 +341,19 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, cs42xx8->rate[tx] = params_rate(params); + if (cs42xx8->is_tdm_mode) { + if (cs42xx8->sysclk < 256 * cs42xx8->rate[tx]) { + dev_err(component->dev, "Unsupported sysclk in TDM mode\n"); + return -EINVAL; + } + + if (!tx && cs42xx8->rate[tx] > 100000) { + dev_err(component->dev, + "ADC does not support Quad-Speed Mode in TDM mode\n"); + return -EINVAL; + } + } + mask = CS42XX8_FUNCMOD_MFREQ_MASK; val = cs42xx8_ratios[i].mfreq; @@ -465,7 +484,7 @@ EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); static int cs42xx8_component_probe(struct snd_soc_component *component) { struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); switch (cs42xx8->drvdata->num_adcs) { case 3: @@ -606,7 +625,6 @@ err_enable: } EXPORT_SYMBOL_GPL(cs42xx8_probe); -#ifdef CONFIG_PM static int cs42xx8_runtime_resume(struct device *dev) { struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); @@ -665,14 +683,11 @@ static int cs42xx8_runtime_suspend(struct device *dev) return 0; } -#endif -const struct dev_pm_ops cs42xx8_pm = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) +EXPORT_GPL_DEV_PM_OPS(cs42xx8_pm) = { + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) }; -EXPORT_SYMBOL_GPL(cs42xx8_pm); MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver"); MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
