diff options
65 files changed, 2123 insertions, 918 deletions
diff --git a/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt b/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt index 92ac86f83822..f7f3b83da630 100644 --- a/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt +++ b/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt @@ -1,7 +1,8 @@ -MT8183 with MT6358, DA7219 and MAX98357 CODECS +MT8183 with MT6358, DA7219, MAX98357, and RT1015 CODECS Required properties: -- compatible : "mediatek,mt8183_da7219_max98357" +- compatible : "mediatek,mt8183_da7219_max98357" for MAX98357A codec + "mediatek,mt8183_da7219_rt1015" for RT1015 codec - mediatek,headset-codec: the phandles of da7219 codecs - mediatek,platform: the phandle of MT8183 ASoC platform diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index e98601eccfa3..2d35b08f0565 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -120,39 +120,21 @@ static int atmel_classd_cpu_dai_startup(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); + int err; regmap_write(dd->regmap, CLASSD_THR, 0x0); - return clk_prepare_enable(dd->pclk); -} - -static void atmel_classd_cpu_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); - - clk_disable_unprepare(dd->pclk); + err = clk_prepare_enable(dd->pclk); + if (err) + return err; + err = clk_prepare_enable(dd->gclk); + if (err) { + clk_disable_unprepare(dd->pclk); + return err; + } + return 0; } -static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = { - .startup = atmel_classd_cpu_dai_startup, - .shutdown = atmel_classd_cpu_dai_shutdown, -}; - -static struct snd_soc_dai_driver atmel_classd_cpu_dai = { - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_CLASSD_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &atmel_classd_cpu_dai_ops, -}; - -static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = { - .name = "atmel-classd", -}; - /* platform */ static int atmel_classd_platform_configure_dma(struct snd_pcm_substream *substream, @@ -306,31 +288,10 @@ static int atmel_classd_component_resume(struct snd_soc_component *component) return regcache_sync(dd->regmap); } -static struct snd_soc_component_driver soc_component_dev_classd = { - .probe = atmel_classd_component_probe, - .resume = atmel_classd_component_resume, - .controls = atmel_classd_snd_controls, - .num_controls = ARRAY_SIZE(atmel_classd_snd_controls), - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, -}; - -/* codec dai component */ -static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); - - return clk_prepare_enable(dd->gclk); -} - -static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai, - int mute) +static int atmel_classd_cpu_dai_digital_mute(struct snd_soc_dai *cpu_dai, + int mute) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; u32 mask, val; mask = CLASSD_MR_LMUTE_MASK | CLASSD_MR_RMUTE_MASK; @@ -373,13 +334,13 @@ static struct { }; static int -atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *codec_dai) +atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; int fs; int i, best, best_val, cur_val, ret; u32 mask, val; @@ -417,8 +378,8 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, } static void -atmel_classd_codec_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) +atmel_classd_cpu_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); @@ -426,10 +387,10 @@ atmel_classd_codec_dai_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(dd->gclk); } -static int atmel_classd_codec_dai_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) +static int atmel_classd_cpu_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; snd_soc_component_update_bits(component, CLASSD_MR, CLASSD_MR_LEN_MASK | CLASSD_MR_REN_MASK, @@ -439,10 +400,10 @@ static int atmel_classd_codec_dai_prepare(struct snd_pcm_substream *substream, return 0; } -static int atmel_classd_codec_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *codec_dai) +static int atmel_classd_cpu_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *cpu_dai) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; u32 mask, val; mask = CLASSD_MR_LEN_MASK | CLASSD_MR_REN_MASK; @@ -468,19 +429,16 @@ static int atmel_classd_codec_dai_trigger(struct snd_pcm_substream *substream, return 0; } -static const struct snd_soc_dai_ops atmel_classd_codec_dai_ops = { - .digital_mute = atmel_classd_codec_dai_digital_mute, - .startup = atmel_classd_codec_dai_startup, - .shutdown = atmel_classd_codec_dai_shutdown, - .hw_params = atmel_classd_codec_dai_hw_params, - .prepare = atmel_classd_codec_dai_prepare, - .trigger = atmel_classd_codec_dai_trigger, +static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = { + .startup = atmel_classd_cpu_dai_startup, + .shutdown = atmel_classd_cpu_dai_shutdown, + .digital_mute = atmel_classd_cpu_dai_digital_mute, + .hw_params = atmel_classd_cpu_dai_hw_params, + .prepare = atmel_classd_cpu_dai_prepare, + .trigger = atmel_classd_cpu_dai_trigger, }; -#define ATMEL_CLASSD_CODEC_DAI_NAME "atmel-classd-hifi" - -static struct snd_soc_dai_driver atmel_classd_codec_dai = { - .name = ATMEL_CLASSD_CODEC_DAI_NAME, +static struct snd_soc_dai_driver atmel_classd_cpu_dai = { .playback = { .stream_name = "Playback", .channels_min = 1, @@ -488,7 +446,18 @@ static struct snd_soc_dai_driver atmel_classd_codec_dai = { .rates = ATMEL_CLASSD_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = &atmel_classd_codec_dai_ops, + .ops = &atmel_classd_cpu_dai_ops, +}; + +static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = { + .name = "atmel-classd", + .probe = atmel_classd_component_probe, + .resume = atmel_classd_component_resume, + .controls = atmel_classd_snd_controls, + .num_controls = ARRAY_SIZE(atmel_classd_snd_controls), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; /* ASoC sound card */ @@ -517,9 +486,9 @@ static int atmel_classd_asoc_card_init(struct device *dev, dai_link->name = "CLASSD"; dai_link->stream_name = "CLASSD PCM"; - dai_link->codecs->dai_name = ATMEL_CLASSD_CODEC_DAI_NAME; + dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); - dai_link->codecs->name = dev_name(dev); + dai_link->codecs->name = "snd-soc-dummy"; dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; @@ -620,13 +589,6 @@ static int atmel_classd_probe(struct platform_device *pdev) return ret; } - ret = devm_snd_soc_register_component(dev, &soc_component_dev_classd, - &atmel_classd_codec_dai, 1); - if (ret) { - dev_err(dev, "could not register component: %d\n", ret); - return ret; - } - /* register sound card */ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) { diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index cb03c4f7324c..0a2e956232af 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c @@ -44,7 +44,7 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = { .buffer_bytes_max = 512 * 1024, }; -/** +/* * atmel_pcm_dma_irq: SSC interrupt handler for DMAENGINE enabled SSC * * We use DMAENGINE to send/receive data to/from SSC so this ISR is only to diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 5245826cd99d..c2b639928c69 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -147,32 +147,26 @@ static int atmel_pdmic_cpu_dai_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_component *component = cpu_dai->component; u32 val; + int ret; /* Clean the PDMIC Converted Data Register */ - return regmap_read(dd->regmap, PDMIC_CDR, &val); -} - -static const struct snd_soc_dai_ops atmel_pdmic_cpu_dai_ops = { - .startup = atmel_pdmic_cpu_dai_startup, - .shutdown = atmel_pdmic_cpu_dai_shutdown, - .prepare = atmel_pdmic_cpu_dai_prepare, -}; + ret = regmap_read(dd->regmap, PDMIC_CDR, &val); + if (ret < 0) + return 0; -#define ATMEL_PDMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) + ret = snd_soc_component_update_bits(component, PDMIC_CR, + PDMIC_CR_ENPDM_MASK, + PDMIC_CR_ENPDM_DIS << + PDMIC_CR_ENPDM_SHIFT); + if (ret < 0) + return ret; -static struct snd_soc_dai_driver atmel_pdmic_cpu_dai = { - .capture = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_KNOT, - .formats = ATMEL_PDMIC_FORMATS,}, - .ops = &atmel_pdmic_cpu_dai_ops, -}; + return 0; +} -static const struct snd_soc_component_driver atmel_pdmic_cpu_dai_component = { - .name = "atmel-pdmic", -}; +#define ATMEL_PDMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) /* platform */ #define ATMEL_PDMIC_MAX_BUF_SIZE (64 * 1024) @@ -355,27 +349,16 @@ static int atmel_pdmic_component_probe(struct snd_soc_component *component) return 0; } -static struct snd_soc_component_driver soc_component_dev_pdmic = { - .probe = atmel_pdmic_component_probe, - .controls = atmel_pdmic_snd_controls, - .num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls), - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, -}; - -/* codec dai component */ #define PDMIC_MR_PRESCAL_MAX_VAL 127 static int -atmel_pdmic_codec_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *codec_dai) +atmel_pdmic_cpu_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; unsigned int rate_min = substream->runtime->hw.rate_min; unsigned int rate_max = substream->runtime->hw.rate_max; int fs = params_rate(params); @@ -445,21 +428,10 @@ atmel_pdmic_codec_dai_hw_params(struct snd_pcm_substream *substream, return 0; } -static int atmel_pdmic_codec_dai_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) -{ - struct snd_soc_component *component = codec_dai->component; - - snd_soc_component_update_bits(component, PDMIC_CR, PDMIC_CR_ENPDM_MASK, - PDMIC_CR_ENPDM_DIS << PDMIC_CR_ENPDM_SHIFT); - - return 0; -} - -static int atmel_pdmic_codec_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *codec_dai) +static int atmel_pdmic_cpu_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *cpu_dai) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; u32 val; switch (cmd) { @@ -482,16 +454,16 @@ static int atmel_pdmic_codec_dai_trigger(struct snd_pcm_substream *substream, return 0; } -static const struct snd_soc_dai_ops atmel_pdmic_codec_dai_ops = { - .hw_params = atmel_pdmic_codec_dai_hw_params, - .prepare = atmel_pdmic_codec_dai_prepare, - .trigger = atmel_pdmic_codec_dai_trigger, +static const struct snd_soc_dai_ops atmel_pdmic_cpu_dai_ops = { + .startup = atmel_pdmic_cpu_dai_startup, + .shutdown = atmel_pdmic_cpu_dai_shutdown, + .prepare = atmel_pdmic_cpu_dai_prepare, + .hw_params = atmel_pdmic_cpu_dai_hw_params, + .trigger = atmel_pdmic_cpu_dai_trigger, }; -#define ATMEL_PDMIC_CODEC_DAI_NAME "atmel-pdmic-hifi" -static struct snd_soc_dai_driver atmel_pdmic_codec_dai = { - .name = ATMEL_PDMIC_CODEC_DAI_NAME, +static struct snd_soc_dai_driver atmel_pdmic_cpu_dai = { .capture = { .stream_name = "Capture", .channels_min = 1, @@ -499,7 +471,17 @@ static struct snd_soc_dai_driver atmel_pdmic_codec_dai = { .rates = SNDRV_PCM_RATE_KNOT, .formats = ATMEL_PDMIC_FORMATS, }, - .ops = &atmel_pdmic_codec_dai_ops, + .ops = &atmel_pdmic_cpu_dai_ops, +}; + +static const struct snd_soc_component_driver atmel_pdmic_cpu_dai_component = { + .name = "atmel-pdmic", + .probe = atmel_pdmic_component_probe, + .controls = atmel_pdmic_snd_controls, + .num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; /* ASoC sound card */ @@ -528,9 +510,9 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, dai_link->name = "PDMIC"; dai_link->stream_name = "PDMIC PCM"; - dai_link->codecs->dai_name = ATMEL_PDMIC_CODEC_DAI_NAME; + dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); - dai_link->codecs->name = dev_name(dev); + dai_link->codecs->name = "snd-soc-dummy"; dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; @@ -684,16 +666,6 @@ static int atmel_pdmic_probe(struct platform_device *pdev) return ret; } - /* register codec and codec dai */ - atmel_pdmic_codec_dai.capture.rate_min = rate_min; - atmel_pdmic_codec_dai.capture.rate_max = rate_max; - ret = devm_snd_soc_register_component(dev, &soc_component_dev_pdmic, - &atmel_pdmic_codec_dai, 1); - if (ret) { - dev_err(dev, "could not register component: %d\n", ret); - return ret; - } - /* register sound card */ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) { diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 0f18dfb85bfe..6a63e8797a0b 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -887,6 +887,7 @@ static int asoc_ssc_init(struct device *dev) /** * atmel_ssc_set_audio - Allocate the specified SSC for audio use. + * @ssc_id: SSD ID in [0, NUM_SSC_DEVICES[ */ int atmel_ssc_set_audio(int ssc_id) { diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 986a6308818b..946a70210f49 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -115,7 +115,8 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MAX98925 imply SND_SOC_MAX98926 imply SND_SOC_MAX98927 - imply SND_SOC_MAX98373 + imply SND_SOC_MAX98373_I2C + imply SND_SOC_MAX98373_SDW imply SND_SOC_MAX98390 imply SND_SOC_MAX9850 imply SND_SOC_MAX9860 @@ -868,8 +869,25 @@ config SND_SOC_MAX98927 depends on I2C config SND_SOC_MAX98373 + tristate + +config SND_SOC_MAX98373_I2C tristate "Maxim Integrated MAX98373 Speaker Amplifier" depends on I2C + select SND_SOC_MAX98373 + +config SND_SOC_MAX98373_SDW + tristate "Maxim Integrated MAX98373 Speaker Amplifier - SDW" + depends on SOUNDWIRE + select SND_SOC_MAX98373 + select REGMAP_SOUNDWIRE + help + Enable support for Maxim Integrated MAX98373 Soundwire + amplifier. MAX98373 supports either the MIPI SoundWire + compatible interface for audio and control data, or + the PCM interface for audio data and a standard I2C + interface for control data. Select this if MAX98373 is + connected via soundwire. config SND_SOC_MAX98390 tristate "Maxim Integrated MAX98390 Speaker Amplifier" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 47ae3cebb61e..0140c60db695 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -115,6 +115,8 @@ snd-soc-max98925-objs := max98925.o snd-soc-max98926-objs := max98926.o snd-soc-max98927-objs := max98927.o snd-soc-max98373-objs := max98373.o +snd-soc-max98373-i2c-objs := max98373-i2c.o +snd-soc-max98373-sdw-objs := max98373-sdw.o snd-soc-max98390-objs := max98390.o snd-soc-max9850-objs := max9850.o snd-soc-max9860-objs := max9860.o @@ -418,6 +420,8 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o +obj-$(CONFIG_SND_SOC_MAX98373_I2C) += snd-soc-max98373-i2c.o +obj-$(CONFIG_SND_SOC_MAX98373_SDW) += snd-soc-max98373-sdw.o obj-$(CONFIG_SND_SOC_MAX98390) += snd-soc-max98390.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index ea92007d1ef5..31a8c4162d20 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2126,7 +2126,7 @@ static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) dev_err(dai->component->dev, "%s: ERROR: The device is either a master or a slave.\n", __func__); - /* fall through */ + fallthrough; default: dev_err(dai->component->dev, "%s: ERROR: Unsupporter master mask 0x%x\n", diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 5ca9b744b7d8..fb006fc81653 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -642,7 +642,7 @@ static int adau1761_setup_digmic_jackdetect(struct snd_soc_component *component) ARRAY_SIZE(adau1761_jack_detect_controls)); if (ret) return ret; - /* fall through */ + fallthrough; case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes, ARRAY_SIZE(adau1761_no_dmic_routes)); @@ -693,7 +693,7 @@ static int adau1761_setup_headphone_mode(struct snd_soc_component *component) ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE, ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP | ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE); - /* fallthrough */ + fallthrough; case ADAU1761_OUTPUT_MODE_HEADPHONE: regmap_update_bits(adau->regmap, ADAU1761_PLAY_HP_RIGHT_VOL, ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP, diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index b6352de077b5..30e072c80ac1 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -385,7 +385,7 @@ static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai, case ADAU17X1_CLK_SRC_PLL_AUTO: if (!adau->mclk) return -EINVAL; - /* Fall-through */ + fallthrough; case ADAU17X1_CLK_SRC_PLL: is_pll = true; break; @@ -469,7 +469,7 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream, ret = adau17x1_auto_pll(dai, params); if (ret) return ret; - /* Fall-through */ + fallthrough; case ADAU17X1_CLK_SRC_PLL: freq = adau->pll_freq; break; diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index c4b9722c3d8f..4fd99280d7db 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -647,7 +647,7 @@ static int adav80x_set_pll(struct snd_soc_component *component, int pll_id, pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; break; } - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index d4d2f0d9231a..8d663e8d64c4 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -451,13 +451,13 @@ static int ak4613_set_bias_level(struct snd_soc_component *component, switch (level) { case SND_SOC_BIAS_ON: mgmt1 |= RSTN; - /* fall through */ + fallthrough; case SND_SOC_BIAS_PREPARE: mgmt1 |= PMADC | PMDAC; - /* fall through */ + fallthrough; case SND_SOC_BIAS_STANDBY: mgmt1 |= PMVR; - /* fall through */ + fallthrough; case SND_SOC_BIAS_OFF: default: break; diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 8d45c628e988..f23956cf4ed8 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -1053,11 +1053,13 @@ static const struct of_device_id cros_ec_codec_of_match[] = { MODULE_DEVICE_TABLE(of, cros_ec_codec_of_match); #endif +#ifdef CONFIG_ACPI static const struct acpi_device_id cros_ec_codec_acpi_id[] = { { "GOOG0013", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, cros_ec_codec_acpi_id); +#endif static struct platform_driver cros_ec_codec_platform_driver = { .driver = { diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 0c99dcf242e4..2bb727dd3a20 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -971,14 +971,16 @@ static int da7210_set_dai_sysclk(struct snd_soc_dai *codec_dai, /** * da7210_set_dai_pll :Configure the codec PLL - * @param codec_dai : pointer to codec DAI - * @param pll_id : da7210 has only one pll, so pll_id is always zero - * @param fref : MCLK frequency, should be < 20MHz - * @param fout : FsDM value, Refer page 44 & 45 of datasheet - * @return int : Zero for success, negative error code for error + * @codec_dai: pointer to codec DAI + * @pll_id: da7210 has only one pll, so pll_id is always zero + * @source: clock source + * @fref: MCLK frequency, should be < 20MHz + * @fout: FsDM value, Refer page 44 & 45 of datasheet * * Note: Supported PLL input frequencies are 12MHz, 13MHz, 13.5MHz, 14.4MHz, * 19.2MHz, 19.6MHz and 19.8MHz + * + * Return: Zero for success, negative error code for error */ static int da7210_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int fref, unsigned int fout) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index f2520a6c7875..153ea30b5a8f 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1708,11 +1708,13 @@ static const struct of_device_id da7219_of_match[] = { }; MODULE_DEVICE_TABLE(of, da7219_of_match); +#ifdef CONFIG_ACPI static const struct acpi_device_id da7219_acpi_match[] = { { .id = "DLGS7219", }, { } }; MODULE_DEVICE_TABLE(acpi, da7219_acpi_match); +#endif static enum da7219_micbias_voltage da7219_fw_micbias_lvl(struct device *dev, u32 val) diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 36eef1fb3d18..70af35c5f727 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -839,11 +839,13 @@ static const struct of_device_id es8316_of_match[] = { }; MODULE_DEVICE_TABLE(of, es8316_of_match); +#ifdef CONFIG_ACPI static const struct acpi_device_id es8316_acpi_match[] = { {"ESSX8316", 0}, {}, }; MODULE_DEVICE_TABLE(acpi, es8316_acpi_match); +#endif static struct i2c_driver es8316_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index fdf64c29f563..757e740459fb 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -562,14 +562,14 @@ static int es8328_set_sysclk(struct snd_soc_dai *codec_dai, break; case 22579200: mclkdiv2 = 1; - /* fall through */ + fallthrough; case 11289600: es8328->sysclk_constraints = &constraints_11289; es8328->mclk_ratios = ratios_11289; break; case 24576000: mclkdiv2 = 1; - /* fall through */ + fallthrough; case 12288000: es8328->sysclk_constraints = &constraints_12288; es8328->mclk_ratios = ratios_12288; diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c index 34775aa62402..4dee585761c2 100644 --- a/sound/soc/codecs/jz4770.c +++ b/sound/soc/codecs/jz4770.c @@ -303,7 +303,6 @@ static int jz4770_codec_digital_mute(struct snd_soc_dai *dai, int mute) static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0); static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0); static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600); -static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, 0, 400, 0); static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0); /* Unconditional controls. */ diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c new file mode 100644 index 000000000000..92921e34f948 --- /dev/null +++ b/sound/soc/codecs/max98373-i2c.c @@ -0,0 +1,612 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017, Maxim Integrated + +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/cdev.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include "max98373.h" + +static struct reg_default max98373_reg[] = { + {MAX98373_R2000_SW_RESET, 0x00}, + {MAX98373_R2001_INT_RAW1, 0x00}, + {MAX98373_R2002_INT_RAW2, 0x00}, + {MAX98373_R2003_INT_RAW3, 0x00}, + {MAX98373_R2004_INT_STATE1, 0x00}, + {MAX98373_R2005_INT_STATE2, 0x00}, + {MAX98373_R2006_INT_STATE3, 0x00}, + {MAX98373_R2007_INT_FLAG1, 0x00}, + {MAX98373_R2008_INT_FLAG2, 0x00}, + {MAX98373_R2009_INT_FLAG3, 0x00}, + {MAX98373_R200A_INT_EN1, 0x00}, + {MAX98373_R200B_INT_EN2, 0x00}, + {MAX98373_R200C_INT_EN3, 0x00}, + {MAX98373_R200D_INT_FLAG_CLR1, 0x00}, + {MAX98373_R200E_INT_FLAG_CLR2, 0x00}, + {MAX98373_R200F_INT_FLAG_CLR3, 0x00}, + {MAX98373_R2010_IRQ_CTRL, 0x00}, + {MAX98373_R2014_THERM_WARN_THRESH, 0x10}, + {MAX98373_R2015_THERM_SHDN_THRESH, 0x27}, + {MAX98373_R2016_THERM_HYSTERESIS, 0x01}, + {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0}, + {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00}, + {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55}, + {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE}, + {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2022_PCM_TX_SRC_1, 0x00}, + {MAX98373_R2023_PCM_TX_SRC_2, 0x00}, + {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0}, + {MAX98373_R2025_AUDIO_IF_MODE, 0x00}, + {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04}, + {MAX98373_R2027_PCM_SR_SETUP_1, 0x08}, + {MAX98373_R2028_PCM_SR_SETUP_2, 0x88}, + {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00}, + {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00}, + {MAX98373_R202B_PCM_RX_EN, 0x00}, + {MAX98373_R202C_PCM_TX_EN, 0x00}, + {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00}, + {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00}, + {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF}, + {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30}, + {MAX98373_R2034_ICC_TX_CNTL, 0x00}, + {MAX98373_R2035_ICC_TX_EN, 0x00}, + {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05}, + {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00}, + {MAX98373_R203E_AMP_PATH_GAIN, 0x08}, + {MAX98373_R203F_AMP_DSP_CFG, 0x02}, + {MAX98373_R2040_TONE_GEN_CFG, 0x00}, + {MAX98373_R2041_AMP_CFG, 0x03}, + {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00}, + {MAX98373_R2043_AMP_EN, 0x00}, + {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04}, + {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00}, + {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00}, + {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00}, + {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00}, + {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00}, + {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00}, + {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00}, + {MAX98373_R2090_BDE_LVL_HOLD, 0x00}, + {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00}, + {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00}, + {MAX98373_R2097_BDE_L1_THRESH, 0x00}, + {MAX98373_R2098_BDE_L2_THRESH, 0x00}, + {MAX98373_R2099_BDE_L3_THRESH, 0x00}, + {MAX98373_R209A_BDE_L4_THRESH, 0x00}, + {MAX98373_R209B_BDE_THRESH_HYST, 0x00}, + {MAX98373_R20A8_BDE_L1_CFG_1, 0x00}, + {MAX98373_R20A9_BDE_L1_CFG_2, 0x00}, + {MAX98373_R20AA_BDE_L1_CFG_3, 0x00}, + {MAX98373_R20AB_BDE_L2_CFG_1, 0x00}, + {MAX98373_R20AC_BDE_L2_CFG_2, 0x00}, + {MAX98373_R20AD_BDE_L2_CFG_3, 0x00}, + {MAX98373_R20AE_BDE_L3_CFG_1, 0x00}, + {MAX98373_R20AF_BDE_L3_CFG_2, 0x00}, + {MAX98373_R20B0_BDE_L3_CFG_3, 0x00}, + {MAX98373_R20B1_BDE_L4_CFG_1, 0x00}, + {MAX98373_R20B2_BDE_L4_CFG_2, 0x00}, + {MAX98373_R20B3_BDE_L4_CFG_3, 0x00}, + {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00}, + {MAX98373_R20B5_BDE_EN, 0x00}, + {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00}, + {MAX98373_R20D1_DHT_CFG, 0x01}, + {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02}, + {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03}, + {MAX98373_R20D4_DHT_EN, 0x00}, + {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00}, + {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00}, + {MAX98373_R20E2_LIMITER_EN, 0x00}, + {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00}, + {MAX98373_R20FF_GLOBAL_SHDN, 0x00}, + {MAX98373_R21FF_REV_ID, 0x42}, +}; + +static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + unsigned int format = 0; + unsigned int invert = 0; + + dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE; + break; + default: + dev_err(component->dev, "DAI invert mode unsupported\n"); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2026_PCM_CLOCK_RATIO, + MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE, + invert); + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + format = MAX98373_PCM_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + format = MAX98373_PCM_FORMAT_LJ; + break; + case SND_SOC_DAIFMT_DSP_A: + format = MAX98373_PCM_FORMAT_TDM_MODE1; + break; + case SND_SOC_DAIFMT_DSP_B: + format = MAX98373_PCM_FORMAT_TDM_MODE0; + break; + default: + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_FORMAT_MASK, + format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT); + + return 0; +} + +/* BCLKs per LRCLK */ +static const int bclk_sel_table[] = { + 32, 48, 64, 96, 128, 192, 256, 384, 512, 320, +}; + +static int max98373_get_bclk_sel(int bclk) +{ + int i; + /* match BCLKs per LRCLK */ + for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { + if (bclk_sel_table[i] == bclk) + return i + 2; + } + return 0; +} + +static int max98373_set_clock(struct snd_soc_component *component, + struct snd_pcm_hw_params *params) +{ + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + /* BCLK/LRCLK ratio calculation */ + int blr_clk_ratio = params_channels(params) * max98373->ch_size; + int value; + + if (!max98373->tdm_mode) { + /* BCLK configuration */ + value = max98373_get_bclk_sel(blr_clk_ratio); + if (!value) { + dev_err(component->dev, "format unsupported %d\n", + params_format(params)); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2026_PCM_CLOCK_RATIO, + MAX98373_PCM_CLK_SETUP_BSEL_MASK, + value); + } + return 0; +} + +static int max98373_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + unsigned int sampling_rate = 0; + unsigned int chan_sz = 0; + + /* pcm mode configuration */ + switch (snd_pcm_format_width(params_format(params))) { + case 16: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "format unsupported %d\n", + params_format(params)); + goto err; + } + + max98373->ch_size = snd_pcm_format_width(params_format(params)); + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + dev_dbg(component->dev, "format supported %d", + params_format(params)); + + /* sampling rate configuration */ + switch (params_rate(params)) { + case 8000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_8000; + break; + case 11025: + sampling_rate = MAX98373_PCM_SR_SET1_SR_11025; + break; + case 12000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_12000; + break; + case 16000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_16000; + break; + case 22050: + sampling_rate = MAX98373_PCM_SR_SET1_SR_22050; + break; + case 24000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_24000; + break; + case 32000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_32000; + break; + case 44100: + sampling_rate = MAX98373_PCM_SR_SET1_SR_44100; + break; + case 48000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; + break; + case 88200: + sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; + break; + case 96000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; + break; + default: + dev_err(component->dev, "rate %d not supported\n", + params_rate(params)); + goto err; + } + + /* set DAI_SR to correct LRCLK frequency */ + regmap_update_bits(max98373->regmap, + MAX98373_R2027_PCM_SR_SETUP_1, + MAX98373_PCM_SR_SET1_SR_MASK, + sampling_rate); + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_SR_MASK, + sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT); + + /* set sampling rate of IV */ + if (max98373->interleave_mode && + sampling_rate > MAX98373_PCM_SR_SET1_SR_16000) + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate - 3); + else + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate); + + return max98373_set_clock(component, params); +err: + return -EINVAL; +} + +static int max98373_dai_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + int bsel = 0; + unsigned int chan_sz = 0; + unsigned int mask; + int x, slot_found; + + if (!tx_mask && !rx_mask && !slots && !slot_width) + max98373->tdm_mode = false; + else + max98373->tdm_mode = true; + + /* BCLK configuration */ + bsel = max98373_get_bclk_sel(slots * slot_width); + if (bsel == 0) { + dev_err(component->dev, "BCLK %d not supported\n", + slots * slot_width); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2026_PCM_CLOCK_RATIO, + MAX98373_PCM_CLK_SETUP_BSEL_MASK, + bsel); + + /* Channel size configuration */ + switch (slot_width) { + case 16: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "format unsupported %d\n", + slot_width); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + /* Rx slot configuration */ + slot_found = 0; + mask = rx_mask; + for (x = 0 ; x < 16 ; x++, mask >>= 1) { + if (mask & 0x1) { + if (slot_found == 0) + regmap_update_bits(max98373->regmap, + MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, + MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x); + else + regmap_write(max98373->regmap, + MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, + x); + slot_found++; + if (slot_found > 1) + break; + } + } + + /* Tx slot Hi-Z configuration */ + regmap_write(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + ~tx_mask & 0xFF); + regmap_write(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + (~tx_mask & 0xFF00) >> 8); + + return 0; +} + +#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000 + +#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_soc_dai_ops max98373_dai_ops = { + .set_fmt = max98373_dai_set_fmt, + .hw_params = max98373_dai_hw_params, + .set_tdm_slot = max98373_dai_tdm_slot, +}; + +static bool max98373_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R2000_SW_RESET: + case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3: + case MAX98373_R2010_IRQ_CTRL: + case MAX98373_R2014_THERM_WARN_THRESH + ... MAX98373_R2018_THERM_FOLDBACK_EN: + case MAX98373_R201E_PIN_DRIVE_STRENGTH + ... MAX98373_R2036_SOUNDWIRE_CTRL: + case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN: + case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG + ... MAX98373_R2047_IV_SENSE_ADC_EN: + case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE + ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN: + case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE: + case MAX98373_R2097_BDE_L1_THRESH + ... MAX98373_R209B_BDE_THRESH_HYST: + case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3: + case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN: + case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN: + case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG + ... MAX98373_R20FF_GLOBAL_SHDN: + case MAX98373_R21FF_REV_ID: + return true; + default: + return false; + } +}; + +static bool max98373_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: + case MAX98373_R203E_AMP_PATH_GAIN: + case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: + case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: + case MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R21FF_REV_ID: + return true; + default: + return false; + } +} + +static struct snd_soc_dai_driver max98373_dai[] = { + { + .name = "max98373-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .ops = &max98373_dai_ops, + } +}; + +#ifdef CONFIG_PM_SLEEP +static int max98373_suspend(struct device *dev) +{ + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + regcache_cache_only(max98373->regmap, true); + regcache_mark_dirty(max98373->regmap); + return 0; +} + +static int max98373_resume(struct device *dev) +{ + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + regcache_cache_only(max98373->regmap, false); + max98373_reset(max98373, dev); + regcache_sync(max98373->regmap); + return 0; +} +#endif + +static const struct dev_pm_ops max98373_pm = { + SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) +}; + +static const struct regmap_config max98373_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = MAX98373_R21FF_REV_ID, + .reg_defaults = max98373_reg, + .num_reg_defaults = ARRAY_SIZE(max98373_reg), + .readable_reg = max98373_readable_register, + .volatile_reg = max98373_volatile_reg, + .cache_type = REGCACHE_RBTREE, +}; + +static int max98373_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + int ret = 0; + int reg = 0; + struct max98373_priv *max98373 = NULL; + + max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL); + + if (!max98373) { + ret = -ENOMEM; + return ret; + } + i2c_set_clientdata(i2c, max98373); + + /* update interleave mode info */ + if (device_property_read_bool(&i2c->dev, "maxim,interleave_mode")) + max98373->interleave_mode = true; + else + max98373->interleave_mode = false; + + /* regmap initialization */ + max98373->regmap = devm_regmap_init_i2c(i2c, &max98373_regmap); + if (IS_ERR(max98373->regmap)) { + ret = PTR_ERR(max98373->regmap); + dev_err(&i2c->dev, + "Failed to allocate regmap: %d\n", ret); + return ret; + } + + /* voltage/current slot & gpio configuration */ + max98373_slot_config(&i2c->dev, max98373); + + /* Power on device */ + if (gpio_is_valid(max98373->reset_gpio)) { + ret = devm_gpio_request(&i2c->dev, max98373->reset_gpio, + "MAX98373_RESET"); + if (ret) { + dev_err(&i2c->dev, "%s: Failed to request gpio %d\n", + __func__, max98373->reset_gpio); + return -EINVAL; + } + gpio_direction_output(max98373->reset_gpio, 0); + msleep(50); + gpio_direction_output(max98373->reset_gpio, 1); + msleep(20); + } + + /* Check Revision ID */ + ret = regmap_read(max98373->regmap, + MAX98373_R21FF_REV_ID, ®); + if (ret < 0) { + dev_err(&i2c->dev, + "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID); + return ret; + } + dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); + + /* codec registration */ + ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, + max98373_dai, ARRAY_SIZE(max98373_dai)); + if (ret < 0) + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); + + return ret; +} + +static const struct i2c_device_id max98373_i2c_id[] = { + { "max98373", 0}, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, max98373_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id max98373_of_match[] = { + { .compatible = "maxim,max98373", }, + { } +}; +MODULE_DEVICE_TABLE(of, max98373_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id max98373_acpi_match[] = { + { "MX98373", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, max98373_acpi_match); +#endif + +static struct i2c_driver max98373_i2c_driver = { + .driver = { + .name = "max98373", + .of_match_table = of_match_ptr(max98373_of_match), + .acpi_match_table = ACPI_PTR(max98373_acpi_match), + .pm = &max98373_pm, + }, + .probe = max98373_i2c_probe, + .id_table = max98373_i2c_id, +}; + +module_i2c_driver(max98373_i2c_driver) + +MODULE_DESCRIPTION("ALSA SoC MAX98373 driver"); +MODULE_AUTHOR("Ryan Lee <[email protected]>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c new file mode 100644 index 000000000000..5fe724728e84 --- /dev/null +++ b/sound/soc/codecs/max98373-sdw.c @@ -0,0 +1,887 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020, Maxim Integrated + +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include <linux/of.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include "max98373.h" +#include "max98373-sdw.h" + +struct sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +static struct reg_default max98373_reg[] = { + {MAX98373_R0040_SCP_INIT_STAT_1, 0x00}, + {MAX98373_R0041_SCP_INIT_MASK_1, 0x00}, + {MAX98373_R0042_SCP_INIT_STAT_2, 0x00}, + {MAX98373_R0044_SCP_CTRL, 0x00}, + {MAX98373_R0045_SCP_SYSTEM_CTRL, 0x00}, + {MAX98373_R0046_SCP_DEV_NUMBER, 0x00}, + {MAX98373_R0050_SCP_DEV_ID_0, 0x21}, + {MAX98373_R0051_SCP_DEV_ID_1, 0x01}, + {MAX98373_R0052_SCP_DEV_ID_2, 0x9F}, + {MAX98373_R0053_SCP_DEV_ID_3, 0x87}, + {MAX98373_R0054_SCP_DEV_ID_4, 0x08}, + {MAX98373_R0055_SCP_DEV_ID_5, 0x00}, + {MAX98373_R0060_SCP_FRAME_CTLR, 0x00}, + {MAX98373_R0070_SCP_FRAME_CTLR, 0x00}, + {MAX98373_R0100_DP1_INIT_STAT, 0x00}, + {MAX98373_R0101_DP1_INIT_MASK, 0x00}, + {MAX98373_R0102_DP1_PORT_CTRL, 0x00}, + {MAX98373_R0103_DP1_BLOCK_CTRL_1, 0x00}, + {MAX98373_R0104_DP1_PREPARE_STATUS, 0x00}, + {MAX98373_R0105_DP1_PREPARE_CTRL, 0x00}, + {MAX98373_R0120_DP1_CHANNEL_EN, 0x00}, + {MAX98373_R0122_DP1_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0123_DP1_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0124_DP1_OFFSET_CTRL1, 0x00}, + {MAX98373_R0125_DP1_OFFSET_CTRL2, 0x00}, + {MAX98373_R0126_DP1_HCTRL, 0x00}, + {MAX98373_R0127_DP1_BLOCK_CTRL3, 0x00}, + {MAX98373_R0130_DP1_CHANNEL_EN, 0x00}, + {MAX98373_R0132_DP1_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0133_DP1_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0134_DP1_OFFSET_CTRL1, 0x00}, + {MAX98373_R0135_DP1_OFFSET_CTRL2, 0x00}, + {MAX98373_R0136_DP1_HCTRL, 0x0136}, + {MAX98373_R0137_DP1_BLOCK_CTRL3, 0x00}, + {MAX98373_R0300_DP3_INIT_STAT, 0x00}, + {MAX98373_R0301_DP3_INIT_MASK, 0x00}, + {MAX98373_R0302_DP3_PORT_CTRL, 0x00}, + {MAX98373_R0303_DP3_BLOCK_CTRL_1, 0x00}, + {MAX98373_R0304_DP3_PREPARE_STATUS, 0x00}, + {MAX98373_R0305_DP3_PREPARE_CTRL, 0x00}, + {MAX98373_R0320_DP3_CHANNEL_EN, 0x00}, + {MAX98373_R0322_DP3_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0323_DP3_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0324_DP3_OFFSET_CTRL1, 0x00}, + {MAX98373_R0325_DP3_OFFSET_CTRL2, 0x00}, + {MAX98373_R0326_DP3_HCTRL, 0x00}, + {MAX98373_R0327_DP3_BLOCK_CTRL3, 0x00}, + {MAX98373_R0330_DP3_CHANNEL_EN, 0x00}, + {MAX98373_R0332_DP3_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0333_DP3_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0334_DP3_OFFSET_CTRL1, 0x00}, + {MAX98373_R0335_DP3_OFFSET_CTRL2, 0x00}, + {MAX98373_R0336_DP3_HCTRL, 0x00}, + {MAX98373_R0337_DP3_BLOCK_CTRL3, 0x00}, + {MAX98373_R2000_SW_RESET, 0x00}, + {MAX98373_R2001_INT_RAW1, 0x00}, + {MAX98373_R2002_INT_RAW2, 0x00}, + {MAX98373_R2003_INT_RAW3, 0x00}, + {MAX98373_R2004_INT_STATE1, 0x00}, + {MAX98373_R2005_INT_STATE2, 0x00}, + {MAX98373_R2006_INT_STATE3, 0x00}, + {MAX98373_R2007_INT_FLAG1, 0x00}, + {MAX98373_R2008_INT_FLAG2, 0x00}, + {MAX98373_R2009_INT_FLAG3, 0x00}, + {MAX98373_R200A_INT_EN1, 0x00}, + {MAX98373_R200B_INT_EN2, 0x00}, + {MAX98373_R200C_INT_EN3, 0x00}, + {MAX98373_R200D_INT_FLAG_CLR1, 0x00}, + {MAX98373_R200E_INT_FLAG_CLR2, 0x00}, + {MAX98373_R200F_INT_FLAG_CLR3, 0x00}, + {MAX98373_R2010_IRQ_CTRL, 0x00}, + {MAX98373_R2014_THERM_WARN_THRESH, 0x10}, + {MAX98373_R2015_THERM_SHDN_THRESH, 0x27}, + {MAX98373_R2016_THERM_HYSTERESIS, 0x01}, + {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0}, + {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00}, + {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55}, + {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE}, + {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2022_PCM_TX_SRC_1, 0x00}, + {MAX98373_R2023_PCM_TX_SRC_2, 0x00}, + {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0}, + {MAX98373_R2025_AUDIO_IF_MODE, 0x00}, + {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04}, + {MAX98373_R2027_PCM_SR_SETUP_1, 0x08}, + {MAX98373_R2028_PCM_SR_SETUP_2, 0x88}, + {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00}, + {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00}, + {MAX98373_R202B_PCM_RX_EN, 0x00}, + {MAX98373_R202C_PCM_TX_EN, 0x00}, + {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00}, + {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00}, + {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF}, + {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30}, + {MAX98373_R2034_ICC_TX_CNTL, 0x00}, + {MAX98373_R2035_ICC_TX_EN, 0x00}, + {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05}, + {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00}, + {MAX98373_R203E_AMP_PATH_GAIN, 0x08}, + {MAX98373_R203F_AMP_DSP_CFG, 0x02}, + {MAX98373_R2040_TONE_GEN_CFG, 0x00}, + {MAX98373_R2041_AMP_CFG, 0x03}, + {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00}, + {MAX98373_R2043_AMP_EN, 0x00}, + {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04}, + {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00}, + {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00}, + {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00}, + {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00}, + {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00}, + {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00}, + {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00}, + {MAX98373_R2090_BDE_LVL_HOLD, 0x00}, + {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00}, + {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00}, + {MAX98373_R2097_BDE_L1_THRESH, 0x00}, + {MAX98373_R2098_BDE_L2_THRESH, 0x00}, + {MAX98373_R2099_BDE_L3_THRESH, 0x00}, + {MAX98373_R209A_BDE_L4_THRESH, 0x00}, + {MAX98373_R209B_BDE_THRESH_HYST, 0x00}, + {MAX98373_R20A8_BDE_L1_CFG_1, 0x00}, + {MAX98373_R20A9_BDE_L1_CFG_2, 0x00}, + {MAX98373_R20AA_BDE_L1_CFG_3, 0x00}, + {MAX98373_R20AB_BDE_L2_CFG_1, 0x00}, + {MAX98373_R20AC_BDE_L2_CFG_2, 0x00}, + {MAX98373_R20AD_BDE_L2_CFG_3, 0x00}, + {MAX98373_R20AE_BDE_L3_CFG_1, 0x00}, + {MAX98373_R20AF_BDE_L3_CFG_2, 0x00}, + {MAX98373_R20B0_BDE_L3_CFG_3, 0x00}, + {MAX98373_R20B1_BDE_L4_CFG_1, 0x00}, + {MAX98373_R20B2_BDE_L4_CFG_2, 0x00}, + {MAX98373_R20B3_BDE_L4_CFG_3, 0x00}, + {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00}, + {MAX98373_R20B5_BDE_EN, 0x00}, + {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00}, + {MAX98373_R20D1_DHT_CFG, 0x01}, + {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02}, + {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03}, + {MAX98373_R20D4_DHT_EN, 0x00}, + {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00}, + {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00}, + {MAX98373_R20E2_LIMITER_EN, 0x00}, + {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00}, + {MAX98373_R20FF_GLOBAL_SHDN, 0x00}, + {MAX98373_R21FF_REV_ID, 0x42}, +}; + +static bool max98373_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R21FF_REV_ID: + case MAX98373_R2010_IRQ_CTRL: + /* SoundWire Control Port Registers */ + case MAX98373_R0040_SCP_INIT_STAT_1 ... MAX98373_R0070_SCP_FRAME_CTLR: + /* Soundwire Data Port 1 Registers */ + case MAX98373_R0100_DP1_INIT_STAT ... MAX98373_R0137_DP1_BLOCK_CTRL3: + /* Soundwire Data Port 3 Registers */ + case MAX98373_R0300_DP3_INIT_STAT ... MAX98373_R0337_DP3_BLOCK_CTRL3: + case MAX98373_R2000_SW_RESET ... MAX98373_R200C_INT_EN3: + case MAX98373_R2014_THERM_WARN_THRESH + ... MAX98373_R2018_THERM_FOLDBACK_EN: + case MAX98373_R201E_PIN_DRIVE_STRENGTH + ... MAX98373_R2036_SOUNDWIRE_CTRL: + case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN: + case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG + ... MAX98373_R2047_IV_SENSE_ADC_EN: + case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE + ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN: + case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE: + case MAX98373_R2097_BDE_L1_THRESH + ... MAX98373_R209B_BDE_THRESH_HYST: + case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3: + case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN: + case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN: + case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG + ... MAX98373_R20FF_GLOBAL_SHDN: + return true; + default: + return false; + } +}; + +static bool max98373_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: + case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: + case MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R21FF_REV_ID: + /* SoundWire Control Port Registers */ + case MAX98373_R0040_SCP_INIT_STAT_1 ... MAX98373_R0070_SCP_FRAME_CTLR: + /* Soundwire Data Port 1 Registers */ + case MAX98373_R0100_DP1_INIT_STAT ... MAX98373_R0137_DP1_BLOCK_CTRL3: + /* Soundwire Data Port 3 Registers */ + case MAX98373_R0300_DP3_INIT_STAT ... MAX98373_R0337_DP3_BLOCK_CTRL3: + case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: + return true; + default: + return false; + } +} + +static const struct regmap_config max98373_sdw_regmap = { + .reg_bits = 32, + .val_bits = 8, + .max_register = MAX98373_R21FF_REV_ID, + .reg_defaults = max98373_reg, + .num_reg_defaults = ARRAY_SIZE(max98373_reg), + .readable_reg = max98373_readable_register, + .volatile_reg = max98373_volatile_reg, + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +/* Power management functions and structure */ +static __maybe_unused int max98373_suspend(struct device *dev) +{ + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + regcache_cache_only(max98373->regmap, true); + regcache_mark_dirty(max98373->regmap); + return 0; +} + +static __maybe_unused int max98373_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct max98373_priv *max98373 = dev_get_drvdata(dev); + unsigned long time; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(2000)); + if (!time) { + dev_err(dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(max98373->regmap, false); + regcache_sync(max98373->regmap); + + return 0; +} + +static const struct dev_pm_ops max98373_pm = { + SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) + SET_RUNTIME_PM_OPS(max98373_suspend, max98373_resume, NULL) +}; + +static int max98373_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i, num_of_ports; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + /* BITMAP: 00001000 Dataport 3 is active */ + prop->source_ports = BIT(3); + /* BITMAP: 00000010 Dataport 1 is active */ + prop->sink_ports = BIT(1); + prop->paging_support = true; + prop->clk_stop_timeout = 20; + + nval = hweight32(prop->source_ports); + num_of_ports = nval; + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), + GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + num_of_ports += nval; + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* Allocate port_ready based on num_of_ports */ + slave->port_ready = devm_kcalloc(&slave->dev, num_of_ports, + sizeof(*slave->port_ready), + GFP_KERNEL); + if (!slave->port_ready) + return -ENOMEM; + + /* Initialize completion */ + for (i = 0; i < num_of_ports; i++) + init_completion(&slave->port_ready[i]); + + /* set the timeout values */ + prop->clk_stop_timeout = 20; + + return 0; +} + +static int max98373_io_init(struct sdw_slave *slave) +{ + struct device *dev = &slave->dev; + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + if (max98373->pm_init_once) { + regcache_cache_only(max98373->regmap, false); + regcache_cache_bypass(max98373->regmap, true); + } + + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + if (!max98373->pm_init_once) { + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(dev); + + pm_runtime_enable(dev); + } + + pm_runtime_get_noresume(dev); + + /* Software Reset */ + max98373_reset(max98373, dev); + + /* Set soundwire mode */ + regmap_write(max98373->regmap, MAX98373_R2025_AUDIO_IF_MODE, 3); + /* Enable ADC */ + regmap_write(max98373->regmap, MAX98373_R2047_IV_SENSE_ADC_EN, 3); + /* Set default Soundwire clock */ + regmap_write(max98373->regmap, MAX98373_R2036_SOUNDWIRE_CTRL, 5); + /* Set default sampling rate for speaker and IVDAC */ + regmap_write(max98373->regmap, MAX98373_R2028_PCM_SR_SETUP_2, 0x88); + /* IV default slot configuration */ + regmap_write(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + 0xFF); + regmap_write(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + 0xFF); + /* L/R mix configuration */ + regmap_write(max98373->regmap, + MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, + 0x80); + regmap_write(max98373->regmap, + MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, + 0x1); + /* Enable DC blocker */ + regmap_write(max98373->regmap, + MAX98373_R203F_AMP_DSP_CFG, + 0x3); + /* Enable IMON VMON DC blocker */ + regmap_write(max98373->regmap, + MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, + 0x7); + /* voltage, current slot configuration */ + regmap_write(max98373->regmap, + MAX98373_R2022_PCM_TX_SRC_1, + (max98373->i_slot << MAX98373_PCM_TX_CH_SRC_A_I_SHIFT | + max98373->v_slot) & 0xFF); + if (max98373->v_slot < 8) + regmap_update_bits(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + 1 << max98373->v_slot, 0); + else + regmap_update_bits(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + 1 << (max98373->v_slot - 8), 0); + + if (max98373->i_slot < 8) + regmap_update_bits(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + 1 << max98373->i_slot, 0); + else + regmap_update_bits(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + 1 << (max98373->i_slot - 8), 0); + + /* speaker feedback slot configuration */ + regmap_write(max98373->regmap, + MAX98373_R2023_PCM_TX_SRC_2, + max98373->spkfb_slot & 0xFF); + + /* Set interleave mode */ + if (max98373->interleave_mode) + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_TX_CH_INTERLEAVE_MASK, + MAX98373_PCM_TX_CH_INTERLEAVE_MASK); + + /* Speaker enable */ + regmap_update_bits(max98373->regmap, + MAX98373_R2043_AMP_EN, + MAX98373_SPK_EN_MASK, 1); + + regmap_write(max98373->regmap, MAX98373_R20B5_BDE_EN, 1); + regmap_write(max98373->regmap, MAX98373_R20E2_LIMITER_EN, 1); + + if (max98373->pm_init_once) { + regcache_cache_bypass(max98373->regmap, false); + regcache_mark_dirty(max98373->regmap); + } + + max98373->pm_init_once = true; + max98373->hw_init = true; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + +static int max98373_clock_calculate(struct sdw_slave *slave, + unsigned int clk_freq) +{ + int x, y; + static const int max98373_clk_family[] = { + 7680000, 8400000, 9600000, 11289600, + 12000000, 12288000, 13000000 + }; + + for (x = 0; x < 4; x++) + for (y = 0; y < ARRAY_SIZE(max98373_clk_family); y++) + if (clk_freq == (max98373_clk_family[y] >> x)) + return (x << 3) + y; + + /* Set default clock (12.288 Mhz) if the value is not in the list */ + dev_err(&slave->dev, "Requested clock not found. (clk_freq = %d)\n", + clk_freq); + return 0x5; +} + +static int max98373_clock_config(struct sdw_slave *slave, + struct sdw_bus_params *params) +{ + struct device *dev = &slave->dev; + struct max98373_priv *max98373 = dev_get_drvdata(dev); + unsigned int clk_freq, value; + + clk_freq = (params->curr_dr_freq >> 1); + + /* + * Select the proper value for the register based on the + * requested clock. If the value is not in the list, + * use reasonable default - 12.288 Mhz + */ + value = max98373_clock_calculate(slave, clk_freq); + + /* SWCLK */ + regmap_write(max98373->regmap, MAX98373_R2036_SOUNDWIRE_CTRL, value); + + /* The default Sampling Rate value for IV is 48KHz*/ + regmap_write(max98373->regmap, MAX98373_R2028_PCM_SR_SETUP_2, 0x88); + + return 0; +} + +#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000 +#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) + +static int max98373_sdw_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = + snd_soc_component_get_drvdata(component); + + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_data *stream; + int ret, chan_sz, sampling_rate; + + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -EINVAL; + + if (!max98373->slave) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + port_config.num = 1; + } else { + direction = SDW_DATA_DIR_TX; + port_config.num = 3; + } + + stream_config.frame_rate = params_rate(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + if (max98373->slot && direction == SDW_DATA_DIR_RX) { + stream_config.ch_count = max98373->slot; + port_config.ch_mask = max98373->rx_mask; + } else { + /* only IV are supported by capture */ + if (direction == SDW_DATA_DIR_TX) + stream_config.ch_count = 2; + else + stream_config.ch_count = params_channels(params); + + port_config.ch_mask = GENMASK((int)stream_config.ch_count - 1, 0); + } + + ret = sdw_stream_add_slave(max98373->slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (ret) { + dev_err(dai->dev, "Unable to configure port\n"); + return ret; + } + + if (params_channels(params) > 16) { + dev_err(component->dev, "Unsupported channels %d\n", + params_channels(params)); + return -EINVAL; + } + + /* Channel size configuration */ + switch (snd_pcm_format_width(params_format(params))) { + case 16: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "Channel size unsupported %d\n", + params_format(params)); + return -EINVAL; + } + + max98373->ch_size = snd_pcm_format_width(params_format(params)); + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + dev_dbg(component->dev, "Format supported %d", params_format(params)); + + /* Sampling rate configuration */ + switch (params_rate(params)) { + case 8000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_8000; + break; + case 11025: + sampling_rate = MAX98373_PCM_SR_SET1_SR_11025; + break; + case 12000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_12000; + break; + case 16000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_16000; + break; + case 22050: + sampling_rate = MAX98373_PCM_SR_SET1_SR_22050; + break; + case 24000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_24000; + break; + case 32000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_32000; + break; + case 44100: + sampling_rate = MAX98373_PCM_SR_SET1_SR_44100; + break; + case 48000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; + break; + case 88200: + sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; + break; + case 96000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; + break; + default: + dev_err(component->dev, "Rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* set correct sampling frequency */ + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_SR_MASK, + sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT); + + /* set sampling rate of IV */ + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate); + + return 0; +} + +static int max98373_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = + snd_soc_component_get_drvdata(component); + struct sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!max98373->slave) + return -EINVAL; + + sdw_stream_remove_slave(max98373->slave, stream->sdw_stream); + return 0; +} + +static int max98373_set_sdw_stream(struct snd_soc_dai *dai, + void *sdw_stream, int direction) +{ + struct sdw_stream_data *stream; + + if (!sdw_stream) + return 0; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void max98373_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int max98373_sdw_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = + snd_soc_component_get_drvdata(component); + + /* tx_mask is unused since it's irrelevant for I/V feedback */ + if (tx_mask) + return -EINVAL; + + if (!rx_mask && !slots && !slot_width) + max98373->tdm_mode = false; + else + max98373->tdm_mode = true; + + max98373->rx_mask = rx_mask; + max98373->slot = slots; + + return 0; +} + +static const struct snd_soc_dai_ops max98373_dai_sdw_ops = { + .hw_params = max98373_sdw_dai_hw_params, + .hw_free = max98373_pcm_hw_free, + .set_sdw_stream = max98373_set_sdw_stream, + .shutdown = max98373_shutdown, + .set_tdm_slot = max98373_sdw_set_tdm_slot, +}; + +static struct snd_soc_dai_driver max98373_sdw_dai[] = { + { + .name = "max98373-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .ops = &max98373_dai_sdw_ops, + } +}; + +static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) +{ + struct max98373_priv *max98373; + int ret; + struct device *dev = &slave->dev; + + /* Allocate and assign private driver data structure */ + max98373 = devm_kzalloc(dev, sizeof(*max98373), GFP_KERNEL); + if (!max98373) + return -ENOMEM; + + dev_set_drvdata(dev, max98373); + max98373->regmap = regmap; + max98373->slave = slave; + + /* Read voltage and slot configuration */ + max98373_slot_config(dev, max98373); + + max98373->hw_init = false; + max98373->pm_init_once = false; + + /* codec registration */ + ret = devm_snd_soc_register_component(dev, &soc_codec_dev_max98373_sdw, + max98373_sdw_dai, + ARRAY_SIZE(max98373_sdw_dai)); + if (ret < 0) + dev_err(dev, "Failed to register codec: %d\n", ret); + + return ret; +} + +static int max98373_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev); + + if (status == SDW_SLAVE_UNATTACHED) + max98373->hw_init = false; + + /* + * Perform initialization only if slave status is SDW_SLAVE_ATTACHED + */ + if (max98373->hw_init || status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return max98373_io_init(slave); +} + +static int max98373_bus_config(struct sdw_slave *slave, + struct sdw_bus_params *params) +{ + int ret; + + ret = max98373_clock_config(slave, params); + if (ret < 0) + dev_err(&slave->dev, "Invalid clk config"); + + return ret; +} + +/* + * slave_ops: callbacks for get_clock_stop_mode, clock_stop and + * port_prep are not defined for now + */ +static struct sdw_slave_ops max98373_slave_ops = { + .read_prop = max98373_read_prop, + .update_status = max98373_update_status, + .bus_config = max98373_bus_config, +}; + +static int max98373_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + + /* Regmap Initialization */ + regmap = devm_regmap_init_sdw(slave, &max98373_sdw_regmap); + if (!regmap) + return -EINVAL; + + return max98373_init(slave, regmap); +} + +#if defined(CONFIG_OF) +static const struct of_device_id max98373_of_match[] = { + { .compatible = "maxim,max98373", }, + {}, +}; +MODULE_DEVICE_TABLE(of, max98373_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id max98373_acpi_match[] = { + { "MX98373", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, max98373_acpi_match); +#endif + +static const struct sdw_device_id max98373_id[] = { + SDW_SLAVE_ENTRY(0x019F, 0x8373, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, max98373_id); + +static struct sdw_driver max98373_sdw_driver = { + .driver = { + .name = "max98373", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max98373_of_match), + .acpi_match_table = ACPI_PTR(max98373_acpi_match), + .pm = &max98373_pm, + }, + .probe = max98373_sdw_probe, + .remove = NULL, + .ops = &max98373_slave_ops, + .id_table = max98373_id, +}; + +module_sdw_driver(max98373_sdw_driver); + +MODULE_DESCRIPTION("ASoC MAX98373 driver SDW"); +MODULE_AUTHOR("Oleg Sherbakov <[email protected]>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/max98373-sdw.h b/sound/soc/codecs/max98373-sdw.h new file mode 100644 index 000000000000..2d8033515d34 --- /dev/null +++ b/sound/soc/codecs/max98373-sdw.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2020 Maxim Integrated */ + +#ifndef _MAX98373_SDW_H +#define _MAX98373_SDW_H + +#include "max98373.h" + +/* SoundWire Slave Control Port (SCP) */ +#define MAX98373_R0040_SCP_INIT_STAT_1 0x0040 +#define MAX98373_R0041_SCP_INIT_MASK_1 0x0041 +#define MAX98373_R0042_SCP_INIT_STAT_2 0x0042 +#define MAX98373_R0044_SCP_CTRL 0x0044 +#define MAX98373_R0045_SCP_SYSTEM_CTRL 0x0045 +#define MAX98373_R0046_SCP_DEV_NUMBER 0x0046 +#define MAX98373_R0050_SCP_DEV_ID_0 0x0050 +#define MAX98373_R0051_SCP_DEV_ID_1 0x0051 +#define MAX98373_R0052_SCP_DEV_ID_2 0x0052 +#define MAX98373_R0053_SCP_DEV_ID_3 0x0053 +#define MAX98373_R0054_SCP_DEV_ID_4 0x0054 +#define MAX98373_R0055_SCP_DEV_ID_5 0x0055 +#define MAX98373_R0060_SCP_FRAME_CTLR 0x0060 +#define MAX98373_R0070_SCP_FRAME_CTLR 0x0070 + +/* SoundWire Device Data Port (DP) */ +/* Data Port 1 Registers */ +#define MAX98373_R0100_DP1_INIT_STAT 0x0100 +#define MAX98373_R0101_DP1_INIT_MASK 0x0101 +#define MAX98373_R0102_DP1_PORT_CTRL 0x0102 +#define MAX98373_R0103_DP1_BLOCK_CTRL_1 0x0103 +#define MAX98373_R0104_DP1_PREPARE_STATUS 0x0104 +#define MAX98373_R0105_DP1_PREPARE_CTRL 0x0105 +/* Data Port 1 Bank 0 Registers */ +#define MAX98373_R0120_DP1_CHANNEL_EN 0x0120 +#define MAX98373_R0122_DP1_SAMPLE_CTRL1 0x0122 +#define MAX98373_R0123_DP1_SAMPLE_CTRL2 0x0123 +#define MAX98373_R0124_DP1_OFFSET_CTRL1 0x0124 +#define MAX98373_R0125_DP1_OFFSET_CTRL2 0x0125 +#define MAX98373_R0126_DP1_HCTRL 0x0126 +#define MAX98373_R0127_DP1_BLOCK_CTRL3 0x0127 +/* Data Port 1 Bank 1 Registers */ +#define MAX98373_R0130_DP1_CHANNEL_EN 0x0130 +#define MAX98373_R0132_DP1_SAMPLE_CTRL1 0x0132 +#define MAX98373_R0133_DP1_SAMPLE_CTRL2 0x0133 +#define MAX98373_R0134_DP1_OFFSET_CTRL1 0x0134 +#define MAX98373_R0135_DP1_OFFSET_CTRL2 0x0135 +#define MAX98373_R0136_DP1_HCTRL 0x0136 +#define MAX98373_R0137_DP1_BLOCK_CTRL3 0x0137 +/* Data Port 3 Registers */ +#define MAX98373_R0300_DP3_INIT_STAT 0x0300 +#define MAX98373_R0301_DP3_INIT_MASK 0x0301 +#define MAX98373_R0302_DP3_PORT_CTRL 0x0302 +#define MAX98373_R0303_DP3_BLOCK_CTRL_1 0x0303 +#define MAX98373_R0304_DP3_PREPARE_STATUS 0x0304 +#define MAX98373_R0305_DP3_PREPARE_CTRL 0x0305 +/* Data Port 3 Bank 0 Registers */ +#define MAX98373_R0320_DP3_CHANNEL_EN 0x0320 +#define MAX98373_R0322_DP3_SAMPLE_CTRL1 0x0322 +#define MAX98373_R0323_DP3_SAMPLE_CTRL2 0x0323 +#define MAX98373_R0324_DP3_OFFSET_CTRL1 0x0324 +#define MAX98373_R0325_DP3_OFFSET_CTRL2 0x0325 +#define MAX98373_R0326_DP3_HCTRL 0x0326 +#define MAX98373_R0327_DP3_BLOCK_CTRL3 0x0327 +/* Data Port 3 Bank 1 Registers */ +#define MAX98373_R0330_DP3_CHANNEL_EN 0x0330 +#define MAX98373_R0332_DP3_SAMPLE_CTRL1 0x0332 +#define MAX98373_R0333_DP3_SAMPLE_CTRL2 0x0333 +#define MAX98373_R0334_DP3_OFFSET_CTRL1 0x0334 +#define MAX98373_R0335_DP3_OFFSET_CTRL2 0x0335 +#define MAX98373_R0336_DP3_HCTRL 0x0336 +#define MAX98373_R0337_DP3_BLOCK_CTRL3 0x0337 +#endif diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 96718e3a1ad0..67b5faa64ec3 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -17,388 +17,6 @@ #include <sound/tlv.h> #include "max98373.h" -static struct reg_default max98373_reg[] = { - {MAX98373_R2000_SW_RESET, 0x00}, - {MAX98373_R2001_INT_RAW1, 0x00}, - {MAX98373_R2002_INT_RAW2, 0x00}, - {MAX98373_R2003_INT_RAW3, 0x00}, - {MAX98373_R2004_INT_STATE1, 0x00}, - {MAX98373_R2005_INT_STATE2, 0x00}, - {MAX98373_R2006_INT_STATE3, 0x00}, - {MAX98373_R2007_INT_FLAG1, 0x00}, - {MAX98373_R2008_INT_FLAG2, 0x00}, - {MAX98373_R2009_INT_FLAG3, 0x00}, - {MAX98373_R200A_INT_EN1, 0x00}, - {MAX98373_R200B_INT_EN2, 0x00}, - {MAX98373_R200C_INT_EN3, 0x00}, - {MAX98373_R200D_INT_FLAG_CLR1, 0x00}, - {MAX98373_R200E_INT_FLAG_CLR2, 0x00}, - {MAX98373_R200F_INT_FLAG_CLR3, 0x00}, - {MAX98373_R2010_IRQ_CTRL, 0x00}, - {MAX98373_R2014_THERM_WARN_THRESH, 0x10}, - {MAX98373_R2015_THERM_SHDN_THRESH, 0x27}, - {MAX98373_R2016_THERM_HYSTERESIS, 0x01}, - {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0}, - {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00}, - {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55}, - {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE}, - {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF}, - {MAX98373_R2022_PCM_TX_SRC_1, 0x00}, - {MAX98373_R2023_PCM_TX_SRC_2, 0x00}, - {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0}, - {MAX98373_R2025_AUDIO_IF_MODE, 0x00}, - {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04}, - {MAX98373_R2027_PCM_SR_SETUP_1, 0x08}, - {MAX98373_R2028_PCM_SR_SETUP_2, 0x88}, - {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00}, - {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00}, - {MAX98373_R202B_PCM_RX_EN, 0x00}, - {MAX98373_R202C_PCM_TX_EN, 0x00}, - {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00}, - {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00}, - {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF}, - {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF}, - {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30}, - {MAX98373_R2034_ICC_TX_CNTL, 0x00}, - {MAX98373_R2035_ICC_TX_EN, 0x00}, - {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05}, - {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00}, - {MAX98373_R203E_AMP_PATH_GAIN, 0x08}, - {MAX98373_R203F_AMP_DSP_CFG, 0x02}, - {MAX98373_R2040_TONE_GEN_CFG, 0x00}, - {MAX98373_R2041_AMP_CFG, 0x03}, - {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00}, - {MAX98373_R2043_AMP_EN, 0x00}, - {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04}, - {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00}, - {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00}, - {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00}, - {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00}, - {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00}, - {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00}, - {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00}, - {MAX98373_R2090_BDE_LVL_HOLD, 0x00}, - {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00}, - {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00}, - {MAX98373_R2097_BDE_L1_THRESH, 0x00}, - {MAX98373_R2098_BDE_L2_THRESH, 0x00}, - {MAX98373_R2099_BDE_L3_THRESH, 0x00}, - {MAX98373_R209A_BDE_L4_THRESH, 0x00}, - {MAX98373_R209B_BDE_THRESH_HYST, 0x00}, - {MAX98373_R20A8_BDE_L1_CFG_1, 0x00}, - {MAX98373_R20A9_BDE_L1_CFG_2, 0x00}, - {MAX98373_R20AA_BDE_L1_CFG_3, 0x00}, - {MAX98373_R20AB_BDE_L2_CFG_1, 0x00}, - {MAX98373_R20AC_BDE_L2_CFG_2, 0x00}, - {MAX98373_R20AD_BDE_L2_CFG_3, 0x00}, - {MAX98373_R20AE_BDE_L3_CFG_1, 0x00}, - {MAX98373_R20AF_BDE_L3_CFG_2, 0x00}, - {MAX98373_R20B0_BDE_L3_CFG_3, 0x00}, - {MAX98373_R20B1_BDE_L4_CFG_1, 0x00}, - {MAX98373_R20B2_BDE_L4_CFG_2, 0x00}, - {MAX98373_R20B3_BDE_L4_CFG_3, 0x00}, - {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00}, - {MAX98373_R20B5_BDE_EN, 0x00}, - {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00}, - {MAX98373_R20D1_DHT_CFG, 0x01}, - {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02}, - {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03}, - {MAX98373_R20D4_DHT_EN, 0x00}, - {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00}, - {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00}, - {MAX98373_R20E2_LIMITER_EN, 0x00}, - {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00}, - {MAX98373_R20FF_GLOBAL_SHDN, 0x00}, - {MAX98373_R21FF_REV_ID, 0x42}, -}; - -static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_component *component = codec_dai->component; - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - unsigned int format = 0; - unsigned int invert = 0; - - dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE; - break; - default: - dev_err(component->dev, "DAI invert mode unsupported\n"); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2026_PCM_CLOCK_RATIO, - MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE, - invert); - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - format = MAX98373_PCM_FORMAT_I2S; - break; - case SND_SOC_DAIFMT_LEFT_J: - format = MAX98373_PCM_FORMAT_LJ; - break; - case SND_SOC_DAIFMT_DSP_A: - format = MAX98373_PCM_FORMAT_TDM_MODE1; - break; - case SND_SOC_DAIFMT_DSP_B: - format = MAX98373_PCM_FORMAT_TDM_MODE0; - break; - default: - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2024_PCM_DATA_FMT_CFG, - MAX98373_PCM_MODE_CFG_FORMAT_MASK, - format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT); - - return 0; -} - -/* BCLKs per LRCLK */ -static const int bclk_sel_table[] = { - 32, 48, 64, 96, 128, 192, 256, 384, 512, 320, -}; - -static int max98373_get_bclk_sel(int bclk) -{ - int i; - /* match BCLKs per LRCLK */ - for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { - if (bclk_sel_table[i] == bclk) - return i + 2; - } - return 0; -} - -static int max98373_set_clock(struct snd_soc_component *component, - struct snd_pcm_hw_params *params) -{ - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - /* BCLK/LRCLK ratio calculation */ - int blr_clk_ratio = params_channels(params) * max98373->ch_size; - int value; - - if (!max98373->tdm_mode) { - /* BCLK configuration */ - value = max98373_get_bclk_sel(blr_clk_ratio); - if (!value) { - dev_err(component->dev, "format unsupported %d\n", - params_format(params)); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2026_PCM_CLOCK_RATIO, - MAX98373_PCM_CLK_SETUP_BSEL_MASK, - value); - } - return 0; -} - -static int max98373_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - unsigned int sampling_rate = 0; - unsigned int chan_sz = 0; - - /* pcm mode configuration */ - switch (snd_pcm_format_width(params_format(params))) { - case 16: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; - break; - case 24: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; - break; - case 32: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; - break; - default: - dev_err(component->dev, "format unsupported %d\n", - params_format(params)); - goto err; - } - - max98373->ch_size = snd_pcm_format_width(params_format(params)); - - regmap_update_bits(max98373->regmap, - MAX98373_R2024_PCM_DATA_FMT_CFG, - MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); - - dev_dbg(component->dev, "format supported %d", - params_format(params)); - - /* sampling rate configuration */ - switch (params_rate(params)) { - case 8000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_8000; - break; - case 11025: - sampling_rate = MAX98373_PCM_SR_SET1_SR_11025; - break; - case 12000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_12000; - break; - case 16000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_16000; - break; - case 22050: - sampling_rate = MAX98373_PCM_SR_SET1_SR_22050; - break; - case 24000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_24000; - break; - case 32000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_32000; - break; - case 44100: - sampling_rate = MAX98373_PCM_SR_SET1_SR_44100; - break; - case 48000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; - break; - case 88200: - sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; - break; - case 96000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; - break; - default: - dev_err(component->dev, "rate %d not supported\n", - params_rate(params)); - goto err; - } - - /* set DAI_SR to correct LRCLK frequency */ - regmap_update_bits(max98373->regmap, - MAX98373_R2027_PCM_SR_SETUP_1, - MAX98373_PCM_SR_SET1_SR_MASK, - sampling_rate); - regmap_update_bits(max98373->regmap, - MAX98373_R2028_PCM_SR_SETUP_2, - MAX98373_PCM_SR_SET2_SR_MASK, - sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT); - - /* set sampling rate of IV */ - if (max98373->interleave_mode && - sampling_rate > MAX98373_PCM_SR_SET1_SR_16000) - regmap_update_bits(max98373->regmap, - MAX98373_R2028_PCM_SR_SETUP_2, - MAX98373_PCM_SR_SET2_IVADC_SR_MASK, - sampling_rate - 3); - else - regmap_update_bits(max98373->regmap, - MAX98373_R2028_PCM_SR_SETUP_2, - MAX98373_PCM_SR_SET2_IVADC_SR_MASK, - sampling_rate); - - return max98373_set_clock(component, params); -err: - return -EINVAL; -} - -static int max98373_dai_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, - int slots, int slot_width) -{ - struct snd_soc_component *component = dai->component; - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - int bsel = 0; - unsigned int chan_sz = 0; - unsigned int mask; - int x, slot_found; - - if (!tx_mask && !rx_mask && !slots && !slot_width) - max98373->tdm_mode = false; - else - max98373->tdm_mode = true; - - /* BCLK configuration */ - bsel = max98373_get_bclk_sel(slots * slot_width); - if (bsel == 0) { - dev_err(component->dev, "BCLK %d not supported\n", - slots * slot_width); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2026_PCM_CLOCK_RATIO, - MAX98373_PCM_CLK_SETUP_BSEL_MASK, - bsel); - - /* Channel size configuration */ - switch (slot_width) { - case 16: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; - break; - case 24: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; - break; - case 32: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; - break; - default: - dev_err(component->dev, "format unsupported %d\n", - slot_width); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2024_PCM_DATA_FMT_CFG, - MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); - - /* Rx slot configuration */ - slot_found = 0; - mask = rx_mask; - for (x = 0 ; x < 16 ; x++, mask >>= 1) { - if (mask & 0x1) { - if (slot_found == 0) - regmap_update_bits(max98373->regmap, - MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, - MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x); - else - regmap_write(max98373->regmap, - MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, - x); - slot_found++; - if (slot_found > 1) - break; - } - } - - /* Tx slot Hi-Z configuration */ - regmap_write(max98373->regmap, - MAX98373_R2020_PCM_TX_HIZ_EN_1, - ~tx_mask & 0xFF); - regmap_write(max98373->regmap, - MAX98373_R2021_PCM_TX_HIZ_EN_2, - (~tx_mask & 0xFF00) >> 8); - - return 0; -} - -#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000 - -#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops max98373_dai_ops = { - .set_fmt = max98373_dai_set_fmt, - .hw_params = max98373_dai_hw_params, - .set_tdm_slot = max98373_dai_tdm_slot, -}; - static int max98373_dac_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -493,52 +111,6 @@ static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv, 0, 60, TLV_DB_SCALE_ITEM(-1500, 25, 0), ); -static bool max98373_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MAX98373_R2000_SW_RESET: - case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3: - case MAX98373_R2010_IRQ_CTRL: - case MAX98373_R2014_THERM_WARN_THRESH - ... MAX98373_R2018_THERM_FOLDBACK_EN: - case MAX98373_R201E_PIN_DRIVE_STRENGTH - ... MAX98373_R2036_SOUNDWIRE_CTRL: - case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN: - case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG - ... MAX98373_R2047_IV_SENSE_ADC_EN: - case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE - ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN: - case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE: - case MAX98373_R2097_BDE_L1_THRESH - ... MAX98373_R209B_BDE_THRESH_HYST: - case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3: - case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK: - case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN: - case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN: - case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG - ... MAX98373_R20FF_GLOBAL_SHDN: - case MAX98373_R21FF_REV_ID: - return true; - default: - return false; - } -}; - -static bool max98373_volatile_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: - case MAX98373_R203E_AMP_PATH_GAIN: - case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: - case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: - case MAX98373_R20B6_BDE_CUR_STATE_READBACK: - case MAX98373_R21FF_REV_ID: - return true; - default: - return false; - } -} - static const char * const max98373_output_voltage_lvl_text[] = { "5.43V", "6.09V", "6.83V", "7.67V", "8.60V", "9.65V", "10.83V", "12.15V", "13.63V", "15.29V" @@ -710,28 +282,7 @@ static const struct snd_soc_dapm_route max98373_audio_map[] = { { "Speaker FB Sense", NULL, "SpkFB Sense" }, }; -static struct snd_soc_dai_driver max98373_dai[] = { - { - .name = "max98373-aif1", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98373_RATES, - .formats = MAX98373_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98373_RATES, - .formats = MAX98373_FORMATS, - }, - .ops = &max98373_dai_ops, - } -}; - -static void max98373_reset(struct max98373_priv *max98373, struct device *dev) +void max98373_reset(struct max98373_priv *max98373, struct device *dev) { int ret, reg, count; @@ -757,6 +308,7 @@ static void max98373_reset(struct max98373_priv *max98373, struct device *dev) } dev_err(dev, "Reset failed. (ret:%d)\n", ret); } +EXPORT_SYMBOL_GPL(max98373_reset); static int max98373_probe(struct snd_soc_component *component) { @@ -837,31 +389,7 @@ static int max98373_probe(struct snd_soc_component *component) return 0; } -#ifdef CONFIG_PM_SLEEP -static int max98373_suspend(struct device *dev) -{ - struct max98373_priv *max98373 = dev_get_drvdata(dev); - - regcache_cache_only(max98373->regmap, true); - regcache_mark_dirty(max98373->regmap); - return 0; -} -static int max98373_resume(struct device *dev) -{ - struct max98373_priv *max98373 = dev_get_drvdata(dev); - - regcache_cache_only(max98373->regmap, false); - max98373_reset(max98373, dev); - regcache_sync(max98373->regmap); - return 0; -} -#endif - -static const struct dev_pm_ops max98373_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) -}; - -static const struct snd_soc_component_driver soc_codec_dev_max98373 = { +const struct snd_soc_component_driver soc_codec_dev_max98373 = { .probe = max98373_probe, .controls = max98373_snd_controls, .num_controls = ARRAY_SIZE(max98373_snd_controls), @@ -874,23 +402,26 @@ static const struct snd_soc_component_driver soc_codec_dev_max98373 = { .endianness = 1, .non_legacy_dai_naming = 1, }; +EXPORT_SYMBOL_GPL(soc_codec_dev_max98373); -static const struct regmap_config max98373_regmap = { - .reg_bits = 16, - .val_bits = 8, - .max_register = MAX98373_R21FF_REV_ID, - .reg_defaults = max98373_reg, - .num_reg_defaults = ARRAY_SIZE(max98373_reg), - .readable_reg = max98373_readable_register, - .volatile_reg = max98373_volatile_reg, - .cache_type = REGCACHE_RBTREE, +const struct snd_soc_component_driver soc_codec_dev_max98373_sdw = { + .probe = NULL, + .controls = max98373_snd_controls, + .num_controls = ARRAY_SIZE(max98373_snd_controls), + .dapm_widgets = max98373_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98373_dapm_widgets), + .dapm_routes = max98373_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98373_audio_map), + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, }; +EXPORT_SYMBOL_GPL(soc_codec_dev_max98373_sdw); -static void max98373_slot_config(struct i2c_client *i2c, - struct max98373_priv *max98373) +void max98373_slot_config(struct device *dev, + struct max98373_priv *max98373) { int value; - struct device *dev = &i2c->dev; if (!device_property_read_u32(dev, "maxim,vmon-slot-no", &value)) max98373->v_slot = value & 0xF; @@ -922,111 +453,7 @@ static void max98373_slot_config(struct i2c_client *i2c, else max98373->spkfb_slot = 2; } - -static int max98373_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - - int ret = 0; - int reg = 0; - struct max98373_priv *max98373 = NULL; - - max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL); - - if (!max98373) { - ret = -ENOMEM; - return ret; - } - i2c_set_clientdata(i2c, max98373); - - /* update interleave mode info */ - if (device_property_read_bool(&i2c->dev, "maxim,interleave_mode")) - max98373->interleave_mode = true; - else - max98373->interleave_mode = false; - - /* regmap initialization */ - max98373->regmap - = devm_regmap_init_i2c(i2c, &max98373_regmap); - if (IS_ERR(max98373->regmap)) { - ret = PTR_ERR(max98373->regmap); - dev_err(&i2c->dev, - "Failed to allocate regmap: %d\n", ret); - return ret; - } - - /* voltage/current slot & gpio configuration */ - max98373_slot_config(i2c, max98373); - - /* Power on device */ - if (gpio_is_valid(max98373->reset_gpio)) { - ret = devm_gpio_request(&i2c->dev, max98373->reset_gpio, - "MAX98373_RESET"); - if (ret) { - dev_err(&i2c->dev, "%s: Failed to request gpio %d\n", - __func__, max98373->reset_gpio); - return -EINVAL; - } - gpio_direction_output(max98373->reset_gpio, 0); - msleep(50); - gpio_direction_output(max98373->reset_gpio, 1); - msleep(20); - } - - /* Check Revision ID */ - ret = regmap_read(max98373->regmap, - MAX98373_R21FF_REV_ID, ®); - if (ret < 0) { - dev_err(&i2c->dev, - "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID); - return ret; - } - dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); - - /* codec registeration */ - ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, - max98373_dai, ARRAY_SIZE(max98373_dai)); - if (ret < 0) - dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); - - return ret; -} - -static const struct i2c_device_id max98373_i2c_id[] = { - { "max98373", 0}, - { }, -}; - -MODULE_DEVICE_TABLE(i2c, max98373_i2c_id); - -#if defined(CONFIG_OF) -static const struct of_device_id max98373_of_match[] = { - { .compatible = "maxim,max98373", }, - { } -}; -MODULE_DEVICE_TABLE(of, max98373_of_match); -#endif - -#ifdef CONFIG_ACPI -static const struct acpi_device_id max98373_acpi_match[] = { - { "MX98373", 0 }, - {}, -}; -MODULE_DEVICE_TABLE(acpi, max98373_acpi_match); -#endif - -static struct i2c_driver max98373_i2c_driver = { - .driver = { - .name = "max98373", - .of_match_table = of_match_ptr(max98373_of_match), - .acpi_match_table = ACPI_PTR(max98373_acpi_match), - .pm = &max98373_pm, - }, - .probe = max98373_i2c_probe, - .id_table = max98373_i2c_id, -}; - -module_i2c_driver(max98373_i2c_driver) +EXPORT_SYMBOL_GPL(max98373_slot_config); MODULE_DESCRIPTION("ALSA SoC MAX98373 driver"); MODULE_AUTHOR("Ryan Lee <[email protected]>"); diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index 63dae8be7105..4ab29b9d51c7 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2017, Maxim Integrated +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2017 Maxim Integrated */ #ifndef _MAX98373_H #define _MAX98373_H @@ -212,5 +212,18 @@ struct max98373_priv { bool interleave_mode; unsigned int ch_size; bool tdm_mode; + /* variables to support soundwire */ + struct sdw_slave *slave; + bool hw_init; + bool pm_init_once; + int slot; + unsigned int rx_mask; }; + +extern const struct snd_soc_component_driver soc_codec_dev_max98373; +extern const struct snd_soc_component_driver soc_codec_dev_max98373_sdw; + +void max98373_reset(struct max98373_priv *max98373, struct device *dev); +void max98373_slot_config(struct device *dev, + struct max98373_priv *max98373); #endif diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index b345e626956d..3e8094241645 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -944,14 +944,6 @@ static const struct regmap_config max98390_regmap = { .cache_type = REGCACHE_RBTREE, }; -#ifdef CONFIG_OF -static const struct of_device_id max98390_dt_ids[] = { - { .compatible = "maxim,max98390", }, - { } -}; -MODULE_DEVICE_TABLE(of, max98390_dt_ids); -#endif - static int max98390_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 8be636fe6552..d5925c42b4b5 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -334,7 +334,7 @@ static int max9860_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } ifc1a ^= MAX9860_WCI; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_IB_NF: ifc1a ^= MAX9860_DBCI; ifc1b ^= MAX9860_ABCI; diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 30da00a3e789..4428c62e25cf 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -608,7 +608,7 @@ static int pm8916_wcd_analog_enable_adc(struct snd_soc_dapm_widget *w, case CDC_A_TX_2_EN: snd_soc_component_update_bits(component, CDC_A_MICB_1_CTL, MICB_1_CTL_CFILT_REF_SEL_MASK, 0); - /* fall through */ + fallthrough; case CDC_A_TX_3_EN: snd_soc_component_update_bits(component, CDC_D_CDC_CONN_TX2_CTL, CONN_TX2_SERIAL_TX2_MUX, diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index cbb5e176d11a..70cf17c0aa99 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -760,7 +760,7 @@ static int rt274_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, break; default: dev_warn(component->dev, "invalid pll source, use BCLK\n"); - /* fall through */ + fallthrough; case RT274_PLL2_S_BCLK: snd_soc_component_update_bits(component, RT274_PLL2_CTRL, RT274_PLL2_SRC_MASK, RT274_PLL2_SRC_BCLK); @@ -788,7 +788,7 @@ static int rt274_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, break; default: dev_warn(component->dev, "invalid freq_in, assume 4.8M\n"); - /* fall through */ + fallthrough; case 100: snd_soc_component_write(component, 0x7a, 0xaab6); snd_soc_component_write(component, 0x7b, 0x0301); @@ -1105,12 +1105,14 @@ static const struct i2c_device_id rt274_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt274_i2c_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt274_acpi_match[] = { { "10EC0274", 0 }, { "INT34C2", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, rt274_acpi_match); +#endif static int rt274_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 9593a9a27bf8..89b1c8b68004 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1079,11 +1079,13 @@ static const struct i2c_device_id rt286_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt286_acpi_match[] = { { "INT343A", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); +#endif static const struct dmi_system_id force_combo_jack_table[] = { { diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 7fc7d6181630..dc0273a5a11f 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1145,11 +1145,13 @@ static const struct i2c_device_id rt298_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt298_i2c_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt298_acpi_match[] = { { "INT343A", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, rt298_acpi_match); +#endif static const struct dmi_system_id force_combo_jack_table[] = { { diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 3b2bb62a2136..1414ad15d01c 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1662,7 +1662,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) break; case RT5640_IF_113: ret |= RT5640_U_IF1; - /* fall through */ + fallthrough; case RT5640_IF_312: case RT5640_IF_213: ret |= RT5640_U_IF2; @@ -1678,7 +1678,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) break; case RT5640_IF_223: ret |= RT5640_U_IF1; - /* fall through */ + fallthrough; case RT5640_IF_123: case RT5640_IF_321: ret |= RT5640_U_IF2; diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index 78371e51bc34..9e3813f7583d 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -1241,12 +1241,14 @@ static const struct of_device_id rt5660_of_match[] = { }; MODULE_DEVICE_TABLE(of, rt5660_of_match); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt5660_acpi_match[] = { { "10EC5660", 0 }, { "10EC3277", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, rt5660_acpi_match); +#endif static int rt5660_parse_dt(struct rt5660_priv *rt5660, struct device *dev) { diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 7bfade8b3d6e..95ac12a5cc6b 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -614,11 +614,13 @@ static int rt5677_spi_probe(struct spi_device *spi) return ret; } +#ifdef CONFIG_ACPI static const struct acpi_device_id rt5677_spi_acpi_id[] = { { "RT5677AA", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, rt5677_spi_acpi_id); +#endif static struct spi_driver rt5677_spi_driver = { .driver = { diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index e9a051a50ab2..9e449d35fc28 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4609,7 +4609,7 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, break; case 25: slot_width_25 = 0x8080; - /* fall through */ + fallthrough; case 24: val |= (2 << 8); break; diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index e8d2ca4b4603..86528b930de8 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -697,7 +697,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, switch (params_width(params)) { case 24: dev_dbg(component->dev, "24bit\n"); - /* fall through */ + fallthrough; case 32: dev_dbg(component->dev, "24bit or 32bit\n"); switch (sta32x->format) { diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index ccb7100b6644..75d3b0618ab5 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -726,7 +726,7 @@ static int sta350_hw_params(struct snd_pcm_substream *substream, switch (params_width(params)) { case 24: dev_dbg(component->dev, "24bit\n"); - /* fall through */ + fallthrough; case 32: dev_dbg(component->dev, "24bit or 32bit\n"); switch (sta350->format) { diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 529c0fb93f9b..d9d239d4256e 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -407,7 +407,7 @@ static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, clk_id = TAS2552_PLL_CLKIN_BCLK; freq = 0; } - /* fall through */ + fallthrough; case TAS2552_PLL_CLKIN_BCLK: case TAS2552_PLL_CLKIN_1_8_FIXED: mask = TAS2552_PLL_SRC_MASK; diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 35fe8ee5bce9..d900af967f8c 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -313,6 +313,14 @@ static const struct snd_kcontrol_new adcx140_dapm_ch3_en_switch = SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 5, 1, 0); static const struct snd_kcontrol_new adcx140_dapm_ch4_en_switch = SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 4, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch5_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 3, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch6_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 2, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch7_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 1, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch8_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 0, 1, 0); static const struct snd_kcontrol_new adcx140_dapm_ch1_dre_en_switch = SOC_DAPM_SINGLE("Switch", ADCX140_CH1_CFG0, 0, 1, 0); @@ -406,6 +414,15 @@ static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("CH4_ASI_EN", SND_SOC_NOPM, 0, 0, &adcx140_dapm_ch4_en_switch), + SND_SOC_DAPM_SWITCH("CH5_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch5_en_switch), + SND_SOC_DAPM_SWITCH("CH6_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch6_en_switch), + SND_SOC_DAPM_SWITCH("CH7_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch7_en_switch), + SND_SOC_DAPM_SWITCH("CH8_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch8_en_switch), + SND_SOC_DAPM_SWITCH("DRE_ENABLE", SND_SOC_NOPM, 0, 0, &adcx140_dapm_dre_en_switch), @@ -446,6 +463,11 @@ static const struct snd_soc_dapm_route adcx140_audio_map[] = { {"CH3_ASI_EN", "Switch", "CH3_ADC"}, {"CH4_ASI_EN", "Switch", "CH4_ADC"}, + {"CH5_ASI_EN", "Switch", "CH5_OUT"}, + {"CH6_ASI_EN", "Switch", "CH6_OUT"}, + {"CH7_ASI_EN", "Switch", "CH7_OUT"}, + {"CH8_ASI_EN", "Switch", "CH8_OUT"}, + {"Decimation Filter", "Linear Phase", "DRE_ENABLE"}, {"Decimation Filter", "Low Latency", "DRE_ENABLE"}, {"Decimation Filter", "Ultra-low Latency", "DRE_ENABLE"}, @@ -624,6 +646,8 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); u8 iface_reg1 = 0; u8 iface_reg2 = 0; + int offset = 0; + int width = adcx140->slot_width; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -666,7 +690,10 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, iface_reg1 |= ADCX140_LEFT_JUST_BIT; break; case SND_SOC_DAIFMT_DSP_A: + offset += (adcx140->tdm_delay * width + 1); + break; case SND_SOC_DAIFMT_DSP_B: + offset += adcx140->tdm_delay * width; break; default: dev_err(component->dev, "Invalid DAI interface format\n"); @@ -683,6 +710,11 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, snd_soc_component_update_bits(component, ADCX140_MST_CFG0, ADCX140_BCLK_FSYNC_MASTER, iface_reg2); + /* Configure data offset */ + snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, + ADCX140_TX_OFFSET_MASK, offset); + + return 0; } @@ -694,11 +726,6 @@ static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); unsigned int lsb; - if (tx_mask != rx_mask) { - dev_err(component->dev, "tx and rx masks must be symmetric\n"); - return -EINVAL; - } - /* TDM based on DSP mode requires slots to be adjacent */ lsb = __ffs(tx_mask); if ((lsb + 1) != __fls(tx_mask)) { @@ -723,34 +750,9 @@ static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, return 0; } -static int adcx140_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); - int offset = 0; - int width = adcx140->slot_width; - - if (!width) - width = substream->runtime->sample_bits; - - /* TDM slot selection only valid in DSP_A/_B mode */ - if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_A) - offset += (adcx140->tdm_delay * width + 1); - else if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_B) - offset += adcx140->tdm_delay * width; - - /* Configure data offset */ - snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, - ADCX140_TX_OFFSET_MASK, offset); - - return 0; -} - static const struct snd_soc_dai_ops adcx140_dai_ops = { .hw_params = adcx140_hw_params, .set_fmt = adcx140_set_dai_fmt, - .prepare = adcx140_prepare, .set_tdm_slot = adcx140_set_dai_tdm_slot, }; diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index d22f75e8fb6a..7d5b6dbf6273 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -449,7 +449,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, break; case SND_SOC_DAIFMT_DSP_A: iface_reg |= TLV320AIC23_LRP_ON; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_B: iface_reg |= TLV320AIC23_FOR_DSP; break; diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 31daa60695bd..6694e56cfe1f 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1080,7 +1080,8 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_I2S: break; case SND_SOC_DAIFMT_DSP_A: - dsp_a_val = 0x1; /* fall through */ + dsp_a_val = 0x1; + fallthrough; case SND_SOC_DAIFMT_DSP_B: /* * NOTE: This CODEC samples on the falling edge of BCLK in diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 0b1f1a5e2a2d..e2d7ae615c52 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -261,7 +261,7 @@ static int tpa6130a2_probe(struct i2c_client *client, default: dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", data->id); - /* fall through */ + fallthrough; case TPA6130A2: regulator = "Vdd"; break; diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index a1b6765c8f23..f3c31121d100 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -966,7 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_component *component, case SND_SOC_DAIFMT_CBS_CFS: break; case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x2; /* fall through */ + ioctl |= 0x2; + fallthrough; case SND_SOC_DAIFMT_CBM_CFS: voice |= 0x0040; break; @@ -1091,7 +1092,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_component *component, case SND_SOC_DAIFMT_CBS_CFS: break; case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x1; /* fall through */ + ioctl |= 0x1; + fallthrough; case SND_SOC_DAIFMT_CBM_CFS: hifi |= 0x0040; break; diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 5de663d61ba6..a52cb8fee82f 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1927,7 +1927,7 @@ static int wm8903_set_pdata_irq_trigger(struct i2c_client *i2c, * We assume the controller imposes no restrictions, * so we are able to select active-high */ - /* Fall-through */ + fallthrough; case IRQ_TYPE_LEVEL_HIGH: pdata->irq_active_low = false; break; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 3f0e49c51fd5..d54257097d56 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1436,7 +1436,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif1 |= 0x3 | WM8904_AIF_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x3; break; @@ -1824,7 +1824,7 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, break; } clk_id = WM8904_CLK_MCLK; - /* fallthrough */ + fallthrough; case WM8904_CLK_MCLK: priv->sysclk_src = clk_id; diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 73c192f58382..0630dcb66c6f 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -683,7 +683,7 @@ static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif |= WM8955_LRP; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif |= 0x3; break; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 9dca6e28032a..e1ab2be51ee7 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -836,7 +836,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, iface |= 0x000c; break; } - /* fall through */ + fallthrough; default: dev_err(component->dev, "unsupported width %d\n", params_width(params)); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index d11a38a0b283..e62a0a8ac297 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -650,7 +650,7 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_B: aif |= WM8961_LRP; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif |= 3; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 6ef022295f55..df8cdc71357d 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2645,7 +2645,7 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif0 |= WM8962_LRCLK_INV | 3; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif0 |= 3; diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 207c0211caa9..8c9f82efcceb 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1073,7 +1073,7 @@ static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai, switch (clk_id) { case WM8993_SYSCLK_MCLK: wm8993->mclk_rate = freq; - /* fall through */ + fallthrough; case WM8993_SYSCLK_FLL: wm8993->sysclk_source = clk_id; break; @@ -1121,7 +1121,7 @@ static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif1 |= WM8993_AIF_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x18; break; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 75242ec47406..903f8e81cd89 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -853,7 +853,7 @@ static void vmid_reference(struct snd_soc_component *component) switch (wm8994->vmid_mode) { default: WARN_ON(NULL == "Invalid VMID mode"); - /* fall through */ + fallthrough; case WM8994_VMID_NORMAL: /* Startup bias, VMID ramp & buffer */ snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, @@ -2776,7 +2776,7 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_B: aif1 |= WM8994_AIF1_LRCLK_INV; lrclk |= WM8958_AIF1_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x18; break; diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 276ffa84cc31..ec752819cb2c 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -1462,7 +1462,7 @@ static int wm8995_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif |= WM8995_AIF1_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif |= (0x3 << WM8995_AIF1_FMT_SHIFT); break; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1d3b3f4e66b3..d303ef7571e9 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1854,7 +1854,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, case 24576000: ratediv = WM8996_SYSCLK_DIV; wm8996->sysclk /= 2; - /* fall through */ + fallthrough; case 11289600: case 12288000: snd_soc_component_update_bits(component, WM8996_AIF_RATE, diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index be5c9c2b0162..b5465e486fb5 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -929,7 +929,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif2 |= WM9081_AIF_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif2 |= 0x3; break; diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 9fb95c6ee7ba..37053e8f29d0 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -776,8 +776,8 @@ static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol, } /* Get valid good bit from interrupt status register */ -static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int fsl_spdif_rx_vbit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); @@ -791,6 +791,35 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, return 0; } +static int fsl_spdif_tx_vbit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); + struct regmap *regmap = spdif_priv->regmap; + u32 val; + + regmap_read(regmap, REG_SPDIF_SCR, &val); + val = (val & SCR_VAL_MASK) >> SCR_VAL_OFFSET; + val = 1 - val; + ucontrol->value.integer.value[0] = val; + + return 0; +} + +static int fsl_spdif_tx_vbit_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); + struct regmap *regmap = spdif_priv->regmap; + u32 val = (1 - ucontrol->value.integer.value[0]) << SCR_VAL_OFFSET; + + regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_VAL_MASK, val); + + return 0; +} + /* DPLL lock information */ static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -948,11 +977,21 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = { /* Valid bit error controller */ { .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 V-Bit Errors", + .name = "IEC958 RX V-Bit Errors", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = fsl_spdif_vbit_info, + .get = fsl_spdif_rx_vbit_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 TX V-Bit", .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_WRITE | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = fsl_spdif_vbit_info, - .get = fsl_spdif_vbit_get, + .get = fsl_spdif_tx_vbit_get, + .put = fsl_spdif_tx_vbit_put, }, /* DPLL lock info get controller */ { @@ -985,6 +1024,10 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); + /*Clear the val bit for Tx*/ + regmap_update_bits(spdif_private->regmap, REG_SPDIF_SCR, + SCR_VAL_MASK, SCR_VAL_CLEAR); + return 0; } diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index f176df2599a5..d96fc1313434 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -390,7 +390,7 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_DA7219 select SND_SOC_MAX98927 - select SND_SOC_MAX98373 + select SND_SOC_MAX98373_I2C select SND_SOC_DMIC select SND_SOC_HDAC_HDMI help @@ -467,7 +467,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\ (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) - select SND_SOC_MAX98373 + select SND_SOC_MAX98373_I2C select SND_SOC_RT1015 select SND_SOC_RT5682_I2C select SND_SOC_DMIC @@ -531,7 +531,7 @@ config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_DA7219 - select SND_SOC_MAX98373 + select SND_SOC_MAX98373_I2C select SND_SOC_DMIC help This adds support for ASoC machine driver for SOF platforms @@ -565,6 +565,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC + select SND_SOC_MAX98373_I2C select SND_SOC_MAX98373_SDW select SND_SOC_RT700_SDW select SND_SOC_RT711_SDW diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 1470c3de7895..1812b786d33b 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -253,13 +253,17 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); /* - * Default mode for SSP configuration is TDM 4 slot. One board/design, - * the Lenovo Miix 2 10 uses not 1 but 2 codecs connected to SSP2. The - * second piggy-backed, output-only codec is inside the keyboard-dock - * (which has extra speakers). Unlike the main rt5672 codec, we cannot - * configure this codec, it is hard coded to use 2 channel 24 bit I2S. - * Since we only support 2 channels anyways, there is no need for TDM - * on any cht-bsw-rt5672 designs. So we simply use I2S 2ch everywhere. + * The default mode for the cpu-dai is TDM 4 slot. The default mode + * for the codec-dai is I2S. So we need to either set the cpu-dai to + * I2S mode to match the codec-dai, or set the codec-dai to TDM 4 slot + * (or program both to yet another mode). + * One board, the Lenovo Miix 2 10, uses not 1 but 2 codecs connected + * to SSP2. The second piggy-backed, output-only codec is inside the + * keyboard-dock (which has extra speakers). Unlike the main rt5672 + * codec, we cannot configure this codec, it is hard coded to use + * 2 channel 24 bit I2S. For this to work we must use I2S mode on this + * board. Since we only support 2 channels anyways, there is no need + * for TDM on any cht-bsw-rt5672 designs. So we use I2S 2ch everywhere. */ ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 45be9ec6d4ef..be8eccb50450 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -237,6 +237,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, true}, .dai_name = "max98373-aif1", .init = sof_sdw_mx8373_init, + .codec_card_late_probe = sof_sdw_mx8373_late_probe, }, { .id = 0x5682, @@ -927,13 +928,29 @@ DMIC: return 0; } +static int sof_sdw_card_late_probe(struct snd_soc_card *card) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (!codec_info_list[i].late_probe) + continue; + + ret = codec_info_list[i].codec_card_late_probe(card); + if (ret < 0) + return ret; + } + + return sof_sdw_hdmi_card_late_probe(card); +} + /* SoC card */ static const char sdw_card_long_name[] = "Intel Soundwire SOF"; static struct snd_soc_card card_sof_sdw = { .name = "soundwire", .owner = THIS_MODULE, - .late_probe = sof_sdw_hdmi_card_late_probe, + .late_probe = sof_sdw_card_late_probe, .codec_conf = codec_conf, .num_configs = ARRAY_SIZE(codec_conf), }; diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 3f820cf99a89..426017626b16 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -11,6 +11,7 @@ #include <linux/bits.h> #include <linux/types.h> +#include <sound/soc.h> #define MAX_NO_PROPS 2 #define MAX_HDMI_NUM 4 @@ -61,6 +62,9 @@ struct sof_sdw_codec_info { struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); + + bool late_probe; + int (*codec_card_late_probe)(struct snd_soc_card *card); }; struct mc_private { @@ -114,6 +118,8 @@ int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, struct sof_sdw_codec_info *info, bool playback); +int sof_sdw_mx8373_late_probe(struct snd_soc_card *card); + /* RT5682 support */ int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index a38ddc099a95..6437872a9b3d 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -68,7 +68,19 @@ int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, if (info->amp_num == 2) dai_links->init = spk_init; + info->late_probe = true; + dai_links->ops = &max_98373_sdw_ops; return 0; } + +int sof_sdw_mx8373_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_dapm_context *dapm = &card->dapm; + + /* Disable Left and Right Spk pin after boot */ + snd_soc_dapm_disable_pin(dapm, "Left Spk"); + snd_soc_dapm_disable_pin(dapm, "Right Spk"); + return snd_soc_dapm_sync(dapm); +} diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 238e4871678a..786a8d5031e4 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -134,15 +134,16 @@ config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A If unsure select "N". config SND_SOC_MT8183_DA7219_MAX98357A - tristate "ASoC Audio driver for MT8183 with DA7219 MAX98357A codec" + tristate "ASoC Audio driver for MT8183 with DA7219 MAX98357A RT1015 codec" depends on SND_SOC_MT8183 && I2C select SND_SOC_MT6358 select SND_SOC_MAX98357A + select SND_SOC_RT1015 select SND_SOC_DA7219 select SND_SOC_BT_SCO help This adds ASoC driver for Mediatek MT8183 boards - with the DA7219 MAX98357A audio codec. + with the DA7219 MAX98357A RT1015 audio codec. Select Y if you have such device. If unsure select "N". diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index b61bb2de4ec3..bc551a4af25f 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -8,14 +8,22 @@ #include <linux/input.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <sound/jack.h> #include <sound/pcm_params.h> #include <sound/soc.h> -#include "mt8183-afe-common.h" #include "../../codecs/da7219-aad.h" #include "../../codecs/da7219.h" +#include "../../codecs/rt1015.h" +#include "mt8183-afe-common.h" + +#define DA7219_CODEC_DAI "da7219-hifi" +#define DA7219_DEV_NAME "da7219.5-001a" +#define RT1015_CODEC_DAI "rt1015-aif" +#define RT1015_DEV0_NAME "rt1015.6-0028" +#define RT1015_DEV1_NAME "rt1015.6-0029" struct mt8183_da7219_max98357_priv { struct snd_soc_jack headset_jack; @@ -54,8 +62,7 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, dev_err(rtd->dev, "failed to set cpu dai sysclk\n"); for_each_rtd_codec_dais(rtd, j, codec_dai) { - - if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { + if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, mclk_fs, @@ -87,8 +94,7 @@ static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream) int ret = 0, j; for_each_rtd_codec_dais(rtd, j, codec_dai) { - - if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { + if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); if (ret < 0) { @@ -107,6 +113,51 @@ static const struct snd_soc_ops mt8183_da7219_i2s_ops = { .hw_free = mt8183_da7219_hw_free, }; +static int +mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int rate = params_rate(params); + struct snd_soc_dai *codec_dai; + int ret = 0, i; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) || + !strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) { + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret) { + dev_err(rtd->dev, "failed to set bclk ratio\n"); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT1015_PLL_S_BCLK, + rate * 64, rate * 256); + if (ret) { + dev_err(rtd->dev, "failed to set pll\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, + RT1015_SCLK_S_PLL, + rate * 256, + SND_SOC_CLOCK_IN); + if (ret) { + dev_err(rtd->dev, "failed to set sysclk\n"); + return ret; + } + } + } + + return mt8183_da7219_i2s_hw_params(substream, params); +} + +static const struct snd_soc_ops mt8183_da7219_rt1015_i2s_ops = { + .hw_params = mt8183_da7219_rt1015_i2s_hw_params, + .hw_free = mt8183_da7219_hw_free, +}; + static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -119,6 +170,18 @@ static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + /* fix BE i2s format to 32bit, clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + static int mt8183_da7219_max98357_startup( struct snd_pcm_substream *substream) @@ -268,13 +331,20 @@ SND_SOC_DAILINK_DEFS(i2s1, SND_SOC_DAILINK_DEFS(i2s2, DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), - DAILINK_COMP_ARRAY(COMP_CODEC("da7219.5-001a", "da7219-hifi")), + DAILINK_COMP_ARRAY(COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)), DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s3, +SND_SOC_DAILINK_DEFS(i2s3_max98357a, DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"), - COMP_CODEC("da7219.5-001a", "da7219-hifi")), + COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s3_rt1015, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI), + COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI), + COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)), DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(i2s5, @@ -287,7 +357,7 @@ SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); -static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { +static struct snd_soc_dai_link mt8183_da7219_dai_links[] = { /* FE */ { .name = "Playback_1", @@ -422,9 +492,6 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, - .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, - .ops = &mt8183_da7219_i2s_ops, - SND_SOC_DAILINK_REG(i2s3), }, { .name = "I2S5", @@ -449,7 +516,36 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { }; static int -mt8183_da7219_max98357_headset_init(struct snd_soc_component *component); +mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) +{ + int ret; + struct mt8183_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(component->card); + + /* Enable Headset and 4 Buttons Jack detection */ + ret = snd_soc_card_jack_new(component->card, + "Headset Jack", + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &priv->headset_jack, + NULL, 0); + if (ret) + return ret; + + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + da7219_aad_jack_det(component, &priv->headset_jack); + + return 0; +} static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = { .dlc = COMP_EMPTY(), @@ -488,57 +584,56 @@ static struct snd_soc_card mt8183_da7219_max98357_card = { .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets), .dapm_routes = mt8183_da7219_max98357_dapm_routes, .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes), - .dai_link = mt8183_da7219_max98357_dai_links, - .num_links = ARRAY_SIZE(mt8183_da7219_max98357_dai_links), + .dai_link = mt8183_da7219_dai_links, + .num_links = ARRAY_SIZE(mt8183_da7219_dai_links), .aux_dev = &mt8183_da7219_max98357_headset_dev, .num_aux_devs = 1, .codec_conf = mt6358_codec_conf, .num_configs = ARRAY_SIZE(mt6358_codec_conf), }; -static int -mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) -{ - int ret; - struct mt8183_da7219_max98357_priv *priv = - snd_soc_card_get_drvdata(component->card); - - /* Enable Headset and 4 Buttons Jack detection */ - ret = snd_soc_card_jack_new(&mt8183_da7219_max98357_card, - "Headset Jack", - SND_JACK_HEADSET | - SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, - &priv->headset_jack, - NULL, 0); - if (ret) - return ret; - - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); - - da7219_aad_jack_det(component, &priv->headset_jack); +static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF("mt6358-sound"), + .name_prefix = "Mt6358", + }, + { + .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), + .name_prefix = "Right", + }, +}; - return 0; -} +static struct snd_soc_card mt8183_da7219_rt1015_card = { + .name = "mt8183_da7219_rt1015", + .owner = THIS_MODULE, + .controls = mt8183_da7219_max98357_snd_controls, + .num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls), + .dapm_widgets = mt8183_da7219_max98357_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets), + .dapm_routes = mt8183_da7219_max98357_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes), + .dai_link = mt8183_da7219_dai_links, + .num_links = ARRAY_SIZE(mt8183_da7219_dai_links), + .aux_dev = &mt8183_da7219_max98357_headset_dev, + .num_aux_devs = 1, + .codec_conf = mt8183_da7219_rt1015_codec_conf, + .num_configs = ARRAY_SIZE(mt8183_da7219_rt1015_codec_conf), +}; static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) { - struct snd_soc_card *card = &mt8183_da7219_max98357_card; + struct snd_soc_card *card; struct device_node *platform_node; struct snd_soc_dai_link *dai_link; struct mt8183_da7219_max98357_priv *priv; struct pinctrl *pinctrl; + const struct of_device_id *match; int ret, i; - card->dev = &pdev->dev; - platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); if (!platform_node) { @@ -546,10 +641,46 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) return -EINVAL; } + match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); + if (!match || !match->data) + return -EINVAL; + + card = (struct snd_soc_card *)match->data; + card->dev = &pdev->dev; + for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platforms->name) - continue; - dai_link->platforms->of_node = platform_node; + if (strcmp(dai_link->name, "I2S3") == 0) { + if (card == &mt8183_da7219_max98357_card) { + dai_link->be_hw_params_fixup = + mt8183_i2s_hw_params_fixup; + dai_link->ops = &mt8183_mt6358_i2s_ops; + dai_link->cpus = i2s3_max98357a_cpus; + dai_link->num_cpus = + ARRAY_SIZE(i2s3_max98357a_cpus); + dai_link->codecs = i2s3_max98357a_codecs; + dai_link->num_codecs = + ARRAY_SIZE(i2s3_max98357a_codecs); + dai_link->platforms = i2s3_max98357a_platforms; + dai_link->num_platforms = + ARRAY_SIZE(i2s3_max98357a_platforms); + } else if (card == &mt8183_da7219_rt1015_card) { + dai_link->be_hw_params_fixup = + mt8183_rt1015_i2s_hw_params_fixup; + dai_link->ops = &mt8183_da7219_rt1015_i2s_ops; + dai_link->cpus = i2s3_rt1015_cpus; + dai_link->num_cpus = + ARRAY_SIZE(i2s3_rt1015_cpus); + dai_link->codecs = i2s3_rt1015_codecs; + dai_link->num_codecs = + ARRAY_SIZE(i2s3_rt1015_codecs); + dai_link->platforms = i2s3_rt1015_platforms; + dai_link->num_platforms = + ARRAY_SIZE(i2s3_rt1015_platforms); + } + } + + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; } mt8183_da7219_max98357_headset_dev.dlc.of_node = @@ -580,14 +711,21 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id mt8183_da7219_max98357_dt_match[] = { - {.compatible = "mediatek,mt8183_da7219_max98357",}, + { + .compatible = "mediatek,mt8183_da7219_max98357", + .data = &mt8183_da7219_max98357_card, + }, + { + .compatible = "mediatek,mt8183_da7219_rt1015", + .data = &mt8183_da7219_rt1015_card, + }, {} }; #endif static struct platform_driver mt8183_da7219_max98357_driver = { .driver = { - .name = "mt8183_da7219_max98357", + .name = "mt8183_da7219", #ifdef CONFIG_OF .of_match_table = mt8183_da7219_max98357_dt_match, #endif diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index a5b1a12b3496..45dfc534c6c7 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -104,8 +104,13 @@ /** * struct s3c_pcm_info - S3C PCM Controller information + * @lock: Spin lock * @dev: The parent device passed to use from the probe. * @regs: The pointer to the device register block. + * @sclk_per_fs: number of sclk per frame sync + * @idleclk: Whether to keep PCMSCLK enabled even when idle (no active xfer) + * @pclk: the PCLK_PCM (pcm) clock pointer + * @cclk: the SCLK_AUDIO (audio-bus) clock pointer * @dma_playback: DMA information for playback channel. * @dma_capture: DMA information for capture channel. */ diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 759fc6644329..4ae7ff623b82 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -70,9 +70,9 @@ * @clk_rate: Current clock rate for calcurate ratio. * @pclk: The peri-clock pointer for spdif master operation. * @sclk: The source clock pointer for making sync signals. - * @save_clkcon: Backup clkcon reg. in suspend. - * @save_con: Backup con reg. in suspend. - * @save_cstas: Backup cstas reg. in suspend. + * @saved_clkcon: Backup clkcon reg. in suspend. + * @saved_con: Backup con reg. in suspend. + * @saved_cstas: Backup cstas reg. in suspend. * @dma_playback: DMA information for playback channel. */ struct samsung_spdif_info { diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index 1070b2710d5e..79dba878d854 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -98,8 +98,7 @@ EXPORT_SYMBOL_GPL(tegra20_das_connect_dac_to_dap); static bool tegra20_das_wr_rd_reg(struct device *dev, unsigned int reg) { - if ((reg >= TEGRA20_DAS_DAP_CTRL_SEL) && - (reg <= LAST_REG(DAP_CTRL_SEL))) + if (reg <= LAST_REG(DAP_CTRL_SEL)) return true; if ((reg >= TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL) && (reg <= LAST_REG(DAC_INPUT_DATA_CLK_SEL))) diff --git a/sound/soc/ti/omap-mcbsp-st.c b/sound/soc/ti/omap-mcbsp-st.c index 5a32b54bbf3b..0bc7d26c660a 100644 --- a/sound/soc/ti/omap-mcbsp-st.c +++ b/sound/soc/ti/omap-mcbsp-st.c @@ -142,11 +142,8 @@ static void omap_mcbsp_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) static void omap_mcbsp_st_chgain(struct omap_mcbsp *mcbsp) { - u16 w; struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - w = MCBSP_ST_READ(mcbsp, SSELCR); - MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | ST_CH1GAIN(st_data->ch1gain)); } diff --git a/sound/soc/uniphier/aio-core.c b/sound/soc/uniphier/aio-core.c index 9bcba06ba52e..b8195778953e 100644 --- a/sound/soc/uniphier/aio-core.c +++ b/sound/soc/uniphier/aio-core.c @@ -93,9 +93,9 @@ void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable) /** * aio_chip_set_pll - set frequency to audio PLL - * @chip : the AIO chip pointer - * @source: PLL - * @freq : frequency in Hz, 0 is ignored + * @chip: the AIO chip pointer + * @pll_id: PLL + * @freq: frequency in Hz, 0 is ignored * * Sets frequency of audio PLL. This function can be called anytime, * but it takes time till PLL is locked. @@ -267,7 +267,6 @@ void aio_port_reset(struct uniphier_aio_sub *sub) /** * aio_port_set_ch - set channels of LPCM * @sub: the AIO substream pointer, PCM substream only - * @ch : count of channels * * Set suitable slot selecting to input/output port block of AIO. * |