summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/cs42xx8.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/cs42xx8.c')
-rw-r--r--sound/soc/codecs/cs42xx8.c43
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.");