diff options
author | Takashi Iwai <tiwai@suse.de> | 2020-08-03 14:41:43 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2020-08-03 14:41:43 +0200 |
commit | 103f528d3bc35d2b6e726a3fffd879e492d191c2 (patch) | |
tree | 2829604c2386f96e228fac7841e49906f698dfff /sound | |
parent | 07c9983b567d0ef33aefc063299de95a987e12a8 (diff) | |
parent | 84569f329f7fcb40b7b1860f273b2909dabf2a2b (diff) |
Merge tag 'asoc-v5.9' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v5.9
The biggest changes here one again come from Mormioto-san who has
continued his dilligent work cleaning up long standing issues in the
APIs, it's particularly nice to see the transition from digital_mute()
to mute_stream() finally completed. There's also been a lot of work on
the x86 code again, this time a big focus has been on cleaning up some
issues identified by various static tests, and on the Freescale systems.
Otherwise the biggest thing has been a lot of driver additions:
- Convert users of digital_mute() to mute_stream().
- Simplify I/O helper functions.
- Add a helper for getting the RTD from a substream.
- Many, many fixes and cleanups to the x86 code.
- New drivers for Freescale MQS and i.MX6sx, Intel KeemBay I2S, Maxim
MAX98360A and MAX98373 Soundwire, several Mediatek boards, nVidia
Tegra 186 and 210, RealTek RL6231, Samsung Midas and Aries boards (some
of the first phones I worked on!) and TI J721e EVM.
Diffstat (limited to 'sound')
490 files changed, 14388 insertions, 4455 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8ad73ccbdeb9..a4eefcc0fe9e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -792,6 +792,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) remove_conn_list(codec); snd_hdac_regmap_exit(&codec->core); } +EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind); static unsigned int hda_set_power_state(struct hda_codec *codec, unsigned int power_state); @@ -3186,7 +3187,7 @@ int snd_hda_codec_prepare(struct hda_codec *codec, EXPORT_SYMBOL_GPL(snd_hda_codec_prepare); /** - * snd_hda_codec_cleanup - Prepare a stream + * snd_hda_codec_cleanup - Clean up stream resources * @codec: the HDA codec * @hinfo: PCM information * @substream: PCM substream diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 7f1747518e79..ddbac3a2169f 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o soc-card.o +snd-soc-core-objs += soc-pcm.o soc-devres.o soc-ops.o soc-link.o soc-card.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index e37cf72f2bab..a6ce000fac3f 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -33,6 +33,7 @@ config SND_SOC_AMD_RV_RT5682_MACH select SND_SOC_MAX98357A select SND_SOC_CROS_EC_CODEC select I2C_CROS_EC_TUNNEL + select SND_SOC_RT1015 depends on SND_SOC_AMD_ACP3x && I2C && CROS_EC help This option enables machine driver for RT5682 and MAX9835. diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 9414d7269c4f..a7702e64ec51 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -99,7 +99,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) static int da7219_clk_enable(struct snd_pcm_substream *substream) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* * Set wclk to 48000 because the rate constraint of this driver is @@ -146,7 +146,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = { static int cz_da7219_play_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -167,7 +167,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream) static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -189,7 +189,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) static int cz_max_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -210,7 +210,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream) static int cz_dmic0_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -231,7 +231,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream) static int cz_dmic1_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -450,11 +450,13 @@ static int cz_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_ACPI static const struct acpi_device_id cz_audio_acpi_match[] = { { "AMD7219", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); +#endif static struct platform_driver cz_pcm_driver = { .driver = { diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index f54beb7f39a8..143155a840ac 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -840,7 +840,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component, u32 val = 0; struct snd_pcm_runtime *runtime; struct audio_substream_data *rtd; - struct snd_soc_pcm_runtime *prtd = substream->private_data; + struct snd_soc_pcm_runtime *prtd = asoc_substream_to_rtd(substream); struct audio_drv_data *adata = dev_get_drvdata(component->dev); struct snd_soc_card *card = prtd->card; struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/amd/acp-rt5645.c b/sound/soc/amd/acp-rt5645.c index 73b31f88a6b5..d6ba94677ac2 100644 --- a/sound/soc/amd/acp-rt5645.c +++ b/sound/soc/amd/acp-rt5645.c @@ -47,7 +47,7 @@ static int cz_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK, @@ -182,11 +182,13 @@ static int cz_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_ACPI static const struct acpi_device_id cz_audio_acpi_match[] = { { "AMDI1002", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); +#endif static struct platform_driver cz_pcm_driver = { .driver = { diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index e499c00e0c66..55815fdaa1aa 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -21,6 +21,7 @@ #include "raven/acp3x.h" #include "../codecs/rt5682.h" +#include "../codecs/rt1015.h" #define PCO_PLAT_CLK 48000000 #define RT5682_PLL_FREQ (48000 * 512) @@ -30,6 +31,13 @@ static struct snd_soc_jack pco_jack; static struct clk *rt5682_dai_wclk; static struct clk *rt5682_dai_bclk; static struct gpio_desc *dmic_sel; +void *soc_is_rltk_max(struct device *dev); + +enum { + RT5682 = 0, + MAX, + EC, +}; static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) { @@ -105,7 +113,7 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) static int rt5682_clk_enable(struct snd_pcm_substream *substream) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* RT5682 will support only 48K output with 48M mclk */ clk_set_rate(rt5682_dai_wclk, 48000); @@ -119,6 +127,34 @@ static int rt5682_clk_enable(struct snd_pcm_substream *substream) return ret; } +static int acp3x_1015_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; + int srate, i, ret; + + ret = 0; + srate = params_rate(params); + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (strcmp(codec_dai->component->name, "rt1015-aif")) + continue; + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, + 64 * srate, 256 * srate); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, + 256 * srate, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + } + return ret; +} + static void rt5682_clk_disable(void) { clk_disable_unprepare(rt5682_dai_wclk); @@ -147,7 +183,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = { static int acp3x_5682_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -165,7 +201,7 @@ static int acp3x_5682_startup(struct snd_pcm_substream *substream) static int acp3x_max_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -181,32 +217,34 @@ static int acp3x_max_startup(struct snd_pcm_substream *substream) static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); machine->cap_i2s_instance = I2S_BT_INSTANCE; snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (dmic_sel) - gpiod_set_value(dmic_sel, 0); return rt5682_clk_enable(substream); } -static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); +static int dmic_switch; - machine->cap_i2s_instance = I2S_BT_INSTANCE; - snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (dmic_sel) - gpiod_set_value(dmic_sel, 1); +static int dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = dmic_switch; + return 0; +} - return rt5682_clk_enable(substream); +static int dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + if (dmic_sel) { + dmic_switch = ucontrol->value.integer.value[0]; + gpiod_set_value(dmic_sel, dmic_switch); + } + return 0; } static void rt5682_shutdown(struct snd_pcm_substream *substream) @@ -222,6 +260,7 @@ static const struct snd_soc_ops acp3x_5682_ops = { static const struct snd_soc_ops acp3x_max_play_ops = { .startup = acp3x_max_startup, .shutdown = rt5682_shutdown, + .hw_params = acp3x_1015_hw_params, }; static const struct snd_soc_ops acp3x_ec_cap0_ops = { @@ -229,11 +268,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = { .shutdown = rt5682_shutdown, }; -static const struct snd_soc_ops acp3x_ec_cap1_ops = { - .startup = acp3x_ec_dmic1_startup, - .shutdown = rt5682_shutdown, -}; - SND_SOC_DAILINK_DEF(acp3x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0"))); SND_SOC_DAILINK_DEF(acp3x_bt, @@ -243,14 +277,28 @@ SND_SOC_DAILINK_DEF(rt5682, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); SND_SOC_DAILINK_DEF(max, DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); +SND_SOC_DAILINK_DEF(rt1015, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1015:00", "rt1015-aif"), + COMP_CODEC("i2c-10EC1015:01", "rt1015-aif"))); SND_SOC_DAILINK_DEF(cros_ec, DAILINK_COMP_ARRAY(COMP_CODEC("GOOG0013:00", "EC Codec I2S RX"))); SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp3x_rv_i2s_dma.0"))); -static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { +static struct snd_soc_codec_conf rt1015_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:00"), + .name_prefix = "Left", + }, { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:01"), + .name_prefix = "Right", + }, +}; + +static struct snd_soc_dai_link acp3x_dai[] = { + [RT5682] = { .name = "acp3x-5682-play", .stream_name = "Playback", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF @@ -261,16 +309,19 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { .ops = &acp3x_5682_ops, SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform), }, - { + [MAX] = { .name = "acp3x-max98357-play", .stream_name = "HiFi Playback", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBS_CFS, .dpcm_playback = 1, .ops = &acp3x_max_play_ops, - SND_SOC_DAILINK_REG(acp3x_bt, max, platform), + .cpus = acp3x_bt, + .num_cpus = ARRAY_SIZE(acp3x_bt), + .platforms = platform, + .num_platforms = ARRAY_SIZE(platform), }, - { + [EC] = { .name = "acp3x-ec-dmic0-capture", .stream_name = "Capture DMIC0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF @@ -279,61 +330,136 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { .ops = &acp3x_ec_cap0_ops, SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), }, - { - .name = "acp3x-ec-dmic1-capture", - .stream_name = "Capture DMIC1", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBS_CFS, - .dpcm_capture = 1, - .ops = &acp3x_ec_cap1_ops, - SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), - }, }; -static const struct snd_soc_dapm_widget acp3x_widgets[] = { +static const char * const dmic_mux_text[] = { + "Front Mic", + "Rear Mic", +}; + +static SOC_ENUM_SINGLE_DECL( + acp3x_dmic_enum, SND_SOC_NOPM, 0, dmic_mux_text); + +static const struct snd_kcontrol_new acp3x_dmic_mux_control = + SOC_DAPM_ENUM_EXT("DMIC Select Mux", acp3x_dmic_enum, + dmic_get, dmic_set); + +static const struct snd_soc_dapm_widget acp3x_5682_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_SPK("Spk", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), }; -static const struct snd_soc_dapm_route acp3x_audio_route[] = { +static const struct snd_soc_dapm_route acp3x_5682_audio_route[] = { {"Headphone Jack", NULL, "HPOL"}, {"Headphone Jack", NULL, "HPOR"}, {"IN1P", NULL, "Headset Mic"}, {"Spk", NULL, "Speaker"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, }; -static const struct snd_kcontrol_new acp3x_mc_controls[] = { +static const struct snd_kcontrol_new acp3x_5682_mc_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Spk"), SOC_DAPM_PIN_SWITCH("Headset Mic"), }; -static struct snd_soc_card acp3x_card = { +static struct snd_soc_card acp3x_5682 = { .name = "acp3xalc5682m98357", .owner = THIS_MODULE, - .dai_link = acp3x_dai_5682_98357, - .num_links = ARRAY_SIZE(acp3x_dai_5682_98357), - .dapm_widgets = acp3x_widgets, - .num_dapm_widgets = ARRAY_SIZE(acp3x_widgets), - .dapm_routes = acp3x_audio_route, - .num_dapm_routes = ARRAY_SIZE(acp3x_audio_route), - .controls = acp3x_mc_controls, - .num_controls = ARRAY_SIZE(acp3x_mc_controls), + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_5682_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_5682_widgets), + .dapm_routes = acp3x_5682_audio_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_5682_audio_route), + .controls = acp3x_5682_mc_controls, + .num_controls = ARRAY_SIZE(acp3x_5682_mc_controls), +}; + +static const struct snd_soc_dapm_widget acp3x_1015_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route acp3x_1015_route[] = { + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, + {"Left Spk", NULL, "Left SPO"}, + {"Right Spk", NULL, "Right SPO"}, +}; + +static const struct snd_kcontrol_new acp3x_mc_1015_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static struct snd_soc_card acp3x_1015 = { + .name = "acp3xalc56821015", + .owner = THIS_MODULE, + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_1015_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_1015_widgets), + .dapm_routes = acp3x_1015_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_1015_route), + .codec_conf = rt1015_conf, + .num_configs = ARRAY_SIZE(rt1015_conf), + .controls = acp3x_mc_1015_controls, + .num_controls = ARRAY_SIZE(acp3x_mc_1015_controls), }; +void *soc_is_rltk_max(struct device *dev) +{ + const struct acpi_device_id *match; + + match = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!match) + return NULL; + return (void *)match->driver_data; +} + +static void card_spk_dai_link_present(struct snd_soc_dai_link *links, + const char *card_name) +{ + if (!strcmp(card_name, "acp3xalc56821015")) { + links[1].codecs = rt1015; + links[1].num_codecs = ARRAY_SIZE(rt1015); + } else { + links[1].codecs = max; + links[1].num_codecs = ARRAY_SIZE(max); + } +} + static int acp3x_probe(struct platform_device *pdev) { int ret; struct snd_soc_card *card; struct acp3x_platform_info *machine; + struct device *dev = &pdev->dev; + + card = (struct snd_soc_card *)soc_is_rltk_max(dev); + if (!card) + return -ENODEV; machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL); if (!machine) return -ENOMEM; - card = &acp3x_card; - acp3x_card.dev = &pdev->dev; + card_spk_dai_link_present(card->dai_link, card->name); + card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); @@ -344,18 +470,19 @@ static int acp3x_probe(struct platform_device *pdev) return PTR_ERR(dmic_sel); } - ret = devm_snd_soc_register_card(&pdev->dev, &acp3x_card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { dev_err(&pdev->dev, "devm_snd_soc_register_card(%s) failed: %d\n", - acp3x_card.name, ret); + card->name, ret); return ret; } return 0; } static const struct acpi_device_id acp3x_audio_acpi_match[] = { - { "AMDI5682", 0 }, + { "AMDI5682", (unsigned long)&acp3x_5682}, + { "AMDI1015", (unsigned long)&acp3x_1015}, {}, }; MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match); @@ -372,5 +499,6 @@ static struct platform_driver acp3x_audio = { module_platform_driver(acp3x_audio); MODULE_AUTHOR("akshu.agrawal@amd.com"); -MODULE_DESCRIPTION("ALC5682 & MAX98357 audio support"); +MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); +MODULE_DESCRIPTION("ALC5682 ALC1015 & MAX98357 audio support"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index a532e01a2622..5bc028692fcf 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -80,7 +80,7 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream, u32 val; u32 reg_val, frmt_reg; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); rtd = substream->runtime->private_data; card = prtd->card; adata = snd_soc_dai_get_drvdata(dai); @@ -149,22 +149,10 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct i2s_stream_instance *rtd; - struct snd_soc_pcm_runtime *prtd; - struct snd_soc_card *card; - struct acp3x_platform_info *pinfo; u32 ret, val, period_bytes, reg_val, ier_val, water_val; u32 buf_size, buf_reg; - prtd = substream->private_data; rtd = substream->runtime->private_data; - card = prtd->card; - pinfo = snd_soc_card_get_drvdata(card); - if (pinfo) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - rtd->i2s_instance = pinfo->play_i2s_instance; - else - rtd->i2s_instance = pinfo->cap_i2s_instance; - } period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size); buf_size = frames_to_bytes(substream->runtime, diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index e6386de20ac7..417cda24030c 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -217,7 +217,7 @@ static int acp3x_dma_open(struct snd_soc_component *component, int ret; runtime = substream->runtime; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); adata = dev_get_drvdata(component->dev); i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL); @@ -238,7 +238,7 @@ static int acp3x_dma_open(struct snd_soc_component *component, } if (!adata->play_stream && !adata->capture_stream && - adata->i2ssp_play_stream && !adata->i2ssp_capture_stream) + !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream) rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); i2s_data->acp3x_base = adata->acp3x_base; @@ -258,7 +258,7 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component, struct i2s_dev_data *adata; u64 size; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); card = prtd->card; pinfo = snd_soc_card_get_drvdata(card); adata = dev_get_drvdata(component->dev); @@ -301,15 +301,11 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component, static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *prtd; - struct snd_soc_card *card; struct i2s_stream_instance *rtd; u32 pos; u32 buffersize; u64 bytescount; - prtd = substream->private_data; - card = prtd->card; rtd = substream->runtime->private_data; buffersize = frames_to_bytes(substream->runtime, @@ -344,7 +340,7 @@ static int acp3x_dma_close(struct snd_soc_component *component, struct i2s_dev_data *adata; struct i2s_stream_instance *ins; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); adata = dev_get_drvdata(component->dev); ins = substream->runtime->private_data; diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c index ebf4388b6262..31b797c8bfe6 100644 --- a/sound/soc/amd/raven/pci-acp3x.c +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -19,10 +19,12 @@ struct acp3x_dev_data { bool acp3x_audio_mode; struct resource *res; struct platform_device *pdev[ACP3x_DEVS]; + u32 pme_en; }; -static int acp3x_power_on(void __iomem *acp3x_base) +static int acp3x_power_on(struct acp3x_dev_data *adata) { + void __iomem *acp3x_base = adata->acp3x_base; u32 val; int timeout; @@ -39,10 +41,10 @@ static int acp3x_power_on(void __iomem *acp3x_base) while (++timeout < 500) { val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); if (!val) { - /* Set PME_EN as after ACP power On, - * PME_EN gets cleared + /* ACP power On clears PME_EN. + * Restore the value to its prior state */ - rv_writel(0x1, acp3x_base + mmACP_PME_EN); + rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN); return 0; } udelay(1); @@ -74,12 +76,13 @@ static int acp3x_reset(void __iomem *acp3x_base) return -ETIMEDOUT; } -static int acp3x_init(void __iomem *acp3x_base) +static int acp3x_init(struct acp3x_dev_data *adata) { + void __iomem *acp3x_base = adata->acp3x_base; int ret; /* power on */ - ret = acp3x_power_on(acp3x_base); + ret = acp3x_power_on(adata); if (ret) { pr_err("ACP3x power on failed\n"); return ret; @@ -151,7 +154,9 @@ static int snd_acp3x_probe(struct pci_dev *pci, } pci_set_master(pci); pci_set_drvdata(pci, adata); - ret = acp3x_init(adata->acp3x_base); + /* Save ACP_PME_EN state */ + adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN); + ret = acp3x_init(adata); if (ret) goto disable_msi; @@ -274,7 +279,7 @@ static int snd_acp3x_resume(struct device *dev) struct acp3x_dev_data *adata; adata = dev_get_drvdata(dev); - ret = acp3x_init(adata->acp3x_base); + ret = acp3x_init(adata); if (ret) { dev_err(dev, "ACP init failed\n"); return ret; diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 859ed67b93cf..b943e59fc302 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -5,6 +5,7 @@ //Copyright 2020 Advanced Micro Devices, Inc. #include <linux/pci.h> +#include <linux/acpi.h> #include <linux/module.h> #include <linux/io.h> #include <linux/delay.h> @@ -18,6 +19,16 @@ static int acp_power_gating; module_param(acp_power_gating, int, 0644); MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); +/** + * dmic_acpi_check = -1 - Checks ACPI method to know DMIC hardware status runtime + * = 0 - Skips the DMIC device creation and returns probe failure + * = 1 - Assumes that platform has DMIC support and skips ACPI + * method check + */ +static int dmic_acpi_check = ACP_DMIC_AUTO; +module_param(dmic_acpi_check, bint, 0644); +MODULE_PARM_DESC(dmic_acpi_check, "checks Dmic hardware runtime"); + struct acp_dev_data { void __iomem *acp_base; struct resource *res; @@ -157,6 +168,10 @@ static int snd_rn_acp_probe(struct pci_dev *pci, { struct acp_dev_data *adata; struct platform_device_info pdevinfo[ACP_DEVS]; +#if defined(CONFIG_ACPI) + acpi_handle handle; + acpi_integer dmic_status; +#endif unsigned int irqflags; int ret, index; u32 addr; @@ -201,6 +216,24 @@ static int snd_rn_acp_probe(struct pci_dev *pci, if (ret) goto disable_msi; + if (!dmic_acpi_check) { + ret = -ENODEV; + goto de_init; + } else if (dmic_acpi_check == ACP_DMIC_AUTO) { +#if defined(CONFIG_ACPI) + handle = ACPI_HANDLE(&pci->dev); + ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); + if (ACPI_FAILURE(ret)) { + ret = -EINVAL; + goto de_init; + } + if (!dmic_status) { + ret = -ENODEV; + goto de_init; + } +#endif + } + adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource) * 2, GFP_KERNEL); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index 75228e306e0b..14620399d766 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -55,6 +55,8 @@ #define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) #define MIN_BUFFER MAX_BUFFER +#define ACP_DMIC_AUTO -1 + struct pdm_dev_data { u32 pdm_irq; void __iomem *acp_base; diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index e98601eccfa3..b1a28a9382fb 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -118,48 +118,30 @@ static const struct snd_pcm_hardware atmel_classd_hw = { static int atmel_classd_cpu_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 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, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); if (params_physical_width(params) != 16) { @@ -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_mute_stream(struct snd_soc_dai *cpu_dai, + int mute, int direction) { - 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 snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 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,19 +378,19 @@ 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 snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); 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,17 @@ 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, + .mute_stream = atmel_classd_cpu_dai_mute_stream, + .hw_params = atmel_classd_cpu_dai_hw_params, + .prepare = atmel_classd_cpu_dai_prepare, + .trigger = atmel_classd_cpu_dai_trigger, + .no_capture_mute = 1, }; -#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 +447,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 +487,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 +590,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..e597e35459ce 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 @@ -53,7 +53,7 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = { static void atmel_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pcm_dma_params *prtd; prtd = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); @@ -78,7 +78,7 @@ static void atmel_pcm_dma_irq(u32 ssc_sr, static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pcm_dma_params *prtd; struct ssc_device *ssc; int ret; diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c index a8daebcbf6c8..704f700013d3 100644 --- a/sound/soc/atmel/atmel-pcm-pdc.c +++ b/sound/soc/atmel/atmel-pcm-pdc.c @@ -205,7 +205,7 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct atmel_runtime_data *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* this may get called several times by oss emulation * with different params */ diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 04ec6f0af179..8e1d8230b180 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -104,7 +104,7 @@ static struct atmel_pdmic_pdata *atmel_pdmic_dt_init(struct device *dev) static int atmel_pdmic_cpu_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -132,7 +132,7 @@ static int atmel_pdmic_cpu_dai_startup(struct snd_pcm_substream *substream, static void atmel_pdmic_cpu_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); /* Disable the overrun error interrupt */ @@ -145,34 +145,28 @@ static void atmel_pdmic_cpu_dai_shutdown(struct snd_pcm_substream *substream, static int atmel_pdmic_cpu_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 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) @@ -197,7 +191,7 @@ atmel_pdmic_platform_configure_dma(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -290,10 +284,10 @@ static int pdmic_get_mic_volsw(struct snd_kcontrol *kcontrol, unsigned int dgain_val, scale_val; int i; - dgain_val = (snd_soc_component_read32(component, PDMIC_DSPR1) & PDMIC_DSPR1_DGAIN_MASK) + dgain_val = (snd_soc_component_read(component, PDMIC_DSPR1) & PDMIC_DSPR1_DGAIN_MASK) >> PDMIC_DSPR1_DGAIN_SHIFT; - scale_val = (snd_soc_component_read32(component, PDMIC_DSPR0) & PDMIC_DSPR0_SCALE_MASK) + scale_val = (snd_soc_component_read(component, PDMIC_DSPR0) & PDMIC_DSPR0_SCALE_MASK) >> PDMIC_DSPR0_SCALE_SHIFT; for (i = 0; i < ARRAY_SIZE(mic_gain_table); i++) { @@ -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 snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 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/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index 148c943cb538..9e237580afa9 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -26,7 +26,7 @@ static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = { static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index d649037bda9b..5f8baad37a40 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -94,7 +94,7 @@ static struct snd_soc_card db1550_ac97_machine = { static int db1200_i2s_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* WM8731 has its own 12MHz crystal */ diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index e82bbf2d1eea..3d67e27fada9 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -278,7 +278,7 @@ static int au1xpsc_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream, component); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int stype = substream->stream, *dmaids; dmaids = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c index 4e246c7e78f2..7f5be90c9ed1 100644 --- a/sound/soc/au1x/dma.c +++ b/sound/soc/au1x/dma.c @@ -191,7 +191,7 @@ static int alchemy_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream, component); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int *dmaids, s = substream->stream; char *name; diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index d80b570e950e..dc34fe1559c6 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -841,9 +841,12 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) dev->clk_prepared = false; dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { - dev_err(&pdev->dev, "could not get clk: %ld\n", - PTR_ERR(dev->clk)); - return PTR_ERR(dev->clk); + ret = PTR_ERR(dev->clk); + if (ret == -EPROBE_DEFER) + dev_dbg(&pdev->dev, "could not get clk: %d\n", ret); + else + dev_err(&pdev->dev, "could not get clk: %d\n", ret); + return ret; } /* Request ioarea */ diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c index b7a1efc7406e..7ec8559d53a2 100644 --- a/sound/soc/bcm/bcm63xx-pcm-whistler.c +++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c @@ -45,7 +45,7 @@ static int bcm63xx_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_hw_params *params) { struct i2s_dma_desc *dma_desc; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); @@ -64,7 +64,7 @@ static int bcm63xx_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct i2s_dma_desc *dma_desc; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); kfree(dma_desc); @@ -81,7 +81,7 @@ static int bcm63xx_pcm_trigger(struct snd_soc_component *component, struct bcm_i2s_priv *i2s_priv; struct regmap *regmap_i2s; - rtd = substream->private_data; + rtd = asoc_substream_to_rtd(substream); i2s_priv = dev_get_drvdata(asoc_rtd_to_cpu(rtd, 0)->dev); regmap_i2s = i2s_priv->regmap_i2s; @@ -148,7 +148,7 @@ static int bcm63xx_pcm_prepare(struct snd_soc_component *component, struct i2s_dma_desc *dma_desc; struct regmap *regmap_i2s; struct bcm_i2s_priv *i2s_priv; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; uint32_t regaddr_desclen, regaddr_descaddr; @@ -267,7 +267,7 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv) if (int_status & I2S_RX_DESC_OFF_INTR_EN_MSK) { substream = i2s_priv->capture_substream; runtime = substream->runtime; - rtd = substream->private_data; + rtd = asoc_substream_to_rtd(substream); prtd = runtime->private_data; dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); @@ -315,7 +315,7 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv) if (int_status & I2S_TX_DESC_OFF_INTR_EN_MSK) { substream = i2s_priv->play_substream; runtime = substream->runtime; - rtd = substream->private_data; + rtd = asoc_substream_to_rtd(substream); prtd = runtime->private_data; dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index f96d27c8b301..7ad07239f99c 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -207,7 +207,7 @@ static u64 cygnus_dma_dmamask = DMA_BIT_MASK(32); static struct cygnus_aio_port *cygnus_dai_get_dma_data( struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); return snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(soc_runtime, 0), substream); } @@ -353,7 +353,7 @@ static void enable_intr(struct snd_pcm_substream *substream) static void disable_intr(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct cygnus_aio_port *aio; u32 set_mask; @@ -581,7 +581,7 @@ static irqreturn_t cygnus_dma_irq(int irq, void *data) static int cygnus_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; int ret; @@ -618,7 +618,7 @@ static int cygnus_pcm_open(struct snd_soc_component *component, static int cygnus_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct cygnus_aio_port *aio; aio = cygnus_dai_get_dma_data(substream); @@ -640,7 +640,7 @@ static int cygnus_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; @@ -656,7 +656,7 @@ static int cygnus_pcm_hw_params(struct snd_soc_component *component, static int cygnus_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct cygnus_aio_port *aio; aio = cygnus_dai_get_dma_data(substream); @@ -669,7 +669,7 @@ static int cygnus_pcm_hw_free(struct snd_soc_component *component, static int cygnus_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; unsigned long bufsize, periodsize; @@ -733,7 +733,7 @@ static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component, static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) { struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_dma_buffer *buf = &substream->dma_buffer; size_t size; diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index ccf65f087ea6..7b6cdc9c8a23 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c @@ -22,7 +22,7 @@ static int edb93xx_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int err; diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 1c45fb9ff990..16f9bb283b5c 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c @@ -285,7 +285,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, /* * As per Cirrus EP93xx errata described below: * - * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf + * https://www.cirrus.com/en/pubs/errata/ER667E2B.pdf * * we will wait for the TX FIFO to be empty before * clearing the TEN bit. diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index cb133e80b7c3..c4b112921661 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -22,7 +22,7 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int err; diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 00b2c43d28a1..cac7e557edc8 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -274,10 +274,10 @@ static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol, unsigned int reg2 = mc->rreg; int val[2], val2[2], i; - val[0] = snd_soc_component_read32(component, reg) & 0x3f; - val[1] = (snd_soc_component_read32(component, PM860X_SIDETONE_SHIFT) >> 4) & 0xf; - val2[0] = snd_soc_component_read32(component, reg2) & 0x3f; - val2[1] = (snd_soc_component_read32(component, PM860X_SIDETONE_SHIFT)) & 0xf; + val[0] = snd_soc_component_read(component, reg) & 0x3f; + val[1] = (snd_soc_component_read(component, PM860X_SIDETONE_SHIFT) >> 4) & 0xf; + val2[0] = snd_soc_component_read(component, reg2) & 0x3f; + val2[1] = (snd_soc_component_read(component, PM860X_SIDETONE_SHIFT)) & 0xf; for (i = 0; i < ARRAY_SIZE(st_table); i++) { if ((st_table[i].m == val[0]) && (st_table[i].n == val[1])) @@ -333,8 +333,8 @@ static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol, int max = mc->max, val, val2; unsigned int mask = (1 << fls(max)) - 1; - val = snd_soc_component_read32(component, reg) >> shift; - val2 = snd_soc_component_read32(component, reg2) >> shift; + val = snd_soc_component_read(component, reg) >> shift; + val2 = snd_soc_component_read(component, reg2) >> shift; ucontrol->value.integer.value[0] = (max - val) & mask; ucontrol->value.integer.value[1] = (max - val2) & mask; @@ -426,7 +426,7 @@ static int pm860x_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, PM860X_EAR_CTRL_2, RSYNC_CHANGE, RSYNC_CHANGE); /* update dac */ - data = snd_soc_component_read32(component, PM860X_DAC_EN_2); + data = snd_soc_component_read(component, PM860X_DAC_EN_2); data &= ~dac; if (!(data & (DAC_LEFT | DAC_RIGHT))) data &= ~MODULATOR; @@ -902,7 +902,7 @@ static const struct snd_soc_dapm_route pm860x_dapm_routes[] = { * Use MUTE_LEFT & MUTE_RIGHT to implement digital mute. * These bits can also be used to mute. */ -static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int pm860x_mute_stream(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; int data = 0, mask = MUTE_LEFT | MUTE_RIGHT; @@ -1136,17 +1136,19 @@ static int pm860x_set_bias_level(struct snd_soc_component *component, } static const struct snd_soc_dai_ops pm860x_pcm_dai_ops = { - .digital_mute = pm860x_digital_mute, + .mute_stream = pm860x_mute_stream, .hw_params = pm860x_pcm_hw_params, .set_fmt = pm860x_pcm_set_dai_fmt, .set_sysclk = pm860x_set_dai_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops pm860x_i2s_dai_ops = { - .digital_mute = pm860x_digital_mute, + .mute_stream = pm860x_mute_stream, .hw_params = pm860x_i2s_hw_params, .set_fmt = pm860x_i2s_set_dai_fmt, .set_sysclk = pm860x_set_dai_sysclk, + .no_capture_mute = 1, }; #define PM860X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ 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 98e25d93440c..31a8c4162d20 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -1100,7 +1100,7 @@ static void anc_configure(struct snd_soc_component *component, if (apply_fir) for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) { - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, drvdata->anc_fir_values[par]); anc_fir(component, bnk, par, val); } @@ -1108,7 +1108,7 @@ static void anc_configure(struct snd_soc_component *component, if (apply_iir) for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) { - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, drvdata->anc_iir_values[par]); anc_iir(component, bnk, par, val); } @@ -1153,7 +1153,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, mutex_lock(&drvdata->ctrl_lock); - sidconf = snd_soc_component_read32(component, AB8500_SIDFIRCONF); + sidconf = snd_soc_component_read(component, AB8500_SIDFIRCONF); if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { if ((sidconf & BIT(AB8500_SIDFIRCONF_ENFIRSIDS)) == 0) { dev_err(component->dev, "%s: Sidetone busy while off!\n", @@ -1168,7 +1168,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, snd_soc_component_write(component, AB8500_SIDFIRADR, 0); for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) { - val = snd_soc_component_read32(component, drvdata->sid_fir_values[param]); + val = snd_soc_component_read(component, drvdata->sid_fir_values[param]); snd_soc_component_write(component, AB8500_SIDFIRCOEF1, val >> 8 & 0xff); snd_soc_component_write(component, AB8500_SIDFIRCOEF2, val & 0xff); } @@ -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/ad193x.c b/sound/soc/codecs/ad193x.c index 980e024a5720..f37ab7eda615 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -143,7 +143,7 @@ static inline bool ad193x_has_adc(const struct ad193x_priv *ad193x) * DAI ops entries */ -static int ad193x_mute(struct snd_soc_dai *dai, int mute) +static int ad193x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(dai->component); @@ -371,10 +371,11 @@ static int ad193x_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops ad193x_dai_ops = { .startup = ad193x_startup, .hw_params = ad193x_hw_params, - .digital_mute = ad193x_mute, + .mute_stream = ad193x_mute, .set_tdm_slot = ad193x_set_tdm_slot, .set_sysclk = ad193x_set_dai_sysclk, .set_fmt = ad193x_set_dai_fmt, + .no_capture_mute = 1, }; /* codec DAI instance */ diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 43b1337bac37..9fd2023da218 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -256,7 +256,7 @@ static int ad1980_soc_probe(struct snd_soc_component *component) if (ret < 0) goto reset_err; - vendor_id2 = snd_soc_component_read32(component, AC97_VENDOR_ID2); + vendor_id2 = snd_soc_component_read(component, AC97_VENDOR_ID2); if (vendor_id2 == 0x5374) { dev_warn(component->dev, "Found AD1981 - only 2/2 IN/OUT Channels supported\n"); @@ -270,7 +270,7 @@ static int ad1980_soc_probe(struct snd_soc_component *component) snd_soc_component_write(component, AC97_SURROUND_MASTER, 0x0000); /*power on LFE/CENTER/Surround DACs*/ - ext_status = snd_soc_component_read32(component, AC97_EXTENDED_STATUS); + ext_status = snd_soc_component_read(component, AC97_EXTENDED_STATUS); snd_soc_component_write(component, AC97_EXTENDED_STATUS, ext_status&~0x3800); return 0; diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 115e296b2ad6..68130eaa64a4 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -573,7 +573,7 @@ static int adau1701_set_bias_level(struct snd_soc_component *component, return 0; } -static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) +static int adau1701_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; unsigned int mask = ADAU1701_DSPCTRL_DAM; @@ -631,8 +631,9 @@ static int adau1701_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops adau1701_dai_ops = { .set_fmt = adau1701_set_dai_fmt, .hw_params = adau1701_hw_params, - .digital_mute = adau1701_digital_mute, + .mute_stream = adau1701_mute_stream, .startup = adau1701_startup, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver adau1701_dai = { 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/ak4458.c b/sound/soc/codecs/ak4458.c index 71562154c0b1..cbe3c782e0ca 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -401,29 +401,29 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const int att_speed[] = { 4080, 2040, 510, 255 }; -static int ak4458_set_dai_mute(struct snd_soc_dai *dai, int mute) +static int ak4458_set_dai_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); - int nfs, ndt, ret, reg; + int nfs, ndt, reg; int ats; nfs = ak4458->fs; - reg = snd_soc_component_read32(component, AK4458_0B_CONTROL7); + reg = snd_soc_component_read(component, AK4458_0B_CONTROL7); ats = (reg & AK4458_ATS_MASK) >> AK4458_ATS_SHIFT; ndt = att_speed[ats] / (nfs / 1000); if (mute) { - ret = snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 1); + snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 1); mdelay(ndt); if (ak4458->mute_gpiod) gpiod_set_value_cansleep(ak4458->mute_gpiod, 1); } else { if (ak4458->mute_gpiod) gpiod_set_value_cansleep(ak4458->mute_gpiod, 0); - ret = snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 0); + snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 0); mdelay(ndt); } @@ -495,8 +495,9 @@ static const struct snd_soc_dai_ops ak4458_dai_ops = { .startup = ak4458_startup, .hw_params = ak4458_hw_params, .set_fmt = ak4458_set_dai_fmt, - .digital_mute = ak4458_set_dai_mute, + .mute_stream = ak4458_set_dai_mute, .set_tdm_slot = ak4458_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ak4458_dai = { diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index b2635f3b11ca..91e7a57c43da 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -261,7 +261,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct ak4535_priv *ak4535 = snd_soc_component_get_drvdata(component); - u8 mode2 = snd_soc_component_read32(component, AK4535_MODE2) & ~(0x3 << 5); + u8 mode2 = snd_soc_component_read(component, AK4535_MODE2) & ~(0x3 << 5); int rate = params_rate(params), fs = 256; if (rate) @@ -309,10 +309,11 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int ak4535_mute(struct snd_soc_dai *dai, int mute) +static int ak4535_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, AK4535_DAC); + u16 mute_reg = snd_soc_component_read(component, AK4535_DAC); + if (!mute) snd_soc_component_write(component, AK4535_DAC, mute_reg & ~0x20); else @@ -348,8 +349,9 @@ static int ak4535_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ak4535_dai_ops = { .hw_params = ak4535_hw_params, .set_fmt = ak4535_set_dai_fmt, - .digital_mute = ak4535_mute, + .mute_stream = ak4535_mute, .set_sysclk = ak4535_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ak4535_dai = { diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index c1181a20714d..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; @@ -490,8 +490,8 @@ static void ak4613_dummy_write(struct work_struct *work) */ udelay(5000000 / priv->rate); - snd_soc_component_read(component, PW_MGMT1, &mgmt1); - snd_soc_component_read(component, PW_MGMT3, &mgmt3); + mgmt1 = snd_soc_component_read(component, PW_MGMT1); + mgmt3 = snd_soc_component_read(component, PW_MGMT3); snd_soc_component_write(component, PW_MGMT1, mgmt1); snd_soc_component_write(component, PW_MGMT3, mgmt3); diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 2d5b640aab58..77004cd7caa3 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -405,7 +405,7 @@ static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, return snd_soc_component_write(component, AK4641_MODE1, mode1); } -static int ak4641_mute(struct snd_soc_dai *dai, int mute) +static int ak4641_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -467,15 +467,17 @@ static int ak4641_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = { .hw_params = ak4641_i2s_hw_params, .set_fmt = ak4641_i2s_set_dai_fmt, - .digital_mute = ak4641_mute, + .mute_stream = ak4641_mute, .set_sysclk = ak4641_set_dai_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = { .hw_params = NULL, /* rates are controlled by BT chip */ .set_fmt = ak4641_pcm_set_dai_fmt, - .digital_mute = ak4641_mute, + .mute_stream = ak4641_mute, .set_sysclk = ak4641_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ak4641_dai[] = { diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 67564798f303..eb435235b5a3 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -425,7 +425,7 @@ static int ak4671_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; u8 fs; - fs = snd_soc_component_read32(component, AK4671_PLL_MODE_SELECT0); + fs = snd_soc_component_read(component, AK4671_PLL_MODE_SELECT0); fs &= ~AK4671_FS; switch (params_rate(params)) { @@ -471,7 +471,7 @@ static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, struct snd_soc_component *component = dai->component; u8 pll; - pll = snd_soc_component_read32(component, AK4671_PLL_MODE_SELECT0); + pll = snd_soc_component_read(component, AK4671_PLL_MODE_SELECT0); pll &= ~AK4671_PLL; switch (freq) { @@ -518,7 +518,7 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) u8 format; /* set master/slave audio interface */ - mode = snd_soc_component_read32(component, AK4671_PLL_MODE_SELECT1); + mode = snd_soc_component_read(component, AK4671_PLL_MODE_SELECT1); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: @@ -532,7 +532,7 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } /* interface format */ - format = snd_soc_component_read32(component, AK4671_FORMAT_SELECT); + format = snd_soc_component_read(component, AK4671_FORMAT_SELECT); format &= ~AK4671_DIF; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 6added8f28da..3d1761a531f5 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -534,7 +534,7 @@ static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 0); /* pll is not used in slave mode */ - reg = snd_soc_component_read32(component, ALC5623_DAI_CONTROL); + reg = snd_soc_component_read(component, ALC5623_DAI_CONTROL); if (reg & ALC5623_DAI_SDP_SLAVE_MODE) return 0; @@ -701,7 +701,7 @@ static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, int coeff, rate; u16 iface; - iface = snd_soc_component_read32(component, ALC5623_DAI_CONTROL); + iface = snd_soc_component_read(component, ALC5623_DAI_CONTROL); iface &= ~ALC5623_DAI_I2S_DL_MASK; /* bit size */ @@ -737,11 +737,11 @@ static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int alc5623_mute(struct snd_soc_dai *dai, int mute) +static int alc5623_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT; - u16 mute_reg = snd_soc_component_read32(component, ALC5623_MISC_CTRL) & ~hp_mute; + u16 mute_reg = snd_soc_component_read(component, ALC5623_MISC_CTRL) & ~hp_mute; if (mute) mute_reg |= hp_mute; @@ -829,10 +829,11 @@ static int alc5623_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops alc5623_dai_ops = { .hw_params = alc5623_pcm_hw_params, - .digital_mute = alc5623_mute, + .mute_stream = alc5623_mute, .set_fmt = alc5623_set_dai_fmt, .set_sysclk = alc5623_set_dai_sysclk, .set_pll = alc5623_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver alc5623_dai = { diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index e4ca87cccfc6..9d6dcd3ffa57 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -694,7 +694,7 @@ static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 0); /* pll is not used in slave mode */ - reg = snd_soc_component_read32(component, ALC5632_DAI_CONTROL); + reg = snd_soc_component_read(component, ALC5632_DAI_CONTROL); if (reg & ALC5632_DAI_SDP_SLAVE_MODE) return 0; @@ -871,7 +871,7 @@ static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, int coeff, rate; u16 iface; - iface = snd_soc_component_read32(component, ALC5632_DAI_CONTROL); + iface = snd_soc_component_read(component, ALC5632_DAI_CONTROL); iface &= ~ALC5632_DAI_I2S_DL_MASK; /* bit size */ @@ -902,12 +902,12 @@ static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int alc5632_mute(struct snd_soc_dai *dai, int mute) +static int alc5632_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 hp_mute = ALC5632_MISC_HP_DEPOP_MUTE_L |ALC5632_MISC_HP_DEPOP_MUTE_R; - u16 mute_reg = snd_soc_component_read32(component, ALC5632_MISC_CTRL) & ~hp_mute; + u16 mute_reg = snd_soc_component_read(component, ALC5632_MISC_CTRL) & ~hp_mute; if (mute) mute_reg |= hp_mute; @@ -1005,10 +1005,11 @@ static int alc5632_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops alc5632_dai_ops = { .hw_params = alc5632_pcm_hw_params, - .digital_mute = alc5632_mute, + .mute_stream = alc5632_mute, .set_fmt = alc5632_set_dai_fmt, .set_sysclk = alc5632_set_dai_sysclk, .set_pll = alc5632_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver alc5632_dai = { diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9716c9624a89..1228f2de0297 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -87,7 +87,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, ARIZONA_INTERRUPT_RAW_STATUS_3); if (val & ARIZONA_SPK_OVERHEAT_STS) { dev_crit(arizona->dev, @@ -897,7 +897,7 @@ static void arizona_in_set_vu(struct snd_soc_component *component, int ena) bool arizona_input_analog(struct snd_soc_component *component, int shift) { unsigned int reg = ARIZONA_IN1L_CONTROL + ((shift / 2) * 8); - unsigned int val = snd_soc_component_read32(component, reg); + unsigned int val = snd_soc_component_read(component, reg); return !(val & ARIZONA_IN1_MODE_MASK); } @@ -937,7 +937,7 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, break; case SND_SOC_DAPM_POST_PMD: /* Disable volume updates if no inputs are enabled */ - reg = snd_soc_component_read32(component, ARIZONA_INPUT_ENABLES); + reg = snd_soc_component_read(component, ARIZONA_INPUT_ENABLES); if (reg == 0) arizona_in_set_vu(component, 0); break; @@ -1755,15 +1755,15 @@ static bool arizona_aif_cfg_changed(struct snd_soc_component *component, { int val; - val = snd_soc_component_read32(component, base + ARIZONA_AIF_BCLK_CTRL); + val = snd_soc_component_read(component, base + ARIZONA_AIF_BCLK_CTRL); if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK)) return true; - val = snd_soc_component_read32(component, base + ARIZONA_AIF_TX_BCLK_RATE); + val = snd_soc_component_read(component, base + ARIZONA_AIF_TX_BCLK_RATE); if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK)) return true; - val = snd_soc_component_read32(component, base + ARIZONA_AIF_FRAME_CTRL_1); + val = snd_soc_component_read(component, base + ARIZONA_AIF_FRAME_CTRL_1); if (frame != (val & (ARIZONA_AIF1TX_WL_MASK | ARIZONA_AIF1TX_SLOT_LEN_MASK))) return true; @@ -1813,7 +1813,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, } /* Force multiple of 2 channels for I2S mode */ - val = snd_soc_component_read32(component, base + ARIZONA_AIF_FORMAT); + val = snd_soc_component_read(component, base + ARIZONA_AIF_FORMAT); val &= ARIZONA_AIF1_FMT_MASK; if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) { arizona_aif_dbg(dai, "Forcing stereo mode\n"); @@ -1845,9 +1845,9 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, if (reconfig) { /* Save AIF TX/RX state */ - aif_tx_state = snd_soc_component_read32(component, + aif_tx_state = snd_soc_component_read(component, base + ARIZONA_AIF_TX_ENABLES); - aif_rx_state = snd_soc_component_read32(component, + aif_rx_state = snd_soc_component_read(component, base + ARIZONA_AIF_RX_ENABLES); /* Disable AIF TX/RX before reconfiguring it */ regmap_update_bits_async(arizona->regmap, diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index d7f05b384f1f..f046987ee4cd 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -1216,7 +1216,7 @@ static int cpcap_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai, return regmap_update_bits(cpcap->regmap, reg, mask, val); } -static int cpcap_hifi_set_mute(struct snd_soc_dai *dai, int mute) +static int cpcap_hifi_set_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); @@ -1237,7 +1237,8 @@ static const struct snd_soc_dai_ops cpcap_dai_hifi_ops = { .hw_params = cpcap_hifi_hw_params, .set_sysclk = cpcap_hifi_set_dai_sysclk, .set_fmt = cpcap_hifi_set_dai_fmt, - .digital_mute = cpcap_hifi_set_mute, + .mute_stream = cpcap_hifi_set_mute, + .no_capture_mute = 1, }; static int cpcap_voice_hw_params(struct snd_pcm_substream *substream, @@ -1370,7 +1371,8 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute) +static int cpcap_voice_set_mute(struct snd_soc_dai *dai, + int mute, int direction) { struct snd_soc_component *component = dai->component; struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); @@ -1391,7 +1393,8 @@ static const struct snd_soc_dai_ops cpcap_dai_voice_ops = { .hw_params = cpcap_voice_hw_params, .set_sysclk = cpcap_voice_set_dai_sysclk, .set_fmt = cpcap_voice_set_dai_fmt, - .digital_mute = cpcap_voice_set_mute, + .mute_stream = cpcap_voice_set_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cpcap_dai[] = { diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index b0cc61178a41..0aae5790222a 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -30,7 +30,7 @@ static const struct snd_kcontrol_new cq93vc_snd_controls[] = { SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0), }; -static int cq93vc_mute(struct snd_soc_dai *dai, int mute) +static int cq93vc_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u8 reg; @@ -87,8 +87,9 @@ static int cq93vc_set_bias_level(struct snd_soc_component *component, #define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) static const struct snd_soc_dai_ops cq93vc_dai_ops = { - .digital_mute = cq93vc_mute, + .mute_stream = cq93vc_mute, .set_sysclk = cq93vc_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cq93vc_dai = { 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/cs4265.c b/sound/soc/codecs/cs4265.c index 2fb65f246b0c..d76be44f46b4 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -378,7 +378,7 @@ static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs4265_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -498,9 +498,10 @@ static int cs4265_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops cs4265_ops = { .hw_params = cs4265_pcm_hw_params, - .digital_mute = cs4265_digital_mute, + .mute_stream = cs4265_mute, .set_fmt = cs4265_set_fmt, .set_sysclk = cs4265_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4265_dai[] = { diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 8a02791e44ad..ddd95c8269ed 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -355,7 +355,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, /* Set the sample rate */ - reg = snd_soc_component_read32(component, CS4270_MODE); + reg = snd_soc_component_read(component, CS4270_MODE); reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); reg |= cs4270_mode_ratios[i].mclk; @@ -372,7 +372,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, /* Set the DAI format */ - reg = snd_soc_component_read32(component, CS4270_FORMAT); + reg = snd_soc_component_read(component, CS4270_FORMAT); reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); switch (cs4270->mode) { @@ -406,13 +406,13 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, * board does not have the MUTEA or MUTEB pins connected to such circuitry, * then this function will do nothing. */ -static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute) +static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct cs4270_private *cs4270 = snd_soc_component_get_drvdata(component); int reg6; - reg6 = snd_soc_component_read32(component, CS4270_MUTE); + reg6 = snd_soc_component_read(component, CS4270_MUTE); if (mute) reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; @@ -471,7 +471,8 @@ static const struct snd_soc_dai_ops cs4270_dai_ops = { .hw_params = cs4270_hw_params, .set_sysclk = cs4270_set_dai_sysclk, .set_fmt = cs4270_set_dai_fmt, - .digital_mute = cs4270_dai_mute, + .mute_stream = cs4270_dai_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4270_dai = { @@ -499,7 +500,7 @@ static struct snd_soc_dai_driver cs4270_dai = { /** * cs4270_probe - ASoC probe function - * @pdev: platform device + * @component: ASoC component * * This function is called when ASoC has all the pieces it needs to * instantiate a sound driver. @@ -540,7 +541,7 @@ static int cs4270_probe(struct snd_soc_component *component) /** * cs4270_remove - ASoC remove function - * @pdev: platform device + * @component: ASoC component * * This function is the counterpart to cs4270_probe(). */ @@ -567,7 +568,7 @@ static int cs4270_soc_suspend(struct snd_soc_component *component) struct cs4270_private *cs4270 = snd_soc_component_get_drvdata(component); int reg, ret; - reg = snd_soc_component_read32(component, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; + reg = snd_soc_component_read(component, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; if (reg < 0) return reg; @@ -599,7 +600,7 @@ static int cs4270_soc_resume(struct snd_soc_component *component) regcache_sync(cs4270->regmap); /* ... then disable the power-down bits */ - reg = snd_soc_component_read32(component, CS4270_PWRCTL); + reg = snd_soc_component_read(component, CS4270_PWRCTL); reg &= ~CS4270_PWRCTL_PDN_ALL; return snd_soc_component_write(component, CS4270_PWRCTL, reg); diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 5125bb9b37b5..210fcbedf241 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -849,7 +849,7 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int cs42l42_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42l42_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; unsigned int regval; @@ -877,7 +877,7 @@ static int cs42l42_digital_mute(struct snd_soc_dai *dai, int mute) CS42L42_PLL_START_MASK, 1 << CS42L42_PLL_START_SHIFT); /* Read the headphone load */ - regval = snd_soc_component_read32(component, CS42L42_LOAD_DET_RCSTAT); + regval = snd_soc_component_read(component, CS42L42_LOAD_DET_RCSTAT); if (((regval & CS42L42_RLA_STAT_MASK) >> CS42L42_RLA_STAT_SHIFT) == CS42L42_RLA_STAT_15_OHM) { fullScaleVol = CS42L42_HP_FULL_SCALE_VOL_MASK; @@ -909,7 +909,8 @@ static const struct snd_soc_dai_ops cs42l42_ops = { .hw_params = cs42l42_pcm_hw_params, .set_fmt = cs42l42_set_dai_fmt, .set_sysclk = cs42l42_set_sysclk, - .digital_mute = cs42l42_digital_mute + .mute_stream = cs42l42_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l42_dai = { @@ -1658,8 +1659,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client, ret = of_property_read_u32(np, "cirrus,btn-det-init-dbnce", &val); if (!ret) { - if ((val >= CS42L42_BTN_DET_INIT_DBNCE_MIN) && - (val <= CS42L42_BTN_DET_INIT_DBNCE_MAX)) + if (val <= CS42L42_BTN_DET_INIT_DBNCE_MAX) cs42l42->btn_det_init_dbnce = val; else { dev_err(&i2c_client->dev, @@ -1676,8 +1676,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client, ret = of_property_read_u32(np, "cirrus,btn-det-event-dbnce", &val); if (!ret) { - if ((val >= CS42L42_BTN_DET_EVENT_DBNCE_MIN) && - (val <= CS42L42_BTN_DET_EVENT_DBNCE_MAX)) + if (val <= CS42L42_BTN_DET_EVENT_DBNCE_MAX) cs42l42->btn_det_event_dbnce = val; else { dev_err(&i2c_client->dev, @@ -1695,8 +1694,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client, if (!ret) { for (i = 0; i < CS42L42_NUM_BIASES; i++) { - if ((thresholds[i] >= CS42L42_HS_DET_LEVEL_MIN) && - (thresholds[i] <= CS42L42_HS_DET_LEVEL_MAX)) + if (thresholds[i] <= CS42L42_HS_DET_LEVEL_MAX) cs42l42->bias_thresholds[i] = thresholds[i]; else { dev_err(&i2c_client->dev, diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index e47758e4fb36..764f2ef8f59d 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -61,7 +61,7 @@ static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - unsigned long value = snd_soc_component_read32(component, CS42L51_PCM_MIXER)&3; + unsigned long value = snd_soc_component_read(component, CS42L51_PCM_MIXER)&3; switch (value) { default: @@ -407,8 +407,8 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - intf_ctl = snd_soc_component_read32(component, CS42L51_INTF_CTL); - power_ctl = snd_soc_component_read32(component, CS42L51_MIC_POWER_CTL); + intf_ctl = snd_soc_component_read(component, CS42L51_INTF_CTL); + power_ctl = snd_soc_component_read(component, CS42L51_MIC_POWER_CTL); intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S | CS42L51_INTF_CTL_DAC_FORMAT(7)); @@ -484,13 +484,13 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, return 0; } -static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute) +static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int reg; int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE; - reg = snd_soc_component_read32(component, CS42L51_DAC_OUT_CTL); + reg = snd_soc_component_read(component, CS42L51_DAC_OUT_CTL); if (mute) reg |= mask; @@ -511,7 +511,8 @@ static const struct snd_soc_dai_ops cs42l51_dai_ops = { .hw_params = cs42l51_hw_params, .set_sysclk = cs42l51_set_dai_sysclk, .set_fmt = cs42l51_set_dai_fmt, - .digital_mute = cs42l51_dai_mute, + .mute_stream = cs42l51_dai_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l51_dai = { diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 2ea4cba3be2a..f772628f233e 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -784,7 +784,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int cs42l52_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42l52_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -865,9 +865,10 @@ static int cs42l52_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops cs42l52_ops = { .hw_params = cs42l52_pcm_hw_params, - .digital_mute = cs42l52_digital_mute, + .mute_stream = cs42l52_mute, .set_fmt = cs42l52_set_fmt, .set_sysclk = cs42l52_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l52_dai = { diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index ac569ab3d30f..97024a6ac96d 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -800,7 +800,7 @@ static int cs42l56_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int cs42l56_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42l56_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -929,9 +929,10 @@ static int cs42l56_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops cs42l56_ops = { .hw_params = cs42l56_pcm_hw_params, - .digital_mute = cs42l56_digital_mute, + .mute_stream = cs42l56_mute, .set_fmt = cs42l56_set_dai_fmt, .set_sysclk = cs42l56_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l56_dai = { diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 36089f8bcf0a..988ca7e19821 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -938,8 +938,8 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) unsigned int inv, format; u8 spc, mmcc; - spc = snd_soc_component_read32(component, CS42L73_SPC(id)); - mmcc = snd_soc_component_read32(component, CS42L73_MMCC(id)); + spc = snd_soc_component_read(component, CS42L73_SPC(id)); + mmcc = snd_soc_component_read(component, CS42L73_MMCC(id)); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 94b1adb088fd..5d6ef660f851 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -362,7 +362,7 @@ static int cs42xx8_hw_free(struct snd_pcm_substream *substream, return 0; } -static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42xx8_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); @@ -380,7 +380,8 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = { .set_sysclk = cs42xx8_set_dai_sysclk, .hw_params = cs42xx8_hw_params, .hw_free = cs42xx8_hw_free, - .digital_mute = cs42xx8_digital_mute, + .mute_stream = cs42xx8_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42xx8_dai = { diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c index ade7477d04f1..f566604de78c 100644 --- a/sound/soc/codecs/cs4341.c +++ b/sound/soc/codecs/cs4341.c @@ -116,7 +116,7 @@ static int cs4341_hw_params(struct snd_pcm_substream *substream, CS4341_MODE2_DIF, mode); } -static int cs4341_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs4341_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int ret; @@ -174,7 +174,8 @@ static const struct snd_kcontrol_new cs4341_controls[] = { static const struct snd_soc_dai_ops cs4341_dai_ops = { .set_fmt = cs4341_set_fmt, .hw_params = cs4341_hw_params, - .digital_mute = cs4341_digital_mute, + .mute_stream = cs4341_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4341_dai = { diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index 3381209a882d..fd5526319779 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -131,7 +131,7 @@ static int cs4349_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int cs4349_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs4349_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int reg; @@ -236,7 +236,8 @@ static const struct snd_soc_dapm_route cs4349_routes[] = { static const struct snd_soc_dai_ops cs4349_dai_ops = { .hw_params = cs4349_pcm_hw_params, .set_fmt = cs4349_set_dai_fmt, - .digital_mute = cs4349_digital_mute, + .mute_stream = cs4349_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4349_dai = { diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 402c6b7c7014..a591e7457d11 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -540,29 +540,29 @@ SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -631,29 +631,29 @@ SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index d7538d50bbd3..7f5dd01f40c9 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -129,19 +129,11 @@ static void cs47l35_hp_post_enable(struct snd_soc_dapm_widget *w) struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); unsigned int val; - int ret; switch (w->shift) { case MADERA_OUT1L_ENA_SHIFT: case MADERA_OUT1R_ENA_SHIFT: - ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, - &val); - if (ret) { - dev_err(component->dev, - "Failed to check output enables: %d\n", ret); - return; - } - + val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1); val &= (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA); if (val != (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA)) @@ -642,43 +634,43 @@ SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), @@ -749,43 +741,43 @@ SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 9de991adad74..47b16466b6c1 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -191,19 +191,11 @@ static void cs47l85_hp_post_enable(struct snd_soc_dapm_widget *w) struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); unsigned int val; - int ret; switch (w->shift) { case MADERA_OUT1L_ENA_SHIFT: case MADERA_OUT1R_ENA_SHIFT: - ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, - &val); - if (ret) { - dev_err(component->dev, - "Failed to check output enables: %d\n", ret); - return; - } - + val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1); val &= (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA); if (val != (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA)) @@ -1024,71 +1016,71 @@ SND_SOC_DAPM_MUX("SPKDAT2R ANC Source", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 6, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 7, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF4TX1", NULL, 0, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 1, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -1213,70 +1205,70 @@ SND_SOC_DAPM_PGA_E("IN6R", MADERA_INPUT_ENABLES, MADERA_IN6R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 6, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 7, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF4RX1", NULL, 0, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 1, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX8_ENA_SHIFT, 0), diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 2715b5da0415..8838dd557321 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -977,71 +977,71 @@ SND_SOC_DAPM_MUX("SPKDAT1R ANC Source", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 6, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 7, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF4TX1", NULL, 0, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 1, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -1147,63 +1147,63 @@ SND_SOC_DAPM_PGA_E("IN5R", MADERA_INPUT_ENABLES, MADERA_IN5R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 6, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 7, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF4RX1", NULL, 0, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 1, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX8_ENA_SHIFT, 0), SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index 108d28007185..6e34106c268f 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -790,70 +790,70 @@ SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 6, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 7, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX3", NULL, 2, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX4", NULL, 3, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX4_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -948,62 +948,62 @@ SND_SOC_DAPM_PGA_E("IN4R", MADERA_INPUT_ENABLES, MADERA_IN4R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 6, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 7, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX3", NULL, 2, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX4", NULL, 3, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX4_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX8_ENA_SHIFT, 0), SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index e172913d04a4..3d05c37f676e 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -330,7 +330,7 @@ static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0]) { /* Check if noise suppression is enabled */ - if (snd_soc_component_read32(component, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) { + if (snd_soc_component_read(component, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) { dev_dbg(component->dev, "Disable noise suppression to enable ALC\n"); return -EINVAL; @@ -354,27 +354,27 @@ static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0]) { /* Check if ALC is enabled */ - if (snd_soc_component_read32(component, DA7210_ADC) & DA7210_ADC_ALC_EN) + if (snd_soc_component_read(component, DA7210_ADC) & DA7210_ADC_ALC_EN) goto err; /* Check ZC for HP and AUX1 PGA */ - if ((snd_soc_component_read32(component, DA7210_ZERO_CROSS) & + if ((snd_soc_component_read(component, DA7210_ZERO_CROSS) & (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC)) goto err; /* Check INPGA_L_VOL and INPGA_R_VOL */ - val = snd_soc_component_read32(component, DA7210_IN_GAIN); + val = snd_soc_component_read(component, DA7210_IN_GAIN); if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) || (((val & DA7210_INPGA_R_VOL) >> 4) < DA7210_INPGA_MIN_VOL_NS)) goto err; /* Check AUX1_L_VOL and AUX1_R_VOL */ - if (((snd_soc_component_read32(component, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) < + if (((snd_soc_component_read(component, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) < DA7210_AUX1_MIN_VOL_NS) || - ((snd_soc_component_read32(component, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) < + ((snd_soc_component_read(component, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) < DA7210_AUX1_MIN_VOL_NS)) goto err; } @@ -767,7 +767,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, /* Enable DAI */ snd_soc_component_write(component, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN); - dai_cfg1 = 0xFC & snd_soc_component_read32(component, DA7210_DAI_CFG1); + dai_cfg1 = 0xFC & snd_soc_component_read(component, DA7210_DAI_CFG1); switch (params_width(params)) { case 16: @@ -874,11 +874,11 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) u32 dai_cfg1; u32 dai_cfg3; - dai_cfg1 = 0x7f & snd_soc_component_read32(component, DA7210_DAI_CFG1); - dai_cfg3 = 0xfc & snd_soc_component_read32(component, DA7210_DAI_CFG3); + dai_cfg1 = 0x7f & snd_soc_component_read(component, DA7210_DAI_CFG1); + dai_cfg3 = 0xfc & snd_soc_component_read(component, DA7210_DAI_CFG3); - if ((snd_soc_component_read32(component, DA7210_PLL) & DA7210_PLL_EN) && - (!(snd_soc_component_read32(component, DA7210_PLL_DIV3) & DA7210_PLL_BYP))) + if ((snd_soc_component_read(component, DA7210_PLL) & DA7210_PLL_EN) && + (!(snd_soc_component_read(component, DA7210_PLL_DIV3) & DA7210_PLL_BYP))) return -EINVAL; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -924,10 +924,10 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) return 0; } -static int da7210_mute(struct snd_soc_dai *dai, int mute) +static int da7210_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u8 mute_reg = snd_soc_component_read32(component, DA7210_DAC_HPF) & 0xFB; + u8 mute_reg = snd_soc_component_read(component, DA7210_DAC_HPF) & 0xFB; if (mute) snd_soc_component_write(component, DA7210_DAC_HPF, mute_reg | 0x4); @@ -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) @@ -1034,7 +1036,8 @@ static const struct snd_soc_dai_ops da7210_dai_ops = { .set_fmt = da7210_set_dai_fmt, .set_sysclk = da7210_set_dai_sysclk, .set_pll = da7210_set_dai_pll, - .digital_mute = da7210_mute, + .mute_stream = da7210_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver da7210_dai = { diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 3e6ad996741b..72402467adcc 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -205,12 +205,12 @@ static int da7213_get_alc_data(struct snd_soc_component *component, u8 reg_val) /* Select middle 8 bits for read back from data register */ snd_soc_component_write(component, DA7213_ALC_CIC_OP_LVL_CTRL, reg_val | DA7213_ALC_DATA_MIDDLE); - mid_data = snd_soc_component_read32(component, DA7213_ALC_CIC_OP_LVL_DATA); + mid_data = snd_soc_component_read(component, DA7213_ALC_CIC_OP_LVL_DATA); /* Select top 8 bits for read back from data register */ snd_soc_component_write(component, DA7213_ALC_CIC_OP_LVL_CTRL, reg_val | DA7213_ALC_DATA_TOP); - top_data = snd_soc_component_read32(component, DA7213_ALC_CIC_OP_LVL_DATA); + top_data = snd_soc_component_read(component, DA7213_ALC_CIC_OP_LVL_DATA); sum += ((mid_data << 8) | (top_data << 16)); } @@ -259,7 +259,7 @@ static void da7213_alc_calib_auto(struct snd_soc_component *component) snd_soc_component_update_bits(component, DA7213_ALC_CTRL1, DA7213_ALC_AUTO_CALIB_EN, DA7213_ALC_AUTO_CALIB_EN); do { - alc_ctrl1 = snd_soc_component_read32(component, DA7213_ALC_CTRL1); + alc_ctrl1 = snd_soc_component_read(component, DA7213_ALC_CTRL1); } while (alc_ctrl1 & DA7213_ALC_AUTO_CALIB_EN); /* If auto calibration fails, fall back to digital gain only mode */ @@ -286,16 +286,16 @@ static void da7213_alc_calib(struct snd_soc_component *component) u8 mic_1_ctrl, mic_2_ctrl; /* Save current values from ADC control registers */ - adc_l_ctrl = snd_soc_component_read32(component, DA7213_ADC_L_CTRL); - adc_r_ctrl = snd_soc_component_read32(component, DA7213_ADC_R_CTRL); + adc_l_ctrl = snd_soc_component_read(component, DA7213_ADC_L_CTRL); + adc_r_ctrl = snd_soc_component_read(component, DA7213_ADC_R_CTRL); /* Save current values from MIXIN_L/R_SELECT registers */ - mixin_l_sel = snd_soc_component_read32(component, DA7213_MIXIN_L_SELECT); - mixin_r_sel = snd_soc_component_read32(component, DA7213_MIXIN_R_SELECT); + mixin_l_sel = snd_soc_component_read(component, DA7213_MIXIN_L_SELECT); + mixin_r_sel = snd_soc_component_read(component, DA7213_MIXIN_R_SELECT); /* Save current values from MIC control registers */ - mic_1_ctrl = snd_soc_component_read32(component, DA7213_MIC_1_CTRL); - mic_2_ctrl = snd_soc_component_read32(component, DA7213_MIC_2_CTRL); + mic_1_ctrl = snd_soc_component_read(component, DA7213_MIC_1_CTRL); + mic_2_ctrl = snd_soc_component_read(component, DA7213_MIC_2_CTRL); /* Enable ADC Left and Right */ snd_soc_component_update_bits(component, DA7213_ADC_L_CTRL, DA7213_ADC_EN, @@ -751,7 +751,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, DA7213_PC_FREERUN_MASK, 0); /* If SRM not enabled then nothing more to do */ - pll_ctrl = snd_soc_component_read32(component, DA7213_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7213_PLL_CTRL); if (!(pll_ctrl & DA7213_PLL_SRM_EN)) return 0; @@ -764,7 +764,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, /* Check SRM has locked */ do { - pll_status = snd_soc_component_read32(component, DA7213_PLL_STATUS); + pll_status = snd_soc_component_read(component, DA7213_PLL_STATUS); if (pll_status & DA7219_PLL_SRM_LOCK) { srm_lock = true; } else { @@ -779,7 +779,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, return 0; case SND_SOC_DAPM_POST_PMD: /* Revert 32KHz PLL lock udpates if applied previously */ - pll_ctrl = snd_soc_component_read32(component, DA7213_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7213_PLL_CTRL); if (pll_ctrl & DA7213_PLL_32K_MODE) { snd_soc_component_write(component, 0xF0, 0x8B); snd_soc_component_write(component, 0xF2, 0x01); @@ -1156,6 +1156,7 @@ static int da7213_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; + struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); u8 dai_ctrl = 0; u8 fs; @@ -1181,33 +1182,43 @@ static int da7213_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: fs = DA7213_SR_8000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 11025: fs = DA7213_SR_11025; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 12000: fs = DA7213_SR_12000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 16000: fs = DA7213_SR_16000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 22050: fs = DA7213_SR_22050; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 32000: fs = DA7213_SR_32000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 44100: fs = DA7213_SR_44100; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 48000: fs = DA7213_SR_48000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 88200: fs = DA7213_SR_88200; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 96000: fs = DA7213_SR_96000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; default: return -EINVAL; @@ -1321,7 +1332,7 @@ static int da7213_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int da7213_mute(struct snd_soc_dai *dai, int mute) +static int da7213_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -1392,9 +1403,9 @@ static int da7213_set_component_sysclk(struct snd_soc_component *component, } /* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */ -static int da7213_set_component_pll(struct snd_soc_component *component, - int pll_id, int source, - unsigned int fref, unsigned int fout) +static int _da7213_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, + unsigned int fref, unsigned int fout) { struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); @@ -1503,11 +1514,22 @@ static int da7213_set_component_pll(struct snd_soc_component *component, return 0; } +static int da7213_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, + unsigned int fref, unsigned int fout) +{ + struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); + da7213->fixed_clk_auto_pll = false; + + return _da7213_set_component_pll(component, pll_id, source, fref, fout); +} + /* DAI operations */ static const struct snd_soc_dai_ops da7213_dai_ops = { .hw_params = da7213_hw_params, .set_fmt = da7213_set_dai_fmt, - .digital_mute = da7213_mute, + .mute_stream = da7213_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver da7213_dai = { @@ -1532,6 +1554,50 @@ static struct snd_soc_dai_driver da7213_dai = { .symmetric_rates = 1, }; +static int da7213_set_auto_pll(struct snd_soc_component *component, bool enable) +{ + struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); + int mode; + + if (!da7213->fixed_clk_auto_pll) + return 0; + + da7213->mclk_rate = clk_get_rate(da7213->mclk); + + if (enable) { + /* Slave mode needs SRM for non-harmonic frequencies */ + if (da7213->master) + mode = DA7213_SYSCLK_PLL; + else + mode = DA7213_SYSCLK_PLL_SRM; + + /* PLL is not required for harmonic frequencies */ + switch (da7213->out_rate) { + case DA7213_PLL_FREQ_OUT_90316800: + if (da7213->mclk_rate == 11289600 || + da7213->mclk_rate == 22579200 || + da7213->mclk_rate == 45158400) + mode = DA7213_SYSCLK_MCLK; + break; + case DA7213_PLL_FREQ_OUT_98304000: + if (da7213->mclk_rate == 12288000 || + da7213->mclk_rate == 24576000 || + da7213->mclk_rate == 49152000) + mode = DA7213_SYSCLK_MCLK; + + break; + default: + return -1; + } + } else { + /* Disable PLL in standby */ + mode = DA7213_SYSCLK_MCLK; + } + + return _da7213_set_component_pll(component, 0, mode, + da7213->mclk_rate, da7213->out_rate); +} + static int da7213_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { @@ -1551,6 +1617,8 @@ static int da7213_set_bias_level(struct snd_soc_component *component, "Failed to enable mclk\n"); return ret; } + + da7213_set_auto_pll(component, true); } } break; @@ -1562,8 +1630,10 @@ static int da7213_set_bias_level(struct snd_soc_component *component, DA7213_VMID_EN | DA7213_BIAS_EN); } else { /* Remove MCLK */ - if (da7213->mclk) + if (da7213->mclk) { + da7213_set_auto_pll(component, false); clk_disable_unprepare(da7213->mclk); + } } break; case SND_SOC_BIAS_OFF: @@ -1693,7 +1763,6 @@ static struct da7213_platform_data return pdata; } - static int da7213_probe(struct snd_soc_component *component) { struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); @@ -1829,6 +1898,11 @@ static int da7213_probe(struct snd_soc_component *component) return PTR_ERR(da7213->mclk); else da7213->mclk = NULL; + } else { + /* Do automatic PLL handling assuming fixed clock until + * set_pll() has been called. This makes the codec usable + * with the simple-audio-card driver. */ + da7213->fixed_clk_auto_pll = true; } return 0; diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index 3890829dfb6e..97ccf0ddd2be 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h @@ -535,10 +535,12 @@ struct da7213_priv { struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES]; struct clk *mclk; unsigned int mclk_rate; + unsigned int out_rate; int clk_src; bool master; bool alc_calib_auto; bool alc_en; + bool fixed_clk_auto_pll; struct da7213_platform_data *pdata; }; diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index a3003f299868..6d78bccb55c3 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -298,22 +298,22 @@ static void da7218_alc_calib(struct snd_soc_component *component) bool calibrated = false; /* Save current state of MIC control registers */ - mic_1_ctrl = snd_soc_component_read32(component, DA7218_MIC_1_CTRL); - mic_2_ctrl = snd_soc_component_read32(component, DA7218_MIC_2_CTRL); + mic_1_ctrl = snd_soc_component_read(component, DA7218_MIC_1_CTRL); + mic_2_ctrl = snd_soc_component_read(component, DA7218_MIC_2_CTRL); /* Save current state of input mixer control registers */ - mixin_1_ctrl = snd_soc_component_read32(component, DA7218_MIXIN_1_CTRL); - mixin_2_ctrl = snd_soc_component_read32(component, DA7218_MIXIN_2_CTRL); + mixin_1_ctrl = snd_soc_component_read(component, DA7218_MIXIN_1_CTRL); + mixin_2_ctrl = snd_soc_component_read(component, DA7218_MIXIN_2_CTRL); /* Save current state of input filter control registers */ - in_1l_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_1L_FILTER_CTRL); - in_1r_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_1R_FILTER_CTRL); - in_2l_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_2L_FILTER_CTRL); - in_2r_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_2R_FILTER_CTRL); + in_1l_filt_ctrl = snd_soc_component_read(component, DA7218_IN_1L_FILTER_CTRL); + in_1r_filt_ctrl = snd_soc_component_read(component, DA7218_IN_1R_FILTER_CTRL); + in_2l_filt_ctrl = snd_soc_component_read(component, DA7218_IN_2L_FILTER_CTRL); + in_2r_filt_ctrl = snd_soc_component_read(component, DA7218_IN_2R_FILTER_CTRL); /* Save current state of input HPF control registers */ - in_1_hpf_ctrl = snd_soc_component_read32(component, DA7218_IN_1_HPF_FILTER_CTRL); - in_2_hpf_ctrl = snd_soc_component_read32(component, DA7218_IN_2_HPF_FILTER_CTRL); + in_1_hpf_ctrl = snd_soc_component_read(component, DA7218_IN_1_HPF_FILTER_CTRL); + in_2_hpf_ctrl = snd_soc_component_read(component, DA7218_IN_2_HPF_FILTER_CTRL); /* Enable then Mute MIC PGAs */ snd_soc_component_update_bits(component, DA7218_MIC_1_CTRL, DA7218_MIC_1_AMP_EN_MASK, @@ -369,7 +369,7 @@ static void da7218_alc_calib(struct snd_soc_component *component) snd_soc_component_update_bits(component, DA7218_CALIB_CTRL, DA7218_CALIB_AUTO_EN_MASK, DA7218_CALIB_AUTO_EN_MASK); do { - calib_ctrl = snd_soc_component_read32(component, DA7218_CALIB_CTRL); + calib_ctrl = snd_soc_component_read(component, DA7218_CALIB_CTRL); if (calib_ctrl & DA7218_CALIB_AUTO_EN_MASK) { ++i; usleep_range(DA7218_ALC_CALIB_DELAY_MIN, @@ -613,7 +613,7 @@ static int da7218_biquad_coeff_put(struct snd_kcontrol *kcontrol, } /* Make sure at least out filter1 enabled to allow programming */ - out_filt1l = snd_soc_component_read32(component, DA7218_OUT_1L_FILTER_CTRL); + out_filt1l = snd_soc_component_read(component, DA7218_OUT_1L_FILTER_CTRL); snd_soc_component_write(component, DA7218_OUT_1L_FILTER_CTRL, out_filt1l | DA7218_OUT_1L_FILTER_EN_MASK); @@ -1419,7 +1419,7 @@ static int da7218_dai_event(struct snd_soc_dapm_widget *w, i = 0; success = false; do { - refosc_cal = snd_soc_component_read32(component, DA7218_PLL_REFOSC_CAL); + refosc_cal = snd_soc_component_read(component, DA7218_PLL_REFOSC_CAL); if (!(refosc_cal & DA7218_PLL_REFOSC_CAL_START_MASK)) { success = true; } else { @@ -1438,7 +1438,7 @@ static int da7218_dai_event(struct snd_soc_dapm_widget *w, DA7218_PC_RESYNC_AUTO_MASK); /* If SRM not enabled, we don't need to check status */ - pll_ctrl = snd_soc_component_read32(component, DA7218_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7218_PLL_CTRL); if ((pll_ctrl & DA7218_PLL_MODE_MASK) != DA7218_PLL_MODE_SRM) return 0; @@ -1446,7 +1446,7 @@ static int da7218_dai_event(struct snd_soc_dapm_widget *w, i = 0; success = false; do { - pll_status = snd_soc_component_read32(component, DA7218_PLL_STATUS); + pll_status = snd_soc_component_read(component, DA7218_PLL_STATUS); if (pll_status & DA7218_PLL_SRM_STATUS_SRM_LOCK) { success = true; } else { @@ -2236,7 +2236,7 @@ static void da7218_hpldet_irq(struct snd_soc_component *component) u8 jack_status; int report; - jack_status = snd_soc_component_read32(component, DA7218_EVENT_STATUS); + jack_status = snd_soc_component_read(component, DA7218_EVENT_STATUS); if (jack_status & DA7218_HPLDET_JACK_STS_MASK) report = SND_JACK_HEADPHONE; @@ -2256,7 +2256,7 @@ static irqreturn_t da7218_irq_thread(int irq, void *data) u8 status; /* Read IRQ status reg */ - status = snd_soc_component_read32(component, DA7218_EVENT); + status = snd_soc_component_read(component, DA7218_EVENT); if (!status) return IRQ_NONE; diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 4f2a96e9fd45..b1dfd91609f7 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -73,7 +73,7 @@ static void da7219_aad_btn_det_work(struct work_struct *work) snd_soc_dapm_sync(dapm); do { - statusa = snd_soc_component_read32(component, DA7219_ACCDET_STATUS_A); + statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A); if (statusa & DA7219_MICBIAS_UP_STS_MASK) micbias_up = true; else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES) @@ -91,7 +91,7 @@ static void da7219_aad_btn_det_work(struct work_struct *work) */ if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) { /* Pulse higher level voltage */ - micbias_ctrl = snd_soc_component_read32(component, DA7219_MICBIAS_CTRL); + micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL); snd_soc_component_update_bits(component, DA7219_MICBIAS_CTRL, DA7219_MICBIAS1_LEVEL_MASK, da7219_aad->micbias_pulse_lvl); @@ -141,11 +141,11 @@ static void da7219_aad_hptest_work(struct work_struct *work) * If MCLK is present, but PLL is not enabled then we enable it here to * ensure a consistent detection procedure. */ - pll_srm_sts = snd_soc_component_read32(component, DA7219_PLL_SRM_STS); + pll_srm_sts = snd_soc_component_read(component, DA7219_PLL_SRM_STS); if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) { tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); - pll_ctrl = snd_soc_component_read32(component, DA7219_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7219_PLL_CTRL); if ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS) da7219_set_pll(component, DA7219_SYSCLK_PLL, DA7219_PLL_FREQ_OUT_98304); @@ -154,7 +154,7 @@ static void da7219_aad_hptest_work(struct work_struct *work) } /* Ensure gain ramping at fastest rate */ - gain_ramp_ctrl = snd_soc_component_read32(component, DA7219_GAIN_RAMP_CTRL); + gain_ramp_ctrl = snd_soc_component_read(component, DA7219_GAIN_RAMP_CTRL); snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8); /* Bypass cache so it saves current settings */ @@ -248,7 +248,7 @@ static void da7219_aad_hptest_work(struct work_struct *work) msleep(DA7219_AAD_HPTEST_PERIOD); /* Grab comparator reading */ - accdet_cfg8 = snd_soc_component_read32(component, DA7219_ACCDET_CONFIG_8); + accdet_cfg8 = snd_soc_component_read(component, DA7219_ACCDET_CONFIG_8); if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK) report |= SND_JACK_HEADPHONE; else @@ -357,7 +357,7 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) return IRQ_NONE; /* Read status register for jack insertion & type status */ - statusa = snd_soc_component_read32(component, DA7219_ACCDET_STATUS_A); + statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A); /* Clear events */ regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, @@ -847,7 +847,7 @@ void da7219_aad_suspend(struct snd_soc_component *component) * suspend then this will be dealt with through the IRQ handler. */ if (da7219_aad->jack_inserted) { - micbias_ctrl = snd_soc_component_read32(component, DA7219_MICBIAS_CTRL); + micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL); if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) { snd_soc_dapm_disable_pin(dapm, "Mic Bias"); snd_soc_dapm_sync(dapm); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index f83a6eaba12c..153ea30b5a8f 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -313,13 +313,13 @@ static void da7219_alc_calib(struct snd_soc_component *component) u8 mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; /* Save current state of mic control register */ - mic_ctrl = snd_soc_component_read32(component, DA7219_MIC_1_CTRL); + mic_ctrl = snd_soc_component_read(component, DA7219_MIC_1_CTRL); /* Save current state of input mixer control register */ - mixin_ctrl = snd_soc_component_read32(component, DA7219_MIXIN_L_CTRL); + mixin_ctrl = snd_soc_component_read(component, DA7219_MIXIN_L_CTRL); /* Save current state of input ADC control register */ - adc_ctrl = snd_soc_component_read32(component, DA7219_ADC_L_CTRL); + adc_ctrl = snd_soc_component_read(component, DA7219_ADC_L_CTRL); /* Enable then Mute MIC PGAs */ snd_soc_component_update_bits(component, DA7219_MIC_1_CTRL, DA7219_MIC_1_AMP_EN_MASK, @@ -344,7 +344,7 @@ static void da7219_alc_calib(struct snd_soc_component *component) DA7219_ALC_AUTO_CALIB_EN_MASK, DA7219_ALC_AUTO_CALIB_EN_MASK); do { - calib_ctrl = snd_soc_component_read32(component, DA7219_ALC_CTRL1); + calib_ctrl = snd_soc_component_read(component, DA7219_ALC_CTRL1); } while (calib_ctrl & DA7219_ALC_AUTO_CALIB_EN_MASK); /* If auto calibration fails, disable DC offset, hybrid ALC */ @@ -822,13 +822,13 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, DA7219_PC_FREERUN_MASK, 0); /* Slave mode, if SRM not enabled no need for status checks */ - pll_ctrl = snd_soc_component_read32(component, DA7219_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7219_PLL_CTRL); if ((pll_ctrl & DA7219_PLL_MODE_MASK) != DA7219_PLL_MODE_SRM) return 0; /* Check SRM has locked */ do { - pll_status = snd_soc_component_read32(component, DA7219_PLL_SRM_STS); + pll_status = snd_soc_component_read(component, DA7219_PLL_SRM_STS); if (pll_status & DA7219_PLL_SRM_STS_SRM_LOCK) { srm_lock = true; } else { @@ -928,7 +928,7 @@ static int da7219_gain_ramp_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMD: /* Ensure nominal gain ramping for DAPM sequence */ da7219->gain_ramp_ctrl = - snd_soc_component_read32(component, DA7219_GAIN_RAMP_CTRL); + snd_soc_component_read(component, DA7219_GAIN_RAMP_CTRL); snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_NOMINAL); break; @@ -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) @@ -1930,7 +1932,7 @@ static int da7219_wclk_is_prepared(struct clk_hw *hw) if (!da7219->master) return -EINVAL; - clk_reg = snd_soc_component_read32(component, DA7219_DAI_CLK_MODE); + clk_reg = snd_soc_component_read(component, DA7219_DAI_CLK_MODE); return !!(clk_reg & DA7219_DAI_CLK_EN_MASK); } @@ -1942,7 +1944,7 @@ static unsigned long da7219_wclk_recalc_rate(struct clk_hw *hw, container_of(hw, struct da7219_priv, dai_clks_hw[DA7219_DAI_WCLK_IDX]); struct snd_soc_component *component = da7219->component; - u8 fs = snd_soc_component_read32(component, DA7219_SR); + u8 fs = snd_soc_component_read(component, DA7219_SR); switch (fs & DA7219_SR_MASK) { case DA7219_SR_8000: @@ -2027,7 +2029,7 @@ static unsigned long da7219_bclk_recalc_rate(struct clk_hw *hw, container_of(hw, struct da7219_priv, dai_clks_hw[DA7219_DAI_BCLK_IDX]); struct snd_soc_component *component = da7219->component; - u8 bclks_per_wclk = snd_soc_component_read32(component, + u8 bclks_per_wclk = snd_soc_component_read(component, DA7219_DAI_CLK_MODE); switch (bclks_per_wclk & DA7219_DAI_BCLKS_PER_WCLK_MASK) { diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 3f60c45e1e6d..d43ee7159ae0 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -361,7 +361,7 @@ static int da732x_hpf_get(struct snd_kcontrol *kcontrol, unsigned int reg = enum_ctrl->reg; int val; - val = snd_soc_component_read32(component, reg) & DA732X_HPF_MASK; + val = snd_soc_component_read(component, reg) & DA732X_HPF_MASK; switch (val) { case DA732X_HPF_VOICE_EN: @@ -1287,9 +1287,9 @@ static void da732x_dac_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check DAC offset sign */ - sign[DA732X_HPL_DAC] = (snd_soc_component_read32(component, DA732X_REG_HPL_DAC_OFF_CNTL) & + sign[DA732X_HPL_DAC] = (snd_soc_component_read(component, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); - sign[DA732X_HPR_DAC] = (snd_soc_component_read32(component, DA732X_REG_HPR_DAC_OFF_CNTL) & + sign[DA732X_HPR_DAC] = (snd_soc_component_read(component, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); /* Binary search DAC offset values (both channels at once) */ @@ -1306,10 +1306,10 @@ static void da732x_dac_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((snd_soc_component_read32(component, DA732X_REG_HPL_DAC_OFF_CNTL) & + if ((snd_soc_component_read(component, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) offset[DA732X_HPL_DAC] &= ~step; - if ((snd_soc_component_read32(component, DA732X_REG_HPR_DAC_OFF_CNTL) & + if ((snd_soc_component_read(component, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) offset[DA732X_HPR_DAC] &= ~step; @@ -1350,9 +1350,9 @@ static void da732x_output_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check output offset sign */ - sign[DA732X_HPL_AMP] = snd_soc_component_read32(component, DA732X_REG_HPL) & + sign[DA732X_HPL_AMP] = snd_soc_component_read(component, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO; - sign[DA732X_HPR_AMP] = snd_soc_component_read32(component, DA732X_REG_HPR) & + sign[DA732X_HPR_AMP] = snd_soc_component_read(component, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO; snd_soc_component_write(component, DA732X_REG_HPL, DA732X_HP_OUT_COMP | @@ -1373,10 +1373,10 @@ static void da732x_output_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((snd_soc_component_read32(component, DA732X_REG_HPL) & + if ((snd_soc_component_read(component, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) offset[DA732X_HPL_AMP] &= ~step; - if ((snd_soc_component_read32(component, DA732X_REG_HPR) & + if ((snd_soc_component_read(component, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) offset[DA732X_HPR_AMP] &= ~step; diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 94800f522d3e..b0d9ca6de685 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -461,12 +461,12 @@ static int da9055_get_alc_data(struct snd_soc_component *component, u8 reg_val) /* Select middle 8 bits for read back from data register */ snd_soc_component_write(component, DA9055_ALC_CIC_OP_LVL_CTRL, reg_val | DA9055_ALC_DATA_MIDDLE); - mid_data = snd_soc_component_read32(component, DA9055_ALC_CIC_OP_LVL_DATA); + mid_data = snd_soc_component_read(component, DA9055_ALC_CIC_OP_LVL_DATA); /* Select top 8 bits for read back from data register */ snd_soc_component_write(component, DA9055_ALC_CIC_OP_LVL_CTRL, reg_val | DA9055_ALC_DATA_TOP); - top_data = snd_soc_component_read32(component, DA9055_ALC_CIC_OP_LVL_DATA); + top_data = snd_soc_component_read(component, DA9055_ALC_CIC_OP_LVL_DATA); sum += ((mid_data << 8) | (top_data << 16)); } @@ -488,8 +488,8 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, */ /* Save current values from Mic control registers */ - mic_left = snd_soc_component_read32(component, DA9055_MIC_L_CTRL); - mic_right = snd_soc_component_read32(component, DA9055_MIC_R_CTRL); + mic_left = snd_soc_component_read(component, DA9055_MIC_L_CTRL); + mic_right = snd_soc_component_read(component, DA9055_MIC_R_CTRL); /* Mute Mic PGA Left and Right */ snd_soc_component_update_bits(component, DA9055_MIC_L_CTRL, @@ -498,8 +498,8 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, DA9055_MIC_R_MUTE_EN, DA9055_MIC_R_MUTE_EN); /* Save current values from ADC control registers */ - adc_left = snd_soc_component_read32(component, DA9055_ADC_L_CTRL); - adc_right = snd_soc_component_read32(component, DA9055_ADC_R_CTRL); + adc_left = snd_soc_component_read(component, DA9055_ADC_L_CTRL); + adc_right = snd_soc_component_read(component, DA9055_ADC_R_CTRL); /* Enable ADC Left and Right */ snd_soc_component_update_bits(component, DA9055_ADC_L_CTRL, @@ -1176,7 +1176,7 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) } /* Don't allow change of mode if PLL is enabled */ - if ((snd_soc_component_read32(component, DA9055_PLL_CTRL) & DA9055_PLL_EN) && + if ((snd_soc_component_read(component, DA9055_PLL_CTRL) & DA9055_PLL_EN) && (da9055->master != mode)) return -EINVAL; @@ -1211,7 +1211,7 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int da9055_mute(struct snd_soc_dai *dai, int mute) +static int da9055_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -1324,7 +1324,8 @@ static const struct snd_soc_dai_ops da9055_dai_ops = { .set_fmt = da9055_set_dai_fmt, .set_sysclk = da9055_set_dai_sysclk, .set_pll = da9055_set_dai_pll, - .digital_mute = da9055_mute, + .mute_stream = da9055_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver da9055_dai = { diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 36eef1fb3d18..bd5d230c5df2 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -507,7 +507,7 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int es8316_mute(struct snd_soc_dai *dai, int mute) +static int es8316_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20, mute ? 0x20 : 0); @@ -522,7 +522,8 @@ static const struct snd_soc_dai_ops es8316_ops = { .hw_params = es8316_pcm_hw_params, .set_fmt = es8316_set_dai_fmt, .set_sysclk = es8316_set_dai_sysclk, - .digital_mute = es8316_mute, + .mute_stream = es8316_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver es8316_dai = { @@ -839,11 +840,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..7e26231a596a 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -449,7 +449,7 @@ static const struct snd_soc_dapm_route es8328_dapm_routes[] = { { "ROUT2", NULL, "Right Out 2" }, }; -static int es8328_mute(struct snd_soc_dai *dai, int mute) +static int es8328_mute(struct snd_soc_dai *dai, int mute, int direction) { return snd_soc_component_update_bits(dai->component, ES8328_DACCONTROL3, ES8328_DACCONTROL3_DACMUTE, @@ -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; @@ -692,9 +692,10 @@ static int es8328_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops es8328_dai_ops = { .startup = es8328_startup, .hw_params = es8328_hw_params, - .digital_mute = es8328_mute, + .mute_stream = es8328_mute, .set_sysclk = es8328_set_sysclk, .set_fmt = es8328_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver es8328_dai = { diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 473efe9ef998..49e6f23fc766 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -289,7 +289,6 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, struct hdac_hda_priv *hda_pvt; struct hda_pcm_stream *hda_stream; struct hda_pcm *pcm; - int ret; hda_pvt = snd_soc_component_get_drvdata(component); pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); @@ -300,11 +299,7 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, hda_stream = &pcm->stream[substream->stream]; - ret = hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream); - if (ret < 0) - snd_hda_codec_pcm_put(pcm); - - return ret; + return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream); } static void hdac_hda_dai_close(struct snd_pcm_substream *substream, @@ -467,7 +462,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) ret = snd_hda_codec_parse_pcms(hcodec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); - goto error_regmap; + goto error_patch; } /* HDMI controls need to be created in machine drivers */ @@ -476,7 +471,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) if (ret < 0) { dev_err(&hdev->dev, "unable to create controls %d\n", ret); - goto error_regmap; + goto error_patch; } } @@ -496,6 +491,9 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) return 0; +error_patch: + if (hcodec->patch_ops.free) + hcodec->patch_ops.free(hcodec); error_regmap: snd_hdac_regmap_exit(hdev); error_pm: @@ -510,6 +508,7 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) struct hdac_hda_priv *hda_pvt = snd_soc_component_get_drvdata(component); struct hdac_device *hdev = &hda_pvt->codec.core; + struct hda_codec *codec = &hda_pvt->codec; struct hdac_ext_link *hlink = NULL; hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); @@ -521,7 +520,10 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) pm_runtime_disable(&hdev->dev); snd_hdac_ext_bus_link_put(hdev->bus, hlink); - snd_hdac_regmap_exit(hdev); + if (codec->patch_ops.free) + codec->patch_ops.free(codec); + + snd_hda_codec_cleanup_for_unbind(codec); } static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = { @@ -605,12 +607,10 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) static int hdac_hda_dev_remove(struct hdac_device *hdev) { - struct hdac_hda_priv *hda_pvt; - - hda_pvt = dev_get_drvdata(&hdev->dev); - if (hda_pvt && hda_pvt->codec.registered) - cancel_delayed_work_sync(&hda_pvt->codec.jackpoll_work); - + /* + * Resources are freed in hdac_hda_codec_remove(). This + * function is kept to keep hda_codec_driver_remove() happy. + */ return 0; } diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index f005751da2cc..8c6f540533ba 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * ALSA SoC codec for HDMI encoder drivers - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/ * Author: Jyri Sarha <jsarha@ti.com> */ #include <linux/module.h> @@ -558,15 +558,24 @@ static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai, return 0; } -static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) +static int hdmi_codec_mute(struct snd_soc_dai *dai, int mute, int direction) { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - if (hcp->hcd.ops->digital_mute) - return hcp->hcd.ops->digital_mute(dai->dev->parent, - hcp->hcd.data, mute); - - return 0; + /* + * ignore if direction was CAPTURE + * and it had .no_capture_mute flag + * see + * snd_soc_dai_digital_mute() + */ + if (hcp->hcd.ops->mute_stream && + (direction == SNDRV_PCM_STREAM_PLAYBACK || + !hcp->hcd.ops->no_capture_mute)) + return hcp->hcd.ops->mute_stream(dai->dev->parent, + hcp->hcd.data, + mute, direction); + + return -ENOTSUPP; } static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { @@ -574,14 +583,14 @@ static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { .shutdown = hdmi_codec_shutdown, .hw_params = hdmi_codec_hw_params, .set_fmt = hdmi_codec_i2s_set_fmt, - .digital_mute = hdmi_codec_digital_mute, + .mute_stream = hdmi_codec_mute, }; static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = { .startup = hdmi_codec_startup, .shutdown = hdmi_codec_shutdown, .hw_params = hdmi_codec_hw_params, - .digital_mute = hdmi_codec_digital_mute, + .mute_stream = hdmi_codec_mute, }; #define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 14d8fe1c28a4..d0e8f0d2fbc1 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -48,11 +48,9 @@ static int rk3036_codec_antipop_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - int val, ret, regval; + int val, regval; - ret = snd_soc_component_read(component, INNO_R09, ®val); - if (ret) - return ret; + regval = snd_soc_component_read(component, INNO_R09); val = ((regval >> INNO_R09_HPL_ANITPOP_SHIFT) & INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON; ucontrol->value.integer.value[0] = val; diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 3626f70f7768..79afced75d76 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -860,7 +860,7 @@ static const struct snd_soc_dapm_route isabelle_intercon[] = { { "LINEOUT2", NULL, "LINEOUT2 Driver" }, }; -static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute) +static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ISABELLE_DAC1_SOFTRAMP_REG, BIT(4), (mute ? BIT(4) : 0)); @@ -868,7 +868,7 @@ static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute) return 0; } -static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute) +static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ISABELLE_DAC2_SOFTRAMP_REG, BIT(4), (mute ? BIT(4) : 0)); @@ -876,7 +876,7 @@ static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute) return 0; } -static int isabelle_line_mute(struct snd_soc_dai *dai, int mute) +static int isabelle_line_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ISABELLE_DAC3_SOFTRAMP_REG, BIT(4), (mute ? BIT(4) : 0)); @@ -1014,19 +1014,22 @@ static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static const struct snd_soc_dai_ops isabelle_hs_dai_ops = { .hw_params = isabelle_hw_params, .set_fmt = isabelle_set_dai_fmt, - .digital_mute = isabelle_hs_mute, + .mute_stream = isabelle_hs_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops isabelle_hf_dai_ops = { .hw_params = isabelle_hw_params, .set_fmt = isabelle_set_dai_fmt, - .digital_mute = isabelle_hf_mute, + .mute_stream = isabelle_hf_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops isabelle_line_dai_ops = { .hw_params = isabelle_hw_params, .set_fmt = isabelle_set_dai_fmt, - .digital_mute = isabelle_line_mute, + .mute_stream = isabelle_line_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops isabelle_ul_dai_ops = { diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c index 34775aa62402..c0a28f06b09a 100644 --- a/sound/soc/codecs/jz4770.c +++ b/sound/soc/codecs/jz4770.c @@ -264,7 +264,7 @@ static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream, return ret; } -static int jz4770_codec_digital_mute(struct snd_soc_dai *dai, int mute) +static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *codec = dai->component; struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); @@ -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. */ @@ -753,7 +752,8 @@ static const struct snd_soc_dai_ops jz4770_codec_dai_ops = { .shutdown = jz4770_codec_shutdown, .hw_params = jz4770_codec_hw_params, .trigger = jz4770_codec_pcm_trigger, - .digital_mute = jz4770_codec_digital_mute, + .mute_stream = jz4770_codec_mute_stream, + .no_capture_mute = 1, }; #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index f864b07cb0b8..06ab61f6f719 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1218,35 +1218,35 @@ static int lm49453_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } -static int lm49453_hp_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_hp_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(1)|BIT(0), (mute ? (BIT(1)|BIT(0)) : 0)); return 0; } -static int lm49453_lo_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_lo_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(3)|BIT(2), (mute ? (BIT(3)|BIT(2)) : 0)); return 0; } -static int lm49453_ls_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_ls_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(5)|BIT(4), (mute ? (BIT(5)|BIT(4)) : 0)); return 0; } -static int lm49453_ep_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_ep_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(4), (mute ? BIT(4) : 0)); return 0; } -static int lm49453_ha_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_ha_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(7)|BIT(6), (mute ? (BIT(7)|BIT(6)) : 0)); @@ -1288,35 +1288,40 @@ static const struct snd_soc_dai_ops lm49453_headset_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_hp_mute, + .mute_stream = lm49453_hp_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_speaker_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_ls_mute, + .mute_stream = lm49453_ls_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_haptic_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_ha_mute, + .mute_stream = lm49453_ha_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_ep_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_ep_mute, + .mute_stream = lm49453_ep_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_lineout_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_lo_mute, + .mute_stream = lm49453_lo_mute, + .no_capture_mute = 1, }; /* LM49453 dai structure. */ diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index ec380b0b2d4e..680f31a6493a 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -628,12 +628,8 @@ int madera_out1_demux_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); unsigned int val; - int ret; - - ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, &val); - if (ret) - return ret; + val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1); val &= MADERA_EP_SEL_MASK; val >>= MADERA_EP_SEL_SHIFT; ucontrol->value.enumerated.item[0] = val; @@ -1068,12 +1064,7 @@ int madera_rate_put(struct snd_kcontrol *kcontrol, */ mutex_lock(&priv->rate_lock); - ret = snd_soc_component_read(component, e->reg, &val); - if (ret < 0) { - dev_warn(priv->madera->dev, "Failed to read 0x%x (%d)\n", - e->reg, ret); - goto out; - } + val = snd_soc_component_read(component, e->reg); val >>= e->shift_l; val &= e->mask; if (snd_soc_enum_item_to_val(e, item) == val) { @@ -2178,10 +2169,7 @@ int madera_dfc_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_mutex_lock(dapm); - ret = snd_soc_component_read(component, reg, &val); - if (ret) - goto exit; - + val = snd_soc_component_read(component, reg); if (val & MADERA_DFC1_ENA) { ret = -EBUSY; dev_err(component->dev, "Can't change mode on an active DFC\n"); @@ -2211,9 +2199,7 @@ int madera_lp_mode_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_mutex_lock(dapm); /* Cannot change lp mode on an active input */ - ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES, &val); - if (ret) - goto exit; + val = snd_soc_component_read(component, MADERA_INPUT_ENABLES); mask = (mc->reg - MADERA_ADC_DIGITAL_VOLUME_1L) / 4; mask ^= 0x1; /* Flip bottom bit for channel order */ @@ -2276,7 +2262,6 @@ int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct madera_priv *priv = snd_soc_component_get_drvdata(component); unsigned int reg, val; - int ret; if (w->shift % 2) reg = MADERA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8); @@ -2305,9 +2290,8 @@ int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, break; case SND_SOC_DAPM_POST_PMD: /* Disable volume updates if no inputs are enabled */ - ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES, - &val); - if (!ret && !val) + val = snd_soc_component_read(component, MADERA_INPUT_ENABLES); + if (!val) madera_in_set_vu(priv, false); break; default: @@ -3087,26 +3071,16 @@ static int madera_aif_cfg_changed(struct snd_soc_component *component, int base, int bclk, int lrclk, int frame) { unsigned int val; - int ret; - ret = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL, - &val); - if (ret) - return ret; + val = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL); if (bclk != (val & MADERA_AIF1_BCLK_FREQ_MASK)) return 1; - ret = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE, - &val); - if (ret) - return ret; + val = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE); if (lrclk != (val & MADERA_AIF1RX_BCPF_MASK)) return 1; - ret = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1, - &val); - if (ret) - return ret; + val = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1); if (frame != (val & (MADERA_AIF1TX_WL_MASK | MADERA_AIF1TX_SLOT_LEN_MASK))) return 1; @@ -3162,10 +3136,7 @@ static int madera_hw_params(struct snd_pcm_substream *substream, } /* Force multiple of 2 channels for I2S mode */ - ret = snd_soc_component_read(component, base + MADERA_AIF_FORMAT, &val); - if (ret) - return ret; - + val = snd_soc_component_read(component, base + MADERA_AIF_FORMAT); val &= MADERA_AIF1_FMT_MASK; if ((channels & 1) && val == MADERA_FMT_I2S_MODE) { madera_aif_dbg(dai, "Forcing stereo mode\n"); diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index f031d2caa8b7..4be24e7f51c8 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -996,7 +996,7 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98088_REG_14_DAI1_FORMAT) + if (snd_soc_component_read(component, M98088_REG_14_DAI1_FORMAT) & M98088_DAI_MAS) { if (max98088->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); @@ -1063,7 +1063,7 @@ static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98088_REG_1C_DAI2_FORMAT) + if (snd_soc_component_read(component, M98088_REG_1C_DAI2_FORMAT) & M98088_DAI_MAS) { if (max98088->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); @@ -1120,7 +1120,7 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, return -EINVAL; } - if (snd_soc_component_read32(component, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { + if (snd_soc_component_read(component, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, @@ -1274,7 +1274,8 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int max98088_dai1_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int reg; @@ -1289,7 +1290,8 @@ static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) return 0; } -static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int max98088_dai2_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int reg; @@ -1354,14 +1356,16 @@ static const struct snd_soc_dai_ops max98088_dai1_ops = { .set_sysclk = max98088_dai_set_sysclk, .set_fmt = max98088_dai1_set_fmt, .hw_params = max98088_dai1_hw_params, - .digital_mute = max98088_dai1_digital_mute, + .mute_stream = max98088_dai1_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops max98088_dai2_ops = { .set_sysclk = max98088_dai_set_sysclk, .set_fmt = max98088_dai2_set_fmt, .hw_params = max98088_dai2_hw_params, - .digital_mute = max98088_dai2_digital_mute, + .mute_stream = max98088_dai2_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver max98088_dai[] = { @@ -1440,7 +1444,7 @@ static void max98088_setup_eq1(struct snd_soc_component *component) pdata->eq_cfg[best].rate, fs); /* Disable EQ while configuring, and save current on/off state */ - save = snd_soc_component_read32(component, M98088_REG_49_CFG_LEVEL); + save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0); coef_set = &pdata->eq_cfg[sel]; @@ -1487,7 +1491,7 @@ static void max98088_setup_eq2(struct snd_soc_component *component) pdata->eq_cfg[best].rate, fs); /* Disable EQ while configuring, and save current on/off state */ - save = snd_soc_component_read32(component, M98088_REG_49_CFG_LEVEL); + save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0); coef_set = &pdata->eq_cfg[sel]; @@ -1673,7 +1677,7 @@ static int max98088_probe(struct snd_soc_component *component) max98088->mic1pre = 0; max98088->mic2pre = 0; - ret = snd_soc_component_read32(component, M98088_REG_FF_REV_ID); + ret = snd_soc_component_read(component, M98088_REG_FF_REV_ID); if (ret < 0) { dev_err(component->dev, "Failed to read device revision: %d\n", ret); diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index e2cc1ad8cb0a..945a79e4f3eb 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -353,7 +353,7 @@ static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int mask = (1 << fls(mc->max)) - 1; - unsigned int val = snd_soc_component_read32(component, mc->reg); + unsigned int val = snd_soc_component_read(component, mc->reg); unsigned int *select; switch (mc->reg) { @@ -394,7 +394,7 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int mask = (1 << fls(mc->max)) - 1; unsigned int sel = ucontrol->value.integer.value[0]; - unsigned int val = snd_soc_component_read32(component, mc->reg); + unsigned int val = snd_soc_component_read(component, mc->reg); unsigned int *select; switch (mc->reg) { @@ -730,7 +730,7 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); - unsigned int val = snd_soc_component_read32(component, w->reg); + unsigned int val = snd_soc_component_read(component, w->reg); if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) val = (val & M98090_MIC_PA1EN_MASK) >> M98090_MIC_PA1EN_SHIFT; @@ -1496,7 +1496,7 @@ static void max98090_configure_bclk(struct snd_soc_component *component) } /* Skip configuration when operating as slave */ - if (!(snd_soc_component_read32(component, M98090_REG_MASTER_MODE) & + if (!(snd_soc_component_read(component, M98090_REG_MASTER_MODE) & M98090_MAS_MASK)) { return; } @@ -2017,7 +2017,8 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int max98090_dai_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int max98090_dai_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int regval; @@ -2132,7 +2133,7 @@ static void max98090_pll_work(struct max98090_priv *max98090) usleep_range(1000, 1200); /* Check lock status */ - pll = snd_soc_component_read32( + pll = snd_soc_component_read( component, M98090_REG_DEVICE_STATUS); if (!(pll & M98090_ULK_MASK)) break; @@ -2157,16 +2158,16 @@ static void max98090_jack_work(struct work_struct *work) msleep(50); - reg = snd_soc_component_read32(component, M98090_REG_JACK_STATUS); + reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); /* Weak pull up allows only insertion detection */ snd_soc_component_update_bits(component, M98090_REG_JACK_DETECT, M98090_JDWK_MASK, M98090_JDWK_MASK); } else { - reg = snd_soc_component_read32(component, M98090_REG_JACK_STATUS); + reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); } - reg = snd_soc_component_read32(component, M98090_REG_JACK_STATUS); + reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); switch (reg & (M98090_LSNS_MASK | M98090_JKSNS_MASK)) { case M98090_LSNS_MASK | M98090_JKSNS_MASK: @@ -2347,8 +2348,9 @@ static const struct snd_soc_dai_ops max98090_dai_ops = { .set_fmt = max98090_dai_set_fmt, .set_tdm_slot = max98090_set_tdm_slot, .hw_params = max98090_dai_hw_params, - .digital_mute = max98090_dai_digital_mute, + .mute_stream = max98090_dai_mute, .trigger = max98090_dai_trigger, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver max98090_dai[] = { @@ -2406,7 +2408,7 @@ static int max98090_probe(struct snd_soc_component *component) max98090->pa1en = 0; max98090->pa2en = 0; - ret = snd_soc_component_read32(component, M98090_REG_REVISION_ID); + ret = snd_soc_component_read(component, M98090_REG_REVISION_ID); if (ret < 0) { dev_err(component->dev, "Failed to read device revision: %d\n", ret); @@ -2446,7 +2448,7 @@ static int max98090_probe(struct snd_soc_component *component) * An old interrupt ocurring prior to installing the ISR * can keep a new interrupt from generating a trigger. */ - snd_soc_component_read32(component, M98090_REG_DEVICE_STATUS); + snd_soc_component_read(component, M98090_REG_DEVICE_STATUS); /* High Performance is default */ snd_soc_component_update_bits(component, M98090_REG_DAC_CONTROL, diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index c7e0a55f3dc2..9bdc6392382a 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -971,7 +971,7 @@ static int max98095_dai1_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98095_02A_DAI1_FORMAT) & M98095_DAI_MAS) { + if (snd_soc_component_read(component, M98095_02A_DAI1_FORMAT) & M98095_DAI_MAS) { if (max98095->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); return -EINVAL; @@ -1032,7 +1032,7 @@ static int max98095_dai2_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98095_034_DAI2_FORMAT) & M98095_DAI_MAS) { + if (snd_soc_component_read(component, M98095_034_DAI2_FORMAT) & M98095_DAI_MAS) { if (max98095->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); return -EINVAL; @@ -1093,7 +1093,7 @@ static int max98095_dai3_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98095_03E_DAI3_FORMAT) & M98095_DAI_MAS) { + if (snd_soc_component_read(component, M98095_03E_DAI3_FORMAT) & M98095_DAI_MAS) { if (max98095->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); return -EINVAL; @@ -1534,7 +1534,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, regmask = (channel == 0) ? M98095_EQ1EN : M98095_EQ2EN; /* Disable filter while configuring, and save current on/off state */ - regsave = snd_soc_component_read32(component, M98095_088_CFG_LEVEL); + regsave = snd_soc_component_read(component, M98095_088_CFG_LEVEL); snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, 0); mutex_lock(&max98095->lock); @@ -1685,7 +1685,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, regmask = (channel == 0) ? M98095_BQ1EN : M98095_BQ2EN; /* Disable filter while configuring, and save current on/off state */ - regsave = snd_soc_component_read32(component, M98095_088_CFG_LEVEL); + regsave = snd_soc_component_read(component, M98095_088_CFG_LEVEL); snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, 0); mutex_lock(&max98095->lock); @@ -1816,7 +1816,7 @@ static irqreturn_t max98095_report_jack(int irq, void *data) int mic_report = 0; /* Read the Jack Status Register */ - value = snd_soc_component_read32(component, M98095_007_JACK_AUTO_STS); + value = snd_soc_component_read(component, M98095_007_JACK_AUTO_STS); /* If ddone is not set, then detection isn't finished yet */ if ((value & M98095_DDONE) == 0) @@ -1972,7 +1972,7 @@ static int max98095_reset(struct snd_soc_component *component) /* Reset to hardware default for registers, as there is not * a soft reset hardware control register */ for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { - ret = snd_soc_component_write(component, i, snd_soc_component_read32(component, i)); + ret = snd_soc_component_write(component, i, snd_soc_component_read(component, i)); if (ret < 0) { dev_err(component->dev, "Failed to reset: %d\n", ret); return ret; @@ -2038,7 +2038,7 @@ static int max98095_probe(struct snd_soc_component *component) } } - ret = snd_soc_component_read32(component, M98095_0FF_REV_ID); + ret = snd_soc_component_read(component, M98095_0FF_REV_ID); if (ret < 0) { dev_err(component->dev, "Failure reading hardware revision: %d\n", ret); diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index a8bd793a7867..918812763884 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -23,36 +23,61 @@ struct max98357a_priv { struct gpio_desc *sdmode; unsigned int sdmode_delay; + int sdmode_switch; }; -static int max98357a_sdmode_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) +static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) { - struct snd_soc_component *component = - snd_soc_dapm_to_component(w->dapm); + struct snd_soc_component *component = dai->component; struct max98357a_priv *max98357a = snd_soc_component_get_drvdata(component); if (!max98357a->sdmode) return 0; - if (event & SND_SOC_DAPM_POST_PMU) { - msleep(max98357a->sdmode_delay); - gpiod_set_value(max98357a->sdmode, 1); - dev_dbg(component->dev, "set sdmode to 1"); - } else if (event & SND_SOC_DAPM_PRE_PMD) { + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + mdelay(max98357a->sdmode_delay); + if (max98357a->sdmode_switch) { + gpiod_set_value(max98357a->sdmode, 1); + dev_dbg(component->dev, "set sdmode to 1"); + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: gpiod_set_value(max98357a->sdmode, 0); dev_dbg(component->dev, "set sdmode to 0"); + break; } return 0; } +static int max98357a_sdmode_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct max98357a_priv *max98357a = + snd_soc_component_get_drvdata(component); + + if (event & SND_SOC_DAPM_POST_PMU) + max98357a->sdmode_switch = 1; + else if (event & SND_SOC_DAPM_POST_PMD) + max98357a->sdmode_switch = 0; + + return 0; +} + static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("Speaker"), SND_SOC_DAPM_OUT_DRV_E("SD_MODE", SND_SOC_NOPM, 0, 0, NULL, 0, max98357a_sdmode_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { @@ -71,6 +96,10 @@ static const struct snd_soc_component_driver max98357a_component_driver = { .non_legacy_dai_naming = 1, }; +static const struct snd_soc_dai_ops max98357a_dai_ops = { + .trigger = max98357a_daiops_trigger, +}; + static struct snd_soc_dai_driver max98357a_dai_driver = { .name = "HiFi", .playback = { @@ -90,6 +119,7 @@ static struct snd_soc_dai_driver max98357a_dai_driver = { .channels_min = 1, .channels_max = 2, }, + .ops = &max98357a_dai_ops, }; static int max98357a_platform_probe(struct platform_device *pdev) @@ -125,6 +155,7 @@ static int max98357a_platform_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id max98357a_device_id[] = { { .compatible = "maxim,max98357a" }, + { .compatible = "maxim,max98360a" }, {} }; MODULE_DEVICE_TABLE(of, max98357a_device_id); 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 <ryans.lee@maximintegrated.com>"); +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 <oleg.sherbakov@maximintegrated.com>"); +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 d87402a86c88..929bb1798c43 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) { @@ -830,31 +382,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), @@ -866,23 +394,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; @@ -914,111 +445,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 <ryans.lee@maximintegrated.com>"); 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 e6613b52bd78..ff5cc9bbec29 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -678,7 +678,7 @@ static const struct snd_kcontrol_new max98390_dai_controls = static const struct snd_soc_dapm_widget max98390_dapm_widgets[] = { SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", - MAX98390_R203A_AMP_EN, 0, 0, max98390_dac_event, + SND_SOC_NOPM, 0, 0, max98390_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, &max98390_dai_controls), @@ -790,7 +790,7 @@ static int max98390_dsm_init(struct snd_soc_component *component) param_start_addr = (dsm_param[0] & 0xff) | (dsm_param[1] & 0xff) << 8; param_size = (dsm_param[2] & 0xff) | (dsm_param[3] & 0xff) << 8; if (param_size > MAX98390_DSM_PARAM_MAX_SIZE || - param_start_addr < DSM_STBASS_HPF_B0_BYTE0 || + param_start_addr < MAX98390_IRQ_CTRL || fw->size < param_size + MAX98390_DSM_PAYLOAD_OFFSET) { dev_err(component->dev, "param fw is invalid.\n"); @@ -842,6 +842,20 @@ static int max98390_dsm_calibrate(struct snd_soc_component *component) return 0; } +static void max98390_init_regs(struct snd_soc_component *component) +{ + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); + regmap_write(max98390->regmap, MAX98390_DAT_MON, 0x00); + regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x00); + regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); + regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); + regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); + regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); +} + static int max98390_probe(struct snd_soc_component *component) { struct max98390_priv *max98390 = @@ -850,21 +864,13 @@ static int max98390_probe(struct snd_soc_component *component) regmap_write(max98390->regmap, MAX98390_SOFTWARE_RESET, 0x01); /* Sleep reset settle time */ msleep(20); + + /* Amp init setting */ + max98390_init_regs(component); /* Update dsm bin param */ max98390_dsm_init(component); - /* Amp Setting */ - regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); - regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); - regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x2d); - regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); - regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); - regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); - /* Dsm Setting */ - regmap_write(max98390->regmap, DSM_VOL_CTRL, 0x94); - regmap_write(max98390->regmap, DSMIG_EN, 0x19); - regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80); if (max98390->ref_rdc_value) { regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, max98390->ref_rdc_value & 0x000000ff); @@ -938,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/max98390.h b/sound/soc/codecs/max98390.h index 5f444e7779b0..dff884f68e3e 100644 --- a/sound/soc/codecs/max98390.h +++ b/sound/soc/codecs/max98390.h @@ -650,7 +650,7 @@ /* DSM register offset */ #define MAX98390_DSM_PAYLOAD_OFFSET 16 -#define MAX98390_DSM_PARAM_MAX_SIZE 770 +#define MAX98390_DSM_PARAM_MAX_SIZE 1024 #define MAX98390_DSM_PARAM_MIN_SIZE 670 struct max98390_priv { diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 6f43748f9239..dec51893af74 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -7,7 +7,7 @@ * Author: Christian Glindkamp <christian.glindkamp@taskit.de> * * Initial development of this code was funded by - * MICRONIC Computer Systeme GmbH, http://www.mcsberlin.de/ + * MICRONIC Computer Systeme GmbH, https://www.mcsberlin.de/ */ #include <linux/module.h> @@ -121,7 +121,7 @@ static int max9850_hw_params(struct snd_pcm_substream *substream, return -EINVAL; /* lrclk_div = 2^22 * rate / iclk with iclk = mclk / sf */ - sf = (snd_soc_component_read32(component, MAX9850_CLOCK) >> 2) + 1; + sf = (snd_soc_component_read(component, MAX9850_CLOCK) >> 2) + 1; lrclk_div = (1 << 22); lrclk_div *= params_rate(params); lrclk_div *= sf; 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/max9867.c b/sound/soc/codecs/max9867.c index c72cb2888c21..fcb31144d69c 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -283,7 +283,7 @@ static int max9867_dai_hw_params(struct snd_pcm_substream *substream, return 0; } -static int max9867_mute(struct snd_soc_dai *dai, int mute) +static int max9867_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component); @@ -393,9 +393,10 @@ static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai, static const struct snd_soc_dai_ops max9867_dai_ops = { .set_sysclk = max9867_set_dai_sysclk, .set_fmt = max9867_dai_set_fmt, - .digital_mute = max9867_mute, + .mute_stream = max9867_mute, .startup = max9867_startup, .hw_params = max9867_dai_hw_params, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver max9867_dai[] = { diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index f9830bd3da18..9e6a0cda43d0 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -5,7 +5,7 @@ * Copyright 2012 Philippe Retornaz, philippe.retornaz@epfl.ch * * Initial development of this code was funded by - * Phytec Messtechnik GmbH, http://www.phytec.de + * Phytec Messtechnik GmbH, https://www.phytec.de */ #include <linux/module.h> #include <linux/device.h> diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 55823bc95d06..70c17be455ca 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -372,7 +372,7 @@ static int ml26124_hw_params(struct snd_pcm_substream *substream, return 0; } -static int ml26124_mute(struct snd_soc_dai *dai, int mute) +static int ml26124_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct ml26124_priv *priv = snd_soc_component_get_drvdata(component); @@ -492,9 +492,10 @@ static int ml26124_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ml26124_dai_ops = { .hw_params = ml26124_hw_params, - .digital_mute = ml26124_mute, + .mute_stream = ml26124_mute, .set_fmt = ml26124_set_dai_fmt, .set_sysclk = ml26124_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ml26124_dai = { diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 85bc7ae4d267..4428c62e25cf 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -510,7 +510,7 @@ static void pm8916_wcd_setup_mbhc(struct pm8916_wcd_analog_priv *wcd) DIG_CLK_CTL_D_MBHC_CLK_EN_MASK, DIG_CLK_CTL_D_MBHC_CLK_EN); - if (snd_soc_component_read32(component, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) + if (snd_soc_component_read(component, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) micbias_enabled = true; pm8916_mbhc_configure_bias(wcd, micbias_enabled); @@ -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, @@ -730,8 +730,8 @@ static int pm8916_wcd_analog_probe(struct snd_soc_component *component) snd_soc_component_init_regmap(component, dev_get_regmap(component->dev->parent, NULL)); snd_soc_component_set_drvdata(component, priv); - priv->pmic_rev = snd_soc_component_read32(component, CDC_D_REVISION1); - priv->codec_version = snd_soc_component_read32(component, CDC_D_PERPH_SUBTYPE); + priv->pmic_rev = snd_soc_component_read(component, CDC_D_REVISION1); + priv->codec_version = snd_soc_component_read(component, CDC_D_PERPH_SUBTYPE); dev_info(component->dev, "PMIC REV: %d\t CODEC Version: %d\n", priv->pmic_rev, priv->codec_version); @@ -990,7 +990,7 @@ static irqreturn_t mbhc_btn_release_irq_handler(int irq, void *arg) if (priv->detect_accessory_type) { struct snd_soc_component *component = priv->component; - u32 val = snd_soc_component_read32(component, CDC_A_MBHC_RESULT_1); + u32 val = snd_soc_component_read(component, CDC_A_MBHC_RESULT_1); /* check if its BTN0 thats released */ if ((val != -1) && !(val & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK)) @@ -1009,7 +1009,7 @@ static irqreturn_t mbhc_btn_press_irq_handler(int irq, void *arg) struct snd_soc_component *component = priv->component; u32 btn_result; - btn_result = snd_soc_component_read32(component, CDC_A_MBHC_RESULT_1) & + btn_result = snd_soc_component_read(component, CDC_A_MBHC_RESULT_1) & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK; switch (btn_result) { @@ -1046,7 +1046,7 @@ static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg) struct snd_soc_component *component = priv->component; bool ins = false; - if (snd_soc_component_read32(component, CDC_A_MBHC_DET_CTL_1) & + if (snd_soc_component_read(component, CDC_A_MBHC_DET_CTL_1) & CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_MASK) ins = true; @@ -1059,7 +1059,7 @@ static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg) if (ins) { /* hs insertion */ bool micbias_enabled = false; - if (snd_soc_component_read32(component, CDC_A_MICB_2_EN) & + if (snd_soc_component_read(component, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) micbias_enabled = true; diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index 09fccacadd6b..fcc10c8bc625 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -366,7 +366,7 @@ static int msm8x16_wcd_codec_set_iir_gain(struct snd_soc_dapm_widget *w, reg = LPASS_CDC_IIR1_GAIN_B1_CTL; else if (w->shift == 1) reg = LPASS_CDC_IIR2_GAIN_B1_CTL; - value = snd_soc_component_read32(component, reg); + value = snd_soc_component_read(component, reg); snd_soc_component_write(component, reg, value); break; default: @@ -387,7 +387,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t)) & 0x7F); - value |= snd_soc_component_read32(component, + value |= snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)); snd_soc_component_write(component, @@ -395,7 +395,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 1) & 0x7F); - value |= (snd_soc_component_read32(component, + value |= (snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8); snd_soc_component_write(component, @@ -403,7 +403,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 2) & 0x7F); - value |= (snd_soc_component_read32(component, + value |= (snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16); snd_soc_component_write(component, @@ -412,7 +412,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, * sizeof(uint32_t) + 3) & 0x7F); /* Mask bits top 2 bits since they are reserved */ - value |= ((snd_soc_component_read32(component, + value |= ((snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) & 0x3f) << 24); return value; @@ -584,7 +584,7 @@ static int msm8916_wcd_digital_enable_interpolator( /* apply the digital gain after the interpolator is enabled */ usleep_range(10000, 10100); snd_soc_component_write(component, rx_gain_reg[w->shift], - snd_soc_component_read32(component, rx_gain_reg[w->shift])); + snd_soc_component_read(component, rx_gain_reg[w->shift])); break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, LPASS_CDC_CLK_RX_RESET_CTL, @@ -615,7 +615,7 @@ static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, tx_vol_ctl_reg, TX_VOL_CTL_CFG_MUTE_EN_MASK, TX_VOL_CTL_CFG_MUTE_EN_ENABLE); - dec_hpf_cut_of_freq = snd_soc_component_read32(component, tx_mux_ctl_reg) & + dec_hpf_cut_of_freq = snd_soc_component_read(component, tx_mux_ctl_reg) & TX_MUX_CTL_CUT_OFF_FREQ_MASK; dec_hpf_cut_of_freq >>= TX_MUX_CTL_CUT_OFF_FREQ_SHIFT; if (dec_hpf_cut_of_freq != TX_MUX_CTL_CF_NEG_3DB_150HZ) { @@ -632,7 +632,7 @@ static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w, TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS); /* apply the digital gain after the decimator is enabled */ snd_soc_component_write(component, tx_gain_reg[w->shift], - snd_soc_component_read32(component, tx_gain_reg[w->shift])); + snd_soc_component_read(component, tx_gain_reg[w->shift])); snd_soc_component_update_bits(component, tx_vol_ctl_reg, TX_VOL_CTL_CFG_MUTE_EN_MASK, 0); break; diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 1b830ea4f6ed..1f39d5998cf6 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -95,6 +95,8 @@ struct mt6358_priv { struct regulator *avdd_reg; int wov_enabled; + + unsigned int dmic_one_wire_mode; }; int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, @@ -1831,7 +1833,10 @@ static int mt6358_dmic_enable(struct mt6358_priv *priv) mt6358_mtkaif_tx_enable(priv); /* UL dmic setting */ - regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); + if (priv->dmic_one_wire_mode) + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0400); + else + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); /* UL turn on */ regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003); @@ -2426,6 +2431,20 @@ static const struct snd_soc_component_driver mt6358_soc_component_driver = { .num_dapm_routes = ARRAY_SIZE(mt6358_dapm_routes), }; +static void mt6358_parse_dt(struct mt6358_priv *priv) +{ + int ret; + struct device *dev = priv->dev; + + ret = of_property_read_u32(dev->of_node, "mediatek,dmic-mode", + &priv->dmic_one_wire_mode); + if (ret) { + dev_warn(priv->dev, "%s() failed to read dmic-mode\n", + __func__); + priv->dmic_one_wire_mode = 0; + } +} + static int mt6358_platform_driver_probe(struct platform_device *pdev) { struct mt6358_priv *priv; @@ -2445,6 +2464,8 @@ static int mt6358_platform_driver_probe(struct platform_device *pdev) if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); + mt6358_parse_dt(priv); + dev_info(priv->dev, "%s(), dev name %s\n", __func__, dev_name(&pdev->dev)); diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index 78db3bd0b3bc..609aeeb27818 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -188,7 +188,7 @@ static int nau8822_eq_get(struct snd_kcontrol *kcontrol, val = (u16 *)ucontrol->value.bytes.data; reg = NAU8822_REG_EQ1; for (i = 0; i < params->max / sizeof(u16); i++) { - reg_val = snd_soc_component_read32(component, reg + i); + reg_val = snd_soc_component_read(component, reg + i); /* conversion of 16-bit integers between native CPU format * and big endian format */ @@ -445,7 +445,7 @@ static int check_mclk_select_pll(struct snd_soc_dapm_widget *source, snd_soc_dapm_to_component(source->dapm); unsigned int value; - value = snd_soc_component_read32(component, NAU8822_REG_CLOCKING); + value = snd_soc_component_read(component, NAU8822_REG_CLOCKING); return (value & NAU8822_CLKM_MASK); } @@ -831,7 +831,7 @@ static int nau8822_hw_params(struct snd_pcm_substream *substream, unsigned int ctrl_val, bclk_fs, bclk_div; /* make BCLK and LRC divide configuration if the codec as master. */ - snd_soc_component_read(component, NAU8822_REG_CLOCKING, &ctrl_val); + ctrl_val = snd_soc_component_read(component, NAU8822_REG_CLOCKING); if (ctrl_val & NAU8822_CLK_MASTER) { /* get the bclk and fs ratio */ bclk_fs = snd_soc_params_to_bclk(params) / params_rate(params); @@ -900,7 +900,7 @@ static int nau8822_hw_params(struct snd_pcm_substream *substream, return 0; } -static int nau8822_mute(struct snd_soc_dai *dai, int mute) +static int nau8822_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -967,10 +967,11 @@ static int nau8822_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops nau8822_dai_ops = { .hw_params = nau8822_hw_params, - .digital_mute = nau8822_mute, + .mute_stream = nau8822_mute, .set_fmt = nau8822_set_dai_fmt, .set_sysclk = nau8822_set_dai_sysclk, .set_pll = nau8822_set_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver nau8822_dai = { diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 4767e158cd5e..07ed8fded471 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -147,7 +147,7 @@ static int pcm1681_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int pcm1681_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm1681_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm1681_private *priv = snd_soc_component_get_drvdata(component); @@ -205,7 +205,8 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops pcm1681_dai_ops = { .set_fmt = pcm1681_set_dai_fmt, .hw_params = pcm1681_hw_params, - .digital_mute = pcm1681_digital_mute, + .mute_stream = pcm1681_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dapm_widget pcm1681_dapm_widgets[] = { diff --git a/sound/soc/codecs/pcm1789.c b/sound/soc/codecs/pcm1789.c index 8df6447c76a6..620dec172ce7 100644 --- a/sound/soc/codecs/pcm1789.c +++ b/sound/soc/codecs/pcm1789.c @@ -60,7 +60,7 @@ static int pcm1789_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int pcm1789_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int pcm1789_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; struct pcm1789_private *priv = snd_soc_component_get_drvdata(component); @@ -167,8 +167,9 @@ static int pcm1789_trigger(struct snd_pcm_substream *substream, int cmd, static const struct snd_soc_dai_ops pcm1789_dai_ops = { .set_fmt = pcm1789_set_dai_fmt, .hw_params = pcm1789_hw_params, - .digital_mute = pcm1789_digital_mute, + .mute_stream = pcm1789_mute, .trigger = pcm1789_trigger, + .no_capture_mute = 1, }; static const DECLARE_TLV_DB_SCALE(pcm1789_dac_tlv, -12000, 50, 1); diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c index 9e70b7385c69..ee60373d7d25 100644 --- a/sound/soc/codecs/pcm179x.c +++ b/sound/soc/codecs/pcm179x.c @@ -76,7 +76,7 @@ static int pcm179x_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int pcm179x_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm179x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm179x_private *priv = snd_soc_component_get_drvdata(component); @@ -145,7 +145,8 @@ static int pcm179x_hw_params(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops pcm179x_dai_ops = { .set_fmt = pcm179x_set_dai_fmt, .hw_params = pcm179x_hw_params, - .digital_mute = pcm179x_digital_mute, + .mute_stream = pcm179x_mute, + .no_capture_mute = 1, }; static const DECLARE_TLV_DB_SCALE(pcm179x_dac_tlv, -12000, 50, 1); diff --git a/sound/soc/codecs/pcm186x-i2c.c b/sound/soc/codecs/pcm186x-i2c.c index 0214dc6d84d0..f8382b74391d 100644 --- a/sound/soc/codecs/pcm186x-i2c.c +++ b/sound/soc/codecs/pcm186x-i2c.c @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC - I2C * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg <dannenberg@ti.com> * Andrew F. Davis <afd@ti.com> */ diff --git a/sound/soc/codecs/pcm186x-spi.c b/sound/soc/codecs/pcm186x-spi.c index b56e19827497..bc1b0f0698ed 100644 --- a/sound/soc/codecs/pcm186x-spi.c +++ b/sound/soc/codecs/pcm186x-spi.c @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC - SPI * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg <dannenberg@ti.com> * Andrew F. Davis <afd@ti.com> */ diff --git a/sound/soc/codecs/pcm186x.c b/sound/soc/codecs/pcm186x.c index c5fcc632f670..f0da55901dcb 100644 --- a/sound/soc/codecs/pcm186x.c +++ b/sound/soc/codecs/pcm186x.c @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg <dannenberg@ti.com> * Andrew F. Davis <afd@ti.com> */ diff --git a/sound/soc/codecs/pcm186x.h b/sound/soc/codecs/pcm186x.h index bb3f0c42a1cd..4d493754a3e2 100644 --- a/sound/soc/codecs/pcm186x.h +++ b/sound/soc/codecs/pcm186x.h @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg <dannenberg@ti.com> * Andrew F. Davis <afd@ti.com> */ diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 9711fab296eb..5e445fee4ef5 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -290,7 +290,7 @@ static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) PCM3168A_MRST_MASK | PCM3168A_SRST_MASK); } -static int pcm3168a_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm3168a_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); @@ -570,8 +570,9 @@ static const struct snd_soc_dai_ops pcm3168a_dai_ops = { .set_fmt = pcm3168a_set_dai_fmt, .set_sysclk = pcm3168a_set_dai_sysclk, .hw_params = pcm3168a_hw_params, - .digital_mute = pcm3168a_digital_mute, + .mute_stream = pcm3168a_mute, .set_tdm_slot = pcm3168a_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver pcm3168a_dais[] = { diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 4cbef9affffd..8153d3d01654 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1394,7 +1394,7 @@ static int pcm512x_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) return 0; } -static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm512x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component); @@ -1445,8 +1445,9 @@ static const struct snd_soc_dai_ops pcm512x_dai_ops = { .startup = pcm512x_dai_startup, .hw_params = pcm512x_hw_params, .set_fmt = pcm512x_set_fmt, - .digital_mute = pcm512x_digital_mute, + .mute_stream = pcm512x_mute, .set_bclk_ratio = pcm512x_set_bclk_ratio, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver pcm512x_dai = { diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 115706a55577..940a2fa933ed 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c @@ -107,7 +107,7 @@ static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute) +static int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(dai->component); @@ -316,9 +316,10 @@ static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops rk3328_dai_ops = { .hw_params = rk3328_hw_params, .set_fmt = rk3328_set_dai_fmt, - .digital_mute = rk3328_digital_mute, + .mute_stream = rk3328_mute_stream, .startup = rk3328_pcm_startup, .shutdown = rk3328_pcm_shutdown, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver rk3328_dai[] = { diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index 8c9daf32bab8..d1fc1706422f 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c @@ -103,7 +103,9 @@ struct pll_calc_map { static const struct pll_calc_map pll_preset_table[] = { {19200000, 4096000, 23, 14, 1, false, false}, {19200000, 24576000, 3, 30, 3, false, false}, + {48000000, 3840000, 23, 2, 0, false, false}, {3840000, 24576000, 3, 30, 0, true, false}, + {3840000, 22579200, 3, 5, 0, true, false}, }; static unsigned int find_best_div(unsigned int in, diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index dec5638060c3..098ecf13814d 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1849,13 +1849,13 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, /* Rx slot configuration */ rx_slotnum = hweight_long(rx_mask); - first_bit = find_next_bit((unsigned long *)&rx_mask, 32, 0); - if (rx_slotnum > 1 || rx_slotnum == 0) { + if (rx_slotnum > 1 || !rx_slotnum) { ret = -EINVAL; - dev_dbg(component->dev, "too many rx slots or zero slot\n"); + dev_err(component->dev, "too many rx slots or zero slot\n"); goto _set_tdm_err_; } + first_bit = __ffs(rx_mask); switch (first_bit) { case 0: case 2: @@ -1892,11 +1892,17 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, /* Tx slot configuration */ tx_slotnum = hweight_long(tx_mask); - first_bit = find_next_bit((unsigned long *)&tx_mask, 32, 0); - last_bit = find_last_bit((unsigned long *)&tx_mask, 32); - if (tx_slotnum > 2 || (last_bit-first_bit) > 1) { + if (tx_slotnum > 2 || !tx_slotnum) { ret = -EINVAL; - dev_dbg(component->dev, "too many tx slots or tx slot location error\n"); + dev_err(component->dev, "too many tx slots or zero slot\n"); + goto _set_tdm_err_; + } + + first_bit = __ffs(tx_mask); + last_bit = __fls(tx_mask); + if (last_bit - first_bit > 1) { + ret = -EINVAL; + dev_err(component->dev, "tx slot location error\n"); goto _set_tdm_err_; } diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 2cccb310fa96..548f68649064 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -8,23 +8,24 @@ // // +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/firmware.h> #include <linux/fs.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/delay.h> +#include <linux/platform_device.h> #include <linux/pm.h> #include <linux/regmap.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <linux/firmware.h> -#include <linux/gpio.h> #include <sound/core.h> +#include <sound/initval.h> #include <sound/pcm.h> #include <sound/pcm_params.h> -#include <sound/soc.h> #include <sound/soc-dapm.h> -#include <sound/initval.h> +#include <sound/soc.h> #include <sound/tlv.h> #include "rl6231.h" @@ -493,7 +494,7 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, if (!rt1015->dac_is_used) { rt1015->bypass_boost = ucontrol->value.integer.value[0]; - if (rt1015->bypass_boost == 1) { + if (rt1015->bypass_boost == RT1015_Bypass_Boost) { snd_soc_component_write(component, RT1015_PWR4, 0x00b2); snd_soc_component_write(component, @@ -549,7 +550,7 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: rt1015->dac_is_used = 1; - if (rt1015->bypass_boost == 0) { + if (rt1015->bypass_boost == RT1015_Enable_Boost) { snd_soc_component_write(component, RT1015_SYS_RST1, 0x05f7); snd_soc_component_write(component, @@ -566,8 +567,17 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, } break; + case SND_SOC_DAPM_POST_PMU: + if (rt1015->bypass_boost == RT1015_Bypass_Boost) { + regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8); + regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597); + regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7); + regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028); + } + break; + case SND_SOC_DAPM_POST_PMD: - if (rt1015->bypass_boost == 0) { + if (rt1015->bypass_boost == RT1015_Enable_Boost) { snd_soc_component_write(component, RT1015_PWR9, 0xa800); snd_soc_component_write(component, @@ -617,7 +627,8 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC_E("DAC", NULL, RT1015_PWR1, RT1015_PWR_DAC_BIT, 0, - r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUTPUT("SPO"), }; diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index 8169962935a5..7bd159e8f958 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -368,6 +368,11 @@ enum { FIXED_ADAPTIVE, }; +enum { + RT1015_Enable_Boost = 0, + RT1015_Bypass_Boost, +}; + struct rt1015_priv { struct snd_soc_component *component; struct regmap *regmap; diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index e27742abfa76..4e9dfd235e59 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -411,7 +411,7 @@ static int rt1305_is_rc_clk_from_pll(struct snd_soc_dapm_widget *source, struct rt1305_priv *rt1305 = snd_soc_component_get_drvdata(component); unsigned int val; - snd_soc_component_read(component, RT1305_CLK_1, &val); + val = snd_soc_component_read(component, RT1305_CLK_1); if (rt1305->sysclk_src == RT1305_FS_SYS_PRE_S_PLL1 && (val & RT1305_SEL_PLL_SRC_2_RCCLK)) 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 e8d14eefc41b..5fb9653d9131 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 f8c0f977206c..dc0273a5a11f 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -508,7 +508,7 @@ static int rt298_adc_event(struct snd_soc_dapm_widget *w, VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 0x7080, 0x7000); /* If MCLK doesn't exist, reset AD filter */ - if (!(snd_soc_component_read32(component, RT298_VAD_CTRL) & 0x200)) { + if (!(snd_soc_component_read(component, RT298_VAD_CTRL) & 0x200)) { pr_info("NO MCLK\n"); switch (nid) { case RT298_ADC_IN1: @@ -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/rt5616.c b/sound/soc/codecs/rt5616.c index fcf16ec64d10..fd0d3a08e9dd 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -348,7 +348,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, { unsigned int val; - val = snd_soc_component_read32(snd_soc_dapm_to_component(source->dapm), RT5616_GLB_CLK); + val = snd_soc_component_read(snd_soc_dapm_to_component(source->dapm), RT5616_GLB_CLK); val &= RT5616_SCLK_SRC_MASK; if (val == RT5616_SCLK_SRC_PLL1) return 1; diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index f70b9f7e68bb..653da3eaf355 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -64,7 +64,7 @@ static const struct reg_default rt5631_reg[] = { { RT5631_PSEUDO_SPATL_CTRL, 0x0553 }, }; -/** +/* * rt5631_write_index - write index register of 2nd layer */ static void rt5631_write_index(struct snd_soc_component *component, @@ -74,7 +74,7 @@ static void rt5631_write_index(struct snd_soc_component *component, snd_soc_component_write(component, RT5631_INDEX_DATA, value); } -/** +/* * rt5631_read_index - read index register of 2nd layer */ static unsigned int rt5631_read_index(struct snd_soc_component *component, @@ -83,7 +83,7 @@ static unsigned int rt5631_read_index(struct snd_soc_component *component, unsigned int value; snd_soc_component_write(component, RT5631_INDEX_ADD, reg); - value = snd_soc_component_read32(component, RT5631_INDEX_DATA); + value = snd_soc_component_read(component, RT5631_INDEX_DATA); return value; } @@ -285,7 +285,7 @@ static int check_sysclk1_source(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_GLOBAL_CLK_CTRL); + reg = snd_soc_component_read(component, RT5631_GLOBAL_CLK_CTRL); return reg & RT5631_SYSCLK_SOUR_SEL_PLL; } @@ -303,7 +303,7 @@ static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_OUTMIXER_L_CTRL); + reg = snd_soc_component_read(component, RT5631_OUTMIXER_L_CTRL); return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L); } @@ -313,7 +313,7 @@ static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_OUTMIXER_R_CTRL); + reg = snd_soc_component_read(component, RT5631_OUTMIXER_R_CTRL); return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R); } @@ -323,7 +323,7 @@ static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_SPK_MIXER_CTRL); + reg = snd_soc_component_read(component, RT5631_SPK_MIXER_CTRL); return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L); } @@ -333,7 +333,7 @@ static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_SPK_MIXER_CTRL); + reg = snd_soc_component_read(component, RT5631_SPK_MIXER_CTRL); return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R); } @@ -343,7 +343,7 @@ static int check_adcl_select(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_ADC_REC_MIXER); + reg = snd_soc_component_read(component, RT5631_ADC_REC_MIXER); return !(reg & RT5631_M_MIC1_TO_RECMIXER_L); } @@ -353,12 +353,13 @@ static int check_adcr_select(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_ADC_REC_MIXER); + reg = snd_soc_component_read(component, RT5631_ADC_REC_MIXER); return !(reg & RT5631_M_MIC2_TO_RECMIXER_R); } /** * onebit_depop_power_stage - auto depop in power stage. + * @component: ASoC component * @enable: power on/off * * When power on/off headphone, the depop sequence is done by hardware. @@ -372,9 +373,9 @@ static void onebit_depop_power_stage(struct snd_soc_component *component, int en RT5631_EN_ONE_BIT_DEPOP, 0); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { /* config one-bit depop parameter */ @@ -397,6 +398,7 @@ static void onebit_depop_power_stage(struct snd_soc_component *component, int en /** * onebit_depop_mute_stage - auto depop in mute stage. + * @component: ASoC component * @enable: mute/unmute * * When mute/unmute headphone, the depop sequence is done by hardware. @@ -410,9 +412,9 @@ static void onebit_depop_mute_stage(struct snd_soc_component *component, int ena RT5631_EN_ONE_BIT_DEPOP, 0); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { schedule_timeout_uninterruptible(msecs_to_jiffies(10)); @@ -435,6 +437,7 @@ static void onebit_depop_mute_stage(struct snd_soc_component *component, int ena /** * onebit_depop_power_stage - step by step depop sequence in power stage. + * @component: ASoC component * @enable: power on/off * * When power on/off headphone, the depop sequence is done in step by step. @@ -448,9 +451,9 @@ static void depop_seq_power_stage(struct snd_soc_component *component, int enabl RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { /* config depop sequence parameter */ @@ -507,6 +510,7 @@ static void depop_seq_power_stage(struct snd_soc_component *component, int enabl /** * depop_seq_mute_stage - step by step depop sequence in mute stage. + * @component: ASoC component * @enable: mute/unmute * * When mute/unmute headphone, the depop sequence is done in step by step. @@ -520,9 +524,9 @@ static void depop_seq_mute_stage(struct snd_soc_component *component, int enable RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { schedule_timeout_uninterruptible(msecs_to_jiffies(10)); diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 747ca248bf10..1414ad15d01c 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1651,7 +1651,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) if (component == NULL) return -EINVAL; - val = snd_soc_component_read32(component, RT5640_I2S1_SDP); + val = snd_soc_component_read(component, RT5640_I2S1_SDP); val = (val & RT5640_I2S_IF_MASK) >> RT5640_I2S_IF_SFT; switch (dai_id) { case RT5640_AIF1: @@ -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; @@ -2081,7 +2081,7 @@ int rt5640_sel_asrc_clk_src(struct snd_soc_component *component, snd_soc_component_update_bits(component, RT5640_ASRC_2, asrc2_mask, asrc2_value); - if (snd_soc_component_read32(component, RT5640_ASRC_2)) { + if (snd_soc_component_read(component, RT5640_ASRC_2)) { rt5640->asrc_en = true; snd_soc_component_update_bits(component, RT5640_JD_CTRL, 0x3, 0x3); } else { @@ -2146,7 +2146,7 @@ static bool rt5640_micbias1_ovcd(struct snd_soc_component *component) { int val; - val = snd_soc_component_read32(component, RT5640_IRQ_CTRL2); + val = snd_soc_component_read(component, RT5640_IRQ_CTRL2); dev_dbg(component->dev, "irq ctrl2 %#04x\n", val); return (val & RT5640_MB1_OC_STATUS); @@ -2157,7 +2157,7 @@ static bool rt5640_jack_inserted(struct snd_soc_component *component) struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); int val; - val = snd_soc_component_read32(component, RT5640_INT_IRQ_ST); + val = snd_soc_component_read(component, RT5640_INT_IRQ_ST); dev_dbg(component->dev, "irq status %#04x\n", val); if (rt5640->jd_inverted) @@ -2484,7 +2484,7 @@ static int rt5640_probe(struct snd_soc_component *component) snd_soc_component_update_bits(component, RT5640_MICBIAS, 0x0030, 0x0030); snd_soc_component_update_bits(component, RT5640_DSP_PATH2, 0xfc00, 0x0c00); - switch (snd_soc_component_read32(component, RT5640_RESET) & RT5640_ID_MASK) { + switch (snd_soc_component_read(component, RT5640_RESET) & RT5640_ID_MASK) { case RT5640_ID_5640: case RT5640_ID_5642: snd_soc_add_component_controls(component, diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index e2e1d5b03b38..420003d062c7 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -866,7 +866,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int val; - val = snd_soc_component_read32(component, RT5645_GLB_CLK); + val = snd_soc_component_read(component, RT5645_GLB_CLK); val &= RT5645_SCLK_SRC_MASK; if (val == RT5645_SCLK_SRC_PLL1) return 1; @@ -909,7 +909,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case 1: case 2: @@ -3121,9 +3121,9 @@ static void rt5645_enable_push_button_irq(struct snd_soc_component *component, RT5645_INT_IRQ_ST, 0x8, 0x8); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x8000); - snd_soc_component_read32(component, RT5650_4BTN_IL_CMD1); + snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, - snd_soc_component_read32(component, RT5650_4BTN_IL_CMD1)); + snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); } else { snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x0); @@ -3216,7 +3216,7 @@ static int rt5645_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5650_4BTN_IL_CMD1); + val = snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("val=0x%x\n", val); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5650_4BTN_IL_CMD1, val); @@ -3271,10 +3271,10 @@ static void rt5645_jack_detect_work(struct work_struct *work) report, SND_JACK_MICROPHONE); return; case 4: - val = snd_soc_component_read32(rt5645->component, RT5645_A_JD_CTRL1) & 0x0020; + val = snd_soc_component_read(rt5645->component, RT5645_A_JD_CTRL1) & 0x0020; break; default: /* read rt5645 jd1_1 status */ - val = snd_soc_component_read32(rt5645->component, RT5645_INT_IRQ_ST) & 0x1000; + val = snd_soc_component_read(rt5645->component, RT5645_INT_IRQ_ST) & 0x1000; break; } @@ -3284,7 +3284,7 @@ static void rt5645_jack_detect_work(struct work_struct *work) } else if (!val && rt5645->jack_type != 0) { /* for push button and jack out */ btn_type = 0; - if (snd_soc_component_read32(rt5645->component, RT5645_INT_IRQ_ST) & 0x4) { + if (snd_soc_component_read(rt5645->component, RT5645_INT_IRQ_ST) & 0x4) { /* button pressed */ report = SND_JACK_HEADSET; btn_type = rt5645_button_detect(rt5645->component); diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index c506c9305043..d198e191fb0c 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1514,7 +1514,7 @@ static int rt5651_set_bias_level(struct snd_soc_component *component, switch (level) { case SND_SOC_BIAS_PREPARE: if (SND_SOC_BIAS_STANDBY == snd_soc_component_get_bias_level(component)) { - if (snd_soc_component_read32(component, RT5651_PLL_MODE_1) & 0x9200) + if (snd_soc_component_read(component, RT5651_PLL_MODE_1) & 0x9200) snd_soc_component_update_bits(component, RT5651_D_MISC, 0xc00, 0xc00); } @@ -1608,7 +1608,7 @@ static bool rt5651_micbias1_ovcd(struct snd_soc_component *component) { int val; - val = snd_soc_component_read32(component, RT5651_IRQ_CTRL2); + val = snd_soc_component_read(component, RT5651_IRQ_CTRL2); dev_dbg(component->dev, "irq ctrl2 %#04x\n", val); return (val & RT5651_MB1_OC_CLR); @@ -1625,7 +1625,7 @@ static bool rt5651_jack_inserted(struct snd_soc_component *component) return val; } - val = snd_soc_component_read32(component, RT5651_INT_IRQ_ST); + val = snd_soc_component_read(component, RT5651_INT_IRQ_ST); dev_dbg(component->dev, "irq status %#04x\n", val); switch (rt5651->jd_src) { diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 89e0f58512fa..41e5917b16a5 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -1195,50 +1195,13 @@ static const struct snd_kcontrol_new rt5659_if3_dac_swap_mux = static const struct snd_kcontrol_new rt5659_if3_adc_swap_mux = SOC_DAPM_ENUM("IF3 ADC Swap Source", rt5659_if3_adc_enum); -static const char * const rt5659_asrc_clk_src[] = { - "clk_sysy_div_out", "clk_i2s1_track", "clk_i2s2_track", - "clk_i2s3_track", "clk_sys2", "clk_sys3" -}; - -static unsigned int rt5659_asrc_clk_map_values[] = { - 0, 1, 2, 3, 5, 6, -}; - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_da_sto_asrc_enum, RT5659_ASRC_2, RT5659_DA_STO_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_da_monol_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_L_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_da_monor_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_R_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_sto1_asrc_enum, RT5659_ASRC_2, RT5659_AD_STO1_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_sto2_asrc_enum, RT5659_ASRC_3, RT5659_AD_STO2_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_monol_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_L_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_monor_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_R_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - static int rt5659_hp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (snd_soc_component_read32(component, RT5659_STO_NG2_CTRL_1) & RT5659_NG2_EN) { + if (snd_soc_component_read(component, RT5659_STO_NG2_CTRL_1) & RT5659_NG2_EN) { snd_soc_component_update_bits(component, RT5659_STO_NG2_CTRL_1, RT5659_NG2_EN_MASK, RT5659_NG2_DIS); snd_soc_component_update_bits(component, RT5659_STO_NG2_CTRL_1, @@ -1305,7 +1268,7 @@ static int rt5659_headset_detect(struct snd_soc_component *component, int jack_i snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power"); snd_soc_dapm_sync(dapm); - reg_63 = snd_soc_component_read32(component, RT5659_PWR_ANLG_1); + reg_63 = snd_soc_component_read(component, RT5659_PWR_ANLG_1); snd_soc_component_update_bits(component, RT5659_PWR_ANLG_1, RT5659_PWR_VREF2 | RT5659_PWR_MB, @@ -1323,7 +1286,7 @@ static int rt5659_headset_detect(struct snd_soc_component *component, int jack_i while (i < 5) { msleep(sleep_time[i]); - val = snd_soc_component_read32(component, RT5659_EJD_CTRL_2) & 0x0003; + val = snd_soc_component_read(component, RT5659_EJD_CTRL_2) & 0x0003; i++; if (val == 0x1 || val == 0x2 || val == 0x3) break; @@ -1357,7 +1320,7 @@ static int rt5659_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5659_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5659_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5659_4BTN_IL_CMD_1, val); @@ -1396,7 +1359,7 @@ static void rt5659_jack_detect_work(struct work_struct *work) if (!rt5659->component) return; - val = snd_soc_component_read32(rt5659->component, RT5659_INT_ST_1) & 0x0080; + val = snd_soc_component_read(rt5659->component, RT5659_INT_ST_1) & 0x0080; if (!val) { /* jack in */ if (rt5659->jack_type == 0) { @@ -1696,7 +1659,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, unsigned int val; struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5659_GLB_CLK); + val = snd_soc_component_read(component, RT5659_GLB_CLK); val &= RT5659_SCLK_SRC_MASK; if (val == RT5659_SCLK_SRC_PLL1) return 1; @@ -1739,7 +1702,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case 1: case 2: diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index efa145e91731..9e3813f7583d 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -373,7 +373,7 @@ static int rt5660_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int val; - val = snd_soc_component_read32(component, RT5660_GLB_CLK); + val = snd_soc_component_read(component, RT5660_GLB_CLK); val &= RT5660_SCLK_SRC_MASK; if (val == RT5660_SCLK_SRC_PLL1) return 1; @@ -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/rt5663.c b/sound/soc/codecs/rt5663.c index e6c1ec6c426e..619fb9a031e3 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -1482,7 +1482,7 @@ static int rt5663_v2_jack_detect(struct snd_soc_component *component, int jack_i while (i < 5) { msleep(sleep_time[i]); - val = snd_soc_component_read32(component, RT5663_CBJ_TYPE_2) & 0x0003; + val = snd_soc_component_read(component, RT5663_CBJ_TYPE_2) & 0x0003; if (val == 0x1 || val == 0x2 || val == 0x3) break; dev_dbg(component->dev, "%s: MX-0011 val=%x sleep %d\n", @@ -1595,7 +1595,7 @@ static int rt5663_jack_detect(struct snd_soc_component *component, int jack_inse i++; } - val = snd_soc_component_read32(component, RT5663_EM_JACK_TYPE_2) & 0x0003; + val = snd_soc_component_read(component, RT5663_EM_JACK_TYPE_2) & 0x0003; dev_dbg(component->dev, "%s val = %d\n", __func__, val); snd_soc_component_update_bits(component, RT5663_HP_CHARGE_PUMP_1, @@ -1698,12 +1698,12 @@ static int rt5663_impedance_sensing(struct snd_soc_component *component) rt5663->imp_table[i].dc_offset_r_manual & 0xffff); } - reg84 = snd_soc_component_read32(component, RT5663_ASRC_2); - reg26 = snd_soc_component_read32(component, RT5663_STO1_ADC_MIXER); - reg2fa = snd_soc_component_read32(component, RT5663_DUMMY_1); - reg91 = snd_soc_component_read32(component, RT5663_HP_CHARGE_PUMP_1); - reg10 = snd_soc_component_read32(component, RT5663_RECMIX); - reg80 = snd_soc_component_read32(component, RT5663_GLB_CLK); + reg84 = snd_soc_component_read(component, RT5663_ASRC_2); + reg26 = snd_soc_component_read(component, RT5663_STO1_ADC_MIXER); + reg2fa = snd_soc_component_read(component, RT5663_DUMMY_1); + reg91 = snd_soc_component_read(component, RT5663_HP_CHARGE_PUMP_1); + reg10 = snd_soc_component_read(component, RT5663_RECMIX); + reg80 = snd_soc_component_read(component, RT5663_GLB_CLK); snd_soc_component_update_bits(component, RT5663_STO_DRE_1, 0x8000, 0); snd_soc_component_write(component, RT5663_ASRC_2, 0); @@ -1768,11 +1768,11 @@ static int rt5663_impedance_sensing(struct snd_soc_component *component) for (i = 0; i < 100; i++) { msleep(20); - if (snd_soc_component_read32(component, RT5663_INT_ST_1) & 0x2) + if (snd_soc_component_read(component, RT5663_INT_ST_1) & 0x2) break; } - value = snd_soc_component_read32(component, RT5663_HP_IMP_SEN_4); + value = snd_soc_component_read(component, RT5663_HP_IMP_SEN_4); snd_soc_component_update_bits(component, RT5663_DEPOP_1, 0x3000, 0); snd_soc_component_write(component, RT5663_INT_ST_1, 0); @@ -1843,7 +1843,7 @@ static int rt5663_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5663_IL_CMD_5); + val = snd_soc_component_read(component, RT5663_IL_CMD_5); dev_dbg(component->dev, "%s: val=0x%x\n", __func__, val); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5663_IL_CMD_5, val); @@ -1879,7 +1879,7 @@ static int rt5663_set_jack_detect(struct snd_soc_component *component, static bool rt5663_check_jd_status(struct snd_soc_component *component) { struct rt5663_priv *rt5663 = snd_soc_component_get_drvdata(component); - int val = snd_soc_component_read32(component, RT5663_INT_ST_1); + int val = snd_soc_component_read(component, RT5663_INT_ST_1); dev_dbg(component->dev, "%s val=%x\n", __func__, val); @@ -2072,7 +2072,7 @@ static int rt5663_is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, unsigned int val; struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5663_GLB_CLK); + val = snd_soc_component_read(component, RT5663_GLB_CLK); val &= RT5663_SCLK_SRC_MASK; if (val == RT5663_SCLK_SRC_PLL1) return 1; @@ -2115,7 +2115,7 @@ static int rt5663_is_using_asrc(struct snd_soc_dapm_widget *w, } } - val = (snd_soc_component_read32(component, reg) >> shift) & 0x7; + val = (snd_soc_component_read(component, reg) >> shift) & 0x7; if (val) return 1; @@ -2130,15 +2130,15 @@ static int rt5663_i2s_use_asrc(struct snd_soc_dapm_widget *source, struct rt5663_priv *rt5663 = snd_soc_component_get_drvdata(component); int da_asrc_en, ad_asrc_en; - da_asrc_en = (snd_soc_component_read32(component, RT5663_ASRC_2) & + da_asrc_en = (snd_soc_component_read(component, RT5663_ASRC_2) & RT5663_DA_STO1_TRACK_MASK) ? 1 : 0; switch (rt5663->codec_ver) { case CODEC_VER_1: - ad_asrc_en = (snd_soc_component_read32(component, RT5663_ASRC_3) & + ad_asrc_en = (snd_soc_component_read(component, RT5663_ASRC_3) & RT5663_V2_AD_STO1_TRACK_MASK) ? 1 : 0; break; case CODEC_VER_0: - ad_asrc_en = (snd_soc_component_read32(component, RT5663_ASRC_2) & + ad_asrc_en = (snd_soc_component_read(component, RT5663_ASRC_2) & RT5663_AD_STO1_TRACK_MASK) ? 1 : 0; break; default: diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 68299ce26d3e..8a915cdce0fe 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -1000,7 +1000,7 @@ static int rt5665_hp_vol_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (snd_soc_component_read32(component, RT5665_STO_NG2_CTRL_1) & RT5665_NG2_EN) { + if (snd_soc_component_read(component, RT5665_STO_NG2_CTRL_1) & RT5665_NG2_EN) { snd_soc_component_update_bits(component, RT5665_STO_NG2_CTRL_1, RT5665_NG2_EN_MASK, RT5665_NG2_DIS); snd_soc_component_update_bits(component, RT5665_STO_NG2_CTRL_1, @@ -1016,7 +1016,7 @@ static int rt5665_mono_vol_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (snd_soc_component_read32(component, RT5665_MONO_NG2_CTRL_1) & RT5665_NG2_EN) { + if (snd_soc_component_read(component, RT5665_MONO_NG2_CTRL_1) & RT5665_NG2_EN) { snd_soc_component_update_bits(component, RT5665_MONO_NG2_CTRL_1, RT5665_NG2_EN_MASK, RT5665_NG2_DIS); snd_soc_component_update_bits(component, RT5665_MONO_NG2_CTRL_1, @@ -1126,7 +1126,7 @@ static int rt5665_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5665_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5665_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5665_4BTN_IL_CMD_1, val); @@ -1198,7 +1198,7 @@ static int rt5665_headset_detect(struct snd_soc_component *component, int jack_i usleep_range(10000, 15000); - rt5665->sar_adc_value = snd_soc_component_read32(rt5665->component, + rt5665->sar_adc_value = snd_soc_component_read(rt5665->component, RT5665_SAR_IL_CMD_4) & 0x7ff; sar_hs_type = rt5665->pdata.sar_hs_type ? @@ -1245,7 +1245,7 @@ static void rt5665_jd_check_handler(struct work_struct *work) struct rt5665_priv *rt5665 = container_of(work, struct rt5665_priv, jd_check_work.work); - if (snd_soc_component_read32(rt5665->component, RT5665_AJD1_CTRL) & 0x0010) { + if (snd_soc_component_read(rt5665->component, RT5665_AJD1_CTRL) & 0x0010) { /* jack out */ rt5665->jack_type = rt5665_headset_detect(rt5665->component, 0); @@ -1310,7 +1310,7 @@ static void rt5665_jack_detect_handler(struct work_struct *work) mutex_lock(&rt5665->calibrate_mutex); - val = snd_soc_component_read32(rt5665->component, RT5665_AJD1_CTRL) & 0x0010; + val = snd_soc_component_read(rt5665->component, RT5665_AJD1_CTRL) & 0x0010; if (!val) { /* jack in */ if (rt5665->jack_type == 0) { @@ -1522,7 +1522,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, unsigned int val; struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5665_GLB_CLK); + val = snd_soc_component_read(component, RT5665_GLB_CLK); val &= RT5665_SCLK_SRC_MASK; if (val == RT5665_SCLK_SRC_PLL1) return 1; @@ -1573,7 +1573,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case RT5665_CLK_SEL_I2S1_ASRC: case RT5665_CLK_SEL_I2S2_ASRC: diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index 5716cede99cb..bc69adc9c8b7 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -847,7 +847,7 @@ static int rt5668_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5668_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5668_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5668_4BTN_IL_CMD_1, val); pr_debug("%s btn_type=%x\n", __func__, btn_type); @@ -907,11 +907,11 @@ static int rt5668_headset_detect(struct snd_soc_component *component, RT5668_TRIG_JD_MASK, RT5668_TRIG_JD_HIGH); count = 0; - val = snd_soc_component_read32(component, RT5668_CBJ_CTRL_2) + val = snd_soc_component_read(component, RT5668_CBJ_CTRL_2) & RT5668_JACK_TYPE_MASK; while (val == 0 && count < 50) { usleep_range(10000, 15000); - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, RT5668_CBJ_CTRL_2) & RT5668_JACK_TYPE_MASK; count++; } @@ -955,7 +955,7 @@ static void rt5668_jd_check_handler(struct work_struct *work) struct rt5668_priv *rt5668 = container_of(work, struct rt5668_priv, jd_check_work.work); - if (snd_soc_component_read32(rt5668->component, RT5668_AJD1_CTRL) + if (snd_soc_component_read(rt5668->component, RT5668_AJD1_CTRL) & RT5668_JDH_RS_MASK) { /* jack out */ rt5668->jack_type = rt5668_headset_detect(rt5668->component, 0); @@ -1030,7 +1030,7 @@ static void rt5668_jack_detect_handler(struct work_struct *work) mutex_lock(&rt5668->calibrate_mutex); - val = snd_soc_component_read32(rt5668->component, RT5668_AJD1_CTRL) + val = snd_soc_component_read(rt5668->component, RT5668_AJD1_CTRL) & RT5668_JDH_RS_MASK; if (!val) { /* jack in */ @@ -1191,7 +1191,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, int ref, val, reg, idx = -EINVAL; static const int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; - val = snd_soc_component_read32(component, RT5668_GPIO_CTRL_1) & + val = snd_soc_component_read(component, RT5668_GPIO_CTRL_1) & RT5668_GP4_PIN_MASK; if (w->shift == RT5668_PWR_ADC_S1F_BIT && val == RT5668_GP4_PIN_ADCDAT2) @@ -1219,7 +1219,7 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5668_GLB_CLK); + val = snd_soc_component_read(component, RT5668_GLB_CLK); val &= RT5668_SCLK_SRC_MASK; if (val == RT5668_SCLK_SRC_PLL1) return 1; @@ -1247,7 +1247,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case RT5668_CLK_SEL_I2S1_ASRC: case RT5668_CLK_SEL_I2S2_ASRC: diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index dfbc0ca38ff7..a0c8f58d729b 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -25,13 +25,12 @@ #include <sound/soc-dapm.h> #include <sound/initval.h> #include <sound/tlv.h> -#include <sound/rt5670.h> #include "rl6231.h" #include "rt5670.h" #include "rt5670-dsp.h" -#define RT5670_DEV_GPIO BIT(0) +#define RT5670_GPIO1_IS_IRQ BIT(0) #define RT5670_IN2_DIFF BIT(1) #define RT5670_DMIC_EN BIT(2) #define RT5670_DMIC1_IN2P BIT(3) @@ -453,13 +452,13 @@ static int rt5670_headset_detect(struct snd_soc_component *component, int jack_i snd_soc_component_update_bits(component, RT5670_CJ_CTRL2, RT5670_CBJ_MN_JD, 0); msleep(300); - val = snd_soc_component_read32(component, RT5670_CJ_CTRL3) & 0x7; + val = snd_soc_component_read(component, RT5670_CJ_CTRL3) & 0x7; if (val == 0x1 || val == 0x2) { rt5670->jack_type = SND_JACK_HEADSET; /* for push button */ snd_soc_component_update_bits(component, RT5670_INT_IRQ_ST, 0x8, 0x8); snd_soc_component_update_bits(component, RT5670_IL_CMD, 0x40, 0x40); - snd_soc_component_read32(component, RT5670_IL_CMD); + snd_soc_component_read(component, RT5670_IL_CMD); } else { snd_soc_component_update_bits(component, RT5670_GEN_CTRL3, 0x4, 0x4); rt5670->jack_type = SND_JACK_HEADPHONE; @@ -499,12 +498,12 @@ static int rt5670_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5670_IL_CMD); + val = snd_soc_component_read(component, RT5670_IL_CMD); btn_type = val & 0xff80; snd_soc_component_write(component, RT5670_IL_CMD, val); if (btn_type != 0) { msleep(20); - val = snd_soc_component_read32(component, RT5670_IL_CMD); + val = snd_soc_component_read(component, RT5670_IL_CMD); snd_soc_component_write(component, RT5670_IL_CMD, val); } @@ -518,10 +517,10 @@ static int rt5670_irq_detection(void *data) struct snd_soc_jack *jack = rt5670->jack; int val, btn_type, report = jack->status; - if (rt5670->pdata.jd_mode == 1) /* 2 port */ - val = snd_soc_component_read32(rt5670->component, RT5670_A_JD_CTRL1) & 0x0070; + if (rt5670->jd_mode == 1) /* 2 port */ + val = snd_soc_component_read(rt5670->component, RT5670_A_JD_CTRL1) & 0x0070; else - val = snd_soc_component_read32(rt5670->component, RT5670_A_JD_CTRL1) & 0x0020; + val = snd_soc_component_read(rt5670->component, RT5670_A_JD_CTRL1) & 0x0020; switch (val) { /* jack in */ @@ -534,7 +533,7 @@ static int rt5670_irq_detection(void *data) break; } btn_type = 0; - if (snd_soc_component_read32(rt5670->component, RT5670_INT_IRQ_ST) & 0x4) { + if (snd_soc_component_read(rt5670->component, RT5670_INT_IRQ_ST) & 0x4) { /* button pressed */ report = SND_JACK_HEADSET; btn_type = rt5670_button_detect(rt5670->component); @@ -763,7 +762,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case 1: case 2: @@ -1454,7 +1453,7 @@ static int rt5670_spk_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); - if (!rt5670->pdata.gpio1_is_ext_spk_en) + if (!rt5670->gpio1_is_ext_spk_en) return 0; switch (event) { @@ -2624,7 +2623,7 @@ static int rt5670_set_bias_level(struct snd_soc_component *component, RT5670_LDO_SEL_MASK, 0x3); break; case SND_SOC_BIAS_OFF: - if (rt5670->pdata.jd_mode) + if (rt5670->jd_mode) snd_soc_component_update_bits(component, RT5670_PWR_ANLG1, RT5670_PWR_VREF1 | RT5670_PWR_MB | RT5670_PWR_BG | RT5670_PWR_VREF2 | @@ -2651,7 +2650,7 @@ static int rt5670_probe(struct snd_soc_component *component) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); - switch (snd_soc_component_read32(component, RT5670_RESET) & RT5670_ID_MASK) { + switch (snd_soc_component_read(component, RT5670_RESET) & RT5670_ID_MASK) { case RT5670_ID_5670: case RT5670_ID_5671: snd_soc_dapm_new_controls(dapm, @@ -2834,7 +2833,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2846,7 +2845,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2858,7 +2857,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC2_INR | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2870,7 +2869,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2882,7 +2881,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2906,7 +2905,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC2_INR | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE3), }, { @@ -2918,7 +2917,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC2_INR | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE3), }, {} @@ -2927,7 +2926,6 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { static int rt5670_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct rt5670_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5670_priv *rt5670; int ret; unsigned int val; @@ -2940,9 +2938,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, rt5670); - if (pdata) - rt5670->pdata = *pdata; - dmi_check_system(dmi_platform_intel_quirks); if (quirk_override) { dev_info(&i2c->dev, "Overriding quirk 0x%x => 0x%x\n", @@ -2950,57 +2945,57 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, rt5670_quirk = quirk_override; } - if (rt5670_quirk & RT5670_DEV_GPIO) { - rt5670->pdata.dev_gpio = true; - dev_info(&i2c->dev, "quirk dev_gpio\n"); + if (rt5670_quirk & RT5670_GPIO1_IS_IRQ) { + rt5670->gpio1_is_irq = true; + dev_info(&i2c->dev, "quirk GPIO1 is IRQ\n"); } if (rt5670_quirk & RT5670_GPIO1_IS_EXT_SPK_EN) { - rt5670->pdata.gpio1_is_ext_spk_en = true; + rt5670->gpio1_is_ext_spk_en = true; dev_info(&i2c->dev, "quirk GPIO1 is external speaker enable\n"); } if (rt5670_quirk & RT5670_IN2_DIFF) { - rt5670->pdata.in2_diff = true; + rt5670->in2_diff = true; dev_info(&i2c->dev, "quirk IN2_DIFF\n"); } if (rt5670_quirk & RT5670_DMIC_EN) { - rt5670->pdata.dmic_en = true; + rt5670->dmic_en = true; dev_info(&i2c->dev, "quirk DMIC enabled\n"); } if (rt5670_quirk & RT5670_DMIC1_IN2P) { - rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; + rt5670->dmic1_data_pin = RT5670_DMIC_DATA_IN2P; dev_info(&i2c->dev, "quirk DMIC1 on IN2P pin\n"); } if (rt5670_quirk & RT5670_DMIC1_GPIO6) { - rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_GPIO6; + rt5670->dmic1_data_pin = RT5670_DMIC_DATA_GPIO6; dev_info(&i2c->dev, "quirk DMIC1 on GPIO6 pin\n"); } if (rt5670_quirk & RT5670_DMIC1_GPIO7) { - rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_GPIO7; + rt5670->dmic1_data_pin = RT5670_DMIC_DATA_GPIO7; dev_info(&i2c->dev, "quirk DMIC1 on GPIO7 pin\n"); } if (rt5670_quirk & RT5670_DMIC2_INR) { - rt5670->pdata.dmic2_data_pin = RT5670_DMIC_DATA_IN3N; + rt5670->dmic2_data_pin = RT5670_DMIC_DATA_IN3N; dev_info(&i2c->dev, "quirk DMIC2 on INR pin\n"); } if (rt5670_quirk & RT5670_DMIC2_GPIO8) { - rt5670->pdata.dmic2_data_pin = RT5670_DMIC_DATA_GPIO8; + rt5670->dmic2_data_pin = RT5670_DMIC_DATA_GPIO8; dev_info(&i2c->dev, "quirk DMIC2 on GPIO8 pin\n"); } if (rt5670_quirk & RT5670_DMIC3_GPIO5) { - rt5670->pdata.dmic3_data_pin = RT5670_DMIC_DATA_GPIO5; + rt5670->dmic3_data_pin = RT5670_DMIC_DATA_GPIO5; dev_info(&i2c->dev, "quirk DMIC3 on GPIO5 pin\n"); } if (rt5670_quirk & RT5670_JD_MODE1) { - rt5670->pdata.jd_mode = 1; + rt5670->jd_mode = 1; dev_info(&i2c->dev, "quirk JD mode 1\n"); } if (rt5670_quirk & RT5670_JD_MODE2) { - rt5670->pdata.jd_mode = 2; + rt5670->jd_mode = 2; dev_info(&i2c->dev, "quirk JD mode 2\n"); } if (rt5670_quirk & RT5670_JD_MODE3) { - rt5670->pdata.jd_mode = 3; + rt5670->jd_mode = 3; dev_info(&i2c->dev, "quirk JD mode 3\n"); } @@ -3041,11 +3036,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, RT5670_MCLK_DET, RT5670_MCLK_DET); - if (rt5670->pdata.in2_diff) + if (rt5670->in2_diff) regmap_update_bits(rt5670->regmap, RT5670_IN2, RT5670_IN_DF2, RT5670_IN_DF2); - if (rt5670->pdata.dev_gpio) { + if (rt5670->gpio1_is_irq) { /* for push button */ regmap_write(rt5670->regmap, RT5670_IL_CMD, 0x0000); regmap_write(rt5670->regmap, RT5670_IL_CMD2, 0x0010); @@ -3057,14 +3052,14 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); } - if (rt5670->pdata.gpio1_is_ext_spk_en) { + if (rt5670->gpio1_is_ext_spk_en) { regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_GPIO1); regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); } - if (rt5670->pdata.jd_mode) { + if (rt5670->jd_mode) { regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK, RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK); rt5670->sysclk = 0; @@ -3079,7 +3074,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, RT5670_JD_TRI_CBJ_SEL_MASK | RT5670_JD_TRI_HPO_SEL_MASK, RT5670_JD_CBJ_JD1_1 | RT5670_JD_HPO_JD1_1); - switch (rt5670->pdata.jd_mode) { + switch (rt5670->jd_mode) { case 1: regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, RT5670_JD1_MODE_MASK, @@ -3100,12 +3095,12 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, } } - if (rt5670->pdata.dmic_en) { + if (rt5670->dmic_en) { regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, RT5670_GP2_PIN_MASK, RT5670_GP2_PIN_DMIC1_SCL); - switch (rt5670->pdata.dmic1_data_pin) { + switch (rt5670->dmic1_data_pin) { case RT5670_DMIC_DATA_IN2P: regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, RT5670_DMIC_1_DP_MASK, @@ -3134,7 +3129,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, break; } - switch (rt5670->pdata.dmic2_data_pin) { + switch (rt5670->dmic2_data_pin) { case RT5670_DMIC_DATA_IN3N: regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, RT5670_DMIC_2_DP_MASK, @@ -3154,7 +3149,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, break; } - switch (rt5670->pdata.dmic3_data_pin) { + switch (rt5670->dmic3_data_pin) { case RT5670_DMIC_DATA_GPIO5: regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL2, RT5670_DMIC_3_DP_MASK, diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index de0203369b7c..56b13fe6bd3c 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h @@ -9,8 +9,6 @@ #ifndef __RT5670_H__ #define __RT5670_H__ -#include <sound/rt5670.h> - /* Info */ #define RT5670_RESET 0x00 #define RT5670_VENDOR_ID 0xfd @@ -1988,11 +1986,23 @@ int rt5670_sel_asrc_clk_src(struct snd_soc_component *component, struct rt5670_priv { struct snd_soc_component *component; - struct rt5670_platform_data pdata; struct regmap *regmap; struct snd_soc_jack *jack; struct snd_soc_jack_gpio hp_gpio; + int jd_mode; + bool in2_diff; + bool gpio1_is_irq; + bool gpio1_is_ext_spk_en; + + bool dmic_en; + unsigned int dmic1_data_pin; + /* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/ + unsigned int dmic2_data_pin; + /* 0 = GPIO8; 1 = IN3N; */ + unsigned int dmic3_data_pin; + /* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/ + int sysclk; int sysclk_src; int lrck[RT5670_AIFS]; diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 7bfade8b3d6e..8f3993a4c1cc 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -112,7 +112,7 @@ static int rt5677_spi_pcm_close( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *codec_component = snd_soc_rtdcom_lookup(rtd, "rt5677"); struct rt5677_priv *rt5677 = @@ -158,7 +158,7 @@ static int rt5677_spi_prepare( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *rt5677_component = snd_soc_rtdcom_lookup(rtd, "rt5677"); struct rt5677_priv *rt5677 = @@ -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/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index e28d08b1cd65..85aba311bdc8 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -59,7 +59,7 @@ static void rt5682_jd_check_handler(struct work_struct *work) struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, jd_check_work.work); - if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) + if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK) { /* jack out */ rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); @@ -232,7 +232,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); - regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080); regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 4cecc5ce545c..94bf6bee78e6 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -431,7 +431,7 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); - regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080); regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index d503b5bef4ba..a4713bd6508d 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -859,7 +859,7 @@ static int rt5682_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5682_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5682_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5682_4BTN_IL_CMD_1, val); dev_dbg(component->dev, "%s btn_type=%x\n", __func__, btn_type); @@ -939,11 +939,11 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_HIGH); count = 0; - val = snd_soc_component_read32(component, RT5682_CBJ_CTRL_2) + val = snd_soc_component_read(component, RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK; while (val == 0 && count < 50) { usleep_range(10000, 15000); - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK; count++; } @@ -963,6 +963,9 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) RT5682_HP_CHARGE_PUMP_1, RT5682_OSW_L_MASK | RT5682_OSW_R_MASK, RT5682_OSW_L_EN | RT5682_OSW_R_EN); + snd_soc_component_update_bits(component, RT5682_MICBIAS_2, + RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, + RT5682_PWR_CLK25M_PU | RT5682_PWR_CLK1M_PU); } else { rt5682_enable_push_button_irq(component, false); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, @@ -975,6 +978,9 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0); snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, RT5682_PWR_CBJ, 0); + snd_soc_component_update_bits(component, RT5682_MICBIAS_2, + RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, + RT5682_PWR_CLK25M_PD | RT5682_PWR_CLK1M_PD); rt5682->jack_type = 0; } @@ -1022,8 +1028,7 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, RT5682_POW_ANA, RT5682_POW_IRQ | RT5682_POW_JDH | RT5682_POW_ANA); regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, - RT5682_PWR_JDH | RT5682_PWR_JDL, - RT5682_PWR_JDH | RT5682_PWR_JDL); + RT5682_PWR_JDH, RT5682_PWR_JDH); regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, RT5682_JD1_EN_MASK | RT5682_JD1_POL_MASK, RT5682_JD1_EN | RT5682_JD1_POL_NOR); @@ -1074,7 +1079,7 @@ void rt5682_jack_detect_handler(struct work_struct *work) mutex_lock(&rt5682->calibrate_mutex); - val = snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) + val = snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK; if (!val) { /* jack in */ @@ -1240,7 +1245,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, if (rt5682->is_sdw) return 0; - val = snd_soc_component_read32(component, RT5682_GPIO_CTRL_1) & + val = snd_soc_component_read(component, RT5682_GPIO_CTRL_1) & RT5682_GP4_PIN_MASK; if (w->shift == RT5682_PWR_ADC_S1F_BIT && val == RT5682_GP4_PIN_ADCDAT2) @@ -1278,7 +1283,7 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5682_GLB_CLK); + val = snd_soc_component_read(component, RT5682_GLB_CLK); val &= RT5682_SCLK_SRC_MASK; if (val == RT5682_SCLK_SRC_PLL1) return 1; @@ -1293,7 +1298,7 @@ static int is_sys_clk_from_pll2(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5682_GLB_CLK); + val = snd_soc_component_read(component, RT5682_GLB_CLK); val &= RT5682_SCLK_SRC_MASK; if (val == RT5682_SCLK_SRC_PLL2) return 1; @@ -1321,7 +1326,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case RT5682_CLK_SEL_I2S1_ASRC: case RT5682_CLK_SEL_I2S2_ASRC: @@ -2255,7 +2260,7 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct rl6231_pll_code pll_code, pll2f_code, pll2b_code; - unsigned int pll2_fout1; + unsigned int pll2_fout1, pll2_ps_val; int ret; if (source == rt5682->pll_src[pll_id] && @@ -2324,8 +2329,15 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, pll2b_code.n_code); snd_soc_component_write(component, RT5682_PLL2_CTRL_3, pll2f_code.n_code << RT5682_PLL2F_N_SFT); + + if (freq_out == 22579200) + pll2_ps_val = 1 << RT5682_PLL2B_SEL_PS_SFT; + else + pll2_ps_val = 1 << RT5682_PLL2B_PS_BYP_SFT; snd_soc_component_update_bits(component, RT5682_PLL2_CTRL_4, + RT5682_PLL2B_SEL_PS_MASK | RT5682_PLL2B_PS_BYP_MASK | RT5682_PLL2B_M_BP_MASK | RT5682_PLL2F_M_BP_MASK | 0xf, + pll2_ps_val | (pll2b_code.m_bp ? 1 : 0) << RT5682_PLL2B_M_BP_SFT | (pll2f_code.m_bp ? 1 : 0) << RT5682_PLL2F_M_BP_SFT | 0xf); @@ -2463,8 +2475,8 @@ static int rt5682_set_bias_level(struct snd_soc_component *component, #ifdef CONFIG_COMMON_CLK #define CLK_PLL2_FIN 48000000 -#define CLK_PLL2_FOUT 24576000 #define CLK_48 48000 +#define CLK_44 44100 static bool rt5682_clk_check(struct rt5682_priv *rt5682) { @@ -2546,13 +2558,22 @@ static unsigned long rt5682_wclk_recalc_rate(struct clk_hw *hw, struct rt5682_priv *rt5682 = container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + const char * const clk_name = __clk_get_name(hw->clk); if (!rt5682_clk_check(rt5682)) return 0; /* - * Only accept to set wclk rate to 48kHz temporarily. + * Only accept to set wclk rate to 44.1k or 48kHz. */ - return CLK_48; + if (rt5682->lrck[RT5682_AIF1] != CLK_48 && + rt5682->lrck[RT5682_AIF1] != CLK_44) { + dev_warn(component->dev, "%s: clk %s only support %d or %d Hz output\n", + __func__, clk_name, CLK_44, CLK_48); + return 0; + } + + return rt5682->lrck[RT5682_AIF1]; } static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, @@ -2561,13 +2582,22 @@ static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, struct rt5682_priv *rt5682 = container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + const char * const clk_name = __clk_get_name(hw->clk); if (!rt5682_clk_check(rt5682)) return -EINVAL; /* - * Only accept to set wclk rate to 48kHz temporarily. + * Only accept to set wclk rate to 44.1k or 48kHz. + * It will force to 48kHz if not both. */ - return CLK_48; + if (rate != CLK_48 && rate != CLK_44) { + dev_warn(component->dev, "%s: clk %s only support %d or %d Hz output\n", + __func__, clk_name, CLK_44, CLK_48); + rate = CLK_48; + } + + return rate; } static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -2580,6 +2610,7 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, struct clk *parent_clk; const char * const clk_name = __clk_get_name(hw->clk); int pre_div; + unsigned int clk_pll2_out; if (!rt5682_clk_check(rt5682)) return -EINVAL; @@ -2602,23 +2633,17 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, clk_name, CLK_PLL2_FIN); /* - * It's a temporary limitation. Only accept to set wclk rate to 48kHz. - * It will force wclk to 48kHz even it's not. - */ - if (rate != CLK_48) { - dev_warn(component->dev, "clk %s only support %d Hz output\n", - clk_name, CLK_48); - rate = CLK_48; - } - - /* - * To achieve the rate conversion from 48MHz to 48kHz, PLL2 is needed. + * To achieve the rate conversion from 48MHz to 44.1k or 48kHz, + * PLL2 is needed. */ + clk_pll2_out = rate * 512; rt5682_set_component_pll(component, RT5682_PLL2, RT5682_PLL2_S_MCLK, - CLK_PLL2_FIN, CLK_PLL2_FOUT); + CLK_PLL2_FIN, clk_pll2_out); rt5682_set_component_sysclk(component, RT5682_SCLK_S_PLL2, 0, - CLK_PLL2_FOUT, SND_SOC_CLOCK_IN); + clk_pll2_out, SND_SOC_CLOCK_IN); + + rt5682->lrck[RT5682_AIF1] = rate; pre_div = rl6231_get_clk_info(rt5682->sysclk, rate); @@ -2639,8 +2664,7 @@ static unsigned long rt5682_bclk_recalc_rate(struct clk_hw *hw, struct snd_soc_component *component = rt5682->component; unsigned int bclks_per_wclk; - snd_soc_component_read(component, RT5682_TDM_TCON_CTRL, - &bclks_per_wclk); + bclks_per_wclk = snd_soc_component_read(component, RT5682_TDM_TCON_CTRL); switch (bclks_per_wclk & RT5682_TDM_BCLK_MS1_MASK) { case RT5682_TDM_BCLK_MS1_256: @@ -2823,6 +2847,7 @@ static int rt5682_probe(struct snd_soc_component *component) struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct sdw_slave *slave; unsigned long time; + struct snd_soc_dapm_context *dapm = &component->dapm; #ifdef CONFIG_COMMON_CLK int ret; @@ -2860,6 +2885,9 @@ static int rt5682_probe(struct snd_soc_component *component) #endif } + snd_soc_dapm_disable_pin(dapm, "MICBIAS"); + snd_soc_dapm_disable_pin(dapm, "Vref2"); + snd_soc_dapm_sync(dapm); return 0; } @@ -3012,13 +3040,14 @@ void rt5682_calibrate(struct rt5682_priv *rt5682) dev_err(rt5682->component->dev, "HP Calibration Failure\n"); /* restore settings */ - regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0x02af); + regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0x002f); regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080); regmap_write(rt5682->regmap, RT5682_GLB_CLK, 0x0000); regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000); regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000); regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005); regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4); + regmap_write(rt5682->regmap, RT5682_CAL_REC, 0x0c0c); mutex_unlock(&rt5682->calibrate_mutex); } diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index f172c9ebd227..6d94327beae5 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1080,6 +1080,10 @@ #define RT5682_PLL2F_N_SFT 8 /* PLL2 M/N/K Code Control 2 (0x009e) */ +#define RT5682_PLL2B_SEL_PS_MASK (0x1 << 13) +#define RT5682_PLL2B_SEL_PS_SFT 13 +#define RT5682_PLL2B_PS_BYP_MASK (0x1 << 12) +#define RT5682_PLL2B_PS_BYP_SFT 12 #define RT5682_PLL2B_M_BP_MASK (0x1 << 11) #define RT5682_PLL2B_M_BP_SFT 11 #define RT5682_PLL2F_M_BP_MASK (0x1 << 7) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index e8a8bf7b4ffe..4d6ff8114622 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -156,14 +156,14 @@ struct sgtl5000_priv { static inline int hp_sel_input(struct snd_soc_component *component) { - return (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_CTRL) & + return (snd_soc_component_read(component, SGTL5000_CHIP_ANA_CTRL) & SGTL5000_HP_SEL_MASK) >> SGTL5000_HP_SEL_SHIFT; } static inline u16 mute_output(struct snd_soc_component *component, u16 mute_mask) { - u16 mute_reg = snd_soc_component_read32(component, + u16 mute_reg = snd_soc_component_read(component, SGTL5000_CHIP_ANA_CTRL); snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, @@ -180,7 +180,7 @@ static inline void restore_output(struct snd_soc_component *component, static void vag_power_on(struct snd_soc_component *component, u32 source) { - if (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & + if (snd_soc_component_read(component, SGTL5000_CHIP_ANA_POWER) & SGTL5000_VAG_POWERUP) return; @@ -225,7 +225,7 @@ static int vag_power_consumers(struct snd_soc_component *component, static void vag_power_off(struct snd_soc_component *component, u32 source) { - u16 ana_pwr = snd_soc_component_read32(component, + u16 ana_pwr = snd_soc_component_read(component, SGTL5000_CHIP_ANA_POWER); if (!(ana_pwr & SGTL5000_VAG_POWERUP)) @@ -545,7 +545,7 @@ static int dac_get_volsw(struct snd_kcontrol *kcontrol, int l; int r; - reg = snd_soc_component_read32(component, SGTL5000_CHIP_DAC_VOL); + reg = snd_soc_component_read(component, SGTL5000_CHIP_DAC_VOL); /* get left channel volume */ l = (reg & SGTL5000_DAC_VOL_LEFT_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT; @@ -633,7 +633,7 @@ static int avc_get_threshold(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int db, i; - u16 reg = snd_soc_component_read32(component, SGTL5000_DAP_AVC_THRESHOLD); + u16 reg = snd_soc_component_read(component, SGTL5000_DAP_AVC_THRESHOLD); /* register value 0 => -96dB */ if (!reg) { @@ -775,7 +775,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { }; /* mute the codec used by alsa core */ -static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int sgtl5000_mute_stream(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; u16 i2s_pwr = SGTL5000_I2S_IN_POWERUP; @@ -1160,9 +1160,10 @@ static int sgtl5000_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops sgtl5000_ops = { .hw_params = sgtl5000_pcm_hw_params, - .digital_mute = sgtl5000_digital_mute, + .mute_stream = sgtl5000_mute_stream, .set_fmt = sgtl5000_set_dai_fmt, .set_sysclk = sgtl5000_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver sgtl5000_dai = { @@ -1325,11 +1326,11 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component) } /* reset value */ - ana_pwr = snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER); + ana_pwr = snd_soc_component_read(component, SGTL5000_CHIP_ANA_POWER); ana_pwr |= SGTL5000_DAC_STEREO | SGTL5000_ADC_STEREO | SGTL5000_REFTOP_POWERUP; - lreg_ctrl = snd_soc_component_read32(component, SGTL5000_CHIP_LINREG_CTRL); + lreg_ctrl = snd_soc_component_read(component, SGTL5000_CHIP_LINREG_CTRL); if (vddio < 3100 && vdda < 3100) { /* enable internal oscillator used for charge pump */ diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index c47e3c4762fe..09449c6c4024 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -388,7 +388,7 @@ static int ssm2518_hw_params(struct snd_pcm_substream *substream, SSM2518_POWER1_MCS_MASK, mcs << 1); } -static int ssm2518_mute(struct snd_soc_dai *dai, int mute) +static int ssm2518_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component); unsigned int val; @@ -623,9 +623,10 @@ static int ssm2518_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops ssm2518_dai_ops = { .startup = ssm2518_startup, .hw_params = ssm2518_hw_params, - .digital_mute = ssm2518_mute, + .mute_stream = ssm2518_mute, .set_fmt = ssm2518_set_dai_fmt, .set_tdm_slot = ssm2518_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ssm2518_dai = { diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 464a4d7873bb..905160246614 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -338,7 +338,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, return 0; } -static int ssm2602_mute(struct snd_soc_dai *dai, int mute) +static int ssm2602_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(dai->component); @@ -505,9 +505,10 @@ static int ssm2602_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ssm2602_dai_ops = { .startup = ssm2602_startup, .hw_params = ssm2602_hw_params, - .digital_mute = ssm2602_mute, + .mute_stream = ssm2602_mute, .set_sysclk = ssm2602_set_dai_sysclk, .set_fmt = ssm2602_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ssm2602_dai = { diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index bb4958bb8fe9..811b1a2c404a 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -220,7 +220,7 @@ static int ssm4567_hw_params(struct snd_pcm_substream *substream, SSM4567_DAC_FS_MASK, dacfs); } -static int ssm4567_mute(struct snd_soc_dai *dai, int mute) +static int ssm4567_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ssm4567 *ssm4567 = snd_soc_component_get_drvdata(dai->component); unsigned int val; @@ -390,9 +390,10 @@ static int ssm4567_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ssm4567_dai_ops = { .hw_params = ssm4567_hw_params, - .digital_mute = ssm4567_mute, + .mute_stream = ssm4567_mute, .set_fmt = ssm4567_set_dai_fmt, .set_tdm_slot = ssm4567_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ssm4567_dai = { diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index e9ccebbc31e4..86528b930de8 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -397,9 +397,9 @@ static void sta32x_watchdog(struct work_struct *work) unsigned int confa, confa_cached; /* check if sta32x has reset itself */ - confa_cached = snd_soc_component_read32(component, STA32X_CONFA); + confa_cached = snd_soc_component_read(component, STA32X_CONFA); regcache_cache_bypass(sta32x->regmap, true); - confa = snd_soc_component_read32(component, STA32X_CONFA); + confa = snd_soc_component_read(component, STA32X_CONFA); regcache_cache_bypass(sta32x->regmap, false); if (confa != confa_cached) { regcache_mark_dirty(sta32x->regmap); @@ -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/sta529.c b/sound/soc/codecs/sta529.c index 2881a0f7bb39..97b5f34027c0 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -251,7 +251,7 @@ static int sta529_hw_params(struct snd_pcm_substream *substream, return 0; } -static int sta529_mute(struct snd_soc_dai *dai, int mute) +static int sta529_mute(struct snd_soc_dai *dai, int mute, int direction) { u8 val = 0; @@ -291,7 +291,8 @@ static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) static const struct snd_soc_dai_ops sta529_dai_ops = { .hw_params = sta529_hw_params, .set_fmt = sta529_set_dai_fmt, - .digital_mute = sta529_mute, + .mute_stream = sta529_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver sta529_dai = { diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index d90e5f2b6f27..bd00c35116cd 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -2,7 +2,7 @@ /* * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Dan Murphy <dmurphy@ti.com> */ @@ -169,7 +169,7 @@ static int tas2552_setup_pll(struct snd_soc_component *component, pll_clkin += tas2552->tdm_delay; } - pll_enable = snd_soc_component_read32(component, TAS2552_CFG_2) & TAS2552_PLL_ENABLE; + pll_enable = snd_soc_component_read(component, TAS2552_CFG_2) & TAS2552_PLL_ENABLE; snd_soc_component_update_bits(component, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); if (pll_clkin == pll_clk) @@ -187,7 +187,7 @@ static int tas2552_setup_pll(struct snd_soc_component *component, unsigned int d, q, t; u8 j; u8 pll_sel = (tas2552->pll_clk_id << 3) & TAS2552_PLL_SRC_MASK; - u8 p = snd_soc_component_read32(component, TAS2552_PLL_CTRL_1); + u8 p = snd_soc_component_read(component, TAS2552_PLL_CTRL_1); p = (p >> 7); @@ -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; @@ -465,7 +465,7 @@ static int tas2552_set_dai_tdm_slot(struct snd_soc_dai *dai, return 0; } -static int tas2552_mute(struct snd_soc_dai *dai, int mute) +static int tas2552_mute(struct snd_soc_dai *dai, int mute, int direction) { u8 cfg1_reg = 0; struct snd_soc_component *component = dai->component; @@ -519,7 +519,8 @@ static const struct snd_soc_dai_ops tas2552_speaker_dai_ops = { .set_sysclk = tas2552_set_dai_sysclk, .set_fmt = tas2552_set_dai_fmt, .set_tdm_slot = tas2552_set_dai_tdm_slot, - .digital_mute = tas2552_mute, + .mute_stream = tas2552_mute, + .no_capture_mute = 1, }; /* Formats supported by TAS2552 driver. */ diff --git a/sound/soc/codecs/tas2552.h b/sound/soc/codecs/tas2552.h index d0958315d6a2..b9c2e70df57e 100644 --- a/sound/soc/codecs/tas2552.h +++ b/sound/soc/codecs/tas2552.h @@ -2,7 +2,7 @@ /* * tas2552.h - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Dan Murphy <dmurphy@ti.com> */ diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index 7fae88655a0f..99920c691d28 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -175,7 +175,37 @@ static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); - int ret = 0; + int left_slot, right_slot; + int slots_cfg; + int ret; + + if (!tx_mask) { + dev_err(component->dev, "tx masks must not be 0\n"); + return -EINVAL; + } + + if (slots == 1) { + if (tx_mask != 1) + return -EINVAL; + + left_slot = 0; + right_slot = 0; + } else { + left_slot = __ffs(tx_mask); + tx_mask &= ~(1 << left_slot); + if (tx_mask == 0) { + right_slot = left_slot; + } else { + right_slot = __ffs(tx_mask); + tx_mask &= ~(1 << right_slot); + } + } + + slots_cfg = (right_slot << TAS2562_RIGHT_SLOT_SHIFT) | left_slot; + + ret = snd_soc_component_write(component, TAS2562_TDM_CFG3, slots_cfg); + if (ret < 0) + return ret; switch (slot_width) { case 16: @@ -208,12 +238,38 @@ static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai, if (ret < 0) return ret; + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5, + TAS2562_TDM_CFG5_VSNS_SLOT_MASK, + tas2562->v_sense_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6, + TAS2562_TDM_CFG6_ISNS_SLOT_MASK, + tas2562->i_sense_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5, + TAS2562_TDM_CFG5_VSNS_SLOT_MASK, + tas2562->v_sense_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6, + TAS2562_TDM_CFG6_ISNS_SLOT_MASK, + tas2562->i_sense_slot); + if (ret < 0) + return ret; + return 0; } static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) { int ret; + int val; + int sense_en; switch (bitwidth) { case SNDRV_PCM_FORMAT_S16_LE: @@ -221,21 +277,18 @@ static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) TAS2562_TDM_CFG2, TAS2562_TDM_CFG2_RXWLEN_MASK, TAS2562_TDM_CFG2_RXWLEN_16B); - tas2562->v_sense_slot = tas2562->i_sense_slot + 2; break; case SNDRV_PCM_FORMAT_S24_LE: snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG2, TAS2562_TDM_CFG2_RXWLEN_MASK, TAS2562_TDM_CFG2_RXWLEN_24B); - tas2562->v_sense_slot = tas2562->i_sense_slot + 4; break; case SNDRV_PCM_FORMAT_S32_LE: snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG2, TAS2562_TDM_CFG2_RXWLEN_MASK, TAS2562_TDM_CFG2_RXWLEN_32B); - tas2562->v_sense_slot = tas2562->i_sense_slot + 4; break; default: @@ -243,17 +296,27 @@ static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) return -EINVAL; } - ret = snd_soc_component_update_bits(tas2562->component, - TAS2562_TDM_CFG5, - TAS2562_TDM_CFG5_VSNS_EN | TAS2562_TDM_CFG5_VSNS_SLOT_MASK, - TAS2562_TDM_CFG5_VSNS_EN | tas2562->v_sense_slot); + val = snd_soc_component_read(tas2562->component, TAS2562_PWR_CTRL); + if (val < 0) + return val; + + if (val & (1 << TAS2562_VSENSE_POWER_EN)) + sense_en = 0; + else + sense_en = TAS2562_TDM_CFG5_VSNS_EN; + + ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG5, + TAS2562_TDM_CFG5_VSNS_EN, sense_en); if (ret < 0) return ret; - ret = snd_soc_component_update_bits(tas2562->component, - TAS2562_TDM_CFG6, - TAS2562_TDM_CFG6_ISNS_EN | TAS2562_TDM_CFG6_ISNS_SLOT_MASK, - TAS2562_TDM_CFG6_ISNS_EN | tas2562->i_sense_slot); + if (val & (1 << TAS2562_ISENSE_POWER_EN)) + sense_en = 0; + else + sense_en = TAS2562_TDM_CFG6_ISNS_EN; + + ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG6, + TAS2562_TDM_CFG6_ISNS_EN, sense_en); if (ret < 0) return ret; @@ -285,7 +348,8 @@ static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_component *component = dai->component; struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); - u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0; + u8 asi_cfg_1 = 0; + u8 tdm_rx_start_slot = 0; int ret; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -307,34 +371,30 @@ static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) dev_err(tas2562->dev, "Failed to set RX edge\n"); return ret; } - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case (SND_SOC_DAIFMT_I2S): - case (SND_SOC_DAIFMT_DSP_A): - case (SND_SOC_DAIFMT_DSP_B): - tdm_rx_start_slot = BIT(1); - break; - case (SND_SOC_DAIFMT_LEFT_J): + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_DSP_B: tdm_rx_start_slot = 0; break; - default: - dev_err(tas2562->dev, "DAI Format is not found, fmt=0x%x\n", - fmt); - ret = -EINVAL; + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_DSP_A: + tdm_rx_start_slot = 1; break; + default: + dev_err(tas2562->dev, + "DAI Format is not found, fmt=0x%x\n", fmt); + return -EINVAL; } ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1, - TAS2562_TDM_CFG1_RX_OFFSET_MASK, - tdm_rx_start_slot); - + TAS2562_RX_OFF_MASK, (tdm_rx_start_slot << 1)); if (ret < 0) return ret; return 0; } -static int tas2562_mute(struct snd_soc_dai *dai, int mute) +static int tas2562_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -504,7 +564,7 @@ static const struct snd_kcontrol_new tas2562_snd_controls[] = { .info = snd_soc_info_volsw, .get = tas2562_volume_control_get, .put = tas2562_volume_control_put, - .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0) , + .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0), }, }; @@ -552,7 +612,8 @@ static const struct snd_soc_dai_ops tas2562_speaker_dai_ops = { .hw_params = tas2562_hw_params, .set_fmt = tas2562_set_dai_fmt, .set_tdm_slot = tas2562_set_dai_tdm_slot, - .digital_mute = tas2562_mute, + .mute_stream = tas2562_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver tas2562_dai[] = { @@ -619,20 +680,49 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) struct device *dev = tas2562->dev; int ret = 0; - tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down-gpio", - GPIOD_OUT_HIGH); + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); if (IS_ERR(tas2562->sdz_gpio)) { - if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) { - tas2562->sdz_gpio = NULL; + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) return -EPROBE_DEFER; - } + + tas2562->sdz_gpio = NULL; + } + + /* + * The shut-down property is deprecated but needs to be checked for + * backwards compatibility. + */ + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); + if (IS_ERR(tas2562->sdz_gpio)) + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + tas2562->sdz_gpio = NULL; } ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no", &tas2562->i_sense_slot); - if (ret) - dev_err(dev, "Looking up %s property failed %d\n", - "ti,imon-slot-no", ret); + if (ret) { + dev_err(dev, "Property %s is missing setting default slot\n", + "ti,imon-slot-no"); + tas2562->i_sense_slot = 0; + } + + + ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", + &tas2562->v_sense_slot); + if (ret) { + dev_info(dev, "Property %s is missing setting default slot\n", + "ti,vmon-slot-no"); + tas2562->v_sense_slot = 2; + } + + if (tas2562->v_sense_slot < tas2562->i_sense_slot) { + dev_err(dev, "Vsense slot must be greater than Isense slot\n"); + return -EINVAL; + } return ret; } diff --git a/sound/soc/codecs/tas2562.h b/sound/soc/codecs/tas2562.h index 28e75fc431d0..81866aeb3fbf 100644 --- a/sound/soc/codecs/tas2562.h +++ b/sound/soc/codecs/tas2562.h @@ -2,7 +2,7 @@ /* * tas2562.h - ALSA SoC Texas Instruments TAS2562 Mono Audio Amplifier * - * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com * * Author: Dan Murphy <dmurphy@ti.com> */ @@ -34,6 +34,10 @@ #define TAS2562_TDM_DET TAS2562_REG(0, 0x11) #define TAS2562_REV_ID TAS2562_REG(0, 0x7d) +#define TAS2562_RX_OFF_MASK GENMASK(5, 1) +#define TAS2562_TX_OFF_MASK GENMASK(3, 1) +#define TAS2562_RIGHT_SLOT_SHIFT 4 + /* Page 2 */ #define TAS2562_DVC_CFG1 TAS2562_REG(2, 0x0c) #define TAS2562_DVC_CFG2 TAS2562_REG(2, 0x0d) @@ -49,7 +53,6 @@ #define TAS2562_TDM_CFG1_RX_EDGE_MASK BIT(0) #define TAS2562_TDM_CFG1_RX_FALLING 1 -#define TAS2562_TDM_CFG1_RX_OFFSET_MASK GENMASK(4, 0) #define TAS2562_TDM_CFG0_RAMPRATE_MASK BIT(5) #define TAS2562_TDM_CFG0_RAMPRATE_44_1 BIT(5) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 54c8135fe43c..c09851834395 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -3,7 +3,7 @@ // ALSA SoC Texas Instruments TAS2770 20-W Digital Input Mono Class-D // Audio Amplifier with Speaker I/V Sense // -// Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ +// Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ // Author: Tracy Yi <tracy-yi@ti.com> // Frank Shi <shifu0704@thundersoft.com> @@ -189,7 +189,7 @@ static const struct snd_soc_dapm_route tas2770_audio_map[] = { {"VSENSE", "Switch", "VMON"}, }; -static int tas2770_mute(struct snd_soc_dai *dai, int mute) +static int tas2770_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int ret; @@ -530,10 +530,11 @@ static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai, } static struct snd_soc_dai_ops tas2770_dai_ops = { - .digital_mute = tas2770_mute, + .mute_stream = tas2770_mute, .hw_params = tas2770_hw_params, .set_fmt = tas2770_set_fmt, .set_tdm_slot = tas2770_set_dai_tdm_slot, + .no_capture_mute = 1, }; #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ @@ -758,8 +759,7 @@ static int tas2770_i2c_probe(struct i2c_client *client, } } - tas2770->reset_gpio = devm_gpiod_get_optional(tas2770->dev, - "reset-gpio", + tas2770->reset_gpio = devm_gpiod_get_optional(tas2770->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(tas2770->reset_gpio)) { if (PTR_ERR(tas2770->reset_gpio) == -EPROBE_DEFER) { diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h index cbb858369fe6..96683971ee9b 100644 --- a/sound/soc/codecs/tas2770.h +++ b/sound/soc/codecs/tas2770.h @@ -2,7 +2,7 @@ * * ALSA SoC TAS2770 codec driver * - * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ */ #ifndef __TAS2770__ #define __TAS2770__ diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 5b7f9fcf6cbf..835a723ce5bc 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -301,7 +301,7 @@ static int tas571x_hw_params(struct snd_pcm_substream *substream, TAS571X_SDI_FMT_MASK, val); } -static int tas571x_mute(struct snd_soc_dai *dai, int mute) +static int tas571x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u8 sysctl2; @@ -354,7 +354,8 @@ static int tas571x_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops tas571x_dai_ops = { .set_fmt = tas571x_set_dai_fmt, .hw_params = tas571x_hw_params, - .digital_mute = tas571x_mute, + .mute_stream = tas571x_mute, + .no_capture_mute = 1, }; diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index 37fab8f22800..9ff644ddb470 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -2,7 +2,7 @@ /* * tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier * - * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C)2015-2016 Texas Instruments Incorporated - https://www.ti.com * * Author: Andreas Dannenberg <dannenberg@ti.com> */ @@ -199,7 +199,7 @@ error_snd_soc_component_update_bits: return ret; } -static int tas5720_mute(struct snd_soc_dai *dai, int mute) +static int tas5720_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int ret; @@ -508,10 +508,10 @@ static int tas5722_volume_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int val; - snd_soc_component_read(component, TAS5720_VOLUME_CTRL_REG, &val); + val = snd_soc_component_read(component, TAS5720_VOLUME_CTRL_REG); ucontrol->value.integer.value[0] = val << 1; - snd_soc_component_read(component, TAS5722_DIGITAL_CTRL2_REG, &val); + val = snd_soc_component_read(component, TAS5722_DIGITAL_CTRL2_REG); ucontrol->value.integer.value[0] |= val & TAS5722_VOL_CONTROL_LSB; return 0; @@ -604,7 +604,8 @@ static const struct snd_soc_dai_ops tas5720_speaker_dai_ops = { .hw_params = tas5720_hw_params, .set_fmt = tas5720_set_dai_fmt, .set_tdm_slot = tas5720_set_dai_tdm_slot, - .digital_mute = tas5720_mute, + .mute_stream = tas5720_mute, + .no_capture_mute = 1, }; /* diff --git a/sound/soc/codecs/tas5720.h b/sound/soc/codecs/tas5720.h index 93079f954f09..223858f0de71 100644 --- a/sound/soc/codecs/tas5720.h +++ b/sound/soc/codecs/tas5720.h @@ -2,7 +2,7 @@ /* * tas5720.h - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier * - * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C)2015-2016 Texas Instruments Incorporated - https://www.ti.com * * Author: Andreas Dannenberg <dannenberg@ti.com> */ diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index aaba39295079..59543d392110 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -2,7 +2,7 @@ /* * ALSA SoC Texas Instruments TAS6424 Quad-Channel Audio Amplifier * - * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ * Author: Andreas Dannenberg <dannenberg@ti.com> * Andrew F. Davis <afd@ti.com> */ @@ -252,7 +252,7 @@ static int tas6424_set_dai_tdm_slot(struct snd_soc_dai *dai, return 0; } -static int tas6424_mute(struct snd_soc_dai *dai, int mute) +static int tas6424_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct tas6424_data *tas6424 = snd_soc_component_get_drvdata(component); @@ -382,7 +382,8 @@ static const struct snd_soc_dai_ops tas6424_speaker_dai_ops = { .hw_params = tas6424_hw_params, .set_fmt = tas6424_set_dai_fmt, .set_tdm_slot = tas6424_set_dai_tdm_slot, - .digital_mute = tas6424_mute, + .mute_stream = tas6424_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver tas6424_dai[] = { diff --git a/sound/soc/codecs/tas6424.h b/sound/soc/codecs/tas6424.h index c67a7835ca66..a6a0d00e5190 100644 --- a/sound/soc/codecs/tas6424.h +++ b/sound/soc/codecs/tas6424.h @@ -2,7 +2,7 @@ /* * ALSA SoC Texas Instruments TAS6424 Quad-Channel Audio Amplifier * - * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ * Author: Andreas Dannenberg <dannenberg@ti.com> * Andrew F. Davis <afd@ti.com> */ diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c index 2bf4f5e8af27..83d220054c96 100644 --- a/sound/soc/codecs/tda7419.c +++ b/sound/soc/codecs/tda7419.c @@ -187,18 +187,13 @@ static int tda7419_vol_get(struct snd_kcontrol *kcontrol, int thresh = tvc->thresh; unsigned int invert = tvc->invert; int val; - int ret; - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, reg); ucontrol->value.integer.value[0] = tda7419_vol_get_value(val, mask, min, thresh, invert); if (tda7419_vol_is_stereo(tvc)) { - ret = snd_soc_component_read(component, rreg, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, rreg); ucontrol->value.integer.value[1] = tda7419_vol_get_value(val, mask, min, thresh, invert); } diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index abc114a3ae2b..3d8e8c2276f0 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c @@ -93,7 +93,7 @@ static int tfa9879_hw_params(struct snd_pcm_substream *substream, return 0; } -static int tfa9879_digital_mute(struct snd_soc_dai *dai, int mute) +static int tfa9879_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -251,8 +251,9 @@ static const struct regmap_config tfa9879_regmap = { static const struct snd_soc_dai_ops tfa9879_dai_ops = { .hw_params = tfa9879_hw_params, - .digital_mute = tfa9879_digital_mute, + .mute_stream = tfa9879_mute_stream, .set_fmt = tfa9879_set_fmt, + .no_capture_mute = 1, }; #define TFA9879_RATES SNDRV_PCM_RATE_8000_96000 diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 35fe8ee5bce9..5cd50d841177 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // TLV320ADCX140 Sound driver -// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ +// Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/ #include <linux/module.h> #include <linux/moduleparam.h> @@ -37,6 +37,13 @@ struct adcx140_priv { unsigned int slot_width; }; +static const char * const gpo_config_names[] = { + "ti,gpo-config-1", + "ti,gpo-config-2", + "ti,gpo-config-3", + "ti,gpo-config-4", +}; + static const struct reg_default adcx140_reg_defaults[] = { { ADCX140_PAGE_SELECT, 0x00 }, { ADCX140_SW_RESET, 0x00 }, @@ -60,10 +67,10 @@ static const struct reg_default adcx140_reg_defaults[] = { { ADCX140_PDMCLK_CFG, 0x40 }, { ADCX140_PDM_CFG, 0x00 }, { ADCX140_GPIO_CFG0, 0x22 }, + { ADCX140_GPO_CFG0, 0x00 }, { ADCX140_GPO_CFG1, 0x00 }, { ADCX140_GPO_CFG2, 0x00 }, { ADCX140_GPO_CFG3, 0x00 }, - { ADCX140_GPO_CFG4, 0x00 }, { ADCX140_GPO_VAL, 0x00 }, { ADCX140_GPIO_MON, 0x00 }, { ADCX140_GPI_CFG0, 0x00 }, @@ -218,8 +225,8 @@ static const struct snd_kcontrol_new in4_resistor_controls[] = { }; /* Analog/Digital Selection */ -static const char *adcx140_mic_sel_text[] = {"Analog", "Line In", "Digital"}; -static const char *adcx140_analog_sel_text[] = {"Analog", "Line In"}; +static const char * const adcx140_mic_sel_text[] = {"Analog", "Line In", "Digital"}; +static const char * const adcx140_analog_sel_text[] = {"Analog", "Line In"}; static SOC_ENUM_SINGLE_DECL(adcx140_mic1p_enum, ADCX140_CH1_CFG0, 5, @@ -313,6 +320,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 +421,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 +470,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"}, @@ -576,7 +605,7 @@ static int adcx140_reset(struct adcx140_priv *adcx140) gpiod_direction_output(adcx140->gpio_reset, 1); } else { ret = regmap_write(adcx140->regmap, ADCX140_SW_RESET, - ADCX140_RESET); + ADCX140_RESET); } /* 8.4.2: wait >= 10 ms after entering sleep mode. */ @@ -624,6 +653,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 +697,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 +717,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 +733,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,36 +757,48 @@ 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) +static const struct snd_soc_dai_ops adcx140_dai_ops = { + .hw_params = adcx140_hw_params, + .set_fmt = adcx140_set_dai_fmt, + .set_tdm_slot = adcx140_set_dai_tdm_slot, +}; + +static int adcx140_configure_gpo(struct adcx140_priv *adcx140) { - 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; + u32 gpo_outputs[ADCX140_NUM_GPOS]; + u32 gpo_output_val = 0; + int ret; + int i; - if (!width) - width = substream->runtime->sample_bits; + for (i = 0; i < ADCX140_NUM_GPOS; i++) { + ret = device_property_read_u32_array(adcx140->dev, + gpo_config_names[i], + gpo_outputs, + ADCX140_NUM_GPO_CFGS); + if (ret) + continue; - /* 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; + if (gpo_outputs[0] > ADCX140_GPO_CFG_MAX) { + dev_err(adcx140->dev, "GPO%d config out of range\n", i + 1); + return -EINVAL; + } - /* Configure data offset */ - snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, - ADCX140_TX_OFFSET_MASK, offset); + if (gpo_outputs[1] > ADCX140_GPO_DRV_MAX) { + dev_err(adcx140->dev, "GPO%d drive out of range\n", i + 1); + return -EINVAL; + } + + gpo_output_val = gpo_outputs[0] << ADCX140_GPO_SHIFT | + gpo_outputs[1]; + ret = regmap_write(adcx140->regmap, ADCX140_GPO_CFG0 + i, + gpo_output_val); + if (ret) + return ret; + } 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, -}; +} static int adcx140_codec_probe(struct snd_soc_component *component) { @@ -792,6 +838,10 @@ static int adcx140_codec_probe(struct snd_soc_component *component) bias_cfg = bias_source << ADCX140_MIC_BIAS_SHIFT | vref_source; + ret = adcx140_reset(adcx140); + if (ret) + goto out; + pdm_count = device_property_count_u32(adcx140->dev, "ti,pdm-edge-select"); if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) { @@ -835,11 +885,11 @@ static int adcx140_codec_probe(struct snd_soc_component *component) return ret; } - ret = adcx140_reset(adcx140); + ret = adcx140_configure_gpo(adcx140); if (ret) goto out; - if(adcx140->supply_areg == NULL) + if (adcx140->supply_areg == NULL) sleep_cfg_val |= ADCX140_AREG_INTERNAL; ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val); @@ -940,8 +990,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c, if (IS_ERR(adcx140->supply_areg)) { if (PTR_ERR(adcx140->supply_areg) == -EPROBE_DEFER) return -EPROBE_DEFER; - else - adcx140->supply_areg = NULL; + + adcx140->supply_areg = NULL; } else { ret = regulator_enable(adcx140->supply_areg); if (ret) { diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h index 39206bf1af12..eedbc1d7221f 100644 --- a/sound/soc/codecs/tlv320adcx140.h +++ b/sound/soc/codecs/tlv320adcx140.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // TLV320ADCX104 Sound driver -// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ +// Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/ #ifndef _TLV320ADCX140_H #define _TLV320ADCX140_H @@ -36,10 +36,10 @@ #define ADCX140_PDMCLK_CFG 0x1f #define ADCX140_PDM_CFG 0x20 #define ADCX140_GPIO_CFG0 0x21 -#define ADCX140_GPO_CFG1 0x22 -#define ADCX140_GPO_CFG2 0x23 -#define ADCX140_GPO_CFG3 0x24 -#define ADCX140_GPO_CFG4 0x25 +#define ADCX140_GPO_CFG0 0x22 +#define ADCX140_GPO_CFG1 0x23 +#define ADCX140_GPO_CFG2 0x24 +#define ADCX140_GPO_CFG3 0x25 #define ADCX140_GPO_VAL 0x29 #define ADCX140_GPIO_MON 0x2a #define ADCX140_GPI_CFG0 0x2b @@ -139,4 +139,10 @@ #define ADCX140_GPI3_INDEX 2 #define ADCX140_GPI4_INDEX 3 +#define ADCX140_NUM_GPOS 4 +#define ADCX140_NUM_GPO_CFGS 2 +#define ADCX140_GPO_SHIFT 4 +#define ADCX140_GPO_CFG_MAX 4 +#define ADCX140_GPO_DRV_MAX 5 + #endif /* _TLV320ADCX140_ */ diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 9868fb22323c..2400093e2c99 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -91,7 +91,7 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, */ val = (val >= 4) ? 4 : (3 - val); - reg = snd_soc_component_read32(component, TLV320AIC23_ANLG) & (~0x1C0); + reg = snd_soc_component_read(component, TLV320AIC23_ANLG) & (~0x1C0); snd_soc_component_write(component, TLV320AIC23_ANLG, reg | (val << 6)); return 0; @@ -103,7 +103,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); u16 val; - val = snd_soc_component_read32(component, TLV320AIC23_ANLG) & (0x1C0); + val = snd_soc_component_read(component, TLV320AIC23_ANLG) & (0x1C0); val = val >> 6; val = (val >= 4) ? 4 : (3 - val); ucontrol->value.integer.value[0] = val; @@ -294,7 +294,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac) static void get_current_sample_rates(struct snd_soc_component *component, int mclk, u32 *sample_rate_adc, u32 *sample_rate_dac) { - int src = snd_soc_component_read32(component, TLV320AIC23_SRATE); + int src = snd_soc_component_read(component, TLV320AIC23_SRATE); int sr = (src >> 2) & 0x0f; int val = (mclk / bosr_usb_divisor_table[src & 3]); int adc = (val * sr_adc_mult_table[sr]) / SR_MULT; @@ -356,7 +356,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - iface_reg = snd_soc_component_read32(component, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); + iface_reg = snd_soc_component_read(component, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); switch (params_width(params)) { case 16: @@ -404,12 +404,12 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, aic23->requested_adc = 0; } -static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) +static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 reg; - reg = snd_soc_component_read32(component, TLV320AIC23_DIGT); + reg = snd_soc_component_read(component, TLV320AIC23_DIGT); if (mute) reg |= TLV320AIC23_DACM_MUTE; @@ -427,7 +427,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 iface_reg; - iface_reg = snd_soc_component_read32(component, TLV320AIC23_DIGT_FMT) & (~0x03); + iface_reg = snd_soc_component_read(component, TLV320AIC23_DIGT_FMT) & (~0x03); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -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; @@ -479,7 +479,7 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int tlv320aic23_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 reg = snd_soc_component_read32(component, TLV320AIC23_PWR) & 0x17f; + u16 reg = snd_soc_component_read(component, TLV320AIC23_PWR) & 0x17f; switch (level) { case SND_SOC_BIAS_ON: @@ -512,9 +512,10 @@ static const struct snd_soc_dai_ops tlv320aic23_dai_ops = { .prepare = tlv320aic23_pcm_prepare, .hw_params = tlv320aic23_hw_params, .shutdown = tlv320aic23_shutdown, - .digital_mute = tlv320aic23_mute, + .mute_stream = tlv320aic23_mute, .set_fmt = tlv320aic23_set_dai_fmt, .set_sysclk = tlv320aic23_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver tlv320aic23_dai = { diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index b9ca3afd4776..c7baef8948d4 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -131,10 +131,10 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, return 0; } -/** +/* * aic26_mute - Mute control to reduce noise when changing audio format */ -static int aic26_mute(struct snd_soc_dai *dai, int mute) +static int aic26_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct aic26 *aic26 = snd_soc_component_get_drvdata(component); @@ -211,9 +211,10 @@ static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static const struct snd_soc_dai_ops aic26_dai_ops = { .hw_params = aic26_hw_params, - .digital_mute = aic26_mute, + .mute_stream = aic26_mute, .set_sysclk = aic26_set_sysclk, .set_fmt = aic26_set_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver aic26_dai = { @@ -266,7 +267,7 @@ static ssize_t aic26_keyclick_show(struct device *dev, struct aic26 *aic26 = dev_get_drvdata(dev); int val, amp, freq, len; - val = snd_soc_component_read32(aic26->component, AIC26_REG_AUDIO_CTRL2); + val = snd_soc_component_read(aic26->component, AIC26_REG_AUDIO_CTRL2); amp = (val >> 12) & 0x7; freq = (125 << ((val >> 8) & 0x7)) >> 1; len = 2 * (1 + ((val >> 4) & 0xf)); @@ -306,7 +307,7 @@ static int aic26_probe(struct snd_soc_component *component) snd_soc_component_write(component, AIC26_REG_POWER_CTRL, 0); /* Audio Control 3 (master mode, fsref rate) */ - reg = snd_soc_component_read32(component, AIC26_REG_AUDIO_CTRL3); + reg = snd_soc_component_read(component, AIC26_REG_AUDIO_CTRL3); reg &= ~0xf800; reg |= 0x0800; /* set master mode */ snd_soc_component_write(component, AIC26_REG_AUDIO_CTRL3, reg); diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 31daa60695bd..5ac7ce264431 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -2,7 +2,7 @@ /* * ALSA SoC TLV320AIC31xx CODEC Driver * - * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2014-2017 Texas Instruments Incorporated - https://www.ti.com/ * Jyri Sarha <jsarha@ti.com> * * Based on ground work by: Ajit Kulkarni <x0175765@ti.com> @@ -877,7 +877,7 @@ static int aic31xx_setup_pll(struct snd_soc_component *component, there may be trouble. To fix the issue edit the aic31xx_divs table for your mclk and sample rate. Details can be found from: - http://www.ti.com/lit/ds/symlink/tlv320aic3100.pdf + https://www.ti.com/lit/ds/symlink/tlv320aic3100.pdf Section: 5.6 CLOCK Generation and PLL */ } @@ -972,7 +972,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream, return aic31xx_setup_pll(component, params); } -static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute) +static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; @@ -1080,7 +1081,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 @@ -1378,7 +1380,8 @@ static const struct snd_soc_dai_ops aic31xx_dai_ops = { .hw_params = aic31xx_hw_params, .set_sysclk = aic31xx_set_dai_sysclk, .set_fmt = aic31xx_set_dai_fmt, - .digital_mute = aic31xx_dac_mute, + .mute_stream = aic31xx_dac_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver dac31xx_dai_driver[] = { diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h index 0523884cee74..81952984613d 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -2,7 +2,7 @@ /* * ALSA SoC TLV320AIC31xx CODEC Driver Definitions * - * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2014-2017 Texas Instruments Incorporated - https://www.ti.com/ */ #ifndef _TLV320AIC31XX_H diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index d087f3b20b1d..467802875c13 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -82,7 +82,7 @@ static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); u8 val; - val = snd_soc_component_read32(component, AIC32X4_DINCTL); + val = snd_soc_component_read(component, AIC32X4_DINCTL); ucontrol->value.integer.value[0] = (val & 0x01); @@ -96,7 +96,7 @@ static int aic32x4_set_mfp2_gpio(struct snd_kcontrol *kcontrol, u8 val; u8 gpio_check; - val = snd_soc_component_read32(component, AIC32X4_DOUTCTL); + val = snd_soc_component_read(component, AIC32X4_DOUTCTL); gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED); if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) { printk(KERN_ERR "%s: MFP2 is not configure as a GPIO output\n", @@ -123,7 +123,7 @@ static int aic32x4_get_mfp3_gpio(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); u8 val; - val = snd_soc_component_read32(component, AIC32X4_SCLKCTL); + val = snd_soc_component_read(component, AIC32X4_SCLKCTL); ucontrol->value.integer.value[0] = (val & 0x01); @@ -137,7 +137,7 @@ static int aic32x4_set_mfp4_gpio(struct snd_kcontrol *kcontrol, u8 val; u8 gpio_check; - val = snd_soc_component_read32(component, AIC32X4_MISOCTL); + val = snd_soc_component_read(component, AIC32X4_MISOCTL); gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED); if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) { printk(KERN_ERR "%s: MFP4 is not configure as a GPIO output\n", @@ -164,7 +164,7 @@ static int aic32x4_get_mfp5_gpio(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); u8 val; - val = snd_soc_component_read32(component, AIC32X4_GPIOCTL); + val = snd_soc_component_read(component, AIC32X4_GPIOCTL); ucontrol->value.integer.value[0] = ((val & 0x2) >> 1); return 0; @@ -177,7 +177,7 @@ static int aic32x4_set_mfp5_gpio(struct snd_kcontrol *kcontrol, u8 val; u8 gpio_check; - val = snd_soc_component_read32(component, AIC32X4_GPIOCTL); + val = snd_soc_component_read(component, AIC32X4_GPIOCTL); gpio_check = (val & AIC32X4_MFP5_GPIO_OUTPUT); if (gpio_check != AIC32X4_MFP5_GPIO_OUTPUT) { printk(KERN_ERR "%s: MFP5 is not configure as a GPIO output\n", @@ -812,7 +812,7 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream, return 0; } -static int aic32x4_mute(struct snd_soc_dai *dai, int mute) +static int aic32x4_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -866,9 +866,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops aic32x4_ops = { .hw_params = aic32x4_hw_params, - .digital_mute = aic32x4_mute, + .mute_stream = aic32x4_mute, .set_fmt = aic32x4_set_dai_fmt, .set_sysclk = aic32x4_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver aic32x4_dai = { @@ -978,7 +979,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component) AIC32X4_LDOCTLEN : 0; snd_soc_component_write(component, AIC32X4_LDOCTL, tmp_reg); - tmp_reg = snd_soc_component_read32(component, AIC32X4_CMMODE); + tmp_reg = snd_soc_component_read(component, AIC32X4_CMMODE); if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) tmp_reg |= AIC32X4_LDOIN_18_36; if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) @@ -1004,7 +1005,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component) * and down for the first capture to work properly. It seems related to * a HW BUG or some kind of behavior not documented in the datasheet. */ - tmp_reg = snd_soc_component_read32(component, AIC32X4_ADCSETUP); + tmp_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP); snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg | AIC32X4_LADC_EN | AIC32X4_RADC_EN); snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 424faafcb85b..6d066bc58ac8 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1056,7 +1056,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, width = params_width(params); /* select data word length */ - data = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); + data = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); switch (width) { case 16: break; @@ -1216,11 +1216,11 @@ static int aic3x_prepare(struct snd_pcm_substream *substream, return 0; } -static int aic3x_mute(struct snd_soc_dai *dai, int mute) +static int aic3x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u8 ldac_reg = snd_soc_component_read32(component, LDAC_VOL) & ~MUTE_ON; - u8 rdac_reg = snd_soc_component_read32(component, RDAC_VOL) & ~MUTE_ON; + u8 ldac_reg = snd_soc_component_read(component, LDAC_VOL) & ~MUTE_ON; + u8 rdac_reg = snd_soc_component_read(component, RDAC_VOL) & ~MUTE_ON; if (mute) { snd_soc_component_write(component, LDAC_VOL, ldac_reg | MUTE_ON); @@ -1256,8 +1256,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); u8 iface_areg, iface_breg; - iface_areg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; - iface_breg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; + iface_areg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; + iface_breg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1407,8 +1407,8 @@ static int aic3x_set_power(struct snd_soc_component *component, int power) * writing one of them and thus caused other one also not * being written */ - pll_c = snd_soc_component_read32(component, AIC3X_PLL_PROGC_REG); - pll_d = snd_soc_component_read32(component, AIC3X_PLL_PROGD_REG); + pll_c = snd_soc_component_read(component, AIC3X_PLL_PROGC_REG); + pll_d = snd_soc_component_read(component, AIC3X_PLL_PROGD_REG); if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { snd_soc_component_write(component, AIC3X_PLL_PROGC_REG, pll_c); @@ -1481,10 +1481,11 @@ static int aic3x_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops aic3x_dai_ops = { .hw_params = aic3x_hw_params, .prepare = aic3x_prepare, - .digital_mute = aic3x_mute, + .mute_stream = aic3x_mute, .set_sysclk = aic3x_set_dai_sysclk, .set_fmt = aic3x_set_dai_fmt, .set_tdm_slot = aic3x_set_dai_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver aic3x_dai = { 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/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index 27b8c6ba72fa..3265d3e8cb28 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -103,7 +103,7 @@ static bool plls_locked(struct snd_soc_component *component) int count = MAX_PLL_LOCK_20MS_WAITS; do { - ret = snd_soc_component_read32(component, R_PLLCTL0); + ret = snd_soc_component_read(component, R_PLLCTL0); if (ret < 0) { dev_err(component->dev, "Failed to read PLL lock status (%d)\n", ret); @@ -148,7 +148,7 @@ static int write_coeff_ram(struct snd_soc_component *component, u8 *coeff_ram, for (cnt = 0; cnt < coeff_cnt; cnt++, addr++) { for (trys = 0; trys < DACCRSTAT_MAX_TRYS; trys++) { - ret = snd_soc_component_read32(component, R_DACCRSTAT); + ret = snd_soc_component_read(component, R_DACCRSTAT); if (ret < 0) { dev_err(component->dev, "Failed to read stat (%d)\n", ret); diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index c3587af9985c..d0af16b4db2f 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -353,12 +353,7 @@ static int write_coeff_ram(struct snd_soc_component *component, u8 *coeff_ram, for (cnt = 0; cnt < coeff_cnt; cnt++, coeff_addr++) { for (trys = 0; trys < DACCRSTAT_MAX_TRYS; trys++) { - ret = snd_soc_component_read(component, r_stat, &val); - if (ret < 0) { - dev_err(component->dev, - "Failed to read stat (%d)\n", ret); - return ret; - } + val = snd_soc_component_read(component, r_stat); if (!val) break; } @@ -444,12 +439,7 @@ static int coeff_ram_put(struct snd_kcontrol *kcontrol, mutex_lock(&tscs454->pll1.lock); mutex_lock(&tscs454->pll2.lock); - ret = snd_soc_component_read(component, R_PLLSTAT, &val); - if (ret < 0) { - dev_err(component->dev, "Failed to read PLL status (%d)\n", - ret); - goto exit; - } + val = snd_soc_component_read(component, R_PLLSTAT); if (val) { /* PLLs locked */ ret = write_coeff_ram(component, coeff_ram, r_stat, r_addr, r_wr, @@ -2642,13 +2632,10 @@ static int tscs454_set_sysclk(struct snd_soc_dai *dai, struct tscs454 *tscs454 = snd_soc_component_get_drvdata(component); unsigned int val; int bclk_dai; - int ret; dev_dbg(component->dev, "%s(): freq = %u\n", __func__, freq); - ret = snd_soc_component_read(component, R_PLLCTL, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, R_PLLCTL); bclk_dai = (val & FM_PLLCTL_BCLKSEL) >> FB_PLLCTL_BCLKSEL; if (bclk_dai != dai->id) @@ -3204,10 +3191,7 @@ static int tscs454_hw_params(struct snd_pcm_substream *substream, } if (!aifs_active(&tscs454->aifs_status)) { /* First active aif */ - ret = snd_soc_component_read(component, R_ISRC, &val); - if (ret < 0) - goto exit; - + val = snd_soc_component_read(component, R_ISRC); if ((val & FM_ISRC_IBR) == FV_IBR_48) tscs454->internal_rate.pll = &tscs454->pll1; else diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index f34637afee51..b37203336c4e 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -997,7 +997,7 @@ static void twl6040_mute_path(struct snd_soc_component *component, enum twl6040_ } } -static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute) +static int twl6040_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { switch (dai->id) { case TWL6040_DAI_LEGACY: @@ -1020,7 +1020,8 @@ static const struct snd_soc_dai_ops twl6040_dai_ops = { .hw_params = twl6040_hw_params, .prepare = twl6040_prepare, .set_sysclk = twl6040_set_dai_sysclk, - .digital_mute = twl6040_digital_mute, + .mute_stream = twl6040_mute_stream, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver twl6040_dai[] = { diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 1cc7f56912dc..bf9182cedb82 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -117,7 +117,7 @@ static inline void uda134x_reset(struct snd_soc_component *component) regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, 0); } -static int uda134x_mute(struct snd_soc_dai *dai, int mute) +static int uda134x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(dai->component); unsigned int mask = 1<<2; @@ -416,9 +416,10 @@ static const struct snd_soc_dai_ops uda134x_dai_ops = { .startup = uda134x_startup, .shutdown = uda134x_shutdown, .hw_params = uda134x_hw_params, - .digital_mute = uda134x_mute, + .mute_stream = uda134x_mute, .set_sysclk = uda134x_set_dai_sysclk, .set_fmt = uda134x_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver uda134x_dai = { diff --git a/sound/soc/codecs/wcd-clsh-v2.c b/sound/soc/codecs/wcd-clsh-v2.c index cc5a9c9b918b..1be82113c59a 100644 --- a/sound/soc/codecs/wcd-clsh-v2.c +++ b/sound/soc/codecs/wcd-clsh-v2.c @@ -119,7 +119,7 @@ static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl, static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp) { - return snd_soc_component_read32(comp, WCD9XXX_A_CDC_CLSH_CRC) & + return snd_soc_component_read(comp, WCD9XXX_A_CDC_CLSH_CRC) & WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK; } diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index fb073f4dc7ed..f2d9d52ee171 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1617,7 +1617,7 @@ static int wcd9335_set_mix_interpolator_rate(struct snd_soc_dai *dai, list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) { for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)) & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; @@ -1650,9 +1650,9 @@ static int wcd9335_set_prim_interpolator_rate(struct snd_soc_dai *dai, * is connected */ for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { - cfg0 = snd_soc_component_read32(comp, + cfg0 = snd_soc_component_read(comp, WCD9335_CDC_RX_INP_MUX_RX_INT_CFG0(j)); - cfg1 = snd_soc_component_read32(comp, + cfg1 = snd_soc_component_read(comp, WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)); inp0_sel = cfg0 & @@ -1826,7 +1826,7 @@ static int wcd9335_set_decimator_rate(struct snd_soc_dai *dai, return -EINVAL; } - tx_mux_sel = snd_soc_component_read32(comp, tx_port_reg) & + tx_mux_sel = snd_soc_component_read(comp, tx_port_reg) & (shift_val << shift); tx_mux_sel = tx_mux_sel >> shift; @@ -2678,17 +2678,17 @@ static int wcd9335_codec_find_amic_input(struct snd_soc_component *comp, if (adc_mux_n < 4) { reg = WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + 2 * adc_mux_n; mreg = WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0 + 2 * adc_mux_n; - mux_sel = snd_soc_component_read32(comp, reg) & 0x3; + mux_sel = snd_soc_component_read(comp, reg) & 0x3; } else { reg = WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0 + adc_mux_n - 4; mreg = reg; - mux_sel = snd_soc_component_read32(comp, reg) >> 6; + mux_sel = snd_soc_component_read(comp, reg) >> 6; } if (mux_sel != WCD9335_CDC_TX_INP_MUX_SEL_AMIC) return 0; - return snd_soc_component_read32(comp, mreg) & 0x07; + return snd_soc_component_read(comp, mreg) & 0x07; } static u16 wcd9335_codec_get_amic_pwlvl_reg(struct snd_soc_component *comp, @@ -2776,7 +2776,7 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, amic_n); if (pwr_level_reg) { - switch ((snd_soc_component_read32(comp, pwr_level_reg) & + switch ((snd_soc_component_read(comp, pwr_level_reg) & WCD9335_AMIC_PWR_LVL_MASK) >> WCD9335_AMIC_PWR_LVL_SHIFT) { case WCD9335_AMIC_PWR_LEVEL_LP: @@ -2798,7 +2798,7 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, break; } } - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; if (hpf_coff_freq != CF_MIN_3DB_150HZ) @@ -2830,10 +2830,10 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x00); snd_soc_component_write(comp, tx_gain_ctl_reg, - snd_soc_component_read32(comp, tx_gain_ctl_reg)); + snd_soc_component_read(comp, tx_gain_ctl_reg)); break; case SND_SOC_DAPM_PRE_PMD: - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x10); snd_soc_component_update_bits(comp, dec_cfg_reg, 0x08, 0x00); @@ -3080,7 +3080,7 @@ static int wcd9335_codec_enable_mix_path(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - val = snd_soc_component_read32(comp, gain_reg); + val = snd_soc_component_read(comp, gain_reg); val += offset_val; snd_soc_component_write(comp, gain_reg, val); break; @@ -3208,7 +3208,7 @@ static int wcd9335_codec_enable_prim_interpolator( } if ((reg != prim_int_reg) && - ((snd_soc_component_read32(comp, prim_int_reg)) & + ((snd_soc_component_read(comp, prim_int_reg)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK)) snd_soc_component_update_bits(comp, reg, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, @@ -3344,7 +3344,7 @@ static int wcd9335_codec_enable_interpolator(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMU: wcd9335_config_compander(comp, w->shift, event); - val = snd_soc_component_read32(comp, gain_reg); + val = snd_soc_component_read(comp, gain_reg); val += offset_val; snd_soc_component_write(comp, gain_reg, val); break; @@ -3366,12 +3366,12 @@ static void wcd9335_codec_hph_mode_gain_opt(struct snd_soc_component *component, u8 hph_pa_status; bool is_hphl_pa, is_hphr_pa; - hph_pa_status = snd_soc_component_read32(component, WCD9335_ANA_HPH); + hph_pa_status = snd_soc_component_read(component, WCD9335_ANA_HPH); is_hphl_pa = hph_pa_status >> 7; is_hphr_pa = (hph_pa_status & 0x40) >> 6; - hph_l_en = snd_soc_component_read32(component, WCD9335_HPH_L_EN); - hph_r_en = snd_soc_component_read32(component, WCD9335_HPH_R_EN); + hph_l_en = snd_soc_component_read(component, WCD9335_HPH_L_EN); + hph_r_en = snd_soc_component_read(component, WCD9335_HPH_R_EN); l_val = (hph_l_en & 0xC0) | 0x20 | gain; r_val = (hph_r_en & 0xC0) | 0x20 | gain; @@ -3542,7 +3542,7 @@ static int wcd9335_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: /* Read DEM INP Select */ - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD9335_CDC_RX1_RX_PATH_SEC0) & 0x03; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) { @@ -3694,7 +3694,7 @@ static int wcd9335_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMU: /* Read DEM INP Select */ - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD9335_CDC_RX2_RX_PATH_SEC0) & WCD9335_CDC_RX_PATH_DEM_INP_SEL_MASK; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || @@ -3755,7 +3755,7 @@ static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD9335_CDC_RX1_RX_PATH_MIX_CTL)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, @@ -3817,7 +3817,7 @@ static int wcd9335_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, mix_vol_reg)) & + if ((snd_soc_component_read(comp, mix_vol_reg)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, mix_vol_reg, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, @@ -3902,7 +3902,7 @@ static int wcd9335_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD9335_CDC_RX2_RX_PATH_MIX_CTL)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, @@ -3942,7 +3942,7 @@ static int wcd9335_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD9335_CDC_RX0_RX_PATH_MIX_CTL)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, @@ -4808,7 +4808,7 @@ static int wcd9335_enable_efuse_sensing(struct snd_soc_component *comp) */ usleep_range(5000, 5500); - if (!(snd_soc_component_read32(comp, + if (!(snd_soc_component_read(comp, WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS) & WCD9335_CHIP_TIER_CTRL_EFUSE_EN_MASK)) WARN(1, "%s: Efuse sense is not complete\n", __func__); diff --git a/sound/soc/codecs/wcd9335.h b/sound/soc/codecs/wcd9335.h index 72060824c743..490fc44144a2 100644 --- a/sound/soc/codecs/wcd9335.h +++ b/sound/soc/codecs/wcd9335.h @@ -4,9 +4,9 @@ #define __WCD9335_H__ /* - * WCD9335 register base can change according to the mode it works in - * in slimbus mode the reg base starts from 0x800 - * in i2s/i2c mode the reg base is 0x0 + * WCD9335 register base can change according to the mode it works in. + * In slimbus mode the reg base starts from 0x800. + * In i2s/i2c mode the reg base is 0x0. */ #define WCD9335_REG(pg, r) ((pg << 8) | (r)) #define WCD9335_REG_OFFSET(r) (r & 0xFF) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 531b8b79e55f..35697b072367 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1464,9 +1464,9 @@ static int wcd934x_set_prim_interpolator_rate(struct snd_soc_dai *dai, if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) continue; - cfg0 = snd_soc_component_read32(comp, + cfg0 = snd_soc_component_read(comp, WCD934X_CDC_RX_INP_MUX_RX_INT_CFG0(j)); - cfg1 = snd_soc_component_read32(comp, + cfg1 = snd_soc_component_read(comp, WCD934X_CDC_RX_INP_MUX_RX_INT_CFG1(j)); inp0_sel = cfg0 & @@ -1513,7 +1513,7 @@ static int wcd934x_set_mix_interpolator_rate(struct snd_soc_dai *dai, /* Interpolators 5 and 6 are not aviliable in Tavil */ if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) continue; - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, WCD934X_CDC_RX_INP_MUX_RX_INT_CFG1(j)) & WCD934X_CDC_RX_INP_MUX_RX_INT_SEL_MASK; @@ -1616,7 +1616,7 @@ static int wcd934x_set_decimator_rate(struct snd_soc_dai *dai, return -EINVAL; } - tx_mux_sel = snd_soc_component_read32(comp, tx_port_reg) & + tx_mux_sel = snd_soc_component_read(comp, tx_port_reg) & (shift_val << shift); tx_mux_sel = tx_mux_sel >> shift; @@ -2346,23 +2346,23 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t)) & 0x7F); - value |= snd_soc_component_read32(component, b2_reg); + value |= snd_soc_component_read(component, b2_reg); snd_soc_component_write(component, reg, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 1) & 0x7F); - value |= (snd_soc_component_read32(component, b2_reg) << 8); + value |= (snd_soc_component_read(component, b2_reg) << 8); snd_soc_component_write(component, reg, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 2) & 0x7F); - value |= (snd_soc_component_read32(component, b2_reg) << 16); + value |= (snd_soc_component_read(component, b2_reg) << 16); snd_soc_component_write(component, reg, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 3) & 0x7F); /* Mask bits top 2 bits since they are reserved */ - value |= (snd_soc_component_read32(component, b2_reg) << 24); + value |= (snd_soc_component_read(component, b2_reg) << 24); return value; } @@ -3535,7 +3535,7 @@ static int wcd934x_codec_enable_mix_path(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMU: - val = snd_soc_component_read32(comp, gain_reg); + val = snd_soc_component_read(comp, gain_reg); val += offset_val; snd_soc_component_write(comp, gain_reg, val); break; @@ -3554,23 +3554,23 @@ static int wcd934x_codec_set_iir_gain(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: /* B1 GAIN */ snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B2 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B3 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B4 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B5 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); break; default: break; @@ -3591,7 +3591,7 @@ static int wcd934x_codec_enable_main_path(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: snd_soc_component_write(comp, gain_reg, - snd_soc_component_read32(comp, gain_reg)); + snd_soc_component_read(comp, gain_reg)); break; } @@ -3635,7 +3635,7 @@ static int wcd934x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: /* Read DEM INP Select */ - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD934X_CDC_RX1_RX_PATH_SEC0) & 0x03; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || @@ -3686,7 +3686,7 @@ static int wcd934x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD934X_CDC_RX2_RX_PATH_SEC0) & 0x03; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) { @@ -3837,7 +3837,7 @@ static int wcd934x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, WCD934X_HPH_AUTOCHOP_TIMER_ENABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) & 0x10) snd_soc_component_update_bits(comp, WCD934X_CDC_RX2_RX_PATH_MIX_CTL, @@ -3889,7 +3889,7 @@ static u32 wcd934x_get_dmic_sample_rate(struct snd_soc_component *comp, ++adc_mux_index; continue; } - adc_mux_sel = ((snd_soc_component_read32(comp, adc_mux_ctl_reg) + adc_mux_sel = ((snd_soc_component_read(comp, adc_mux_ctl_reg) & 0xF8) >> 3) - 1; if (adc_mux_sel == dmic) { @@ -3902,7 +3902,7 @@ static u32 wcd934x_get_dmic_sample_rate(struct snd_soc_component *comp, if (dec_found && adc_mux_index <= 8) { tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL + (16 * adc_mux_index); - tx_stream_fs = snd_soc_component_read32(comp, tx_fs_reg) & 0x0F; + tx_stream_fs = snd_soc_component_read(comp, tx_fs_reg) & 0x0F; if (tx_stream_fs <= 4) { if (wcd->dmic_sample_rate <= WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ) @@ -4104,12 +4104,12 @@ static int wcd934x_codec_find_amic_input(struct snd_soc_component *comp, adc_mux_n - 4; } - is_amic = (((snd_soc_component_read32(comp, adc_mux_in_reg) + is_amic = (((snd_soc_component_read(comp, adc_mux_in_reg) & mask) >> shift) == 1); if (!is_amic) return 0; - return snd_soc_component_read32(comp, amic_mux_sel_reg) & 0x07; + return snd_soc_component_read(comp, amic_mux_sel_reg) & 0x07; } static u16 wcd934x_codec_get_amic_pwlvl_reg(struct snd_soc_component *comp, @@ -4193,7 +4193,7 @@ static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w, if (!pwr_level_reg) break; - switch ((snd_soc_component_read32(comp, pwr_level_reg) & + switch ((snd_soc_component_read(comp, pwr_level_reg) & WCD934X_AMIC_PWR_LVL_MASK) >> WCD934X_AMIC_PWR_LVL_SHIFT) { case WCD934X_AMIC_PWR_LEVEL_LP: @@ -4216,7 +4216,7 @@ static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_POST_PMU: - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; if (hpf_coff_freq != CF_MIN_3DB_150HZ) { snd_soc_component_update_bits(comp, dec_cfg_reg, @@ -4236,11 +4236,11 @@ static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w, } /* apply gain after decimator is enabled */ snd_soc_component_write(comp, tx_gain_ctl_reg, - snd_soc_component_read32(comp, + snd_soc_component_read(comp, tx_gain_ctl_reg)); break; case SND_SOC_DAPM_PRE_PMD: - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; if (hpf_coff_freq != CF_MIN_3DB_150HZ) { diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index fbcee21736e8..2f2b2f5d55e4 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -515,7 +515,7 @@ static int wm0010_stage2_load(struct snd_soc_component *component) dev_dbg(component->dev, "Downloading %zu byte stage 2 loader\n", fw->size); /* Copy to local buffer first as vmalloc causes problems for dma */ - img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); + img = kmemdup(&fw->data[0], fw->size, GFP_KERNEL | GFP_DMA); if (!img) { ret = -ENOMEM; goto abort2; @@ -527,8 +527,6 @@ static int wm0010_stage2_load(struct snd_soc_component *component) goto abort1; } - memcpy(img, &fw->data[0], fw->size); - spi_message_init(&m); memset(&t, 0, sizeof(t)); t.rx_buf = out; diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 7b087d94141b..c62f7ad0022c 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2027,7 +2027,7 @@ static int wm2200_set_fll(struct snd_soc_component *component, int fll_id, int s msleep(1); } - ret = snd_soc_component_read32(component, + ret = snd_soc_component_read(component, WM2200_INTERRUPT_RAW_STATUS_2); if (ret < 0) { dev_err(component->dev, @@ -2060,7 +2060,7 @@ static int wm2200_dai_probe(struct snd_soc_dai *dai) unsigned int val = 0; int ret; - ret = snd_soc_component_read32(component, WM2200_GPIO_CTRL_1); + ret = snd_soc_component_read(component, WM2200_GPIO_CTRL_1); if (ret >= 0) { if ((ret & WM2200_GP1_FN_MASK) != 0) { wm2200->symmetric_rates = true; diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 91cc63c5a51f..9cab01ee4ee9 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -137,7 +137,7 @@ static int wm5100_alloc_sr(struct snd_soc_component *component, int rate) sr_free = i; continue; } - if ((snd_soc_component_read32(component, wm5100_sr_regs[i]) & + if ((snd_soc_component_read(component, wm5100_sr_regs[i]) & WM5100_SAMPLE_RATE_1_MASK) == sr_code) break; } @@ -189,7 +189,7 @@ static void wm5100_free_sr(struct snd_soc_component *component, int rate) if (!wm5100->sr_ref[i]) continue; - if ((snd_soc_component_read32(component, wm5100_sr_regs[i]) & + if ((snd_soc_component_read(component, wm5100_sr_regs[i]) & WM5100_SAMPLE_RATE_1_MASK) == sr_code) break; } @@ -738,9 +738,9 @@ static void wm5100_seq_notifier(struct snd_soc_component *component, /* Wait for the outputs to flag themselves as enabled */ if (wm5100->out_ena[0]) { - expect = snd_soc_component_read32(component, WM5100_CHANNEL_ENABLES_1); + expect = snd_soc_component_read(component, WM5100_CHANNEL_ENABLES_1); for (i = 0; i < 200; i++) { - val = snd_soc_component_read32(component, WM5100_OUTPUT_STATUS_1); + val = snd_soc_component_read(component, WM5100_OUTPUT_STATUS_1); if (val == expect) { wm5100->out_ena[0] = false; break; @@ -753,9 +753,9 @@ static void wm5100_seq_notifier(struct snd_soc_component *component, } if (wm5100->out_ena[1]) { - expect = snd_soc_component_read32(component, WM5100_OUTPUT_ENABLES_2); + expect = snd_soc_component_read(component, WM5100_OUTPUT_ENABLES_2); for (i = 0; i < 200; i++) { - val = snd_soc_component_read32(component, WM5100_OUTPUT_STATUS_2); + val = snd_soc_component_read(component, WM5100_OUTPUT_STATUS_2); if (val == expect) { wm5100->out_ena[1] = false; break; @@ -841,13 +841,13 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w, struct wm5100_priv *wm5100 = snd_soc_component_get_drvdata(component); int ret; - ret = snd_soc_component_read32(component, WM5100_INTERRUPT_RAW_STATUS_3); + ret = snd_soc_component_read(component, WM5100_INTERRUPT_RAW_STATUS_3); ret &= WM5100_SPK_SHUTDOWN_WARN_STS | WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS | WM5100_CLKGEN_ERR_ASYNC_STS; wm5100_log_status3(wm5100, ret); - ret = snd_soc_component_read32(component, WM5100_INTERRUPT_RAW_STATUS_4); + ret = snd_soc_component_read(component, WM5100_INTERRUPT_RAW_STATUS_4); wm5100_log_status4(wm5100, ret); return 0; @@ -1848,7 +1848,7 @@ static int wm5100_set_fll(struct snd_soc_component *component, int fll_id, int s msleep(1); } - ret = snd_soc_component_read32(component, + ret = snd_soc_component_read(component, WM5100_INTERRUPT_RAW_STATUS_3); if (ret < 0) { dev_err(component->dev, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 44de44bff423..4238929b2375 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -290,7 +290,7 @@ static int wm5110_hp_pre_enable(struct snd_soc_dapm_widget *w) struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct arizona_priv *priv = snd_soc_component_get_drvdata(component); struct arizona *arizona = priv->arizona; - unsigned int val = snd_soc_component_read32(component, ARIZONA_DRE_ENABLE); + unsigned int val = snd_soc_component_read(component, ARIZONA_DRE_ENABLE); const struct reg_sequence *wseq; int nregs; @@ -326,7 +326,7 @@ static int wm5110_hp_pre_disable(struct snd_soc_dapm_widget *w) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct arizona_priv *priv = snd_soc_component_get_drvdata(component); - unsigned int val = snd_soc_component_read32(component, ARIZONA_DRE_ENABLE); + unsigned int val = snd_soc_component_read(component, ARIZONA_DRE_ENABLE); switch (w->shift) { case ARIZONA_OUT1L_ENA_SHIFT: @@ -524,7 +524,7 @@ static int wm5110_in_analog_ev(struct snd_soc_dapm_widget *w, wm5110->in_post_pending++; return 0; case SND_SOC_DAPM_PRE_PMU: - wm5110->in_pga_cache[w->shift] = snd_soc_component_read32(component, reg); + wm5110->in_pga_cache[w->shift] = snd_soc_component_read(component, reg); snd_soc_component_update_bits(component, reg, mask, 0x40 << ARIZONA_IN1L_PGA_VOL_SHIFT); diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index fe99584c917f..a6aa212fa0c8 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -331,7 +331,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); snd_soc_component_write(component, reg, val | WM8350_OUT1_VU); return 1; } @@ -766,7 +766,7 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, case WM8350_MCLK_SEL_PLL_32K: wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1, WM8350_MCLK_SEL); - fll_4 = snd_soc_component_read32(component, WM8350_FLL_CONTROL_4) & + fll_4 = snd_soc_component_read(component, WM8350_FLL_CONTROL_4) & ~WM8350_FLL_CLK_SRC_MASK; snd_soc_component_write(component, WM8350_FLL_CONTROL_4, fll_4 | clk_id); break; @@ -790,37 +790,37 @@ static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) switch (div_id) { case WM8350_ADC_CLKDIV: - val = snd_soc_component_read32(component, WM8350_ADC_DIVIDER) & + val = snd_soc_component_read(component, WM8350_ADC_DIVIDER) & ~WM8350_ADC_CLKDIV_MASK; snd_soc_component_write(component, WM8350_ADC_DIVIDER, val | div); break; case WM8350_DAC_CLKDIV: - val = snd_soc_component_read32(component, WM8350_DAC_CLOCK_CONTROL) & + val = snd_soc_component_read(component, WM8350_DAC_CLOCK_CONTROL) & ~WM8350_DAC_CLKDIV_MASK; snd_soc_component_write(component, WM8350_DAC_CLOCK_CONTROL, val | div); break; case WM8350_BCLK_CLKDIV: - val = snd_soc_component_read32(component, WM8350_CLOCK_CONTROL_1) & + val = snd_soc_component_read(component, WM8350_CLOCK_CONTROL_1) & ~WM8350_BCLK_DIV_MASK; snd_soc_component_write(component, WM8350_CLOCK_CONTROL_1, val | div); break; case WM8350_OPCLK_CLKDIV: - val = snd_soc_component_read32(component, WM8350_CLOCK_CONTROL_1) & + val = snd_soc_component_read(component, WM8350_CLOCK_CONTROL_1) & ~WM8350_OPCLK_DIV_MASK; snd_soc_component_write(component, WM8350_CLOCK_CONTROL_1, val | div); break; case WM8350_SYS_CLKDIV: - val = snd_soc_component_read32(component, WM8350_CLOCK_CONTROL_1) & + val = snd_soc_component_read(component, WM8350_CLOCK_CONTROL_1) & ~WM8350_MCLK_DIV_MASK; snd_soc_component_write(component, WM8350_CLOCK_CONTROL_1, val | div); break; case WM8350_DACLR_CLKDIV: - val = snd_soc_component_read32(component, WM8350_DAC_LR_RATE) & + val = snd_soc_component_read(component, WM8350_DAC_LR_RATE) & ~WM8350_DACLRC_RATE_MASK; snd_soc_component_write(component, WM8350_DAC_LR_RATE, val | div); break; case WM8350_ADCLR_CLKDIV: - val = snd_soc_component_read32(component, WM8350_ADC_LR_RATE) & + val = snd_soc_component_read(component, WM8350_ADC_LR_RATE) & ~WM8350_ADCLRC_RATE_MASK; snd_soc_component_write(component, WM8350_ADC_LR_RATE, val | div); break; @@ -834,13 +834,13 @@ static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8350_AI_FORMATING) & + u16 iface = snd_soc_component_read(component, WM8350_AI_FORMATING) & ~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK); - u16 master = snd_soc_component_read32(component, WM8350_AI_DAC_CONTROL) & + u16 master = snd_soc_component_read(component, WM8350_AI_DAC_CONTROL) & ~WM8350_BCLK_MSTR; - u16 dac_lrc = snd_soc_component_read32(component, WM8350_DAC_LR_RATE) & + u16 dac_lrc = snd_soc_component_read(component, WM8350_DAC_LR_RATE) & ~WM8350_DACLRC_ENA; - u16 adc_lrc = snd_soc_component_read32(component, WM8350_ADC_LR_RATE) & + u16 adc_lrc = snd_soc_component_read(component, WM8350_ADC_LR_RATE) & ~WM8350_ADCLRC_ENA; /* set master/slave audio interface */ @@ -907,7 +907,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = codec_dai->component; struct wm8350_data *wm8350_data = snd_soc_component_get_drvdata(component); struct wm8350 *wm8350 = wm8350_data->wm8350; - u16 iface = snd_soc_component_read32(component, WM8350_AI_FORMATING) & + u16 iface = snd_soc_component_read(component, WM8350_AI_FORMATING) & ~WM8350_AIF_WL_MASK; /* bit size */ @@ -942,7 +942,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8350_mute(struct snd_soc_dai *dai, int mute) +static int wm8350_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; unsigned int val; @@ -1047,7 +1047,7 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai, fll_div.ratio); /* set up N.K & dividers */ - fll_1 = snd_soc_component_read32(component, WM8350_FLL_CONTROL_1) & + fll_1 = snd_soc_component_read(component, WM8350_FLL_CONTROL_1) & ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000); snd_soc_component_write(component, WM8350_FLL_CONTROL_1, fll_1 | (fll_div.div << 8) | 0x50); @@ -1055,7 +1055,7 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai, (fll_div.ratio << 11) | (fll_div. n & WM8350_FLL_N_MASK)); snd_soc_component_write(component, WM8350_FLL_CONTROL_3, fll_div.k); - fll_4 = snd_soc_component_read32(component, WM8350_FLL_CONTROL_4) & + fll_4 = snd_soc_component_read(component, WM8350_FLL_CONTROL_4) & ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF); snd_soc_component_write(component, WM8350_FLL_CONTROL_4, fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) | @@ -1426,11 +1426,12 @@ EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); static const struct snd_soc_dai_ops wm8350_dai_ops = { .hw_params = wm8350_pcm_hw_params, - .digital_mute = wm8350_mute, + .mute_stream = wm8350_mute, .set_fmt = wm8350_set_dai_fmt, .set_sysclk = wm8350_set_dai_sysclk, .set_pll = wm8350_set_fll, .set_clkdiv = wm8350_set_clkdiv, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8350_dai = { diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index e25c09b8a693..bf5e77c86aed 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -67,16 +67,12 @@ static void wm8400_component_reset(struct snd_soc_component *component) wm8400_reset_codec_reg_cache(wm8400->wm8400); } -static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0); - static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0); static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -2100, 0, 0); static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0); -static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0); - static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0); static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0); @@ -98,7 +94,7 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); return snd_soc_component_write(component, reg, val | 0x0100); } @@ -328,7 +324,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, switch (reg_shift) { case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : - reg = snd_soc_component_read32(component, WM8400_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8400_OUTPUT_MIXER1); if (reg & WM8400_LDLO) { printk(KERN_WARNING "Cannot set as Output Mixer 1 LDLO Set\n"); @@ -336,7 +332,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, } break; case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): - reg = snd_soc_component_read32(component, WM8400_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8400_OUTPUT_MIXER2); if (reg & WM8400_RDRO) { printk(KERN_WARNING "Cannot set as Output Mixer 2 RDRO Set\n"); @@ -344,7 +340,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, } break; case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): - reg = snd_soc_component_read32(component, WM8400_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8400_SPEAKER_MIXER); if (reg & WM8400_LDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer LDSPK Set\n"); @@ -352,7 +348,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, } break; case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): - reg = snd_soc_component_read32(component, WM8400_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8400_SPEAKER_MIXER); if (reg & WM8400_RDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer RDSPK Set\n"); @@ -439,14 +435,6 @@ static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum, static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); -/* RXVOICE */ -static const struct snd_kcontrol_new wm8400_dapm_rxvoice_controls[] = { -SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8400_INPUT_MIXER5, WM8400_LR4BVOL_SHIFT, - WM8400_LR4BVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8400_INPUT_MIXER6, WM8400_RL4BVOL_SHIFT, - WM8400_RL4BVOL_MASK, 0, in_mix_tlv), -}; - /* LOMIX */ static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = { SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1, @@ -957,11 +945,11 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, wm8400->fll_in = freq_in; /* We *must* disable the FLL before any changes */ - reg = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_2); + reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_2); reg &= ~WM8400_FLL_ENA; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_2, reg); - reg = snd_soc_component_read32(component, WM8400_FLL_CONTROL_1); + reg = snd_soc_component_read(component, WM8400_FLL_CONTROL_1); reg &= ~WM8400_FLL_OSC_ENA; snd_soc_component_write(component, WM8400_FLL_CONTROL_1, reg); @@ -976,7 +964,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8400_FLL_CONTROL_2, factors.k); snd_soc_component_write(component, WM8400_FLL_CONTROL_3, factors.n); - reg = snd_soc_component_read32(component, WM8400_FLL_CONTROL_4); + reg = snd_soc_component_read(component, WM8400_FLL_CONTROL_4); reg &= ~WM8400_FLL_OUTDIV_MASK; reg |= factors.outdiv; snd_soc_component_write(component, WM8400_FLL_CONTROL_4, reg); @@ -993,8 +981,8 @@ static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 audio1, audio3; - audio1 = snd_soc_component_read32(component, WM8400_AUDIO_INTERFACE_1); - audio3 = snd_soc_component_read32(component, WM8400_AUDIO_INTERFACE_3); + audio1 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_1); + audio3 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_3); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1048,22 +1036,22 @@ static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8400_MCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_2) & ~WM8400_MCLK_DIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div); break; case WM8400_DACCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_2) & ~WM8400_DAC_CLKDIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div); break; case WM8400_ADCCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_2) & ~WM8400_ADC_CLKDIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div); break; case WM8400_BCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_1) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_1) & ~WM8400_BCLK_DIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_1, reg | div); break; @@ -1082,7 +1070,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 audio1 = snd_soc_component_read32(component, WM8400_AUDIO_INTERFACE_1); + u16 audio1 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_1); audio1 &= ~WM8400_AIF_WL_MASK; /* bit size */ @@ -1104,10 +1092,10 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8400_mute(struct snd_soc_dai *dai, int mute) +static int wm8400_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 val = snd_soc_component_read32(component, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; + u16 val = snd_soc_component_read(component, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; if (mute) snd_soc_component_write(component, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); @@ -1131,7 +1119,7 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_PREPARE: /* VMID=2*50k */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1) & ~WM8400_VMID_MODE_MASK; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val | 0x2); break; @@ -1157,7 +1145,7 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, msleep(50); /* Enable VREF & VMID at 2x50k */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); val |= 0x2 | WM8400_VREF_ENA; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val); @@ -1171,7 +1159,7 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, } /* VMID=2*300k */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1) & ~WM8400_VMID_MODE_MASK; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val | 0x4); break; @@ -1187,11 +1175,11 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, WM8400_BUFIOEN); /* mute DAC */ - val = snd_soc_component_read32(component, WM8400_DAC_CTRL); + val = snd_soc_component_read(component, WM8400_DAC_CTRL); snd_soc_component_write(component, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); /* Enable any disabled outputs */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | WM8400_OUT4_ENA | WM8400_LOUT_ENA | WM8400_ROUT_ENA; @@ -1234,11 +1222,12 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8400_dai_ops = { .hw_params = wm8400_hw_params, - .digital_mute = wm8400_mute, + .mute_stream = wm8400_mute, .set_fmt = wm8400_set_dai_fmt, .set_clkdiv = wm8400_set_dai_clkdiv, .set_sysclk = wm8400_set_dai_sysclk, .set_pll = wm8400_set_dai_pll, + .no_capture_mute = 1, }; /* @@ -1293,14 +1282,14 @@ static int wm8400_component_probe(struct snd_soc_component *component) wm8400_component_reset(component); - reg = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA); /* Latch volume update bits */ - reg = snd_soc_component_read32(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); + reg = snd_soc_component_read(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); snd_soc_component_write(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME, reg & WM8400_IPVU); - reg = snd_soc_component_read32(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); + reg = snd_soc_component_read(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); snd_soc_component_write(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, reg & WM8400_IPVU); @@ -1314,7 +1303,7 @@ static void wm8400_component_remove(struct snd_soc_component *component) { u16 reg; - reg = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, reg & (~WM8400_CODEC_ENA)); } diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index cd3e0c848cae..73c4a8b9f59e 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -318,11 +318,11 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_component_read32(component, WM8510_CLOCK); + reg = snd_soc_component_read(component, WM8510_CLOCK); snd_soc_component_write(component, WM8510_CLOCK, reg & 0x0ff); /* Turn off PLL */ - reg = snd_soc_component_read32(component, WM8510_POWER1); + reg = snd_soc_component_read(component, WM8510_POWER1); snd_soc_component_write(component, WM8510_POWER1, reg & 0x1df); return 0; } @@ -333,11 +333,11 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8510_PLLK1, pll_div.k >> 18); snd_soc_component_write(component, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); snd_soc_component_write(component, WM8510_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_component_read32(component, WM8510_POWER1); + reg = snd_soc_component_read(component, WM8510_POWER1); snd_soc_component_write(component, WM8510_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_component_read32(component, WM8510_CLOCK); + reg = snd_soc_component_read(component, WM8510_CLOCK); snd_soc_component_write(component, WM8510_CLOCK, reg | 0x100); return 0; @@ -354,23 +354,23 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8510_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8510_GPIO) & 0x1cf; + reg = snd_soc_component_read(component, WM8510_GPIO) & 0x1cf; snd_soc_component_write(component, WM8510_GPIO, reg | div); break; case WM8510_MCLKDIV: - reg = snd_soc_component_read32(component, WM8510_CLOCK) & 0x11f; + reg = snd_soc_component_read(component, WM8510_CLOCK) & 0x11f; snd_soc_component_write(component, WM8510_CLOCK, reg | div); break; case WM8510_ADCCLK: - reg = snd_soc_component_read32(component, WM8510_ADC) & 0x1f7; + reg = snd_soc_component_read(component, WM8510_ADC) & 0x1f7; snd_soc_component_write(component, WM8510_ADC, reg | div); break; case WM8510_DACCLK: - reg = snd_soc_component_read32(component, WM8510_DAC) & 0x1f7; + reg = snd_soc_component_read(component, WM8510_DAC) & 0x1f7; snd_soc_component_write(component, WM8510_DAC, reg | div); break; case WM8510_BCLKDIV: - reg = snd_soc_component_read32(component, WM8510_CLOCK) & 0x1e3; + reg = snd_soc_component_read(component, WM8510_CLOCK) & 0x1e3; snd_soc_component_write(component, WM8510_CLOCK, reg | div); break; default: @@ -385,7 +385,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_component *component = codec_dai->component; u16 iface = 0; - u16 clk = snd_soc_component_read32(component, WM8510_CLOCK) & 0x1fe; + u16 clk = snd_soc_component_read(component, WM8510_CLOCK) & 0x1fe; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -442,8 +442,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 iface = snd_soc_component_read32(component, WM8510_IFACE) & 0x19f; - u16 adn = snd_soc_component_read32(component, WM8510_ADD) & 0x1f1; + u16 iface = snd_soc_component_read(component, WM8510_IFACE) & 0x19f; + u16 adn = snd_soc_component_read(component, WM8510_ADD) & 0x1f1; /* bit size */ switch (params_width(params)) { @@ -487,10 +487,10 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8510_mute(struct snd_soc_dai *dai, int mute) +static int wm8510_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8510_DAC) & 0xffbf; + u16 mute_reg = snd_soc_component_read(component, WM8510_DAC) & 0xffbf; if (mute) snd_soc_component_write(component, WM8510_DAC, mute_reg | 0x40); @@ -504,7 +504,7 @@ static int wm8510_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8510_priv *wm8510 = snd_soc_component_get_drvdata(component); - u16 power1 = snd_soc_component_read32(component, WM8510_POWER1) & ~0x3; + u16 power1 = snd_soc_component_read(component, WM8510_POWER1) & ~0x3; switch (level) { case SND_SOC_BIAS_ON: @@ -547,10 +547,11 @@ static int wm8510_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8510_dai_ops = { .hw_params = wm8510_pcm_hw_params, - .digital_mute = wm8510_mute, + .mute_stream = wm8510_mute, .set_fmt = wm8510_set_dai_fmt, .set_clkdiv = wm8510_set_dai_clkdiv, .set_pll = wm8510_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8510_dai = { diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 04d67ee8203b..c8b50aac6c18 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -147,8 +147,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component); int i; - u16 aifctrl1 = snd_soc_component_read32(component, WM8523_AIF_CTRL1); - u16 aifctrl2 = snd_soc_component_read32(component, WM8523_AIF_CTRL2); + u16 aifctrl1 = snd_soc_component_read(component, WM8523_AIF_CTRL1); + u16 aifctrl2 = snd_soc_component_read(component, WM8523_AIF_CTRL2); /* Find a supported LRCLK ratio */ for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { @@ -258,7 +258,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 aifctrl1 = snd_soc_component_read32(component, WM8523_AIF_CTRL1); + u16 aifctrl1 = snd_soc_component_read(component, WM8523_AIF_CTRL1); aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK | WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 0227c769937f..85ad2f03cfd0 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -511,7 +511,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8580_PLLA3 + offset, (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); - reg = snd_soc_component_read32(component, WM8580_PLLA4 + offset); + reg = snd_soc_component_read(component, WM8580_PLLA4 + offset); reg &= ~0x1b; reg |= pll_div.prescale | pll_div.postscale << 1 | pll_div.freqmode << 3; @@ -608,8 +608,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int aifb; int can_invert_lrclk; - aifa = snd_soc_component_read32(component, WM8580_PAIF1 + codec_dai->driver->id); - aifb = snd_soc_component_read32(component, WM8580_PAIF3 + codec_dai->driver->id); + aifa = snd_soc_component_read(component, WM8580_PAIF1 + codec_dai->driver->id); + aifb = snd_soc_component_read(component, WM8580_PAIF3 + codec_dai->driver->id); aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); @@ -689,7 +689,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8580_MCLK: - reg = snd_soc_component_read32(component, WM8580_PLLB4); + reg = snd_soc_component_read(component, WM8580_PLLB4); reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; switch (div) { @@ -715,7 +715,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, break; case WM8580_CLKOUTSRC: - reg = snd_soc_component_read32(component, WM8580_PLLB4); + reg = snd_soc_component_read(component, WM8580_PLLB4); reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; switch (div) { @@ -800,12 +800,12 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } -static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8580_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; unsigned int reg; - reg = snd_soc_component_read32(component, WM8580_DAC_CONTROL5); + reg = snd_soc_component_read(component, WM8580_DAC_CONTROL5); if (mute) reg |= WM8580_DAC_CONTROL5_MUTEALL; @@ -866,7 +866,8 @@ static const struct snd_soc_dai_ops wm8580_dai_ops_playback = { .set_fmt = wm8580_set_paif_dai_fmt, .set_clkdiv = wm8580_set_dai_clkdiv, .set_pll = wm8580_set_dai_pll, - .digital_mute = wm8580_digital_mute, + .mute_stream = wm8580_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8580_dai_ops_capture = { diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 5ad905dd78b7..bc4d161c59e5 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -158,7 +158,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8711_priv *wm8711 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8711_IFACE) & 0xfff3; + u16 iface = snd_soc_component_read(component, WM8711_IFACE) & 0xfff3; int i = get_coeff(wm8711->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) | coeff_div[i].usb; @@ -204,10 +204,10 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, } } -static int wm8711_mute(struct snd_soc_dai *dai, int mute) +static int wm8711_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8711_APDIGI) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8711_APDIGI) & 0xfff7; if (mute) snd_soc_component_write(component, WM8711_APDIGI, mute_reg | 0x8); @@ -239,7 +239,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8711_IFACE) & 0x000c; + u16 iface = snd_soc_component_read(component, WM8711_IFACE) & 0x000c; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -298,7 +298,7 @@ static int wm8711_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8711_priv *wm8711 = snd_soc_component_get_drvdata(component); - u16 reg = snd_soc_component_read32(component, WM8711_PWR) & 0xff7f; + u16 reg = snd_soc_component_read(component, WM8711_PWR) & 0xff7f; switch (level) { case SND_SOC_BIAS_ON: @@ -329,9 +329,10 @@ static const struct snd_soc_dai_ops wm8711_ops = { .prepare = wm8711_pcm_prepare, .hw_params = wm8711_hw_params, .shutdown = wm8711_shutdown, - .digital_mute = wm8711_mute, + .mute_stream = wm8711_mute, .set_sysclk = wm8711_set_dai_sysclk, .set_fmt = wm8711_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8711_dai = { diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 8b876659f29c..2cd58d133899 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -69,10 +69,10 @@ static const struct snd_soc_dapm_route wm8728_intercon[] = { {"VOUTR", NULL, "DAC"}, }; -static int wm8728_mute(struct snd_soc_dai *dai, int mute) +static int wm8728_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8728_DACCTL); + u16 mute_reg = snd_soc_component_read(component, WM8728_DACCTL); if (mute) snd_soc_component_write(component, WM8728_DACCTL, mute_reg | 1); @@ -87,7 +87,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 dac = snd_soc_component_read32(component, WM8728_DACCTL); + u16 dac = snd_soc_component_read(component, WM8728_DACCTL); dac &= ~0x18; @@ -113,7 +113,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8728_IFCTL); + u16 iface = snd_soc_component_read(component, WM8728_IFCTL); /* Currently only I2S is supported by the driver, though the * hardware is more flexible. @@ -169,7 +169,7 @@ static int wm8728_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { /* Power everything up... */ - reg = snd_soc_component_read32(component, WM8728_DACCTL); + reg = snd_soc_component_read(component, WM8728_DACCTL); snd_soc_component_write(component, WM8728_DACCTL, reg & ~0x4); /* ..then sync in the register cache. */ @@ -178,7 +178,7 @@ static int wm8728_set_bias_level(struct snd_soc_component *component, break; case SND_SOC_BIAS_OFF: - reg = snd_soc_component_read32(component, WM8728_DACCTL); + reg = snd_soc_component_read(component, WM8728_DACCTL); snd_soc_component_write(component, WM8728_DACCTL, reg | 0x4); break; } @@ -192,8 +192,9 @@ static int wm8728_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8728_dai_ops = { .hw_params = wm8728_hw_params, - .digital_mute = wm8728_mute, + .mute_stream = wm8728_mute, .set_fmt = wm8728_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8728_dai = { diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 6fd1bef848ed..304bf725a613 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -336,7 +336,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8731_priv *wm8731 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8731_IFACE) & 0xfff3; + u16 iface = snd_soc_component_read(component, WM8731_IFACE) & 0xfff3; int i = get_coeff(wm8731->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) | coeff_div[i].usb; @@ -366,10 +366,10 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8731_mute(struct snd_soc_dai *dai, int mute) +static int wm8731_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8731_APDIGI) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8731_APDIGI) & 0xfff7; if (mute) snd_soc_component_write(component, WM8731_APDIGI, mute_reg | 0x8); @@ -510,7 +510,7 @@ static int wm8731_set_bias_level(struct snd_soc_component *component, } /* Clear PWROFF, gate CLKOUT, everything else as-is */ - reg = snd_soc_component_read32(component, WM8731_PWR) & 0xff7f; + reg = snd_soc_component_read(component, WM8731_PWR) & 0xff7f; snd_soc_component_write(component, WM8731_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: @@ -546,9 +546,10 @@ static int wm8731_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops wm8731_dai_ops = { .startup = wm8731_startup, .hw_params = wm8731_hw_params, - .digital_mute = wm8731_mute, + .mute_stream = wm8731_mute, .set_sysclk = wm8731_set_dai_sysclk, .set_fmt = wm8731_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8731_dai = { diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 328df81ee839..0e3994326936 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -364,7 +364,7 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int wm8741_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8741_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; @@ -386,7 +386,8 @@ static const struct snd_soc_dai_ops wm8741_dai_ops = { .hw_params = wm8741_hw_params, .set_sysclk = wm8741_set_dai_sysclk, .set_fmt = wm8741_set_dai_fmt, - .digital_mute = wm8741_mute, + .mute_stream = wm8741_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8741_dai = { diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 5f3466170f78..9491817020d8 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -578,8 +578,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8750_priv *wm8750 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8750_IFACE) & 0x1f3; - u16 srate = snd_soc_component_read32(component, WM8750_SRATE) & 0x1c0; + u16 iface = snd_soc_component_read(component, WM8750_IFACE) & 0x1f3; + u16 srate = snd_soc_component_read(component, WM8750_SRATE) & 0x1c0; int coeff = get_coeff(wm8750->sysclk, params_rate(params)); /* bit size */ @@ -606,10 +606,10 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8750_mute(struct snd_soc_dai *dai, int mute) +static int wm8750_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8750_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8750_ADCDAC) & 0xfff7; if (mute) snd_soc_component_write(component, WM8750_ADCDAC, mute_reg | 0x8); @@ -621,7 +621,7 @@ static int wm8750_mute(struct snd_soc_dai *dai, int mute) static int wm8750_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 pwr_reg = snd_soc_component_read32(component, WM8750_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_component_read(component, WM8750_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: @@ -660,9 +660,10 @@ static int wm8750_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8750_dai_ops = { .hw_params = wm8750_pcm_hw_params, - .digital_mute = wm8750_mute, + .mute_stream = wm8750_mute, .set_fmt = wm8750_set_dai_fmt, .set_sysclk = wm8750_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8750_dai = { diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 8753c55c73fa..deaa54be6268 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -244,7 +244,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, if (snd_soc_component_active(component)) return -EBUSY; - ioctl = snd_soc_component_read32(component, WM8753_IOCTL); + ioctl = snd_soc_component_read(component, WM8753_IOCTL); wm8753->dai_func = ucontrol->value.enumerated.item[0]; @@ -748,11 +748,11 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (pll_id == WM8753_PLL1) { offset = 0; enable = 0x10; - reg = snd_soc_component_read32(component, WM8753_CLOCK) & 0xffef; + reg = snd_soc_component_read(component, WM8753_CLOCK) & 0xffef; } else { offset = 4; enable = 0x8; - reg = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfff7; + reg = snd_soc_component_read(component, WM8753_CLOCK) & 0xfff7; } if (!freq_in || !freq_out) { @@ -888,7 +888,7 @@ static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_component *component, unsigned int fmt) { - u16 voice = snd_soc_component_read32(component, WM8753_PCM) & 0x01ec; + u16 voice = snd_soc_component_read(component, WM8753_PCM) & 0x01ec; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -923,8 +923,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); - u16 voice = snd_soc_component_read32(component, WM8753_PCM) & 0x01f3; - u16 srate = snd_soc_component_read32(component, WM8753_SRATE1) & 0x017f; + u16 voice = snd_soc_component_read(component, WM8753_PCM) & 0x01f3; + u16 srate = snd_soc_component_read(component, WM8753_SRATE1) & 0x017f; /* bit size */ switch (params_width(params)) { @@ -958,15 +958,16 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_component *component, { u16 voice, ioctl; - voice = snd_soc_component_read32(component, WM8753_PCM) & 0x011f; - ioctl = snd_soc_component_read32(component, WM8753_IOCTL) & 0x015d; + voice = snd_soc_component_read(component, WM8753_PCM) & 0x011f; + ioctl = snd_soc_component_read(component, WM8753_IOCTL) & 0x015d; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 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; @@ -1026,15 +1027,15 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8753_PCMDIV: - reg = snd_soc_component_read32(component, WM8753_CLOCK) & 0x003f; + reg = snd_soc_component_read(component, WM8753_CLOCK) & 0x003f; snd_soc_component_write(component, WM8753_CLOCK, reg | div); break; case WM8753_BCLKDIV: - reg = snd_soc_component_read32(component, WM8753_SRATE2) & 0x01c7; + reg = snd_soc_component_read(component, WM8753_SRATE2) & 0x01c7; snd_soc_component_write(component, WM8753_SRATE2, reg | div); break; case WM8753_VXCLKDIV: - reg = snd_soc_component_read32(component, WM8753_SRATE2) & 0x003f; + reg = snd_soc_component_read(component, WM8753_SRATE2) & 0x003f; snd_soc_component_write(component, WM8753_SRATE2, reg | div); break; default: @@ -1049,7 +1050,7 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, static int wm8753_hdac_set_dai_fmt(struct snd_soc_component *component, unsigned int fmt) { - u16 hifi = snd_soc_component_read32(component, WM8753_HIFI) & 0x01e0; + u16 hifi = snd_soc_component_read(component, WM8753_HIFI) & 0x01e0; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -1083,15 +1084,16 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_component *component, { u16 ioctl, hifi; - hifi = snd_soc_component_read32(component, WM8753_HIFI) & 0x013f; - ioctl = snd_soc_component_read32(component, WM8753_IOCTL) & 0x00ae; + hifi = snd_soc_component_read(component, WM8753_HIFI) & 0x013f; + ioctl = snd_soc_component_read(component, WM8753_IOCTL) & 0x00ae; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 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; @@ -1152,8 +1154,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); - u16 srate = snd_soc_component_read32(component, WM8753_SRATE1) & 0x01c0; - u16 hifi = snd_soc_component_read32(component, WM8753_HIFI) & 0x01f3; + u16 srate = snd_soc_component_read(component, WM8753_SRATE1) & 0x01c0; + u16 hifi = snd_soc_component_read(component, WM8753_HIFI) & 0x01f3; int coeff; /* is digital filter coefficient valid ? */ @@ -1190,7 +1192,7 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_component *component, u16 clock; /* set clk source as pcmclk */ - clock = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfffb; + clock = snd_soc_component_read(component, WM8753_CLOCK) & 0xfffb; snd_soc_component_write(component, WM8753_CLOCK, clock); return wm8753_vdac_adc_set_dai_fmt(component, fmt); @@ -1208,7 +1210,7 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_component *component, u16 clock; /* set clk source as pcmclk */ - clock = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfffb; + clock = snd_soc_component_read(component, WM8753_CLOCK) & 0xfffb; snd_soc_component_write(component, WM8753_CLOCK, clock); return wm8753_vdac_adc_set_dai_fmt(component, fmt); @@ -1220,7 +1222,7 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_component *component, u16 clock; /* set clk source as mclk */ - clock = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfffb; + clock = snd_soc_component_read(component, WM8753_CLOCK) & 0xfffb; snd_soc_component_write(component, WM8753_CLOCK, clock | 0x4); if (wm8753_hdac_set_dai_fmt(component, fmt) < 0) @@ -1295,10 +1297,10 @@ static int wm8753_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, return wm8753_voice_write_dai_fmt(component, fmt); }; -static int wm8753_mute(struct snd_soc_dai *dai, int mute) +static int wm8753_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8753_DAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8753_DAC) & 0xfff7; struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); /* the digital mute covers the HiFi and Voice DAC's on the WM8753. @@ -1329,7 +1331,7 @@ static int wm8753_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); - u16 pwr_reg = snd_soc_component_read32(component, WM8753_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_component_read(component, WM8753_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: @@ -1380,20 +1382,22 @@ static int wm8753_set_bias_level(struct snd_soc_component *component, */ static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = { .hw_params = wm8753_i2s_hw_params, - .digital_mute = wm8753_mute, + .mute_stream = wm8753_mute, .set_fmt = wm8753_hifi_set_dai_fmt, .set_clkdiv = wm8753_set_dai_clkdiv, .set_pll = wm8753_set_dai_pll, .set_sysclk = wm8753_set_dai_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = { .hw_params = wm8753_pcm_hw_params, - .digital_mute = wm8753_mute, + .mute_stream = wm8753_mute, .set_fmt = wm8753_voice_set_dai_fmt, .set_clkdiv = wm8753_set_dai_clkdiv, .set_pll = wm8753_set_dai_pll, .set_sysclk = wm8753_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8753_dai[] = { diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index bc8243443b9d..1176a6ad269d 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -447,7 +447,7 @@ static int wm8770_hw_params(struct snd_pcm_substream *substream, } /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_component_read32(component, WM8770_MSTRCTRL) & 0x100) { + if (snd_soc_component_read(component, WM8770_MSTRCTRL) & 0x100) { for (; i < ARRAY_SIZE(mclk_ratios); ++i) { ratio = wm8770->sysclk / params_rate(params); if (ratio == mclk_ratios[i]) @@ -472,7 +472,7 @@ static int wm8770_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8770_mute(struct snd_soc_dai *dai, int mute) +static int wm8770_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component; @@ -538,10 +538,11 @@ static int wm8770_set_bias_level(struct snd_soc_component *component, SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops wm8770_dai_ops = { - .digital_mute = wm8770_mute, + .mute_stream = wm8770_mute, .hw_params = wm8770_hw_params, .set_fmt = wm8770_set_fmt, .set_sysclk = wm8770_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8770_dai = { diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 9143eb1ce2f7..554acf56130c 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -282,7 +282,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, } /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_component_read32(component, WM8776_MSTRCTRL) & master) { + if (snd_soc_component_read(component, WM8776_MSTRCTRL) & master) { for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { if (wm8776->sysclk[dai->driver->id] / params_rate(params) == mclk_ratios[i]) @@ -309,7 +309,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8776_mute(struct snd_soc_dai *dai, int mute) +static int wm8776_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -361,10 +361,11 @@ static int wm8776_set_bias_level(struct snd_soc_component *component, SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops wm8776_dac_ops = { - .digital_mute = wm8776_mute, + .mute_stream = wm8776_mute, .hw_params = wm8776_hw_params, .set_fmt = wm8776_set_fmt, .set_sysclk = wm8776_set_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8776_adc_ops = { diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 09302550c12b..4ddb5e32df5d 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -172,7 +172,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol, if (snd_soc_component_test_bits(component, e->reg, mask, val)) { /* save the current power state of the transmitter */ - txpwr = snd_soc_component_read32(component, WM8804_PWRDN) & 0x4; + txpwr = snd_soc_component_read(component, WM8804_PWRDN) & 0x4; /* power down the transmitter */ snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x4); diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 3e239fa9bc8d..a9a6d766a176 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -222,7 +222,7 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 hpctl1 = snd_soc_component_read32(component, WM8900_REG_HPCTL1); + u16 hpctl1 = snd_soc_component_read(component, WM8900_REG_HPCTL1); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -629,7 +629,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; u16 reg; - reg = snd_soc_component_read32(component, WM8900_REG_AUDIO1) & ~0x60; + reg = snd_soc_component_read(component, WM8900_REG_AUDIO1) & ~0x60; switch (params_width(params)) { case 16: @@ -650,7 +650,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, snd_soc_component_write(component, WM8900_REG_AUDIO1, reg); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - reg = snd_soc_component_read32(component, WM8900_REG_DACCTRL); + reg = snd_soc_component_read(component, WM8900_REG_DACCTRL); if (params_rate(params) <= 24000) reg |= WM8900_REG_DACCTRL_DAC_SB_FILT; @@ -860,10 +860,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; unsigned int clocking1, aif1, aif3, aif4; - clocking1 = snd_soc_component_read32(component, WM8900_REG_CLOCKING1); - aif1 = snd_soc_component_read32(component, WM8900_REG_AUDIO1); - aif3 = snd_soc_component_read32(component, WM8900_REG_AUDIO3); - aif4 = snd_soc_component_read32(component, WM8900_REG_AUDIO4); + clocking1 = snd_soc_component_read(component, WM8900_REG_CLOCKING1); + aif1 = snd_soc_component_read(component, WM8900_REG_AUDIO1); + aif3 = snd_soc_component_read(component, WM8900_REG_AUDIO3); + aif4 = snd_soc_component_read(component, WM8900_REG_AUDIO4); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -967,12 +967,12 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8900_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; u16 reg; - reg = snd_soc_component_read32(component, WM8900_REG_DACCTRL); + reg = snd_soc_component_read(component, WM8900_REG_DACCTRL); if (mute) reg |= WM8900_REG_DACCTRL_MUTE; @@ -997,7 +997,8 @@ static const struct snd_soc_dai_ops wm8900_dai_ops = { .set_clkdiv = wm8900_set_dai_clkdiv, .set_pll = wm8900_set_dai_pll, .set_fmt = wm8900_set_dai_fmt, - .digital_mute = wm8900_digital_mute, + .mute_stream = wm8900_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8900_dai = { @@ -1068,7 +1069,7 @@ static int wm8900_set_bias_level(struct snd_soc_component *component, WM8900_REG_POWER1_BIAS_ENA | 0x1); } - reg = snd_soc_component_read32(component, WM8900_REG_POWER1); + reg = snd_soc_component_read(component, WM8900_REG_POWER1); snd_soc_component_write(component, WM8900_REG_POWER1, (reg & WM8900_REG_POWER1_FLL_ENA) | WM8900_REG_POWER1_BIAS_ENA | 0x1); @@ -1079,7 +1080,7 @@ static int wm8900_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_OFF: /* Startup bias enable */ - reg = snd_soc_component_read32(component, WM8900_REG_POWER1); + reg = snd_soc_component_read(component, WM8900_REG_POWER1); snd_soc_component_write(component, WM8900_REG_POWER1, reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA); snd_soc_component_write(component, WM8900_REG_ADDCTL, @@ -1170,7 +1171,7 @@ static int wm8900_probe(struct snd_soc_component *component) { int reg; - reg = snd_soc_component_read32(component, WM8900_REG_ID); + reg = snd_soc_component_read(component, WM8900_REG_ID); if (reg != 0x8900) { dev_err(component->dev, "Device is not a WM8900 - ID %x\n", reg); return -ENODEV; diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fa2f67850f18..09f4980630c7 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -342,7 +342,7 @@ static void wm8903_seq_notifier(struct snd_soc_component *component, if (!(wm8903->dcs_pending & (1 << i))) continue; - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, WM8903_DC_SERVO_READBACK_1 + i); dev_dbg(component->dev, "DC servo %d: %x\n", 3 - i, val); @@ -375,7 +375,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, u16 reg; int ret; - reg = snd_soc_component_read32(component, WM8903_CLASS_W_0); + reg = snd_soc_component_read(component, WM8903_CLASS_W_0); /* Turn it off if we're about to enable bypass */ if (ucontrol->value.integer.value[0]) { @@ -1224,7 +1224,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 aif1 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_1); + u16 aif1 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_1); aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); @@ -1307,12 +1307,12 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8903_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; u16 reg; - reg = snd_soc_component_read32(component, WM8903_DAC_DIGITAL_1); + reg = snd_soc_component_read(component, WM8903_DAC_DIGITAL_1); if (mute) reg |= WM8903_DAC_MUTE; @@ -1451,12 +1451,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, int cur_val; int clk_sys; - u16 aif1 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_1); - u16 aif2 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_2); - u16 aif3 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_3); - u16 clock0 = snd_soc_component_read32(component, WM8903_CLOCK_RATES_0); - u16 clock1 = snd_soc_component_read32(component, WM8903_CLOCK_RATES_1); - u16 dac_digital1 = snd_soc_component_read32(component, WM8903_DAC_DIGITAL_1); + u16 aif1 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_1); + u16 aif2 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_2); + u16 aif3 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_3); + u16 clock0 = snd_soc_component_read(component, WM8903_CLOCK_RATES_0); + u16 clock1 = snd_soc_component_read(component, WM8903_CLOCK_RATES_1); + u16 dac_digital1 = snd_soc_component_read(component, WM8903_DAC_DIGITAL_1); /* Enable sloping stopband filter for low sample rates */ if (fs <= 24000) @@ -1737,9 +1737,10 @@ static irqreturn_t wm8903_irq(int irq, void *data) static const struct snd_soc_dai_ops wm8903_dai_ops = { .hw_params = wm8903_hw_params, - .digital_mute = wm8903_digital_mute, + .mute_stream = wm8903_mute, .set_fmt = wm8903_set_dai_fmt, .set_sysclk = wm8903_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8903_dai = { @@ -1927,7 +1928,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 5ffbaddd6e49..1c360bae5652 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -317,7 +317,7 @@ static int wm8904_configure_clocking(struct snd_soc_component *component) unsigned int clock0, clock2, rate; /* Gate the clock while we're updating to avoid misclocking */ - clock2 = snd_soc_component_read32(component, WM8904_CLOCK_RATES_2); + clock2 = snd_soc_component_read(component, WM8904_CLOCK_RATES_2); snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2, WM8904_SYSCLK_SRC, 0); @@ -374,7 +374,7 @@ static void wm8904_set_drc(struct snd_soc_component *component) int save, i; /* Save any enables; the configuration should clear them. */ - save = snd_soc_component_read32(component, WM8904_DRC_0); + save = snd_soc_component_read(component, WM8904_DRC_0); for (i = 0; i < WM8904_DRC_REGS; i++) snd_soc_component_update_bits(component, WM8904_DRC_0 + i, 0xffff, @@ -447,7 +447,7 @@ static void wm8904_set_retune_mobile(struct snd_soc_component *component) /* The EQ will be disabled while reconfiguring it, remember the * current configuration. */ - save = snd_soc_component_read32(component, WM8904_EQ1); + save = snd_soc_component_read(component, WM8904_EQ1); for (i = 0; i < WM8904_EQ_REGS; i++) snd_soc_component_update_bits(component, WM8904_EQ1 + i, 0xffff, @@ -776,7 +776,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, /* Wait for DC servo to complete */ dcs_mask <<= WM8904_DCS_CAL_COMPLETE_SHIFT; do { - val = snd_soc_component_read32(component, WM8904_DC_SERVO_READBACK_0); + val = snd_soc_component_read(component, WM8904_DC_SERVO_READBACK_0); if ((val & dcs_mask) == dcs_mask) break; @@ -814,8 +814,8 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: /* Cache the DC servo configuration; this will be * invalidated if we change the configuration. */ - wm8904->dcs_state[dcs_l] = snd_soc_component_read32(component, dcs_l_reg); - wm8904->dcs_state[dcs_r] = snd_soc_component_read32(component, dcs_r_reg); + wm8904->dcs_state[dcs_l] = snd_soc_component_read(component, dcs_l_reg); + wm8904->dcs_state[dcs_r] = snd_soc_component_read(component, dcs_r_reg); snd_soc_component_update_bits(component, WM8904_DC_SERVO_0, dcs_mask, 0); @@ -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; @@ -1671,7 +1671,7 @@ static int wm8904_set_fll(struct snd_soc_dai *dai, int fll_id, int source, Fout == wm8904->fll_fout) return 0; - clock2 = snd_soc_component_read32(component, WM8904_CLOCK_RATES_2); + clock2 = snd_soc_component_read(component, WM8904_CLOCK_RATES_2); if (Fout == 0) { dev_dbg(component->dev, "FLL disabled\n"); @@ -1716,7 +1716,7 @@ static int wm8904_set_fll(struct snd_soc_dai *dai, int fll_id, int source, /* Save current state then disable the FLL and SYSCLK to avoid * misclocking */ - fll1 = snd_soc_component_read32(component, WM8904_FLL_CONTROL_1); + fll1 = snd_soc_component_read(component, WM8904_FLL_CONTROL_1); snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2, WM8904_CLK_SYS_ENA, 0); snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1, @@ -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; @@ -1846,7 +1846,7 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } -static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8904_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; int val; @@ -1962,7 +1962,8 @@ static const struct snd_soc_dai_ops wm8904_dai_ops = { .set_tdm_slot = wm8904_set_tdm_slot, .set_pll = wm8904_set_fll, .hw_params = wm8904_hw_params, - .digital_mute = wm8904_digital_mute, + .mute_stream = wm8904_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8904_dai = { diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index c194fbde8ad6..016cd8aeef37 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -337,8 +337,8 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8940_IFACE) & 0xFE67; - u16 clk = snd_soc_component_read32(component, WM8940_CLOCK) & 0x1fe; + u16 iface = snd_soc_component_read(component, WM8940_IFACE) & 0xFE67; + u16 clk = snd_soc_component_read(component, WM8940_CLOCK) & 0x1fe; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: @@ -392,9 +392,9 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 iface = snd_soc_component_read32(component, WM8940_IFACE) & 0xFD9F; - u16 addcntrl = snd_soc_component_read32(component, WM8940_ADDCNTRL) & 0xFFF1; - u16 companding = snd_soc_component_read32(component, + u16 iface = snd_soc_component_read(component, WM8940_IFACE) & 0xFD9F; + u16 addcntrl = snd_soc_component_read(component, WM8940_ADDCNTRL) & 0xFFF1; + u16 companding = snd_soc_component_read(component, WM8940_COMPANDINGCTL) & 0xFFDF; int ret; @@ -452,10 +452,10 @@ error_ret: return ret; } -static int wm8940_mute(struct snd_soc_dai *dai, int mute) +static int wm8940_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8940_DAC) & 0xffbf; + u16 mute_reg = snd_soc_component_read(component, WM8940_DAC) & 0xffbf; if (mute) mute_reg |= 0x40; @@ -468,7 +468,7 @@ static int wm8940_set_bias_level(struct snd_soc_component *component, { struct wm8940_priv *wm8940 = snd_soc_component_get_drvdata(component); u16 val; - u16 pwr_reg = snd_soc_component_read32(component, WM8940_POWER1) & 0x1F0; + u16 pwr_reg = snd_soc_component_read(component, WM8940_POWER1) & 0x1F0; int ret = 0; switch (level) { @@ -476,7 +476,7 @@ static int wm8940_set_bias_level(struct snd_soc_component *component, /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* Enable thermal shutdown */ - val = snd_soc_component_read32(component, WM8940_OUTPUTCTL); + val = snd_soc_component_read(component, WM8940_OUTPUTCTL); ret = snd_soc_component_write(component, WM8940_OUTPUTCTL, val | 0x2); if (ret) break; @@ -577,12 +577,12 @@ static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, u16 reg; /* Turn off PLL */ - reg = snd_soc_component_read32(component, WM8940_POWER1); + reg = snd_soc_component_read(component, WM8940_POWER1); snd_soc_component_write(component, WM8940_POWER1, reg & 0x1df); if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_component_read32(component, WM8940_CLOCK); + reg = snd_soc_component_read(component, WM8940_CLOCK); snd_soc_component_write(component, WM8940_CLOCK, reg & 0x0ff); /* Pll power down */ snd_soc_component_write(component, WM8940_PLLN, (1 << 7)); @@ -601,11 +601,11 @@ static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff); snd_soc_component_write(component, WM8940_PLLK3, pll_div.k & 0x1ff); /* Enable the PLL */ - reg = snd_soc_component_read32(component, WM8940_POWER1); + reg = snd_soc_component_read(component, WM8940_POWER1); snd_soc_component_write(component, WM8940_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_component_read32(component, WM8940_CLOCK); + reg = snd_soc_component_read(component, WM8940_CLOCK); snd_soc_component_write(component, WM8940_CLOCK, reg | 0x100); return 0; @@ -638,15 +638,15 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8940_BCLKDIV: - reg = snd_soc_component_read32(component, WM8940_CLOCK) & 0xFFE3; + reg = snd_soc_component_read(component, WM8940_CLOCK) & 0xFFE3; ret = snd_soc_component_write(component, WM8940_CLOCK, reg | (div << 2)); break; case WM8940_MCLKDIV: - reg = snd_soc_component_read32(component, WM8940_CLOCK) & 0xFF1F; + reg = snd_soc_component_read(component, WM8940_CLOCK) & 0xFF1F; ret = snd_soc_component_write(component, WM8940_CLOCK, reg | (div << 5)); break; case WM8940_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8940_GPIO) & 0xFFCF; + reg = snd_soc_component_read(component, WM8940_GPIO) & 0xFFCF; ret = snd_soc_component_write(component, WM8940_GPIO, reg | (div << 4)); break; } @@ -664,10 +664,11 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, static const struct snd_soc_dai_ops wm8940_dai_ops = { .hw_params = wm8940_i2s_hw_params, .set_sysclk = wm8940_set_dai_sysclk, - .digital_mute = wm8940_mute, + .mute_stream = wm8940_mute, .set_fmt = wm8940_set_dai_fmt, .set_clkdiv = wm8940_set_dai_clkdiv, .set_pll = wm8940_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8940_dai = { @@ -711,7 +712,7 @@ static int wm8940_probe(struct snd_soc_component *component) if (!pdata) dev_warn(component->dev, "No platform data supplied\n"); else { - reg = snd_soc_component_read32(component, WM8940_OUTPUTCTL); + reg = snd_soc_component_read(component, WM8940_OUTPUTCTL); ret = snd_soc_component_write(component, WM8940_OUTPUTCTL, reg | pdata->vroi); if (ret < 0) return ret; diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 9c7e2892c8cb..513df47bd87d 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -619,7 +619,7 @@ static int wm8955_hw_params(struct snd_pcm_substream *substream, /* If the chip is clocked then disable the clocks and force a * reconfiguration, otherwise DAPM will power up the * clocks for us later. */ - ret = snd_soc_component_read32(component, WM8955_POWER_MANAGEMENT_1); + ret = snd_soc_component_read(component, WM8955_POWER_MANAGEMENT_1); if (ret < 0) return ret; if (ret & WM8955_DIGENB) { @@ -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; @@ -745,7 +745,7 @@ static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } -static int wm8955_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8955_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; int val; @@ -848,7 +848,8 @@ static const struct snd_soc_dai_ops wm8955_dai_ops = { .set_sysclk = wm8955_set_sysclk, .set_fmt = wm8955_set_fmt, .hw_params = wm8955_hw_params, - .digital_mute = wm8955_digital_mute, + .mute_stream = wm8955_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8955_dai = { diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index ca42445b649d..68a3b48e6b31 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -192,7 +192,7 @@ static void wm8958_dsp_start_mbc(struct snd_soc_component *component, int path) int i; /* If the DSP is already running then noop */ - if (snd_soc_component_read32(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA) + if (snd_soc_component_read(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA) return; /* If we have MBC firmware download it */ @@ -324,7 +324,7 @@ static void wm8958_dsp_start_enh_eq(struct snd_soc_component *component, int pat static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int start) { struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); - int pwr_reg = snd_soc_component_read32(component, WM8994_POWER_MANAGEMENT_5); + int pwr_reg = snd_soc_component_read(component, WM8994_POWER_MANAGEMENT_5); int ena, reg, aif; switch (path) { @@ -352,7 +352,7 @@ static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int if (!pwr_reg) ena = 0; - reg = snd_soc_component_read32(component, WM8958_DSP2_PROGRAM); + reg = snd_soc_component_read(component, WM8958_DSP2_PROGRAM); dev_dbg(component->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n", path, wm8994->dsp_active, start, pwr_reg, reg); @@ -363,9 +363,9 @@ static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int return; /* If either AIFnCLK is not yet enabled postpone */ - if (!(snd_soc_component_read32(component, WM8994_AIF1_CLOCKING_1) + if (!(snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1) & WM8994_AIF1CLK_ENA_MASK) && - !(snd_soc_component_read32(component, WM8994_AIF2_CLOCKING_1) + !(snd_soc_component_read(component, WM8994_AIF2_CLOCKING_1) & WM8994_AIF2CLK_ENA_MASK)) return; @@ -456,7 +456,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; @@ -546,7 +546,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; @@ -579,7 +579,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; @@ -746,7 +746,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 6cf0f6612bda..660ec46eecf2 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -612,7 +612,7 @@ static const int bclk_divs[] = { * triplet, we relax the bclk such that bclk is chosen as the * closest available frequency greater than expected bclk. * - * @wm8960_priv: wm8960 codec private data + * @wm8960: codec private data * @mclk: MCLK used to derive sysclk * @sysclk_idx: sysclk_divs index for found sysclk * @dac_idx: dac_divs index for found lrclk @@ -742,7 +742,7 @@ static int wm8960_configure_clocking(struct snd_soc_component *component) { struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); int freq_out, freq_in; - u16 iface1 = snd_soc_component_read32(component, WM8960_IFACE1); + u16 iface1 = snd_soc_component_read(component, WM8960_IFACE1); int i, j, k; int ret; @@ -812,7 +812,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8960_IFACE1) & 0xfff3; + u16 iface = snd_soc_component_read(component, WM8960_IFACE1) & 0xfff3; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int i; @@ -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)); @@ -878,7 +878,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream, return 0; } -static int wm8960_mute(struct snd_soc_dai *dai, int mute) +static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -893,7 +893,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); - u16 pm2 = snd_soc_component_read32(component, WM8960_POWER2); + u16 pm2 = snd_soc_component_read(component, WM8960_POWER2); int ret; switch (level) { @@ -983,7 +983,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); - u16 pm2 = snd_soc_component_read32(component, WM8960_POWER2); + u16 pm2 = snd_soc_component_read(component, WM8960_POWER2); int reg, ret; switch (level) { @@ -1202,7 +1202,7 @@ static int wm8960_set_pll(struct snd_soc_component *component, if (!freq_in || !freq_out) return 0; - reg = snd_soc_component_read32(component, WM8960_PLL1) & ~0x3f; + reg = snd_soc_component_read(component, WM8960_PLL1) & ~0x3f; reg |= pll_div.pre_div << 4; reg |= pll_div.n; @@ -1245,23 +1245,23 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8960_SYSCLKDIV: - reg = snd_soc_component_read32(component, WM8960_CLOCK1) & 0x1f9; + reg = snd_soc_component_read(component, WM8960_CLOCK1) & 0x1f9; snd_soc_component_write(component, WM8960_CLOCK1, reg | div); break; case WM8960_DACDIV: - reg = snd_soc_component_read32(component, WM8960_CLOCK1) & 0x1c7; + reg = snd_soc_component_read(component, WM8960_CLOCK1) & 0x1c7; snd_soc_component_write(component, WM8960_CLOCK1, reg | div); break; case WM8960_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8960_PLL1) & 0x03f; + reg = snd_soc_component_read(component, WM8960_PLL1) & 0x03f; snd_soc_component_write(component, WM8960_PLL1, reg | div); break; case WM8960_DCLKDIV: - reg = snd_soc_component_read32(component, WM8960_CLOCK2) & 0x03f; + reg = snd_soc_component_read(component, WM8960_CLOCK2) & 0x03f; snd_soc_component_write(component, WM8960_CLOCK2, reg | div); break; case WM8960_TOCLKSEL: - reg = snd_soc_component_read32(component, WM8960_ADDCTL1) & 0x1fd; + reg = snd_soc_component_read(component, WM8960_ADDCTL1) & 0x1fd; snd_soc_component_write(component, WM8960_ADDCTL1, reg | div); break; default: @@ -1315,11 +1315,12 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, static const struct snd_soc_dai_ops wm8960_dai_ops = { .hw_params = wm8960_hw_params, .hw_free = wm8960_hw_free, - .digital_mute = wm8960_mute, + .mute_stream = wm8960_mute, .set_fmt = wm8960_set_dai_fmt, .set_clkdiv = wm8960_set_dai_clkdiv, .set_pll = wm8960_set_dai_pll, .set_sysclk = wm8960_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8960_dai = { @@ -1389,6 +1390,12 @@ static void wm8960_set_pdata_from_of(struct i2c_client *i2c, if (of_property_read_bool(np, "wlf,shared-lrclk")) pdata->shared_lrclk = true; + + of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_cfg, + ARRAY_SIZE(pdata->gpio_cfg)); + + of_property_read_u32_array(np, "wlf,hp-cfg", pdata->hp_cfg, + ARRAY_SIZE(pdata->hp_cfg)); } static int wm8960_i2c_probe(struct i2c_client *i2c, @@ -1446,6 +1453,20 @@ static int wm8960_i2c_probe(struct i2c_client *i2c, regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100); regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100); + /* ADCLRC pin configured as GPIO. */ + regmap_update_bits(wm8960->regmap, WM8960_IFACE2, 1 << 6, + wm8960->pdata.gpio_cfg[0] << 6); + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 0xF << 4, + wm8960->pdata.gpio_cfg[1] << 4); + + /* Enable headphone jack detect */ + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 3 << 2, + wm8960->pdata.hp_cfg[0] << 2); + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, 3 << 5, + wm8960->pdata.hp_cfg[1] << 5); + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL1, 3, + wm8960->pdata.hp_cfg[2]); + i2c_set_clientdata(i2c, wm8960); ret = devm_snd_soc_register_component(&i2c->dev, diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 72504f3b702d..ef80d9fc1eec 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -192,10 +192,10 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 hp_reg = snd_soc_component_read32(component, WM8961_ANALOGUE_HP_0); - u16 cp_reg = snd_soc_component_read32(component, WM8961_CHARGE_PUMP_1); - u16 pwr_reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_2); - u16 dcs_reg = snd_soc_component_read32(component, WM8961_DC_SERVO_1); + u16 hp_reg = snd_soc_component_read(component, WM8961_ANALOGUE_HP_0); + u16 cp_reg = snd_soc_component_read(component, WM8961_CHARGE_PUMP_1); + u16 pwr_reg = snd_soc_component_read(component, WM8961_PWR_MGMT_2); + u16 dcs_reg = snd_soc_component_read(component, WM8961_DC_SERVO_1); int timeout = 500; if (event & SND_SOC_DAPM_POST_PMU) { @@ -229,7 +229,7 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w, snd_soc_component_write(component, WM8961_DC_SERVO_1, dcs_reg); do { msleep(1); - dcs_reg = snd_soc_component_read32(component, WM8961_DC_SERVO_1); + dcs_reg = snd_soc_component_read(component, WM8961_DC_SERVO_1); } while (--timeout && dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | WM8961_DCS_TRIG_STARTUP_HPL)); @@ -284,8 +284,8 @@ static int wm8961_spk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 pwr_reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_2); - u16 spk_reg = snd_soc_component_read32(component, WM8961_CLASS_D_CONTROL_1); + u16 pwr_reg = snd_soc_component_read(component, WM8961_PWR_MGMT_2); + u16 spk_reg = snd_soc_component_read(component, WM8961_CLASS_D_CONTROL_1); if (event & SND_SOC_DAPM_POST_PMU) { /* Enable the PGA */ @@ -521,7 +521,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, abs(wm8961_srate[best].rate - fs)) best = i; } - reg = snd_soc_component_read32(component, WM8961_ADDITIONAL_CONTROL_3); + reg = snd_soc_component_read(component, WM8961_ADDITIONAL_CONTROL_3); reg &= ~WM8961_SAMPLE_RATE_MASK; reg |= wm8961_srate[best].val; snd_soc_component_write(component, WM8961_ADDITIONAL_CONTROL_3, reg); @@ -554,12 +554,12 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs, wm8961->sysclk / fs); - reg = snd_soc_component_read32(component, WM8961_CLOCKING_4); + reg = snd_soc_component_read(component, WM8961_CLOCKING_4); reg &= ~WM8961_CLK_SYS_RATE_MASK; reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT; snd_soc_component_write(component, WM8961_CLOCKING_4, reg); - reg = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_0); + reg = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_0); reg &= ~WM8961_WL_MASK; switch (params_width(params)) { case 16: @@ -579,7 +579,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, snd_soc_component_write(component, WM8961_AUDIO_INTERFACE_0, reg); /* Sloping stop-band filter is recommended for <= 24kHz */ - reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_2); + reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_2); if (fs <= 24000) reg |= WM8961_DACSLOPE; else @@ -595,7 +595,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, { struct snd_soc_component *component = dai->component; struct wm8961_priv *wm8961 = snd_soc_component_get_drvdata(component); - u16 reg = snd_soc_component_read32(component, WM8961_CLOCKING1); + u16 reg = snd_soc_component_read(component, WM8961_CLOCKING1); if (freq > 33000000) { dev_err(component->dev, "MCLK must be <33MHz\n"); @@ -621,7 +621,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_component *component = dai->component; - u16 aif = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_0); + u16 aif = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_0); aif &= ~(WM8961_BCLKINV | WM8961_LRP | WM8961_MS | WM8961_FORMAT_MASK); @@ -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) { @@ -688,7 +688,7 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) { struct snd_soc_component *component = dai->component; - u16 reg = snd_soc_component_read32(component, WM8961_ADDITIONAL_CONTROL_2); + u16 reg = snd_soc_component_read(component, WM8961_ADDITIONAL_CONTROL_2); if (tristate) reg |= WM8961_TRIS; @@ -698,10 +698,10 @@ static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) return snd_soc_component_write(component, WM8961_ADDITIONAL_CONTROL_2, reg); } -static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute) +static int wm8961_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_1); + u16 reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_1); if (mute) reg |= WM8961_DACMU; @@ -720,14 +720,14 @@ static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) switch (div_id) { case WM8961_BCLK: - reg = snd_soc_component_read32(component, WM8961_CLOCKING2); + reg = snd_soc_component_read(component, WM8961_CLOCKING2); reg &= ~WM8961_BCLKDIV_MASK; reg |= div; snd_soc_component_write(component, WM8961_CLOCKING2, reg); break; case WM8961_LRCLK: - reg = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_2); + reg = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_2); reg &= ~WM8961_LRCLK_RATE_MASK; reg |= div; snd_soc_component_write(component, WM8961_AUDIO_INTERFACE_2, reg); @@ -757,12 +757,12 @@ static int wm8961_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_PREPARE: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY) { /* Enable bias generation */ - reg = snd_soc_component_read32(component, WM8961_ANTI_POP); + reg = snd_soc_component_read(component, WM8961_ANTI_POP); reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; snd_soc_component_write(component, WM8961_ANTI_POP, reg); /* VMID=2*50k, VREF */ - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); reg &= ~WM8961_VMIDSEL_MASK; reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF; snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); @@ -772,17 +772,17 @@ static int wm8961_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE) { /* VREF off */ - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); reg &= ~WM8961_VREF; snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); /* Bias generation off */ - reg = snd_soc_component_read32(component, WM8961_ANTI_POP); + reg = snd_soc_component_read(component, WM8961_ANTI_POP); reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN); snd_soc_component_write(component, WM8961_ANTI_POP, reg); /* VMID off */ - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); reg &= ~WM8961_VMIDSEL_MASK; snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); } @@ -806,9 +806,10 @@ static const struct snd_soc_dai_ops wm8961_dai_ops = { .hw_params = wm8961_hw_params, .set_sysclk = wm8961_set_sysclk, .set_fmt = wm8961_set_fmt, - .digital_mute = wm8961_digital_mute, + .mute_stream = wm8961_mute, .set_tristate = wm8961_set_tristate, .set_clkdiv = wm8961_set_clkdiv, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8961_dai = { @@ -833,35 +834,35 @@ static int wm8961_probe(struct snd_soc_component *component) u16 reg; /* Enable class W */ - reg = snd_soc_component_read32(component, WM8961_CHARGE_PUMP_B); + reg = snd_soc_component_read(component, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; snd_soc_component_write(component, WM8961_CHARGE_PUMP_B, reg); /* Latch volume update bits (right channel only, we always * write both out) and default ZC on. */ - reg = snd_soc_component_read32(component, WM8961_ROUT1_VOLUME); + reg = snd_soc_component_read(component, WM8961_ROUT1_VOLUME); snd_soc_component_write(component, WM8961_ROUT1_VOLUME, reg | WM8961_LO1ZC | WM8961_OUT1VU); snd_soc_component_write(component, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); - reg = snd_soc_component_read32(component, WM8961_ROUT2_VOLUME); + reg = snd_soc_component_read(component, WM8961_ROUT2_VOLUME); snd_soc_component_write(component, WM8961_ROUT2_VOLUME, reg | WM8961_SPKRZC | WM8961_SPKVU); snd_soc_component_write(component, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); - reg = snd_soc_component_read32(component, WM8961_RIGHT_ADC_VOLUME); + reg = snd_soc_component_read(component, WM8961_RIGHT_ADC_VOLUME); snd_soc_component_write(component, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); - reg = snd_soc_component_read32(component, WM8961_RIGHT_INPUT_VOLUME); + reg = snd_soc_component_read(component, WM8961_RIGHT_INPUT_VOLUME); snd_soc_component_write(component, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); /* Use soft mute by default */ - reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_2); + reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_2); reg |= WM8961_DACSMM; snd_soc_component_write(component, WM8961_ADC_DAC_CONTROL_2, reg); /* Use automatic clocking mode by default; for now this is all * we support. */ - reg = snd_soc_component_read32(component, WM8961_CLOCKING_3); + reg = snd_soc_component_read(component, WM8961_CLOCKING_3); reg &= ~WM8961_MANUAL_MODE; snd_soc_component_write(component, WM8961_CLOCKING_3, reg); diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1cc23a05ffe4..317916cb4e27 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -151,6 +151,7 @@ static const struct reg_default wm8962_reg[] = { { 40, 0x0000 }, /* R40 - SPKOUTL volume */ { 41, 0x0000 }, /* R41 - SPKOUTR volume */ + { 48, 0x0000 }, /* R48 - Additional control(4) */ { 49, 0x0010 }, /* R49 - Class D Control 1 */ { 51, 0x0003 }, /* R51 - Class D Control 2 */ @@ -841,7 +842,6 @@ static bool wm8962_readable_register(struct device *dev, unsigned int reg) case WM8962_SPKOUTL_VOLUME: case WM8962_SPKOUTR_VOLUME: case WM8962_THERMAL_SHUTDOWN_STATUS: - case WM8962_ADDITIONAL_CONTROL_4: case WM8962_CLASS_D_CONTROL_1: case WM8962_CLASS_D_CONTROL_2: case WM8962_CLOCKING_4: @@ -956,7 +956,6 @@ static bool wm8962_readable_register(struct device *dev, unsigned int reg) case WM8962_EQ39: case WM8962_EQ40: case WM8962_EQ41: - case WM8962_GPIO_BASE: case WM8962_GPIO_2: case WM8962_GPIO_3: case WM8962_GPIO_5: @@ -1480,9 +1479,9 @@ static int wm8962_dsp2_write_config(struct snd_soc_component *component) static int wm8962_dsp2_set_enable(struct snd_soc_component *component, u16 val) { - u16 adcl = snd_soc_component_read32(component, WM8962_LEFT_ADC_VOLUME); - u16 adcr = snd_soc_component_read32(component, WM8962_RIGHT_ADC_VOLUME); - u16 dac = snd_soc_component_read32(component, WM8962_ADC_DAC_CONTROL_1); + u16 adcl = snd_soc_component_read(component, WM8962_LEFT_ADC_VOLUME); + u16 adcr = snd_soc_component_read(component, WM8962_RIGHT_ADC_VOLUME); + u16 dac = snd_soc_component_read(component, WM8962_ADC_DAC_CONTROL_1); /* Mute the ADCs and DACs */ snd_soc_component_write(component, WM8962_LEFT_ADC_VOLUME, 0); @@ -1561,7 +1560,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component); int old = wm8962->dsp2_ena; int ret = 0; - int dsp2_running = snd_soc_component_read32(component, WM8962_DSP2_POWER_MANAGEMENT) & + int dsp2_running = snd_soc_component_read(component, WM8962_DSP2_POWER_MANAGEMENT) & WM8962_DSP2_ENA; mutex_lock(&wm8962->dsp2_ena_lock); @@ -1604,17 +1603,17 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - ret = snd_soc_component_read32(component, WM8962_PWR_MGMT_2); + ret = snd_soc_component_read(component, WM8962_PWR_MGMT_2); if (ret & WM8962_HPOUTL_PGA_ENA) { snd_soc_component_write(component, WM8962_HPOUTL_VOLUME, - snd_soc_component_read32(component, WM8962_HPOUTL_VOLUME)); + snd_soc_component_read(component, WM8962_HPOUTL_VOLUME)); return 1; } /* ...otherwise the right. The VU is stereo. */ if (ret & WM8962_HPOUTR_PGA_ENA) snd_soc_component_write(component, WM8962_HPOUTR_VOLUME, - snd_soc_component_read32(component, WM8962_HPOUTR_VOLUME)); + snd_soc_component_read(component, WM8962_HPOUTR_VOLUME)); return 1; } @@ -1634,17 +1633,17 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - ret = snd_soc_component_read32(component, WM8962_PWR_MGMT_2); + ret = snd_soc_component_read(component, WM8962_PWR_MGMT_2); if (ret & WM8962_SPKOUTL_PGA_ENA) { snd_soc_component_write(component, WM8962_SPKOUTL_VOLUME, - snd_soc_component_read32(component, WM8962_SPKOUTL_VOLUME)); + snd_soc_component_read(component, WM8962_SPKOUTL_VOLUME)); return 1; } /* ...otherwise the right. The VU is stereo. */ if (ret & WM8962_SPKOUTR_PGA_ENA) snd_soc_component_write(component, WM8962_SPKOUTR_VOLUME, - snd_soc_component_read32(component, WM8962_SPKOUTR_VOLUME)); + snd_soc_component_read(component, WM8962_SPKOUTR_VOLUME)); return 1; } @@ -1888,7 +1887,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, timeout = 0; do { msleep(1); - reg = snd_soc_component_read32(component, WM8962_DC_SERVO_6); + reg = snd_soc_component_read(component, WM8962_DC_SERVO_6); if (reg < 0) { dev_err(component->dev, "Failed to read DCS status: %d\n", @@ -1975,7 +1974,8 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - return snd_soc_component_write(component, reg, snd_soc_component_read32(component, reg)); + return snd_soc_component_write(component, reg, + snd_soc_component_read(component, reg)); default: WARN(1, "Invalid event %d\n", event); return -EINVAL; @@ -2442,7 +2442,7 @@ static void wm8962_configure_bclk(struct snd_soc_component *component) snd_soc_component_update_bits(component, WM8962_CLOCKING2, WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); - dspclk = snd_soc_component_read32(component, WM8962_CLOCKING1); + dspclk = snd_soc_component_read(component, WM8962_CLOCKING1); if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON) snd_soc_component_update_bits(component, WM8962_CLOCKING2, @@ -2644,7 +2644,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; @@ -2917,7 +2917,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s return 0; } -static int wm8962_mute(struct snd_soc_dai *dai, int mute) +static int wm8962_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int val, ret; @@ -2950,7 +2950,8 @@ static const struct snd_soc_dai_ops wm8962_dai_ops = { .hw_params = wm8962_hw_params, .set_sysclk = wm8962_set_dai_sysclk, .set_fmt = wm8962_set_dai_fmt, - .digital_mute = wm8962_mute, + .mute_stream = wm8962_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8962_dai = { @@ -2983,7 +2984,7 @@ static void wm8962_mic_work(struct work_struct *work) int irq_pol = 0; int reg; - reg = snd_soc_component_read32(component, WM8962_ADDITIONAL_CONTROL_4); + reg = snd_soc_component_read(component, WM8962_ADDITIONAL_CONTROL_4); if (reg & WM8962_MICDET_STS) { status |= SND_JACK_MICROPHONE; @@ -3436,8 +3437,14 @@ static int wm8962_probe(struct snd_soc_component *component) /* Save boards having to disable DMIC when not in use */ dmicclk = false; dmicdat = false; - for (i = 0; i < WM8962_MAX_GPIO; i++) { - switch (snd_soc_component_read32(component, WM8962_GPIO_BASE + i) + for (i = 1; i < WM8962_MAX_GPIO; i++) { + /* + * Register 515 (WM8962_GPIO_BASE + 3) does not exist, + * so skip its access + */ + if (i == 3) + continue; + switch (snd_soc_component_read(component, WM8962_GPIO_BASE + i) & WM8962_GP2_FN_MASK) { case WM8962_GPIO_FN_DMICCLK: dmicclk = true; diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 5266eabd9650..21ae55c32a6d 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -508,8 +508,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8971_priv *wm8971 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8971_IFACE) & 0x1f3; - u16 srate = snd_soc_component_read32(component, WM8971_SRATE) & 0x1c0; + u16 iface = snd_soc_component_read(component, WM8971_IFACE) & 0x1f3; + u16 srate = snd_soc_component_read(component, WM8971_SRATE) & 0x1c0; int coeff = get_coeff(wm8971->sysclk, params_rate(params)); /* bit size */ @@ -536,10 +536,10 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8971_mute(struct snd_soc_dai *dai, int mute) +static int wm8971_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8971_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8971_ADCDAC) & 0xfff7; if (mute) snd_soc_component_write(component, WM8971_ADCDAC, mute_reg | 0x8); @@ -561,7 +561,7 @@ static int wm8971_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8971_priv *wm8971 = snd_soc_component_get_drvdata(component); - u16 pwr_reg = snd_soc_component_read32(component, WM8971_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_component_read(component, WM8971_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: @@ -602,9 +602,10 @@ static int wm8971_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8971_dai_ops = { .hw_params = wm8971_pcm_hw_params, - .digital_mute = wm8971_mute, + .mute_stream = wm8971_mute, .set_fmt = wm8971_set_dai_fmt, .set_sysclk = wm8971_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8971_dai = { diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 7cfc89602fc3..c86231dfcf4f 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -318,11 +318,11 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_component_read32(component, WM8974_CLOCK); + reg = snd_soc_component_read(component, WM8974_CLOCK); snd_soc_component_write(component, WM8974_CLOCK, reg & 0x0ff); /* Turn off PLL */ - reg = snd_soc_component_read32(component, WM8974_POWER1); + reg = snd_soc_component_read(component, WM8974_POWER1); snd_soc_component_write(component, WM8974_POWER1, reg & 0x1df); return 0; } @@ -333,11 +333,11 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8974_PLLK1, pll_div.k >> 18); snd_soc_component_write(component, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff); snd_soc_component_write(component, WM8974_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_component_read32(component, WM8974_POWER1); + reg = snd_soc_component_read(component, WM8974_POWER1); snd_soc_component_write(component, WM8974_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_component_read32(component, WM8974_CLOCK); + reg = snd_soc_component_read(component, WM8974_CLOCK); snd_soc_component_write(component, WM8974_CLOCK, reg | 0x100); return 0; @@ -354,15 +354,15 @@ static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8974_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8974_GPIO) & 0x1cf; + reg = snd_soc_component_read(component, WM8974_GPIO) & 0x1cf; snd_soc_component_write(component, WM8974_GPIO, reg | div); break; case WM8974_MCLKDIV: - reg = snd_soc_component_read32(component, WM8974_CLOCK) & 0x11f; + reg = snd_soc_component_read(component, WM8974_CLOCK) & 0x11f; snd_soc_component_write(component, WM8974_CLOCK, reg | div); break; case WM8974_BCLKDIV: - reg = snd_soc_component_read32(component, WM8974_CLOCK) & 0x1e3; + reg = snd_soc_component_read(component, WM8974_CLOCK) & 0x1e3; snd_soc_component_write(component, WM8974_CLOCK, reg | div); break; default: @@ -450,7 +450,7 @@ static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_component *component = codec_dai->component; u16 iface = 0; - u16 clk = snd_soc_component_read32(component, WM8974_CLOCK) & 0x1fe; + u16 clk = snd_soc_component_read(component, WM8974_CLOCK) & 0x1fe; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -512,8 +512,8 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8974_priv *priv = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8974_IFACE) & 0x19f; - u16 adn = snd_soc_component_read32(component, WM8974_ADD) & 0x1f1; + u16 iface = snd_soc_component_read(component, WM8974_IFACE) & 0x19f; + u16 adn = snd_soc_component_read(component, WM8974_ADD) & 0x1f1; int err; priv->fs = params_rate(params); @@ -563,10 +563,10 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8974_mute(struct snd_soc_dai *dai, int mute) +static int wm8974_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8974_DAC) & 0xffbf; + u16 mute_reg = snd_soc_component_read(component, WM8974_DAC) & 0xffbf; if (mute) snd_soc_component_write(component, WM8974_DAC, mute_reg | 0x40); @@ -579,7 +579,7 @@ static int wm8974_mute(struct snd_soc_dai *dai, int mute) static int wm8974_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 power1 = snd_soc_component_read32(component, WM8974_POWER1) & ~0x3; + u16 power1 = snd_soc_component_read(component, WM8974_POWER1) & ~0x3; switch (level) { case SND_SOC_BIAS_ON: @@ -620,11 +620,12 @@ static int wm8974_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8974_ops = { .hw_params = wm8974_pcm_hw_params, - .digital_mute = wm8974_mute, + .mute_stream = wm8974_mute, .set_fmt = wm8974_set_dai_fmt, .set_clkdiv = wm8974_set_dai_clkdiv, .set_pll = wm8974_set_dai_pll, .set_sysclk = wm8974_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8974_dai = { diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index af35ae101367..a7acb8981715 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -653,8 +653,8 @@ static int wm8978_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) * BCLK polarity mask = 0x100, LRC clock polarity mask = 0x80, * Data Format mask = 0x18: all will be calculated anew */ - u16 iface = snd_soc_component_read32(component, WM8978_AUDIO_INTERFACE) & ~0x198; - u16 clk = snd_soc_component_read32(component, WM8978_CLOCKING); + u16 iface = snd_soc_component_read(component, WM8978_AUDIO_INTERFACE) & ~0x198; + u16 clk = snd_soc_component_read(component, WM8978_CLOCKING); dev_dbg(component->dev, "%s\n", __func__); @@ -720,10 +720,10 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component); /* Word length mask = 0x60 */ - u16 iface_ctl = snd_soc_component_read32(component, WM8978_AUDIO_INTERFACE) & ~0x60; + u16 iface_ctl = snd_soc_component_read(component, WM8978_AUDIO_INTERFACE) & ~0x60; /* Sampling rate mask = 0xe (for filters) */ - u16 add_ctl = snd_soc_component_read32(component, WM8978_ADDITIONAL_CONTROL) & ~0xe; - u16 clking = snd_soc_component_read32(component, WM8978_CLOCKING); + u16 add_ctl = snd_soc_component_read(component, WM8978_ADDITIONAL_CONTROL) & ~0xe; + u16 clking = snd_soc_component_read(component, WM8978_CLOCKING); enum wm8978_sysclk_src current_clk_id = clking & 0x100 ? WM8978_PLL : WM8978_MCLK; unsigned int f_sel, diff, diff_best = INT_MAX; @@ -836,7 +836,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8978_mute(struct snd_soc_dai *dai, int mute) +static int wm8978_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -853,7 +853,7 @@ static int wm8978_mute(struct snd_soc_dai *dai, int mute) static int wm8978_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 power1 = snd_soc_component_read32(component, WM8978_POWER_MANAGEMENT_1) & ~3; + u16 power1 = snd_soc_component_read(component, WM8978_POWER_MANAGEMENT_1) & ~3; switch (level) { case SND_SOC_BIAS_ON: @@ -893,10 +893,11 @@ static int wm8978_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8978_dai_ops = { .hw_params = wm8978_hw_params, - .digital_mute = wm8978_mute, + .mute_stream = wm8978_mute, .set_fmt = wm8978_set_dai_fmt, .set_clkdiv = wm8978_set_dai_clkdiv, .set_sysclk = wm8978_set_dai_sysclk, + .no_capture_mute = 1, }; /* Also supports 12kHz */ diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index a7e0376f9cf6..d1d2d408ad95 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -492,7 +492,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int reg; - reg = snd_soc_component_read32(component, WM8983_EQ1_LOW_SHELF); + reg = snd_soc_component_read(component, WM8983_EQ1_LOW_SHELF); if (reg & WM8983_EQ3DMODE) ucontrol->value.enumerated.item[0] = 1; else @@ -512,7 +512,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, && ucontrol->value.enumerated.item[0] != 1) return -EINVAL; - reg_eq = snd_soc_component_read32(component, WM8983_EQ1_LOW_SHELF); + reg_eq = snd_soc_component_read(component, WM8983_EQ1_LOW_SHELF); switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) { case 0: if (!ucontrol->value.enumerated.item[0]) @@ -524,8 +524,8 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, break; } - regpwr2 = snd_soc_component_read32(component, WM8983_POWER_MANAGEMENT_2); - regpwr3 = snd_soc_component_read32(component, WM8983_POWER_MANAGEMENT_3); + regpwr2 = snd_soc_component_read(component, WM8983_POWER_MANAGEMENT_2); + regpwr3 = snd_soc_component_read(component, WM8983_POWER_MANAGEMENT_3); /* disable the DACs and ADCs */ snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_2, WM8983_ADCENR_MASK | WM8983_ADCENL_MASK, 0); @@ -557,7 +557,7 @@ static bool wm8983_writeable(struct device *dev, unsigned int reg) } } -static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) +static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -943,11 +943,12 @@ static int wm8983_probe(struct snd_soc_component *component) } static const struct snd_soc_dai_ops wm8983_dai_ops = { - .digital_mute = wm8983_dac_mute, + .mute_stream = wm8983_dac_mute, .hw_params = wm8983_hw_params, .set_fmt = wm8983_set_fmt, .set_sysclk = wm8983_set_sysclk, - .set_pll = wm8983_set_pll + .set_pll = wm8983_set_pll, + .no_capture_mute = 1, }; #define WM8983_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index a62907d0f340..3f27482349b2 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -592,7 +592,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int reg; - reg = snd_soc_component_read32(component, WM8985_EQ1_LOW_SHELF); + reg = snd_soc_component_read(component, WM8985_EQ1_LOW_SHELF); if (reg & WM8985_EQ3DMODE) ucontrol->value.enumerated.item[0] = 1; else @@ -612,7 +612,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, && ucontrol->value.enumerated.item[0] != 1) return -EINVAL; - reg_eq = snd_soc_component_read32(component, WM8985_EQ1_LOW_SHELF); + reg_eq = snd_soc_component_read(component, WM8985_EQ1_LOW_SHELF); switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) { case 0: if (!ucontrol->value.enumerated.item[0]) @@ -624,8 +624,8 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, break; } - regpwr2 = snd_soc_component_read32(component, WM8985_POWER_MANAGEMENT_2); - regpwr3 = snd_soc_component_read32(component, WM8985_POWER_MANAGEMENT_3); + regpwr2 = snd_soc_component_read(component, WM8985_POWER_MANAGEMENT_2); + regpwr3 = snd_soc_component_read(component, WM8985_POWER_MANAGEMENT_3); /* disable the DACs and ADCs */ snd_soc_component_update_bits(component, WM8985_POWER_MANAGEMENT_2, WM8985_ADCENR_MASK | WM8985_ADCENL_MASK, 0); @@ -649,7 +649,7 @@ static int wm8985_reset(struct snd_soc_component *component) return snd_soc_component_write(component, WM8985_SOFTWARE_RESET, 0x0); } -static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute) +static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -1072,11 +1072,12 @@ err_reg_enable: } static const struct snd_soc_dai_ops wm8985_dai_ops = { - .digital_mute = wm8985_dac_mute, + .mute_stream = wm8985_dac_mute, .hw_params = wm8985_hw_params, .set_fmt = wm8985_set_fmt, .set_sysclk = wm8985_set_sysclk, - .set_pll = wm8985_set_pll + .set_pll = wm8985_set_pll, + .no_capture_mute = 1, }; #define WM8985_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 85bfd041d546..d2c2d0d943f0 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -242,10 +242,10 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 adctl2 = snd_soc_component_read32(component, WM8988_ADCTL2); + u16 adctl2 = snd_soc_component_read(component, WM8988_ADCTL2); /* Use the DAC to gate LRC if active, otherwise use ADC */ - if (snd_soc_component_read32(component, WM8988_PWR2) & 0x180) + if (snd_soc_component_read(component, WM8988_PWR2) & 0x180) adctl2 &= ~0x4; else adctl2 |= 0x4; @@ -667,8 +667,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8988_IFACE) & 0x1f3; - u16 srate = snd_soc_component_read32(component, WM8988_SRATE) & 0x180; + u16 iface = snd_soc_component_read(component, WM8988_IFACE) & 0x1f3; + u16 srate = snd_soc_component_read(component, WM8988_SRATE) & 0x180; int coeff; coeff = get_coeff(wm8988->sysclk, params_rate(params)); @@ -707,10 +707,10 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8988_mute(struct snd_soc_dai *dai, int mute) +static int wm8988_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8988_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8988_ADCDAC) & 0xfff7; if (mute) snd_soc_component_write(component, WM8988_ADCDAC, mute_reg | 0x8); @@ -723,7 +723,7 @@ static int wm8988_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component); - u16 pwr_reg = snd_soc_component_read32(component, WM8988_PWR1) & ~0x1c1; + u16 pwr_reg = snd_soc_component_read(component, WM8988_PWR1) & ~0x1c1; switch (level) { case SND_SOC_BIAS_ON: @@ -766,7 +766,8 @@ static const struct snd_soc_dai_ops wm8988_ops = { .hw_params = wm8988_pcm_hw_params, .set_fmt = wm8988_set_dai_fmt, .set_sysclk = wm8988_set_dai_sysclk, - .digital_mute = wm8988_mute, + .mute_stream = wm8988_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8988_dai = { diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 499a29b47d5e..938940777e5d 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -61,7 +61,7 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); return snd_soc_component_write(component, reg, val | 0x0100); } @@ -298,7 +298,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, switch (reg_shift) { case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : - reg = snd_soc_component_read32(component, WM8990_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8990_OUTPUT_MIXER1); if (reg & WM8990_LDLO) { printk(KERN_WARNING "Cannot set as Output Mixer 1 LDLO Set\n"); @@ -306,7 +306,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): - reg = snd_soc_component_read32(component, WM8990_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8990_OUTPUT_MIXER2); if (reg & WM8990_RDRO) { printk(KERN_WARNING "Cannot set as Output Mixer 2 RDRO Set\n"); @@ -314,7 +314,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): - reg = snd_soc_component_read32(component, WM8990_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8990_SPEAKER_MIXER); if (reg & WM8990_LDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer LDSPK Set\n"); @@ -322,7 +322,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): - reg = snd_soc_component_read32(component, WM8990_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8990_SPEAKER_MIXER); if (reg & WM8990_RDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer RDSPK Set\n"); @@ -892,8 +892,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 audio1, audio3; - audio1 = snd_soc_component_read32(component, WM8990_AUDIO_INTERFACE_1); - audio3 = snd_soc_component_read32(component, WM8990_AUDIO_INTERFACE_3); + audio1 = snd_soc_component_read(component, WM8990_AUDIO_INTERFACE_1); + audio3 = snd_soc_component_read(component, WM8990_AUDIO_INTERFACE_3); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -976,7 +976,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 audio1 = snd_soc_component_read32(component, WM8990_AUDIO_INTERFACE_1); + u16 audio1 = snd_soc_component_read(component, WM8990_AUDIO_INTERFACE_1); audio1 &= ~WM8990_AIF_WL_MASK; /* bit size */ @@ -998,12 +998,12 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8990_mute(struct snd_soc_dai *dai, int mute) +static int wm8990_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 val; - val = snd_soc_component_read32(component, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; + val = snd_soc_component_read(component, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; if (mute) snd_soc_component_write(component, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); @@ -1152,11 +1152,12 @@ static int wm8990_set_bias_level(struct snd_soc_component *component, */ static const struct snd_soc_dai_ops wm8990_dai_ops = { .hw_params = wm8990_hw_params, - .digital_mute = wm8990_mute, + .mute_stream = wm8990_mute, .set_fmt = wm8990_set_dai_fmt, .set_clkdiv = wm8990_set_dai_clkdiv, .set_pll = wm8990_set_dai_pll, .set_sysclk = wm8990_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8990_dai = { diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index f8375d67e901..16bc8609d0d2 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -139,7 +139,7 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); return snd_soc_component_write(component, reg, val | 0x0100); } @@ -364,7 +364,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, switch (reg_shift) { case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8991_OUTPUT_MIXER1); if (reg & WM8991_LDLO) { printk(KERN_WARNING "Cannot set as Output Mixer 1 LDLO Set\n"); @@ -373,7 +373,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, break; case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8991_OUTPUT_MIXER2); if (reg & WM8991_RDRO) { printk(KERN_WARNING "Cannot set as Output Mixer 2 RDRO Set\n"); @@ -382,7 +382,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, break; case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8991_SPEAKER_MIXER); if (reg & WM8991_LDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer LDSPK Set\n"); @@ -391,7 +391,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, break; case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8991_SPEAKER_MIXER); if (reg & WM8991_RDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer RDSPK Set\n"); @@ -922,12 +922,12 @@ static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai, pll_factors(&pll_div, freq_out * 4, freq_in); /* Turn on PLL */ - reg = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_2); + reg = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_2); reg |= WM8991_PLL_ENA; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_2, reg); /* sysclk comes from PLL */ - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2); + reg = snd_soc_component_read(component, WM8991_CLOCKING_2); snd_soc_component_write(component, WM8991_CLOCKING_2, reg | WM8991_SYSCLK_SRC); /* set up N , fractional mode and pre-divisor if necessary */ @@ -937,7 +937,7 @@ static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai, snd_soc_component_write(component, WM8991_PLL3, (u8)(pll_div.k & 0xFF)); } else { /* Turn on PLL */ - reg = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_2); + reg = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_2); reg &= ~WM8991_PLL_ENA; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_2, reg); } @@ -953,8 +953,8 @@ static int wm8991_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 audio1, audio3; - audio1 = snd_soc_component_read32(component, WM8991_AUDIO_INTERFACE_1); - audio3 = snd_soc_component_read32(component, WM8991_AUDIO_INTERFACE_3); + audio1 = snd_soc_component_read(component, WM8991_AUDIO_INTERFACE_1); + audio3 = snd_soc_component_read(component, WM8991_AUDIO_INTERFACE_3); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1008,22 +1008,22 @@ static int wm8991_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8991_MCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_2) & ~WM8991_MCLK_DIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_2, reg | div); break; case WM8991_DACCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_2) & ~WM8991_DAC_CLKDIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_2, reg | div); break; case WM8991_ADCCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_2) & ~WM8991_ADC_CLKDIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_2, reg | div); break; case WM8991_BCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_1) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_1) & ~WM8991_BCLK_DIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_1, reg | div); break; @@ -1042,7 +1042,7 @@ static int wm8991_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 audio1 = snd_soc_component_read32(component, WM8991_AUDIO_INTERFACE_1); + u16 audio1 = snd_soc_component_read(component, WM8991_AUDIO_INTERFACE_1); audio1 &= ~WM8991_AIF_WL_MASK; /* bit size */ @@ -1064,12 +1064,12 @@ static int wm8991_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8991_mute(struct snd_soc_dai *dai, int mute) +static int wm8991_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 val; - val = snd_soc_component_read32(component, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE; + val = snd_soc_component_read(component, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE; if (mute) snd_soc_component_write(component, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); else @@ -1089,7 +1089,7 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_PREPARE: /* VMID=2*50k */ - val = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_1) & ~WM8991_VMID_MODE_MASK; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_1, val | 0x2); break; @@ -1146,7 +1146,7 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, } /* VMID=2*250k */ - val = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_1) & ~WM8991_VMID_MODE_MASK; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_1, val | 0x4); break; @@ -1162,7 +1162,7 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, WM8991_BUFIOEN); /* mute DAC */ - val = snd_soc_component_read32(component, WM8991_DAC_CTRL); + val = snd_soc_component_read(component, WM8991_DAC_CTRL); snd_soc_component_write(component, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); /* Enable any disabled outputs */ @@ -1196,10 +1196,11 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8991_ops = { .hw_params = wm8991_hw_params, - .digital_mute = wm8991_mute, + .mute_stream = wm8991_mute, .set_fmt = wm8991_set_dai_fmt, .set_clkdiv = wm8991_set_dai_clkdiv, - .set_pll = wm8991_set_dai_pll + .set_pll = wm8991_set_dai_pll, + .no_capture_mute = 1, }; /* diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 3fb8f37a3fad..9f310082e3c1 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -483,7 +483,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int wm8993->fll_fref = 0; wm8993->fll_fout = 0; - reg1 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_1); + reg1 = snd_soc_component_read(component, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_component_write(component, WM8993_FLL_CONTROL_1, reg1); @@ -494,7 +494,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int if (ret != 0) return ret; - reg5 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_5); + reg5 = snd_soc_component_read(component, WM8993_FLL_CONTROL_5); reg5 &= ~WM8993_FLL_CLK_SRC_MASK; switch (fll_id) { @@ -516,7 +516,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int /* Any FLL configuration change requires that the FLL be * disabled first. */ - reg1 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_1); + reg1 = snd_soc_component_read(component, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_component_write(component, WM8993_FLL_CONTROL_1, reg1); @@ -532,7 +532,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); snd_soc_component_write(component, WM8993_FLL_CONTROL_3, fll_div.k); - reg4 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_4); + reg4 = snd_soc_component_read(component, WM8993_FLL_CONTROL_4); reg4 &= ~WM8993_FLL_N_MASK; reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; snd_soc_component_write(component, WM8993_FLL_CONTROL_4, reg4); @@ -583,7 +583,7 @@ static int configure_clock(struct snd_soc_component *component) case WM8993_SYSCLK_MCLK: dev_dbg(component->dev, "Using %dHz MCLK\n", wm8993->mclk_rate); - reg = snd_soc_component_read32(component, WM8993_CLOCKING_2); + reg = snd_soc_component_read(component, WM8993_CLOCKING_2); reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC); if (wm8993->mclk_rate > 13500000) { reg |= WM8993_MCLK_DIV; @@ -599,7 +599,7 @@ static int configure_clock(struct snd_soc_component *component) dev_dbg(component->dev, "Using %dHz FLL clock\n", wm8993->fll_fout); - reg = snd_soc_component_read32(component, WM8993_CLOCKING_2); + reg = snd_soc_component_read(component, WM8993_CLOCKING_2); reg |= WM8993_SYSCLK_SRC; if (wm8993->fll_fout > 13500000) { reg |= WM8993_MCLK_DIV; @@ -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; @@ -1090,8 +1090,8 @@ static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct wm8993_priv *wm8993 = snd_soc_component_get_drvdata(component); - unsigned int aif1 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_1); - unsigned int aif4 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_4); + unsigned int aif1 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_1); + unsigned int aif4 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_4); aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK); @@ -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; @@ -1190,16 +1190,16 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, int ret, i, best, best_val, cur_val; unsigned int clocking1, clocking3, aif1, aif4; - clocking1 = snd_soc_component_read32(component, WM8993_CLOCKING_1); + clocking1 = snd_soc_component_read(component, WM8993_CLOCKING_1); clocking1 &= ~WM8993_BCLK_DIV_MASK; - clocking3 = snd_soc_component_read32(component, WM8993_CLOCKING_3); + clocking3 = snd_soc_component_read(component, WM8993_CLOCKING_3); clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK); - aif1 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_1); + aif1 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_1); aif1 &= ~WM8993_AIF_WL_MASK; - aif4 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_4); + aif4 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_4); aif4 &= ~WM8993_LRCLK_RATE_MASK; /* What BCLK do we need? */ @@ -1299,7 +1299,7 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, /* ReTune Mobile? */ if (wm8993->pdata.num_retune_configs) { - u16 eq1 = snd_soc_component_read32(component, WM8993_EQ1); + u16 eq1 = snd_soc_component_read(component, WM8993_EQ1); struct wm8993_retune_mobile_setting *s; best = 0; @@ -1330,12 +1330,12 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8993_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; unsigned int reg; - reg = snd_soc_component_read32(component, WM8993_DAC_CTRL); + reg = snd_soc_component_read(component, WM8993_DAC_CTRL); if (mute) reg |= WM8993_DAC_MUTE; @@ -1444,9 +1444,10 @@ static const struct snd_soc_dai_ops wm8993_ops = { .set_sysclk = wm8993_set_sysclk, .set_fmt = wm8993_set_dai_fmt, .hw_params = wm8993_hw_params, - .digital_mute = wm8993_digital_mute, + .mute_stream = wm8993_mute, .set_pll = wm8993_set_fll, .set_tdm_slot = wm8993_set_tdm_slot, + .no_capture_mute = 1, }; #define WM8993_RATES SNDRV_PCM_RATE_8000_48000 diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 55d0b9be6ff0..a84ae879d37e 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -113,7 +113,7 @@ static void wm8958_micd_set_rate(struct snd_soc_component *component) idle = !wm8994->jack_mic; - sysclk = snd_soc_component_read32(component, WM8994_CLOCKING_1); + sysclk = snd_soc_component_read(component, WM8994_CLOCKING_1); if (sysclk & WM8994_SYSCLK_SRC) sysclk = wm8994->aifclk[1]; else @@ -247,7 +247,7 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink) { struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); - int reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + int reg = snd_soc_component_read(component, WM8994_CLOCKING_1); const char *clk; /* Check what we're currently using for CLK_SYS */ @@ -305,7 +305,7 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, else mask = WM8994_AIF1DAC1_DRC_ENA_MASK; - ret = snd_soc_component_read32(component, mc->reg); + ret = snd_soc_component_read(component, mc->reg); if (ret < 0) return ret; if (ret & mask) @@ -324,7 +324,7 @@ static void wm8994_set_drc(struct snd_soc_component *component, int drc) int save, i; /* Save any enables; the configuration should clear them. */ - save = snd_soc_component_read32(component, base); + save = snd_soc_component_read(component, base); save &= WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | WM8994_AIF1ADC1R_DRC_ENA; @@ -434,7 +434,7 @@ static void wm8994_set_retune_mobile(struct snd_soc_component *component, int bl /* The EQ will be disabled while reconfiguring it, remember the * current configuration. */ - save = snd_soc_component_read32(component, base); + save = snd_soc_component_read(component, base); save &= WM8994_AIF1DAC1_EQ_ENA; for (i = 0; i < WM8994_EQ_REGS; i++) @@ -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, @@ -998,7 +998,7 @@ static bool wm8994_check_class_w_digital(struct snd_soc_component *component) int reg, reg_r; /* We also need the same AIF source for L/R and only one path */ - reg = snd_soc_component_read32(component, WM8994_DAC1_LEFT_MIXER_ROUTING); + reg = snd_soc_component_read(component, WM8994_DAC1_LEFT_MIXER_ROUTING); switch (reg) { case WM8994_AIF2DACL_TO_DAC1L: dev_vdbg(component->dev, "Class W source AIF2DAC\n"); @@ -1017,7 +1017,7 @@ static bool wm8994_check_class_w_digital(struct snd_soc_component *component) return false; } - reg_r = snd_soc_component_read32(component, WM8994_DAC1_RIGHT_MIXER_ROUTING); + reg_r = snd_soc_component_read(component, WM8994_DAC1_RIGHT_MIXER_ROUTING); if (reg_r != reg) { dev_vdbg(component->dev, "Left and right DAC mixers different\n"); return false; @@ -1041,7 +1041,7 @@ static int aif_mclk_set(struct snd_soc_component *component, int aif, bool enabl else offset = 0; - val = snd_soc_component_read32(component, WM8994_AIF1_CLOCKING_1 + offset); + val = snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1 + offset); val &= WM8994_AIF1CLK_SRC_MASK; switch (val) { @@ -1100,7 +1100,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, if (wm8994->channels[0] <= 2) mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); - val = snd_soc_component_read32(component, WM8994_AIF1_CONTROL_1); + val = snd_soc_component_read(component, WM8994_AIF1_CONTROL_1); if ((val & WM8994_AIF1ADCL_SRC) && (val & WM8994_AIF1ADCR_SRC)) adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA; @@ -1111,7 +1111,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA | WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; - val = snd_soc_component_read32(component, WM8994_AIF1_CONTROL_2); + val = snd_soc_component_read(component, WM8994_AIF1_CONTROL_2); if ((val & WM8994_AIF1DACL_SRC) && (val & WM8994_AIF1DACR_SRC)) dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA; @@ -1146,7 +1146,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) snd_soc_component_write(component, wm8994_vu_bits[i].reg, - snd_soc_component_read32(component, + snd_soc_component_read(component, wm8994_vu_bits[i].reg)); break; @@ -1157,7 +1157,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, mask, 0); - val = snd_soc_component_read32(component, WM8994_CLOCKING_1); + val = snd_soc_component_read(component, WM8994_CLOCKING_1); if (val & WM8994_AIF2DSPCLK_ENA) val = WM8994_SYSDSPCLK_ENA; else @@ -1192,7 +1192,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, if (ret < 0) return ret; - val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_1); + val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_1); if ((val & WM8994_AIF2ADCL_SRC) && (val & WM8994_AIF2ADCR_SRC)) adc = WM8994_AIF2ADCR_ENA; @@ -1203,7 +1203,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; - val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_2); + val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_2); if ((val & WM8994_AIF2DACL_SRC) && (val & WM8994_AIF2DACR_SRC)) dac = WM8994_AIF2DACR_ENA; @@ -1239,7 +1239,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) snd_soc_component_write(component, wm8994_vu_bits[i].reg, - snd_soc_component_read32(component, + snd_soc_component_read(component, wm8994_vu_bits[i].reg)); break; @@ -1252,7 +1252,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA, 0); - val = snd_soc_component_read32(component, WM8994_CLOCKING_1); + val = snd_soc_component_read(component, WM8994_CLOCKING_1); if (val & WM8994_AIF1DSPCLK_ENA) val = WM8994_SYSDSPCLK_ENA; else @@ -1429,7 +1429,7 @@ static int post_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); dev_dbg(component->dev, "SRC status: %x\n", - snd_soc_component_read32(component, + snd_soc_component_read(component, WM8994_RATE_STATUS)); return 0; } @@ -2209,7 +2209,7 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, return -EINVAL; } - reg = snd_soc_component_read32(component, WM8994_FLL1_CONTROL_1 + reg_offset); + reg = snd_soc_component_read(component, WM8994_FLL1_CONTROL_1 + reg_offset); was_enabled = reg & WM8994_FLL1_ENA; switch (src) { @@ -2250,12 +2250,12 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, return ret; /* Make sure that we're not providing SYSCLK right now */ - clk1 = snd_soc_component_read32(component, WM8994_CLOCKING_1); + clk1 = snd_soc_component_read(component, WM8994_CLOCKING_1); if (clk1 & WM8994_SYSCLK_SRC) aif_reg = WM8994_AIF2_CLOCKING_1; else aif_reg = WM8994_AIF1_CLOCKING_1; - reg = snd_soc_component_read32(component, aif_reg); + reg = snd_soc_component_read(component, aif_reg); if ((reg & WM8994_AIF1CLK_ENA) && (reg & WM8994_AIF1CLK_SRC_MASK) == aif_src) { @@ -2270,7 +2270,7 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, /* Disable MCLK if needed before we possibly change to new clock parent */ if (was_enabled) { - reg = snd_soc_component_read32(component, WM8994_FLL1_CONTROL_5 + reg = snd_soc_component_read(component, WM8994_FLL1_CONTROL_5 + reg_offset); reg = ((reg & WM8994_FLL1_REFCLK_SRC_MASK) >> WM8994_FLL1_REFCLK_SRC_SHIFT) + 1; @@ -2423,9 +2423,9 @@ out: if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { dev_dbg(component->dev, "Configuring AIFs for 128fs\n"); - wm8994->aifdiv[0] = snd_soc_component_read32(component, WM8994_AIF1_RATE) + wm8994->aifdiv[0] = snd_soc_component_read(component, WM8994_AIF1_RATE) & WM8994_AIF1CLK_RATE_MASK; - wm8994->aifdiv[1] = snd_soc_component_read32(component, WM8994_AIF2_RATE) + wm8994->aifdiv[1] = snd_soc_component_read(component, WM8994_AIF2_RATE) & WM8994_AIF1CLK_RATE_MASK; snd_soc_component_update_bits(component, WM8994_AIF1_RATE, @@ -2567,9 +2567,9 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { dev_dbg(component->dev, "Configuring AIFs for 128fs\n"); - wm8994->aifdiv[0] = snd_soc_component_read32(component, WM8994_AIF1_RATE) + wm8994->aifdiv[0] = snd_soc_component_read(component, WM8994_AIF1_RATE) & WM8994_AIF1CLK_RATE_MASK; - wm8994->aifdiv[1] = snd_soc_component_read32(component, WM8994_AIF2_RATE) + wm8994->aifdiv[1] = snd_soc_component_read(component, WM8994_AIF2_RATE) & WM8994_AIF1CLK_RATE_MASK; snd_soc_component_update_bits(component, WM8994_AIF1_RATE, @@ -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; @@ -2991,7 +2991,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, dai->id, wm8994->aifclk[id], bclk_rate); if (wm8994->channels[id] == 1 && - (snd_soc_component_read32(component, aif1_reg) & 0x18) == 0x18) + (snd_soc_component_read(component, aif1_reg) & 0x18) == 0x18) aif2 |= WM8994_AIF1_MONO; if (wm8994->aifclk[id] == 0) { @@ -3110,7 +3110,8 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, return snd_soc_component_update_bits(component, aif1_reg, WM8994_AIF1_WL_MASK, aif1); } -static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int mute_reg; @@ -3187,18 +3188,20 @@ static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = { .set_sysclk = wm8994_set_dai_sysclk, .set_fmt = wm8994_set_dai_fmt, .hw_params = wm8994_hw_params, - .digital_mute = wm8994_aif_mute, + .mute_stream = wm8994_aif_mute, .set_pll = wm8994_set_fll, .set_tristate = wm8994_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = { .set_sysclk = wm8994_set_dai_sysclk, .set_fmt = wm8994_set_dai_fmt, .hw_params = wm8994_hw_params, - .digital_mute = wm8994_aif_mute, + .mute_stream = wm8994_aif_mute, .set_pll = wm8994_set_fll, .set_tristate = wm8994_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = { @@ -3795,7 +3798,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) mutex_lock(&wm8994->accdet_lock); - reg = snd_soc_component_read32(component, WM1811_JACKDET_CTRL); + reg = snd_soc_component_read(component, WM1811_JACKDET_CTRL); if (reg < 0) { dev_err(component->dev, "Failed to read jack status: %d\n", reg); mutex_unlock(&wm8994->accdet_lock); @@ -3877,6 +3880,10 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work) * * @component: WM8958 component * @jack: jack to report detection events on + * @det_cb: detection callback + * @det_cb_data: data for detection callback + * @id_cb: mic id callback + * @id_cb_data: data for mic id callback * * Enable microphone detection functionality for the WM8958. By * default simple detection which supports the detection of up to 6 @@ -4006,7 +4013,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) * with an update of the MICDET status; if so it will have * stopped detection and we can ignore this interrupt. */ - if (!(snd_soc_component_read32(component, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) + if (!(snd_soc_component_read(component, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) return IRQ_HANDLED; cancel_delayed_work_sync(&wm8994->mic_complete_work); @@ -4019,7 +4026,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) */ count = 10; do { - reg = snd_soc_component_read32(component, WM8958_MIC_DETECT_3); + reg = snd_soc_component_read(component, WM8958_MIC_DETECT_3); if (reg < 0) { dev_err(component->dev, "Failed to read mic detect status: %d\n", @@ -4048,7 +4055,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) /* Avoid a transient report when the accessory is being removed */ if (wm8994->jackdet) { - ret = snd_soc_component_read32(component, WM1811_JACKDET_CTRL); + ret = snd_soc_component_read(component, WM1811_JACKDET_CTRL); if (ret < 0) { dev_err(component->dev, "Failed to read jack status: %d\n", ret); diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 53e285caa926..b896d9c5bea0 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -489,7 +489,7 @@ static void wm8995_update_class_w(struct snd_soc_component *component) int reg, reg_r; /* We also need the same setting for L/R and only one path */ - reg = snd_soc_component_read32(component, WM8995_DAC1_LEFT_MIXER_ROUTING); + reg = snd_soc_component_read(component, WM8995_DAC1_LEFT_MIXER_ROUTING); switch (reg) { case WM8995_AIF2DACL_TO_DAC1L: dev_dbg(component->dev, "Class W source AIF2DAC\n"); @@ -509,7 +509,7 @@ static void wm8995_update_class_w(struct snd_soc_component *component) break; } - reg_r = snd_soc_component_read32(component, WM8995_DAC1_RIGHT_MIXER_ROUTING); + reg_r = snd_soc_component_read(component, WM8995_DAC1_RIGHT_MIXER_ROUTING); if (reg_r != reg) { dev_dbg(component->dev, "Left and right DAC mixers different\n"); enable = 0; @@ -535,7 +535,7 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source, unsigned int reg; const char *clk; - reg = snd_soc_component_read32(component, WM8995_CLOCKING_1); + reg = snd_soc_component_read(component, WM8995_CLOCKING_1); /* Check what we're currently using for CLK_SYS */ if (reg & WM8995_SYSCLK_SRC) clk = "AIF2CLK"; @@ -596,7 +596,7 @@ static void dc_servo_cmd(struct snd_soc_component *component, snd_soc_component_write(component, reg, val); while (timeout--) { msleep(10); - val = snd_soc_component_read32(component, WM8995_DC_SERVO_READBACK_0); + val = snd_soc_component_read(component, WM8995_DC_SERVO_READBACK_0); if ((val & mask) == mask) return; } @@ -610,7 +610,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, WM8995_ANALOGUE_HP_1); + reg = snd_soc_component_read(component, WM8995_ANALOGUE_HP_1); switch (event) { case SND_SOC_DAPM_POST_PMU: @@ -1417,7 +1417,7 @@ static bool wm8995_volatile(struct device *dev, unsigned int reg) } } -static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute) +static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int mute_reg; @@ -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; @@ -1804,10 +1804,10 @@ static int wm8995_set_fll(struct snd_soc_dai *dai, int id, component = dai->component; wm8995 = snd_soc_component_get_drvdata(component); - aif1 = snd_soc_component_read32(component, WM8995_AIF1_CLOCKING_1) + aif1 = snd_soc_component_read(component, WM8995_AIF1_CLOCKING_1) & WM8995_AIF1CLK_ENA; - aif2 = snd_soc_component_read32(component, WM8995_AIF2_CLOCKING_1) + aif2 = snd_soc_component_read(component, WM8995_AIF2_CLOCKING_1) & WM8995_AIF2CLK_ENA; switch (id) { @@ -2040,7 +2040,7 @@ static int wm8995_probe(struct snd_soc_component *component) return ret; } - ret = snd_soc_component_read32(component, WM8995_SOFTWARE_RESET); + ret = snd_soc_component_read(component, WM8995_SOFTWARE_RESET); if (ret < 0) { dev_err(component->dev, "Failed to read device ID: %d\n", ret); goto err_reg_enable; @@ -2094,18 +2094,20 @@ static const struct snd_soc_dai_ops wm8995_aif1_dai_ops = { .set_sysclk = wm8995_set_dai_sysclk, .set_fmt = wm8995_set_dai_fmt, .hw_params = wm8995_hw_params, - .digital_mute = wm8995_aif_mute, + .mute_stream = wm8995_aif_mute, .set_pll = wm8995_set_fll, .set_tristate = wm8995_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8995_aif2_dai_ops = { .set_sysclk = wm8995_set_dai_sysclk, .set_fmt = wm8995_set_dai_fmt, .hw_params = wm8995_hw_params, - .digital_mute = wm8995_aif_mute, + .mute_stream = wm8995_aif_mute, .set_pll = wm8995_set_fll, .set_tristate = wm8995_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8995_aif3_dai_ops = { diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 50eaa60d6cb3..d303ef7571e9 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -343,7 +343,7 @@ static void wm8996_set_retune_mobile(struct snd_soc_component *component, int bl switch (block) { case 0: base = WM8996_DSP1_RX_EQ_GAINS_1; - if (snd_soc_component_read32(component, WM8996_POWER_MANAGEMENT_8) & + if (snd_soc_component_read(component, WM8996_POWER_MANAGEMENT_8) & WM8996_DSP1RX_SRC) iface = 1; else @@ -351,7 +351,7 @@ static void wm8996_set_retune_mobile(struct snd_soc_component *component, int bl break; case 1: base = WM8996_DSP1_RX_EQ_GAINS_2; - if (snd_soc_component_read32(component, WM8996_POWER_MANAGEMENT_8) & + if (snd_soc_component_read(component, WM8996_POWER_MANAGEMENT_8) & WM8996_DSP2RX_SRC) iface = 1; else @@ -386,7 +386,7 @@ static void wm8996_set_retune_mobile(struct snd_soc_component *component, int bl /* The EQ will be disabled while reconfiguring it, remember the * current configuration. */ - save = snd_soc_component_read32(component, base); + save = snd_soc_component_read(component, base); save &= WM8996_DSP1RX_EQ_ENA; for (i = 0; i < ARRAY_SIZE(pdata->retune_mobile_cfgs[best].regs); i++) @@ -672,7 +672,7 @@ static void wait_for_dc_servo(struct snd_soc_component *component, u16 mask) timeout--; } - ret = snd_soc_component_read32(component, WM8996_DC_SERVO_2); + ret = snd_soc_component_read(component, WM8996_DC_SERVO_2); dev_dbg(component->dev, "DC servo state: %x\n", ret); } while (timeout && ret & mask); @@ -1741,7 +1741,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, switch (dai->id) { case 0: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - (snd_soc_component_read32(component, WM8996_GPIO_1)) & WM8996_GP1_FN_MASK) { + (snd_soc_component_read(component, WM8996_GPIO_1)) & WM8996_GP1_FN_MASK) { aifdata_reg = WM8996_AIF1RX_DATA_CONFIGURATION; lrclk_reg = WM8996_AIF1_RX_LRCLK_1; } else { @@ -1752,7 +1752,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, break; case 1: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - (snd_soc_component_read32(component, WM8996_GPIO_2)) & WM8996_GP2_FN_MASK) { + (snd_soc_component_read(component, WM8996_GPIO_2)) & WM8996_GP2_FN_MASK) { aifdata_reg = WM8996_AIF2RX_DATA_CONFIGURATION; lrclk_reg = WM8996_AIF2_RX_LRCLK_1; } else { @@ -1822,7 +1822,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, return 0; /* Disable SYSCLK while we reconfigure */ - old = snd_soc_component_read32(component, WM8996_AIF_CLOCKING_1) & WM8996_SYSCLK_ENA; + old = snd_soc_component_read(component, WM8996_AIF_CLOCKING_1) & WM8996_SYSCLK_ENA; snd_soc_component_update_bits(component, WM8996_AIF_CLOCKING_1, WM8996_SYSCLK_ENA, 0); @@ -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, @@ -2078,7 +2078,7 @@ static int wm8996_set_fll(struct snd_soc_component *component, int fll_id, int s snd_soc_component_write(component, WM8996_FLL_EFS_1, fll_div.lambda); /* Enable the bandgap if it's not already enabled */ - ret = snd_soc_component_read32(component, WM8996_FLL_CONTROL_1); + ret = snd_soc_component_read(component, WM8996_FLL_CONTROL_1); if (!(ret & WM8996_FLL_ENA)) wm8996_bg_enable(component); @@ -2117,7 +2117,7 @@ static int wm8996_set_fll(struct snd_soc_component *component, int fll_id, int s break; } - ret = snd_soc_component_read32(component, WM8996_INTERRUPT_RAW_STATUS_2); + ret = snd_soc_component_read(component, WM8996_INTERRUPT_RAW_STATUS_2); if (ret & WM8996_FLL_LOCK_STS) break; } @@ -2224,6 +2224,9 @@ static void wm8996_free_gpio(struct wm8996_priv *wm8996) /** * wm8996_detect - Enable default WM8996 jack detection + * @component: ASoC component + * @jack: jack pointer + * @polarity_cb: polarity callback * * The WM8996 has advanced accessory detection support for headsets. * This function provides a default implementation which integrates @@ -2291,7 +2294,7 @@ static void wm8996_hpdet_irq(struct snd_soc_component *component) */ report = SND_JACK_HEADPHONE; - reg = snd_soc_component_read32(component, WM8996_HEADPHONE_DETECT_2); + reg = snd_soc_component_read(component, WM8996_HEADPHONE_DETECT_2); if (reg < 0) { dev_err(component->dev, "Failed to read HPDET status\n"); goto out; @@ -2324,7 +2327,7 @@ out: wm8996->detecting = false; /* If the output isn't running re-clamp it */ - if (!(snd_soc_component_read32(component, WM8996_POWER_MANAGEMENT_1) & + if (!(snd_soc_component_read(component, WM8996_POWER_MANAGEMENT_1) & (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT))) snd_soc_component_update_bits(component, WM8996_ANALOGUE_HP_1, WM8996_HPOUT1L_RMV_SHORT | @@ -2383,7 +2386,7 @@ static void wm8996_micd(struct snd_soc_component *component) struct wm8996_priv *wm8996 = snd_soc_component_get_drvdata(component); int val, reg; - val = snd_soc_component_read32(component, WM8996_MIC_DETECT_3); + val = snd_soc_component_read(component, WM8996_MIC_DETECT_3); dev_dbg(component->dev, "Microphone event: %x\n", val); @@ -2449,7 +2452,7 @@ static void wm8996_micd(struct snd_soc_component *component) return; } - reg = snd_soc_component_read32(component, WM8996_ACCESSORY_DETECT_MODE_2); + reg = snd_soc_component_read(component, WM8996_ACCESSORY_DETECT_MODE_2); reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | WM8996_MICD_BIAS_SRC; snd_soc_component_update_bits(component, WM8996_ACCESSORY_DETECT_MODE_2, @@ -2486,13 +2489,13 @@ static irqreturn_t wm8996_irq(int irq, void *data) struct wm8996_priv *wm8996 = snd_soc_component_get_drvdata(component); int irq_val; - irq_val = snd_soc_component_read32(component, WM8996_INTERRUPT_STATUS_2); + irq_val = snd_soc_component_read(component, WM8996_INTERRUPT_STATUS_2); if (irq_val < 0) { dev_err(component->dev, "Failed to read IRQ status: %d\n", irq_val); return IRQ_NONE; } - irq_val &= ~snd_soc_component_read32(component, WM8996_INTERRUPT_STATUS_2_MASK); + irq_val &= ~snd_soc_component_read(component, WM8996_INTERRUPT_STATUS_2_MASK); if (!irq_val) return IRQ_NONE; diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 7c1899219573..f6c5cc80c970 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -43,7 +43,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - val = snd_soc_component_read32(component, ARIZONA_ASRC_RATE1); + val = snd_soc_component_read(component, ARIZONA_ASRC_RATE1); val &= ARIZONA_ASRC_RATE1_MASK; val >>= ARIZONA_ASRC_RATE1_SHIFT; @@ -51,7 +51,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, case 0: case 1: case 2: - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, ARIZONA_SAMPLE_RATE_1 + val); if (val >= 0x11) { dev_warn(component->dev, @@ -67,7 +67,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, return -EINVAL; } - val = snd_soc_component_read32(component, ARIZONA_ASRC_RATE2); + val = snd_soc_component_read(component, ARIZONA_ASRC_RATE2); val &= ARIZONA_ASRC_RATE2_MASK; val >>= ARIZONA_ASRC_RATE2_SHIFT; @@ -75,7 +75,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, case 8: case 9: val -= 0x8; - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, ARIZONA_ASYNC_SAMPLE_RATE_1 + val); if (val >= 0x11) { dev_warn(component->dev, diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index c42ea626a240..4a667ee82fe2 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -338,7 +338,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int reg; - reg = snd_soc_component_read32(component, WM9081_ANALOGUE_SPEAKER_2); + reg = snd_soc_component_read(component, WM9081_ANALOGUE_SPEAKER_2); if (reg & WM9081_SPK_MODE) ucontrol->value.enumerated.item[0] = 1; else @@ -357,8 +357,8 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - unsigned int reg_pwr = snd_soc_component_read32(component, WM9081_POWER_MANAGEMENT); - unsigned int reg2 = snd_soc_component_read32(component, WM9081_ANALOGUE_SPEAKER_2); + unsigned int reg_pwr = snd_soc_component_read(component, WM9081_POWER_MANAGEMENT); + unsigned int reg2 = snd_soc_component_read(component, WM9081_ANALOGUE_SPEAKER_2); /* Are we changing anything? */ if (ucontrol->value.enumerated.item[0] == @@ -568,7 +568,7 @@ static int wm9081_set_fll(struct snd_soc_component *component, int fll_id, if (ret != 0) return ret; - reg5 = snd_soc_component_read32(component, WM9081_FLL_CONTROL_5); + reg5 = snd_soc_component_read(component, WM9081_FLL_CONTROL_5); reg5 &= ~WM9081_FLL_CLK_SRC_MASK; switch (fll_id) { @@ -582,14 +582,14 @@ static int wm9081_set_fll(struct snd_soc_component *component, int fll_id, } /* Disable CLK_SYS while we reconfigure */ - clk_sys_reg = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_3); + clk_sys_reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_3); if (clk_sys_reg & WM9081_CLK_SYS_ENA) snd_soc_component_write(component, WM9081_CLOCK_CONTROL_3, clk_sys_reg & ~WM9081_CLK_SYS_ENA); /* Any FLL configuration change requires that the FLL be * disabled first. */ - reg1 = snd_soc_component_read32(component, WM9081_FLL_CONTROL_1); + reg1 = snd_soc_component_read(component, WM9081_FLL_CONTROL_1); reg1 &= ~WM9081_FLL_ENA; snd_soc_component_write(component, WM9081_FLL_CONTROL_1, reg1); @@ -605,7 +605,7 @@ static int wm9081_set_fll(struct snd_soc_component *component, int fll_id, (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT)); snd_soc_component_write(component, WM9081_FLL_CONTROL_3, fll_div.k); - reg4 = snd_soc_component_read32(component, WM9081_FLL_CONTROL_4); + reg4 = snd_soc_component_read(component, WM9081_FLL_CONTROL_4); reg4 &= ~WM9081_FLL_N_MASK; reg4 |= fll_div.n << WM9081_FLL_N_SHIFT; snd_soc_component_write(component, WM9081_FLL_CONTROL_4, reg4); @@ -707,14 +707,14 @@ static int configure_clock(struct snd_soc_component *component) return -EINVAL; } - reg = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_1); + reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_1); if (mclkdiv) reg |= WM9081_MCLKDIV2; else reg &= ~WM9081_MCLKDIV2; snd_soc_component_write(component, WM9081_CLOCK_CONTROL_1, reg); - reg = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_3); + reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_3); if (fll) reg |= WM9081_CLK_SRC_SEL; else @@ -901,7 +901,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component); - unsigned int aif2 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_2); + unsigned int aif2 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_2); aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV | WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK); @@ -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; @@ -997,18 +997,18 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, int ret, i, best, best_val, cur_val; unsigned int clk_ctrl2, aif1, aif2, aif3, aif4; - clk_ctrl2 = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_2); + clk_ctrl2 = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_2); clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK); - aif1 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_1); + aif1 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_1); - aif2 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_2); + aif2 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_2); aif2 &= ~WM9081_AIF_WL_MASK; - aif3 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_3); + aif3 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_3); aif3 &= ~WM9081_BCLK_DIV_MASK; - aif4 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_4); + aif4 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_4); aif4 &= ~WM9081_LRCLK_RATE_MASK; wm9081->fs = params_rate(params); @@ -1127,7 +1127,7 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, s->name, s->rate); /* If the EQ is enabled then disable it while we write out */ - eq1 = snd_soc_component_read32(component, WM9081_EQ_1) & WM9081_EQ_ENA; + eq1 = snd_soc_component_read(component, WM9081_EQ_1) & WM9081_EQ_ENA; if (eq1 & WM9081_EQ_ENA) snd_soc_component_write(component, WM9081_EQ_1, 0); @@ -1147,12 +1147,12 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm9081_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; unsigned int reg; - reg = snd_soc_component_read32(component, WM9081_DAC_DIGITAL_2); + reg = snd_soc_component_read(component, WM9081_DAC_DIGITAL_2); if (mute) reg |= WM9081_DAC_MUTE; @@ -1188,7 +1188,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component); - unsigned int aif1 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_1); + unsigned int aif1 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_1); aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK); @@ -1232,8 +1232,9 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, static const struct snd_soc_dai_ops wm9081_dai_ops = { .hw_params = wm9081_hw_params, .set_fmt = wm9081_set_dai_fmt, - .digital_mute = wm9081_digital_mute, + .mute_stream = wm9081_mute, .set_tdm_slot = wm9081_set_tdm_slot, + .no_capture_mute = 1, }; /* We report two channels because the CODEC processes a stereo signal, even diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 6c001d118599..e0231a54609c 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -139,7 +139,7 @@ static void wait_for_dc_servo(struct snd_soc_component *component) do { count++; msleep(1); - reg = snd_soc_component_read32(component, WM9090_DC_SERVO_READBACK_0); + reg = snd_soc_component_read(component, WM9090_DC_SERVO_READBACK_0); dev_dbg(component->dev, "DC servo status: %x\n", reg); } while ((reg & WM9090_DCS_CAL_COMPLETE_MASK) != WM9090_DCS_CAL_COMPLETE_MASK && count < 1000); @@ -239,7 +239,7 @@ static int hp_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - unsigned int reg = snd_soc_component_read32(component, WM9090_ANALOGUE_HP_0); + unsigned int reg = snd_soc_component_read(component, WM9090_ANALOGUE_HP_0); switch (event) { case SND_SOC_DAPM_POST_PMU: diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 6497c1ea6228..7072ffacbdfd 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -807,7 +807,7 @@ static void pll_factors(struct snd_soc_component *component, pll_div->k = K; } -/** +/* * Please note that changing the PLL input frequency may require * resynchronisation with the AC97 controller. */ @@ -939,7 +939,7 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 gpio = snd_soc_component_read32(component, AC97_GPIO_CFG) & 0xffc5; + u16 gpio = snd_soc_component_read(component, AC97_GPIO_CFG) & 0xffc5; u16 reg = 0x8000; /* clock masters */ diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 519ca2e69637..410cca57da52 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -355,9 +355,11 @@ static void wm_adsp_buf_free(struct list_head *list) #define WM_ADSP_FW_ASR 7 #define WM_ADSP_FW_TRACE 8 #define WM_ADSP_FW_SPK_PROT 9 -#define WM_ADSP_FW_MISC 10 +#define WM_ADSP_FW_SPK_CALI 10 +#define WM_ADSP_FW_SPK_DIAG 11 +#define WM_ADSP_FW_MISC 12 -#define WM_ADSP_NUM_FW 11 +#define WM_ADSP_NUM_FW 13 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", @@ -370,6 +372,8 @@ static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { [WM_ADSP_FW_ASR] = "ASR Assist", [WM_ADSP_FW_TRACE] = "Dbg Trace", [WM_ADSP_FW_SPK_PROT] = "Protection", + [WM_ADSP_FW_SPK_CALI] = "Calibration", + [WM_ADSP_FW_SPK_DIAG] = "Diagnostic", [WM_ADSP_FW_MISC] = "Misc", }; @@ -586,6 +590,8 @@ static const struct { .caps = trace_caps, }, [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" }, + [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" }, + [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" }, [WM_ADSP_FW_MISC] = { .file = "misc" }, }; @@ -2615,6 +2621,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) switch (type) { case (WMFW_NAME_TEXT << 8): case (WMFW_INFO_TEXT << 8): + case (WMFW_METADATA << 8): break; case (WMFW_ABSOLUTE << 8): /* diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e93af7edd8f7..891effe220fe 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -85,7 +85,7 @@ static void wait_for_dc_servo(struct snd_soc_component *component, unsigned int else msleep(1); - reg = snd_soc_component_read32(component, WM8993_DC_SERVO_0); + reg = snd_soc_component_read(component, WM8993_DC_SERVO_0); dev_dbg(component->dev, "DC servo: %x\n", reg); } while (reg & op && count < timeout); @@ -109,7 +109,7 @@ static bool wm_hubs_dac_hp_direct(struct snd_soc_component *component) int reg; /* If we're going via the mixer we'll need to do additional checks */ - reg = snd_soc_component_read32(component, WM8993_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER1); if (!(reg & WM8993_DACL_TO_HPOUT1L)) { if (reg & ~WM8993_DACL_TO_MIXOUTL) { dev_vdbg(component->dev, "Analogue paths connected: %x\n", @@ -122,7 +122,7 @@ static bool wm_hubs_dac_hp_direct(struct snd_soc_component *component) dev_vdbg(component->dev, "HPL connected to DAC\n"); } - reg = snd_soc_component_read32(component, WM8993_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER2); if (!(reg & WM8993_DACR_TO_HPOUT1R)) { if (reg & ~WM8993_DACR_TO_MIXOUTR) { dev_vdbg(component->dev, "Analogue paths connected: %x\n", @@ -152,10 +152,10 @@ static bool wm_hubs_dcs_cache_get(struct snd_soc_component *component, struct wm_hubs_dcs_cache *cache; unsigned int left, right; - left = snd_soc_component_read32(component, WM8993_LEFT_OUTPUT_VOLUME); + left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME); left &= WM8993_HPOUT1L_VOL_MASK; - right = snd_soc_component_read32(component, WM8993_RIGHT_OUTPUT_VOLUME); + right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME); right &= WM8993_HPOUT1R_VOL_MASK; list_for_each_entry(cache, &hubs->dcs_cache, list) { @@ -181,10 +181,10 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_component *component, u16 dcs_c if (!cache) return; - cache->left = snd_soc_component_read32(component, WM8993_LEFT_OUTPUT_VOLUME); + cache->left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME); cache->left &= WM8993_HPOUT1L_VOL_MASK; - cache->right = snd_soc_component_read32(component, WM8993_RIGHT_OUTPUT_VOLUME); + cache->right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME); cache->right &= WM8993_HPOUT1R_VOL_MASK; cache->dcs_cfg = dcs_cfg; @@ -216,14 +216,14 @@ static int wm_hubs_read_dc_servo(struct snd_soc_component *component, */ switch (hubs->dcs_readback_mode) { case 0: - *reg_l = snd_soc_component_read32(component, WM8993_DC_SERVO_READBACK_1) + *reg_l = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_1) & WM8993_DCS_INTEG_CHAN_0_MASK; - *reg_r = snd_soc_component_read32(component, WM8993_DC_SERVO_READBACK_2) + *reg_r = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_2) & WM8993_DCS_INTEG_CHAN_1_MASK; break; case 2: case 1: - reg = snd_soc_component_read32(component, dcs_reg); + reg = snd_soc_component_read(component, dcs_reg); *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; @@ -342,7 +342,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, return ret; /* Only need to do this if the outputs are active */ - if (snd_soc_component_read32(component, WM8993_POWER_MANAGEMENT_1) + if (snd_soc_component_read(component, WM8993_POWER_MANAGEMENT_1) & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) snd_soc_component_update_bits(component, WM8993_DC_SERVO_0, @@ -538,7 +538,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - unsigned int reg = snd_soc_component_read32(component, WM8993_ANALOGUE_HP_0); + unsigned int reg = snd_soc_component_read(component, WM8993_ANALOGUE_HP_0); switch (event) { case SND_SOC_DAPM_POST_PMU: @@ -590,7 +590,7 @@ static int earpiece_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 reg = snd_soc_component_read32(component, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; + u16 reg = snd_soc_component_read(component, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -680,9 +680,9 @@ void wm_hubs_update_class_w(struct snd_soc_component *component) WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); snd_soc_component_write(component, WM8993_LEFT_OUTPUT_VOLUME, - snd_soc_component_read32(component, WM8993_LEFT_OUTPUT_VOLUME)); + snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME)); snd_soc_component_write(component, WM8993_RIGHT_OUTPUT_VOLUME, - snd_soc_component_read32(component, WM8993_RIGHT_OUTPUT_VOLUME)); + snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME)); } EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h index 4278aa6aeb01..7423272c30e9 100644 --- a/sound/soc/codecs/wmfw.h +++ b/sound/soc/codecs/wmfw.h @@ -180,6 +180,7 @@ struct wmfw_coeff_item { #define WMFW_ABSOLUTE 0xf0 #define WMFW_ALGORITHM_DATA 0xf2 +#define WMFW_METADATA 0xfc #define WMFW_NAME_TEXT 0xfe #define WMFW_INFO_TEXT 0xff diff --git a/sound/soc/dwc/dwc-pcm.c b/sound/soc/dwc/dwc-pcm.c index 9868e7373d36..9f25631d43d3 100644 --- a/sound/soc/dwc/dwc-pcm.c +++ b/sound/soc/dwc/dwc-pcm.c @@ -139,7 +139,7 @@ static int dw_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); snd_soc_set_runtime_hwparams(substream, &dw_pcm_hardware); diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index ea7b4787a8af..1c4ca5ec8caf 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -315,6 +315,7 @@ config SND_SOC_FSL_ASOC_CARD depends on OF && I2C # enforce SND_SOC_FSL_ASOC_CARD=m if SND_AC97_CODEC=m: depends on SND_AC97_CODEC || SND_AC97_CODEC=n + select SND_SIMPLE_CARD_UTILS select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_PCM_DMA select SND_SOC_FSL_ESAI diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 4ff2d21bb32f..e13271ea84de 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -30,7 +30,7 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 00be73900888..de136c0a497d 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -15,6 +15,8 @@ #endif #include <sound/pcm_params.h> #include <sound/soc.h> +#include <sound/jack.h> +#include <sound/simple_card_utils.h> #include "fsl_esai.h" #include "fsl_sai.h" @@ -33,8 +35,7 @@ #define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF) /** - * CODEC private data - * + * struct codec_priv - CODEC private data * @mclk_freq: Clock rate of MCLK * @mclk_id: MCLK (or main clock) id for set_sysclk() * @fll_id: FLL (or secordary clock) id for set_sysclk() @@ -48,11 +49,10 @@ struct codec_priv { }; /** - * CPU private data - * - * @sysclk_freq[2]: SYSCLK rates for set_sysclk() - * @sysclk_dir[2]: SYSCLK directions for set_sysclk() - * @sysclk_id[2]: SYSCLK ids for set_sysclk() + * struct cpu_priv - CPU private data + * @sysclk_freq: SYSCLK rates for set_sysclk() + * @sysclk_dir: SYSCLK directions for set_sysclk() + * @sysclk_id: SYSCLK ids for set_sysclk() * @slot_width: Slot width of each frame * * Note: [1] for tx and [0] for rx @@ -65,9 +65,10 @@ struct cpu_priv { }; /** - * Freescale Generic ASOC card private data - * - * @dai_link[3]: DAI link structure including normal one and DPCM link + * struct fsl_asoc_card_priv - Freescale Generic ASOC card private data + * @dai_link: DAI link structure including normal one and DPCM link + * @hp_jack: Headphone Jack structure + * @mic_jack: Microphone Jack structure * @pdev: platform device pointer * @codec_priv: CODEC private data * @cpu_priv: CPU private data @@ -82,6 +83,8 @@ struct cpu_priv { struct fsl_asoc_card_priv { struct snd_soc_dai_link dai_link[3]; + struct asoc_simple_jack hp_jack; + struct asoc_simple_jack mic_jack; struct platform_device *pdev; struct codec_priv codec_priv; struct cpu_priv cpu_priv; @@ -94,8 +97,8 @@ struct fsl_asoc_card_priv { char name[32]; }; -/** - * This dapm route map exsits for DPCM link only. +/* + * This dapm route map exists for DPCM link only. * The other routes shall go through Device Tree. * * Note: keep all ASRC routes in the second half @@ -119,6 +122,13 @@ static const struct snd_soc_dapm_route audio_map_ac97[] = { {"ASRC-Capture", NULL, "AC97 Capture"}, }; +static const struct snd_soc_dapm_route audio_map_tx[] = { + /* 1st half -- Normal DAPM routes */ + {"Playback", NULL, "CPU-Playback"}, + /* 2nd half -- ASRC DAPM routes */ + {"CPU-Playback", NULL, "ASRC-Playback"}, +}; + /* Add all possible widgets into here without being redundant */ static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = { SND_SOC_DAPM_LINE("Line Out Jack", NULL), @@ -138,7 +148,7 @@ static bool fsl_asoc_card_is_ac97(struct fsl_asoc_card_priv *priv) static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct cpu_priv *cpu_priv = &priv->cpu_priv; @@ -441,6 +451,44 @@ static int fsl_asoc_card_audmux_init(struct device_node *np, return 0; } +static int hp_jack_event(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct snd_soc_jack *jack = (struct snd_soc_jack *)data; + struct snd_soc_dapm_context *dapm = &jack->card->dapm; + + if (event & SND_JACK_HEADPHONE) + /* Disable speaker if headphone is plugged in */ + snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + else + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + + return 0; +} + +static struct notifier_block hp_jack_nb = { + .notifier_call = hp_jack_event, +}; + +static int mic_jack_event(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct snd_soc_jack *jack = (struct snd_soc_jack *)data; + struct snd_soc_dapm_context *dapm = &jack->card->dapm; + + if (event & SND_JACK_MICROPHONE) + /* Disable dmic if microphone is plugged in */ + snd_soc_dapm_disable_pin(dapm, "DMIC"); + else + snd_soc_dapm_enable_pin(dapm, "DMIC"); + + return 0; +} + +static struct notifier_block mic_jack_nb = { + .notifier_call = mic_jack_event, +}; + static int fsl_asoc_card_late_probe(struct snd_soc_card *card) { struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card); @@ -483,10 +531,14 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) struct device_node *cpu_np, *codec_np, *asrc_np; struct device_node *np = pdev->dev.of_node; struct platform_device *asrc_pdev = NULL; + struct device_node *bitclkmaster = NULL; + struct device_node *framemaster = NULL; struct platform_device *cpu_pdev; struct fsl_asoc_card_priv *priv; - struct i2c_client *codec_dev; + struct device *codec_dev = NULL; const char *codec_dai_name; + const char *codec_dev_name; + unsigned int daifmt; u32 width; int ret; @@ -512,10 +564,23 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } codec_np = of_parse_phandle(np, "audio-codec", 0); - if (codec_np) - codec_dev = of_find_i2c_device_by_node(codec_np); - else - codec_dev = NULL; + if (codec_np) { + struct platform_device *codec_pdev; + struct i2c_client *codec_i2c; + + codec_i2c = of_find_i2c_device_by_node(codec_np); + if (codec_i2c) { + codec_dev = &codec_i2c->dev; + codec_dev_name = codec_i2c->name; + } + if (!codec_dev) { + codec_pdev = of_find_device_by_node(codec_np); + if (codec_pdev) { + codec_dev = &codec_pdev->dev; + codec_dev_name = codec_pdev->name; + } + } + } asrc_np = of_parse_phandle(np, "audio-asrc", 0); if (asrc_np) @@ -523,7 +588,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* Get the MCLK rate only, and leave it controlled by CODEC drivers */ if (codec_dev) { - struct clk *codec_clk = clk_get(&codec_dev->dev, NULL); + struct clk *codec_clk = clk_get(codec_dev, NULL); if (!IS_ERR(codec_clk)) { priv->codec_priv.mclk_freq = clk_get_rate(codec_clk); @@ -538,6 +603,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* Assign a default DAI format, and allow each card to overwrite it */ priv->dai_fmt = DAI_FMT_BASE; + memcpy(priv->dai_link, fsl_asoc_card_dai, + sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); + + priv->card.dapm_routes = audio_map; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); /* Diversify the card configurations */ if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { codec_dai_name = "cs42888"; @@ -573,12 +643,58 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) codec_dai_name = "ac97-hifi"; priv->card.set_bias_level = NULL; priv->dai_fmt = SND_SOC_DAIFMT_AC97; + priv->card.dapm_routes = audio_map_ac97; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97); + } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) { + codec_dai_name = "fsl-mqs-dai"; + priv->card.set_bias_level = NULL; + priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_NB_NF; + priv->dai_link[1].dpcm_capture = 0; + priv->dai_link[2].dpcm_capture = 0; + priv->card.dapm_routes = audio_map_tx; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); + } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) { + codec_dai_name = "wm8524-hifi"; + priv->card.set_bias_level = NULL; + priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; + priv->dai_link[1].dpcm_capture = 0; + priv->dai_link[2].dpcm_capture = 0; + priv->cpu_priv.slot_width = 32; + priv->card.dapm_routes = audio_map_tx; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL; goto asrc_fail; } + /* Format info from DT is optional. */ + daifmt = snd_soc_of_parse_daifmt(np, NULL, + &bitclkmaster, &framemaster); + daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; + if (bitclkmaster || framemaster) { + if (codec_np == bitclkmaster) + daifmt |= (codec_np == framemaster) ? + SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; + else + daifmt |= (codec_np == framemaster) ? + SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; + + /* Override dai_fmt with value from DT */ + priv->dai_fmt = daifmt; + } + + /* Change direction according to format */ + if (priv->dai_fmt & SND_SOC_DAIFMT_CBM_CFM) { + priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_IN; + priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_IN; + } + + of_node_put(bitclkmaster); + of_node_put(framemaster); + if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) { dev_err(&pdev->dev, "failed to find codec device\n"); ret = -EPROBE_DEFER; @@ -601,19 +717,17 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1; } - snprintf(priv->name, sizeof(priv->name), "%s-audio", - fsl_asoc_card_is_ac97(priv) ? "ac97" : - codec_dev->name); - /* Initialize sound card */ priv->pdev = pdev; priv->card.dev = &pdev->dev; - priv->card.name = priv->name; + ret = snd_soc_of_parse_card_name(&priv->card, "model"); + if (ret) { + snprintf(priv->name, sizeof(priv->name), "%s-audio", + fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name); + priv->card.name = priv->name; + } priv->card.dai_link = priv->dai_link; - priv->card.dapm_routes = fsl_asoc_card_is_ac97(priv) ? - audio_map_ac97 : audio_map; priv->card.late_probe = fsl_asoc_card_late_probe; - priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets; priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets); @@ -621,13 +735,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) if (!asrc_pdev) priv->card.num_dapm_routes /= 2; - memcpy(priv->dai_link, fsl_asoc_card_dai, - sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); - - ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing"); - if (ret) { - dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret); - goto asrc_fail; + if (of_property_read_bool(np, "audio-routing")) { + ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing"); + if (ret) { + dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret); + goto asrc_fail; + } } /* Normal DAI Link */ @@ -704,8 +817,37 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(&priv->card, priv); ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); - if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + goto asrc_fail; + } + + /* + * Properties "hp-det-gpio" and "mic-det-gpio" are optional, and + * asoc_simple_init_jack uses these properties for creating + * Headphone Jack and Microphone Jack. + * + * The notifier is initialized in snd_soc_card_jack_new(), then + * snd_soc_jack_notifier_register can be called. + */ + if (of_property_read_bool(np, "hp-det-gpio")) { + ret = asoc_simple_init_jack(&priv->card, &priv->hp_jack, + 1, NULL, "Headphone Jack"); + if (ret) + goto asrc_fail; + + snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb); + } + + if (of_property_read_bool(np, "mic-det-gpio")) { + ret = asoc_simple_init_jack(&priv->card, &priv->mic_jack, + 0, NULL, "Mic Jack"); + if (ret) + goto asrc_fail; + + snd_soc_jack_notifier_register(&priv->mic_jack.jack, &mic_jack_nb); + } asrc_fail: of_node_put(asrc_np); @@ -724,6 +866,8 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-sgtl5000", }, { .compatible = "fsl,imx-audio-wm8962", }, { .compatible = "fsl,imx-audio-wm8960", }, + { .compatible = "fsl,imx-audio-mqs", }, + { .compatible = "fsl,imx-audio-wm8524", }, {} }; MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 95f6a9617b0b..02c81d2e34ad 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -37,7 +37,7 @@ static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = { .list = supported_asrc_rate, }; -/** +/* * The following tables map the relationship between asrc_inclk/asrc_outclk in * fsl_asrc.h and the registers of ASRCSR */ @@ -68,7 +68,7 @@ static unsigned char output_clk_map_imx53[ASRC_CLK_MAP_LEN] = { 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, }; -/** +/* * i.MX8QM/i.MX8QXP uses the same map for input and output. * clk_map_imx8qm[0] is for i.MX8QM asrc0 * clk_map_imx8qm[1] is for i.MX8QM asrc1 @@ -102,16 +102,17 @@ static unsigned char clk_map_imx8qxp[2][ASRC_CLK_MAP_LEN] = { }; /** - * Select the pre-processing and post-processing options + * fsl_asrc_sel_proc - Select the pre-processing and post-processing options + * @inrate: input sample rate + * @outrate: output sample rate + * @pre_proc: return value for pre-processing option + * @post_proc: return value for post-processing option + * * Make sure to exclude following unsupported cases before * calling this function: * 1) inrate > 8.125 * outrate * 2) inrate > 16.125 * outrate * - * inrate: input sample rate - * outrate: output sample rate - * pre_proc: return value for pre-processing option - * post_proc: return value for post-processing option */ static void fsl_asrc_sel_proc(int inrate, int outrate, int *pre_proc, int *post_proc) @@ -148,7 +149,9 @@ static void fsl_asrc_sel_proc(int inrate, int outrate, } /** - * Request ASRC pair + * fsl_asrc_request_pair - Request ASRC pair + * @channels: number of channels + * @pair: pointer to pair * * It assigns pair by the order of A->C->B because allocation of pair B, * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A @@ -193,7 +196,8 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) } /** - * Release ASRC pair + * fsl_asrc_release_pair - Release ASRC pair + * @pair: pair to release * * It clears the resource from asrc and releases the occupied channels. */ @@ -217,7 +221,10 @@ static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) } /** - * Configure input and output thresholds + * fsl_asrc_set_watermarks- configure input and output thresholds + * @pair: pointer to pair + * @in: input threshold + * @out: output threshold */ static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) { @@ -234,7 +241,9 @@ static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) } /** - * Calculate the total divisor between asrck clock rate and sample rate + * fsl_asrc_cal_asrck_divisor - Calculate the total divisor between asrck clock rate and sample rate + * @pair: pointer to pair + * @div: divider * * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider */ @@ -250,7 +259,10 @@ static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div) } /** - * Calculate and set the ratio for Ideal Ratio mode only + * fsl_asrc_set_ideal_ratio - Calculate and set the ratio for Ideal Ratio mode only + * @pair: pointer to pair + * @inrate: input rate + * @outrate: output rate * * The ratio is a 32-bit fixed point value with 26 fractional bits. */ @@ -293,7 +305,9 @@ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, } /** - * Configure the assigned ASRC pair + * fsl_asrc_config_pair - Configure the assigned ASRC pair + * @pair: pointer to pair + * @use_ideal_rate: boolean configuration * * It configures those ASRC registers according to a configuration instance * of struct asrc_config which includes in/output sample rate, width, channel @@ -508,7 +522,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) } /** - * Start the assigned ASRC pair + * fsl_asrc_start_pair - Start the assigned ASRC pair + * @pair: pointer to pair * * It enables the assigned pair and makes it stopped at the stall level. */ @@ -539,7 +554,8 @@ static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair) } /** - * Stop the assigned ASRC pair + * fsl_asrc_stop_pair - Stop the assigned ASRC pair + * @pair: pointer to pair */ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) { @@ -552,7 +568,9 @@ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) } /** - * Get DMA channel according to the pair and direction. + * fsl_asrc_get_dma_channel- Get DMA channel according to the pair and direction. + * @pair: pointer to pair + * @dir: DMA direction */ static struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) @@ -582,11 +600,51 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints); } +/* Select proper clock source for internal ratio mode */ +static void fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv, + struct fsl_asrc_pair *pair, + int in_rate, + int out_rate) +{ + struct fsl_asrc_pair_priv *pair_priv = pair->private; + struct asrc_config *config = pair_priv->config; + int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */ + int clk_rate, clk_index; + int i = 0, j = 0; + + rate[IN] = in_rate; + rate[OUT] = out_rate; + + /* Select proper clock source for internal ratio mode */ + for (j = 0; j < 2; j++) { + for (i = 0; i < ASRC_CLK_MAP_LEN; i++) { + clk_index = asrc_priv->clk_map[j][i]; + clk_rate = clk_get_rate(asrc_priv->asrck_clk[clk_index]); + /* Only match a perfect clock source with no remainder */ + if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 && + (clk_rate % rate[j]) == 0) + break; + } + + select_clk[j] = i; + } + + /* Switch to ideal ratio mode if there is no proper clock source */ + if (select_clk[IN] == ASRC_CLK_MAP_LEN || select_clk[OUT] == ASRC_CLK_MAP_LEN) { + select_clk[IN] = INCLK_NONE; + select_clk[OUT] = OUTCLK_ASRCK1_CLK; + } + + config->inclk = select_clk[IN]; + config->outclk = select_clk[OUT]; +} + static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai); + struct fsl_asrc_priv *asrc_priv = asrc->private; struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; struct fsl_asrc_pair_priv *pair_priv = pair->private; @@ -605,8 +663,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, config.pair = pair->index; config.channel_num = channels; - config.inclk = INCLK_NONE; - config.outclk = OUTCLK_ASRCK1_CLK; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { config.input_format = params_format(params); @@ -620,6 +676,10 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, config.output_sample_rate = rate; } + fsl_asrc_select_clk(asrc_priv, pair, + config.input_sample_rate, + config.output_sample_rate); + ret = fsl_asrc_config_pair(pair, false); if (ret) { dev_err(dai->dev, "fail to config asrc pair\n"); @@ -854,7 +914,8 @@ static const struct regmap_config fsl_asrc_regmap_config = { }; /** - * Initialize ASRC registers with a default configurations + * fsl_asrc_init - Initialize ASRC registers with a default configuration + * @asrc: ASRC context */ static int fsl_asrc_init(struct fsl_asrc *asrc) { @@ -888,7 +949,9 @@ static int fsl_asrc_init(struct fsl_asrc *asrc) } /** - * Interrupt handler for ASRC + * fsl_asrc_isr- Interrupt handler for ASRC + * @irq: irq number + * @dev_id: ASRC context */ static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) { diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 5f01a58f422a..29f91cdecbc3 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -129,7 +129,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct snd_pcm_hw_params *params) { enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL; struct snd_dmaengine_dai_dma_data *dma_params_be = NULL; @@ -313,7 +313,7 @@ static int fsl_asrc_dma_startup(struct snd_soc_component *component, struct snd_pcm_substream *substream) { bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dmaengine_dai_dma_data *dma_data; struct device *dev = component->dev; diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 8b9027f76d8a..a447bafa00d2 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -116,13 +116,9 @@ static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int *item = ucontrol->value.enumerated.item; unsigned int reg_val, val, mix_clk; - int ret; /* Get current state */ - ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, ®_val); - if (ret) - return ret; - + reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR); mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK) >> FSL_AUDMIX_CTR_MIXCLK_SHIFT); val = snd_soc_enum_item_to_val(e, item[0]); @@ -162,9 +158,7 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol, int ret; /* Get current state */ - ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, ®_val); - if (ret) - return ret; + reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR); /* "From" state */ out_src = ((reg_val & FSL_AUDMIX_CTR_OUTSRC_MASK) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 13ae089c1911..be021250d6e9 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -200,7 +200,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) { struct fsl_dma_private *dma_private = dev_id; struct snd_pcm_substream *substream = dma_private->substream; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->dev; struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; irqreturn_t ret = IRQ_NONE; diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index c6b5eb2d2af7..60951a8aabd3 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -79,11 +79,8 @@ static int fsl_easrc_get_reg(struct snd_kcontrol *kcontrol, struct soc_mreg_control *mc = (struct soc_mreg_control *)kcontrol->private_value; unsigned int regval; - int ret; - ret = snd_soc_component_read(component, mc->regbase, ®val); - if (ret < 0) - return ret; + regval = snd_soc_component_read(component, mc->regbase); ucontrol->value.integer.value[0] = regval; @@ -179,22 +176,21 @@ static int fsl_easrc_set_rs_ratio(struct fsl_asrc_pair *ctx) struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; unsigned int in_rate = ctx_priv->in_params.norm_rate; unsigned int out_rate = ctx_priv->out_params.norm_rate; - unsigned int int_bits; unsigned int frac_bits; u64 val; u32 *r; switch (easrc_priv->rs_num_taps) { case EASRC_RS_32_TAPS: - int_bits = 5; + /* integer bits = 5; */ frac_bits = 39; break; case EASRC_RS_64_TAPS: - int_bits = 6; + /* integer bits = 6; */ frac_bits = 38; break; case EASRC_RS_128_TAPS: - int_bits = 7; + /* integer bits = 7; */ frac_bits = 37; break; default: @@ -390,11 +386,11 @@ static int fsl_easrc_resampler_config(struct fsl_asrc *easrc) * For input int[16, 24, 32] -> output float32 * scale it by multiplying filter coefficients by 2^-15, 2^-23, 2^-31 * input: - * asrc: Structure pointer of fsl_asrc - * infilter : Pointer to non-scaled input filter - * shift: The multiply factor + * @easrc: Structure pointer of fsl_asrc + * @infilter : Pointer to non-scaled input filter + * @shift: The multiply factor * output: - * outfilter: scaled filter + * @outfilter: scaled filter */ static int fsl_easrc_normalize_filter(struct fsl_asrc *easrc, u64 *infilter, @@ -964,7 +960,7 @@ static int fsl_easrc_release_slot(struct fsl_asrc *easrc, unsigned int ctx_id) * * Configure the register relate with context. */ -int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id) +static int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id) { struct fsl_easrc_ctx_priv *ctx_priv; struct fsl_asrc_pair *ctx; @@ -1125,15 +1121,15 @@ static int fsl_easrc_process_format(struct fsl_asrc_pair *ctx, return 0; } -int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, - snd_pcm_format_t *in_raw_format, - snd_pcm_format_t *out_raw_format) +static int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, + snd_pcm_format_t *in_raw_format, + snd_pcm_format_t *out_raw_format) { struct fsl_asrc *easrc = ctx->asrc; struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; struct fsl_easrc_data_fmt *in_fmt = &ctx_priv->in_params.fmt; struct fsl_easrc_data_fmt *out_fmt = &ctx_priv->out_params.fmt; - int ret; + int ret = 0; /* Get the bitfield values for input data format */ if (in_raw_format && out_raw_format) { @@ -1198,10 +1194,9 @@ int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, * to conform with this format. Interleaving parameters are accessed * through the ASRC_CTRL_IN_ACCESSa and ASRC_CTRL_OUT_ACCESSa registers */ -int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) +static int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) { struct fsl_easrc_ctx_priv *ctx_priv; - struct device *dev; struct fsl_asrc *easrc; if (!ctx) @@ -1209,7 +1204,6 @@ int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) easrc = ctx->asrc; ctx_priv = ctx->private; - dev = &easrc->pdev->dev; /* input interleaving parameters */ regmap_update_bits(easrc->regmap, REG_EASRC_CIA(ctx->index), @@ -1242,7 +1236,7 @@ int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) * Returns a negative number on error and >=0 as context id * on success */ -int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) +static int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) { enum asrc_pair_index index = ASRC_INVALID_PAIR; struct fsl_asrc *easrc = ctx->asrc; @@ -1287,17 +1281,15 @@ int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) * * This funciton is mainly doing the revert thing in request context */ -void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) +static void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) { unsigned long lock_flags; struct fsl_asrc *easrc; - struct device *dev; if (!ctx) return; easrc = ctx->asrc; - dev = &easrc->pdev->dev; spin_lock_irqsave(&easrc->lock, lock_flags); @@ -1314,7 +1306,7 @@ void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) * * Enable the DMA request and context */ -int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) +static int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) { struct fsl_asrc *easrc = ctx->asrc; @@ -1332,7 +1324,7 @@ int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) * * Disable the DMA request and context */ -int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) +static int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) { struct fsl_asrc *easrc = ctx->asrc; int val, i; @@ -1379,8 +1371,8 @@ int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) return 0; } -struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, - bool dir) +static struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, + bool dir) { struct fsl_asrc *easrc = ctx->asrc; enum asrc_pair_index index = ctx->index; @@ -1391,7 +1383,6 @@ struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, return dma_request_slave_channel(&easrc->pdev->dev, name); }; -EXPORT_SYMBOL_GPL(fsl_easrc_get_dma_channel); static const unsigned int easrc_rates[] = { 8000, 11025, 12000, 16000, diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index cbcb70d6f8c8..4ae36099ae82 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -22,8 +22,7 @@ SNDRV_PCM_FMTBIT_S24_LE) /** - * fsl_esai_soc_data: soc specific data - * + * struct fsl_esai_soc_data - soc specific data * @imx: for imx platform * @reset_at_xrun: flags for enable reset operaton */ @@ -33,8 +32,7 @@ struct fsl_esai_soc_data { }; /** - * fsl_esai: ESAI private data - * + * struct fsl_esai - ESAI private data * @dma_params_rx: DMA parameters for receive channel * @dma_params_tx: DMA parameters for transmit channel * @pdev: platform device pointer @@ -49,6 +47,8 @@ struct fsl_esai_soc_data { * @fifo_depth: depth of tx/rx FIFO * @slot_width: width of each DAI slot * @slots: number of slots + * @tx_mask: slot mask for TX + * @rx_mask: slot mask for RX * @channels: channel num for tx or rx * @hck_rate: clock rate of desired HCKx clock * @sck_rate: clock rate of desired SCKx clock @@ -157,13 +157,15 @@ static irqreturn_t esai_isr(int irq, void *devid) } /** - * This function is used to calculate the divisors of psr, pm, fp and it is - * supposed to be called in set_dai_sysclk() and set_bclk(). + * fsl_esai_divisor_cal - This function is used to calculate the + * divisors of psr, pm, fp and it is supposed to be called in + * set_dai_sysclk() and set_bclk(). * + * @dai: pointer to DAI + * @tx: current setting is for playback or capture * @ratio: desired overall ratio for the paticipating dividers * @usefp: for HCK setting, there is no need to set fp divider * @fp: bypass other dividers by setting fp directly if fp != 0 - * @tx: current setting is for playback or capture */ static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio, bool usefp, u32 fp) @@ -250,13 +252,12 @@ out_fp: } /** - * This function mainly configures the clock frequency of MCLK (HCKT/HCKR) - * - * @Parameters: - * clk_id: The clock source of HCKT/HCKR + * fsl_esai_set_dai_sysclk - configure the clock frequency of MCLK (HCKT/HCKR) + * @dai: pointer to DAI + * @clk_id: The clock source of HCKT/HCKR * (Input from outside; output from inside, FSYS or EXTAL) - * freq: The required clock rate of HCKT/HCKR - * dir: The clock direction of HCKT/HCKR + * @freq: The required clock rate of HCKT/HCKR + * @dir: The clock direction of HCKT/HCKR * * Note: If the direction is input, we do not care about clk_id. */ @@ -358,7 +359,10 @@ out: } /** - * This function configures the related dividers according to the bclk rate + * fsl_esai_set_bclk - configure the related dividers according to the bclk rate + * @dai: pointer to DAI + * @tx: direction boolean + * @freq: bclk freq */ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) { @@ -1008,7 +1012,7 @@ static int fsl_esai_probe(struct platform_device *pdev) if (irq < 0) return irq; - ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, esai_isr, IRQF_SHARED, esai_priv->name, esai_priv); if (ret) { dev_err(&pdev->dev, "failed to claim irq %u\n", irq); diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 9d436b0c5718..cdff739924e2 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -680,10 +680,11 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs), - FSL_SAI_CR1_RFW_MASK, + FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX); regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs), - FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1); + FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), + FSL_SAI_MAXBURST_RX - 1); snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx); @@ -1016,6 +1017,7 @@ static int fsl_sai_probe(struct platform_device *pdev) platform_set_drvdata(pdev, sai); pm_runtime_enable(&pdev->dev); + regcache_cache_only(sai->regmap, true); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, &fsl_sai_dai, 1); @@ -1107,7 +1109,6 @@ static int fsl_sai_runtime_suspend(struct device *dev) clk_disable_unprepare(sai->bus_clk); regcache_cache_only(sai->regmap, true); - regcache_mark_dirty(sai->regmap); return 0; } @@ -1137,6 +1138,7 @@ static int fsl_sai_runtime_resume(struct device *dev) } regcache_cache_only(sai->regmap, false); + regcache_mark_dirty(sai->regmap); regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); usleep_range(1000, 2000); diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 76b15deea80c..6aba7d28f5f3 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -94,7 +94,7 @@ #define FSL_SAI_CSR_FRDE BIT(0) /* SAI Transmit and Receive Configuration 1 Register */ -#define FSL_SAI_CR1_RFW_MASK 0x1f +#define FSL_SAI_CR1_RFW_MASK(x) ((x) - 1) /* SAI Transmit and Receive Configuration 2 Register */ #define FSL_SAI_CR2_SYNC BIT(30) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 1b2e516f9162..455f96908377 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -16,6 +16,7 @@ #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/regmap.h> +#include <linux/pm_runtime.h> #include <sound/asoundef.h> #include <sound/dmaengine_pcm.h> @@ -42,6 +43,18 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; #define DEFAULT_RXCLK_SRC 1 +/** + * struct fsl_spdif_soc_data: soc specific data + * + * @imx: for imx platform + * @shared_root_clock: flag of sharing a clock source with others; + * so the driver shouldn't set root clock rate + */ +struct fsl_spdif_soc_data { + bool imx; + bool shared_root_clock; +}; + /* * SPDIF control structure * Defines channel status, subcode and Q sub @@ -68,8 +81,8 @@ struct spdif_mixer_control { }; /** - * fsl_spdif_priv: Freescale SPDIF private data - * + * struct fsl_spdif_priv - Freescale SPDIF private data + * @soc: SPDIF soc data * @fsl_spdif_control: SPDIF control data * @cpu_dai_drv: cpu dai driver * @pdev: platform device pointer @@ -87,8 +100,10 @@ struct spdif_mixer_control { * @spbaclk: SPBA clock (optional, depending on SoC design) * @dma_params_tx: DMA parameters for transmit channel * @dma_params_rx: DMA parameters for receive channel + * @regcache_srpc: regcache for SRPC */ struct fsl_spdif_priv { + const struct fsl_spdif_soc_data *soc; struct spdif_mixer_control fsl_spdif_control; struct snd_soc_dai_driver cpu_dai_drv; struct platform_device *pdev; @@ -110,6 +125,27 @@ struct fsl_spdif_priv { u32 regcache_srpc; }; +static struct fsl_spdif_soc_data fsl_spdif_vf610 = { + .imx = false, + .shared_root_clock = false, +}; + +static struct fsl_spdif_soc_data fsl_spdif_imx35 = { + .imx = true, + .shared_root_clock = false, +}; + +static struct fsl_spdif_soc_data fsl_spdif_imx6sx = { + .imx = true, + .shared_root_clock = true, +}; + +/* Check if clk is a root clock that does not share clock source with others */ +static inline bool fsl_spdif_can_set_clk_rate(struct fsl_spdif_priv *spdif, int clk) +{ + return (clk == STC_TXCLK_SPDIF_ROOT) && !spdif->soc->shared_root_clock; +} + /* DPLL locked and lock loss interrupt handler */ static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) { @@ -369,7 +405,7 @@ static int spdif_set_rx_clksrc(struct fsl_spdif_priv *spdif_priv, static int spdif_set_sample_rate(struct snd_pcm_substream *substream, int sample_rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; struct regmap *regmap = spdif_priv->regmap; @@ -420,8 +456,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, sysclk_df = spdif_priv->sysclk_df[rate]; - /* Don't mess up the clocks from other modules */ - if (clk != STC_TXCLK_SPDIF_ROOT) + if (!fsl_spdif_can_set_clk_rate(spdif_priv, clk)) goto clk_set_bypass; /* The S/PDIF block needs a clock of 64 * fs * txclk_df */ @@ -457,34 +492,19 @@ clk_set_bypass: static int fsl_spdif_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct platform_device *pdev = spdif_priv->pdev; struct regmap *regmap = spdif_priv->regmap; u32 scr, mask; - int i; int ret; /* Reset module and interrupts only for first initialization */ if (!snd_soc_dai_active(cpu_dai)) { - ret = clk_prepare_enable(spdif_priv->coreclk); - if (ret) { - dev_err(&pdev->dev, "failed to enable core clock\n"); - return ret; - } - - if (!IS_ERR(spdif_priv->spbaclk)) { - ret = clk_prepare_enable(spdif_priv->spbaclk); - if (ret) { - dev_err(&pdev->dev, "failed to enable spba clock\n"); - goto err_spbaclk; - } - } - ret = spdif_softreset(spdif_priv); if (ret) { dev_err(&pdev->dev, "failed to soft reset\n"); - goto err; + return ret; } /* Disable all the interrupts */ @@ -498,18 +518,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | SCR_TXFIFO_FSEL_MASK; - for (i = 0; i < SPDIF_TXRATE_MAX; i++) { - ret = clk_prepare_enable(spdif_priv->txclk[i]); - if (ret) - goto disable_txclk; - } } else { scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC; mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; - ret = clk_prepare_enable(spdif_priv->rxclk); - if (ret) - goto err; } regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); @@ -517,39 +529,25 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, 0); return 0; - -disable_txclk: - for (i--; i >= 0; i--) - clk_disable_unprepare(spdif_priv->txclk[i]); -err: - if (!IS_ERR(spdif_priv->spbaclk)) - clk_disable_unprepare(spdif_priv->spbaclk); -err_spbaclk: - clk_disable_unprepare(spdif_priv->coreclk); - - return ret; } static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct regmap *regmap = spdif_priv->regmap; - u32 scr, mask, i; + u32 scr, mask; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { scr = 0; mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | SCR_TXFIFO_FSEL_MASK; - for (i = 0; i < SPDIF_TXRATE_MAX; i++) - clk_disable_unprepare(spdif_priv->txclk[i]); } else { scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO; mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; - clk_disable_unprepare(spdif_priv->rxclk); } regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); @@ -558,9 +556,6 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, spdif_intr_status_clear(spdif_priv); regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, SCR_LOW_POWER); - if (!IS_ERR(spdif_priv->spbaclk)) - clk_disable_unprepare(spdif_priv->spbaclk); - clk_disable_unprepare(spdif_priv->coreclk); } } @@ -568,7 +563,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; struct platform_device *pdev = spdif_priv->pdev; @@ -596,7 +591,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, static int fsl_spdif_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct regmap *regmap = spdif_priv->regmap; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; @@ -781,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); @@ -796,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) @@ -953,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_vbit_get, + .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_tx_vbit_get, + .put = fsl_spdif_tx_vbit_put, }, /* DPLL lock info get controller */ { @@ -990,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; } @@ -1186,7 +1224,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, continue; ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index, - i == STC_TXCLK_SPDIF_ROOT); + fsl_spdif_can_set_clk_rate(spdif_priv, i)); if (savesub == ret) continue; @@ -1230,6 +1268,12 @@ static int fsl_spdif_probe(struct platform_device *pdev) spdif_priv->pdev = pdev; + spdif_priv->soc = of_device_get_match_data(&pdev->dev); + if (!spdif_priv->soc) { + dev_err(&pdev->dev, "failed to get soc data\n"); + return -ENODEV; + } + /* Initialize this copy of the CPU DAI driver structure */ memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev); @@ -1311,6 +1355,8 @@ static int fsl_spdif_probe(struct platform_device *pdev) /* Register with ASoC */ dev_set_drvdata(&pdev->dev, spdif_priv); + pm_runtime_enable(&pdev->dev); + regcache_cache_only(spdif_priv->regmap, true); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component, &spdif_priv->cpu_dai_drv, 1); @@ -1326,41 +1372,96 @@ static int fsl_spdif_probe(struct platform_device *pdev) return ret; } -#ifdef CONFIG_PM_SLEEP -static int fsl_spdif_suspend(struct device *dev) +#ifdef CONFIG_PM +static int fsl_spdif_runtime_suspend(struct device *dev) { struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev); + int i; regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC, &spdif_priv->regcache_srpc); - regcache_cache_only(spdif_priv->regmap, true); - regcache_mark_dirty(spdif_priv->regmap); + + clk_disable_unprepare(spdif_priv->rxclk); + + for (i = 0; i < SPDIF_TXRATE_MAX; i++) + clk_disable_unprepare(spdif_priv->txclk[i]); + + if (!IS_ERR(spdif_priv->spbaclk)) + clk_disable_unprepare(spdif_priv->spbaclk); + clk_disable_unprepare(spdif_priv->coreclk); return 0; } -static int fsl_spdif_resume(struct device *dev) +static int fsl_spdif_runtime_resume(struct device *dev) { struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev); + int ret; + int i; + + ret = clk_prepare_enable(spdif_priv->coreclk); + if (ret) { + dev_err(dev, "failed to enable core clock\n"); + return ret; + } + + if (!IS_ERR(spdif_priv->spbaclk)) { + ret = clk_prepare_enable(spdif_priv->spbaclk); + if (ret) { + dev_err(dev, "failed to enable spba clock\n"); + goto disable_core_clk; + } + } + + for (i = 0; i < SPDIF_TXRATE_MAX; i++) { + ret = clk_prepare_enable(spdif_priv->txclk[i]); + if (ret) + goto disable_tx_clk; + } + + ret = clk_prepare_enable(spdif_priv->rxclk); + if (ret) + goto disable_tx_clk; regcache_cache_only(spdif_priv->regmap, false); + regcache_mark_dirty(spdif_priv->regmap); regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SRPC, SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK, spdif_priv->regcache_srpc); - return regcache_sync(spdif_priv->regmap); + ret = regcache_sync(spdif_priv->regmap); + if (ret) + goto disable_rx_clk; + + return 0; + +disable_rx_clk: + clk_disable_unprepare(spdif_priv->rxclk); +disable_tx_clk: + for (i--; i >= 0; i--) + clk_disable_unprepare(spdif_priv->txclk[i]); + if (!IS_ERR(spdif_priv->spbaclk)) + clk_disable_unprepare(spdif_priv->spbaclk); +disable_core_clk: + clk_disable_unprepare(spdif_priv->coreclk); + + return ret; } -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_spdif_pm = { - SET_SYSTEM_SLEEP_PM_OPS(fsl_spdif_suspend, fsl_spdif_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(fsl_spdif_runtime_suspend, fsl_spdif_runtime_resume, + NULL) }; static const struct of_device_id fsl_spdif_dt_ids[] = { - { .compatible = "fsl,imx35-spdif", }, - { .compatible = "fsl,vf610-spdif", }, + { .compatible = "fsl,imx35-spdif", .data = &fsl_spdif_imx35, }, + { .compatible = "fsl,vf610-spdif", .data = &fsl_spdif_vf610, }, + { .compatible = "fsl,imx6sx-spdif", .data = &fsl_spdif_imx6sx, }, {} }; MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 1a2fa7f18142..d8b9c6547142 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -203,12 +203,10 @@ struct fsl_ssi_soc_data { }; /** - * fsl_ssi: per-SSI private data - * + * struct fsl_ssi - per-SSI private data * @regs: Pointer to the regmap registers * @irq: IRQ of this SSI * @cpu_dai_drv: CPU DAI driver for this device - * * @dai_fmt: DAI configuration this device is currently used with * @streams: Mask of current active streams: BIT(TX) and BIT(RX) * @i2s_net: I2S and Network mode configurations of SCR register @@ -221,38 +219,29 @@ struct fsl_ssi_soc_data { * @slot_width: Width of each DAI slot * @slots: Number of slots * @regvals: Specific RX/TX register settings - * * @clk: Clock source to access register * @baudclk: Clock source to generate bit and frame-sync clocks * @baudclk_streams: Active streams that are using baudclk - * * @regcache_sfcsr: Cache sfcsr register value during suspend and resume * @regcache_sacnt: Cache sacnt register value during suspend and resume - * * @dma_params_tx: DMA transmit parameters * @dma_params_rx: DMA receive parameters * @ssi_phys: physical address of the SSI registers - * * @fiq_params: FIQ stream filtering parameters - * * @card_pdev: Platform_device pointer to register a sound card for PowerPC or * to register a CODEC platform device for AC97 * @card_name: Platform_device name to register a sound card for PowerPC or * to register a CODEC platform device for AC97 * @card_idx: The index of SSI to register a sound card for PowerPC or * to register a CODEC platform device for AC97 - * * @dbg_stats: Debugging statistics - * * @soc: SoC specific data * @dev: Pointer to &pdev->dev - * * @fifo_watermark: The FIFO watermark setting. Notifies DMA when there are * @fifo_watermark or fewer words in TX fifo or * @fifo_watermark or more empty words in RX fifo. * @dma_maxburst: Max number of words to transfer in one go. So far, * this is always the same as fifo_watermark. - * * @ac97_reg_lock: Mutex lock to serialize AC97 register access operations */ struct fsl_ssi { @@ -374,7 +363,9 @@ static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi *ssi) } /** - * Interrupt handler to gather states + * fsl_ssi_irq - Interrupt handler to gather states + * @irq: irq number + * @dev_id: context */ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) { @@ -395,7 +386,10 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) } /** - * Set SCR, SIER, STCR and SRCR registers with cached values in regvals + * fsl_ssi_config_enable - Set SCR, SIER, STCR and SRCR registers with + * cached values in regvals + * @ssi: SSI context + * @tx: direction * * Notes: * 1) For offline_config SoCs, enable all necessary bits of both streams @@ -474,7 +468,7 @@ enable_scr: ssi->streams |= BIT(dir); } -/** +/* * Exclude bits that are used by the opposite stream * * When both streams are active, disabling some bits for the current stream @@ -495,7 +489,10 @@ enable_scr: ((vals) & _ssi_xor_shared_bits(vals, avals, aactive)) /** - * Unset SCR, SIER, STCR and SRCR registers with cached values in regvals + * fsl_ssi_config_disable - Unset SCR, SIER, STCR and SRCR registers + * with cached values in regvals + * @ssi: SSI context + * @tx: direction * * Notes: * 1) For offline_config SoCs, to avoid online reconfigurations, disable all @@ -577,7 +574,9 @@ static void fsl_ssi_tx_ac97_saccst_setup(struct fsl_ssi *ssi) } /** - * Cache critical bits of SIER, SRCR, STCR and SCR to later set them safely + * fsl_ssi_setup_regvals - Cache critical bits of SIER, SRCR, STCR and + * SCR to later set them safely + * @ssi: SSI context */ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi) { @@ -630,7 +629,7 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi) static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); int ret; @@ -654,16 +653,19 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); clk_disable_unprepare(ssi->clk); } /** - * Configure Digital Audio Interface bit clock + * fsl_ssi_set_bclk - Configure Digital Audio Interface bit clock + * @substream: ASoC substream + * @dai: pointer to DAI + * @hw_params: pointers to hw_params * - * Note: This function can be only called when using SSI as DAI master + * Notes: This function can be only called when using SSI as DAI master * * Quick instruction for parameters: * freq: Output BCLK frequency = samplerate * slots * slot_width @@ -782,7 +784,10 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, } /** - * Configure SSI based on PCM hardware parameters + * fsl_ssi_hw_params - Configure SSI based on PCM hardware parameters + * @substream: ASoC substream + * @hw_params: pointers to hw_params + * @dai: pointer to DAI * * Notes: * 1) SxCCR.WL bits are critical bits that require SSI to be temporarily @@ -858,7 +863,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, static int fsl_ssi_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); if (fsl_ssi_is_i2s_master(ssi) && @@ -997,7 +1002,9 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) } /** - * Configure Digital Audio Interface (DAI) Format + * fsl_ssi_set_dai_fmt - Configure Digital Audio Interface (DAI) Format + * @dai: pointer to DAI + * @fmt: format mask */ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { @@ -1011,7 +1018,12 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } /** - * Set TDM slot number and slot width + * fsl_ssi_set_dai_tdm_slot - Set TDM slot number and slot width + * @dai: pointer to DAI + * @tx_mask: mask for TX + * @rx_mask: mask for RX + * @slots: number of slots + * @slot_width: number of bits per slot */ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask, int slots, int slot_width) @@ -1055,7 +1067,10 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, } /** - * Start or stop SSI and corresponding DMA transaction. + * fsl_ssi_trigger - Start or stop SSI and corresponding DMA transaction. + * @substream: ASoC substream + * @cmd: trigger command + * @dai: pointer to DAI * * The DMA channel is in external master start and pause mode, which * means the SSI completely controls the flow of data. @@ -1063,7 +1078,7 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; @@ -1239,7 +1254,8 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = { }; /** - * Initialize SSI registers + * fsl_ssi_hw_init - Initialize SSI registers + * @ssi: SSI context */ static int fsl_ssi_hw_init(struct fsl_ssi *ssi) { @@ -1268,7 +1284,8 @@ static int fsl_ssi_hw_init(struct fsl_ssi *ssi) } /** - * Clear SSI registers + * fsl_ssi_hw_clean - Clear SSI registers + * @ssi: SSI context */ static void fsl_ssi_hw_clean(struct fsl_ssi *ssi) { @@ -1285,7 +1302,8 @@ static void fsl_ssi_hw_clean(struct fsl_ssi *ssi) regmap_update_bits(ssi->regs, REG_SSI_SCR, SSI_SCR_SSIEN, 0); } } -/** + +/* * Make every character in a string lower-case */ static void make_lowercase(char *s) diff --git a/sound/soc/fsl/fsl_ssi_dbg.c b/sound/soc/fsl/fsl_ssi_dbg.c index 2a20ee23dc52..2c46c55f0a88 100644 --- a/sound/soc/fsl/fsl_ssi_dbg.c +++ b/sound/soc/fsl/fsl_ssi_dbg.c @@ -78,7 +78,7 @@ void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *dbg, u32 sisr) dbg->stats.tfe0++; } -/** +/* * Show the statistics of a flag only if its interrupt is enabled * * Compilers will optimize it to a no-op if the interrupt is disabled @@ -90,7 +90,7 @@ void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *dbg, u32 sisr) } while (0) -/** +/* * Display the statistics for the current SSI device * * To avoid confusion, only show those counts that are enabled diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index e09b45de0efd..202fb8950078 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -6,8 +6,8 @@ * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * https://www.opensource.org/licenses/gpl-license.html + * https://www.gnu.org/copyleft/gpl.html */ #include <linux/module.h> @@ -44,7 +44,7 @@ static const struct snd_pcm_hw_constraint_list imx_audmix_rate_constraints = { static int imx_audmix_fe_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct imx_audmix *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_pcm_runtime *runtime = substream->runtime; struct device *dev = rtd->card->dev; @@ -73,7 +73,7 @@ static int imx_audmix_fe_startup(struct snd_pcm_substream *substream) static int imx_audmix_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->card->dev; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF; @@ -112,7 +112,7 @@ static int imx_audmix_fe_hw_params(struct snd_pcm_substream *substream, static int imx_audmix_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->card->dev; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF; diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 3ce85a43e08f..25c18b9e348f 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -5,7 +5,7 @@ // Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> // // Initial development of this code was funded by -// Phytec Messtechnik GmbH, http://www.phytec.de +// Phytec Messtechnik GmbH, https://www.phytec.de #include <linux/clk.h> #include <linux/debugfs.h> diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index fab2d6c56653..dd9c1ac81cf5 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c @@ -26,7 +26,7 @@ static int imx_mc13783_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 3b8c796d7829..9e4f66b6b92b 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -114,7 +114,7 @@ static int psc_dma_hw_free(struct snd_soc_component *component, static int psc_dma_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct snd_pcm_runtime *runtime = substream->runtime; struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); @@ -216,7 +216,7 @@ static int psc_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct psc_dma_stream *s; int rc; @@ -244,7 +244,7 @@ static int psc_dma_open(struct snd_soc_component *component, static int psc_dma_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct psc_dma_stream *s; @@ -270,7 +270,7 @@ static snd_pcm_uframes_t psc_dma_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct psc_dma_stream *s; dma_addr_t count; diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 1ab4fbda08cb..3149d59ae968 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -38,7 +38,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); u32 mode; diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index f7bd90051ce7..eccc833390d4 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -98,7 +98,7 @@ static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card) */ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mpc8610_hpcd_data *machine_data = container_of(rtd->card, struct mpc8610_hpcd_data, card); struct device *dev = rtd->card->dev; @@ -426,9 +426,11 @@ static int __init mpc8610_hpcd_init(void) guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); if (of_address_to_resource(guts_np, 0, &res)) { pr_err("mpc8610-hpcd: missing/invalid global utilities node\n"); + of_node_put(guts_np); return -EINVAL; } guts_phys = res.start; + of_node_put(guts_np); return platform_driver_register(&mpc8610_hpcd_driver); } diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index a36d4e8cd55c..4ead537e090a 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c @@ -36,7 +36,7 @@ static int mx27vis_amp_muter_gpio; static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index fe3091590f20..ac68d2238045 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -121,7 +121,7 @@ static int p1022_ds_machine_probe(struct snd_soc_card *card) */ static int p1022_ds_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct machine_data *mdata = container_of(rtd->card, struct machine_data, card); struct device *dev = rtd->card->dev; diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c index f5374fe354ab..714515b8081f 100644 --- a/sound/soc/fsl/p1022_rdk.c +++ b/sound/soc/fsl/p1022_rdk.c @@ -127,7 +127,7 @@ static int p1022_rdk_machine_probe(struct snd_soc_card *card) */ static int p1022_rdk_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct machine_data *mdata = container_of(rtd->card, struct machine_data, card); struct device *dev = rtd->card->dev; diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index 8b1551c55452..99611a037ada 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c @@ -75,7 +75,7 @@ static const struct _wm8350_audio wm8350_audio[] = { static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, found = 0; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 8c54dc6710fe..6cada4c1e283 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -193,7 +193,7 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_clk); int asoc_simple_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); int ret; @@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(asoc_simple_startup); void asoc_simple_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); @@ -248,7 +248,7 @@ static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai, int asoc_simple_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); @@ -540,7 +540,8 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches); int asoc_simple_init_jack(struct snd_soc_card *card, struct asoc_simple_jack *sjack, - int is_hp, char *prefix) + int is_hp, char *prefix, + char *pin) { struct device *dev = card->dev; enum of_gpio_flags flags; @@ -557,12 +558,12 @@ int asoc_simple_init_jack(struct snd_soc_card *card, if (is_hp) { snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix); - pin_name = "Headphones"; + pin_name = pin ? pin : "Headphones"; gpio_name = "Headphone detection"; mask = SND_JACK_HEADPHONE; } else { snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix); - pin_name = "Mic Jack"; + pin_name = pin ? pin : "Mic Jack"; gpio_name = "Mic detection"; mask = SND_JACK_MICROPHONE; } diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index e30b66b94bf6..0843235d73c9 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -343,8 +343,10 @@ static int img_i2s_in_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) chan_control_mask = IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK; ret = pm_runtime_get_sync(i2s->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(i2s->dev); return ret; + } for (i = 0; i < i2s->active_channels; i++) img_i2s_in_ch_disable(i2s, i); diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c index 5ddbe3a31c2e..4da49a42e854 100644 --- a/sound/soc/img/img-parallel-out.c +++ b/sound/soc/img/img-parallel-out.c @@ -163,8 +163,10 @@ static int img_prl_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } ret = pm_runtime_get_sync(prl->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(prl->dev); return ret; + } reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL); reg = (reg & ~IMG_PRL_OUT_CTL_EDGE_MASK) | control_set; diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 36f547939f0a..82805a8681e5 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -240,6 +240,13 @@ config SND_SOC_ACPI_INTEL_MATCH endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL +config SND_SOC_INTEL_KEEMBAY + tristate "Keembay Platforms" + depends on ARM64 || COMPILE_TEST + depends on COMMON_CLK + help + If you have a Intel Keembay platform then enable this option + by saying Y or m. # ASoC codec drivers source "sound/soc/intel/boards/Kconfig" diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index e16d6dc4d4e6..04ee48204fc9 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/ obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/ +obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += keembay/ # Machine support obj-$(CONFIG_SND_SOC) += boards/ diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 69f3af4524ab..ff42f629b035 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -61,8 +61,13 @@ static int sst_fill_and_send_cmd_unlocked(struct sst_data *drv, /** * sst_fill_and_send_cmd - generate the IPC message and send it to the FW - * @ipc_msg: type of IPC (CMD, SET_PARAMS, GET_PARAMS) - * @cmd_data: the IPC payload + * @drv: sst_data + * @ipc_msg: type of IPC (CMD, SET_PARAMS, GET_PARAMS) + * @block: block index + * @task_id: task index + * @pipe_id: pipe index + * @cmd_data: the IPC payload + * @len: length of data to be sent */ static int sst_fill_and_send_cmd(struct sst_data *drv, u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id, @@ -78,7 +83,7 @@ static int sst_fill_and_send_cmd(struct sst_data *drv, return ret; } -/** +/* * tx map value is a bitfield where each bit represents a FW channel * * 3 2 1 0 # 0 = codec0, 1 = codec1 @@ -90,7 +95,7 @@ static u8 sst_ssp_tx_map[SST_MAX_TDM_SLOTS] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default rx map */ }; -/** +/* * rx map value is a bitfield where each bit represents a slot * * 76543210 # 0 = slot 0, 1 = slot 1 @@ -101,7 +106,7 @@ static u8 sst_ssp_rx_map[SST_MAX_TDM_SLOTS] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default tx map */ }; -/** +/* * NOTE: this is invoked with lock held */ static int sst_send_slot_map(struct sst_data *drv) @@ -145,7 +150,8 @@ static int sst_slot_enum_info(struct snd_kcontrol *kcontrol, /** * sst_slot_get - get the status of the interleaver/deinterleaver control - * + * @kcontrol: control pointer + * @ucontrol: User data * Searches the map where the control status is stored, and gets the * channel/slot which is currently set for this enumerated control. Since it is * an enumerated control, there is only one possible value. @@ -197,7 +203,8 @@ static int sst_check_and_send_slot_map(struct sst_data *drv, struct snd_kcontrol /** * sst_slot_put - set the status of interleaver/deinterleaver control - * + * @kcontrol: control pointer + * @ucontrol: User data * (de)interleaver controls are defined in opposite sense to be user-friendly * * Instead of the enum value being the value written to the register, it is the @@ -280,7 +287,9 @@ static int sst_send_algo_cmd(struct sst_data *drv, /** * sst_find_and_send_pipe_algo - send all the algo parameters for a pipe - * + * @drv: sst_data + * @pipe: string identifier + * @ids: list of algorithms * The algos which are in each pipeline are sent to the firmware one by one * * Called with lock held @@ -379,11 +388,15 @@ static int sst_gain_ctl_info(struct snd_kcontrol *kcontrol, /** * sst_send_gain_cmd - send the gain algorithm IPC to the FW - * @gv: the stored value of gain (also contains rampduration) - * @mute: flag that indicates whether this was called from the - * digital_mute callback or directly. If called from the - * digital_mute callback, module will be muted/unmuted based on this - * flag. The flag is always 0 if called directly. + * @drv: sst_data + * @gv:the stored value of gain (also contains rampduration) + * @task_id: task index + * @loc_id: location/position index + * @module_id: module index + * @mute: flag that indicates whether this was called from the + * digital_mute callback or directly. If called from the + * digital_mute callback, module will be muted/unmuted based on this + * flag. The flag is always 0 if called directly. * * Called with sst_data.lock held * @@ -544,9 +557,12 @@ static const uint swm_mixer_input_ids[SST_SWM_INPUT_COUNT] = { /** * fill_swm_input - fill in the SWM input ids given the register + * @cmpnt: ASoC component + * @swm_input: array of swm_input_ids + * @reg: the register value is a bit-field inicated which mixer inputs are ON. * - * The register value is a bit-field inicated which mixer inputs are ON. Use the - * lookup table to get the input-id and fill it in the structure. + * Use the lookup table to get the input-id and fill it in the + * structure. */ static int fill_swm_input(struct snd_soc_component *cmpnt, struct swm_input_ids *swm_input, unsigned int reg) @@ -577,7 +593,7 @@ static int fill_swm_input(struct snd_soc_component *cmpnt, } -/** +/* * called with lock held */ static int sst_set_pipe_gain(struct sst_ids *ids, @@ -707,7 +723,7 @@ SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm2_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_sprot_l0_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l1_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls); -SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_voip_controls); +SST_SBA_DECLARE_MIX_CONTROLS(__maybe_unused sst_mix_voip_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_modem_controls); @@ -881,7 +897,7 @@ int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -/** +/* * sst_ssp_config - contains SSP configuration for media UC * this can be overwritten by set_dai_xxx APIs */ @@ -1300,6 +1316,9 @@ static bool is_sst_dapm_widget(struct snd_soc_dapm_widget *w) /** * sst_send_pipe_gains - send gains for the front-end DAIs + * @dai: front-end dai + * @stream: direction + * @mute: boolean indicating mute status * * The gains in the pipes connected to the front-ends are muted/unmuted * automatically via the digital_mute() DAPM callback. This function sends the @@ -1357,7 +1376,9 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) /** * sst_fill_module_list - populate the list of modules/gains for a pipe - * + * @kctl: kcontrol pointer + * @w: dapm widget + * @type: widget type * * Fills the widget pointer in the kcontrol private data, and also fills the * kcontrol pointer in the widget private data. @@ -1403,7 +1424,8 @@ static int sst_fill_module_list(struct snd_kcontrol *kctl, /** * sst_fill_widget_module_info - fill list of gains/algos for the pipe - * @widget: pipe modelled as a DAPM widget + * @w: pipe modeled as a DAPM widget + * @component: ASoC component * * Fill the list of gains/algos for the widget by looking at all the card * controls and comparing the name of the widget with the first part of control @@ -1463,6 +1485,8 @@ static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w, /** * sst_fill_linked_widgets - fill the parent pointer for the linked widget + * @component: ASoC component + * @ids: sst_ids array */ static void sst_fill_linked_widgets(struct snd_soc_component *component, struct sst_ids *ids) @@ -1480,6 +1504,7 @@ static void sst_fill_linked_widgets(struct snd_soc_component *component, /** * sst_map_modules_to_pipe - fill algo/gains list for all pipes + * @component: ASoC component */ static int sst_map_modules_to_pipe(struct snd_soc_component *component) { diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 8817eaae6bb7..49b9f18472bc 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -274,7 +274,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) { struct sst_runtime_stream *stream = substream->runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret_val; dev_dbg(rtd->dev, "setting buffer ptr param\n"); @@ -582,7 +582,7 @@ static int sst_soc_trigger(struct snd_soc_component *component, int ret_val = 0, str_id; struct sst_runtime_stream *stream; int status; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); dev_dbg(rtd->dev, "%s called\n", __func__); if (substream->pcm->internal) @@ -630,7 +630,7 @@ static snd_pcm_uframes_t sst_soc_pointer(struct snd_soc_component *component, struct sst_runtime_stream *stream; int ret_val, status; struct pcm_stream_info *str_info; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); stream = substream->runtime->private_data; status = sst_get_stream_status(stream); diff --git a/sound/soc/intel/atom/sst/sst_loader.c b/sound/soc/intel/atom/sst/sst_loader.c index 9b0e3739c738..fc91a304256b 100644 --- a/sound/soc/intel/atom/sst/sst_loader.c +++ b/sound/soc/intel/atom/sst/sst_loader.c @@ -49,6 +49,7 @@ void memcpy32_fromio(void *dst, const void __iomem *src, int count) /** * intel_sst_reset_dsp_mrfld - Resetting SST DSP + * @sst_drv_ctx: intel_sst_drv context pointer * * This resets DSP in case of MRFLD platfroms */ @@ -77,6 +78,7 @@ int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx) /** * sst_start_merrifield - Start the SST DSP processor + * @sst_drv_ctx: intel_sst_drv context pointer * * This starts the DSP in MERRIFIELD platfroms */ @@ -274,12 +276,10 @@ void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx) struct sst_memcpy_list *listnode, *tmplistnode; /* Free the list */ - if (!list_empty(&sst_drv_ctx->memcpy_list)) { - list_for_each_entry_safe(listnode, tmplistnode, - &sst_drv_ctx->memcpy_list, memcpylist) { - list_del(&listnode->memcpylist); - kfree(listnode); - } + list_for_each_entry_safe(listnode, tmplistnode, + &sst_drv_ctx->memcpy_list, memcpylist) { + list_del(&listnode->memcpylist); + kfree(listnode); } } @@ -387,6 +387,8 @@ void sst_post_download_mrfld(struct intel_sst_drv *ctx) /** * sst_load_fw - function to load FW into DSP + * @sst_drv_ctx: intel_sst_drv context pointer + * * Transfers the FW to DSP using dma/memcpy */ int sst_load_fw(struct intel_sst_drv *sst_drv_ctx) diff --git a/sound/soc/intel/atom/sst/sst_stream.c b/sound/soc/intel/atom/sst/sst_stream.c index ea09f4170201..c0221e103e79 100644 --- a/sound/soc/intel/atom/sst/sst_stream.c +++ b/sound/soc/intel/atom/sst/sst_stream.c @@ -92,8 +92,8 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params) /** * sst_realloc_stream - Send msg for (re-)allocating a stream using the - * @sst_drv_ctx intel_sst_drv context pointer - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * Send a msg for (re-)allocating a stream using the parameters previously * passed to sst_alloc_stream_mrfld() for the same stream ID. @@ -142,12 +142,13 @@ out: } /** -* sst_start_stream - Send msg for a starting stream -* @str_id: stream ID -* -* This function is called by any function which wants to start -* a stream. -*/ + * sst_start_stream - Send msg for a starting stream + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID + * + * This function is called by any function which wants to start + * a stream. + */ int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) { int retval = 0; @@ -234,7 +235,8 @@ out: /** * sst_pause_stream - Send msg for a pausing stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to pause * an already running stream. @@ -278,7 +280,8 @@ int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) /** * sst_resume_stream - Send msg for resuming stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to resume * an already paused stream. @@ -345,7 +348,8 @@ int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) /** * sst_drop_stream - Send msg for stopping stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to stop * a stream. @@ -377,12 +381,14 @@ int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) } /** -* sst_drain_stream - Send msg for draining stream -* @str_id: stream ID -* -* This function is called by any function which wants to drain -* a stream. -*/ + * sst_drain_stream - Send msg for draining stream + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID + * @partial_drain: boolean indicating if a gapless transition is taking place + * + * This function is called by any function which wants to drain + * a stream. + */ int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx, int str_id, bool partial_drain) { @@ -415,7 +421,8 @@ int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx, /** * sst_free_stream - Frees a stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to free * a stream. diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c index 53383055c8dc..54a66cc6db89 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c +++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c @@ -62,7 +62,7 @@ static int sst_byt_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -121,7 +121,7 @@ static int sst_byt_pcm_hw_params(struct snd_soc_component *component, static int sst_byt_pcm_restore_stream_context(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; @@ -155,7 +155,7 @@ static void sst_byt_pcm_work(struct work_struct *work) static int sst_byt_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -197,7 +197,7 @@ static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) struct sst_byt_pcm_data *pcm_data = data; struct snd_pcm_substream *substream = pcm_data->substream; struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt *byt = pdata->byt; @@ -219,7 +219,7 @@ static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; @@ -232,7 +232,7 @@ static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_soc_component *component static int sst_byt_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -260,7 +260,7 @@ static int sst_byt_pcm_open(struct snd_soc_component *component, static int sst_byt_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -286,7 +286,7 @@ static int sst_byt_pcm_mmap(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct vm_area_struct *vma) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); dev_dbg(rtd->dev, "PCM: mmap\n"); return snd_pcm_lib_default_mmap(substream, vma); diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 5dc489a79454..d96fc1313434 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -288,6 +288,7 @@ config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC tristate select SND_SOC_DA7219 select SND_SOC_MAX98357A + select SND_SOC_MAX98390 select SND_SOC_DMIC select SND_SOC_HDAC_HDMI @@ -298,14 +299,14 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON if SND_SOC_INTEL_APL config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH - tristate "Broxton with DA7219 and MAX98357A in I2S Mode" + tristate "Broxton with DA7219 and MAX98357A/MAX98390 in I2S Mode" depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON help This adds support for ASoC machine driver for Broxton-P platforms - with DA7219 + MAX98357A I2S audio codec. + with DA7219 + MAX98357A/MAX98390 I2S audio codec. Say Y or m if you have such a device. This is a recommended option. If unsure select "N". @@ -389,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 @@ -466,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 @@ -530,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 @@ -564,6 +565,8 @@ 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 select SND_SOC_RT1308_SDW @@ -573,7 +576,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_DMIC help Add support for Intel SoundWire-based platforms connected to - RT700, RT711, RT1308 and RT715 + MAX98373, RT700, RT711, RT1308 and RT715 If unsure select "N". endif diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 15684610f8c6..dc04acb911b6 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -34,9 +34,11 @@ snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o hda_dsp_common.o snd-soc-ehl-rt5660-objs := ehl_rt5660.o hda_dsp_common.o snd-soc-sof-sdw-objs += sof_sdw.o \ + sof_sdw_max98373.o \ sof_sdw_rt711.o sof_sdw_rt700.o \ sof_sdw_rt1308.o sof_sdw_rt715.o \ sof_sdw_rt5682.o \ + sof_maxim_common.o \ sof_sdw_dmic.o sof_sdw_hdmi.o hda_dsp_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index a97e912adf4b..ce7320916b22 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -106,7 +106,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int bdw_rt5650_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -297,9 +297,19 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bdw rt5650" /* card name will be 'sof-bdw rt5650' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bdw-rt5650" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* ASoC machine driver for Broadwell DSP + RT5650 */ static struct snd_soc_card bdw_rt5650_card = { - .name = "bdw-rt5650", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = bdw_rt5650_dais, .num_links = ARRAY_SIZE(bdw_rt5650_dais), diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index bed4d5f73d9c..86e427e3822f 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -156,7 +156,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -173,7 +173,7 @@ static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream, static int bdw_rt5677_dsp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -272,8 +272,8 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) RT5677_CLK_SEL_SYS2); /* Request rt5677 GPIO for headphone amp control */ - bdw_rt5677->gpio_hp_en = devm_gpiod_get(component->dev, "headphone-enable", - GPIOD_OUT_LOW); + bdw_rt5677->gpio_hp_en = gpiod_get(component->dev, "headphone-enable", + GPIOD_OUT_LOW); if (IS_ERR(bdw_rt5677->gpio_hp_en)) { dev_err(component->dev, "Can't find HP_AMP_SHDN_L gpio\n"); return PTR_ERR(bdw_rt5677->gpio_hp_en); @@ -307,6 +307,19 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) return 0; } +static void bdw_rt5677_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct bdw_rt5677_priv *bdw_rt5677 = + snd_soc_card_get_drvdata(rtd->card); + + /* + * The .exit() can be reached without going through the .init() + * so explicitly test if the gpiod is valid + */ + if (!IS_ERR_OR_NULL(bdw_rt5677->gpio_hp_en)) + gpiod_put(bdw_rt5677->gpio_hp_en); +} + /* broadwell digital audio interface glue - connects codec <--> CPU */ SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); @@ -373,6 +386,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5677_init, + .exit = bdw_rt5677_exit, #if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_REG(dummy, be, dummy), #else @@ -405,9 +419,19 @@ static int bdw_rt5677_resume_post(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bdw rt5677" /* card name will be 'sof-bdw rt5677' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bdw-rt5677" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* ASoC machine driver for Broadwell DSP + RT5677 */ static struct snd_soc_card bdw_rt5677_card = { - .name = "bdw-rt5677", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = bdw_rt5677_dais, .num_links = ARRAY_SIZE(bdw_rt5677_dais), diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 42f8723beef2..f6399077d291 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -103,7 +103,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -291,9 +291,19 @@ static int broadwell_resume(struct snd_soc_card *card){ return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bdw rt286" /* card name will be 'sof-bdw rt286' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "broadwell-rt286" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* broadwell audio machine driver for WPT + RT286S */ static struct snd_soc_card broadwell_rt286 = { - .name = "broadwell-rt286", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = broadwell_rt286_dais, .num_links = ARRAY_SIZE(broadwell_rt286_dais), diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 44016c16f25e..0c0a717823c4 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -25,9 +25,14 @@ #define BXT_DIALOG_CODEC_DAI "da7219-hifi" #define BXT_MAXIM_CODEC_DAI "HiFi" +#define MAX98390_DEV0_NAME "i2c-MX98390:00" +#define MAX98390_DEV1_NAME "i2c-MX98390:01" #define DUAL_CHANNEL 2 #define QUAD_CHANNEL 4 +#define SPKAMP_MAX98357A 1 +#define SPKAMP_MAX98390 2 + static struct snd_soc_jack broxton_headset; static struct snd_soc_jack broxton_hdmi[3]; @@ -40,6 +45,7 @@ struct bxt_hdmi_pcm { struct bxt_card_private { struct list_head hdmi_pcm_list; bool common_hdmi_codec_drv; + int spkamp; }; enum { @@ -85,13 +91,20 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, static const struct snd_kcontrol_new broxton_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_kcontrol_new max98357a_controls[] = { SOC_DAPM_PIN_SWITCH("Spk"), }; +static const struct snd_kcontrol_new max98390_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + static const struct snd_soc_dapm_widget broxton_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Spk", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL), SND_SOC_DAPM_SPK("HDMI1", NULL), SND_SOC_DAPM_SPK("HDMI2", NULL), @@ -100,14 +113,20 @@ static const struct snd_soc_dapm_widget broxton_widgets[] = { platform_clock_control, SND_SOC_DAPM_POST_PMD|SND_SOC_DAPM_PRE_PMU), }; +static const struct snd_soc_dapm_widget max98357a_widgets[] = { + SND_SOC_DAPM_SPK("Spk", NULL), +}; + +static const struct snd_soc_dapm_widget max98390_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + static const struct snd_soc_dapm_route audio_map[] = { /* HP jack connectors - unknown if we have jack detection */ {"Headphone Jack", NULL, "HPL"}, {"Headphone Jack", NULL, "HPR"}, - /* speaker */ - {"Spk", NULL, "Speaker"}, - /* other jacks */ {"MIC", NULL, "Headset Mic"}, @@ -134,6 +153,17 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Headset Mic", NULL, "Platform Clock" }, }; +static const struct snd_soc_dapm_route max98357a_routes[] = { + /* speaker */ + {"Spk", NULL, "Speaker"}, +}; + +static const struct snd_soc_dapm_route max98390_routes[] = { + /* Speaker */ + {"Left Spk", NULL, "Left BE_OUT"}, + {"Right Spk", NULL, "Right BE_OUT"}, +}; + static const struct snd_soc_dapm_route broxton_map[] = { {"HiFi Playback", NULL, "ssp5 Tx"}, {"ssp5 Tx", NULL, "codec0_out"}, @@ -404,6 +434,10 @@ SND_SOC_DAILINK_DEF(ssp5_pin, SND_SOC_DAILINK_DEF(ssp5_codec, DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", BXT_MAXIM_CODEC_DAI))); +SND_SOC_DAILINK_DEF(max98390_codec, + DAILINK_COMP_ARRAY( + /* Left */ COMP_CODEC(MAX98390_DEV0_NAME, "max98390-aif1"), + /* Right */ COMP_CODEC(MAX98390_DEV1_NAME, "max98390-aif1"))); SND_SOC_DAILINK_DEF(ssp1_pin, DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); @@ -601,15 +635,69 @@ static struct snd_soc_dai_link broxton_dais[] = { }, }; +static struct snd_soc_codec_conf max98390_codec_confs[] = { + { + .dlc = COMP_CODEC_CONF(MAX98390_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(MAX98390_DEV1_NAME), + .name_prefix = "Right", + }, +}; + #define NAME_SIZE 32 static int bxt_card_late_probe(struct snd_soc_card *card) { struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); struct bxt_hdmi_pcm *pcm; struct snd_soc_component *component = NULL; - int err, i = 0; + const struct snd_kcontrol_new *controls; + const struct snd_soc_dapm_widget *widgets; + const struct snd_soc_dapm_route *routes; + int num_controls, num_widgets, num_routes, err, i = 0; char jack_name[NAME_SIZE]; + switch (ctx->spkamp) { + case SPKAMP_MAX98357A: + controls = max98357a_controls; + num_controls = ARRAY_SIZE(max98357a_controls); + widgets = max98357a_widgets; + num_widgets = ARRAY_SIZE(max98357a_widgets); + routes = max98357a_routes; + num_routes = ARRAY_SIZE(max98357a_routes); + break; + case SPKAMP_MAX98390: + controls = max98390_controls; + num_controls = ARRAY_SIZE(max98390_controls); + widgets = max98390_widgets; + num_widgets = ARRAY_SIZE(max98390_widgets); + routes = max98390_routes; + num_routes = ARRAY_SIZE(max98390_routes); + break; + default: + dev_err(card->dev, "Invalid speaker amplifier %d\n", ctx->spkamp); + return -EINVAL; + } + + err = snd_soc_dapm_new_controls(&card->dapm, widgets, num_widgets); + if (err) { + dev_err(card->dev, "Fail to new widgets\n"); + return err; + } + + err = snd_soc_add_card_controls(card, controls, num_controls); + if (err) { + dev_err(card->dev, "Fail to add controls\n"); + return err; + } + + err = snd_soc_dapm_add_routes(&card->dapm, routes, num_routes); + if (err) { + dev_err(card->dev, "Fail to add routes\n"); + return err; + } + if (soc_intel_is_glk()) snd_soc_dapm_add_routes(&card->dapm, gemini_map, ARRAY_SIZE(gemini_map)); @@ -678,6 +766,11 @@ static int broxton_audio_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ctx->hdmi_pcm_list); + if (acpi_dev_present("MX98390", NULL, -1)) + ctx->spkamp = SPKAMP_MAX98390; + else + ctx->spkamp = SPKAMP_MAX98357A; + broxton_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&broxton_audio_card, ctx); if (soc_intel_is_glk()) { @@ -702,7 +795,13 @@ static int broxton_audio_probe(struct platform_device *pdev) } else if (soc_intel_is_cml()) { unsigned int i; - broxton_audio_card.name = "cmlda7219max"; + if (ctx->spkamp == SPKAMP_MAX98390) { + broxton_audio_card.name = "cml_max98390_da7219"; + + broxton_audio_card.codec_conf = max98390_codec_confs; + broxton_audio_card.num_configs = ARRAY_SIZE(max98390_codec_confs); + } else + broxton_audio_card.name = "cmlda7219max"; for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { /* MAXIM_CODEC is connected to SSP1. */ @@ -710,6 +809,11 @@ static int broxton_audio_probe(struct platform_device *pdev) BXT_MAXIM_CODEC_DAI)) { broxton_dais[i].name = "SSP1-Codec"; broxton_dais[i].cpus->dai_name = "SSP1 Pin"; + + if (ctx->spkamp == SPKAMP_MAX98390) { + broxton_dais[i].codecs = max98390_codec; + broxton_dais[i].num_codecs = ARRAY_SIZE(max98390_codec); + } } /* DIALOG_CODEC is connected to SSP0 */ else if (!strcmp(broxton_dais[i].codecs->dai_name, @@ -759,6 +863,7 @@ MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>"); MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>"); +MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:bxt_da7219_max98357a"); MODULE_ALIAS("platform:glk_da7219_max98357a"); diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 7a4decf34191..0f3157dfa838 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -224,7 +224,7 @@ static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd, static int broxton_rt298_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -565,6 +565,7 @@ static int bxt_card_late_probe(struct snd_soc_card *card) /* broxton audio machine driver for SPT + RT298S */ static struct snd_soc_card broxton_rt298 = { .name = "broxton-rt298", + .owner = THIS_MODULE, .dai_link = broxton_rt298_dais, .num_links = ARRAY_SIZE(broxton_rt298_dais), .controls = broxton_controls, @@ -580,6 +581,7 @@ static struct snd_soc_card broxton_rt298 = { static struct snd_soc_card geminilake_rt298 = { .name = "geminilake-rt298", + .owner = THIS_MODULE, .dai_link = broxton_rt298_dais, .num_links = ARRAY_SIZE(broxton_rt298_dais), .controls = broxton_controls, diff --git a/sound/soc/intel/boards/byt-rt5640.c b/sound/soc/intel/boards/byt-rt5640.c index ace232f8aed6..8851949f38e2 100644 --- a/sound/soc/intel/boards/byt-rt5640.c +++ b/sound/soc/intel/boards/byt-rt5640.c @@ -72,7 +72,7 @@ static const struct snd_kcontrol_new byt_rt5640_controls[] = { static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index fad937610494..9cb42ba40c07 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -205,9 +205,19 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht cx2072x" /* card name will be 'sof-bytcht cx2072x' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcht-cx2072x" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card byt_cht_cx2072x_card = { - .name = "bytcht-cx2072x", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_cht_cx2072x_dais, .num_links = ARRAY_SIZE(byt_cht_cx2072x_dais), diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index f3791ff2bad1..e1e46b4bbac5 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -105,7 +105,7 @@ static int aif1_startup(struct snd_pcm_substream *substream) static int aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -126,7 +126,7 @@ static int aif1_hw_params(struct snd_pcm_substream *substream, static int aif1_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -205,9 +205,19 @@ static struct snd_soc_dai_link dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht da7213" /* card name will be 'sof-bytcht da7213' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcht-da7213" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card bytcht_da7213_card = { - .name = "bytcht-da7213", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = dailink, .num_links = ARRAY_SIZE(dailink), diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index ecbc58e8a37f..414ae4bb5224 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -407,8 +407,18 @@ static int byt_cht_es8316_resume(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht es8316" /* card name will be 'sof-bytcht es8316' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcht-es8316" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + static struct snd_soc_card byt_cht_es8316_card = { - .name = "bytcht-es8316", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_cht_es8316_dais, .num_links = ARRAY_SIZE(byt_cht_es8316_dais), @@ -515,9 +525,8 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) BYT_CHT_ES8316_MONO_SPEAKER; } if (quirk_override != -1) { - dev_info(dev, "Overriding quirk 0x%x => 0x%x\n", - (unsigned int)quirk, - quirk_override); + dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n", + quirk, quirk_override); quirk = quirk_override; } log_quirks(dev); diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 1fdb70b9e478..479992f4e97a 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -380,7 +380,7 @@ static struct snd_soc_jack_pin rt5640_pins[] = { static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params)); @@ -1127,8 +1127,18 @@ static int byt_rt5640_resume(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcr-rt5640" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + static struct snd_soc_card byt_rt5640_card = { - .name = "bytcr-rt5640", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_rt5640_dais, .num_links = ARRAY_SIZE(byt_rt5640_dais), @@ -1255,8 +1265,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) if (dmi_id) byt_rt5640_quirk = (unsigned long)dmi_id->driver_data; if (quirk_override != -1) { - dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n", - (unsigned int)byt_rt5640_quirk, quirk_override); + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + byt_rt5640_quirk, quirk_override); byt_rt5640_quirk = quirk_override; } diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 520e916e329c..4e2897596cea 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -347,7 +347,7 @@ static struct snd_soc_jack_pin bytcr_jack_pins[] = { static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); snd_pcm_format_t format = params_format(params); int rate = params_rate(params); @@ -827,8 +827,18 @@ static int byt_rt5651_resume(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht rt5651" /* card name will be 'sof-bytcht rt5651' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcr-rt5651" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + static struct snd_soc_card byt_rt5651_card = { - .name = "bytcr-rt5651", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_rt5651_dais, .num_links = ARRAY_SIZE(byt_rt5651_dais), @@ -967,8 +977,8 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) dmi_check_system(byt_rt5651_quirk_table); if (quirk_override != -1) { - dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n", - (unsigned int)byt_rt5651_quirk, quirk_override); + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + byt_rt5651_quirk, quirk_override); byt_rt5651_quirk = quirk_override; } diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 767ac2ae03e2..835e9bd6b52d 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -112,7 +112,7 @@ static const struct snd_kcontrol_new cht_mc_controls[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -382,9 +382,19 @@ static struct snd_soc_dai_link cht_dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht max98090" /* card name will be 'sof-bytcht max98090 */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "chtmax98090" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_cht = { - .name = "chtmax98090", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index 2f7c94d335c1..3e12bff15fed 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -72,7 +72,7 @@ static const struct snd_kcontrol_new cht_mc_controls[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -231,9 +231,19 @@ static struct snd_soc_dai_link cht_dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht nau8824" /* card name will be 'sof-bytcht nau8824 */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "chtnau8824" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_cht = { - .name = "chtnau8824", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 22de138ffa33..b53c02481749 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -207,7 +207,7 @@ static struct snd_soc_jack_pin cht_bsw_jack_pins[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -479,9 +479,21 @@ static struct snd_soc_dai_link cht_dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_RT5645_NAME "bytcht rt5645" /* card name 'sof-bytcht rt5645' */ +#define CARD_RT5650_NAME "bytcht rt5650" /* card name 'sof-bytcht rt5650' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_RT5645_NAME "chtrt5645" +#define CARD_RT5650_NAME "chtrt5650" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_chtrt5645 = { - .name = "chtrt5645", + .name = CARD_RT5645_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), @@ -494,7 +506,8 @@ static struct snd_soc_card snd_soc_card_chtrt5645 = { }; static struct snd_soc_card snd_soc_card_chtrt5650 = { - .name = "chtrt5650", + .name = CARD_RT5650_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 22e432768edb..8442be93eb1c 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -143,7 +143,7 @@ static const struct snd_kcontrol_new cht_mc_controls[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -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 | @@ -378,9 +382,19 @@ static int cht_resume_post(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht rt5672" /* card name will be 'sof-bytcht rt5672' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "cht-bsw-rt5672" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_cht = { - .name = "cht-bsw-rt5672", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index 68eff29daf8f..14813beb33d1 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -34,7 +34,6 @@ #define SOF_RT1011_SPEAKER_WR BIT(1) #define SOF_RT1011_SPEAKER_TL BIT(2) #define SOF_RT1011_SPEAKER_TR BIT(3) -#define SPK_CH 4 /* Default: Woofer speakers */ static unsigned long sof_rt1011_quirk = SOF_RT1011_SPEAKER_WL | @@ -161,6 +160,13 @@ static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; }; +static void cml_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_set_jack(component, NULL, NULL); +} + static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd) { int ret = 0; @@ -193,7 +199,7 @@ static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd) static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out, ret; @@ -226,7 +232,7 @@ static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; struct snd_soc_card *card = rtd->card; int srate, i, ret = 0; @@ -376,10 +382,17 @@ SND_SOC_DAILINK_DEF(ssp0_codec, SND_SOC_DAILINK_DEF(ssp1_pin, DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, +SND_SOC_DAILINK_DEF(ssp1_codec_2spk, DAILINK_COMP_ARRAY( /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI))); +SND_SOC_DAILINK_DEF(ssp1_codec_4spk, + DAILINK_COMP_ARRAY( + /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), + /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI), + /* TL */ COMP_CODEC("i2c-10EC1011:02", CML_RT1011_CODEC_DAI), + /* TR */ COMP_CODEC("i2c-10EC1011:03", CML_RT1011_CODEC_DAI))); + SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); @@ -415,6 +428,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .name = "SSP0-Codec", .id = 0, .init = cml_rt5682_codec_init, + .exit = cml_rt5682_codec_exit, .ignore_pmdown_time = 1, .ops = &cml_rt5682_ops, .dpcm_playback = 1, @@ -475,7 +489,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .no_pcm = 1, .init = cml_rt1011_spk_init, .ops = &cml_rt1011_ops, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec_2spk, platform), }, }; @@ -488,11 +502,21 @@ static struct snd_soc_codec_conf rt1011_conf[] = { .dlc = COMP_CODEC_CONF("i2c-10EC1011:01"), .name_prefix = "WR", }, + /* single configuration structure for 2 and 4 channels */ + { + .dlc = COMP_CODEC_CONF("i2c-10EC1011:02"), + .name_prefix = "TL", + }, + { + .dlc = COMP_CODEC_CONF("i2c-10EC1011:03"), + .name_prefix = "TR", + }, }; /* Cometlake audio machine driver for RT1011 and RT5682 */ static struct snd_soc_card snd_soc_card_cml = { .name = "cml_rt1011_rt5682", + .owner = THIS_MODULE, .dai_link = cml_rt1011_rt5682_dailink, .num_links = ARRAY_SIZE(cml_rt1011_rt5682_dailink), .codec_conf = rt1011_conf, @@ -509,8 +533,7 @@ static struct snd_soc_card snd_soc_card_cml = { static int snd_cml_rt1011_probe(struct platform_device *pdev) { - struct snd_soc_dai_link_component *rt1011_dais_components; - struct snd_soc_codec_conf *rt1011_dais_confs; + struct snd_soc_dai_link *dai_link; struct card_private *ctx; struct snd_soc_acpi_mach *mach; const char *platform_name; @@ -527,67 +550,16 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev) dmi_check_system(sof_rt1011_quirk_table); - dev_info(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk); + dev_dbg(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk); + /* when 4 speaker is available, update codec config */ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | SOF_RT1011_SPEAKER_TR)) { - rt1011_dais_confs = devm_kzalloc(&pdev->dev, - sizeof(struct snd_soc_codec_conf) * - SPK_CH, GFP_KERNEL); - - if (!rt1011_dais_confs) - return -ENOMEM; - - rt1011_dais_components = devm_kzalloc(&pdev->dev, - sizeof(struct snd_soc_dai_link_component) * - SPK_CH, GFP_KERNEL); - - if (!rt1011_dais_components) - return -ENOMEM; - - for (i = 0; i < SPK_CH; i++) { - rt1011_dais_confs[i].dlc.name = devm_kasprintf(&pdev->dev, - GFP_KERNEL, - "i2c-10EC1011:0%d", - i); - - if (!rt1011_dais_confs[i].dlc.name) - return -ENOMEM; - - switch (i) { - case 0: - rt1011_dais_confs[i].name_prefix = "WL"; - break; - case 1: - rt1011_dais_confs[i].name_prefix = "WR"; - break; - case 2: - rt1011_dais_confs[i].name_prefix = "TL"; - break; - case 3: - rt1011_dais_confs[i].name_prefix = "TR"; - break; - default: - return -EINVAL; - } - rt1011_dais_components[i].name = devm_kasprintf(&pdev->dev, - GFP_KERNEL, - "i2c-10EC1011:0%d", - i); - if (!rt1011_dais_components[i].name) - return -ENOMEM; - - rt1011_dais_components[i].dai_name = CML_RT1011_CODEC_DAI; - } - - snd_soc_card_cml.codec_conf = rt1011_dais_confs; - snd_soc_card_cml.num_configs = SPK_CH; - - for (i = 0; i < ARRAY_SIZE(cml_rt1011_rt5682_dailink); i++) { - if (!strcmp(cml_rt1011_rt5682_dailink[i].codecs->dai_name, - CML_RT1011_CODEC_DAI)) { - cml_rt1011_rt5682_dailink[i].codecs = rt1011_dais_components; - cml_rt1011_rt5682_dailink[i].num_codecs = SPK_CH; + for_each_card_prelinks(&snd_soc_card_cml, i, dai_link) { + if (!strcmp(dai_link->codecs[0].dai_name, + CML_RT1011_CODEC_DAI)) { + dai_link->codecs = ssp1_codec_4spk; + dai_link->num_codecs = ARRAY_SIZE(ssp1_codec_4spk); } } } diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c index 78160e3b1615..7c0d4e915406 100644 --- a/sound/soc/intel/boards/ehl_rt5660.c +++ b/sound/soc/intel/boards/ehl_rt5660.c @@ -109,7 +109,7 @@ static int card_late_probe(struct snd_soc_card *card) static int rt5660_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index 954ab01f695b..62cca511522e 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -187,7 +187,7 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) static int geminilake_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 74af090f2657..744b7b5b8106 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -55,7 +55,7 @@ static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index e29c31ffd241..cc9a2509ace2 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -175,7 +175,7 @@ static const struct snd_soc_dapm_route kabylake_ssp1_map[] = { static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = substream->private_data; + struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret, j; @@ -220,7 +220,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, static int kabylake_ssp0_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int j, ret; @@ -455,7 +455,7 @@ static struct snd_pcm_hw_constraint_list constraints_channels_quad = { static int kbl_fe_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_rt = substream->private_data; + struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream); /* * On this platform for PCM device we support, @@ -512,7 +512,7 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_dmic_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_rt = substream->private_data; + struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream); runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index d2a078454784..3a9f91b58e11 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -165,8 +165,8 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) dev_warn(component->dev, "Failed to add driver gpios\n"); /* Request rt5660 GPIO for lineout mute control, return if fails */ - ctx->gpio_lo_mute = devm_gpiod_get(component->dev, "lineout-mute", - GPIOD_OUT_HIGH); + ctx->gpio_lo_mute = gpiod_get(component->dev, "lineout-mute", + GPIOD_OUT_HIGH); if (IS_ERR(ctx->gpio_lo_mute)) { dev_err(component->dev, "Can't find GPIO_MUTE# gpio\n"); return PTR_ERR(ctx->gpio_lo_mute); @@ -207,6 +207,18 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) return 0; } +static void kabylake_rt5660_codec_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); + + /* + * The .exit() can be reached without going through the .init() + * so explicitly test if the gpiod is valid + */ + if (!IS_ERR_OR_NULL(ctx->gpio_lo_mute)) + gpiod_put(ctx->gpio_lo_mute); +} + static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); @@ -243,7 +255,7 @@ static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_rt5660_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -421,6 +433,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .id = 0, .no_pcm = 1, .init = kabylake_rt5660_codec_init, + .exit = kabylake_rt5660_codec_exit, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 09ba55fc36d5..3ea4602dfb3e 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -430,7 +430,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -468,7 +468,7 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret = 0, j; diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index b34cf6cf1139..922cd0176e1f 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -336,22 +336,45 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_interval *chan = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_soc_dpcm *dpcm = container_of( - params, struct snd_soc_dpcm, hw_params); - struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link; - struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link; + struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL; + + /* + * The following loop will be called only for playback stream + * In this platform, there is only one playback device on every SSP + */ + for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { + rtd_dpcm = dpcm; + break; + } + + /* + * This following loop will be called only for capture stream + * In this platform, there is only one capture device on every SSP + */ + for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) { + rtd_dpcm = dpcm; + break; + } + + if (!rtd_dpcm) + return -EINVAL; + + /* + * The above 2 loops are mutually exclusive based on the stream direction, + * thus rtd_dpcm variable will never be overwritten + */ /* * The ADSP will convert the FE rate to 48k, stereo, 24 bit */ - if (!strcmp(fe_dai_link->name, "Kbl Audio Port") || - !strcmp(fe_dai_link->name, "Kbl Audio Headset Playback") || - !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) { + if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") || + !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") || + !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) { rate->min = rate->max = 48000; chan->min = chan->max = 2; snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - } else if (!strcmp(fe_dai_link->name, "Kbl Audio DMIC cap")) { + } else if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio DMIC cap")) { if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) chan->min = chan->max = 2; @@ -362,7 +385,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, * The speaker on the SSP0 supports S16_LE and not S24_LE. * thus changing the mask here */ - if (!strcmp(be_dai_link->name, "SSP0-Codec")) + if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec")) snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); return 0; @@ -371,7 +394,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -395,7 +418,7 @@ static struct snd_soc_ops kabylake_rt5663_ops = { static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret = 0, j; diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h index 507750ef67f3..4b0b3959182e 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.h +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h @@ -33,6 +33,7 @@ struct skl_hda_private { int dai_index; const char *platform_name; bool common_hdmi_codec_drv; + bool idisp_codec; }; extern struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS]; diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 79c8947f840b..ca4900036ead 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -79,6 +79,9 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) link->platforms->name = ctx->platform_name; link->nonatomic = 1; + if (!ctx->idisp_codec) + return 0; + if (strstr(link->name, "HDMI")) { ret = skl_hda_hdmi_add_pcm(card, ctx->pcm_count); @@ -118,19 +121,20 @@ static char hda_soc_components[30]; static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) { struct snd_soc_card *card = &hda_soc_card; + struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link *dai_link; - u32 codec_count, codec_mask, idisp_mask; + u32 codec_count, codec_mask; int i, num_links, num_route; codec_mask = mach_params->codec_mask; codec_count = hweight_long(codec_mask); - idisp_mask = codec_mask & IDISP_CODEC_MASK; + ctx->idisp_codec = !!(codec_mask & IDISP_CODEC_MASK); if (!codec_count || codec_count > 2 || - (codec_count == 2 && !idisp_mask)) + (codec_count == 2 && !ctx->idisp_codec)) return -EINVAL; - if (codec_mask == idisp_mask) { + if (codec_mask == IDISP_CODEC_MASK) { /* topology with iDisp as the only HDA codec */ num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT; num_route = IDISP_ROUTE_COUNT; @@ -152,7 +156,7 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) num_route = ARRAY_SIZE(skl_hda_map); card->dapm_widgets = skl_hda_widgets; card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets); - if (!idisp_mask) { + if (!ctx->idisp_codec) { for (i = 0; i < IDISP_DAI_COUNT; i++) { skl_hda_be_dai_links[i].codecs = dummy_codec; skl_hda_be_dai_links[i].num_codecs = @@ -211,6 +215,8 @@ static int skl_hda_audio_probe(struct platform_device *pdev) if (!mach) return -EINVAL; + snd_soc_card_set_drvdata(&hda_soc_card, ctx); + ret = skl_hda_fill_card_info(&mach->mach_params); if (ret < 0) { dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n"); @@ -223,7 +229,6 @@ static int skl_hda_audio_probe(struct platform_device *pdev) ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; hda_soc_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&hda_soc_card, ctx); if (mach->mach_params.dmic_num > 0) { snprintf(hda_soc_components, sizeof(hda_soc_components), diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index d7b8154c43a4..55802900069a 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -295,7 +295,7 @@ static const struct snd_soc_ops skylake_nau8825_fe_ops = { static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index 4b317bcf6ea0..0c734f3a9364 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -347,7 +347,7 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 903ae1b28ec9..5a0c64a83146 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -228,7 +228,7 @@ static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int skylake_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index 703703858595..f3cb0773e70e 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -179,7 +179,7 @@ static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) static int ssp1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = substream->private_data; + struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); int ret, j; for (j = 0; j < runtime->num_codecs; j++) { diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 1a549b32d1c9..1a6961592029 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -9,7 +9,9 @@ #include <uapi/sound/asound.h> #include "sof_maxim_common.h" -static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { +#define MAX_98373_PIN_NAME 16 + +const struct snd_soc_dapm_route max_98373_dapm_routes[] = { /* speaker */ { "Left Spk", NULL, "Left BE_OUT" }, { "Right Spk", NULL, "Right BE_OUT" }, @@ -27,11 +29,11 @@ static struct snd_soc_codec_conf max_98373_codec_conf[] = { }; struct snd_soc_dai_link_component max_98373_components[] = { - { /* For Left */ + { /* For Right */ .name = MAX_98373_DEV0_NAME, .dai_name = MAX_98373_CODEC_DAI, }, - { /* For Right */ + { /* For Left */ .name = MAX_98373_DEV1_NAME, .dai_name = MAX_98373_CODEC_DAI, }, @@ -40,25 +42,68 @@ struct snd_soc_dai_link_component max_98373_components[] = { static int max98373_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int j; for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) { /* DEV0 tdm slot configuration */ - snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); + snd_soc_dai_set_tdm_slot(codec_dai, 0x03, 3, 8, 24); } if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) { /* DEV1 tdm slot configuration */ - snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); + snd_soc_dai_set_tdm_slot(codec_dai, 0x0C, 3, 8, 24); } } return 0; } +int max98373_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int j; + int ret = 0; + + for_each_rtd_codec_dais(rtd, j, codec_dai) { + struct snd_soc_component *component = codec_dai->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char pin_name[MAX_98373_PIN_NAME]; + + snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk", + codec_dai->component->name_prefix); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = snd_soc_dapm_enable_pin(dapm, pin_name); + if (!ret) + snd_soc_dapm_sync(dapm); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + /* Make sure no streams are active before disable pin */ + if (snd_soc_dai_active(codec_dai) != 1) + break; + ret = snd_soc_dapm_disable_pin(dapm, pin_name); + if (!ret) + snd_soc_dapm_sync(dapm); + break; + default: + break; + } + } + + return ret; +} + struct snd_soc_ops max_98373_ops = { .hw_params = max98373_hw_params, + .trigger = max98373_trigger, }; int max98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 785b34335368..5240b1c9d379 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -18,7 +18,10 @@ extern struct snd_soc_dai_link_component max_98373_components[2]; extern struct snd_soc_ops max_98373_ops; +extern const struct snd_soc_dapm_route max_98373_dapm_routes[]; int max98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd); void sof_max98373_codec_conf(struct snd_soc_card *card); +int max98373_trigger(struct snd_pcm_substream *substream, int cmd); + #endif /* __SOF_MAXIM_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index 9fa8a4911276..d2b0456236c7 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -96,7 +96,7 @@ static int sof_pcm512x_codec_init(struct snd_soc_pcm_runtime *rtd) static int aif1_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, @@ -107,7 +107,7 @@ static int aif1_startup(struct snd_pcm_substream *substream) static void aif1_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 13a48b0c35ae..0129d23694ed 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -43,6 +43,7 @@ ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK) #define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(13) #define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(14) +#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(15) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | @@ -206,10 +207,17 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; }; +static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_set_jack(component, NULL, NULL); +} + static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out, ret; @@ -267,7 +275,7 @@ static struct snd_soc_ops sof_rt5682_ops = { static int sof_rt1015_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai; int i, ret; @@ -276,8 +284,15 @@ static int sof_rt1015_hw_params(struct snd_pcm_substream *substream, return 0; for_each_rtd_codec_dais(rtd, i, codec_dai) { + /* Set tdm/i2s1 master bclk ratio */ + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) { + dev_err(card->dev, "failed to set bclk ratio\n"); + return ret; + } + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, - params_rate(params) * 50, + params_rate(params) * 64, params_rate(params) * 256); if (ret < 0) { dev_err(card->dev, "failed to set pll\n"); @@ -311,6 +326,7 @@ static int sof_card_late_probe(struct snd_soc_card *card) { struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_component *component = NULL; + struct snd_soc_dapm_context *dapm = &card->dapm; char jack_name[NAME_SIZE]; struct sof_hdmi_pcm *pcm; int err; @@ -349,6 +365,14 @@ static int sof_card_late_probe(struct snd_soc_card *card) i++; } + if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) { + /* Disable Left and Right Spk pin after boot */ + snd_soc_dapm_disable_pin(dapm, "Left Spk"); + snd_soc_dapm_disable_pin(dapm, "Right Spk"); + err = snd_soc_dapm_sync(dapm); + if (err < 0) + return err; + } return hdac_hdmi_jack_port_init(component, &card->dapm); } @@ -484,6 +508,13 @@ static struct snd_soc_dai_link_component max98357a_component[] = { } }; +static struct snd_soc_dai_link_component max98360a_component[] = { + { + .name = "MX98360A:00", + .dai_name = "HiFi", + } +}; + static struct snd_soc_dai_link_component rt1015_components[] = { { .name = "i2c-10EC1015:00", @@ -525,6 +556,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].init = sof_rt5682_codec_init; + links[id].exit = sof_rt5682_codec_exit; links[id].ops = &sof_rt5682_ops; links[id].nonatomic = true; links[id].dpcm_playback = 1; @@ -645,6 +677,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].num_codecs = ARRAY_SIZE(max_98373_components); links[id].init = max98373_spk_codec_init; links[id].ops = &max_98373_ops; + } else if (sof_rt5682_quirk & + SOF_MAX98360A_SPEAKER_AMP_PRESENT) { + links[id].codecs = max98360a_component; + links[id].num_codecs = ARRAY_SIZE(max98360a_component); + links[id].init = speaker_codec_init; } else { links[id].codecs = max98357a_component; links[id].num_codecs = ARRAY_SIZE(max98357a_component); @@ -786,21 +823,6 @@ static int sof_audio_probe(struct platform_device *pdev) &sof_audio_card_rt5682); } -static int sof_rt5682_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - struct snd_soc_component *component = NULL; - - for_each_card_components(card, component) { - if (!strcmp(component->name, rt5682_component[0].name)) { - snd_soc_component_set_jack(component, NULL, NULL); - break; - } - } - - return 0; -} - static const struct platform_device_id board_ids[] = { { .name = "sof_rt5682", @@ -831,12 +853,20 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_AMP(1) | SOF_RT5682_NUM_HDMIDEV(4)), }, + { + .name = "jsl_rt5682_max98360a", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_MCLK_24MHZ | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98360A_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1)), + }, { } }; static struct platform_driver sof_audio = { .probe = sof_audio_probe, - .remove = sof_rt5682_remove, .driver = { .name = "sof_rt5682", .pm = &snd_soc_pm_ops, @@ -854,3 +884,4 @@ MODULE_ALIAS("platform:sof_rt5682"); MODULE_ALIAS("platform:tgl_max98357a_rt5682"); MODULE_ALIAS("platform:jsl_rt5682_rt1015"); MODULE_ALIAS("platform:tgl_max98373_rt5682"); +MODULE_ALIAS("platform:jsl_rt5682_max98360a"); diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e1c1a8ba78e6..2463d432bf4d 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -15,9 +15,32 @@ #include "sof_sdw_common.h" unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1; +static int quirk_override = -1; +module_param_named(quirk, quirk_override, int, 0444); +MODULE_PARM_DESC(quirk, "Board-specific quirk override"); #define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0) +static void log_quirks(struct device *dev) +{ + if (SOF_RT711_JDSRC(sof_sdw_quirk)) + dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", + SOF_RT711_JDSRC(sof_sdw_quirk)); + if (sof_sdw_quirk & SOF_SDW_FOUR_SPK) + dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n"); + if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) + dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n"); + if (sof_sdw_quirk & SOF_SDW_PCH_DMIC) + dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n"); + if (SOF_SSP_GET_PORT(sof_sdw_quirk)) + dev_dbg(dev, "SSP port %ld\n", + SOF_SSP_GET_PORT(sof_sdw_quirk)); + if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX) + dev_dbg(dev, "quirk SOF_RT715_DAI_ID_FIX enabled\n"); + if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) + dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); +} + static int sof_sdw_quirk_cb(const struct dmi_system_id *id) { sof_sdw_quirk = (unsigned long)id->driver_data; @@ -97,7 +120,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC), + .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + SOF_SDW_FOUR_SPK), }, {} @@ -136,6 +160,15 @@ static struct snd_soc_codec_conf codec_conf[] = { .dlc = COMP_CODEC_CONF("sdw:3:25d:715:0"), .name_prefix = "rt715", }, + /* two MAX98373s on link1 with different unique id */ + { + .dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:3"), + .name_prefix = "Right", + }, + { + .dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:7"), + .name_prefix = "Left", + }, { .dlc = COMP_CODEC_CONF("sdw:0:25d:5682:0"), .name_prefix = "rt5682", @@ -157,12 +190,12 @@ static struct snd_soc_dai_link_component platform_component[] = { }; /* these wrappers are only needed to avoid typecast compilation errors */ -static int sdw_startup(struct snd_pcm_substream *substream) +int sdw_startup(struct snd_pcm_substream *substream) { return sdw_startup_stream(substream); } -static void sdw_shutdown(struct snd_pcm_substream *substream) +void sdw_shutdown(struct snd_pcm_substream *substream) { sdw_shutdown_stream(substream); } @@ -184,6 +217,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, true}, .dai_name = "rt711-aif1", .init = sof_sdw_rt711_init, + .exit = sof_sdw_rt711_exit, }, { .id = 0x1308, @@ -200,6 +234,13 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt715_init, }, { + .id = 0x8373, + .direction = {true, true}, + .dai_name = "max98373-aif1", + .init = sof_sdw_mx8373_init, + .codec_card_late_probe = sof_sdw_mx8373_late_probe, + }, + { .id = 0x5682, .direction = {true, true}, .dai_name = "rt5682-sdw", @@ -658,11 +699,14 @@ static inline int get_next_be_id(struct snd_soc_dai_link *links, return links[be_id - 1].id + 1; } +#define IDISP_CODEC_MASK 0x4 + static int sof_card_dai_links_create(struct device *dev, struct snd_soc_acpi_mach *mach, struct snd_soc_card *card) { int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link_component *idisp_components; struct snd_soc_dai_link_component *ssp_components; struct snd_soc_acpi_mach_params *mach_params; @@ -706,12 +750,15 @@ static int sof_card_dai_links_create(struct device *dev, return ret; } + if (mach_params->codec_mask & IDISP_CODEC_MASK) + ctx->idisp_codec = true; + /* enable dmic01 & dmic16k */ dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0; comp_num += dmic_num; dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, - dmic_num, hdmi_num); + dmic_num, ctx->idisp_codec ? hdmi_num : 0); /* allocate BE dailinks */ num_links = comp_num + sdw_be_num; @@ -860,13 +907,18 @@ DMIC: if (!name) return -ENOMEM; - idisp_components[i].name = "ehdaudio0D2"; - idisp_components[i].dai_name = devm_kasprintf(dev, - GFP_KERNEL, - "intel-hdmi-hifi%d", - i + 1); - if (!idisp_components[i].dai_name) - return -ENOMEM; + if (ctx->idisp_codec) { + idisp_components[i].name = "ehdaudio0D2"; + idisp_components[i].dai_name = devm_kasprintf(dev, + GFP_KERNEL, + "intel-hdmi-hifi%d", + i + 1); + if (!idisp_components[i].dai_name) + return -ENOMEM; + } else { + idisp_components[i].name = "snd-soc-dummy"; + idisp_components[i].dai_name = "snd-soc-dummy-dai"; + } cpu_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); @@ -888,12 +940,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", - .late_probe = sof_sdw_hdmi_card_late_probe, + .owner = THIS_MODULE, + .late_probe = sof_sdw_card_late_probe, .codec_conf = codec_conf, .num_configs = ARRAY_SIZE(codec_conf), }; @@ -914,9 +983,17 @@ static int mc_probe(struct platform_device *pdev) dmi_check_system(sof_sdw_quirk_table); + if (quirk_override != -1) { + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + sof_sdw_quirk, quirk_override); + sof_sdw_quirk = quirk_override; + } + log_quirks(&pdev->dev); + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, ctx); mach = pdev->dev.platform_data; ret = sof_card_dai_links_create(&pdev->dev, mach, @@ -926,8 +1003,6 @@ static int mc_probe(struct platform_device *pdev) ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; - snd_soc_card_set_drvdata(card, ctx); - /* * the default amp_num is zero for each codec and * amp_num will only be increased for active amp diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 69b363b8a686..12e32439ba46 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,16 +62,23 @@ 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 { struct list_head hdmi_pcm_list; bool common_hdmi_codec_drv; + bool idisp_codec; struct snd_soc_jack sdw_headset; }; extern unsigned long sof_sdw_quirk; +int sdw_startup(struct snd_pcm_substream *substream); +void sdw_shutdown(struct snd_pcm_substream *substream); + /* generic HDMI support */ int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd); @@ -84,6 +92,7 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); +int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link); /* RT700 support */ int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, @@ -105,6 +114,14 @@ int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, struct sof_sdw_codec_info *info, bool playback); +/* MAX98373 support */ +int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + 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_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index 0654b38a7e0d..99b04bb2f3a0 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -52,6 +52,12 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) int err, i = 0; char jack_name[NAME_SIZE]; + if (!ctx->idisp_codec) + return 0; + + if (list_empty(&ctx->hdmi_pcm_list)) + return -EINVAL; + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm, head); component = pcm->codec_dai->component; diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c new file mode 100644 index 000000000000..6437872a9b3d --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation +// +// sof_sdw_max98373 - Helpers to handle 2x MAX98373 +// codec devices from generic machine driver + +#include <linux/device.h> +#include <linux/errno.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "sof_sdw_common.h" +#include "sof_maxim_common.h" + +static const struct snd_soc_dapm_widget mx8373_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_kcontrol_new mx8373_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static int spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:mx8373", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, mx8373_controls, + ARRAY_SIZE(mx8373_controls)); + if (ret) { + dev_err(card->dev, "mx8373 ctrls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, mx8373_widgets, + ARRAY_SIZE(mx8373_widgets)); + if (ret) { + dev_err(card->dev, "mx8373 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, 2); + if (ret) + dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops max_98373_sdw_ops = { + .startup = sdw_startup, + .trigger = max98373_trigger, + .shutdown = sdw_shutdown, +}; + +int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + info->amp_num++; + 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/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index 177cc781ada6..3655e890acec 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -91,7 +91,7 @@ static int all_spk_init(struct snd_soc_pcm_runtime *rtd) static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out; diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index d4d75c8dc6b7..606009fa3901 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -133,6 +133,21 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } +int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link) +{ + struct device *sdw_dev; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, + dai_link->codecs[0].name); + if (!sdw_dev) + return -EINVAL; + + device_remove_properties(sdw_dev); + put_device(sdw_dev); + + return 0; +} + int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, @@ -147,7 +162,7 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, if (!playback) return 0; - ret = rt711_add_codec_device_props("sdw:0:25d:711:0"); + ret = rt711_add_codec_device_props(dai_links->codecs[0].name); if (ret < 0) return ret; diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c index c13fd20da559..a46ba13e8eb0 100644 --- a/sound/soc/intel/boards/sof_wm8804.c +++ b/sound/soc/intel/boards/sof_wm8804.c @@ -49,7 +49,7 @@ static const struct dmi_system_id sof_wm8804_quirk_table[] = { static int sof_wm8804_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_component *codec = codec_dai->component; diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index cdea0c09fe0a..dee1f0fa998b 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -19,6 +19,11 @@ static struct snd_soc_acpi_codecs max98357a_spk_codecs = { .codecs = {"MX98357A"} }; +static struct snd_soc_acpi_codecs max98390_spk_codecs = { + .num_codecs = 1, + .codecs = {"MX98390"} +}; + /* * The order of the three entries with .id = "10EC5682" matters * here, because DSDT tables expose an ACPI HID for the MAX98357A @@ -55,6 +60,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { .sof_fw_filename = "sof-cml.ri", .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", }, + { + .id = "DLGS7219", + .drv_name = "cml_da7219_max98357a", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &max98390_spk_codecs, + .sof_fw_filename = "sof-cml.ri", + .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines); diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index 45e07d886013..badafc1d54d2 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -12,7 +12,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = { { - .id = "INTC1027", + .id = "10EC5660", .drv_name = "ehl_rt5660", .sof_fw_filename = "sof-ehl.ri", .sof_tplg_filename = "sof-ehl-rt5660.tplg", diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index 859f8a1bd914..34f5fcad5701 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -19,6 +19,11 @@ static struct snd_soc_acpi_codecs rt1015_spk = { .codecs = {"10EC1015"} }; +static struct snd_soc_acpi_codecs mx98360a_spk = { + .num_codecs = 1, + .codecs = {"MX98360A"} +}; + /* * When adding new entry to the snd_soc_acpi_intel_jsl_machines array, * use .quirk_data member to distinguish different machine driver, @@ -47,6 +52,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { .quirk_data = &rt1015_spk, .sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg", }, + { + .id = "10EC5682", + .drv_name = "jsl_rt5682_max98360a", + .sof_fw_filename = "sof-jsl.ri", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &mx98360a_spk, + .sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines); diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 5a56f4359479..2ffa608d987d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -56,6 +56,19 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device mx8373_1_adr[] = { + { + .adr = 0x000123019F837300, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + }, + { + .adr = 0x000127019F837300, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + } +}; + static const struct snd_soc_acpi_adr_device rt5682_0_adr[] = { { .adr = 0x000021025D568200, @@ -93,6 +106,11 @@ static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = { .num_adr = ARRAY_SIZE(rt5682_0_adr), .adr_d = rt5682_0_adr, }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(mx8373_1_adr), + .adr_d = mx8373_1_adr, + }, {} }; @@ -140,6 +158,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg", }, { + .link_mask = 0x3, /* rt5682 on link0 & 2xmax98373 on link 1 */ + .links = tgl_chromebook_base, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg", + }, + { .link_mask = 0x1, /* this will only enable rt5682 for now */ .links = tgl_chromebook_base, .drv_name = "sof_sdw", diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c index 16ac16f5a641..b8d86c74c53d 100644 --- a/sound/soc/intel/haswell/sst-haswell-pcm.c +++ b/sound/soc/intel/haswell/sst-haswell-pcm.c @@ -462,7 +462,7 @@ static int hsw_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; @@ -652,7 +652,7 @@ static int hsw_pcm_hw_params(struct snd_soc_component *component, static int hsw_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; struct sst_hsw_stream *sst_stream; @@ -695,7 +695,7 @@ static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) struct hsw_pcm_data *pcm_data = data; struct snd_pcm_substream *substream = pcm_data->substream; struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_hsw *hsw = pdata->hsw; @@ -760,7 +760,7 @@ static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; @@ -785,7 +785,7 @@ static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_soc_component *component, static int hsw_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; struct sst_hsw *hsw = pdata->hsw; @@ -818,7 +818,7 @@ static int hsw_pcm_open(struct snd_soc_component *component, static int hsw_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; struct sst_hsw *hsw = pdata->hsw; diff --git a/sound/soc/intel/keembay/Makefile b/sound/soc/intel/keembay/Makefile new file mode 100644 index 000000000000..9084e8c63854 --- /dev/null +++ b/sound/soc/intel/keembay/Makefile @@ -0,0 +1,4 @@ +snd-soc-kmb_platform-objs := \ + kmb_platform.o + +obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += snd-soc-kmb_platform.o diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c new file mode 100644 index 000000000000..16f9fc4c663d --- /dev/null +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -0,0 +1,668 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (C) 2020 Intel Corporation. +// +// Intel KeemBay Platform driver. +// + +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/module.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include "kmb_platform.h" + +#define PERIODS_MIN 2 +#define PERIODS_MAX 48 +#define PERIOD_BYTES_MIN 4096 +#define BUFFER_BYTES_MAX (PERIODS_MAX * PERIOD_BYTES_MIN) +#define TDM_OPERATION 1 +#define I2S_OPERATION 0 +#define DATA_WIDTH_CONFIG_BIT 6 +#define TDM_CHANNEL_CONFIG_BIT 3 + +static const struct snd_pcm_hardware kmb_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, + .rate_min = 8000, + .rate_max = 48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = BUFFER_BYTES_MAX, + .period_bytes_min = PERIOD_BYTES_MIN, + .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN, + .periods_min = PERIODS_MIN, + .periods_max = PERIODS_MAX, + .fifo_size = 16, +}; + +static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_runtime *runtime, + unsigned int tx_ptr, bool *period_elapsed) +{ + unsigned int period_pos = tx_ptr % runtime->period_size; + void __iomem *i2s_base = kmb_i2s->i2s_base; + void *buf = runtime->dma_area; + int i; + + /* KMB i2s uses two separate L/R FIFO */ + for (i = 0; i < kmb_i2s->fifo_th; i++) { + if (kmb_i2s->config.data_width == 16) { + writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); + writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); + } else { + writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); + writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); + } + + period_pos++; + + if (++tx_ptr >= runtime->buffer_size) + tx_ptr = 0; + } + + *period_elapsed = period_pos >= runtime->period_size; + + return tx_ptr; +} + +static unsigned int kmb_pcm_rx_fn(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_runtime *runtime, + unsigned int rx_ptr, bool *period_elapsed) +{ + unsigned int period_pos = rx_ptr % runtime->period_size; + void __iomem *i2s_base = kmb_i2s->i2s_base; + void *buf = runtime->dma_area; + int i; + + /* KMB i2s uses two separate L/R FIFO */ + for (i = 0; i < kmb_i2s->fifo_th; i++) { + if (kmb_i2s->config.data_width == 16) { + ((u16(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0)); + ((u16(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0)); + } else { + ((u32(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0)); + ((u32(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0)); + } + + period_pos++; + + if (++rx_ptr >= runtime->buffer_size) + rx_ptr = 0; + } + + *period_elapsed = period_pos >= runtime->period_size; + + return rx_ptr; +} + +static inline void kmb_i2s_disable_channels(struct kmb_i2s_info *kmb_i2s, + u32 stream) +{ + u32 i; + + /* Disable all channels regardless of configuration*/ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < MAX_ISR; i++) + writel(0, kmb_i2s->i2s_base + TER(i)); + } else { + for (i = 0; i < MAX_ISR; i++) + writel(0, kmb_i2s->i2s_base + RER(i)); + } +} + +static inline void kmb_i2s_clear_irqs(struct kmb_i2s_info *kmb_i2s, u32 stream) +{ + struct i2s_clk_config_data *config = &kmb_i2s->config; + u32 i; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < config->chan_nr / 2; i++) + readl(kmb_i2s->i2s_base + TOR(i)); + } else { + for (i = 0; i < config->chan_nr / 2; i++) + readl(kmb_i2s->i2s_base + ROR(i)); + } +} + +static inline void kmb_i2s_irq_trigger(struct kmb_i2s_info *kmb_i2s, + u32 stream, int chan_nr, bool trigger) +{ + u32 i, irq; + u32 flag; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + flag = TX_INT_FLAG; + else + flag = RX_INT_FLAG; + + for (i = 0; i < chan_nr / 2; i++) { + irq = readl(kmb_i2s->i2s_base + IMR(i)); + + if (trigger) + irq = irq & ~flag; + else + irq = irq | flag; + + writel(irq, kmb_i2s->i2s_base + IMR(i)); + } +} + +static void kmb_pcm_operation(struct kmb_i2s_info *kmb_i2s, bool playback) +{ + struct snd_pcm_substream *substream; + bool period_elapsed; + unsigned int new_ptr; + unsigned int ptr; + + if (playback) + substream = kmb_i2s->tx_substream; + else + substream = kmb_i2s->rx_substream; + + if (!substream || !snd_pcm_running(substream)) + return; + + if (playback) { + ptr = kmb_i2s->tx_ptr; + new_ptr = kmb_pcm_tx_fn(kmb_i2s, substream->runtime, + ptr, &period_elapsed); + cmpxchg(&kmb_i2s->tx_ptr, ptr, new_ptr); + } else { + ptr = kmb_i2s->rx_ptr; + new_ptr = kmb_pcm_rx_fn(kmb_i2s, substream->runtime, + ptr, &period_elapsed); + cmpxchg(&kmb_i2s->rx_ptr, ptr, new_ptr); + } + + if (period_elapsed) + snd_pcm_period_elapsed(substream); +} + +static int kmb_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct kmb_i2s_info *kmb_i2s; + + kmb_i2s = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + snd_soc_set_runtime_hwparams(substream, &kmb_pcm_hardware); + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + runtime->private_data = kmb_i2s; + + return 0; +} + +static int kmb_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct kmb_i2s_info *kmb_i2s = runtime->private_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + kmb_i2s->tx_ptr = 0; + kmb_i2s->tx_substream = substream; + } else { + kmb_i2s->rx_ptr = 0; + kmb_i2s->rx_substream = substream; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + kmb_i2s->tx_substream = NULL; + else + kmb_i2s->rx_substream = NULL; + break; + default: + return -EINVAL; + } + + return 0; +} + +static irqreturn_t kmb_i2s_irq_handler(int irq, void *dev_id) +{ + struct kmb_i2s_info *kmb_i2s = dev_id; + struct i2s_clk_config_data *config = &kmb_i2s->config; + irqreturn_t ret = IRQ_NONE; + u32 isr[4]; + int i; + + for (i = 0; i < config->chan_nr / 2; i++) + isr[i] = readl(kmb_i2s->i2s_base + ISR(i)); + + kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK); + kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE); + + for (i = 0; i < config->chan_nr / 2; i++) { + /* + * Check if TX fifo is empty. If empty fill FIFO with samples + */ + if ((isr[i] & ISR_TXFE)) { + kmb_pcm_operation(kmb_i2s, true); + ret = IRQ_HANDLED; + } + /* + * Data available. Retrieve samples from FIFO + */ + if ((isr[i] & ISR_RXDA)) { + kmb_pcm_operation(kmb_i2s, false); + ret = IRQ_HANDLED; + } + /* Error Handling: TX */ + if (isr[i] & ISR_TXFO) { + dev_dbg(kmb_i2s->dev, "TX overrun (ch_id=%d)\n", i); + ret = IRQ_HANDLED; + } + /* Error Handling: RX */ + if (isr[i] & ISR_RXFO) { + dev_dbg(kmb_i2s->dev, "RX overrun (ch_id=%d)\n", i); + ret = IRQ_HANDLED; + } + } + + return ret; +} + +static int kmb_platform_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *soc_runtime) +{ + size_t size = kmb_pcm_hardware.buffer_bytes_max; + /* Use SNDRV_DMA_TYPE_CONTINUOUS as KMB doesn't use PCI sg buffer */ + snd_pcm_set_managed_buffer_all(soc_runtime->pcm, + SNDRV_DMA_TYPE_CONTINUOUS, + NULL, size, size); + return 0; +} + +static snd_pcm_uframes_t kmb_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct kmb_i2s_info *kmb_i2s = runtime->private_data; + snd_pcm_uframes_t pos; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + pos = kmb_i2s->tx_ptr; + else + pos = kmb_i2s->rx_ptr; + + return pos < runtime->buffer_size ? pos : 0; +} + +static const struct snd_soc_component_driver kmb_component = { + .name = "kmb", + .pcm_construct = kmb_platform_pcm_new, + .open = kmb_pcm_open, + .trigger = kmb_pcm_trigger, + .pointer = kmb_pcm_pointer, +}; + +static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_substream *substream) +{ + struct i2s_clk_config_data *config = &kmb_i2s->config; + + /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */ + writel(1, kmb_i2s->i2s_base + IER); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(1, kmb_i2s->i2s_base + ITER); + else + writel(1, kmb_i2s->i2s_base + IRER); + + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, config->chan_nr, true); + + if (kmb_i2s->master) + writel(1, kmb_i2s->i2s_base + CER); + else + writel(0, kmb_i2s->i2s_base + CER); +} + +static void kmb_i2s_stop(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_substream *substream) +{ + /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */ + kmb_i2s_clear_irqs(kmb_i2s, substream->stream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(0, kmb_i2s->i2s_base + ITER); + else + writel(0, kmb_i2s->i2s_base + IRER); + + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false); + + if (!kmb_i2s->active) { + writel(0, kmb_i2s->i2s_base + CER); + writel(0, kmb_i2s->i2s_base + IER); + } +} + +static void kmb_disable_clk(void *clk) +{ + clk_disable_unprepare(clk); +} + +static int kmb_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + int ret; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + kmb_i2s->master = false; + ret = 0; + break; + case SND_SOC_DAIFMT_CBS_CFS: + writel(MASTER_MODE, kmb_i2s->pss_base + I2S_GEN_CFG_0); + + ret = clk_prepare_enable(kmb_i2s->clk_i2s); + if (ret < 0) + return ret; + + ret = devm_add_action_or_reset(kmb_i2s->dev, kmb_disable_clk, + kmb_i2s->clk_i2s); + if (ret) + return ret; + + kmb_i2s->master = true; + break; + default: + return -EINVAL; + } + + return ret; +} + +static int kmb_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* Keep track of i2s activity before turn off + * the i2s interface + */ + kmb_i2s->active++; + kmb_i2s_start(kmb_i2s, substream); + break; + case SNDRV_PCM_TRIGGER_STOP: + kmb_i2s->active--; + kmb_i2s_stop(kmb_i2s, substream); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void kmb_i2s_config(struct kmb_i2s_info *kmb_i2s, int stream) +{ + struct i2s_clk_config_data *config = &kmb_i2s->config; + u32 ch_reg; + + kmb_i2s_disable_channels(kmb_i2s, stream); + + for (ch_reg = 0; ch_reg < config->chan_nr / 2; ch_reg++) { + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + writel(kmb_i2s->xfer_resolution, + kmb_i2s->i2s_base + TCR(ch_reg)); + + writel(kmb_i2s->fifo_th - 1, + kmb_i2s->i2s_base + TFCR(ch_reg)); + + writel(1, kmb_i2s->i2s_base + TER(ch_reg)); + } else { + writel(kmb_i2s->xfer_resolution, + kmb_i2s->i2s_base + RCR(ch_reg)); + + writel(kmb_i2s->fifo_th - 1, + kmb_i2s->i2s_base + RFCR(ch_reg)); + + writel(1, kmb_i2s->i2s_base + RER(ch_reg)); + } + } +} + +static int kmb_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + struct i2s_clk_config_data *config = &kmb_i2s->config; + u32 register_val, write_val; + int ret; + + switch (params_format(hw_params)) { + case SNDRV_PCM_FORMAT_S16_LE: + config->data_width = 16; + kmb_i2s->ccr = 0x00; + kmb_i2s->xfer_resolution = 0x02; + break; + case SNDRV_PCM_FORMAT_S24_LE: + config->data_width = 24; + kmb_i2s->ccr = 0x08; + kmb_i2s->xfer_resolution = 0x04; + break; + case SNDRV_PCM_FORMAT_S32_LE: + config->data_width = 32; + kmb_i2s->ccr = 0x10; + kmb_i2s->xfer_resolution = 0x05; + break; + default: + dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt"); + return -EINVAL; + } + + config->chan_nr = params_channels(hw_params); + + switch (config->chan_nr) { + /* TODO: This switch case will handle up to TDM8 in the near future */ + case TWO_CHANNEL_SUPPORT: + write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) | + (config->data_width << DATA_WIDTH_CONFIG_BIT) | + MASTER_MODE | I2S_OPERATION; + + writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0); + + register_val = readl(kmb_i2s->pss_base + I2S_GEN_CFG_0); + dev_dbg(kmb_i2s->dev, "pss register = 0x%X", register_val); + break; + default: + dev_dbg(kmb_i2s->dev, "channel not supported\n"); + return -EINVAL; + } + + kmb_i2s_config(kmb_i2s, substream->stream); + + writel(kmb_i2s->ccr, kmb_i2s->i2s_base + CCR); + + config->sample_rate = params_rate(hw_params); + + if (kmb_i2s->master) { + /* Only 2 ch supported in Master mode */ + u32 bitclk = config->sample_rate * config->data_width * 2; + + ret = clk_set_rate(kmb_i2s->clk_i2s, bitclk); + if (ret) { + dev_err(kmb_i2s->dev, + "Can't set I2S clock rate: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int kmb_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(1, kmb_i2s->i2s_base + TXFFR); + else + writel(1, kmb_i2s->i2s_base + RXFFR); + + return 0; +} + +static struct snd_soc_dai_ops kmb_dai_ops = { + .trigger = kmb_dai_trigger, + .hw_params = kmb_dai_hw_params, + .prepare = kmb_dai_prepare, + .set_fmt = kmb_set_dai_fmt, +}; + +static struct snd_soc_dai_driver intel_kmb_platform_dai[] = { + { + .name = "kmb-plat-dai", + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, + .rate_min = 8000, + .rate_max = 48000, + .formats = (SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S16_LE), + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + /* + * .channels_max will be overwritten + * if provided by Device Tree + */ + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, + .rate_min = 8000, + .rate_max = 48000, + .formats = (SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S16_LE), + }, + .ops = &kmb_dai_ops, + }, +}; + +static int kmb_plat_dai_probe(struct platform_device *pdev) +{ + struct snd_soc_dai_driver *kmb_i2s_dai; + struct device *dev = &pdev->dev; + struct kmb_i2s_info *kmb_i2s; + int ret, irq; + u32 comp1_reg; + + kmb_i2s = devm_kzalloc(dev, sizeof(*kmb_i2s), GFP_KERNEL); + if (!kmb_i2s) + return -ENOMEM; + + kmb_i2s_dai = devm_kzalloc(dev, sizeof(*kmb_i2s_dai), GFP_KERNEL); + if (!kmb_i2s_dai) + return -ENOMEM; + + kmb_i2s_dai->ops = &kmb_dai_ops; + + /* Prepare the related clocks */ + kmb_i2s->clk_apb = devm_clk_get(dev, "apb_clk"); + if (IS_ERR(kmb_i2s->clk_apb)) { + dev_err(dev, "Failed to get apb clock\n"); + return PTR_ERR(kmb_i2s->clk_apb); + } + + ret = clk_prepare_enable(kmb_i2s->clk_apb); + if (ret < 0) + return ret; + + ret = devm_add_action_or_reset(dev, kmb_disable_clk, kmb_i2s->clk_apb); + if (ret) { + dev_err(dev, "Failed to add clk_apb reset action\n"); + return ret; + } + + kmb_i2s->clk_i2s = devm_clk_get(dev, "osc"); + if (IS_ERR(kmb_i2s->clk_i2s)) { + dev_err(dev, "Failed to get osc clock\n"); + return PTR_ERR(kmb_i2s->clk_i2s); + } + + kmb_i2s->i2s_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(kmb_i2s->i2s_base)) + return PTR_ERR(kmb_i2s->i2s_base); + + kmb_i2s->pss_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(kmb_i2s->pss_base)) + return PTR_ERR(kmb_i2s->pss_base); + + kmb_i2s->dev = &pdev->dev; + + irq = platform_get_irq_optional(pdev, 0); + if (irq > 0) { + ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0, + pdev->name, kmb_i2s); + if (ret < 0) { + dev_err(dev, "failed to request irq\n"); + return ret; + } + } + + comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1); + + kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2; + + ret = devm_snd_soc_register_component(dev, &kmb_component, + intel_kmb_platform_dai, + ARRAY_SIZE(intel_kmb_platform_dai)); + if (ret) { + dev_err(dev, "not able to register dai\n"); + return ret; + } + + /* To ensure none of the channels are enabled at boot up */ + kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK); + kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE); + + dev_set_drvdata(dev, kmb_i2s); + + return ret; +} + +static const struct of_device_id kmb_plat_of_match[] = { + { .compatible = "intel,keembay-i2s", }, + {} +}; + +static struct platform_driver kmb_plat_dai_driver = { + .driver = { + .name = "kmb-plat-dai", + .of_match_table = kmb_plat_of_match, + }, + .probe = kmb_plat_dai_probe, +}; + +module_platform_driver(kmb_plat_dai_driver); + +MODULE_DESCRIPTION("ASoC Intel KeemBay Platform driver"); +MODULE_AUTHOR("Sia Jee Heng <jee.heng.sia@intel.com>"); +MODULE_AUTHOR("Sit, Michael Wei Hong <michael.wei.hong.sit@intel.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:kmb_platform"); diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h new file mode 100644 index 000000000000..9756b132c12f --- /dev/null +++ b/sound/soc/intel/keembay/kmb_platform.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Intel KeemBay Platform driver + * + * Copyright (C) 2020 Intel Corporation. + * + */ + +#ifndef KMB_PLATFORM_H_ +#define KMB_PLATFORM_H_ + +#include <linux/bits.h> +#include <linux/bitfield.h> +#include <linux/types.h> + +/* Register values with reference to KMB databook v1.1 */ +/* common register for all channel */ +#define IER 0x000 +#define IRER 0x004 +#define ITER 0x008 +#define CER 0x00C +#define CCR 0x010 +#define RXFFR 0x014 +#define TXFFR 0x018 + +/* Interrupt status register fields */ +#define ISR_TXFO BIT(5) +#define ISR_TXFE BIT(4) +#define ISR_RXFO BIT(1) +#define ISR_RXDA BIT(0) + +/* I2S Tx Rx Registers for all channels */ +#define LRBR_LTHR(x) (0x40 * (x) + 0x020) +#define RRBR_RTHR(x) (0x40 * (x) + 0x024) +#define RER(x) (0x40 * (x) + 0x028) +#define TER(x) (0x40 * (x) + 0x02C) +#define RCR(x) (0x40 * (x) + 0x030) +#define TCR(x) (0x40 * (x) + 0x034) +#define ISR(x) (0x40 * (x) + 0x038) +#define IMR(x) (0x40 * (x) + 0x03C) +#define ROR(x) (0x40 * (x) + 0x040) +#define TOR(x) (0x40 * (x) + 0x044) +#define RFCR(x) (0x40 * (x) + 0x048) +#define TFCR(x) (0x40 * (x) + 0x04C) +#define RFF(x) (0x40 * (x) + 0x050) +#define TFF(x) (0x40 * (x) + 0x054) + +/* I2S COMP Registers */ +#define I2S_COMP_PARAM_2 0x01F0 +#define I2S_COMP_PARAM_1 0x01F4 +#define I2S_COMP_VERSION 0x01F8 +#define I2S_COMP_TYPE 0x01FC + +/* PSS_GEN_CTRL_I2S_GEN_CFG_0 Registers */ +#define I2S_GEN_CFG_0 0x000 +#define PSS_CPR_RST_EN 0x010 +#define PSS_CPR_RST_SET 0x014 +#define PSS_CPR_CLK_CLR 0x000 +#define PSS_CPR_AUX_RST_EN 0x070 + +#define MASTER_MODE BIT(13) + +/* Interrupt Flag */ +#define TX_INT_FLAG GENMASK(5, 4) +#define RX_INT_FLAG GENMASK(1, 0) +/* + * Component parameter register fields - define the I2S block's + * configuration. + */ +#define COMP1_TX_WORDSIZE_3(r) FIELD_GET(GENMASK(27, 25), (r)) +#define COMP1_TX_WORDSIZE_2(r) FIELD_GET(GENMASK(24, 22), (r)) +#define COMP1_TX_WORDSIZE_1(r) FIELD_GET(GENMASK(21, 19), (r)) +#define COMP1_TX_WORDSIZE_0(r) FIELD_GET(GENMASK(18, 16), (r)) +#define COMP1_RX_ENABLED(r) FIELD_GET(BIT(6), (r)) +#define COMP1_TX_ENABLED(r) FIELD_GET(BIT(5), (r)) +#define COMP1_MODE_EN(r) FIELD_GET(BIT(4), (r)) +#define COMP1_APB_DATA_WIDTH(r) FIELD_GET(GENMASK(1, 0), (r)) +#define COMP2_RX_WORDSIZE_3(r) FIELD_GET(GENMASK(12, 10), (r)) +#define COMP2_RX_WORDSIZE_2(r) FIELD_GET(GENMASK(9, 7), (r)) +#define COMP2_RX_WORDSIZE_1(r) FIELD_GET(GENMASK(5, 3), (r)) +#define COMP2_RX_WORDSIZE_0(r) FIELD_GET(GENMASK(2, 0), (r)) + +/* Add 1 to the below registers to indicate the actual size */ +#define COMP1_TX_CHANNELS(r) (FIELD_GET(GENMASK(10, 9), (r)) + 1) +#define COMP1_RX_CHANNELS(r) (FIELD_GET(GENMASK(8, 7), (r)) + 1) +#define COMP1_FIFO_DEPTH(r) (FIELD_GET(GENMASK(3, 2), (r)) + 1) + +/* Number of entries in WORDSIZE and DATA_WIDTH parameter registers */ +#define COMP_MAX_WORDSIZE 8 /* 3 bits register width */ + +#define MAX_CHANNEL_NUM 8 +#define MIN_CHANNEL_NUM 2 +#define MAX_ISR 4 + +#define TWO_CHANNEL_SUPPORT 2 /* up to 2.0 */ +#define FOUR_CHANNEL_SUPPORT 4 /* up to 3.1 */ +#define SIX_CHANNEL_SUPPORT 6 /* up to 5.1 */ +#define EIGHT_CHANNEL_SUPPORT 8 /* up to 7.1 */ + +#define DWC_I2S_PLAY BIT(0) +#define DWC_I2S_RECORD BIT(1) +#define DW_I2S_SLAVE BIT(2) +#define DW_I2S_MASTER BIT(3) + +#define I2S_RXDMA 0x01C0 +#define I2S_TXDMA 0x01C8 + +/* + * struct i2s_clk_config_data - represent i2s clk configuration data + * @chan_nr: number of channel + * @data_width: number of bits per sample (8/16/24/32 bit) + * @sample_rate: sampling frequency (8Khz, 16Khz, 48Khz) + */ +struct i2s_clk_config_data { + int chan_nr; + u32 data_width; + u32 sample_rate; +}; + +struct kmb_i2s_info { + void __iomem *i2s_base; + void __iomem *pss_base; + struct clk *clk_i2s; + struct clk *clk_apb; + int active; + unsigned int capability; + unsigned int i2s_reg_comp1; + unsigned int i2s_reg_comp2; + struct device *dev; + u32 ccr; + u32 xfer_resolution; + u32 fifo_th; + bool master; + + struct i2s_clk_config_data config; + int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); + + /* data related to PIO transfers */ + bool use_pio; + struct snd_pcm_substream *tx_substream; + struct snd_pcm_substream *rx_substream; + unsigned int tx_ptr; + unsigned int rx_ptr; +}; + +#endif /* KMB_PLATFORM_H_ */ diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 89dcccdfb1cd..5dee55e9546b 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -544,7 +544,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, { struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *link_dev; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct skl_pipe_params p_params = {0}; struct hdac_ext_link *link; @@ -634,7 +634,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hdac_ext_stream *link_dev = snd_soc_dai_get_dma_data(dai, substream); struct hdac_ext_link *link; @@ -1071,7 +1071,7 @@ int skl_dai_load(struct snd_soc_component *cmp, int index, static int skl_platform_soc_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai_link *dai_link = rtd->dai_link; dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "In %s:%s\n", __func__, @@ -1225,7 +1225,7 @@ static int skl_platform_soc_mmap(struct snd_soc_component *component, static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, u64 nsec) { - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); u64 codec_frames, codec_nsecs; @@ -1509,11 +1509,9 @@ int skl_platform_unregister(struct device *dev) struct skl_dev *skl = bus_to_skl(bus); struct skl_module_deferred_bind *modules, *tmp; - if (!list_empty(&skl->bind_list)) { - list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { - list_del(&modules->node); - kfree(modules); - } + list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { + list_del(&modules->node); + kfree(modules); } kfree(skl->dais); diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index b9aab47d1202..b7d2d97d12a7 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -3773,9 +3773,8 @@ void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) struct skl_dev *skl = bus_to_skl(bus); struct skl_pipeline *ppl, *tmp; - if (!list_empty(&skl->ppl_list)) - list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) - list_del(&ppl->node); + list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) + list_del(&ppl->node); /* clean up topology */ snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 9889f728752c..5e93ad85e06d 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -97,7 +97,7 @@ struct skl_audio_data_format { u8 number_of_channels; u8 valid_bit_depth; u8 sample_type; - u8 reserved[1]; + u8 reserved; } __packed; struct skl_base_cfg { diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c index 4f66b011f1b4..8e44ae37ad1e 100644 --- a/sound/soc/kirkwood/armada-370-db.c +++ b/sound/soc/kirkwood/armada-370-db.c @@ -18,7 +18,7 @@ static int a370db_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int freq; diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index a656d2014127..f7bc007bbdec 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -118,30 +118,34 @@ config SND_SOC_MT8183 If unsure select "N". config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A - tristate "ASoC Audio driver for MT8183 with MT6358 TS3A227E MAX98357A codec" + tristate "ASoC Audio driver for MT8183 with MT6358 TS3A227E MAX98357A RT1015 codec" depends on I2C depends on SND_SOC_MT8183 select SND_SOC_MT6358 select SND_SOC_MAX98357A + select SND_SOC_RT1015 select SND_SOC_BT_SCO select SND_SOC_TS3A227E select SND_SOC_CROS_EC_CODEC if CROS_EC + select SND_SOC_HDMI_CODEC help This adds ASoC driver for Mediatek MT8183 boards - with the MT6358 TS3A227E MAX98357A audio codec. + with the MT6358 TS3A227E MAX98357A RT1015 audio codec. Select Y if you have such device. 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 + select SND_SOC_HDMI_CODEC 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/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index 375e3b492922..882cdf86c8bf 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -37,7 +37,7 @@ static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val) int mtk_afe_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct snd_pcm_runtime *runtime = substream->runtime; int memif_num = asoc_rtd_to_cpu(rtd, 0)->id; @@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_fe_startup); void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id]; int irq_id; @@ -120,7 +120,7 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = asoc_rtd_to_cpu(rtd, 0)->id; struct mtk_base_afe_memif *memif = &afe->memif[id]; @@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_free); int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime * const runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = asoc_rtd_to_cpu(rtd, 0)->id; @@ -263,7 +263,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_fe_trigger); int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = asoc_rtd_to_cpu(rtd, 0)->id; int pbuf_size; @@ -505,7 +505,7 @@ EXPORT_SYMBOL_GPL(mtk_memif_set_rate); int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, int id, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c index 0a1a65c86f0e..01501d5747a7 100644 --- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c +++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c @@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control); snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id]; const struct mtk_base_memif_data *memif_data = memif->data; diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index f0250b0dd734..df29641c74aa 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -494,7 +494,7 @@ static int mt2701_dlm_fe_trigger(struct snd_pcm_substream *substream, static int mt2701_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int fs; if (asoc_rtd_to_cpu(rtd, 0)->id != MT2701_MEMIF_ULBT) diff --git a/sound/soc/mediatek/mt2701/mt2701-cs42448.c b/sound/soc/mediatek/mt2701/mt2701-cs42448.c index c47af9b6949b..44a8d5cfb0aa 100644 --- a/sound/soc/mediatek/mt2701/mt2701-cs42448.c +++ b/sound/soc/mediatek/mt2701/mt2701-cs42448.c @@ -127,7 +127,7 @@ static const struct snd_soc_ops mt2701_cs42448_48k_fe_ops = { static int mt2701_cs42448_be_ops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int mclk_rate; diff --git a/sound/soc/mediatek/mt2701/mt2701-wm8960.c b/sound/soc/mediatek/mt2701/mt2701-wm8960.c index 0122e7df067f..414e422c0eba 100644 --- a/sound/soc/mediatek/mt2701/mt2701-wm8960.c +++ b/sound/soc/mediatek/mt2701/mt2701-wm8960.c @@ -24,7 +24,7 @@ static const struct snd_kcontrol_new mt2701_wm8960_controls[] = { static int mt2701_wm8960_be_ops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int mclk_rate; diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index 7f3ac04b9425..3d68e4726ea2 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -139,7 +139,7 @@ static const struct snd_pcm_hardware mt6797_afe_hardware = { static int mt6797_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -150,7 +150,7 @@ static int mt6797_memif_fs(struct snd_pcm_substream *substream, static int mt6797_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 1cc044425a9e..7e7bda70d12e 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -482,7 +482,7 @@ static int mt8173_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, static int mt8173_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id]; diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index 37693d354e66..fc94314bfc02 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c @@ -52,7 +52,7 @@ static const struct snd_kcontrol_new mt8173_max98090_controls[] = { static int mt8173_max98090_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); return snd_soc_dai_set_sysclk(codec_dai, 0, params_rate(params) * 256, diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c index 51009a172777..0f28dc2217c0 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c @@ -43,7 +43,7 @@ static const struct snd_kcontrol_new mt8173_rt5650_rt5514_controls[] = { static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int i, ret; diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index 247ac7690805..077c6ee06780 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c @@ -47,7 +47,7 @@ static const struct snd_kcontrol_new mt8173_rt5650_rt5676_controls[] = { static int mt8173_rt5650_rt5676_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int i, ret; diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 2065c94dbf99..347b095d478d 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -58,7 +58,7 @@ static const struct snd_kcontrol_new mt8173_rt5650_controls[] = { static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int mclk_clock; struct snd_soc_dai *codec_dai; int i, ret; diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index e0c4714da92c..c4a598cbbdaa 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -142,7 +142,7 @@ static const struct snd_pcm_hardware mt8183_afe_hardware = { static int mt8183_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -153,7 +153,7 @@ static int mt8183_memif_fs(struct snd_pcm_substream *substream, static int mt8183_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index ffd7c931e7bb..06d0a4f80fc1 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -8,23 +8,32 @@ #include <linux/input.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> +#include <sound/hdmi-codec.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; + struct snd_soc_jack headset_jack, hdmi_jack; }; static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 128; unsigned int mclk_fs = rate * mclk_fs_ratio; @@ -40,7 +49,7 @@ static const struct snd_soc_ops mt8183_mt6358_i2s_ops = { static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 256; @@ -54,8 +63,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, @@ -82,13 +90,12 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; 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 +114,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 = asoc_substream_to_rtd(substream); + 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 +171,58 @@ 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) +{ + static const unsigned int rates[] = { + 48000, + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const unsigned int channels[] = { + 2, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_pcm_runtime *runtime = substream->runtime; + + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + runtime->hw.channels_max = 2; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); + + return 0; +} + +static const struct snd_soc_ops mt8183_da7219_max98357_ops = { + .startup = mt8183_da7219_max98357_startup, +}; + static int mt8183_da7219_max98357_bt_sco_startup( struct snd_pcm_substream *substream) @@ -228,13 +332,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, @@ -244,10 +355,25 @@ SND_SOC_DAILINK_DEFS(i2s5, SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_CPU("TDM")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), DAILINK_COMP_ARRAY(COMP_EMPTY())); -static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { +static int mt8183_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8183_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) + return ret; + + return hdmi_codec_set_jack_detect(asoc_rtd_to_codec(rtd, 0)->component, + &priv->hdmi_jack); +} + +static struct snd_soc_dai_link mt8183_da7219_dai_links[] = { /* FE */ { .name = "Playback_1", @@ -256,6 +382,7 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + .ops = &mt8183_da7219_max98357_ops, SND_SOC_DAILINK_REG(playback1), }, { @@ -303,6 +430,7 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + .ops = &mt8183_da7219_max98357_ops, SND_SOC_DAILINK_REG(capture3), }, { @@ -380,9 +508,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", @@ -402,12 +527,42 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, + .init = mt8183_da7219_max98357_hdmi_init, SND_SOC_DAILINK_REG(tdm), }, }; 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(), @@ -446,57 +601,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 device_node *platform_node; + struct snd_soc_card *card; + struct device_node *platform_node, *hdmi_codec; 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) { @@ -504,10 +658,52 @@ 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; + + hdmi_codec = of_parse_phandle(pdev->dev.of_node, + "mediatek,hdmi-codec", 0); + 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 (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) + dai_link->codecs->of_node = hdmi_codec; + + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; } mt8183_da7219_max98357_headset_dev.dlc.of_node = @@ -538,14 +734,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/mediatek/mt8183/mt8183-dai-i2s.c b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c index 777e93d70bea..138591d71ebd 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c @@ -49,6 +49,8 @@ struct mtk_afe_i2s_priv { int mclk_id; int mclk_rate; int mclk_apll; + + int use_eiaj; }; static unsigned int get_i2s_wlen(snd_pcm_format_t format) @@ -711,7 +713,7 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, unsigned int rate_reg = mt8183_rate_transform(afe->dev, rate, i2s_id); snd_pcm_format_t format = params_format(params); - unsigned int i2s_con = 0; + unsigned int i2s_con = 0, fmt_con = I2S_FMT_I2S << I2S_FMT_SFT; int ret = 0; dev_info(afe->dev, "%s(), id %d, rate %d, format %d\n", @@ -719,17 +721,21 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, i2s_id, rate, format); - if (i2s_priv) + if (i2s_priv) { i2s_priv->rate = rate; - else + + if (i2s_priv->use_eiaj) + fmt_con = I2S_FMT_EIAJ << I2S_FMT_SFT; + } else { dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__); + } switch (i2s_id) { case MT8183_DAI_I2S_0: regmap_update_bits(afe->regmap, AFE_DAC_CON1, I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT); i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT; - i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON, 0xffffeffe, i2s_con); @@ -737,7 +743,7 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, case MT8183_DAI_I2S_1: i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT; i2s_con |= rate_reg << I2S2_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0xffffeffe, i2s_con); @@ -745,21 +751,21 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, case MT8183_DAI_I2S_2: i2s_con = 8 << I2S3_UPDATE_WORD_SFT; i2s_con |= rate_reg << I2S3_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0xffffeffe, i2s_con); break; case MT8183_DAI_I2S_3: i2s_con = rate_reg << I2S4_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON3, 0xffffeffe, i2s_con); break; case MT8183_DAI_I2S_5: i2s_con = rate_reg << I2S5_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S5_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S5_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON4, 0xffffeffe, i2s_con); @@ -841,9 +847,46 @@ static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai, return 0; } +static int mtk_dai_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8183_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv; + + switch (dai->id) { + case MT8183_DAI_I2S_0: + case MT8183_DAI_I2S_1: + case MT8183_DAI_I2S_2: + case MT8183_DAI_I2S_3: + case MT8183_DAI_I2S_5: + break; + default: + dev_warn(afe->dev, "%s(), id %d not support\n", + __func__, dai->id); + return -EINVAL; + } + i2s_priv = afe_priv->dai_priv[dai->id]; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_LEFT_J: + i2s_priv->use_eiaj = 1; + break; + case SND_SOC_DAIFMT_I2S: + i2s_priv->use_eiaj = 0; + break; + default: + dev_warn(afe->dev, "%s(), DAI format %d not support\n", + __func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + return 0; +} + static const struct snd_soc_dai_ops mtk_dai_i2s_ops = { .hw_params = mtk_dai_i2s_hw_params, .set_sysclk = mtk_dai_i2s_set_sysclk, + .set_fmt = mtk_dai_i2s_set_fmt, }; /* dai driver */ diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 1fca8df109b4..07410d7afaa9 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -7,13 +7,20 @@ // Author: Shunli Wang <shunli.wang@mediatek.com> #include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pinctrl/consumer.h> +#include <sound/hdmi-codec.h> +#include <sound/jack.h> #include <sound/pcm_params.h> #include <sound/soc.h> -#include <sound/jack.h> -#include <linux/pinctrl/consumer.h> -#include "mt8183-afe-common.h" +#include "../../codecs/rt1015.h" #include "../../codecs/ts3a227e.h" +#include "mt8183-afe-common.h" + +#define RT1015_CODEC_DAI "rt1015-aif" +#define RT1015_DEV0_NAME "rt1015.6-0028" +#define RT1015_DEV1_NAME "rt1015.6-0029" enum PINCTRL_PIN_STATE { PIN_STATE_DEFAULT = 0, @@ -30,13 +37,13 @@ static const char * const mt8183_pin_str[PIN_STATE_MAX] = { struct mt8183_mt6358_ts3a227_max98357_priv { struct pinctrl *pinctrl; struct pinctrl_state *pin_states[PIN_STATE_MAX]; - struct snd_soc_jack headset_jack; + struct snd_soc_jack headset_jack, hdmi_jack; }; static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 128; unsigned int mclk_fs = rate * mclk_fs_ratio; @@ -49,6 +56,48 @@ static const struct snd_soc_ops mt8183_mt6358_i2s_ops = { .hw_params = mt8183_mt6358_i2s_hw_params, }; +static int +mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 128; + unsigned int mclk_fs = rate * mclk_fs_ratio; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai; + int ret, i; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) { + dev_err(card->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 < 0) { + dev_err(card->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 < 0) { + dev_err(card->dev, "failed to set sysclk\n"); + return ret; + } + } + + return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), + 0, mclk_fs, SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8183_mt6358_rt1015_i2s_ops = { + .hw_params = mt8183_mt6358_rt1015_i2s_hw_params, +}; + static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -62,6 +111,19 @@ 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) +{ + dev_dbg(rtd->dev, "%s(), fix format to 32bit\n", __func__); + + /* 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_mt6358_ts3a227_max98357_bt_sco_startup( struct snd_pcm_substream *substream) @@ -179,11 +241,17 @@ SND_SOC_DAILINK_DEFS(i2s2, DAILINK_COMP_ARRAY(COMP_DUMMY()), 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")), 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)), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + SND_SOC_DAILINK_DEFS(i2s5, DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), @@ -191,12 +259,12 @@ SND_SOC_DAILINK_DEFS(i2s5, SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_CPU("TDM")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), DAILINK_COMP_ARRAY(COMP_EMPTY())); static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -215,7 +283,7 @@ static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) static void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -239,7 +307,7 @@ static int mt8183_mt6358_ts3a227_max98357_wov_startup( struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(card); @@ -252,7 +320,7 @@ static void mt8183_mt6358_ts3a227_max98357_wov_shutdown( struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(card); @@ -270,8 +338,23 @@ static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_wov_ops = { .shutdown = mt8183_mt6358_ts3a227_max98357_wov_shutdown, }; -static struct snd_soc_dai_link -mt8183_mt6358_ts3a227_max98357_dai_links[] = { +static int +mt8183_mt6358_ts3a227_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8183_mt6358_ts3a227_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) + return ret; + + return hdmi_codec_set_jack_detect(asoc_rtd_to_codec(rtd, 0)->component, + &priv->hdmi_jack); +} + +static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = { /* FE */ { .name = "Playback_1", @@ -413,9 +496,6 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, - .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, - .ops = &mt8183_mt6358_i2s_ops, - SND_SOC_DAILINK_REG(i2s3), }, { .name = "I2S5", @@ -436,6 +516,7 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_tdm_ops, + .init = mt8183_mt6358_ts3a227_max98357_hdmi_init, SND_SOC_DAILINK_REG(tdm), }, }; @@ -443,8 +524,35 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { .name = "mt8183_mt6358_ts3a227_max98357", .owner = THIS_MODULE, - .dai_link = mt8183_mt6358_ts3a227_max98357_dai_links, - .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dai_links), + .dai_link = mt8183_mt6358_ts3a227_dai_links, + .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), +}; + +static struct snd_soc_card mt8183_mt6358_ts3a227_max98357b_card = { + .name = "mt8183_mt6358_ts3a227_max98357b", + .owner = THIS_MODULE, + .dai_link = mt8183_mt6358_ts3a227_dai_links, + .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), +}; + +static struct snd_soc_codec_conf mt8183_mt6358_ts3a227_rt1015_amp_conf[] = { + { + .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), + .name_prefix = "Right", + }, +}; + +static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015_card = { + .name = "mt8183_mt6358_ts3a227_rt1015", + .owner = THIS_MODULE, + .dai_link = mt8183_mt6358_ts3a227_dai_links, + .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), + .codec_conf = mt8183_mt6358_ts3a227_rt1015_amp_conf, + .num_configs = ARRAY_SIZE(mt8183_mt6358_ts3a227_rt1015_amp_conf), }; static int @@ -455,7 +563,7 @@ mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) snd_soc_card_get_drvdata(component->card); /* Enable Headset and 4 Buttons Jack detection */ - ret = snd_soc_card_jack_new(&mt8183_mt6358_ts3a227_max98357_card, + ret = snd_soc_card_jack_new(component->card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | @@ -478,14 +586,12 @@ static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = { static int mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) { - struct snd_soc_card *card = &mt8183_mt6358_ts3a227_max98357_card; - struct device_node *platform_node, *ec_codec; + struct snd_soc_card *card; + struct device_node *platform_node, *ec_codec, *hdmi_codec; struct snd_soc_dai_link *dai_link; struct mt8183_mt6358_ts3a227_max98357_priv *priv; - int ret; - int i; - - card->dev = &pdev->dev; + const struct of_device_id *match; + int ret, i; platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); @@ -494,12 +600,18 @@ mt8183_mt6358_ts3a227_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; + ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0); + hdmi_codec = of_parse_phandle(pdev->dev.of_node, + "mediatek,hdmi-codec", 0); for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platforms->name) - continue; - if (ec_codec && strcmp(dai_link->name, "Wake on Voice") == 0) { dai_link->cpus[0].name = NULL; dai_link->cpus[0].of_node = ec_codec; @@ -509,9 +621,52 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) dai_link->codecs[0].dai_name = "Wake on Voice"; dai_link->platforms[0].of_node = ec_codec; dai_link->ignore = 0; - } else { - dai_link->platforms->of_node = platform_node; } + + if (strcmp(dai_link->name, "I2S3") == 0) { + if (card == &mt8183_mt6358_ts3a227_max98357_card || + card == &mt8183_mt6358_ts3a227_max98357b_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_mt6358_ts3a227_rt1015_card) { + dai_link->be_hw_params_fixup = + mt8183_rt1015_i2s_hw_params_fixup; + dai_link->ops = &mt8183_mt6358_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 (card == &mt8183_mt6358_ts3a227_max98357b_card) { + if (strcmp(dai_link->name, "I2S2") == 0 || + strcmp(dai_link->name, "I2S3") == 0) + dai_link->dai_fmt = SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM; + } + + if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) + dai_link->codecs->of_node = hdmi_codec; + + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; } mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node = @@ -568,14 +723,25 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match[] = { - {.compatible = "mediatek,mt8183_mt6358_ts3a227_max98357",}, + { + .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357", + .data = &mt8183_mt6358_ts3a227_max98357_card, + }, + { + .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357b", + .data = &mt8183_mt6358_ts3a227_max98357b_card, + }, + { + .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015", + .data = &mt8183_mt6358_ts3a227_rt1015_card, + }, {} }; #endif static struct platform_driver mt8183_mt6358_ts3a227_max98357_driver = { .driver = { - .name = "mt8183_mt6358_ts3a227_max98357", + .name = "mt8183_mt6358_ts3a227", #ifdef CONFIG_OF .of_match_table = mt8183_mt6358_ts3a227_max98357_dt_match, #endif diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 8b6295283989..363dc3b1bbe4 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -68,6 +68,7 @@ config SND_MESON_AXG_SOUND_CARD imply SND_MESON_AXG_SPDIFOUT imply SND_MESON_AXG_SPDIFIN imply SND_MESON_AXG_PDM + imply SND_MESON_G12A_TOACODEC imply SND_MESON_G12A_TOHDMITX if DRM_MESON_DW_HDMI help Select Y or M to add support for the AXG SoC sound card diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index 832e22d275fe..932224552146 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -72,11 +72,10 @@ static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component, { /* Always operate in split (classic interleaved) mode */ unsigned int desc = AIU_I2S_SOURCE_DESC_MODE_SPLIT; - unsigned int val; /* Reset required to update the pipeline */ snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST); - snd_soc_component_read(component, AIU_I2S_SYNC, &val); + snd_soc_component_read(component, AIU_I2S_SYNC); switch (params_physical_width(params)) { case 16: /* Nothing to do */ diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c index 9a5271ce80fe..d91b0d874342 100644 --- a/sound/soc/meson/aiu-fifo-i2s.c +++ b/sound/soc/meson/aiu-fifo-i2s.c @@ -46,7 +46,6 @@ static int aiu_fifo_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - unsigned int val; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -54,7 +53,7 @@ static int aiu_fifo_i2s_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST); - snd_soc_component_read(component, AIU_I2S_SYNC, &val); + snd_soc_component_read(component, AIU_I2S_SYNC); break; } diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c index d9cede4c33ff..aa88aae8e517 100644 --- a/sound/soc/meson/aiu-fifo.c +++ b/sound/soc/meson/aiu-fifo.c @@ -37,8 +37,7 @@ snd_pcm_uframes_t aiu_fifo_pointer(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; unsigned int addr; - snd_soc_component_read(component, fifo->mem_offset + AIU_MEM_RD, - &addr); + addr = snd_soc_component_read(component, fifo->mem_offset + AIU_MEM_RD); return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr); } diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 89f7f64747cd..2b77010c2c5c 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -40,7 +40,7 @@ static const struct snd_soc_pcm_stream codec_params = { static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; @@ -116,7 +116,7 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, lb = &card->dai_link[*index + 1]; - lb->name = kasprintf(GFP_KERNEL, "%s-lb", pad->name); + lb->name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-lb", pad->name); if (!lb->name) return -ENOMEM; @@ -327,20 +327,22 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; if (axg_card_cpu_is_playback_fe(dai_link->cpus->of_node)) - ret = meson_card_set_fe_link(card, dai_link, np, true); + return meson_card_set_fe_link(card, dai_link, np, true); else if (axg_card_cpu_is_capture_fe(dai_link->cpus->of_node)) - ret = meson_card_set_fe_link(card, dai_link, np, false); - else - ret = meson_card_set_be_link(card, dai_link, np); + return meson_card_set_fe_link(card, dai_link, np, false); + + ret = meson_card_set_be_link(card, dai_link, np); if (ret) return ret; - if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node)) - ret = axg_card_parse_tdm(card, np, index); - else if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) { + if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) { dai_link->params = &codec_params; - dai_link->no_pcm = 0; /* link is not a DPCM BE */ + } else { + dai_link->no_pcm = 1; + snd_soc_dai_link_set_capabilities(dai_link); + if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node)) + ret = axg_card_parse_tdm(card, np, index); } return ret; diff --git a/sound/soc/meson/axg-spdifout.c b/sound/soc/meson/axg-spdifout.c index 7ce6aa97ddf7..e769a5ee6e27 100644 --- a/sound/soc/meson/axg-spdifout.c +++ b/sound/soc/meson/axg-spdifout.c @@ -108,7 +108,7 @@ static int axg_spdifout_trigger(struct snd_pcm_substream *substream, int cmd, } } -static int axg_spdifout_digital_mute(struct snd_soc_dai *dai, int mute) +static int axg_spdifout_mute(struct snd_soc_dai *dai, int mute, int direction) { struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); @@ -285,10 +285,11 @@ static void axg_spdifout_shutdown(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops axg_spdifout_ops = { .trigger = axg_spdifout_trigger, - .digital_mute = axg_spdifout_digital_mute, + .mute_stream = axg_spdifout_mute, .hw_params = axg_spdifout_hw_params, .startup = axg_spdifout_startup, .shutdown = axg_spdifout_shutdown, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver axg_spdifout_dai_drv[] = { diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index 358c8c0d861c..f7e8e9da68a0 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks); static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter) { struct axg_tdm_stream *ts = formatter->stream; - bool invert = formatter->drv->quirks->invert_sclk; + bool invert; int ret; /* Do nothing if the formatter is already enabled */ @@ -96,11 +96,12 @@ static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter) return ret; /* - * If sclk is inverted, invert it back and provide the inversion - * required by the formatter + * If sclk is inverted, it means the bit should latched on the + * rising edge which is what our HW expects. If not, we need to + * invert it before the formatter. */ - invert ^= axg_tdm_sclk_invert(ts->iface->fmt); - ret = clk_set_phase(formatter->sclk, invert ? 180 : 0); + invert = axg_tdm_sclk_invert(ts->iface->fmt); + ret = clk_set_phase(formatter->sclk, invert ? 0 : 180); if (ret) return ret; diff --git a/sound/soc/meson/axg-tdm-formatter.h b/sound/soc/meson/axg-tdm-formatter.h index 9ef98e955cb2..a1f0dcc0ff13 100644 --- a/sound/soc/meson/axg-tdm-formatter.h +++ b/sound/soc/meson/axg-tdm-formatter.h @@ -16,7 +16,6 @@ struct snd_kcontrol; struct axg_tdm_formatter_hw { unsigned int skew_offset; - bool invert_sclk; }; struct axg_tdm_formatter_ops { diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 6de27238e9df..36df30915378 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -119,18 +119,25 @@ static int axg_tdm_iface_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); - /* These modes are not supported */ - if (fmt & (SND_SOC_DAIFMT_CBS_CFM | SND_SOC_DAIFMT_CBM_CFS)) { + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + if (!iface->mclk) { + dev_err(dai->dev, "cpu clock master: mclk missing\n"); + return -ENODEV; + } + break; + + case SND_SOC_DAIFMT_CBM_CFM: + break; + + case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBM_CFS: dev_err(dai->dev, "only CBS_CFS and CBM_CFM are supported\n"); + /* Fall-through */ + default: return -EINVAL; } - /* If the TDM interface is the clock master, it requires mclk */ - if (!iface->mclk && (fmt & SND_SOC_DAIFMT_CBS_CFS)) { - dev_err(dai->dev, "cpu clock master: mclk missing\n"); - return -ENODEV; - } - iface->fmt = fmt; return 0; } @@ -319,7 +326,8 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - if (iface->fmt & SND_SOC_DAIFMT_CBS_CFS) { + if ((iface->fmt & SND_SOC_DAIFMT_MASTER_MASK) == + SND_SOC_DAIFMT_CBS_CFS) { ret = axg_tdm_iface_set_sclk(dai, params); if (ret) return ret; diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c index 973d4c02ef8d..88ed95ae886b 100644 --- a/sound/soc/meson/axg-tdmin.c +++ b/sound/soc/meson/axg-tdmin.c @@ -228,15 +228,29 @@ static const struct axg_tdm_formatter_driver axg_tdmin_drv = { .regmap_cfg = &axg_tdmin_regmap_cfg, .ops = &axg_tdmin_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = false, .skew_offset = 2, }, }; +static const struct axg_tdm_formatter_driver g12a_tdmin_drv = { + .component_drv = &axg_tdmin_component_drv, + .regmap_cfg = &axg_tdmin_regmap_cfg, + .ops = &axg_tdmin_ops, + .quirks = &(const struct axg_tdm_formatter_hw) { + .skew_offset = 3, + }, +}; + static const struct of_device_id axg_tdmin_of_match[] = { { .compatible = "amlogic,axg-tdmin", .data = &axg_tdmin_drv, + }, { + .compatible = "amlogic,g12a-tdmin", + .data = &g12a_tdmin_drv, + }, { + .compatible = "amlogic,sm1-tdmin", + .data = &g12a_tdmin_drv, }, {} }; MODULE_DEVICE_TABLE(of, axg_tdmin_of_match); diff --git a/sound/soc/meson/axg-tdmout.c b/sound/soc/meson/axg-tdmout.c index 418ec314b37d..3ceabddae629 100644 --- a/sound/soc/meson/axg-tdmout.c +++ b/sound/soc/meson/axg-tdmout.c @@ -238,7 +238,6 @@ static const struct axg_tdm_formatter_driver axg_tdmout_drv = { .regmap_cfg = &axg_tdmout_regmap_cfg, .ops = &axg_tdmout_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = true, .skew_offset = 1, }, }; @@ -248,7 +247,6 @@ static const struct axg_tdm_formatter_driver g12a_tdmout_drv = { .regmap_cfg = &axg_tdmout_regmap_cfg, .ops = &axg_tdmout_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = true, .skew_offset = 2, }, }; @@ -309,7 +307,6 @@ static const struct axg_tdm_formatter_driver sm1_tdmout_drv = { .regmap_cfg = &axg_tdmout_regmap_cfg, .ops = &axg_tdmout_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = true, .skew_offset = 2, }, }; diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c index 4abf7efb7eac..5119434a81c4 100644 --- a/sound/soc/meson/gx-card.c +++ b/sound/soc/meson/gx-card.c @@ -29,7 +29,7 @@ static const struct snd_soc_pcm_stream codec_params = { static int gx_card_i2s_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct gx_dai_link_i2s_data *be = (struct gx_dai_link_i2s_data *)priv->link_data[rtd->num]; @@ -96,21 +96,21 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; if (gx_card_cpu_identify(dai_link->cpus, "FIFO")) - ret = meson_card_set_fe_link(card, dai_link, np, true); - else - ret = meson_card_set_be_link(card, dai_link, np); + return meson_card_set_fe_link(card, dai_link, np, true); + ret = meson_card_set_be_link(card, dai_link, np); if (ret) return ret; - /* Check if the cpu is the i2s encoder and parse i2s data */ - if (gx_card_cpu_identify(dai_link->cpus, "I2S Encoder")) - ret = gx_card_parse_i2s(card, np, index); - /* Or apply codec to codec params if necessary */ - else if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) { + if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) { dai_link->params = &codec_params; - dai_link->no_pcm = 0; /* link is not a DPCM BE */ + } else { + dai_link->no_pcm = 1; + snd_soc_dai_link_set_capabilities(dai_link); + /* Check if the cpu is the i2s encoder and parse i2s data */ + if (gx_card_cpu_identify(dai_link->cpus, "I2S Encoder")) + ret = gx_card_parse_i2s(card, np, index); } return ret; diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c index 5a4a91c88734..6a64ac01b5ca 100644 --- a/sound/soc/meson/meson-card-utils.c +++ b/sound/soc/meson/meson-card-utils.c @@ -13,7 +13,7 @@ int meson_card_i2s_set_sysclk(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, unsigned int mclk_fs) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; unsigned int mclk; int ret, i; @@ -119,7 +119,7 @@ unsigned int meson_card_parse_daifmt(struct device_node *node, struct device_node *framemaster = NULL; unsigned int daifmt; - daifmt = snd_soc_of_parse_daifmt(node, DT_PREFIX, + daifmt = snd_soc_of_parse_daifmt(node, "", &bitclkmaster, &framemaster); daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; @@ -147,10 +147,6 @@ int meson_card_set_be_link(struct snd_soc_card *card, struct device_node *np; int ret, num_codecs; - link->no_pcm = 1; - link->dpcm_playback = 1; - link->dpcm_capture = 1; - num_codecs = of_get_child_count(node); if (!num_codecs) { dev_err(card->dev, "be link %s has no codec\n", diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c index 524a33472337..d07270d17cee 100644 --- a/sound/soc/meson/meson-codec-glue.c +++ b/sound/soc/meson/meson-codec-glue.c @@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(meson_codec_glue_input_set_fmt); int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_codec_glue_input *in_data = meson_codec_glue_output_get_input_data(dai->capture_widget); diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index f46d7aca8cf6..a6407f4388de 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -19,7 +19,7 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int rate = params_rate(params); diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c index 016a91199485..f310a8e91bbf 100644 --- a/sound/soc/pxa/brownstone.c +++ b/sound/soc/pxa/brownstone.c @@ -43,7 +43,7 @@ static const struct snd_soc_dapm_route brownstone_audio_map[] = { static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int freq_out, sspa_mclk, sysclk; diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 6fbef9a0afa7..8ee2dea25a8d 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -96,7 +96,7 @@ static void corgi_ext_control(struct snd_soc_dapm_context *dapm) static int corgi_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ corgi_ext_control(&rtd->card->dapm); @@ -115,7 +115,7 @@ static void corgi_shutdown(struct snd_pcm_substream *substream) static int corgi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index b4da9a9a6521..7334fac758de 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c @@ -53,7 +53,7 @@ static struct snd_soc_jack_gpio hs_jack_gpio = { static int hx4700_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c index 3014e8244ab4..a575676508b3 100644 --- a/sound/soc/pxa/imote2.c +++ b/sound/soc/pxa/imote2.c @@ -11,7 +11,7 @@ static int imote2_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index e4c818f4cd62..a5f326c97af2 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -68,7 +68,7 @@ static void magician_ext_control(struct snd_soc_dapm_context *dapm) static int magician_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ magician_ext_control(&rtd->card->dapm); @@ -82,7 +82,7 @@ static int magician_startup(struct snd_pcm_substream *substream) static int magician_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int width; @@ -120,7 +120,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream, static int magician_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index bf27b277c01f..763db7bbd9bb 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -51,14 +51,14 @@ static int rear_amp_power(struct snd_soc_component *component, int power) unsigned short reg; if (power) { - reg = snd_soc_component_read32(component, AC97_GPIO_CFG); + reg = snd_soc_component_read(component, AC97_GPIO_CFG); snd_soc_component_write(component, AC97_GPIO_CFG, reg | 0x0100); - reg = snd_soc_component_read32(component, AC97_GPIO_PULL); + reg = snd_soc_component_read(component, AC97_GPIO_PULL); snd_soc_component_write(component, AC97_GPIO_PULL, reg | (1<<15)); } else { - reg = snd_soc_component_read32(component, AC97_GPIO_CFG); + reg = snd_soc_component_read(component, AC97_GPIO_CFG); snd_soc_component_write(component, AC97_GPIO_CFG, reg & ~0x0100); - reg = snd_soc_component_read32(component, AC97_GPIO_PULL); + reg = snd_soc_component_read(component, AC97_GPIO_PULL); snd_soc_component_write(component, AC97_GPIO_PULL, reg & ~(1<<15)); } diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 3fe6c4c5a3ab..53fc49e32fbc 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c @@ -110,7 +110,7 @@ static bool filter(struct dma_chan *chan, void *param) static int mmp_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct platform_device *pdev = to_platform_device(component->dev); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct mmp_dma_data dma_data; diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 287984a564c8..323ba3e23039 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -68,7 +68,7 @@ static void poodle_ext_control(struct snd_soc_dapm_context *dapm) static int poodle_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ poodle_ext_control(&rtd->card->dapm); @@ -89,7 +89,7 @@ static void poodle_shutdown(struct snd_pcm_substream *substream) static int poodle_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 6a72cc1665b7..d1e09ade0190 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -178,7 +178,7 @@ static int pxa_ssp_resume(struct snd_soc_component *component) #define pxa_ssp_resume NULL #endif -/** +/* * ssp_set_clkdiv - set SSP clock divider * @div: serial clock rate divider */ diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 03102e938ba1..5301859a8453 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -95,7 +95,7 @@ static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_in = { static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); if (IS_ERR(clk_i2s)) diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 6d8174f62935..7c1384a869ca 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -105,7 +105,7 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) static int spitz_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ spitz_ext_control(&rtd->card->dapm); @@ -116,7 +116,7 @@ static int spitz_startup(struct snd_pcm_substream *substream) static int spitz_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index b429db25f884..3b40b5fa5de7 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -72,7 +72,7 @@ static void tosa_ext_control(struct snd_soc_dapm_context *dapm) static int tosa_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ tosa_ext_control(&rtd->card->dapm); diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 6eee1aefc89a..edf2b9eec5b8 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -33,7 +33,7 @@ static struct snd_soc_card snd_soc_z2; static int z2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 447b59b8bd33..bb89a53f4ab1 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -75,7 +75,7 @@ static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int wm9713_div = 0; diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 92f51d0e9fe2..5d6b2466a2f2 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -37,6 +37,7 @@ config SND_SOC_APQ8016_SBC tristate "SoC Audio support for APQ8016 SBC platforms" depends on SND_SOC_QCOM select SND_SOC_LPASS_APQ8016 + select SND_SOC_QCOM_COMMON help Support for Qualcomm Technologies LPASS audio block in APQ8016 SOC-based systems. @@ -99,12 +100,12 @@ config SND_SOC_MSM8996 config SND_SOC_SDM845 tristate "SoC Machine driver for SDM845 boards" - depends on QCOM_APR && CROS_EC && I2C && SOUNDWIRE + depends on QCOM_APR && I2C && SOUNDWIRE select SND_SOC_QDSP6 select SND_SOC_QCOM_COMMON select SND_SOC_RT5663 select SND_SOC_MAX98927 - select SND_SOC_CROS_EC_CODEC + imply SND_SOC_CROS_EC_CODEC help To add support for audio on Qualcomm Technologies Inc. SDM845 SoC-based systems. diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 2ef090f4af9e..083413abc2f6 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -16,13 +16,14 @@ #include <sound/soc.h> #include <uapi/linux/input-event-codes.h> #include <dt-bindings/sound/apq8016-lpass.h> +#include "common.h" struct apq8016_sbc_data { + struct snd_soc_card card; void __iomem *mic_iomux; void __iomem *spkr_iomux; struct snd_soc_jack jack; bool jack_setup; - struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ }; #define MIC_CTRL_TER_WS_SLAVE_SEL BIT(21) @@ -110,107 +111,13 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) +static void apq8016_sbc_add_ops(struct snd_soc_card *card) { - struct device *dev = card->dev; struct snd_soc_dai_link *link; - struct device_node *np, *codec, *cpu, *node = dev->of_node; - struct apq8016_sbc_data *data; - struct snd_soc_dai_link_component *dlc; - int ret, num_links; - - ret = snd_soc_of_parse_card_name(card, "qcom,model"); - if (ret) { - dev_err(dev, "Error parsing card name: %d\n", ret); - return ERR_PTR(ret); - } - - /* DAPM routes */ - if (of_property_read_bool(node, "qcom,audio-routing")) { - ret = snd_soc_of_parse_audio_routing(card, - "qcom,audio-routing"); - if (ret) - return ERR_PTR(ret); - } - - - /* Populate links */ - num_links = of_get_child_count(node); - - /* Allocate the private data and the DAI link array */ - data = devm_kzalloc(dev, - struct_size(data, dai_link, num_links), - GFP_KERNEL); - if (!data) - return ERR_PTR(-ENOMEM); - - card->dai_link = &data->dai_link[0]; - card->num_links = num_links; - - link = data->dai_link; - - for_each_child_of_node(node, np) { - dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); - if (!dlc) - return ERR_PTR(-ENOMEM); - - link->cpus = &dlc[0]; - link->platforms = &dlc[1]; - - link->num_cpus = 1; - link->num_platforms = 1; - - cpu = of_get_child_by_name(np, "cpu"); - codec = of_get_child_by_name(np, "codec"); - - if (!cpu || !codec) { - dev_err(dev, "Can't find cpu/codec DT node\n"); - ret = -EINVAL; - goto error; - } + int i; - link->cpus->of_node = of_parse_phandle(cpu, "sound-dai", 0); - if (!link->cpus->of_node) { - dev_err(card->dev, "error getting cpu phandle\n"); - ret = -EINVAL; - goto error; - } - - ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); - if (ret) { - dev_err(card->dev, "error getting cpu dai name\n"); - goto error; - } - - ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); - - if (ret < 0) { - dev_err(card->dev, "error getting codec dai name\n"); - goto error; - } - - link->platforms->of_node = link->cpus->of_node; - ret = of_property_read_string(np, "link-name", &link->name); - if (ret) { - dev_err(card->dev, "error getting codec dai_link name\n"); - goto error; - } - - link->stream_name = link->name; + for_each_card_prelinks(card, i, link) link->init = apq8016_sbc_dai_init; - link++; - - of_node_put(cpu); - of_node_put(codec); - } - - return data; - - error: - of_node_put(np); - of_node_put(cpu); - of_node_put(codec); - return ERR_PTR(ret); } static const struct snd_soc_dapm_widget apq8016_sbc_dapm_widgets[] = { @@ -228,20 +135,20 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) struct snd_soc_card *card; struct apq8016_sbc_data *data; struct resource *res; + int ret; - card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); - if (!card) + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) return -ENOMEM; + card = &data->card; card->dev = dev; card->dapm_widgets = apq8016_sbc_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets); - data = apq8016_sbc_parse_of(card); - if (IS_ERR(data)) { - dev_err(&pdev->dev, "Error resolving dai links: %ld\n", - PTR_ERR(data)); - return PTR_ERR(data); - } + + ret = qcom_snd_parse_of(card); + if (ret) + return ret; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mic-iomux"); data->mic_iomux = devm_ioremap_resource(dev, res); @@ -255,6 +162,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, data); + apq8016_sbc_add_ops(card); return devm_snd_soc_register_card(&pdev->dev, card); } diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c index 287ad2aa27f3..253549600c5a 100644 --- a/sound/soc/qcom/apq8096.c +++ b/sound/soc/qcom/apq8096.c @@ -30,7 +30,7 @@ static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int msm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; @@ -109,7 +109,7 @@ static int apq8096_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - card = kzalloc(sizeof(*card), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; @@ -117,31 +117,10 @@ static int apq8096_platform_probe(struct platform_device *pdev) dev_set_drvdata(dev, card); ret = qcom_snd_parse_of(card); if (ret) - goto err; + return ret; apq8096_add_be_ops(card); - ret = snd_soc_register_card(card); - if (ret) - goto err_card_register; - - return 0; - -err_card_register: - kfree(card->dai_link); -err: - kfree(card); - return ret; -} - -static int apq8096_platform_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_card(card); - kfree(card->dai_link); - kfree(card); - - return 0; + return devm_snd_soc_register_card(dev, card); } static const struct of_device_id msm_snd_apq8096_dt_match[] = { @@ -153,7 +132,6 @@ MODULE_DEVICE_TABLE(of, msm_snd_apq8096_dt_match); static struct platform_driver msm_snd_apq8096_driver = { .probe = apq8096_platform_probe, - .remove = apq8096_platform_remove, .driver = { .name = "msm-snd-apq8096", .of_match_table = msm_snd_apq8096_dt_match, diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 8ada4ecba847..5194d90ddb96 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -4,7 +4,6 @@ #include <linux/module.h> #include "common.h" -#include "qdsp6/q6afe.h" int qcom_snd_parse_of(struct snd_soc_card *card) { @@ -19,6 +18,9 @@ int qcom_snd_parse_of(struct snd_soc_card *card) int ret, num_links; ret = snd_soc_of_parse_card_name(card, "model"); + if (ret == 0 && !card->name) + /* Deprecated, only for compatibility with old device trees */ + ret = snd_soc_of_parse_card_name(card, "qcom,model"); if (ret) { dev_err(dev, "Error parsing card name: %d\n", ret); return ret; @@ -26,8 +28,13 @@ int qcom_snd_parse_of(struct snd_soc_card *card) /* DAPM routes */ if (of_property_read_bool(dev->of_node, "audio-routing")) { - ret = snd_soc_of_parse_audio_routing(card, - "audio-routing"); + ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); + if (ret) + return ret; + } + /* Deprecated, only for compatibility with old device trees */ + if (of_property_read_bool(dev->of_node, "qcom,audio-routing")) { + ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing"); if (ret) return ret; } @@ -36,7 +43,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) num_links = of_get_child_count(dev->of_node); /* Allocate the DAI link array */ - card->dai_link = kcalloc(num_links, sizeof(*link), GFP_KERNEL); + card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL); if (!card->dai_link) return -ENOMEM; @@ -81,11 +88,13 @@ int qcom_snd_parse_of(struct snd_soc_card *card) ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); if (ret) { - dev_err(card->dev, "%s: error getting cpu dai name\n", link->name); + if (ret != -EPROBE_DEFER) + dev_err(card->dev, "%s: error getting cpu dai name: %d\n", + link->name, ret); goto err; } - if (codec && platform) { + if (platform) { link->platforms->of_node = of_parse_phandle(platform, "sound-dai", 0); @@ -94,24 +103,26 @@ int qcom_snd_parse_of(struct snd_soc_card *card) ret = -EINVAL; goto err; } + } else { + link->platforms->of_node = link->cpus->of_node; + } + if (codec) { ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); if (ret < 0) { - dev_err(card->dev, "%s: codec dai not found\n", link->name); + if (ret != -EPROBE_DEFER) + dev_err(card->dev, "%s: codec dai not found: %d\n", + link->name, ret); goto err; } - link->no_pcm = 1; - link->ignore_pmdown_time = 1; - - if (q6afe_is_rx_port(link->id)) { - link->dpcm_playback = 1; - link->dpcm_capture = 0; - } else { - link->dpcm_playback = 0; - link->dpcm_capture = 1; - } + if (platform) { + /* DPCM backend */ + link->no_pcm = 1; + link->ignore_pmdown_time = 1; + } } else { + /* DPCM frontend */ dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -119,16 +130,18 @@ int qcom_snd_parse_of(struct snd_soc_card *card) link->codecs = dlc; link->num_codecs = 1; - link->platforms->of_node = link->cpus->of_node; link->codecs->dai_name = "snd-soc-dummy-dai"; link->codecs->name = "snd-soc-dummy"; link->dynamic = 1; - link->dpcm_playback = 1; - link->dpcm_capture = 1; } - link->ignore_suspend = 1; - link->nonatomic = 1; + if (platform || !codec) { + /* DPCM */ + snd_soc_dai_link_set_capabilities(link); + link->ignore_suspend = 1; + link->nonatomic = 1; + } + link->stream_name = link->name; link++; @@ -143,7 +156,6 @@ err: of_node_put(cpu); of_node_put(codec); of_node_put(platform); - kfree(card->dai_link); return ret; } EXPORT_SYMBOL(qcom_snd_parse_of); diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 34f7fd1bab1c..01179bc0e5e5 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -54,7 +54,7 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct lpass_variant *v = drvdata->variant; @@ -125,7 +125,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -218,7 +218,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, static int lpass_platform_pcmops_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -239,7 +239,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -291,7 +291,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -365,7 +365,7 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -410,7 +410,7 @@ static irqreturn_t lpass_dma_interrupt_handler( struct lpass_data *drvdata, int chan, u32 interrupts) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_variant *v = drvdata->variant; irqreturn_t ret = IRQ_NONE; int rv; diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c index da242515e146..2f3ea6beb066 100644 --- a/sound/soc/qcom/qdsp6/q6adm.c +++ b/sound/soc/qcom/qdsp6/q6adm.c @@ -403,7 +403,7 @@ struct q6copp *q6adm_open(struct device *dev, int port_id, int path, int rate, spin_lock_irqsave(&adm->copps_list_lock, flags); copp = q6adm_alloc_copp(adm, port_id); - if (IS_ERR_OR_NULL(copp)) { + if (IS_ERR(copp)) { spin_unlock_irqrestore(&adm->copps_list_lock, flags); return ERR_CAST(copp); } @@ -419,7 +419,6 @@ struct q6copp *q6adm_open(struct device *dev, int port_id, int path, int rate, copp->bit_width = bit_width; copp->app_type = app_type; - ret = q6adm_device_open(adm, copp, port_id, path, topology, channel_mode, bit_width, rate); if (ret < 0) { @@ -588,12 +587,12 @@ static int q6adm_probe(struct apr_device *adev) struct device *dev = &adev->dev; struct q6adm *adm; - adm = devm_kzalloc(&adev->dev, sizeof(*adm), GFP_KERNEL); + adm = devm_kzalloc(dev, sizeof(*adm), GFP_KERNEL); if (!adm) return -ENOMEM; adm->apr = adev; - dev_set_drvdata(&adev->dev, adm); + dev_set_drvdata(dev, adm); adm->dev = dev; q6core_get_svc_api_info(adev->svc_id, &adm->ainfo); mutex_init(&adm->lock); diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 0ce4eb60f984..e0945f7a58c8 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -800,14 +800,6 @@ int q6afe_get_port_id(int index) } EXPORT_SYMBOL_GPL(q6afe_get_port_id); -int q6afe_is_rx_port(int index) -{ - if (index < 0 || index >= AFE_PORT_MAX) - return -EINVAL; - - return port_maps[index].is_rx; -} -EXPORT_SYMBOL_GPL(q6afe_is_rx_port); static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt, struct q6afe_port *port) { diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 1a0f80a14afe..c7ed5422baff 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -198,7 +198,6 @@ int q6afe_port_start(struct q6afe_port *port); int q6afe_port_stop(struct q6afe_port *port); void q6afe_port_put(struct q6afe_port *port); int q6afe_get_port_id(int index); -int q6afe_is_rx_port(int index); void q6afe_hdmi_port_prepare(struct q6afe_port *port, struct q6afe_hdmi_cfg *cfg); void q6afe_slim_port_prepare(struct q6afe_port *port, diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index aff57052a735..9b7b218f2a20 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -37,9 +37,6 @@ #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) -#define Q6ASM_DAI_TX_RX 0 -#define Q6ASM_DAI_TX 1 -#define Q6ASM_DAI_RX 2 #define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1) #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2) @@ -215,9 +212,10 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream); struct q6asm_dai_rtd *prtd = runtime->private_data; struct q6asm_dai_data *pdata; + struct device *dev = component->dev; int ret, i; pdata = snd_soc_component_get_drvdata(component); @@ -225,7 +223,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, return -EINVAL; if (!prtd || !prtd->audio_client) { - pr_err("%s: private data null or audio client freed\n", + dev_err(dev, "%s: private data null or audio client freed\n", __func__); return -EINVAL; } @@ -248,7 +246,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, prtd->periods); if (ret < 0) { - pr_err("Audio Start: Buffer Allocation failed rc = %d\n", + dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); return -ENOMEM; } @@ -262,7 +260,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, } if (ret < 0) { - pr_err("%s: q6asm_open_write failed\n", __func__); + dev_err(dev, "%s: q6asm_open_write failed\n", __func__); q6asm_audio_client_free(prtd->audio_client); prtd->audio_client = NULL; return -ENOMEM; @@ -272,7 +270,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE, prtd->session_id, substream->stream); if (ret) { - pr_err("%s: stream reg failed ret:%d\n", __func__, ret); + dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret); return ret; } @@ -292,7 +290,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, } if (ret < 0) - pr_info("%s: CMD Format block failed\n", __func__); + dev_info(dev, "%s: CMD Format block failed\n", __func__); prtd->state = Q6ASM_STREAM_RUNNING; @@ -332,7 +330,7 @@ static int q6asm_dai_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_prtd, 0); struct q6asm_dai_rtd *prtd; struct q6asm_dai_data *pdata; @@ -344,7 +342,7 @@ static int q6asm_dai_open(struct snd_soc_component *component, pdata = snd_soc_component_get_drvdata(component); if (!pdata) { - pr_err("Drv data not found ..\n"); + dev_err(dev, "Drv data not found ..\n"); return -EINVAL; } @@ -357,7 +355,7 @@ static int q6asm_dai_open(struct snd_soc_component *component, (q6asm_cb)event_handler, prtd, stream_id, LEGACY_PCM_MODE); if (IS_ERR(prtd->audio_client)) { - pr_info("%s: Could not allocate memory\n", __func__); + dev_info(dev, "%s: Could not allocate memory\n", __func__); ret = PTR_ERR(prtd->audio_client); kfree(prtd); return ret; @@ -372,12 +370,12 @@ static int q6asm_dai_open(struct snd_soc_component *component, SNDRV_PCM_HW_PARAM_RATE, &constraints_sample_rates); if (ret < 0) - pr_info("snd_pcm_hw_constraint_list failed\n"); + dev_info(dev, "snd_pcm_hw_constraint_list failed\n"); /* Ensure that buffer size is a multiple of period size */ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) - pr_info("snd_pcm_hw_constraint_integer failed\n"); + dev_info(dev, "snd_pcm_hw_constraint_integer failed\n"); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = snd_pcm_hw_constraint_minmax(runtime, @@ -385,21 +383,21 @@ static int q6asm_dai_open(struct snd_soc_component *component, PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE, PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE); if (ret < 0) { - pr_err("constraint for buffer bytes min max ret = %d\n", - ret); + dev_err(dev, "constraint for buffer bytes min max ret = %d\n", + ret); } } ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); if (ret < 0) { - pr_err("constraint for period bytes step ret = %d\n", + dev_err(dev, "constraint for period bytes step ret = %d\n", ret); } ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); if (ret < 0) { - pr_err("constraint for buffer bytes step ret = %d\n", + dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); } @@ -424,7 +422,7 @@ static int q6asm_dai_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream); struct q6asm_dai_rtd *prtd = runtime->private_data; if (prtd->audio_client) { diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index ae4b2cabdf2d..755062eadcc8 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -311,7 +311,7 @@ static int q6asm_apr_send_session_pkt(struct q6asm *a, struct audio_client *ac, 5 * HZ); if (!rc) { - dev_err(a->dev, "CMD timeout\n"); + dev_err(a->dev, "CMD %x timeout\n", hdr->opcode); rc = -ETIMEDOUT; } else if (ac->result.status > 0) { dev_err(a->dev, "DSP returned error[%x]\n", @@ -891,7 +891,7 @@ static int q6asm_ac_send_cmd_sync(struct audio_client *ac, struct apr_pkt *pkt) rc = wait_event_timeout(ac->cmd_wait, (ac->result.opcode == hdr->opcode), 5 * HZ); if (!rc) { - dev_err(ac->dev, "CMD timeout\n"); + dev_err(ac->dev, "CMD %x timeout\n", hdr->opcode); rc = -ETIMEDOUT; goto err; } @@ -912,9 +912,9 @@ err: /** * q6asm_open_write() - Open audio client for writing - * * @ac: audio client pointer * @format: audio sample format + * @codec_profile: compressed format profile * @bits_per_sample: bits per sample * * Return: Will be an negative value on error or zero on success diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 46e50612b92c..eaa95b5a7b66 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -924,7 +924,7 @@ static int routing_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct msm_routing_data *data = dev_get_drvdata(component->dev); unsigned int be_id = asoc_rtd_to_cpu(rtd, 0)->id; struct session_data *session; diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 68e9388ff46f..0d10fba53945 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -45,7 +45,7 @@ static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28}; static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai; struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -85,7 +85,7 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai; int ret = 0, j; @@ -170,7 +170,7 @@ end: static int sdm845_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret = 0; @@ -301,7 +301,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream) { unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); @@ -391,7 +391,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream) static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); @@ -437,7 +437,7 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) static int sdm845_snd_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -476,7 +476,7 @@ static int sdm845_snd_prepare(struct snd_pcm_substream *substream) static int sdm845_snd_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -543,16 +543,14 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - card = kzalloc(sizeof(*card), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; /* Allocate the private data */ - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto data_alloc_fail; - } + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; card->dapm_widgets = sdm845_snd_widgets; card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets); @@ -560,38 +558,13 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev) dev_set_drvdata(dev, card); ret = qcom_snd_parse_of(card); if (ret) - goto parse_dt_fail; + return ret; data->card = card; snd_soc_card_set_drvdata(card, data); sdm845_add_ops(card); - ret = snd_soc_register_card(card); - if (ret) { - dev_err(dev, "Sound card registration failed\n"); - goto register_card_fail; - } - return ret; - -register_card_fail: - kfree(card->dai_link); -parse_dt_fail: - kfree(data); -data_alloc_fail: - kfree(card); - return ret; -} - -static int sdm845_snd_platform_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = dev_get_drvdata(&pdev->dev); - struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); - - snd_soc_unregister_card(card); - kfree(card->dai_link); - kfree(data); - kfree(card); - return 0; + return devm_snd_soc_register_card(dev, card); } static const struct of_device_id sdm845_snd_device_id[] = { @@ -604,7 +577,6 @@ MODULE_DEVICE_TABLE(of, sdm845_snd_device_id); static struct platform_driver sdm845_snd_driver = { .probe = sdm845_snd_platform_probe, - .remove = sdm845_snd_platform_remove, .driver = { .name = "msm-snd-sdm845", .of_match_table = sdm845_snd_device_id, diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index 3a6e18709b9e..c0c388d4db82 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c @@ -19,7 +19,7 @@ static int storm_ops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct snd_soc_card *card = soc_runtime->card; snd_pcm_format_t format = params_format(params); unsigned int rate = params_rate(params); diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index 01078155a914..33a00774746d 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -66,7 +66,7 @@ static int rk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk; diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 9539b0d024fe..e2d52d8d0ff9 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -32,6 +32,19 @@ static unsigned int dmic_wakeup_delay; static struct snd_soc_jack rockchip_sound_jack; +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = { + { + .pin = "Headphones", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + +}; + static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphones", NULL), SND_SOC_DAPM_SPK("Speakers", NULL), @@ -51,7 +64,7 @@ static const struct snd_kcontrol_new rockchip_controls[] = { static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int mclk; int ret; @@ -70,7 +83,7 @@ static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substrea static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int mclk; @@ -102,7 +115,7 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk, ret; @@ -176,7 +189,9 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, - &rockchip_sound_jack, NULL, 0); + &rockchip_sound_jack, + rockchip_sound_jack_pins, + ARRAY_SIZE(rockchip_sound_jack_pins)); if (ret) { dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret); @@ -200,7 +215,7 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int mclk; int ret; diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 61c984f10d8e..d1438753edb4 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -272,7 +272,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct rk_i2s_dev *i2s = to_info(dai); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int val = 0; unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck; diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 1f527d3763ce..9acfd024aa5d 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -145,7 +145,7 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk; diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index 0617ccf4e42c..16ca2ad92426 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -55,7 +55,7 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk; diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index 6635145a26c4..674810851fbc 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -306,44 +306,22 @@ static int rk_spdif_probe(struct platform_device *pdev) return -ENOMEM; spdif->hclk = devm_clk_get(&pdev->dev, "hclk"); - if (IS_ERR(spdif->hclk)) { - dev_err(&pdev->dev, "Can't retrieve rk_spdif bus clock\n"); + if (IS_ERR(spdif->hclk)) return PTR_ERR(spdif->hclk); - } - ret = clk_prepare_enable(spdif->hclk); - if (ret) { - dev_err(spdif->dev, "hclock enable failed %d\n", ret); - return ret; - } spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); - if (IS_ERR(spdif->mclk)) { - dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); - ret = PTR_ERR(spdif->mclk); - goto err_disable_hclk; - } - - ret = clk_prepare_enable(spdif->mclk); - if (ret) { - dev_err(spdif->dev, "clock enable failed %d\n", ret); - goto err_disable_clocks; - } + if (IS_ERR(spdif->mclk)) + return PTR_ERR(spdif->mclk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) { - ret = PTR_ERR(regs); - goto err_disable_clocks; - } + if (IS_ERR(regs)) + return PTR_ERR(regs); spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, &rk_spdif_regmap_config); - if (IS_ERR(spdif->regmap)) { - dev_err(&pdev->dev, - "Failed to initialise managed register map\n"); - ret = PTR_ERR(spdif->regmap); - goto err_disable_clocks; - } + if (IS_ERR(spdif->regmap)) + return PTR_ERR(spdif->regmap); spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -352,47 +330,44 @@ static int rk_spdif_probe(struct platform_device *pdev) spdif->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, spdif); - pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - pm_request_idle(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + ret = rk_spdif_runtime_resume(&pdev->dev); + if (ret) + goto err_pm_runtime; + } ret = devm_snd_soc_register_component(&pdev->dev, &rk_spdif_component, &rk_spdif_dai, 1); if (ret) { dev_err(&pdev->dev, "Could not register DAI\n"); - goto err_pm_runtime; + goto err_pm_suspend; } ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); if (ret) { dev_err(&pdev->dev, "Could not register PCM\n"); - goto err_pm_runtime; + goto err_pm_suspend; } return 0; +err_pm_suspend: + if (!pm_runtime_status_suspended(&pdev->dev)) + rk_spdif_runtime_suspend(&pdev->dev); err_pm_runtime: pm_runtime_disable(&pdev->dev); -err_disable_clocks: - clk_disable_unprepare(spdif->mclk); -err_disable_hclk: - clk_disable_unprepare(spdif->hclk); return ret; } static int rk_spdif_remove(struct platform_device *pdev) { - struct rk_spdif_dev *spdif = dev_get_drvdata(&pdev->dev); - pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) rk_spdif_runtime_suspend(&pdev->dev); - clk_disable_unprepare(spdif->mclk); - clk_disable_unprepare(spdif->hclk); - return 0; } diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 99a49248e966..1431be4ed054 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -77,7 +77,7 @@ config SND_SOC_SAMSUNG_S3C24XX_UDA134X config SND_SOC_SAMSUNG_SIMTEC tristate help - Internal node for common S3C24XX/Simtec suppor + Internal node for common S3C24XX/Simtec support. config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" @@ -212,4 +212,25 @@ config SND_SOC_SAMSUNG_TM2_WM5110 help Say Y if you want to add support for SoC audio on the TM2 board. +config SND_SOC_SAMSUNG_ARIES_WM8994 + tristate "SoC I2S Audio support for WM8994 on Aries" + depends on SND_SOC_SAMSUNG && MFD_WM8994 && IIO && EXTCON + select SND_SOC_BT_SCO + select SND_SOC_WM8994 + select SND_SAMSUNG_I2S + help + Say Y if you want to add support for SoC audio on Aries boards, + which has a WM8994 codec connected to a BT codec, a cellular + modem, and the Samsung I2S controller. Jack detection is done + via ADC, GPIOs, and an extcon device. Switching between the Mic + and TV-Out path is also handled. + +config SND_SOC_SAMSUNG_MIDAS_WM1811 + tristate "SoC I2S Audio support for Midas boards" + depends on SND_SOC_SAMSUNG + select SND_SAMSUNG_I2S + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on the Midas boards. + endif #SND_SOC_SAMSUNG diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 8f5dfe20b9f1..398e843f388c 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -41,6 +41,8 @@ snd-soc-bells-objs := bells.o snd-soc-odroid-objs := odroid.o snd-soc-arndale-objs := arndale.o snd-soc-tm2-wm5110-objs := tm2_wm5110.o +snd-soc-aries-wm8994-objs := aries_wm8994.o +snd-soc-midas-wm1811-objs := midas_wm1811.o obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -64,3 +66,5 @@ obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o obj-$(CONFIG_SND_SOC_ODROID) += snd-soc-odroid.o obj-$(CONFIG_SND_SOC_ARNDALE) += snd-soc-arndale.o obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o +obj-$(CONFIG_SND_SOC_SAMSUNG_ARIES_WM8994) += snd-soc-aries-wm8994.o +obj-$(CONFIG_SND_SOC_SAMSUNG_MIDAS_WM1811) += snd-soc-midas-wm1811.o diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c new file mode 100644 index 000000000000..0ac5956ba270 --- /dev/null +++ b/sound/soc/samsung/aries_wm8994.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include <linux/extcon.h> +#include <linux/iio/consumer.h> +#include <linux/iio/iio.h> +#include <linux/input-event-codes.h> +#include <linux/mfd/wm8994/registers.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_gpio.h> +#include <linux/regulator/consumer.h> +#include <sound/jack.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include "i2s.h" +#include "../codecs/wm8994.h" + +#define ARIES_MCLK1_FREQ 24000000 + +struct aries_wm8994_variant { + unsigned int modem_dai_fmt; + bool has_fm_radio; +}; + +struct aries_wm8994_data { + struct extcon_dev *usb_extcon; + struct regulator *reg_main_micbias; + struct regulator *reg_headset_micbias; + struct gpio_desc *gpio_headset_detect; + struct gpio_desc *gpio_headset_key; + struct gpio_desc *gpio_earpath_sel; + struct iio_channel *adc; + const struct aries_wm8994_variant *variant; +}; + +/* USB dock */ +static struct snd_soc_jack aries_dock; + +static struct snd_soc_jack_pin dock_pins[] = { + { + .pin = "LINE", + .mask = SND_JACK_LINEOUT, + }, +}; + +static int aries_extcon_notifier(struct notifier_block *this, + unsigned long connected, void *_cmd) +{ + if (connected) + snd_soc_jack_report(&aries_dock, SND_JACK_LINEOUT, + SND_JACK_LINEOUT); + else + snd_soc_jack_report(&aries_dock, 0, SND_JACK_LINEOUT); + + return NOTIFY_DONE; +} + +static struct notifier_block aries_extcon_notifier_block = { + .notifier_call = aries_extcon_notifier, +}; + +/* Headset jack */ +static struct snd_soc_jack aries_headset; + +static struct snd_soc_jack_pin jack_pins[] = { + { + .pin = "HP", + .mask = SND_JACK_HEADPHONE, + }, { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static struct snd_soc_jack_zone headset_zones[] = { + { + .min_mv = 0, + .max_mv = 241, + .jack_type = SND_JACK_HEADPHONE, + }, { + .min_mv = 242, + .max_mv = 2980, + .jack_type = SND_JACK_HEADSET, + }, { + .min_mv = 2981, + .max_mv = UINT_MAX, + .jack_type = SND_JACK_HEADPHONE, + }, +}; + +static irqreturn_t headset_det_irq_thread(int irq, void *data) +{ + struct aries_wm8994_data *priv = (struct aries_wm8994_data *) data; + int ret = 0; + int time_left_ms = 300; + int adc; + + while (time_left_ms > 0) { + if (!gpiod_get_value(priv->gpio_headset_detect)) { + snd_soc_jack_report(&aries_headset, 0, + SND_JACK_HEADSET); + gpiod_set_value(priv->gpio_earpath_sel, 0); + return IRQ_HANDLED; + } + msleep(20); + time_left_ms -= 20; + } + + /* Temporarily enable micbias and earpath selector */ + ret = regulator_enable(priv->reg_headset_micbias); + if (ret) + pr_err("%s failed to enable micbias: %d", __func__, ret); + + gpiod_set_value(priv->gpio_earpath_sel, 1); + + ret = iio_read_channel_processed(priv->adc, &adc); + if (ret < 0) { + /* failed to read ADC, so assume headphone */ + pr_err("%s failed to read ADC, assuming headphones", __func__); + snd_soc_jack_report(&aries_headset, SND_JACK_HEADPHONE, + SND_JACK_HEADSET); + } else { + snd_soc_jack_report(&aries_headset, + snd_soc_jack_get_type(&aries_headset, adc), + SND_JACK_HEADSET); + } + + ret = regulator_disable(priv->reg_headset_micbias); + if (ret) + pr_err("%s failed disable micbias: %d", __func__, ret); + + /* Disable earpath selector when no mic connected */ + if (!(aries_headset.status & SND_JACK_MICROPHONE)) + gpiod_set_value(priv->gpio_earpath_sel, 0); + + return IRQ_HANDLED; +} + +static int headset_button_check(void *data) +{ + struct aries_wm8994_data *priv = (struct aries_wm8994_data *) data; + + /* Filter out keypresses when 4 pole jack not detected */ + if (gpiod_get_value_cansleep(priv->gpio_headset_key) && + aries_headset.status & SND_JACK_MICROPHONE) + return SND_JACK_BTN_0; + + return 0; +} + +static struct snd_soc_jack_gpio headset_button_gpio[] = { + { + .name = "Media Button", + .report = SND_JACK_BTN_0, + .debounce_time = 30, + .jack_status_check = headset_button_check, + }, +}; + +static int aries_spk_cfg(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_component *component; + int ret = 0; + + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]); + component = asoc_rtd_to_codec(rtd, 0)->component; + + /** + * We have an odd setup - the SPKMODE pin is pulled up so + * we only have access to the left side SPK configs, + * but SPKOUTR isn't bridged so when playing back in + * stereo, we only get the left hand channel. The only + * option we're left with is to force the AIF into mono + * mode. + */ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + ret = snd_soc_component_update_bits(component, + WM8994_AIF1_DAC1_FILTERS_1, + WM8994_AIF1DAC1_MONO, WM8994_AIF1DAC1_MONO); + break; + case SND_SOC_DAPM_PRE_PMD: + ret = snd_soc_component_update_bits(component, + WM8994_AIF1_DAC1_FILTERS_1, + WM8994_AIF1DAC1_MONO, 0); + break; + } + + return ret; +} + +static int aries_main_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(priv->reg_main_micbias); + break; + case SND_SOC_DAPM_POST_PMD: + ret = regulator_disable(priv->reg_main_micbias); + break; + } + + return ret; +} + +static int aries_headset_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(priv->reg_headset_micbias); + break; + case SND_SOC_DAPM_POST_PMD: + ret = regulator_disable(priv->reg_headset_micbias); + break; + } + + return ret; +} + +static const struct snd_kcontrol_new aries_controls[] = { + SOC_DAPM_PIN_SWITCH("Modem In"), + SOC_DAPM_PIN_SWITCH("Modem Out"), +}; + +static const struct snd_soc_dapm_widget aries_dapm_widgets[] = { + SND_SOC_DAPM_HP("HP", NULL), + + SND_SOC_DAPM_SPK("SPK", aries_spk_cfg), + SND_SOC_DAPM_SPK("RCV", NULL), + + SND_SOC_DAPM_LINE("LINE", NULL), + + SND_SOC_DAPM_MIC("Main Mic", aries_main_bias), + SND_SOC_DAPM_MIC("Headset Mic", aries_headset_bias), + + SND_SOC_DAPM_MIC("Bluetooth Mic", NULL), + SND_SOC_DAPM_SPK("Bluetooth SPK", NULL), + + SND_SOC_DAPM_LINE("Modem In", NULL), + SND_SOC_DAPM_LINE("Modem Out", NULL), + + /* This must be last as it is conditionally not used */ + SND_SOC_DAPM_LINE("FM In", NULL), +}; + +static int aries_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int pll_out; + int ret; + + /* AIF1CLK should be >=3MHz for optimal performance */ + if (params_width(params) == 24) + pll_out = params_rate(params) * 384; + else if (params_rate(params) == 8000 || params_rate(params) == 11025) + pll_out = params_rate(params) * 512; + else + pll_out = params_rate(params) * 256; + + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, + ARIES_MCLK1_FREQ, pll_out); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, + pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static int aries_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int ret; + + /* Switch sysclk to MCLK1 */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, + ARIES_MCLK1_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* Stop PLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, + ARIES_MCLK1_FREQ, 0); + if (ret < 0) + return ret; + + return 0; +} + +/* + * Main DAI operations + */ +static struct snd_soc_ops aries_ops = { + .hw_params = aries_hw_params, + .hw_free = aries_hw_free, +}; + +static int aries_baseband_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int pll_out; + int ret; + + pll_out = 8000 * 512; + + /* Set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, WM8994_FLL_SRC_MCLK1, + ARIES_MCLK1_FREQ, pll_out); + if (ret < 0) + return ret; + + /* Set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, + pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static int aries_late_probe(struct snd_soc_card *card) +{ + struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card); + int ret, irq; + + ret = snd_soc_card_jack_new(card, "Dock", SND_JACK_LINEOUT, + &aries_dock, dock_pins, ARRAY_SIZE(dock_pins)); + if (ret) + return ret; + + ret = devm_extcon_register_notifier(card->dev, + priv->usb_extcon, EXTCON_JACK_LINE_OUT, + &aries_extcon_notifier_block); + if (ret) + return ret; + + if (extcon_get_state(priv->usb_extcon, + EXTCON_JACK_LINE_OUT) > 0) + snd_soc_jack_report(&aries_dock, SND_JACK_LINEOUT, + SND_JACK_LINEOUT); + else + snd_soc_jack_report(&aries_dock, 0, SND_JACK_LINEOUT); + + ret = snd_soc_card_jack_new(card, "Headset", + SND_JACK_HEADSET | SND_JACK_BTN_0, + &aries_headset, + jack_pins, ARRAY_SIZE(jack_pins)); + if (ret) + return ret; + + ret = snd_soc_jack_add_zones(&aries_headset, ARRAY_SIZE(headset_zones), + headset_zones); + if (ret) + return ret; + + irq = gpiod_to_irq(priv->gpio_headset_detect); + if (irq < 0) { + dev_err(card->dev, "Failed to map headset detect gpio to irq"); + return -EINVAL; + } + + ret = devm_request_threaded_irq(card->dev, irq, NULL, + headset_det_irq_thread, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "headset_detect", priv); + if (ret) { + dev_err(card->dev, "Failed to request headset detect irq"); + return ret; + } + + headset_button_gpio[0].data = priv; + headset_button_gpio[0].desc = priv->gpio_headset_key; + + snd_jack_set_key(aries_headset.jack, SND_JACK_BTN_0, KEY_MEDIA); + + return snd_soc_jack_add_gpios(&aries_headset, + ARRAY_SIZE(headset_button_gpio), headset_button_gpio); +} + +static const struct snd_soc_pcm_stream baseband_params = { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 1, + .channels_max = 1, +}; + +static const struct snd_soc_pcm_stream bluetooth_params = { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 1, + .channels_max = 2, +}; + +static const struct snd_soc_dapm_widget aries_modem_widgets[] = { + SND_SOC_DAPM_INPUT("Modem RX"), + SND_SOC_DAPM_OUTPUT("Modem TX"), +}; + +static const struct snd_soc_dapm_route aries_modem_routes[] = { + { "Modem Capture", NULL, "Modem RX" }, + { "Modem TX", NULL, "Modem Playback" }, +}; + +static const struct snd_soc_component_driver aries_component = { + .name = "aries-audio", + .dapm_widgets = aries_modem_widgets, + .num_dapm_widgets = ARRAY_SIZE(aries_modem_widgets), + .dapm_routes = aries_modem_routes, + .num_dapm_routes = ARRAY_SIZE(aries_modem_routes), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static struct snd_soc_dai_driver aries_ext_dai[] = { + { + .name = "Voice call", + .playback = { + .stream_name = "Modem Playback", + .channels_min = 1, + .channels_max = 1, + .rate_min = 8000, + .rate_max = 8000, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "Modem Capture", + .channels_min = 1, + .channels_max = 1, + .rate_min = 8000, + .rate_max = 8000, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +SND_SOC_DAILINK_DEFS(aif1, + DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(baseband, + DAILINK_COMP_ARRAY(COMP_CPU("Voice call")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2"))); + +SND_SOC_DAILINK_DEFS(bluetooth, + DAILINK_COMP_ARRAY(COMP_CPU("bt-sco-pcm")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3"))); + +static struct snd_soc_dai_link aries_dai[] = { + { + .name = "WM8994 AIF1", + .stream_name = "HiFi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + .ops = &aries_ops, + SND_SOC_DAILINK_REG(aif1), + }, + { + .name = "WM8994 AIF2", + .stream_name = "Baseband", + .init = &aries_baseband_init, + .params = &baseband_params, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(baseband), + }, + { + .name = "WM8994 AIF3", + .stream_name = "Bluetooth", + .params = &bluetooth_params, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(bluetooth), + }, +}; + +static struct snd_soc_card aries_card = { + .name = "ARIES", + .owner = THIS_MODULE, + .dai_link = aries_dai, + .num_links = ARRAY_SIZE(aries_dai), + .controls = aries_controls, + .num_controls = ARRAY_SIZE(aries_controls), + .dapm_widgets = aries_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aries_dapm_widgets), + .late_probe = aries_late_probe, +}; + +static const struct aries_wm8994_variant fascinate4g_variant = { + .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS + | SND_SOC_DAIFMT_IB_NF, + .has_fm_radio = false, +}; + +static const struct aries_wm8994_variant aries_variant = { + .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM + | SND_SOC_DAIFMT_IB_NF, + .has_fm_radio = true, +}; + +static const struct of_device_id samsung_wm8994_of_match[] = { + { + .compatible = "samsung,fascinate4g-wm8994", + .data = &fascinate4g_variant, + }, + { + .compatible = "samsung,aries-wm8994", + .data = &aries_variant, + }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match); + +static int aries_audio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *cpu, *codec, *extcon_np; + struct device *dev = &pdev->dev; + struct snd_soc_card *card = &aries_card; + struct aries_wm8994_data *priv; + struct snd_soc_dai_link *dai_link; + const struct of_device_id *match; + int ret, i; + + if (!np) + return -EINVAL; + + card->dev = dev; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + + match = of_match_node(samsung_wm8994_of_match, np); + priv->variant = match->data; + + /* Remove FM widget if not present */ + if (!priv->variant->has_fm_radio) + card->num_dapm_widgets--; + + priv->reg_main_micbias = devm_regulator_get(dev, "main-micbias"); + if (IS_ERR(priv->reg_main_micbias)) { + dev_err(dev, "Failed to get main micbias regulator\n"); + return PTR_ERR(priv->reg_main_micbias); + } + + priv->reg_headset_micbias = devm_regulator_get(dev, "headset-micbias"); + if (IS_ERR(priv->reg_headset_micbias)) { + dev_err(dev, "Failed to get headset micbias regulator\n"); + return PTR_ERR(priv->reg_headset_micbias); + } + + priv->gpio_earpath_sel = devm_gpiod_get(dev, "earpath-sel", + GPIOD_OUT_LOW); + if (IS_ERR(priv->gpio_earpath_sel)) { + dev_err(dev, "Failed to get earpath selector gpio"); + return PTR_ERR(priv->gpio_earpath_sel); + } + + extcon_np = of_parse_phandle(np, "extcon", 0); + priv->usb_extcon = extcon_find_edev_by_node(extcon_np); + if (IS_ERR(priv->usb_extcon)) { + if (PTR_ERR(priv->usb_extcon) != -EPROBE_DEFER) + dev_err(dev, "Failed to get extcon device"); + return PTR_ERR(priv->usb_extcon); + } + of_node_put(extcon_np); + + priv->adc = devm_iio_channel_get(dev, "headset-detect"); + if (IS_ERR(priv->adc)) { + if (PTR_ERR(priv->adc) != -EPROBE_DEFER) + dev_err(dev, "Failed to get ADC channel"); + return PTR_ERR(priv->adc); + } + if (priv->adc->channel->type != IIO_VOLTAGE) + return -EINVAL; + + priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key", + GPIOD_IN); + if (IS_ERR(priv->gpio_headset_key)) { + dev_err(dev, "Failed to get headset key gpio"); + return PTR_ERR(priv->gpio_headset_key); + } + + priv->gpio_headset_detect = devm_gpiod_get(dev, + "headset-detect", GPIOD_IN); + if (IS_ERR(priv->gpio_headset_detect)) { + dev_err(dev, "Failed to get headset detect gpio"); + return PTR_ERR(priv->gpio_headset_detect); + } + + /* Update card-name if provided through DT, else use default name */ + snd_soc_of_parse_card_name(card, "model"); + + ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); + if (ret < 0) { + dev_err(dev, "Audio routing invalid/unspecified\n"); + return ret; + } + + aries_dai[1].dai_fmt = priv->variant->modem_dai_fmt; + + cpu = of_get_child_by_name(dev->of_node, "cpu"); + if (!cpu) + return -EINVAL; + + codec = of_get_child_by_name(dev->of_node, "codec"); + if (!codec) + return -EINVAL; + + for_each_card_prelinks(card, i, dai_link) { + dai_link->codecs->of_node = of_parse_phandle(codec, + "sound-dai", 0); + if (!dai_link->codecs->of_node) { + ret = -EINVAL; + goto out; + } + } + + /* Set CPU and platform of_node for main DAI */ + aries_dai[0].cpus->of_node = of_parse_phandle(cpu, + "sound-dai", 0); + if (!aries_dai[0].cpus->of_node) { + ret = -EINVAL; + goto out; + } + + aries_dai[0].platforms->of_node = aries_dai[0].cpus->of_node; + + /* Set CPU of_node for BT DAI */ + aries_dai[2].cpus->of_node = of_parse_phandle(cpu, + "sound-dai", 1); + if (!aries_dai[2].cpus->of_node) { + ret = -EINVAL; + goto out; + } + + ret = devm_snd_soc_register_component(dev, &aries_component, + aries_ext_dai, ARRAY_SIZE(aries_ext_dai)); + if (ret < 0) { + dev_err(dev, "Failed to register component: %d\n", ret); + goto out; + } + + ret = devm_snd_soc_register_card(dev, card); + if (ret) + dev_err(dev, "snd_soc_register_card() failed:%d\n", ret); + +out: + of_node_put(cpu); + of_node_put(codec); + + return ret; +} + +static struct platform_driver aries_audio_driver = { + .driver = { + .name = "aries-audio-wm8994", + .of_match_table = of_match_ptr(samsung_wm8994_of_match), + .pm = &snd_soc_pm_ops, + }, + .probe = aries_audio_probe, +}; + +module_platform_driver(aries_audio_driver); + +MODULE_DESCRIPTION("ALSA SoC ARIES WM8994"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:aries-audio-wm8994"); diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c index c81ece78e036..28587375813a 100644 --- a/sound/soc/samsung/arndale.c +++ b/sound/soc/samsung/arndale.c @@ -20,7 +20,7 @@ static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int rfs, ret; @@ -55,7 +55,7 @@ static struct snd_soc_ops arndale_rt5631_ops = { static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int rfs, rclk; diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 9139a1e7e200..b8f0057a0510 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -67,7 +67,7 @@ static int h1940_startup(struct snd_pcm_substream *substream) static int h1940_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int div; int ret; diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index f86e3028b402..80ecb5c7fed0 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -931,7 +931,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, { struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct i2s_dai *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); unsigned long flags; diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index 30899016cf08..40a85f539509 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c @@ -32,7 +32,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { static int jive_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct s3c_i2sv2_rate_calc div; diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index f4375c49f7f4..a1ff1400857e 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -104,7 +104,7 @@ static int littlemill_set_bias_level_post(struct snd_soc_card *card, static int littlemill_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c new file mode 100644 index 000000000000..d03340ce49a2 --- /dev/null +++ b/sound/soc/samsung/midas_wm1811.c @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Midas audio support +// +// Copyright (C) 2018 Simon Shields <simon@lineageos.org> +// Copyright (C) 2020 Samsung Electronics Co., Ltd. + +#include <linux/clk.h> +#include <linux/mfd/wm8994/registers.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_gpio.h> +#include <linux/regulator/consumer.h> +#include <sound/jack.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include "i2s.h" +#include "../codecs/wm8994.h" + +/* + * The MCLK1 clock source is XCLKOUT with its mux set to the external fixed rate + * oscillator (XXTI). + */ +#define MCLK1_RATE 24000000U +#define MCLK2_RATE 32768U +#define DEFAULT_FLL1_RATE 11289600U + +struct midas_priv { + struct regulator *reg_mic_bias; + struct regulator *reg_submic_bias; + struct gpio_desc *gpio_fm_sel; + struct gpio_desc *gpio_lineout_sel; + unsigned int fll1_rate; + + struct snd_soc_jack headset_jack; +}; + +static int midas_start_fll1(struct snd_soc_pcm_runtime *rtd, unsigned int rate) +{ + struct snd_soc_card *card = rtd->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + int ret; + + if (!rate) + rate = priv->fll1_rate; + /* + * If no new rate is requested, set FLL1 to a sane default for jack + * detection. + */ + if (!rate) + rate = DEFAULT_FLL1_RATE; + + if (rate != priv->fll1_rate && priv->fll1_rate) { + /* while reconfiguring, switch to MCLK2 for SYSCLK */ + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, + MCLK2_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret); + return ret; + } + } + + ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, + MCLK1_RATE, rate); + if (ret < 0) { + dev_err(card->dev, "Failed to set FLL1 rate: %d\n", ret); + return ret; + } + priv->fll1_rate = rate; + + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_FLL1, + priv->fll1_rate, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "Failed to set SYSCLK source: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, 0, + SAMSUNG_I2S_OPCLK_PCLK); + if (ret < 0) { + dev_err(card->dev, "Failed to set OPCLK source: %d\n", ret); + return ret; + } + + return 0; +} + +static int midas_stop_fll1(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + int ret; + + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, + MCLK2_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, 0, 0, 0); + if (ret < 0) { + dev_err(card->dev, "Unable to stop FLL1: %d\n", ret); + return ret; + } + + priv->fll1_rate = 0; + + return 0; +} + +static int midas_aif1_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int pll_out; + + /* AIF1CLK should be at least 3MHz for "optimal performance" */ + if (params_rate(params) == 8000 || params_rate(params) == 11025) + pll_out = params_rate(params) * 512; + else + pll_out = params_rate(params) * 256; + + return midas_start_fll1(rtd, pll_out); +} + +static struct snd_soc_ops midas_aif1_ops = { + .hw_params = midas_aif1_hw_params, +}; + +/* + * We only have a single external speaker, so mix stereo data + * to a single mono stream. + */ +static int midas_ext_spkmode(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS, + WM8994_SPKMIXR_TO_SPKOUTL_MASK, + WM8994_SPKMIXR_TO_SPKOUTL); + break; + case SND_SOC_DAPM_POST_PMD: + ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS, + WM8994_SPKMIXR_TO_SPKOUTL_MASK, + 0); + break; + } + + return ret; +} + +static int midas_mic_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return regulator_enable(priv->reg_mic_bias); + case SND_SOC_DAPM_POST_PMD: + return regulator_disable(priv->reg_mic_bias); + } + + return 0; +} + +static int midas_submic_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return regulator_enable(priv->reg_submic_bias); + case SND_SOC_DAPM_POST_PMD: + return regulator_disable(priv->reg_submic_bias); + } + + return 0; +} + +static int midas_fm_set(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + if (!priv->gpio_fm_sel) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + gpiod_set_value_cansleep(priv->gpio_fm_sel, 1); + break; + case SND_SOC_DAPM_POST_PMD: + gpiod_set_value_cansleep(priv->gpio_fm_sel, 0); + break; + } + + return 0; +} + +static int midas_line_set(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + if (!priv->gpio_lineout_sel) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + gpiod_set_value_cansleep(priv->gpio_lineout_sel, 1); + break; + case SND_SOC_DAPM_POST_PMD: + gpiod_set_value_cansleep(priv->gpio_lineout_sel, 0); + break; + } + + return 0; +} + +static const struct snd_kcontrol_new midas_controls[] = { + SOC_DAPM_PIN_SWITCH("HP"), + + SOC_DAPM_PIN_SWITCH("SPK"), + SOC_DAPM_PIN_SWITCH("RCV"), + + SOC_DAPM_PIN_SWITCH("LINE"), + SOC_DAPM_PIN_SWITCH("HDMI"), + + SOC_DAPM_PIN_SWITCH("Main Mic"), + SOC_DAPM_PIN_SWITCH("Sub Mic"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + + SOC_DAPM_PIN_SWITCH("FM In"), +}; + +static const struct snd_soc_dapm_widget midas_dapm_widgets[] = { + SND_SOC_DAPM_HP("HP", NULL), + + SND_SOC_DAPM_SPK("SPK", midas_ext_spkmode), + SND_SOC_DAPM_SPK("RCV", NULL), + + /* FIXME: toggle MAX77693 on i9300/i9305 */ + SND_SOC_DAPM_LINE("LINE", midas_line_set), + SND_SOC_DAPM_LINE("HDMI", NULL), + SND_SOC_DAPM_LINE("FM In", midas_fm_set), + + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Main Mic", midas_mic_bias), + SND_SOC_DAPM_MIC("Sub Mic", midas_submic_bias), +}; + +static int midas_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, + &card->dai_link[0]); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + + if (dapm->dev != aif1_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + return midas_stop_fll1(rtd); + case SND_SOC_BIAS_PREPARE: + return midas_start_fll1(rtd, 0); + default: + break; + } + + return 0; +} + +static int midas_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, + &card->dai_link[0]); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + int ret; + + /* Use MCLK2 as SYSCLK for boot */ + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, MCLK2_RATE, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(aif1_dai->dev, "Failed to switch to MCLK2: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(card, "Headset", + SND_JACK_HEADSET | SND_JACK_MECHANICAL | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5, + &priv->headset_jack, NULL, 0); + if (ret) + return ret; + + wm8958_mic_detect(aif1_dai->component, &priv->headset_jack, + NULL, NULL, NULL, NULL); + return 0; +} + +static struct snd_soc_dai_driver midas_ext_dai[] = { + { + .name = "Voice call", + .playback = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + .name = "Bluetooth", + .playback = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +static const struct snd_soc_component_driver midas_component = { + .name = "midas-audio", +}; + +SND_SOC_DAILINK_DEFS(wm1811_hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(wm1811_voice, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(wm1811_bt, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link midas_dai[] = { + { + .name = "WM8994 AIF1", + .stream_name = "HiFi Primary", + .ops = &midas_aif1_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(wm1811_hifi), + }, { + .name = "WM1811 Voice", + .stream_name = "Voice call", + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wm1811_voice), + }, { + .name = "WM1811 BT", + .stream_name = "Bluetooth", + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wm1811_bt), + }, +}; + +static struct snd_soc_card midas_card = { + .name = "Midas WM1811", + .owner = THIS_MODULE, + + .dai_link = midas_dai, + .num_links = ARRAY_SIZE(midas_dai), + .controls = midas_controls, + .num_controls = ARRAY_SIZE(midas_controls), + .dapm_widgets = midas_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(midas_dapm_widgets), + + .set_bias_level = midas_set_bias_level, + .late_probe = midas_late_probe, +}; + +static int midas_probe(struct platform_device *pdev) +{ + struct device_node *cpu_dai_node = NULL, *codec_dai_node = NULL; + struct device_node *cpu = NULL, *codec = NULL; + struct snd_soc_card *card = &midas_card; + struct device *dev = &pdev->dev; + static struct snd_soc_dai_link *dai_link; + struct midas_priv *priv; + int ret, i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + card->dev = dev; + + priv->reg_mic_bias = devm_regulator_get(dev, "mic-bias"); + if (IS_ERR(priv->reg_mic_bias)) { + dev_err(dev, "Failed to get mic bias regulator\n"); + return PTR_ERR(priv->reg_mic_bias); + } + + priv->reg_submic_bias = devm_regulator_get(dev, "submic-bias"); + if (IS_ERR(priv->reg_submic_bias)) { + dev_err(dev, "Failed to get submic bias regulator\n"); + return PTR_ERR(priv->reg_submic_bias); + } + + priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpio_fm_sel)) { + dev_err(dev, "Failed to get FM selection GPIO\n"); + return PTR_ERR(priv->gpio_fm_sel); + } + + priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpio_lineout_sel)) { + dev_err(dev, "Failed to get line out selection GPIO\n"); + return PTR_ERR(priv->gpio_lineout_sel); + } + + ret = snd_soc_of_parse_card_name(card, "model"); + if (ret < 0) { + dev_err(dev, "Card name is not specified\n"); + return ret; + } + + ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); + if (ret < 0) { + dev_err(dev, "Audio routing invalid/unspecified\n"); + return ret; + } + + cpu = of_get_child_by_name(dev->of_node, "cpu"); + if (!cpu) + return -EINVAL; + + codec = of_get_child_by_name(dev->of_node, "codec"); + if (!codec) { + of_node_put(cpu); + return -EINVAL; + } + + cpu_dai_node = of_parse_phandle(cpu, "sound-dai", 0); + of_node_put(cpu); + if (!cpu_dai_node) { + dev_err(dev, "parsing cpu/sound-dai failed\n"); + of_node_put(codec); + return -EINVAL; + } + + codec_dai_node = of_parse_phandle(codec, "sound-dai", 0); + of_node_put(codec); + if (!codec_dai_node) { + dev_err(dev, "audio-codec property invalid/missing\n"); + ret = -EINVAL; + goto put_cpu_dai_node; + } + + for_each_card_prelinks(card, i, dai_link) { + dai_link->codecs->of_node = codec_dai_node; + dai_link->cpus->of_node = cpu_dai_node; + dai_link->platforms->of_node = cpu_dai_node; + } + + ret = devm_snd_soc_register_component(dev, &midas_component, + midas_ext_dai, ARRAY_SIZE(midas_ext_dai)); + if (ret < 0) { + dev_err(dev, "Failed to register component: %d\n", ret); + goto put_codec_dai_node; + } + + ret = devm_snd_soc_register_card(dev, card); + if (ret < 0) { + dev_err(dev, "Failed to register card: %d\n", ret); + goto put_codec_dai_node; + } + + return 0; + +put_codec_dai_node: + of_node_put(codec_dai_node); +put_cpu_dai_node: + of_node_put(cpu_dai_node); + return ret; +} + +static const struct of_device_id midas_of_match[] = { + { .compatible = "samsung,midas-audio" }, + { }, +}; +MODULE_DEVICE_TABLE(of, midas_of_match); + +static struct platform_driver midas_driver = { + .driver = { + .name = "midas-audio", + .of_match_table = midas_of_match, + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = midas_probe, +}; +module_platform_driver(midas_driver); + +MODULE_AUTHOR("Simon Shields <simon@lineageos.org>"); +MODULE_DESCRIPTION("ASoC support for Midas"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index b7ce1da854ce..54317e0f68f8 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -25,7 +25,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int pll_out = 0, bclk = 0; @@ -99,7 +99,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* disable the PLL */ @@ -117,7 +117,7 @@ static struct snd_soc_ops neo1973_hifi_ops = { static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int pcmdiv = 0; int ret = 0; @@ -154,7 +154,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* disable the PLL */ diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 6eda5af989fe..ca643a488c3c 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -35,7 +35,7 @@ static int odroid_card_fe_startup(struct snd_pcm_substream *substream) static int odroid_card_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned long flags; int ret = 0; @@ -56,7 +56,7 @@ static const struct snd_soc_ops odroid_card_fe_ops = { static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned int pll_freq, rclk_freq, rfs; unsigned long flags; @@ -115,7 +115,7 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned long flags; diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index a5b1a12b3496..6f50c7b47326 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. */ @@ -211,7 +216,7 @@ static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on) static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); unsigned long flags; @@ -255,7 +260,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); void __iomem *regs = pcm->regs; struct clk *clk; diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 3afe63c0923e..08f7c82aedb6 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -148,7 +148,7 @@ static int rx1950_spk_power(struct snd_soc_dapm_widget *w, static int rx1950_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int div; int ret; diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 5e95c30fb2ba..ed21786104a1 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -379,7 +379,7 @@ static int s3c_i2sv2_set_sysclk(struct snd_soc_dai *cpu_dai, static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c_i2sv2_info *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); unsigned long irqs; diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c index fd2a4da086f3..3cddd11344ac 100644 --- a/sound/soc/samsung/s3c24xx_simtec.c +++ b/sound/soc/samsung/s3c24xx_simtec.c @@ -159,7 +159,7 @@ EXPORT_SYMBOL_GPL(simtec_audio_init); static int simtec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index abb5c4713c53..6272070dcd92 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -49,7 +49,7 @@ static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; @@ -101,7 +101,7 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); mutex_lock(&priv->clk_lock); @@ -118,7 +118,7 @@ static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index 36bef136d57f..c95629becbc3 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c @@ -24,7 +24,7 @@ static struct snd_soc_card snd_soc_smartq; static int smartq_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c index 776a270261bf..6f3eeb7bc834 100644 --- a/sound/soc/samsung/smdk_spdif.c +++ b/sound/soc/samsung/smdk_spdif.c @@ -100,7 +100,7 @@ static int set_audio_clock_rate(unsigned long epll_rate, static int smdk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned long pll_out, rclk_rate; int ret, ratio; diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index 02074c34a2b2..ed753a2f202e 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c @@ -22,7 +22,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int pll_out; int rfs, ret; diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index a9f345f19a8a..64a1a64656ab 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -44,7 +44,7 @@ static struct smdk_wm8994_data smdk_board_data = { static int smdk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int pll_out; int ret; diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 746930dde5d7..a01640576f71 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -43,7 +43,7 @@ static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned long mclk_freq; diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 40c5de8df0ff..07163f07c6d5 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -30,7 +30,7 @@ static int snow_card_hw_params(struct snd_pcm_substream *substream, static const unsigned int pll_rate[] = { 73728000U, 67737602U, 49152000U, 45158401U, 32768001U }; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snow_priv *priv = snd_soc_card_get_drvdata(rtd->card); int bfs, psr, rfs, bitwidth; unsigned long int rclk; diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 759fc6644329..226c359892e9 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 { @@ -141,7 +141,7 @@ static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai, static int spdif_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct samsung_spdif_info *spdif = to_info(asoc_rtd_to_cpu(rtd, 0)); unsigned long flags; @@ -177,7 +177,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct samsung_spdif_info *spdif = to_info(asoc_rtd_to_cpu(rtd, 0)); void __iomem *regs = spdif->regs; struct snd_dmaengine_dai_dma_data *dma_data; @@ -279,7 +279,7 @@ err: static void spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct samsung_spdif_info *spdif = to_info(asoc_rtd_to_cpu(rtd, 0)); void __iomem *regs = spdif->regs; u32 con, clkcon; diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 6dfd540e2d74..9300fef9bf26 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -92,7 +92,7 @@ static int tm2_stop_sysclk(struct snd_soc_card *card) static int tm2_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card); @@ -133,7 +133,7 @@ static struct snd_soc_ops tm2_aif1_ops = { static int tm2_aif2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; unsigned int asyncclk_rate; int ret; @@ -187,7 +187,7 @@ static int tm2_aif2_hw_params(struct snd_pcm_substream *substream, static int tm2_aif2_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int ret; @@ -208,7 +208,7 @@ static struct snd_soc_ops tm2_aif2_ops = { static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int bfs; int bitwidth, ret; diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index dc20f0f7080a..ef8a29b9f641 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -30,8 +30,8 @@ config SND_SOC_SH4_FSI config SND_SOC_SH4_SIU tristate depends on ARCH_SHMOBILE && HAVE_CLK + depends on DMADEVICES select DMA_ENGINE - select DMADEVICES select SH_DMAE select FW_LOADER diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index a35de78f14a9..b70068dd5a06 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -118,7 +118,7 @@ static void camelot_rxdma(void *data) static int camelot_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int ret, dmairq; @@ -152,7 +152,7 @@ static int camelot_pcm_open(struct snd_soc_component *component, static int camelot_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int dmairq; @@ -174,7 +174,7 @@ static int camelot_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int ret; @@ -193,7 +193,7 @@ static int camelot_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; pr_debug("PCM data: addr 0x%08lx len %d\n", @@ -241,7 +241,7 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam) static int camelot_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; @@ -269,7 +269,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; unsigned long pos; diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1c3c4fdc9bef..3c574792231b 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -406,7 +406,7 @@ static int fsi_is_play(struct snd_pcm_substream *substream) static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); return asoc_rtd_to_cpu(rtd, 0); } @@ -1632,12 +1632,12 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); int ret; - /* set master/slave audio interface */ + /* set clock master audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: break; case SND_SOC_DAIFMT_CBS_CFS: - fsi->clk_master = 1; /* codec is slave, cpu is master */ + fsi->clk_master = 1; /* cpu is master */ break; default: return -EINVAL; diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index d5702fbf176b..7082c12d3bf2 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -45,7 +45,7 @@ static struct clk_lookup *siumckb_lookup; static int migor_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; unsigned int rate = params_rate(params); @@ -78,7 +78,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, static int migor_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); if (use_count) { diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4349f2fb823f..6e670b3e92a0 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -694,7 +694,7 @@ static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io) static struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); return asoc_rtd_to_cpu(rtd, 0); } @@ -759,13 +759,13 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); - /* set master/slave audio interface */ + /* set clock master for audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: rdai->clk_master = 0; break; case SND_SOC_DAIFMT_CBS_CFS: - rdai->clk_master = 1; /* codec is slave, cpu is master */ + rdai->clk_master = 1; /* cpu is master */ break; default: return -EINVAL; @@ -1399,7 +1399,7 @@ static int rsnd_hw_params(struct snd_soc_component *component, struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); /* * rsnd assumes that it might be used under DPCM if user want to use diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d47608ff5fac..6b519370fd64 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -775,7 +775,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv); void rsnd_ssi_remove(struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); -u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io); +u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io); #define rsnd_ssi_is_pin_sharing(io) \ __rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io)) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 47d5ddb526f2..d0ded427a836 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -111,8 +111,8 @@ struct rsnd_ssi { #define rsnd_ssi_nr(priv) ((priv)->ssi_nr) #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io)) -#define rsnd_ssi_is_multi_slave(mod, io) \ - (rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod))) +#define rsnd_ssi_is_multi_secondary(mod, io) \ + (rsnd_ssi_multi_secondaries(io) & (1 << rsnd_mod_id(mod))) #define rsnd_ssi_is_run_mods(mod, io) \ (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod))) #define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod)) @@ -165,7 +165,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, dev_warn(dev, "%s status check failed\n", rsnd_mod_name(mod)); } -static u32 rsnd_ssi_multi_slaves(struct rsnd_dai_stream *io) +static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) { struct rsnd_mod *mod; enum rsnd_mod_type types[] = { @@ -193,7 +193,7 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io) struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); u32 mods; - mods = rsnd_ssi_multi_slaves_runtime(io) | + mods = rsnd_ssi_multi_secondaries_runtime(io) | 1 << rsnd_mod_id(ssi_mod); if (ssi_parent_mod) @@ -202,10 +202,10 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io) return mods; } -u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io) +u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io) { if (rsnd_runtime_is_multi_ssi(io)) - return rsnd_ssi_multi_slaves(io); + return rsnd_ssi_multi_secondaries(io); return 0; } @@ -283,7 +283,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, if (!rsnd_ssi_can_output_clk(mod)) return 0; - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return 0; if (rsnd_runtime_is_tdm_split(io)) @@ -626,7 +626,7 @@ static int rsnd_ssi_start(struct rsnd_mod *mod, * EN will be set via SSIU :: SSI_CONTROL * if Multi channel mode */ - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) return 0; /* @@ -675,7 +675,7 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod, /* In multi-SSI mode, stop is performed by setting ssi0129 in * SSI_CONTROL to 0 (in rsnd_ssio_stop_gen2). Do nothing here. */ - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) return 0; /* @@ -888,7 +888,7 @@ static void rsnd_ssi_parent_attach(struct rsnd_mod *mod, if (!rsnd_rdai_is_clk_master(rdai)) return; - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return; switch (rsnd_mod_id(mod)) { @@ -930,9 +930,9 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod, /* * SSIP/SSIU/IRQ are not needed on - * SSI Multi slaves + * SSI Multi secondaries */ - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return 0; /* @@ -1091,9 +1091,9 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, /* * SSIP/SSIU/IRQ/DMA are not needed on - * SSI Multi slaves + * SSI Multi secondaries */ - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return 0; ret = rsnd_ssi_common_probe(mod, io, priv); diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 9c7c3e7539c9..f29bd72f3a26 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -60,7 +60,7 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_dai *rdai = rsnd_io_to_rdai(io); - u32 ssis = rsnd_ssi_multi_slaves_runtime(io); + u32 ssis = rsnd_ssi_multi_secondaries_runtime(io); int use_busif = rsnd_ssi_use_busif(io); int id = rsnd_mod_id(mod); int is_clk_master = rsnd_rdai_is_clk_master(rdai); @@ -246,7 +246,7 @@ static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod, rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4)); - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) rsnd_mod_write(mod, SSI_CONTROL, 0x1); return 0; @@ -267,7 +267,7 @@ static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod, if (--ssiu->usrcnt) return 0; - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) rsnd_mod_write(mod, SSI_CONTROL, 0); return 0; diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 6a6ffd6d3192..bd9de77c35f3 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -281,11 +281,11 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info) return 0; } -static bool filter(struct dma_chan *chan, void *slave) +static bool filter(struct dma_chan *chan, void *secondary) { - struct sh_dmae_slave *param = slave; + struct sh_dmae_slave *param = secondary; - pr_debug("%s: slave ID %d\n", __func__, param->shdma_slave.slave_id); + pr_debug("%s: secondary ID %d\n", __func__, param->shdma_slave.slave_id); chan->private = ¶m->shdma_slave; return true; diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index 8125fa3840b6..15b01bcefca5 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c @@ -304,7 +304,7 @@ static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ssicr |= CR_SWS_MASTER | CR_SCK_MASTER; break; default: - pr_debug("ssi: invalid master/slave configuration\n"); + pr_debug("ssi: invalid master/secondary configuration\n"); return -EINVAL; } diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index c086786e4471..65db083e242b 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -82,13 +82,12 @@ static int snd_soc_ac97_gpio_get(struct gpio_chip *chip, unsigned offset) struct snd_soc_component *component = gpio_to_component(chip); int ret; - if (snd_soc_component_read(component, AC97_GPIO_STATUS, &ret) < 0) - ret = -1; + ret = snd_soc_component_read(component, AC97_GPIO_STATUS); dev_dbg(component->dev, "get gpio %d : %d\n", offset, - ret < 0 ? ret : ret & (1 << offset)); + ret & (1 << offset)); - return ret < 0 ? ret : !!(ret & (1 << offset)); + return !!(ret & (1 << offset)); } static void snd_soc_ac97_gpio_set(struct gpio_chip *chip, unsigned offset, @@ -394,6 +393,8 @@ EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); /** * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions + * @ops: bus ops + * @pdev: platform device * * This function sets the reset and warm_reset properties of ops and parses * the device node of pdev to get pinctrl states and gpio numbers to use. diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 785a0385cc7f..f0b4f4bc44a4 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -2,12 +2,53 @@ // // soc-component.c // +// Copyright 2009-2011 Wolfson Microelectronics PLC. // Copyright (C) 2019 Renesas Electronics Corp. +// +// Mark Brown <broonie@opensource.wolfsonmicro.com> // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> // #include <linux/module.h> #include <sound/soc.h> +#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret) +static inline int _soc_component_ret(struct snd_soc_component *component, + const char *func, int ret) +{ + /* Positive/Zero values are not errors */ + if (ret >= 0) + return ret; + + /* Negative values might be errors */ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + break; + default: + dev_err(component->dev, + "ASoC: error at %s on %s: %d\n", + func, component->name, ret); + } + + return ret; +} + +void snd_soc_component_set_aux(struct snd_soc_component *component, + struct snd_soc_aux_dev *aux) +{ + component->init = (aux) ? aux->init : NULL; +} + +int snd_soc_component_init(struct snd_soc_component *component) +{ + int ret = 0; + + if (component->init) + ret = component->init(component); + + return soc_component_ret(component, ret); +} + /** * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. * @component: COMPONENT @@ -22,11 +63,13 @@ int snd_soc_component_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsigned int freq, int dir) { + int ret = -ENOTSUPP; + if (component->driver->set_sysclk) - return component->driver->set_sysclk(component, clk_id, source, + ret = component->driver->set_sysclk(component, clk_id, source, freq, dir); - return -ENOTSUPP; + return soc_component_ret(component, ret); } EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); @@ -44,11 +87,13 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { + int ret = -EINVAL; + if (component->driver->set_pll) - return component->driver->set_pll(component, pll_id, source, + ret = component->driver->set_pll(component, pll_id, source, freq_in, freq_out); - return -EINVAL; + return soc_component_ret(component, ret); } EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); @@ -62,194 +107,105 @@ void snd_soc_component_seq_notifier(struct snd_soc_component *component, int snd_soc_component_stream_event(struct snd_soc_component *component, int event) { + int ret = 0; + if (component->driver->stream_event) - return component->driver->stream_event(component, event); + ret = component->driver->stream_event(component, event); - return 0; + return soc_component_ret(component, ret); } int snd_soc_component_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { + int ret = 0; + if (component->driver->set_bias_level) - return component->driver->set_bias_level(component, level); + ret = component->driver->set_bias_level(component, level); - return 0; + return soc_component_ret(component, ret); } -int snd_soc_component_enable_pin(struct snd_soc_component *component, - const char *pin) +static int soc_component_pin(struct snd_soc_component *component, + const char *pin, + int (*pin_func)(struct snd_soc_dapm_context *dapm, + const char *pin)) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); char *full_name; int ret; - if (!component->name_prefix) - return snd_soc_dapm_enable_pin(dapm, pin); + if (!component->name_prefix) { + ret = pin_func(dapm, pin); + goto end; + } full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; + if (!full_name) { + ret = -ENOMEM; + goto end; + } - ret = snd_soc_dapm_enable_pin(dapm, full_name); + ret = pin_func(dapm, full_name); kfree(full_name); +end: + return soc_component_ret(component, ret); +} - return ret; +int snd_soc_component_enable_pin(struct snd_soc_component *component, + const char *pin) +{ + return soc_component_pin(component, pin, snd_soc_dapm_enable_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_enable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); int snd_soc_component_disable_pin(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_disable_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_disable_pin(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_disable_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_disable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); int snd_soc_component_nc_pin(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_nc_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_nc_pin(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_nc_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_nc_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); int snd_soc_component_get_pin_status(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_get_pin_status(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_get_pin_status(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status); } EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); int snd_soc_component_force_enable_pin(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_force_enable_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_force_enable_pin(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); @@ -257,22 +213,7 @@ int snd_soc_component_force_enable_pin_unlocked( struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); @@ -287,21 +228,25 @@ EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); int snd_soc_component_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jack, void *data) { + int ret = -ENOTSUPP; + if (component->driver->set_jack) - return component->driver->set_jack(component, jack, data); + ret = component->driver->set_jack(component, jack, data); - return -ENOTSUPP; + return soc_component_ret(component, ret); } EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); int snd_soc_component_module_get(struct snd_soc_component *component, int upon_open) { + int ret = 0; + if (component->driver->module_get_upon_open == !!upon_open && !try_module_get(component->dev->driver->owner)) - return -ENODEV; + ret = -ENODEV; - return 0; + return soc_component_ret(component, ret); } void snd_soc_component_module_put(struct snd_soc_component *component, @@ -314,52 +259,23 @@ void snd_soc_component_module_put(struct snd_soc_component *component, int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { + int ret = 0; + if (component->driver->open) - return component->driver->open(component, substream); - return 0; + ret = component->driver->open(component, substream); + + return soc_component_ret(component, ret); } int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - if (component->driver->close) - return component->driver->close(component, substream); - return 0; -} + int ret = 0; -int snd_soc_component_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - if (component->driver->prepare) - return component->driver->prepare(component, substream); - return 0; -} - -int snd_soc_component_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - if (component->driver->hw_params) - return component->driver->hw_params(component, - substream, params); - return 0; -} - -int snd_soc_component_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - if (component->driver->hw_free) - return component->driver->hw_free(component, substream); - return 0; -} + if (component->driver->close) + ret = component->driver->close(component, substream); -int snd_soc_component_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - int cmd) -{ - if (component->driver->trigger) - return component->driver->trigger(component, substream, cmd); - return 0; + return soc_component_ret(component, ret); } void snd_soc_component_suspend(struct snd_soc_component *component) @@ -383,10 +299,12 @@ int snd_soc_component_is_suspended(struct snd_soc_component *component) int snd_soc_component_probe(struct snd_soc_component *component) { + int ret = 0; + if (component->driver->probe) - return component->driver->probe(component); + ret = component->driver->probe(component); - return 0; + return soc_component_ret(component, ret); } void snd_soc_component_remove(struct snd_soc_component *component) @@ -398,10 +316,12 @@ void snd_soc_component_remove(struct snd_soc_component *component) int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, struct device_node *ep) { + int ret = -ENOTSUPP; + if (component->driver->of_xlate_dai_id) - return component->driver->of_xlate_dai_id(component, ep); + ret = component->driver->of_xlate_dai_id(component, ep); - return -ENOTSUPP; + return soc_component_ret(component, ret); } int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, @@ -410,13 +330,269 @@ int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, { if (component->driver->of_xlate_dai_name) return component->driver->of_xlate_dai_name(component, - args, dai_name); + args, dai_name); + /* + * Don't use soc_component_ret here because we may not want to report + * the error just yet. If a device has more than one component, the + * first may not match and we don't want spam the log with this. + */ return -ENOTSUPP; } +void snd_soc_component_setup_regmap(struct snd_soc_component *component) +{ + int val_bytes = regmap_get_val_bytes(component->regmap); + + /* Errors are legitimate for non-integer byte multiples */ + if (val_bytes > 0) + component->val_bytes = val_bytes; +} + +#ifdef CONFIG_REGMAP + +/** + * snd_soc_component_init_regmap() - Initialize regmap instance for the + * component + * @component: The component for which to initialize the regmap instance + * @regmap: The regmap instance that should be used by the component + * + * This function allows deferred assignment of the regmap instance that is + * associated with the component. Only use this if the regmap instance is not + * yet ready when the component is registered. The function must also be called + * before the first IO attempt of the component. + */ +void snd_soc_component_init_regmap(struct snd_soc_component *component, + struct regmap *regmap) +{ + component->regmap = regmap; + snd_soc_component_setup_regmap(component); +} +EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); + +/** + * snd_soc_component_exit_regmap() - De-initialize regmap instance for the + * component + * @component: The component for which to de-initialize the regmap instance + * + * Calls regmap_exit() on the regmap instance associated to the component and + * removes the regmap instance from the component. + * + * This function should only be used if snd_soc_component_init_regmap() was used + * to initialize the regmap instance. + */ +void snd_soc_component_exit_regmap(struct snd_soc_component *component) +{ + regmap_exit(component->regmap); + component->regmap = NULL; +} +EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); + +#endif + +static unsigned int soc_component_read_no_lock( + struct snd_soc_component *component, + unsigned int reg) +{ + int ret; + unsigned int val = 0; + + if (component->regmap) + ret = regmap_read(component->regmap, reg, &val); + else if (component->driver->read) { + ret = 0; + val = component->driver->read(component, reg); + } + else + ret = -EIO; + + if (ret < 0) + soc_component_ret(component, ret); + + return val; +} + +/** + * snd_soc_component_read() - Read register value + * @component: Component to read from + * @reg: Register to read + * + * Return: read value + */ +unsigned int snd_soc_component_read(struct snd_soc_component *component, + unsigned int reg) +{ + unsigned int val; + + mutex_lock(&component->io_mutex); + val = soc_component_read_no_lock(component, reg); + mutex_unlock(&component->io_mutex); + + return val; +} +EXPORT_SYMBOL_GPL(snd_soc_component_read); + +static int soc_component_write_no_lock( + struct snd_soc_component *component, + unsigned int reg, unsigned int val) +{ + int ret = -EIO; + + if (component->regmap) + ret = regmap_write(component->regmap, reg, val); + else if (component->driver->write) + ret = component->driver->write(component, reg, val); + + return soc_component_ret(component, ret); +} + +/** + * snd_soc_component_write() - Write register value + * @component: Component to write to + * @reg: Register to write + * @val: Value to write to the register + * + * Return: 0 on success, a negative error code otherwise. + */ +int snd_soc_component_write(struct snd_soc_component *component, + unsigned int reg, unsigned int val) +{ + int ret; + + mutex_lock(&component->io_mutex); + ret = soc_component_write_no_lock(component, reg, val); + mutex_unlock(&component->io_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_write); + +static int snd_soc_component_update_bits_legacy( + struct snd_soc_component *component, unsigned int reg, + unsigned int mask, unsigned int val, bool *change) +{ + unsigned int old, new; + int ret = 0; + + mutex_lock(&component->io_mutex); + + old = soc_component_read_no_lock(component, reg); + + new = (old & ~mask) | (val & mask); + *change = old != new; + if (*change) + ret = soc_component_write_no_lock(component, reg, new); + + mutex_unlock(&component->io_mutex); + + return soc_component_ret(component, ret); +} + +/** + * snd_soc_component_update_bits() - Perform read/modify/write cycle + * @component: Component to update + * @reg: Register to update + * @mask: Mask that specifies which bits to update + * @val: New value for the bits specified by mask + * + * Return: 1 if the operation was successful and the value of the register + * changed, 0 if the operation was successful, but the value did not change. + * Returns a negative error code otherwise. + */ +int snd_soc_component_update_bits(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, unsigned int val) +{ + bool change; + int ret; + + if (component->regmap) + ret = regmap_update_bits_check(component->regmap, reg, mask, + val, &change); + else + ret = snd_soc_component_update_bits_legacy(component, reg, + mask, val, &change); + + if (ret < 0) + return soc_component_ret(component, ret); + return change; +} +EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); + +/** + * snd_soc_component_update_bits_async() - Perform asynchronous + * read/modify/write cycle + * @component: Component to update + * @reg: Register to update + * @mask: Mask that specifies which bits to update + * @val: New value for the bits specified by mask + * + * This function is similar to snd_soc_component_update_bits(), but the update + * operation is scheduled asynchronously. This means it may not be completed + * when the function returns. To make sure that all scheduled updates have been + * completed snd_soc_component_async_complete() must be called. + * + * Return: 1 if the operation was successful and the value of the register + * changed, 0 if the operation was successful, but the value did not change. + * Returns a negative error code otherwise. + */ +int snd_soc_component_update_bits_async(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, unsigned int val) +{ + bool change; + int ret; + + if (component->regmap) + ret = regmap_update_bits_check_async(component->regmap, reg, + mask, val, &change); + else + ret = snd_soc_component_update_bits_legacy(component, reg, + mask, val, &change); + + if (ret < 0) + return soc_component_ret(component, ret); + return change; +} +EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); + +/** + * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed + * @component: Component for which to wait + * + * This function blocks until all asynchronous I/O which has previously been + * scheduled using snd_soc_component_update_bits_async() has completed. + */ +void snd_soc_component_async_complete(struct snd_soc_component *component) +{ + if (component->regmap) + regmap_async_complete(component->regmap); +} +EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); + +/** + * snd_soc_component_test_bits - Test register for change + * @component: component + * @reg: Register to test + * @mask: Mask that specifies which bits to test + * @value: Value to test against + * + * Tests a register with a new value and checks if the new value is + * different from the old value. + * + * Return: 1 for change, otherwise 0. + */ +int snd_soc_component_test_bits(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, unsigned int value) +{ + unsigned int old, new; + + old = snd_soc_component_read(component, reg); + new = (old & ~mask) | value; + return old != new; +} +EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); + int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; @@ -431,22 +607,24 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; /* FIXME: use 1st ioctl */ for_each_rtd_components(rtd, i, component) if (component->driver->ioctl) - return component->driver->ioctl(component, substream, - cmd, arg); + return soc_component_ret( + component, + component->driver->ioctl(component, + substream, cmd, arg)); return snd_pcm_lib_ioctl(substream, cmd, arg); } int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i, ret; @@ -455,7 +633,7 @@ int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) ret = component->driver->sync_stop(component, substream); if (ret < 0) - return ret; + return soc_component_ret(component, ret); } } @@ -466,15 +644,18 @@ int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, int channel, unsigned long pos, void __user *buf, unsigned long bytes) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; /* FIXME. it returns 1st copy now */ for_each_rtd_components(rtd, i, component) if (component->driver->copy_user) - return component->driver->copy_user( - component, substream, channel, pos, buf, bytes); + return soc_component_ret( + component, + component->driver->copy_user( + component, substream, channel, + pos, buf, bytes)); return -EINVAL; } @@ -482,7 +663,7 @@ int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, unsigned long offset) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct page *page; int i; @@ -503,15 +684,17 @@ struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; /* FIXME. it returns 1st mmap now */ for_each_rtd_components(rtd, i, component) if (component->driver->mmap) - return component->driver->mmap(component, - substream, vma); + return soc_component_ret( + component, + component->driver->mmap(component, + substream, vma)); return -EINVAL; } @@ -526,7 +709,7 @@ int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd) if (component->driver->pcm_construct) { ret = component->driver->pcm_construct(component, rtd); if (ret < 0) - return ret; + return soc_component_ret(component, ret); } } @@ -545,3 +728,80 @@ void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd) if (component->driver->pcm_destruct) component->driver->pcm_destruct(component, rtd->pcm); } + +int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component->driver->prepare) { + ret = component->driver->prepare(component, substream); + if (ret < 0) + return soc_component_ret(component, ret); + } + } + + return 0; +} + +int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_component **last) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component->driver->hw_params) { + ret = component->driver->hw_params(component, + substream, params); + if (ret < 0) { + *last = component; + return soc_component_ret(component, ret); + } + } + } + + *last = NULL; + return 0; +} + +void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_component *last) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component == last) + break; + + if (component->driver->hw_free) { + ret = component->driver->hw_free(component, substream); + if (ret < 0) + soc_component_ret(component, ret); + } + } +} + +int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component->driver->trigger) { + ret = component->driver->trigger(component, substream, cmd); + if (ret < 0) + return soc_component_ret(component, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 4984b6a2c370..415510909a82 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -867,8 +867,8 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) rtd->compr = compr; compr->private_data = rtd; - dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", - codec_dai->name, cpu_dai->name); + dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", + codec_dai->name, cpu_dai->name); return 0; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2b8abf88ec60..2fe1b2ec7c8f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -446,7 +446,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( dev->parent = card->dev; dev->release = soc_release_rtd_dev; - dev->groups = soc_dev_attr_groups; dev_set_name(dev, "%s", dai_link->name); @@ -503,6 +502,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( /* see for_each_card_rtds */ list_add_tail(&rtd->list, &card->rtd_list); + ret = device_add_groups(dev, soc_dev_attr_groups); + if (ret < 0) + goto free_rtd; + return rtd; free_rtd: @@ -548,7 +551,7 @@ int snd_soc_suspend(struct device *dev) if (rtd->dai_link->ignore_suspend) continue; - for_each_rtd_codec_dais(rtd, i, dai) { + for_each_rtd_dais(rtd, i, dai) { if (snd_soc_dai_stream_active(dai, playback)) snd_soc_dai_digital_mute(dai, 1, playback); } @@ -687,7 +690,7 @@ static void soc_resume_deferred(struct work_struct *work) if (rtd->dai_link->ignore_suspend) continue; - for_each_rtd_codec_dais(rtd, i, dai) { + for_each_rtd_dais(rtd, i, dai) { if (snd_soc_dai_stream_active(dai, playback)) snd_soc_dai_digital_mute(dai, 0, playback); } @@ -945,6 +948,9 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, { lockdep_assert_held(&client_mutex); + /* release machine specific resources */ + snd_soc_link_exit(rtd); + /* * Notify the machine driver for extra destruction */ @@ -1208,15 +1214,14 @@ static int soc_probe_component(struct snd_soc_card *card, component->name); probed = 1; - /* machine specific init */ - if (component->init) { - ret = component->init(component); - if (ret < 0) { - dev_err(component->dev, - "Failed to do machine specific init %d\n", ret); - goto err_probe; - } - } + /* + * machine specific init + * see + * snd_soc_component_set_aux() + */ + ret = snd_soc_component_init(component); + if (ret < 0) + goto err_probe; ret = snd_soc_add_component_controls(component, component->driver->controls, @@ -1330,7 +1335,8 @@ static void soc_unbind_aux_dev(struct snd_soc_card *card) struct snd_soc_component *component, *_component; for_each_card_auxs_safe(card, component, _component) { - component->init = NULL; + /* for snd_soc_component_init() */ + snd_soc_component_set_aux(component, NULL); list_del(&component->card_aux_list); } } @@ -1347,7 +1353,8 @@ static int soc_bind_aux_dev(struct snd_soc_card *card) if (!component) return -EPROBE_DEFER; - component->init = aux->init; + /* for snd_soc_component_init() */ + snd_soc_component_set_aux(component, aux); /* see for_each_card_auxs */ list_add(&component->card_aux_list, &card->aux_comp_list); } @@ -1638,8 +1645,8 @@ match: continue; } - dev_info(card->dev, "info: override BE DAI link %s\n", - card->dai_link[i].name); + dev_dbg(card->dev, "info: override BE DAI link %s\n", + card->dai_link[i].name); /* override platform component */ if (!dai_link->platforms) { @@ -2378,76 +2385,6 @@ err: return ret; } -static int snd_soc_component_initialize(struct snd_soc_component *component, - const struct snd_soc_component_driver *driver, struct device *dev) -{ - INIT_LIST_HEAD(&component->dai_list); - INIT_LIST_HEAD(&component->dobj_list); - INIT_LIST_HEAD(&component->card_list); - mutex_init(&component->io_mutex); - - component->name = fmt_single_name(dev, &component->id); - if (!component->name) { - dev_err(dev, "ASoC: Failed to allocate name\n"); - return -ENOMEM; - } - - component->dev = dev; - component->driver = driver; - - return 0; -} - -static void snd_soc_component_setup_regmap(struct snd_soc_component *component) -{ - int val_bytes = regmap_get_val_bytes(component->regmap); - - /* Errors are legitimate for non-integer byte multiples */ - if (val_bytes > 0) - component->val_bytes = val_bytes; -} - -#ifdef CONFIG_REGMAP - -/** - * snd_soc_component_init_regmap() - Initialize regmap instance for the - * component - * @component: The component for which to initialize the regmap instance - * @regmap: The regmap instance that should be used by the component - * - * This function allows deferred assignment of the regmap instance that is - * associated with the component. Only use this if the regmap instance is not - * yet ready when the component is registered. The function must also be called - * before the first IO attempt of the component. - */ -void snd_soc_component_init_regmap(struct snd_soc_component *component, - struct regmap *regmap) -{ - component->regmap = regmap; - snd_soc_component_setup_regmap(component); -} -EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); - -/** - * snd_soc_component_exit_regmap() - De-initialize regmap instance for the - * component - * @component: The component for which to de-initialize the regmap instance - * - * Calls regmap_exit() on the regmap instance associated to the component and - * removes the regmap instance from the component. - * - * This function should only be used if snd_soc_component_init_regmap() was used - * to initialize the regmap instance. - */ -void snd_soc_component_exit_regmap(struct snd_soc_component *component) -{ - regmap_exit(component->regmap); - component->regmap = NULL; -} -EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); - -#endif - #define ENDIANNESS_MAP(name) \ (SNDRV_PCM_FMTBIT_##name##LE | SNDRV_PCM_FMTBIT_##name##BE) static u64 endianness_format_map[] = { @@ -2504,22 +2441,38 @@ static void snd_soc_del_component_unlocked(struct snd_soc_component *component) list_del(&component->list); } -int snd_soc_add_component(struct device *dev, - struct snd_soc_component *component, - const struct snd_soc_component_driver *component_driver, - struct snd_soc_dai_driver *dai_drv, - int num_dai) +int snd_soc_component_initialize(struct snd_soc_component *component, + const struct snd_soc_component_driver *driver, + struct device *dev) +{ + INIT_LIST_HEAD(&component->dai_list); + INIT_LIST_HEAD(&component->dobj_list); + INIT_LIST_HEAD(&component->card_list); + mutex_init(&component->io_mutex); + + component->name = fmt_single_name(dev, &component->id); + if (!component->name) { + dev_err(dev, "ASoC: Failed to allocate name\n"); + return -ENOMEM; + } + + component->dev = dev; + component->driver = driver; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_component_initialize); + +int snd_soc_add_component(struct snd_soc_component *component, + struct snd_soc_dai_driver *dai_drv, + int num_dai) { int ret; int i; mutex_lock(&client_mutex); - ret = snd_soc_component_initialize(component, component_driver, dev); - if (ret) - goto err_free; - - if (component_driver->endianness) { + if (component->driver->endianness) { for (i = 0; i < num_dai; i++) { convert_endianness_formats(&dai_drv[i].playback); convert_endianness_formats(&dai_drv[i].capture); @@ -2528,7 +2481,8 @@ int snd_soc_add_component(struct device *dev, ret = snd_soc_register_dais(component, dai_drv, num_dai); if (ret < 0) { - dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret); + dev_err(component->dev, "ASoC: Failed to register DAIs: %d\n", + ret); goto err_cleanup; } @@ -2546,7 +2500,7 @@ int snd_soc_add_component(struct device *dev, err_cleanup: if (ret < 0) snd_soc_del_component_unlocked(component); -err_free: + mutex_unlock(&client_mutex); if (ret == 0) @@ -2562,13 +2516,17 @@ int snd_soc_register_component(struct device *dev, int num_dai) { struct snd_soc_component *component; + int ret; component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL); if (!component) return -ENOMEM; - return snd_soc_add_component(dev, component, component_driver, - dai_drv, num_dai); + ret = snd_soc_component_initialize(component, component_driver, dev); + if (ret < 0) + return ret; + + return snd_soc_add_component(component, dai_drv, num_dai); } EXPORT_SYMBOL_GPL(snd_soc_register_component); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 457159975b01..91a2551e4cef 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -298,13 +298,15 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, { int ret = -ENOTSUPP; + /* + * ignore if direction was CAPTURE + * and it had .no_capture_mute flag + */ if (dai->driver->ops && - dai->driver->ops->mute_stream) + dai->driver->ops->mute_stream && + (direction == SNDRV_PCM_STREAM_PLAYBACK || + !dai->driver->ops->no_capture_mute)) ret = dai->driver->ops->mute_stream(dai, mute, direction); - else if (direction == SNDRV_PCM_STREAM_PLAYBACK && - dai->driver->ops && - dai->driver->ops->digital_mute) - ret = dai->driver->ops->digital_mute(dai, mute); return soc_dai_ret(dai, ret); } @@ -314,7 +316,7 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; /* perform any topology hw_params fixups before DAI */ @@ -400,28 +402,30 @@ void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link) struct snd_soc_dai_link_component *codec; struct snd_soc_dai *dai; bool supported[SNDRV_PCM_STREAM_LAST + 1]; + bool supported_cpu; + bool supported_codec; int direction; int i; for_each_pcm_streams(direction) { - supported[direction] = true; + supported_cpu = false; + supported_codec = false; for_each_link_cpus(dai_link, i, cpu) { dai = snd_soc_find_dai(cpu); - if (!dai || !snd_soc_dai_stream_valid(dai, direction)) { - supported[direction] = false; + if (dai && snd_soc_dai_stream_valid(dai, direction)) { + supported_cpu = true; break; } } - if (!supported[direction]) - continue; for_each_link_codecs(dai_link, i, codec) { dai = snd_soc_find_dai(codec); - if (!dai || !snd_soc_dai_stream_valid(dai, direction)) { - supported[direction] = false; + if (dai && snd_soc_dai_stream_valid(dai, direction)) { + supported_codec = true; break; } } + supported[direction] = supported_cpu && supported_codec; } dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK]; @@ -514,7 +518,7 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret; @@ -533,7 +537,7 @@ int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret; @@ -552,7 +556,7 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2491e1ce16d3..3273161e2787 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -616,12 +616,11 @@ static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm) return dapm->component->name_prefix; } -static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg, - unsigned int *value) +static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg) { if (!dapm->component) return -EIO; - return snd_soc_component_read(dapm->component, reg, value); + return snd_soc_component_read(dapm->component, reg); } static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm, @@ -753,7 +752,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, int i; if (e->reg != SND_SOC_NOPM) { - soc_dapm_read(dapm, e->reg, &val); + val = soc_dapm_read(dapm, e->reg); val = (val >> e->shift_l) & e->mask; item = snd_soc_enum_val_to_item(e, val); } else { @@ -790,7 +789,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i, unsigned int val; if (reg != SND_SOC_NOPM) { - soc_dapm_read(p->sink->dapm, reg, &val); + val = soc_dapm_read(p->sink->dapm, reg); /* * The nth_path argument allows this function to know * which path of a kcontrol it is setting the initial @@ -805,7 +804,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i, */ if (snd_soc_volsw_is_stereo(mc) && nth_path > 0) { if (reg != mc->rreg) - soc_dapm_read(p->sink->dapm, mc->rreg, &val); + val = soc_dapm_read(p->sink->dapm, mc->rreg); val = (val >> mc->rshift) & mask; } else { val = (val >> shift) & mask; @@ -1799,7 +1798,7 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie) /* If we're off and we're not supposed to go into STANDBY */ if (d->bias_level == SND_SOC_BIAS_OFF && d->target_bias_level != SND_SOC_BIAS_OFF) { - if (d->dev) + if (d->dev && cookie) pm_runtime_get_sync(d->dev); ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); @@ -1846,7 +1845,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie) dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n", ret); - if (d->dev) + if (d->dev && cookie) pm_runtime_put(d->dev); } @@ -2674,7 +2673,7 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; mutex_lock_nested(&rtd->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); @@ -3246,7 +3245,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) /* Read the initial power state from the device */ if (w->reg >= 0) { - soc_dapm_read(w->dapm, w->reg, &val); + val = soc_dapm_read(w->dapm, w->reg); val = val >> w->shift; val &= w->mask; if (val == w->on_val) @@ -3288,15 +3287,14 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int reg_val, val, rval = 0; - int ret = 0; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { - ret = soc_dapm_read(dapm, reg, ®_val); + reg_val = soc_dapm_read(dapm, reg); val = (reg_val >> shift) & mask; - if (ret == 0 && reg != mc->rreg) - ret = soc_dapm_read(dapm, mc->rreg, ®_val); + if (reg != mc->rreg) + reg_val = soc_dapm_read(dapm, mc->rreg); if (snd_soc_volsw_is_stereo(mc)) rval = (reg_val >> mc->rshift) & mask; @@ -3309,9 +3307,6 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, } mutex_unlock(&card->dapm_mutex); - if (ret) - return ret; - if (invert) ucontrol->value.integer.value[0] = max - val; else @@ -3324,7 +3319,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] = rval; } - return ret; + return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); @@ -3439,11 +3434,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) { - int ret = soc_dapm_read(dapm, e->reg, ®_val); - if (ret) { - mutex_unlock(&card->dapm_mutex); - return ret; - } + reg_val = soc_dapm_read(dapm, e->reg); } else { reg_val = dapm_kcontrol_get_value(kcontrol); } @@ -3804,7 +3795,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, { struct snd_soc_dapm_path *path; struct snd_soc_dai *source, *sink; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_hw_params *params = NULL; const struct snd_soc_pcm_stream *config = NULL; struct snd_pcm_runtime *runtime = NULL; @@ -4126,7 +4117,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_pcm_substream *substream, char *id) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dapm_widget template; struct snd_soc_dapm_widget *w; const char **w_param_text; diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 61844403f181..fb95c1464e66 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -46,7 +46,7 @@ static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_dmaengine_dai_dma_data *dma_data; int ret; @@ -105,7 +105,7 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct dmaengine_pcm *pcm = soc_component_to_pcm(component); struct device *dma_dev = dmaengine_dma_dev(pcm, substream); struct dma_chan *chan = pcm->chan[substream->stream]; @@ -424,6 +424,7 @@ static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) int snd_dmaengine_pcm_register(struct device *dev, const struct snd_dmaengine_pcm_config *config, unsigned int flags) { + const struct snd_soc_component_driver *driver; struct dmaengine_pcm *pcm; int ret; @@ -442,12 +443,15 @@ int snd_dmaengine_pcm_register(struct device *dev, goto err_free_dma; if (config && config->process) - ret = snd_soc_add_component(dev, &pcm->component, - &dmaengine_pcm_component_process, - NULL, 0); + driver = &dmaengine_pcm_component_process; else - ret = snd_soc_add_component(dev, &pcm->component, - &dmaengine_pcm_component, NULL, 0); + driver = &dmaengine_pcm_component; + + ret = snd_soc_component_initialize(&pcm->component, driver, dev); + if (ret) + goto err_free_dma; + + ret = snd_soc_add_component(&pcm->component, NULL, 0); if (ret) goto err_free_dma; diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c deleted file mode 100644 index 1ff9175e9d5e..000000000000 --- a/sound/soc/soc-io.c +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// soc-io.c -- ASoC register I/O helpers -// -// Copyright 2009-2011 Wolfson Microelectronics PLC. -// -// Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - -#include <linux/i2c.h> -#include <linux/spi/spi.h> -#include <linux/regmap.h> -#include <linux/export.h> -#include <sound/soc.h> - -/** - * snd_soc_component_read() - Read register value - * @component: Component to read from - * @reg: Register to read - * @val: Pointer to where the read value is stored - * - * Return: 0 on success, a negative error code otherwise. - */ -int snd_soc_component_read(struct snd_soc_component *component, - unsigned int reg, unsigned int *val) -{ - int ret; - - if (component->regmap) - ret = regmap_read(component->regmap, reg, val); - else if (component->driver->read) { - *val = component->driver->read(component, reg); - ret = 0; - } - else - ret = -EIO; - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_read); - -unsigned int snd_soc_component_read32(struct snd_soc_component *component, - unsigned int reg) -{ - unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return -1; - - return val; -} -EXPORT_SYMBOL_GPL(snd_soc_component_read32); - -/** - * snd_soc_component_write() - Write register value - * @component: Component to write to - * @reg: Register to write - * @val: Value to write to the register - * - * Return: 0 on success, a negative error code otherwise. - */ -int snd_soc_component_write(struct snd_soc_component *component, - unsigned int reg, unsigned int val) -{ - if (component->regmap) - return regmap_write(component->regmap, reg, val); - else if (component->driver->write) - return component->driver->write(component, reg, val); - else - return -EIO; -} -EXPORT_SYMBOL_GPL(snd_soc_component_write); - -static int snd_soc_component_update_bits_legacy( - struct snd_soc_component *component, unsigned int reg, - unsigned int mask, unsigned int val, bool *change) -{ - unsigned int old, new; - int ret; - - mutex_lock(&component->io_mutex); - - ret = snd_soc_component_read(component, reg, &old); - if (ret < 0) - goto out_unlock; - - new = (old & ~mask) | (val & mask); - *change = old != new; - if (*change) - ret = snd_soc_component_write(component, reg, new); -out_unlock: - mutex_unlock(&component->io_mutex); - - return ret; -} - -/** - * snd_soc_component_update_bits() - Perform read/modify/write cycle - * @component: Component to update - * @reg: Register to update - * @mask: Mask that specifies which bits to update - * @val: New value for the bits specified by mask - * - * Return: 1 if the operation was successful and the value of the register - * changed, 0 if the operation was successful, but the value did not change. - * Returns a negative error code otherwise. - */ -int snd_soc_component_update_bits(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int val) -{ - bool change; - int ret; - - if (component->regmap) - ret = regmap_update_bits_check(component->regmap, reg, mask, - val, &change); - else - ret = snd_soc_component_update_bits_legacy(component, reg, - mask, val, &change); - - if (ret < 0) - return ret; - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); - -/** - * snd_soc_component_update_bits_async() - Perform asynchronous - * read/modify/write cycle - * @component: Component to update - * @reg: Register to update - * @mask: Mask that specifies which bits to update - * @val: New value for the bits specified by mask - * - * This function is similar to snd_soc_component_update_bits(), but the update - * operation is scheduled asynchronously. This means it may not be completed - * when the function returns. To make sure that all scheduled updates have been - * completed snd_soc_component_async_complete() must be called. - * - * Return: 1 if the operation was successful and the value of the register - * changed, 0 if the operation was successful, but the value did not change. - * Returns a negative error code otherwise. - */ -int snd_soc_component_update_bits_async(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int val) -{ - bool change; - int ret; - - if (component->regmap) - ret = regmap_update_bits_check_async(component->regmap, reg, - mask, val, &change); - else - ret = snd_soc_component_update_bits_legacy(component, reg, - mask, val, &change); - - if (ret < 0) - return ret; - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); - -/** - * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed - * @component: Component for which to wait - * - * This function blocks until all asynchronous I/O which has previously been - * scheduled using snd_soc_component_update_bits_async() has completed. - */ -void snd_soc_component_async_complete(struct snd_soc_component *component) -{ - if (component->regmap) - regmap_async_complete(component->regmap); -} -EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); - -/** - * snd_soc_component_test_bits - Test register for change - * @component: component - * @reg: Register to test - * @mask: Mask that specifies which bits to test - * @value: Value to test against - * - * Tests a register with a new value and checks if the new value is - * different from the old value. - * - * Return: 1 for change, otherwise 0. - */ -int snd_soc_component_test_bits(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int value) -{ - unsigned int old, new; - int ret; - - ret = snd_soc_component_read(component, reg, &old); - if (ret < 0) - return ret; - new = (old & ~mask) | value; - return old != new; -} -EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index f849278beba0..cec70b19863e 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -40,6 +40,12 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } +void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd) +{ + if (rtd->dai_link->exit) + rtd->dai_link->exit(rtd); +} + int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -53,7 +59,7 @@ int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, int snd_soc_link_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && @@ -65,7 +71,7 @@ int snd_soc_link_startup(struct snd_pcm_substream *substream) void snd_soc_link_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) @@ -74,7 +80,7 @@ void snd_soc_link_shutdown(struct snd_pcm_substream *substream) int snd_soc_link_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && @@ -87,7 +93,7 @@ int snd_soc_link_prepare(struct snd_pcm_substream *substream) int snd_soc_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && @@ -99,7 +105,7 @@ int snd_soc_link_hw_params(struct snd_pcm_substream *substream, void snd_soc_link_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) @@ -108,7 +114,7 @@ void snd_soc_link_hw_free(struct snd_pcm_substream *substream) int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 55ffb34be95e..10f48827bb0e 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -63,11 +63,8 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, item; unsigned int reg_val; - int ret; - ret = snd_soc_component_read(component, e->reg, ®_val); - if (ret) - return ret; + reg_val = snd_soc_component_read(component, e->reg); val = (reg_val >> e->shift_l) & e->mask; item = snd_soc_enum_val_to_item(e, val); ucontrol->value.enumerated.item[0] = item; @@ -136,10 +133,7 @@ static int snd_soc_read_signed(struct snd_soc_component *component, int ret; unsigned int val; - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return ret; - + val = snd_soc_component_read(component, reg); val = (val >> shift) & mask; if (!sign_bit) { @@ -375,19 +369,12 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, int min = mc->min; unsigned int mask = (1U << (fls(min + max) - 1)) - 1; unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, reg); ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; if (snd_soc_volsw_is_stereo(mc)) { - ret = snd_soc_component_read(component, reg2, &val); - if (ret < 0) - return ret; - + val = snd_soc_component_read(component, reg2); val = ((val >> rshift) - min) & mask; ucontrol->value.integer.value[1] = val; } @@ -548,12 +535,8 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret) - return ret; + val = snd_soc_component_read(component, reg); ucontrol->value.integer.value[0] = (val >> shift) & mask; if (invert) ucontrol->value.integer.value[0] = @@ -563,10 +546,7 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] - min; if (snd_soc_volsw_is_stereo(mc)) { - ret = snd_soc_component_read(component, rreg, &val); - if (ret) - return ret; - + val = snd_soc_component_read(component, rreg); ucontrol->value.integer.value[1] = (val >> shift) & mask; if (invert) ucontrol->value.integer.value[1] = @@ -833,12 +813,9 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, long val = 0; unsigned int regval; unsigned int i; - int ret; for (i = 0; i < regcount; i++) { - ret = snd_soc_component_read(component, regbase+i, ®val); - if (ret) - return ret; + regval = snd_soc_component_read(component, regbase+i); val |= (regval & regwmask) << (regwshift*(regcount-i-1)); } val &= mask; @@ -918,12 +895,8 @@ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, unsigned int mask = 1 << shift; unsigned int invert = mc->invert != 0; unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret) - return ret; + val = snd_soc_component_read(component, reg); val &= mask; if (shift != 0 && val != 0) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index c517064f5391..00ac1cbf6f88 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -208,6 +208,7 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) * PCM runtime components * @rtd: ASoC PCM runtime that is activated * @stream: Direction of the PCM stream + * @action: Activate stream if 1. Deactivate if -1. * * Increments/Decrements the active count for all the DAIs and components * attached to a PCM runtime. @@ -303,7 +304,7 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_dai *soc_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; if (soc_dai->rate && (soc_dai->driver->symmetric_rates || @@ -360,7 +361,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; struct snd_soc_dai *cpu_dai; unsigned int rate, channels, sample_bits, symmetry, i; @@ -422,7 +423,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai_link *link = rtd->dai_link; struct snd_soc_dai *dai; unsigned int symmetry, i; @@ -442,7 +443,7 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; if (!bits) @@ -456,7 +457,7 @@ static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu; @@ -591,7 +592,7 @@ EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw); static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) { struct snd_pcm_hardware *hw = &substream->runtime->hw; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); u64 formats = hw->formats; /* @@ -607,7 +608,7 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) static int soc_pcm_components_open(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *last = NULL; struct snd_soc_component *component; int i, ret = 0; @@ -649,7 +650,7 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream) static int soc_pcm_components_close(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i, r, ret = 0; @@ -671,7 +672,7 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream) */ static int soc_pcm_close(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct snd_soc_dai *dai; int i; @@ -710,7 +711,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) */ static int soc_pcm_open(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_component *component; struct snd_soc_dai *dai; @@ -849,8 +850,7 @@ static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd) */ static int soc_pcm_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret = 0; @@ -860,14 +860,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) if (ret < 0) goto out; - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_prepare(component, substream); - if (ret < 0) { - dev_err(component->dev, - "ASoC: platform prepare error: %d\n", ret); - goto out; - } - } + ret = snd_soc_pcm_component_prepare(substream); + if (ret < 0) + goto out; ret = snd_soc_pcm_dai_prepare(substream); if (ret < 0) { @@ -904,25 +899,6 @@ static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params, interval->max = channels; } -static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_component *last) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - int i, r, ret = 0; - - for_each_rtd_components(rtd, i, component) { - if (component == last) - break; - - r = snd_soc_component_hw_free(component, substream); - if (r < 0) - ret = r; /* use last ret */ - } - - return ret; -} - /* * Called by ALSA when the hardware params are set by application. This * function can also be called multiple times and can allocate buffers @@ -931,7 +907,7 @@ static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, static int soc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; @@ -1015,23 +991,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, snd_soc_dapm_update_dai(substream, params, cpu_dai); } - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_hw_params(component, substream, params); - if (ret < 0) { - dev_err(component->dev, - "ASoC: %s hw params failed: %d\n", - component->name, ret); - goto component_err; - } - } - component = NULL; + ret = snd_soc_pcm_component_hw_params(substream, params, &component); + if (ret < 0) + goto component_err; out: mutex_unlock(&rtd->card->pcm_mutex); return ret; component_err: - soc_pcm_components_hw_free(substream, component); + snd_soc_pcm_component_hw_free(substream, component); i = rtd->num_cpus; @@ -1066,7 +1035,7 @@ codec_err: */ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i; @@ -1090,7 +1059,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) snd_soc_link_hw_free(substream); /* free any component resources */ - soc_pcm_components_hw_free(substream, NULL); + snd_soc_pcm_component_hw_free(substream, NULL); /* now free hw params for the DAIs */ for_each_rtd_dais(rtd, i, dai) { @@ -1104,65 +1073,37 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) return 0; } -static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - int i, ret; - - ret = snd_soc_link_trigger(substream, cmd); - if (ret < 0) - return ret; - - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_trigger(component, substream, cmd); - if (ret < 0) - return ret; - } - - return snd_soc_pcm_dai_trigger(substream, cmd); -} - -static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - int i, ret; - - ret = snd_soc_pcm_dai_trigger(substream, cmd); - if (ret < 0) - return ret; - - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_trigger(component, substream, cmd); - if (ret < 0) - return ret; - } - - ret = snd_soc_link_trigger(substream, cmd); - if (ret < 0) - return ret; - - return 0; -} - static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - int ret; + int ret = -EINVAL; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = soc_pcm_trigger_start(substream, cmd); + ret = snd_soc_link_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_pcm_component_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_pcm_dai_trigger(substream, cmd); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = soc_pcm_trigger_stop(substream, cmd); + ret = snd_soc_pcm_dai_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_pcm_component_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_link_trigger(substream, cmd); break; - default: - return -EINVAL; } return ret; @@ -1175,7 +1116,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) */ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; struct snd_pcm_runtime *runtime = substream->runtime; @@ -1653,7 +1594,7 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, u64 *formats) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); struct snd_soc_dpcm *dpcm; struct snd_soc_dai *dai; int stream = substream->stream; @@ -1690,7 +1631,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, unsigned int *channels_min, unsigned int *channels_max) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1745,7 +1686,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, unsigned int *rate_min, unsigned int *rate_max) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1783,7 +1724,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; int i; @@ -1834,7 +1775,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, int stream) { struct snd_soc_dpcm *dpcm; - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dai *fe_cpu_dai; int err; int i; @@ -1865,7 +1806,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, if (!be_substream) continue; - rtd = be_substream->private_data; + rtd = asoc_substream_to_rtd(be_substream); if (rtd->dai_link->be_hw_params_fixup) continue; @@ -1887,7 +1828,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_pcm_runtime *runtime = fe_substream->runtime; int stream = fe_substream->stream, ret = 0; @@ -1968,7 +1909,7 @@ int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream; dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); @@ -2034,7 +1975,7 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int err, stream = substream->stream; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2139,7 +2080,7 @@ unwind: static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int ret, stream = substream->stream; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2285,7 +2226,7 @@ EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, int cmd, bool fe_first) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int ret; /* call trigger on the frontend before the backend. */ @@ -2316,7 +2257,7 @@ static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream; int ret = 0; enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; @@ -2401,7 +2342,7 @@ out: static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream; /* if FE's runtime_update is already set, we're in race; @@ -2454,7 +2395,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream, ret = 0; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2721,7 +2662,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update); static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dpcm *dpcm; int stream = fe_substream->stream; @@ -2736,7 +2677,7 @@ static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream) static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); int ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2750,7 +2691,7 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dapm_widget_list *list; int ret; int stream = fe_substream->stream; @@ -2802,30 +2743,36 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (rtd->dai_link->dpcm_playback) { stream = SNDRV_PCM_STREAM_PLAYBACK; - for_each_rtd_cpu_dais(rtd, i, cpu_dai) - if (!snd_soc_dai_stream_valid(cpu_dai, - stream)) { - dev_err(rtd->card->dev, - "CPU DAI %s for rtd %s does not support playback\n", - cpu_dai->name, - rtd->dai_link->stream_name); - return -EINVAL; + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + if (snd_soc_dai_stream_valid(cpu_dai, stream)) { + playback = 1; + break; } - playback = 1; + } + + if (!playback) { + dev_err(rtd->card->dev, + "No CPU DAIs support playback for stream %s\n", + rtd->dai_link->stream_name); + return -EINVAL; + } } if (rtd->dai_link->dpcm_capture) { stream = SNDRV_PCM_STREAM_CAPTURE; - for_each_rtd_cpu_dais(rtd, i, cpu_dai) - if (!snd_soc_dai_stream_valid(cpu_dai, - stream)) { - dev_err(rtd->card->dev, - "CPU DAI %s for rtd %s does not support capture\n", - cpu_dai->name, - rtd->dai_link->stream_name); - return -EINVAL; + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + if (snd_soc_dai_stream_valid(cpu_dai, stream)) { + capture = 1; + break; } - capture = 1; + } + + if (!capture) { + dev_err(rtd->card->dev, + "No CPU DAIs support capture for stream %s\n", + rtd->dai_link->stream_name); + return -EINVAL; + } } } else { /* Adapt stream for codec2codec links */ @@ -2891,8 +2838,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) capture, &pcm); } if (ret < 0) { - dev_err(rtd->card->dev, "ASoC: can't create pcm for %s\n", - rtd->dai_link->name); + dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n", + new_name, rtd->dai_link->name, ret); return ret; } dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name); @@ -2957,15 +2904,16 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) ret = snd_soc_pcm_component_new(rtd); if (ret < 0) { - dev_err(rtd->dev, "ASoC: pcm constructor failed: %d\n", ret); + dev_err(rtd->dev, "ASoC: pcm %s constructor failed for dailink %s: %d\n", + new_name, rtd->dai_link->name, ret); return ret; } pcm->no_device_suspend = true; out: - dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", - (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, - (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name); + dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n", + (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, + (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name); return ret; } diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 6eaa00c21011..cee998671318 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -741,7 +741,8 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, struct snd_soc_tplg_bytes_control *be; struct soc_bytes_ext *sbe; struct snd_kcontrol_new kc; - int i, err; + int i; + int err = 0; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_bytes_control), count, @@ -786,7 +787,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, if (err) { soc_control_err(tplg, &be->hdr, be->hdr.name); kfree(sbe); - continue; + break; } /* pass control to driver for optional further init */ @@ -796,7 +797,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); kfree(sbe); - continue; + break; } /* register control here */ @@ -806,12 +807,12 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: failed to add %s\n", be->hdr.name); kfree(sbe); - continue; + break; } list_add(&sbe->dobj.list, &tplg->comp->dobj_list); } - return 0; + return err; } @@ -821,7 +822,8 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, struct snd_soc_tplg_mixer_control *mc; struct soc_mixer_control *sm; struct snd_kcontrol_new kc; - int i, err; + int i; + int err = 0; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_mixer_control), @@ -880,7 +882,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, if (err) { soc_control_err(tplg, &mc->hdr, mc->hdr.name); kfree(sm); - continue; + break; } /* create any TLV data */ @@ -889,7 +891,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); kfree(sm); - continue; + break; } /* pass control to driver for optional further init */ @@ -900,7 +902,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, mc->hdr.name); soc_tplg_free_tlv(tplg, &kc); kfree(sm); - continue; + break; } /* register control here */ @@ -911,13 +913,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, mc->hdr.name); soc_tplg_free_tlv(tplg, &kc); kfree(sm); - continue; + break; } list_add(&sm->dobj.list, &tplg->comp->dobj_list); } - return 0; + return err; } static int soc_tplg_denum_create_texts(struct soc_enum *se, @@ -997,7 +999,8 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, struct snd_soc_tplg_enum_control *ec; struct soc_enum *se; struct snd_kcontrol_new kc; - int i, ret, err; + int i; + int err = 0; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_enum_control), @@ -1052,8 +1055,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* fall through */ case SND_SOC_TPLG_CTL_ENUM: @@ -1064,24 +1066,22 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } break; default: + err = -EINVAL; dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", ec->hdr.ops.info, ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* map io handlers */ err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); if (err) { soc_control_err(tplg, &ec->hdr, ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* pass control to driver for optional further init */ @@ -1090,24 +1090,25 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* register control here */ - ret = soc_tplg_add_kcontrol(tplg, - &kc, &se->dobj.control.kcontrol); - if (ret < 0) { + err = soc_tplg_add_kcontrol(tplg, + &kc, &se->dobj.control.kcontrol); + if (err < 0) { dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } list_add(&se->dobj.list, &tplg->comp->dobj_list); } - return 0; + +err_denum: + kfree(se); + return err; } static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, @@ -1262,6 +1263,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, ret = soc_tplg_add_route(tplg, routes[i]); if (ret < 0) { + dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret); /* * this route was added to the list, it will * be freed in remove_route() so increment the @@ -1361,8 +1363,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( if (err < 0) { dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); - kfree(sm); - continue; + goto err_sm; } /* pass control to driver for optional further init */ @@ -2743,15 +2744,21 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg) /* make sure header is valid before loading */ ret = soc_valid_header(tplg, hdr); - if (ret < 0) + if (ret < 0) { + dev_err(tplg->dev, + "ASoC: topology: invalid header: %d\n", ret); return ret; - else if (ret == 0) + } else if (ret == 0) { break; + } /* load the header object */ ret = soc_tplg_load_header(tplg, hdr); - if (ret < 0) + if (ret < 0) { + dev_err(tplg->dev, + "ASoC: topology: could not load header: %d\n", ret); return ret; + } /* goto next header */ tplg->hdr_pos += le32_to_cpu(hdr->payload_size) + diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 922eac930df9..f27f94ca064b 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -66,7 +66,7 @@ static const struct snd_pcm_hardware dummy_dma_hardware = { static int dummy_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* BE's dont need dummy params */ if (!rtd->dai_link->no_pcm) @@ -86,12 +86,13 @@ static const struct snd_soc_component_driver dummy_codec = { .non_legacy_dai_naming = 1, }; -#define STUB_RATES SNDRV_PCM_RATE_8000_192000 +#define STUB_RATES SNDRV_PCM_RATE_8000_384000 #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_U8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_U16_LE | \ SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ SNDRV_PCM_FMTBIT_U24_LE | \ SNDRV_PCM_FMTBIT_S32_LE | \ SNDRV_PCM_FMTBIT_U32_LE | \ diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index a4fa8451d8cb..bc0628c7b88c 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -374,7 +374,7 @@ static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev, static struct snd_soc_dai_driver imx8_dai[] = { { - .name = "esai-port", + .name = "esai0", .playback = { .channels_min = 1, .channels_max = 8, @@ -384,6 +384,17 @@ static struct snd_soc_dai_driver imx8_dai[] = { .channels_max = 8, }, }, +{ + .name = "sai1", + .playback = { + .channels_min = 1, + .channels_max = 32, + }, + .capture = { + .channels_min = 1, + .channels_max = 32, + }, +}, }; /* i.MX8 ops */ @@ -415,7 +426,14 @@ struct snd_sof_dsp_ops sof_imx8_ops = { /* DAI drivers */ .drv = imx8_dai, - .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ + .num_drv = ARRAY_SIZE(imx8_dai), + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_imx8_ops); @@ -448,7 +466,7 @@ struct snd_sof_dsp_ops sof_imx8x_ops = { /* DAI drivers */ .drv = imx8_dai, - .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ + .num_drv = ARRAY_SIZE(imx8_dai), /* ALSA HW info flags */ .hw_info = SNDRV_PCM_INFO_MMAP | diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 287114a37688..86320941fcee 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -188,8 +188,7 @@ static int imx8m_probe(struct snd_sof_dev *sdev) } sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, - res.end - res.start + - 1); + resource_size(&res)); if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", base, size); @@ -239,7 +238,7 @@ static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev, static struct snd_soc_dai_driver imx8m_dai[] = { { - .name = "sai-port", + .name = "sai3", .playback = { .channels_min = 1, .channels_max = 32, @@ -280,7 +279,7 @@ struct snd_sof_dsp_ops sof_imx8m_ops = { /* DAI drivers */ .drv = imx8m_dai, - .num_drv = 1, /* we have only 1 SAI interface on i.MX8M */ + .num_drv = ARRAY_SIZE(imx8m_dai), .hw_info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 3934cd6bf87a..df1c6997cb4e 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -56,7 +56,7 @@ static struct hdac_ext_stream * hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *res = NULL; struct hdac_stream *stream = NULL; @@ -203,7 +203,7 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, struct hdac_stream *hstream = substream->runtime->private_data; struct hdac_bus *bus = hstream->bus; struct hdac_ext_stream *link_dev; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct sof_intel_hda_stream *hda_stream; struct hda_pipe_params p_params = {0}; @@ -264,7 +264,7 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream, snd_soc_dai_get_dma_data(dai, substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int stream = substream->stream; if (link_dev->link_prepared) @@ -291,7 +291,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, hstream = substream->runtime->private_data; bus = hstream->bus; - rtd = snd_pcm_substream_chip(substream); + rtd = asoc_substream_to_rtd(substream); link = snd_hdac_ext_bus_get_link(bus, asoc_rtd_to_codec(rtd, 0)->component->name); if (!link) @@ -357,7 +357,7 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream, hstream = substream->runtime->private_data; bus = hstream->bus; - rtd = snd_pcm_substream_chip(substream); + rtd = asoc_substream_to_rtd(substream); link_dev = snd_soc_dai_get_dma_data(dai, substream); if (!link_dev) { diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 9e5ff8c18f99..ed4d65a29d3a 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -408,11 +408,13 @@ static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev, value = SOF_HDA_VS_D0I3C_I3; /* - * Trace DMA is disabled by default when the DSP enters D0I3. - * But it can be kept enabled when the DSP enters D0I3 while the - * system is in S0 for debug. + * Trace DMA need to be disabled when the DSP enters + * D0I3 for S0Ix suspend, but it can be kept enabled + * when the DSP enters D0I3 while the system is in S0 + * for debug purpose. */ - if (hda_enable_trace_D0I3_S0 && + if (!sdev->dtrace_is_supported || + !hda_enable_trace_D0I3_S0 || sdev->system_suspend_target != SOF_SUSPEND_NONE) flags = HDA_PM_NO_DMA_TRACE; } else { @@ -696,12 +698,35 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) .state = SOF_DSP_PM_D0, .substate = SOF_HDA_DSP_PM_D0I0, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_ext_link *hlink = NULL; +#endif int ret; /* resume from D0I3 */ if (sdev->dsp_power_state.state == SOF_DSP_PM_D0) { hda_codec_i915_display_power(sdev, true); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* power up links that were active before suspend */ + list_for_each_entry(hlink, &bus->hlink_list, list) { + if (hlink->ref_count) { + ret = snd_hdac_ext_bus_link_power_up(hlink); + if (ret < 0) { + dev_dbg(sdev->dev, + "error %x in %s: failed to power up links", + ret, __func__); + return ret; + } + } + } + + /* set up CORB/RIRB buffers if was on before suspend */ + if (bus->cmd_dma_state) + snd_hdac_bus_init_cmd_io(bus); +#endif + /* Set DSP power state */ ret = snd_sof_dsp_set_power_state(sdev, &target_state); if (ret < 0) { @@ -808,6 +833,21 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* stop the CORB/RIRB DMA if it is On */ + if (bus->cmd_dma_state) + snd_hdac_bus_stop_cmd_io(bus); + + /* no link can be powered in s0ix state */ + ret = snd_hdac_ext_bus_link_power_down_all(bus); + if (ret < 0) { + dev_dbg(sdev->dev, + "error %d in %s: failed to power down links", + ret, __func__); + return ret; + } +#endif + /* enable the system waking up via IPC IRQ */ enable_irq_wake(pci->irq); pci_save_state(pci); @@ -846,7 +886,7 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) * explicitly during suspend. */ if (stream->link_substream) { - rtd = snd_pcm_substream_chip(stream->link_substream); + rtd = asoc_substream_to_rtd(stream->link_substream); name = asoc_rtd_to_codec(rtd, 0)->component->name; link = snd_hdac_ext_bus_get_link(bus, name); if (!link) diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 53a875ac52d6..b527d5958ae5 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -147,7 +147,7 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *scomp = sdev->component; struct hdac_stream *hstream = substream->runtime->private_data; struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index d03b5be31255..9e922df6a710 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -14,6 +14,7 @@ static struct snd_soc_card sof_nocodec_card = { .name = "nocodec", /* the sof- prefix is added by the core */ + .owner = THIS_MODULE }; static int sof_nocodec_bes_setup(struct device *dev, diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 22fe9d5e932b..d730e437e4ba 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -25,7 +25,7 @@ static int create_page_table(struct snd_soc_component *component, struct snd_pcm_substream *substream, unsigned char *dma_area, size_t size) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_pcm *spcm; struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream); int stream = substream->stream; @@ -71,7 +71,7 @@ void snd_sof_pcm_period_elapsed_work(struct work_struct *work) */ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_pcm *spcm; @@ -120,7 +120,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; @@ -237,7 +237,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, static int sof_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int ret, err = 0; @@ -273,7 +273,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, static int sof_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_pcm *spcm; int ret; @@ -310,7 +310,7 @@ static int sof_pcm_prepare(struct snd_soc_component *component, static int sof_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct sof_ipc_stream stream; @@ -423,7 +423,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; snd_pcm_uframes_t host, dai; @@ -456,7 +456,7 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, static int sof_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); const struct snd_sof_dsp_ops *ops = sof_ops(sdev); @@ -528,7 +528,7 @@ static int sof_pcm_open(struct snd_soc_component *component, static int sof_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int err; @@ -718,18 +718,26 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, /* do nothing for ALH dai_link */ break; case SOF_DAI_IMX_ESAI: + rate->min = dai->dai_config->esai.fsync_rate; + rate->max = dai->dai_config->esai.fsync_rate; channels->min = dai->dai_config->esai.tdm_slots; channels->max = dai->dai_config->esai.tdm_slots; dev_dbg(component->dev, + "rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", channels->min, channels->max); break; case SOF_DAI_IMX_SAI: + rate->min = dai->dai_config->sai.fsync_rate; + rate->max = dai->dai_config->sai.fsync_rate; channels->min = dai->dai_config->sai.tdm_slots; channels->max = dai->dai_config->sai.tdm_slots; dev_dbg(component->dev, + "rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", channels->min, channels->max); break; diff --git a/sound/soc/sof/probe.h b/sound/soc/sof/probe.h index b04b728c7224..5e159ab239fa 100644 --- a/sound/soc/sof/probe.h +++ b/sound/soc/sof/probe.h @@ -36,7 +36,7 @@ struct sof_probe_point_desc { struct sof_ipc_probe_dma_add_params { struct sof_ipc_cmd_hdr hdr; unsigned int num_elems; - struct sof_probe_dma dma[0]; + struct sof_probe_dma dma[]; } __packed; struct sof_ipc_probe_info_params { @@ -51,19 +51,19 @@ struct sof_ipc_probe_info_params { struct sof_ipc_probe_dma_remove_params { struct sof_ipc_cmd_hdr hdr; unsigned int num_elems; - unsigned int stream_tag[0]; + unsigned int stream_tag[]; } __packed; struct sof_ipc_probe_point_add_params { struct sof_ipc_cmd_hdr hdr; unsigned int num_elems; - struct sof_probe_point_desc desc[0]; + struct sof_probe_point_desc desc[]; } __packed; struct sof_ipc_probe_point_remove_params { struct sof_ipc_cmd_hdr hdr; unsigned int num_elems; - unsigned int buffer_id[0]; + unsigned int buffer_id[]; } __packed; int sof_ipc_probe_init(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index c5eaaa978054..8aecc46b3647 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -35,7 +35,7 @@ MODULE_PARM_DESC(sof_acpi_debug, "SOF ACPI debug options (0x0 all off)"); #define SOF_ACPI_DISABLE_PM_RUNTIME BIT(0) -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) static const struct sof_dev_desc sof_acpi_broadwell_desc = { .machines = snd_soc_acpi_intel_broadwell_machines, .resindex_lpe_base = 0, @@ -51,7 +51,7 @@ static const struct sof_dev_desc sof_acpi_broadwell_desc = { }; #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) /* BYTCR uses different IRQ index */ static const struct sof_dev_desc sof_acpi_baytrailcr_desc = { @@ -133,7 +133,7 @@ static int sof_acpi_probe(struct platform_device *pdev) if (!desc) return -ENODEV; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) if (desc == &sof_acpi_baytrail_desc && soc_intel_is_byt_cr(pdev)) desc = &sof_acpi_baytrailcr_desc; #endif @@ -191,6 +191,7 @@ static int sof_acpi_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_ACPI static const struct acpi_device_id sof_acpi_match[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) { "INT3438", (unsigned long)&sof_acpi_broadwell_desc }, @@ -202,6 +203,7 @@ static const struct acpi_device_id sof_acpi_match[] = { { } }; MODULE_DEVICE_TABLE(acpi, sof_acpi_match); +#endif /* acpi_driver definition */ static struct platform_driver snd_sof_acpi_driver = { diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 6a9703e5ff60..13e10a0c0b05 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2831,6 +2831,8 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index, } config->sai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); + config->sai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); + config->sai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); config->sai.mclk_direction = hw_config->mclk_direction; config->sai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index 58d5843811f9..38f9fff5be6b 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c @@ -188,7 +188,7 @@ static int spdif_out_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } -static int spdif_digital_mute(struct snd_soc_dai *dai, int mute) +static int spdif_mute(struct snd_soc_dai *dai, int mute, int direction) { struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); u32 val; @@ -229,7 +229,8 @@ static int spdif_mute_put(struct snd_kcontrol *kcontrol, if (host->saved_params.mute == ucontrol->value.integer.value[0]) return 0; - spdif_digital_mute(cpu_dai, ucontrol->value.integer.value[0]); + spdif_mute(cpu_dai, ucontrol->value.integer.value[0], + SNDRV_PCM_STREAM_PLAYBACK); return 1; } @@ -250,11 +251,12 @@ static int spdif_soc_dai_probe(struct snd_soc_dai *dai) } static const struct snd_soc_dai_ops spdif_out_dai_ops = { - .digital_mute = spdif_digital_mute, + .mute_stream = spdif_mute, .startup = spdif_out_startup, .shutdown = spdif_out_shutdown, .trigger = spdif_out_trigger, .hw_params = spdif_out_hw_params, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver spdif_out_dai = { diff --git a/sound/soc/sprd/sprd-pcm-dma.c b/sound/soc/sprd/sprd-pcm-dma.c index 5074123f8855..5e3a96d4793c 100644 --- a/sound/soc/sprd/sprd-pcm-dma.c +++ b/sound/soc/sprd/sprd-pcm-dma.c @@ -190,7 +190,7 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct sprd_pcm_dma_private *dma_private = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sprd_pcm_dma_params *dma_params; size_t totsize = params_buffer_bytes(params); size_t period = params_period_bytes(params); diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index 2dc2da5d458b..a16adeb7c1e9 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1348,7 +1348,7 @@ struct sti_uniperiph_data { struct sti_uniperiph_dai dai_data; }; -static const struct snd_pcm_hardware uni_tdm_hw = { +static __maybe_unused const struct snd_pcm_hardware uni_tdm_hw = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID, diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 16ff02953015..ec27c13af04f 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -168,7 +168,7 @@ static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) { struct stm32_adfsdm_priv *priv = private; - struct snd_soc_pcm_runtime *rtd = priv->substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(priv->substream); u8 *pcm_buff = priv->pcm_buff; u8 *src_buff = (u8 *)data; unsigned int old_pos = priv->pos; @@ -213,7 +213,7 @@ static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) static int stm32_adfsdm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -234,7 +234,7 @@ static int stm32_adfsdm_trigger(struct snd_soc_component *component, static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); int ret; @@ -248,7 +248,7 @@ static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, static int stm32_adfsdm_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -261,7 +261,7 @@ static snd_pcm_uframes_t stm32_adfsdm_pcm_pointer( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -272,7 +272,7 @@ static int stm32_adfsdm_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -344,12 +344,17 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); if (!component) return -ENOMEM; + + ret = snd_soc_component_initialize(component, + &stm32_adfsdm_soc_platform, + &pdev->dev); + if (ret < 0) + return ret; #ifdef CONFIG_DEBUG_FS component->debugfs_prefix = "pcm"; #endif - ret = snd_soc_add_component(&pdev->dev, component, - &stm32_adfsdm_soc_platform, NULL, 0); + ret = snd_soc_add_component(component, NULL, 0); if (ret < 0) dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", __func__); diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 41f01c3e639e..3fb9513cedb2 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1237,7 +1237,7 @@ static int stm32_sai_pcm_process_spdif(struct snd_pcm_substream *substream, void *buf, unsigned long bytes) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); int *ptr = (int *)(runtime->dma_area + hwoff + diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 34f3e0be3058..2af6404dbd62 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -286,7 +286,7 @@ static void sun4i_codec_stop_capture(struct sun4i_codec *scodec) static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); switch (cmd) { @@ -318,7 +318,7 @@ static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd, static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); @@ -360,7 +360,7 @@ static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream, static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); u32 val; @@ -573,7 +573,7 @@ static int sun4i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); unsigned long clk_freq; int ret, hwrate; @@ -614,7 +614,7 @@ static struct snd_pcm_hw_constraint_list sun4i_codec_constraints = { static int sun4i_codec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); snd_pcm_hw_constraint_list(substream->runtime, 0, @@ -634,7 +634,7 @@ static int sun4i_codec_startup(struct snd_pcm_substream *substream, static void sun4i_codec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); clk_disable_unprepare(scodec->clk_module); diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index d0a8d5810c0a..f23ff29e7c1d 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -128,13 +128,21 @@ struct sun4i_i2s; /** * struct sun4i_i2s_quirks - Differences between SoC variants. - * * @has_reset: SoC needs reset deasserted. * @reg_offset_txdata: offset of the tx fifo. * @sun4i_i2s_regmap: regmap config to use. * @field_clkdiv_mclk_en: regmap field to enable mclk output. * @field_fmt_wss: regmap field to set word select size. * @field_fmt_sr: regmap field to set sample resolution. + * @bclk_dividers: bit clock dividers array + * @num_bclk_dividers: number of bit clock dividers + * @mclk_dividers: mclk dividers array + * @num_mclk_dividers: number of mclk dividers + * @get_bclk_parent_rate: callback to get bclk parent rate + * @get_sr: callback to get sample resolution + * @get_wss: callback to get word select size + * @set_chan_cfg: callback to set channel configuration + * @set_fmt: callback to set format */ struct sun4i_i2s_quirks { bool has_reset; diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 86779a99df75..228485fe0734 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -167,7 +167,7 @@ /** * struct sun4i_spdif_quirks - Differences between SoC variants. * - * @reg_dac_tx_data: TX FIFO offset for DMA config. + * @reg_dac_txdata: TX FIFO offset for DMA config. * @has_reset: SoC needs reset deasserted. * @val_fctl_ftx: TX FIFO flush bitmask. */ @@ -243,7 +243,7 @@ static void sun4i_snd_txctrl_off(struct snd_pcm_substream *substream, static int sun4i_spdif_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index addadc827b91..3d91bd3e59cd 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -62,6 +62,62 @@ config SND_SOC_TEGRA30_I2S Tegra30 I2S interface. You will also need to select the individual machine drivers to support below. +config SND_SOC_TEGRA210_AHUB + tristate "Tegra210 AHUB module" + depends on SND_SOC_TEGRA + help + Config to enable Audio Hub (AHUB) module, which comprises of a + switch called Audio Crossbar (AXBAR) used to configure or modify + the audio routing path between various HW accelerators present in + AHUB. + Say Y or M if you want to add support for Tegra210 AHUB module. + +config SND_SOC_TEGRA210_DMIC + tristate "Tegra210 DMIC module" + depends on SND_SOC_TEGRA + help + Config to enable the Digital MIC (DMIC) controller which is used + to interface with Pulse Density Modulation (PDM) input devices. + The DMIC controller implements a converter to convert PDM signals + to Pulse Code Modulation (PCM) signals. This can be viewed as a + PDM receiver. + Say Y or M if you want to add support for Tegra210 DMIC module. + +config SND_SOC_TEGRA210_I2S + tristate "Tegra210 I2S module" + depends on SND_SOC_TEGRA + help + Config to enable the Inter-IC Sound (I2S) Controller which + implements full-duplex and bidirectional and single direction + point-to-point serial interfaces. It can interface with I2S + compatible devices. + Say Y or M if you want to add support for Tegra210 I2S module. + +config SND_SOC_TEGRA186_DSPK + tristate "Tegra186 DSPK module" + depends on SND_SOC_TEGRA + help + Config to enable the Digital Speaker Controller (DSPK) which + converts the multi-bit Pulse Code Modulation (PCM) audio input to + oversampled 1-bit Pulse Density Modulation (PDM) output. From the + signal flow perspective DSPK can be viewed as a PDM transmitter + that up-samples the input to the desired sampling rate by + interpolation and then converts the oversampled PCM input to + the desired 1-bit output via Delta Sigma Modulation (DSM). + Say Y or M if you want to add support for Tegra186 DSPK module. + +config SND_SOC_TEGRA210_ADMAIF + tristate "Tegra210 ADMAIF module" + depends on SND_SOC_TEGRA + help + Config to enable ADMAIF which is the interface between ADMA and + Audio Hub (AHUB). Each ADMA channel that sends/receives data to/ + from AHUB must interface through an ADMAIF channel. ADMA channel + sending data to AHUB pairs with an ADMAIF Tx channel, where as + ADMA channel receiving data from AHUB pairs with an ADMAIF Rx + channel. Buffer size is configurable for each ADMAIIF channel. + Say Y or M if you want to add support for Tegra210 ADMAIF module. + config SND_SOC_TEGRA_RT5640 tristate "SoC Audio support for Tegra boards using an RT5640 codec" depends on SND_SOC_TEGRA && I2C && GPIOLIB diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index c84f183919f2..60040a06b814 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -8,6 +8,11 @@ snd-soc-tegra20-i2s-objs := tegra20_i2s.o snd-soc-tegra20-spdif-objs := tegra20_spdif.o snd-soc-tegra30-ahub-objs := tegra30_ahub.o snd-soc-tegra30-i2s-objs := tegra30_i2s.o +snd-soc-tegra210-ahub-objs := tegra210_ahub.o +snd-soc-tegra210-dmic-objs := tegra210_dmic.o +snd-soc-tegra210-i2s-objs := tegra210_i2s.o +snd-soc-tegra186-dspk-objs := tegra186_dspk.o +snd-soc-tegra210-admaif-objs := tegra210_admaif.o obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o @@ -17,6 +22,11 @@ obj-$(CONFIG_SND_SOC_TEGRA20_I2S) += snd-soc-tegra20-i2s.o obj-$(CONFIG_SND_SOC_TEGRA20_SPDIF) += snd-soc-tegra20-spdif.o obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o +obj-$(CONFIG_SND_SOC_TEGRA210_DMIC) += snd-soc-tegra210-dmic.o +obj-$(CONFIG_SND_SOC_TEGRA210_AHUB) += snd-soc-tegra210-ahub.o +obj-$(CONFIG_SND_SOC_TEGRA210_I2S) += snd-soc-tegra210-i2s.o +obj-$(CONFIG_SND_SOC_TEGRA186_DSPK) += snd-soc-tegra186-dspk.o +obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o # Tegra machine Support snd-soc-tegra-rt5640-objs := tegra_rt5640.o diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c new file mode 100644 index 000000000000..fe7117171a0e --- /dev/null +++ b/sound/soc/tegra/tegra186_dspk.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra186_dspk.c - Tegra186 DSPK driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <sound/core.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include "tegra186_dspk.h" +#include "tegra_cif.h" + +static const struct reg_default tegra186_dspk_reg_defaults[] = { + { TEGRA186_DSPK_RX_INT_MASK, 0x00000007 }, + { TEGRA186_DSPK_RX_CIF_CTRL, 0x00007700 }, + { TEGRA186_DSPK_CG, 0x00000001 }, + { TEGRA186_DSPK_CORE_CTRL, 0x00000310 }, + { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, +}; + +static int tegra186_dspk_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); + + if (strstr(kcontrol->id.name, "FIFO Threshold")) + ucontrol->value.integer.value[0] = dspk->rx_fifo_th; + else if (strstr(kcontrol->id.name, "OSR Value")) + ucontrol->value.integer.value[0] = dspk->osr_val; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + ucontrol->value.integer.value[0] = dspk->lrsel; + else if (strstr(kcontrol->id.name, "Channel Select")) + ucontrol->value.integer.value[0] = dspk->ch_sel; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + ucontrol->value.integer.value[0] = dspk->mono_to_stereo; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + ucontrol->value.integer.value[0] = dspk->stereo_to_mono; + + return 0; +} + +static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); + int val = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "FIFO Threshold")) + dspk->rx_fifo_th = val; + else if (strstr(kcontrol->id.name, "OSR Value")) + dspk->osr_val = val; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + dspk->lrsel = val; + else if (strstr(kcontrol->id.name, "Channel Select")) + dspk->ch_sel = val; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + dspk->mono_to_stereo = val; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + dspk->stereo_to_mono = val; + + return 0; +} + +static int tegra186_dspk_runtime_suspend(struct device *dev) +{ + struct tegra186_dspk *dspk = dev_get_drvdata(dev); + + regcache_cache_only(dspk->regmap, true); + regcache_mark_dirty(dspk->regmap); + + clk_disable_unprepare(dspk->clk_dspk); + + return 0; +} + +static int tegra186_dspk_runtime_resume(struct device *dev) +{ + struct tegra186_dspk *dspk = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(dspk->clk_dspk); + if (err) { + dev_err(dev, "failed to enable DSPK clock, err: %d\n", err); + return err; + } + + regcache_cache_only(dspk->regmap, false); + regcache_sync(dspk->regmap); + + return 0; +} + +static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai); + unsigned int channels, srate, dspk_clk; + struct device *dev = dai->dev; + struct tegra_cif_conf cif_conf; + unsigned int max_th; + int err; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + channels = params_channels(params); + cif_conf.audio_ch = channels; + + /* Client channel */ + switch (dspk->ch_sel) { + case DSPK_CH_SELECT_LEFT: + case DSPK_CH_SELECT_RIGHT: + cif_conf.client_ch = 1; + break; + case DSPK_CH_SELECT_STEREO: + cif_conf.client_ch = 2; + break; + default: + dev_err(dev, "Invalid DSPK client channels\n"); + return -EINVAL; + } + + cif_conf.client_bits = TEGRA_ACIF_BITS_24; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + break; + case SNDRV_PCM_FORMAT_S32_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + break; + default: + dev_err(dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + srate = params_rate(params); + + /* RX FIFO threshold in terms of frames */ + max_th = (TEGRA186_DSPK_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1; + + if (dspk->rx_fifo_th > max_th) + dspk->rx_fifo_th = max_th; + + cif_conf.threshold = dspk->rx_fifo_th; + cif_conf.mono_conv = dspk->mono_to_stereo; + cif_conf.stereo_conv = dspk->stereo_to_mono; + + tegra_set_cif(dspk->regmap, TEGRA186_DSPK_RX_CIF_CTRL, + &cif_conf); + + /* + * DSPK clock and PDM codec clock should be synchronous with 4:1 ratio, + * this is because it takes 4 clock cycles to send out one sample to + * codec by sigma delta modulator. Finally the clock rate is a multiple + * of 'Over Sampling Ratio', 'Sample Rate' and 'Interface Clock Ratio'. + */ + dspk_clk = (DSPK_OSR_FACTOR << dspk->osr_val) * srate * DSPK_CLK_RATIO; + + err = clk_set_rate(dspk->clk_dspk, dspk_clk); + if (err) { + dev_err(dev, "can't set DSPK clock rate %u, err: %d\n", + dspk_clk, err); + + return err; + } + + regmap_update_bits(dspk->regmap, + /* Reg */ + TEGRA186_DSPK_CORE_CTRL, + /* Mask */ + TEGRA186_DSPK_OSR_MASK | + TEGRA186_DSPK_CHANNEL_SELECT_MASK | + TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK, + /* Value */ + (dspk->osr_val << DSPK_OSR_SHIFT) | + ((dspk->ch_sel + 1) << CH_SEL_SHIFT) | + (dspk->lrsel << LRSEL_POL_SHIFT)); + + return 0; +} + +static const struct snd_soc_dai_ops tegra186_dspk_dai_ops = { + .hw_params = tegra186_dspk_hw_params, +}; + +static struct snd_soc_dai_driver tegra186_dspk_dais[] = { + { + .name = "DSPK-CIF", + .playback = { + .stream_name = "CIF-Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + }, + { + .name = "DSPK-DAP", + .playback = { + .stream_name = "DAP-Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tegra186_dspk_dai_ops, + .symmetric_rates = 1, + }, +}; + +static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = { + SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0), + SND_SOC_DAPM_SPK("SPK", NULL), +}; + +static const struct snd_soc_dapm_route tegra186_dspk_routes[] = { + { "XBAR-Playback", NULL, "XBAR-TX" }, + { "CIF-Playback", NULL, "XBAR-Playback" }, + { "RX", NULL, "CIF-Playback" }, + { "DAP-Playback", NULL, "RX" }, + { "SPK", NULL, "DAP-Playback" }, +}; + +static const char * const tegra186_dspk_ch_sel_text[] = { + "Left", "Right", "Stereo", +}; + +static const struct soc_enum tegra186_dspk_ch_sel_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_ch_sel_text), + tegra186_dspk_ch_sel_text); + +static const char * const tegra186_dspk_osr_text[] = { + "OSR_32", "OSR_64", "OSR_128", "OSR_256", +}; + +static const struct soc_enum tegra186_dspk_osr_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_osr_text), + tegra186_dspk_osr_text); + +static const char * const tegra186_dspk_lrsel_text[] = { + "Left", "Right", +}; + +static const char * const tegra186_dspk_mono_conv_text[] = { + "Zero", "Copy", +}; + +static const struct soc_enum tegra186_dspk_mono_conv_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, + ARRAY_SIZE(tegra186_dspk_mono_conv_text), + tegra186_dspk_mono_conv_text); + +static const char * const tegra186_dspk_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const struct soc_enum tegra186_dspk_stereo_conv_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, + ARRAY_SIZE(tegra186_dspk_stereo_conv_text), + tegra186_dspk_stereo_conv_text); + +static const struct soc_enum tegra186_dspk_lrsel_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_lrsel_text), + tegra186_dspk_lrsel_text); + +static const struct snd_kcontrol_new tegrat186_dspk_controls[] = { + SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0, + TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), +}; + +static const struct snd_soc_component_driver tegra186_dspk_cmpnt = { + .dapm_widgets = tegra186_dspk_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra186_dspk_widgets), + .dapm_routes = tegra186_dspk_routes, + .num_dapm_routes = ARRAY_SIZE(tegra186_dspk_routes), + .controls = tegrat186_dspk_controls, + .num_controls = ARRAY_SIZE(tegrat186_dspk_controls), +}; + +static bool tegra186_dspk_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA186_DSPK_RX_INT_MASK ... TEGRA186_DSPK_RX_CIF_CTRL: + case TEGRA186_DSPK_ENABLE ... TEGRA186_DSPK_CG: + case TEGRA186_DSPK_CORE_CTRL ... TEGRA186_DSPK_CODEC_CTRL: + return true; + default: + return false; + }; +} + +static bool tegra186_dspk_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra186_dspk_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA186_DSPK_RX_STATUS: + case TEGRA186_DSPK_RX_INT_STATUS: + case TEGRA186_DSPK_STATUS: + case TEGRA186_DSPK_INT_STATUS: + return true; + default: + return false; + }; +} + +static bool tegra186_dspk_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA186_DSPK_RX_STATUS: + case TEGRA186_DSPK_RX_INT_STATUS: + case TEGRA186_DSPK_STATUS: + case TEGRA186_DSPK_INT_STATUS: + return true; + default: + return false; + }; +} + +static const struct regmap_config tegra186_dspk_regmap = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA186_DSPK_CODEC_CTRL, + .writeable_reg = tegra186_dspk_wr_reg, + .readable_reg = tegra186_dspk_rd_reg, + .volatile_reg = tegra186_dspk_volatile_reg, + .reg_defaults = tegra186_dspk_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra186_dspk_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static const struct of_device_id tegra186_dspk_of_match[] = { + { .compatible = "nvidia,tegra186-dspk" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra186_dspk_of_match); + +static int tegra186_dspk_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra186_dspk *dspk; + void __iomem *regs; + int err; + + dspk = devm_kzalloc(dev, sizeof(*dspk), GFP_KERNEL); + if (!dspk) + return -ENOMEM; + + dspk->osr_val = DSPK_OSR_64; + dspk->lrsel = DSPK_LRSEL_LEFT; + dspk->ch_sel = DSPK_CH_SELECT_STEREO; + dspk->mono_to_stereo = 0; /* "Zero" */ + + dev_set_drvdata(dev, dspk); + + dspk->clk_dspk = devm_clk_get(dev, "dspk"); + if (IS_ERR(dspk->clk_dspk)) { + dev_err(dev, "can't retrieve DSPK clock\n"); + return PTR_ERR(dspk->clk_dspk); + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + dspk->regmap = devm_regmap_init_mmio(dev, regs, &tegra186_dspk_regmap); + if (IS_ERR(dspk->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(dspk->regmap); + } + + regcache_cache_only(dspk->regmap, true); + + err = devm_snd_soc_register_component(dev, &tegra186_dspk_cmpnt, + tegra186_dspk_dais, + ARRAY_SIZE(tegra186_dspk_dais)); + if (err) { + dev_err(dev, "can't register DSPK component, err: %d\n", + err); + return err; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int tegra186_dspk_platform_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra186_dspk_pm_ops = { + SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend, + tegra186_dspk_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver tegra186_dspk_driver = { + .driver = { + .name = "tegra186-dspk", + .of_match_table = tegra186_dspk_of_match, + .pm = &tegra186_dspk_pm_ops, + }, + .probe = tegra186_dspk_platform_probe, + .remove = tegra186_dspk_platform_remove, +}; +module_platform_driver(tegra186_dspk_driver); + +MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>"); +MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>"); +MODULE_DESCRIPTION("Tegra186 ASoC DSPK driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra186_dspk.h b/sound/soc/tegra/tegra186_dspk.h new file mode 100644 index 000000000000..b2a879065d3c --- /dev/null +++ b/sound/soc/tegra/tegra186_dspk.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra186_dspk.h - Definitions for Tegra186 DSPK driver + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA186_DSPK_H__ +#define __TEGRA186_DSPK_H__ + +/* Register offsets from DSPK BASE */ +#define TEGRA186_DSPK_RX_STATUS 0x0c +#define TEGRA186_DSPK_RX_INT_STATUS 0x10 +#define TEGRA186_DSPK_RX_INT_MASK 0x14 +#define TEGRA186_DSPK_RX_INT_SET 0x18 +#define TEGRA186_DSPK_RX_INT_CLEAR 0x1c +#define TEGRA186_DSPK_RX_CIF_CTRL 0x20 +#define TEGRA186_DSPK_ENABLE 0x40 +#define TEGRA186_DSPK_SOFT_RESET 0x44 +#define TEGRA186_DSPK_CG 0x48 +#define TEGRA186_DSPK_STATUS 0x4c +#define TEGRA186_DSPK_INT_STATUS 0x50 +#define TEGRA186_DSPK_CORE_CTRL 0x60 +#define TEGRA186_DSPK_CODEC_CTRL 0x64 + +/* DSPK CORE CONTROL fields */ +#define CH_SEL_SHIFT 8 +#define TEGRA186_DSPK_CHANNEL_SELECT_MASK (0x3 << CH_SEL_SHIFT) +#define DSPK_OSR_SHIFT 4 +#define TEGRA186_DSPK_OSR_MASK (0x3 << DSPK_OSR_SHIFT) +#define LRSEL_POL_SHIFT 0 +#define TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK (0x1 << LRSEL_POL_SHIFT) +#define TEGRA186_DSPK_RX_FIFO_DEPTH 64 + +#define DSPK_OSR_FACTOR 32 + +/* DSPK interface clock ratio */ +#define DSPK_CLK_RATIO 4 + +enum tegra_dspk_osr { + DSPK_OSR_32, + DSPK_OSR_64, + DSPK_OSR_128, + DSPK_OSR_256, +}; + +enum tegra_dspk_ch_sel { + DSPK_CH_SELECT_LEFT, + DSPK_CH_SELECT_RIGHT, + DSPK_CH_SELECT_STEREO, +}; + +enum tegra_dspk_lrsel { + DSPK_LRSEL_LEFT, + DSPK_LRSEL_RIGHT, +}; + +struct tegra186_dspk { + unsigned int rx_fifo_th; + unsigned int osr_val; + unsigned int lrsel; + unsigned int ch_sel; + unsigned int mono_to_stereo; + unsigned int stereo_to_mono; + struct clk *clk_dspk; + struct regmap *regmap; +}; + +#endif 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/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h index 16b95b770a1d..d22abc4d08e6 100644 --- a/sound/soc/tegra/tegra20_das.h +++ b/sound/soc/tegra/tegra20_das.h @@ -91,14 +91,14 @@ struct tegra20_das { */ /* - * Connect a DAP to to a DAC + * Connect a DAP to a DAC * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_* * dac_sel: DAC to connect to: TEGRA20_DAS_DAP_SEL_DAC* */ extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel); /* - * Connect a DAP to to another DAP + * Connect a DAP to another DAP * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_* * other_dap_sel: DAP to connect to: TEGRA20_DAS_DAP_SEL_DAP* * master: Is this DAP the master (1) or slave (0) diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c new file mode 100644 index 000000000000..4894e8e6ee7f --- /dev/null +++ b/sound/soc/tegra/tegra210_admaif.c @@ -0,0 +1,800 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_admaif.c - Tegra ADMAIF driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include "tegra210_admaif.h" +#include "tegra_cif.h" +#include "tegra_pcm.h" + +#define CH_REG(offset, reg, id) \ + ((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id))) + +#define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id) + +#define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id) + +#define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base) \ + { CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 }, \ + { CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), 0x00007700 }, \ + { CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl }, \ + { CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 }, \ + { CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), 0x00007700 }, \ + { CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl } + +#define ADMAIF_REG_DEFAULTS(id, chip) \ + REG_DEFAULTS((id) - 1, \ + chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT, \ + chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT, \ + chip ## _ADMAIF_TX_BASE, \ + chip ## _ADMAIF_RX_BASE) + +static const struct reg_default tegra186_admaif_reg_defaults[] = { + {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003}, + ADMAIF_REG_DEFAULTS(1, TEGRA186), + ADMAIF_REG_DEFAULTS(2, TEGRA186), + ADMAIF_REG_DEFAULTS(3, TEGRA186), + ADMAIF_REG_DEFAULTS(4, TEGRA186), + ADMAIF_REG_DEFAULTS(5, TEGRA186), + ADMAIF_REG_DEFAULTS(6, TEGRA186), + ADMAIF_REG_DEFAULTS(7, TEGRA186), + ADMAIF_REG_DEFAULTS(8, TEGRA186), + ADMAIF_REG_DEFAULTS(9, TEGRA186), + ADMAIF_REG_DEFAULTS(10, TEGRA186), + ADMAIF_REG_DEFAULTS(11, TEGRA186), + ADMAIF_REG_DEFAULTS(12, TEGRA186), + ADMAIF_REG_DEFAULTS(13, TEGRA186), + ADMAIF_REG_DEFAULTS(14, TEGRA186), + ADMAIF_REG_DEFAULTS(15, TEGRA186), + ADMAIF_REG_DEFAULTS(16, TEGRA186), + ADMAIF_REG_DEFAULTS(17, TEGRA186), + ADMAIF_REG_DEFAULTS(18, TEGRA186), + ADMAIF_REG_DEFAULTS(19, TEGRA186), + ADMAIF_REG_DEFAULTS(20, TEGRA186) +}; + +static const struct reg_default tegra210_admaif_reg_defaults[] = { + {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003}, + ADMAIF_REG_DEFAULTS(1, TEGRA210), + ADMAIF_REG_DEFAULTS(2, TEGRA210), + ADMAIF_REG_DEFAULTS(3, TEGRA210), + ADMAIF_REG_DEFAULTS(4, TEGRA210), + ADMAIF_REG_DEFAULTS(5, TEGRA210), + ADMAIF_REG_DEFAULTS(6, TEGRA210), + ADMAIF_REG_DEFAULTS(7, TEGRA210), + ADMAIF_REG_DEFAULTS(8, TEGRA210), + ADMAIF_REG_DEFAULTS(9, TEGRA210), + ADMAIF_REG_DEFAULTS(10, TEGRA210) +}; + +static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE; + unsigned int num_ch = admaif->soc_data->num_ch; + unsigned int rx_base = admaif->soc_data->rx_base; + unsigned int tx_base = admaif->soc_data->tx_base; + unsigned int global_base = admaif->soc_data->global_base; + unsigned int reg_max = admaif->soc_data->regmap_conf->max_register; + unsigned int rx_max = rx_base + (num_ch * ch_stride); + unsigned int tx_max = tx_base + (num_ch * ch_stride); + + if ((reg >= rx_base) && (reg < rx_max)) { + reg = (reg - rx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_RX_ENABLE) || + (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_RX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL)) + return true; + } else if ((reg >= tx_base) && (reg < tx_max)) { + reg = (reg - tx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_TX_ENABLE) || + (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_TX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL)) + return true; + } else if ((reg >= global_base) && (reg < reg_max)) { + if (reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) + return true; + } + + return false; +} + +static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE; + unsigned int num_ch = admaif->soc_data->num_ch; + unsigned int rx_base = admaif->soc_data->rx_base; + unsigned int tx_base = admaif->soc_data->tx_base; + unsigned int global_base = admaif->soc_data->global_base; + unsigned int reg_max = admaif->soc_data->regmap_conf->max_register; + unsigned int rx_max = rx_base + (num_ch * ch_stride); + unsigned int tx_max = tx_base + (num_ch * ch_stride); + + if ((reg >= rx_base) && (reg < rx_max)) { + reg = (reg - rx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_RX_ENABLE) || + (reg == TEGRA_ADMAIF_RX_STATUS) || + (reg == TEGRA_ADMAIF_RX_INT_STATUS) || + (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_RX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL)) + return true; + } else if ((reg >= tx_base) && (reg < tx_max)) { + reg = (reg - tx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_TX_ENABLE) || + (reg == TEGRA_ADMAIF_TX_STATUS) || + (reg == TEGRA_ADMAIF_TX_INT_STATUS) || + (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_TX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL)) + return true; + } else if ((reg >= global_base) && (reg < reg_max)) { + if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) || + (reg == (global_base + TEGRA_ADMAIF_GLOBAL_CG_0)) || + (reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS))) + return true; + } + + return false; +} + +static bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE; + unsigned int num_ch = admaif->soc_data->num_ch; + unsigned int rx_base = admaif->soc_data->rx_base; + unsigned int tx_base = admaif->soc_data->tx_base; + unsigned int global_base = admaif->soc_data->global_base; + unsigned int reg_max = admaif->soc_data->regmap_conf->max_register; + unsigned int rx_max = rx_base + (num_ch * ch_stride); + unsigned int tx_max = tx_base + (num_ch * ch_stride); + + if ((reg >= rx_base) && (reg < rx_max)) { + reg = (reg - rx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_RX_ENABLE) || + (reg == TEGRA_ADMAIF_RX_STATUS) || + (reg == TEGRA_ADMAIF_RX_INT_STATUS) || + (reg == TEGRA_ADMAIF_RX_SOFT_RESET)) + return true; + } else if ((reg >= tx_base) && (reg < tx_max)) { + reg = (reg - tx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_TX_ENABLE) || + (reg == TEGRA_ADMAIF_TX_STATUS) || + (reg == TEGRA_ADMAIF_TX_INT_STATUS) || + (reg == TEGRA_ADMAIF_TX_SOFT_RESET)) + return true; + } else if ((reg >= global_base) && (reg < reg_max)) { + if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS))) + return true; + } + + return false; +} + +static const struct regmap_config tegra210_admaif_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_ADMAIF_LAST_REG, + .writeable_reg = tegra_admaif_wr_reg, + .readable_reg = tegra_admaif_rd_reg, + .volatile_reg = tegra_admaif_volatile_reg, + .reg_defaults = tegra210_admaif_reg_defaults, + .num_reg_defaults = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config tegra186_admaif_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA186_ADMAIF_LAST_REG, + .writeable_reg = tegra_admaif_wr_reg, + .readable_reg = tegra_admaif_rd_reg, + .volatile_reg = tegra_admaif_volatile_reg, + .reg_defaults = tegra186_admaif_reg_defaults, + .num_reg_defaults = TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1, + .cache_type = REGCACHE_FLAT, +}; + +static int tegra_admaif_runtime_suspend(struct device *dev) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + + regcache_cache_only(admaif->regmap, true); + regcache_mark_dirty(admaif->regmap); + + return 0; +} + +static int tegra_admaif_runtime_resume(struct device *dev) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + + regcache_cache_only(admaif->regmap, false); + regcache_sync(admaif->regmap); + + return 0; +} + +static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg, + int valid_bit) +{ + switch (valid_bit) { + case DATA_8BIT: + regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN); + regmap_update_bits(map, reg, PACK16_EN_MASK, 0); + break; + case DATA_16BIT: + regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN); + regmap_update_bits(map, reg, PACK8_EN_MASK, 0); + break; + case DATA_32BIT: + regmap_update_bits(map, reg, PACK16_EN_MASK, 0); + regmap_update_bits(map, reg, PACK8_EN_MASK, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tegra_admaif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->dev; + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + struct tegra_cif_conf cif_conf; + unsigned int reg, path; + int valid_bit, channels; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + cif_conf.audio_bits = TEGRA_ACIF_BITS_8; + cif_conf.client_bits = TEGRA_ACIF_BITS_8; + valid_bit = DATA_8BIT; + break; + case SNDRV_PCM_FORMAT_S16_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + cif_conf.client_bits = TEGRA_ACIF_BITS_16; + valid_bit = DATA_16BIT; + break; + case SNDRV_PCM_FORMAT_S32_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + cif_conf.client_bits = TEGRA_ACIF_BITS_32; + valid_bit = DATA_32BIT; + break; + default: + dev_err(dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + channels = params_channels(params); + cif_conf.client_ch = channels; + cif_conf.audio_ch = channels; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + path = ADMAIF_TX_PATH; + reg = CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL, dai->id); + } else { + path = ADMAIF_RX_PATH; + reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id); + } + + cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id]; + cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id]; + + tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit); + + tegra_set_cif(admaif->regmap, reg, &cif_conf); + + return 0; +} + +static int tegra_admaif_start(struct snd_soc_dai *dai, int direction) +{ + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + unsigned int reg, mask, val; + + switch (direction) { + case SNDRV_PCM_STREAM_PLAYBACK: + mask = TX_ENABLE_MASK; + val = TX_ENABLE; + reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id); + break; + case SNDRV_PCM_STREAM_CAPTURE: + mask = RX_ENABLE_MASK; + val = RX_ENABLE; + reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id); + break; + default: + return -EINVAL; + } + + regmap_update_bits(admaif->regmap, reg, mask, val); + + return 0; +} + +static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction) +{ + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + unsigned int enable_reg, status_reg, reset_reg, mask, val; + char *dir_name; + int err, enable; + + switch (direction) { + case SNDRV_PCM_STREAM_PLAYBACK: + mask = TX_ENABLE_MASK; + enable = TX_ENABLE; + dir_name = "TX"; + enable_reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id); + status_reg = CH_TX_REG(TEGRA_ADMAIF_TX_STATUS, dai->id); + reset_reg = CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET, dai->id); + break; + case SNDRV_PCM_STREAM_CAPTURE: + mask = RX_ENABLE_MASK; + enable = RX_ENABLE; + dir_name = "RX"; + enable_reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id); + status_reg = CH_RX_REG(TEGRA_ADMAIF_RX_STATUS, dai->id); + reset_reg = CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET, dai->id); + break; + default: + return -EINVAL; + } + + /* Disable TX/RX channel */ + regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable); + + /* Wait until ADMAIF TX/RX status is disabled */ + err = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val, + !(val & enable), 10, 10000); + if (err < 0) + dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n", + dai->id + 1, dir_name); + + /* SW reset */ + regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET); + + /* Wait till SW reset is complete */ + err = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val, + !(val & SW_RESET_MASK & SW_RESET), + 10, 10000); + if (err) { + dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n", + dai->id + 1, dir_name); + return err; + } + + return 0; +} + +static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + int err; + + err = snd_dmaengine_pcm_trigger(substream, cmd); + if (err) + return err; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + return tegra_admaif_start(dai, substream->stream); + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + return tegra_admaif_stop(dai, substream->stream); + default: + return -EINVAL; + } +} + +static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { + .hw_params = tegra_admaif_hw_params, + .trigger = tegra_admaif_trigger, +}; + +static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); + long *uctl_val = &ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) + *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) + *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) + *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) + *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; + + return 0; +} + +static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); + int value = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) + admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) + admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) + admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) + admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; + + return 0; +} + +static int tegra_admaif_dai_probe(struct snd_soc_dai *dai) +{ + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + + dai->capture_dma_data = &admaif->capture_dma_data[dai->id]; + dai->playback_dma_data = &admaif->playback_dma_data[dai->id]; + + return 0; +} + +#define DAI(dai_name) \ + { \ + .name = dai_name, \ + .probe = tegra_admaif_dai_probe, \ + .playback = { \ + .stream_name = dai_name " Playback", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + .capture = { \ + .stream_name = dai_name " Capture", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + .ops = &tegra_admaif_dai_ops, \ + } + +static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = { + DAI("ADMAIF1"), + DAI("ADMAIF2"), + DAI("ADMAIF3"), + DAI("ADMAIF4"), + DAI("ADMAIF5"), + DAI("ADMAIF6"), + DAI("ADMAIF7"), + DAI("ADMAIF8"), + DAI("ADMAIF9"), + DAI("ADMAIF10"), +}; + +static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = { + DAI("ADMAIF1"), + DAI("ADMAIF2"), + DAI("ADMAIF3"), + DAI("ADMAIF4"), + DAI("ADMAIF5"), + DAI("ADMAIF6"), + DAI("ADMAIF7"), + DAI("ADMAIF8"), + DAI("ADMAIF9"), + DAI("ADMAIF10"), + DAI("ADMAIF11"), + DAI("ADMAIF12"), + DAI("ADMAIF13"), + DAI("ADMAIF14"), + DAI("ADMAIF15"), + DAI("ADMAIF16"), + DAI("ADMAIF17"), + DAI("ADMAIF18"), + DAI("ADMAIF19"), + DAI("ADMAIF20"), +}; + +static const char * const tegra_admaif_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const char * const tegra_admaif_mono_conv_text[] = { + "Zero", "Copy", +}; + +/* + * Below macro is added to avoid looping over all ADMAIFx controls related + * to mono/stereo conversions in get()/put() callbacks. + */ +#define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .info = snd_soc_info_enum_double, \ + .name = xname, \ + .get = xhandler_get, \ + .put = xhandler_put, \ + .private_value = (unsigned long)&(struct soc_enum) \ + SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text) \ +} + +#define TEGRA_ADMAIF_CIF_CTRL(reg) \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_mono_conv_text), \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_stereo_conv_text), \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_mono_conv_text), \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_stereo_conv_text) + +static struct snd_kcontrol_new tegra210_admaif_controls[] = { + TEGRA_ADMAIF_CIF_CTRL(1), + TEGRA_ADMAIF_CIF_CTRL(2), + TEGRA_ADMAIF_CIF_CTRL(3), + TEGRA_ADMAIF_CIF_CTRL(4), + TEGRA_ADMAIF_CIF_CTRL(5), + TEGRA_ADMAIF_CIF_CTRL(6), + TEGRA_ADMAIF_CIF_CTRL(7), + TEGRA_ADMAIF_CIF_CTRL(8), + TEGRA_ADMAIF_CIF_CTRL(9), + TEGRA_ADMAIF_CIF_CTRL(10), +}; + +static struct snd_kcontrol_new tegra186_admaif_controls[] = { + TEGRA_ADMAIF_CIF_CTRL(1), + TEGRA_ADMAIF_CIF_CTRL(2), + TEGRA_ADMAIF_CIF_CTRL(3), + TEGRA_ADMAIF_CIF_CTRL(4), + TEGRA_ADMAIF_CIF_CTRL(5), + TEGRA_ADMAIF_CIF_CTRL(6), + TEGRA_ADMAIF_CIF_CTRL(7), + TEGRA_ADMAIF_CIF_CTRL(8), + TEGRA_ADMAIF_CIF_CTRL(9), + TEGRA_ADMAIF_CIF_CTRL(10), + TEGRA_ADMAIF_CIF_CTRL(11), + TEGRA_ADMAIF_CIF_CTRL(12), + TEGRA_ADMAIF_CIF_CTRL(13), + TEGRA_ADMAIF_CIF_CTRL(14), + TEGRA_ADMAIF_CIF_CTRL(15), + TEGRA_ADMAIF_CIF_CTRL(16), + TEGRA_ADMAIF_CIF_CTRL(17), + TEGRA_ADMAIF_CIF_CTRL(18), + TEGRA_ADMAIF_CIF_CTRL(19), + TEGRA_ADMAIF_CIF_CTRL(20), +}; + +static const struct snd_soc_component_driver tegra210_admaif_cmpnt = { + .controls = tegra210_admaif_controls, + .num_controls = ARRAY_SIZE(tegra210_admaif_controls), + .pcm_construct = tegra_pcm_construct, + .pcm_destruct = tegra_pcm_destruct, + .open = tegra_pcm_open, + .close = tegra_pcm_close, + .hw_params = tegra_pcm_hw_params, + .hw_free = tegra_pcm_hw_free, + .mmap = tegra_pcm_mmap, + .pointer = tegra_pcm_pointer, +}; + +static const struct snd_soc_component_driver tegra186_admaif_cmpnt = { + .controls = tegra186_admaif_controls, + .num_controls = ARRAY_SIZE(tegra186_admaif_controls), + .pcm_construct = tegra_pcm_construct, + .pcm_destruct = tegra_pcm_destruct, + .open = tegra_pcm_open, + .close = tegra_pcm_close, + .hw_params = tegra_pcm_hw_params, + .hw_free = tegra_pcm_hw_free, + .mmap = tegra_pcm_mmap, + .pointer = tegra_pcm_pointer, +}; + +static const struct tegra_admaif_soc_data soc_data_tegra210 = { + .num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT, + .cmpnt = &tegra210_admaif_cmpnt, + .dais = tegra210_admaif_cmpnt_dais, + .regmap_conf = &tegra210_admaif_regmap_config, + .global_base = TEGRA210_ADMAIF_GLOBAL_BASE, + .tx_base = TEGRA210_ADMAIF_TX_BASE, + .rx_base = TEGRA210_ADMAIF_RX_BASE, +}; + +static const struct tegra_admaif_soc_data soc_data_tegra186 = { + .num_ch = TEGRA186_ADMAIF_CHANNEL_COUNT, + .cmpnt = &tegra186_admaif_cmpnt, + .dais = tegra186_admaif_cmpnt_dais, + .regmap_conf = &tegra186_admaif_regmap_config, + .global_base = TEGRA186_ADMAIF_GLOBAL_BASE, + .tx_base = TEGRA186_ADMAIF_TX_BASE, + .rx_base = TEGRA186_ADMAIF_RX_BASE, +}; + +static const struct of_device_id tegra_admaif_of_match[] = { + { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 }, + { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra_admaif_of_match); + +static int tegra_admaif_probe(struct platform_device *pdev) +{ + struct tegra_admaif *admaif; + void __iomem *regs; + struct resource *res; + int err, i; + + admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL); + if (!admaif) + return -ENOMEM; + + admaif->soc_data = of_device_get_match_data(&pdev->dev); + + dev_set_drvdata(&pdev->dev, admaif); + + admaif->capture_dma_data = + devm_kcalloc(&pdev->dev, + admaif->soc_data->num_ch, + sizeof(struct snd_dmaengine_dai_dma_data), + GFP_KERNEL); + if (!admaif->capture_dma_data) + return -ENOMEM; + + admaif->playback_dma_data = + devm_kcalloc(&pdev->dev, + admaif->soc_data->num_ch, + sizeof(struct snd_dmaengine_dai_dma_data), + GFP_KERNEL); + if (!admaif->playback_dma_data) + return -ENOMEM; + + for (i = 0; i < ADMAIF_PATHS; i++) { + admaif->mono_to_stereo[i] = + devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch, + sizeof(unsigned int), GFP_KERNEL); + if (!admaif->mono_to_stereo[i]) + return -ENOMEM; + + admaif->stereo_to_mono[i] = + devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch, + sizeof(unsigned int), GFP_KERNEL); + if (!admaif->stereo_to_mono[i]) + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs, + admaif->soc_data->regmap_conf); + if (IS_ERR(admaif->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + return PTR_ERR(admaif->regmap); + } + + regcache_cache_only(admaif->regmap, true); + + regmap_update_bits(admaif->regmap, admaif->soc_data->global_base + + TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1); + + for (i = 0; i < admaif->soc_data->num_ch; i++) { + admaif->playback_dma_data[i].addr = res->start + + CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i); + + admaif->capture_dma_data[i].addr = res->start + + CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i); + + admaif->playback_dma_data[i].addr_width = 32; + + if (of_property_read_string_index(pdev->dev.of_node, + "dma-names", (i * 2) + 1, + &admaif->playback_dma_data[i].chan_name) < 0) { + dev_err(&pdev->dev, + "missing property nvidia,dma-names\n"); + + return -ENODEV; + } + + admaif->capture_dma_data[i].addr_width = 32; + + if (of_property_read_string_index(pdev->dev.of_node, + "dma-names", + (i * 2), + &admaif->capture_dma_data[i].chan_name) < 0) { + dev_err(&pdev->dev, + "missing property nvidia,dma-names\n"); + + return -ENODEV; + } + } + + err = devm_snd_soc_register_component(&pdev->dev, + admaif->soc_data->cmpnt, + admaif->soc_data->dais, + admaif->soc_data->num_ch); + if (err) { + dev_err(&pdev->dev, + "can't register ADMAIF component, err: %d\n", err); + return err; + } + + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int tegra_admaif_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra_admaif_pm_ops = { + SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend, + tegra_admaif_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver tegra_admaif_driver = { + .probe = tegra_admaif_probe, + .remove = tegra_admaif_remove, + .driver = { + .name = "tegra210-admaif", + .of_match_table = tegra_admaif_of_match, + .pm = &tegra_admaif_pm_ops, + }, +}; +module_platform_driver(tegra_admaif_driver); + +MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>"); +MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_admaif.h b/sound/soc/tegra/tegra210_admaif.h new file mode 100644 index 000000000000..96686dc92081 --- /dev/null +++ b/sound/soc/tegra/tegra210_admaif.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_admaif.h - Tegra ADMAIF registers + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA_ADMAIF_H__ +#define __TEGRA_ADMAIF_H__ + +#define TEGRA_ADMAIF_CHANNEL_REG_STRIDE 0x40 +/* Tegra210 specific */ +#define TEGRA210_ADMAIF_LAST_REG 0x75f +#define TEGRA210_ADMAIF_CHANNEL_COUNT 10 +#define TEGRA210_ADMAIF_RX_BASE 0x0 +#define TEGRA210_ADMAIF_TX_BASE 0x300 +#define TEGRA210_ADMAIF_GLOBAL_BASE 0x700 +/* Tegra186 specific */ +#define TEGRA186_ADMAIF_LAST_REG 0xd5f +#define TEGRA186_ADMAIF_CHANNEL_COUNT 20 +#define TEGRA186_ADMAIF_RX_BASE 0x0 +#define TEGRA186_ADMAIF_TX_BASE 0x500 +#define TEGRA186_ADMAIF_GLOBAL_BASE 0xd00 +/* Global registers */ +#define TEGRA_ADMAIF_GLOBAL_ENABLE 0x0 +#define TEGRA_ADMAIF_GLOBAL_CG_0 0x8 +#define TEGRA_ADMAIF_GLOBAL_STATUS 0x10 +#define TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS 0x20 +#define TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS 0x24 +/* RX channel registers */ +#define TEGRA_ADMAIF_RX_ENABLE 0x0 +#define TEGRA_ADMAIF_RX_SOFT_RESET 0x4 +#define TEGRA_ADMAIF_RX_STATUS 0xc +#define TEGRA_ADMAIF_RX_INT_STATUS 0x10 +#define TEGRA_ADMAIF_RX_INT_MASK 0x14 +#define TEGRA_ADMAIF_RX_INT_SET 0x18 +#define TEGRA_ADMAIF_RX_INT_CLEAR 0x1c +#define TEGRA_ADMAIF_CH_ACIF_RX_CTRL 0x20 +#define TEGRA_ADMAIF_RX_FIFO_CTRL 0x28 +#define TEGRA_ADMAIF_RX_FIFO_READ 0x2c +/* TX channel registers */ +#define TEGRA_ADMAIF_TX_ENABLE 0x0 +#define TEGRA_ADMAIF_TX_SOFT_RESET 0x4 +#define TEGRA_ADMAIF_TX_STATUS 0xc +#define TEGRA_ADMAIF_TX_INT_STATUS 0x10 +#define TEGRA_ADMAIF_TX_INT_MASK 0x14 +#define TEGRA_ADMAIF_TX_INT_SET 0x18 +#define TEGRA_ADMAIF_TX_INT_CLEAR 0x1c +#define TEGRA_ADMAIF_CH_ACIF_TX_CTRL 0x20 +#define TEGRA_ADMAIF_TX_FIFO_CTRL 0x28 +#define TEGRA_ADMAIF_TX_FIFO_WRITE 0x2c +/* Bit fields */ +#define PACK8_EN_SHIFT 31 +#define PACK8_EN_MASK BIT(PACK8_EN_SHIFT) +#define PACK8_EN BIT(PACK8_EN_SHIFT) +#define PACK16_EN_SHIFT 30 +#define PACK16_EN_MASK BIT(PACK16_EN_SHIFT) +#define PACK16_EN BIT(PACK16_EN_SHIFT) +#define TX_ENABLE_SHIFT 0 +#define TX_ENABLE_MASK BIT(TX_ENABLE_SHIFT) +#define TX_ENABLE BIT(TX_ENABLE_SHIFT) +#define RX_ENABLE_SHIFT 0 +#define RX_ENABLE_MASK BIT(RX_ENABLE_SHIFT) +#define RX_ENABLE BIT(RX_ENABLE_SHIFT) +#define SW_RESET_MASK 1 +#define SW_RESET 1 +/* Default values - Tegra210 */ +#define TEGRA210_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300 +#define TEGRA210_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304 +#define TEGRA210_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000208 +#define TEGRA210_ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT 0x0000020b +#define TEGRA210_ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT 0x0000020e +#define TEGRA210_ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT 0x00000211 +#define TEGRA210_ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT 0x00000214 +#define TEGRA210_ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT 0x00000217 +#define TEGRA210_ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT 0x0000021a +#define TEGRA210_ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT 0x0000021d +#define TEGRA210_ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT 0x02000300 +#define TEGRA210_ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT 0x02000304 +#define TEGRA210_ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT 0x01800208 +#define TEGRA210_ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT 0x0180020b +#define TEGRA210_ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT 0x0180020e +#define TEGRA210_ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT 0x01800211 +#define TEGRA210_ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT 0x01800214 +#define TEGRA210_ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT 0x01800217 +#define TEGRA210_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x0180021a +#define TEGRA210_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021d +/* Default values - Tegra186 */ +#define TEGRA186_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300 +#define TEGRA186_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304 +#define TEGRA186_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000308 +#define TEGRA186_ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT 0x0000030c +#define TEGRA186_ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT 0x00000210 +#define TEGRA186_ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT 0x00000213 +#define TEGRA186_ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT 0x00000216 +#define TEGRA186_ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT 0x00000219 +#define TEGRA186_ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT 0x0000021c +#define TEGRA186_ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT 0x0000021f +#define TEGRA186_ADMAIF_RX11_FIFO_CTRL_REG_DEFAULT 0x00000222 +#define TEGRA186_ADMAIF_RX12_FIFO_CTRL_REG_DEFAULT 0x00000225 +#define TEGRA186_ADMAIF_RX13_FIFO_CTRL_REG_DEFAULT 0x00000228 +#define TEGRA186_ADMAIF_RX14_FIFO_CTRL_REG_DEFAULT 0x0000022b +#define TEGRA186_ADMAIF_RX15_FIFO_CTRL_REG_DEFAULT 0x0000022e +#define TEGRA186_ADMAIF_RX16_FIFO_CTRL_REG_DEFAULT 0x00000231 +#define TEGRA186_ADMAIF_RX17_FIFO_CTRL_REG_DEFAULT 0x00000234 +#define TEGRA186_ADMAIF_RX18_FIFO_CTRL_REG_DEFAULT 0x00000237 +#define TEGRA186_ADMAIF_RX19_FIFO_CTRL_REG_DEFAULT 0x0000023a +#define TEGRA186_ADMAIF_RX20_FIFO_CTRL_REG_DEFAULT 0x0000023d +#define TEGRA186_ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT 0x02000300 +#define TEGRA186_ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT 0x02000304 +#define TEGRA186_ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT 0x02000308 +#define TEGRA186_ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT 0x0200030c +#define TEGRA186_ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT 0x01800210 +#define TEGRA186_ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT 0x01800213 +#define TEGRA186_ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT 0x01800216 +#define TEGRA186_ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT 0x01800219 +#define TEGRA186_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x0180021c +#define TEGRA186_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021f +#define TEGRA186_ADMAIF_TX11_FIFO_CTRL_REG_DEFAULT 0x01800222 +#define TEGRA186_ADMAIF_TX12_FIFO_CTRL_REG_DEFAULT 0x01800225 +#define TEGRA186_ADMAIF_TX13_FIFO_CTRL_REG_DEFAULT 0x01800228 +#define TEGRA186_ADMAIF_TX14_FIFO_CTRL_REG_DEFAULT 0x0180022b +#define TEGRA186_ADMAIF_TX15_FIFO_CTRL_REG_DEFAULT 0x0180022e +#define TEGRA186_ADMAIF_TX16_FIFO_CTRL_REG_DEFAULT 0x01800231 +#define TEGRA186_ADMAIF_TX17_FIFO_CTRL_REG_DEFAULT 0x01800234 +#define TEGRA186_ADMAIF_TX18_FIFO_CTRL_REG_DEFAULT 0x01800237 +#define TEGRA186_ADMAIF_TX19_FIFO_CTRL_REG_DEFAULT 0x0180023a +#define TEGRA186_ADMAIF_TX20_FIFO_CTRL_REG_DEFAULT 0x0180023d + +enum { + DATA_8BIT, + DATA_16BIT, + DATA_32BIT +}; + +enum { + ADMAIF_RX_PATH, + ADMAIF_TX_PATH, + ADMAIF_PATHS, +}; + +struct tegra_admaif_soc_data { + const struct snd_soc_component_driver *cmpnt; + const struct regmap_config *regmap_conf; + struct snd_soc_dai_driver *dais; + unsigned int global_base; + unsigned int tx_base; + unsigned int rx_base; + unsigned int num_ch; +}; + +struct tegra_admaif { + struct snd_dmaengine_dai_dma_data *capture_dma_data; + struct snd_dmaengine_dai_dma_data *playback_dma_data; + const struct tegra_admaif_soc_data *soc_data; + unsigned int *mono_to_stereo[ADMAIF_PATHS]; + unsigned int *stereo_to_mono[ADMAIF_PATHS]; + struct regmap *regmap; +}; + +#endif diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c new file mode 100644 index 000000000000..5123a96fdde8 --- /dev/null +++ b/sound/soc/tegra/tegra210_ahub.c @@ -0,0 +1,676 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_ahub.c - Tegra210 AHUB driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <sound/soc.h> +#include "tegra210_ahub.h" + +static int tegra_ahub_get_value_enum(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_kcontrol_component(kctl); + struct tegra_ahub *ahub = snd_soc_component_get_drvdata(cmpnt); + struct soc_enum *e = (struct soc_enum *)kctl->private_value; + unsigned int reg, i, bit_pos = 0; + + /* + * Find the bit position of current MUX input. + * If nothing is set, position would be 0 and it corresponds to 'None'. + */ + for (i = 0; i < ahub->soc_data->reg_count; i++) { + unsigned int reg_val; + + reg = e->reg + (TEGRA210_XBAR_PART1_RX * i); + reg_val = snd_soc_component_read(cmpnt, reg); + reg_val &= ahub->soc_data->mask[i]; + + if (reg_val) { + bit_pos = ffs(reg_val) + + (8 * cmpnt->val_bytes * i); + break; + } + } + + /* Find index related to the item in array *_ahub_mux_texts[] */ + for (i = 0; i < e->items; i++) { + if (bit_pos == e->values[i]) { + uctl->value.enumerated.item[0] = i; + break; + } + } + + return 0; +} + +static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_kcontrol_component(kctl); + struct tegra_ahub *ahub = snd_soc_component_get_drvdata(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctl); + struct soc_enum *e = (struct soc_enum *)kctl->private_value; + struct snd_soc_dapm_update update[TEGRA_XBAR_UPDATE_MAX_REG] = { }; + unsigned int *item = uctl->value.enumerated.item; + unsigned int value = e->values[item[0]]; + unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; + + if (item[0] >= e->items) + return -EINVAL; + + if (value) { + /* Get the register index and value to set */ + reg_idx = (value - 1) / (8 * cmpnt->val_bytes); + bit_pos = (value - 1) % (8 * cmpnt->val_bytes); + reg_val = BIT(bit_pos); + } + + /* + * Run through all parts of a MUX register to find the state changes. + * There will be an additional update if new MUX input value is from + * different part of the MUX register. + */ + for (i = 0; i < ahub->soc_data->reg_count; i++) { + update[i].reg = e->reg + (TEGRA210_XBAR_PART1_RX * i); + update[i].val = (i == reg_idx) ? reg_val : 0; + update[i].mask = ahub->soc_data->mask[i]; + update[i].kcontrol = kctl; + + /* Update widget power if state has changed */ + if (snd_soc_component_test_bits(cmpnt, update[i].reg, + update[i].mask, update[i].val)) + snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e, + &update[i]); + } + + return 0; +} + +static struct snd_soc_dai_driver tegra210_ahub_dais[] = { + DAI(ADMAIF1), + DAI(ADMAIF2), + DAI(ADMAIF3), + DAI(ADMAIF4), + DAI(ADMAIF5), + DAI(ADMAIF6), + DAI(ADMAIF7), + DAI(ADMAIF8), + DAI(ADMAIF9), + DAI(ADMAIF10), + DAI(I2S1), + DAI(I2S2), + DAI(I2S3), + DAI(I2S4), + DAI(I2S5), + DAI(DMIC1), + DAI(DMIC2), + DAI(DMIC3), +}; + +static struct snd_soc_dai_driver tegra186_ahub_dais[] = { + DAI(ADMAIF1), + DAI(ADMAIF2), + DAI(ADMAIF3), + DAI(ADMAIF4), + DAI(ADMAIF5), + DAI(ADMAIF6), + DAI(ADMAIF7), + DAI(ADMAIF8), + DAI(ADMAIF9), + DAI(ADMAIF10), + DAI(ADMAIF11), + DAI(ADMAIF12), + DAI(ADMAIF13), + DAI(ADMAIF14), + DAI(ADMAIF15), + DAI(ADMAIF16), + DAI(ADMAIF17), + DAI(ADMAIF18), + DAI(ADMAIF19), + DAI(ADMAIF20), + DAI(I2S1), + DAI(I2S2), + DAI(I2S3), + DAI(I2S4), + DAI(I2S5), + DAI(I2S6), + DAI(DMIC1), + DAI(DMIC2), + DAI(DMIC3), + DAI(DMIC4), + DAI(DSPK1), + DAI(DSPK2), +}; + +static const char * const tegra210_ahub_mux_texts[] = { + "None", + "ADMAIF1", + "ADMAIF2", + "ADMAIF3", + "ADMAIF4", + "ADMAIF5", + "ADMAIF6", + "ADMAIF7", + "ADMAIF8", + "ADMAIF9", + "ADMAIF10", + "I2S1", + "I2S2", + "I2S3", + "I2S4", + "I2S5", + "DMIC1", + "DMIC2", + "DMIC3", +}; + +static const char * const tegra186_ahub_mux_texts[] = { + "None", + "ADMAIF1", + "ADMAIF2", + "ADMAIF3", + "ADMAIF4", + "ADMAIF5", + "ADMAIF6", + "ADMAIF7", + "ADMAIF8", + "ADMAIF9", + "ADMAIF10", + "ADMAIF11", + "ADMAIF12", + "ADMAIF13", + "ADMAIF14", + "ADMAIF15", + "ADMAIF16", + "I2S1", + "I2S2", + "I2S3", + "I2S4", + "I2S5", + "I2S6", + "ADMAIF17", + "ADMAIF18", + "ADMAIF19", + "ADMAIF20", + "DMIC1", + "DMIC2", + "DMIC3", + "DMIC4", +}; + +static const unsigned int tegra210_ahub_mux_values[] = { + 0, + MUX_VALUE(0, 0), + MUX_VALUE(0, 1), + MUX_VALUE(0, 2), + MUX_VALUE(0, 3), + MUX_VALUE(0, 4), + MUX_VALUE(0, 5), + MUX_VALUE(0, 6), + MUX_VALUE(0, 7), + MUX_VALUE(0, 8), + MUX_VALUE(0, 9), + MUX_VALUE(0, 16), + MUX_VALUE(0, 17), + MUX_VALUE(0, 18), + MUX_VALUE(0, 19), + MUX_VALUE(0, 20), + MUX_VALUE(2, 18), + MUX_VALUE(2, 19), + MUX_VALUE(2, 20), +}; + +static const unsigned int tegra186_ahub_mux_values[] = { + 0, + MUX_VALUE(0, 0), + MUX_VALUE(0, 1), + MUX_VALUE(0, 2), + MUX_VALUE(0, 3), + MUX_VALUE(0, 4), + MUX_VALUE(0, 5), + MUX_VALUE(0, 6), + MUX_VALUE(0, 7), + MUX_VALUE(0, 8), + MUX_VALUE(0, 9), + MUX_VALUE(0, 10), + MUX_VALUE(0, 11), + MUX_VALUE(0, 12), + MUX_VALUE(0, 13), + MUX_VALUE(0, 14), + MUX_VALUE(0, 15), + MUX_VALUE(0, 16), + MUX_VALUE(0, 17), + MUX_VALUE(0, 18), + MUX_VALUE(0, 19), + MUX_VALUE(0, 20), + MUX_VALUE(0, 21), + MUX_VALUE(3, 16), + MUX_VALUE(3, 17), + MUX_VALUE(3, 18), + MUX_VALUE(3, 19), + MUX_VALUE(2, 18), + MUX_VALUE(2, 19), + MUX_VALUE(2, 20), + MUX_VALUE(2, 21), +}; + +/* Controls for t210 */ +MUX_ENUM_CTRL_DECL(t210_admaif1_tx, 0x00); +MUX_ENUM_CTRL_DECL(t210_admaif2_tx, 0x01); +MUX_ENUM_CTRL_DECL(t210_admaif3_tx, 0x02); +MUX_ENUM_CTRL_DECL(t210_admaif4_tx, 0x03); +MUX_ENUM_CTRL_DECL(t210_admaif5_tx, 0x04); +MUX_ENUM_CTRL_DECL(t210_admaif6_tx, 0x05); +MUX_ENUM_CTRL_DECL(t210_admaif7_tx, 0x06); +MUX_ENUM_CTRL_DECL(t210_admaif8_tx, 0x07); +MUX_ENUM_CTRL_DECL(t210_admaif9_tx, 0x08); +MUX_ENUM_CTRL_DECL(t210_admaif10_tx, 0x09); +MUX_ENUM_CTRL_DECL(t210_i2s1_tx, 0x10); +MUX_ENUM_CTRL_DECL(t210_i2s2_tx, 0x11); +MUX_ENUM_CTRL_DECL(t210_i2s3_tx, 0x12); +MUX_ENUM_CTRL_DECL(t210_i2s4_tx, 0x13); +MUX_ENUM_CTRL_DECL(t210_i2s5_tx, 0x14); + +/* Controls for t186 */ +MUX_ENUM_CTRL_DECL_186(t186_admaif1_tx, 0x00); +MUX_ENUM_CTRL_DECL_186(t186_admaif2_tx, 0x01); +MUX_ENUM_CTRL_DECL_186(t186_admaif3_tx, 0x02); +MUX_ENUM_CTRL_DECL_186(t186_admaif4_tx, 0x03); +MUX_ENUM_CTRL_DECL_186(t186_admaif5_tx, 0x04); +MUX_ENUM_CTRL_DECL_186(t186_admaif6_tx, 0x05); +MUX_ENUM_CTRL_DECL_186(t186_admaif7_tx, 0x06); +MUX_ENUM_CTRL_DECL_186(t186_admaif8_tx, 0x07); +MUX_ENUM_CTRL_DECL_186(t186_admaif9_tx, 0x08); +MUX_ENUM_CTRL_DECL_186(t186_admaif10_tx, 0x09); +MUX_ENUM_CTRL_DECL_186(t186_i2s1_tx, 0x10); +MUX_ENUM_CTRL_DECL_186(t186_i2s2_tx, 0x11); +MUX_ENUM_CTRL_DECL_186(t186_i2s3_tx, 0x12); +MUX_ENUM_CTRL_DECL_186(t186_i2s4_tx, 0x13); +MUX_ENUM_CTRL_DECL_186(t186_i2s5_tx, 0x14); +MUX_ENUM_CTRL_DECL_186(t186_admaif11_tx, 0x0a); +MUX_ENUM_CTRL_DECL_186(t186_admaif12_tx, 0x0b); +MUX_ENUM_CTRL_DECL_186(t186_admaif13_tx, 0x0c); +MUX_ENUM_CTRL_DECL_186(t186_admaif14_tx, 0x0d); +MUX_ENUM_CTRL_DECL_186(t186_admaif15_tx, 0x0e); +MUX_ENUM_CTRL_DECL_186(t186_admaif16_tx, 0x0f); +MUX_ENUM_CTRL_DECL_186(t186_i2s6_tx, 0x15); +MUX_ENUM_CTRL_DECL_186(t186_dspk1_tx, 0x30); +MUX_ENUM_CTRL_DECL_186(t186_dspk2_tx, 0x31); +MUX_ENUM_CTRL_DECL_186(t186_admaif17_tx, 0x68); +MUX_ENUM_CTRL_DECL_186(t186_admaif18_tx, 0x69); +MUX_ENUM_CTRL_DECL_186(t186_admaif19_tx, 0x6a); +MUX_ENUM_CTRL_DECL_186(t186_admaif20_tx, 0x6b); + +/* + * The number of entries in, and order of, this array is closely tied to the + * calculation of tegra210_ahub_codec.num_dapm_widgets near the end of + * tegra210_ahub_probe() + */ +static const struct snd_soc_dapm_widget tegra210_ahub_widgets[] = { + WIDGETS("ADMAIF1", t210_admaif1_tx), + WIDGETS("ADMAIF2", t210_admaif2_tx), + WIDGETS("ADMAIF3", t210_admaif3_tx), + WIDGETS("ADMAIF4", t210_admaif4_tx), + WIDGETS("ADMAIF5", t210_admaif5_tx), + WIDGETS("ADMAIF6", t210_admaif6_tx), + WIDGETS("ADMAIF7", t210_admaif7_tx), + WIDGETS("ADMAIF8", t210_admaif8_tx), + WIDGETS("ADMAIF9", t210_admaif9_tx), + WIDGETS("ADMAIF10", t210_admaif10_tx), + WIDGETS("I2S1", t210_i2s1_tx), + WIDGETS("I2S2", t210_i2s2_tx), + WIDGETS("I2S3", t210_i2s3_tx), + WIDGETS("I2S4", t210_i2s4_tx), + WIDGETS("I2S5", t210_i2s5_tx), + TX_WIDGETS("DMIC1"), + TX_WIDGETS("DMIC2"), + TX_WIDGETS("DMIC3"), +}; + +static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = { + WIDGETS("ADMAIF1", t186_admaif1_tx), + WIDGETS("ADMAIF2", t186_admaif2_tx), + WIDGETS("ADMAIF3", t186_admaif3_tx), + WIDGETS("ADMAIF4", t186_admaif4_tx), + WIDGETS("ADMAIF5", t186_admaif5_tx), + WIDGETS("ADMAIF6", t186_admaif6_tx), + WIDGETS("ADMAIF7", t186_admaif7_tx), + WIDGETS("ADMAIF8", t186_admaif8_tx), + WIDGETS("ADMAIF9", t186_admaif9_tx), + WIDGETS("ADMAIF10", t186_admaif10_tx), + WIDGETS("ADMAIF11", t186_admaif11_tx), + WIDGETS("ADMAIF12", t186_admaif12_tx), + WIDGETS("ADMAIF13", t186_admaif13_tx), + WIDGETS("ADMAIF14", t186_admaif14_tx), + WIDGETS("ADMAIF15", t186_admaif15_tx), + WIDGETS("ADMAIF16", t186_admaif16_tx), + WIDGETS("ADMAIF17", t186_admaif17_tx), + WIDGETS("ADMAIF18", t186_admaif18_tx), + WIDGETS("ADMAIF19", t186_admaif19_tx), + WIDGETS("ADMAIF20", t186_admaif20_tx), + WIDGETS("I2S1", t186_i2s1_tx), + WIDGETS("I2S2", t186_i2s2_tx), + WIDGETS("I2S3", t186_i2s3_tx), + WIDGETS("I2S4", t186_i2s4_tx), + WIDGETS("I2S5", t186_i2s5_tx), + WIDGETS("I2S6", t186_i2s6_tx), + TX_WIDGETS("DMIC1"), + TX_WIDGETS("DMIC2"), + TX_WIDGETS("DMIC3"), + TX_WIDGETS("DMIC4"), + WIDGETS("DSPK1", t186_dspk1_tx), + WIDGETS("DSPK2", t186_dspk2_tx), +}; + +#define TEGRA_COMMON_MUX_ROUTES(name) \ + { name " XBAR-TX", NULL, name " Mux" }, \ + { name " Mux", "ADMAIF1", "ADMAIF1 XBAR-RX" }, \ + { name " Mux", "ADMAIF2", "ADMAIF2 XBAR-RX" }, \ + { name " Mux", "ADMAIF3", "ADMAIF3 XBAR-RX" }, \ + { name " Mux", "ADMAIF4", "ADMAIF4 XBAR-RX" }, \ + { name " Mux", "ADMAIF5", "ADMAIF5 XBAR-RX" }, \ + { name " Mux", "ADMAIF6", "ADMAIF6 XBAR-RX" }, \ + { name " Mux", "ADMAIF7", "ADMAIF7 XBAR-RX" }, \ + { name " Mux", "ADMAIF8", "ADMAIF8 XBAR-RX" }, \ + { name " Mux", "ADMAIF9", "ADMAIF9 XBAR-RX" }, \ + { name " Mux", "ADMAIF10", "ADMAIF10 XBAR-RX" }, \ + { name " Mux", "I2S1", "I2S1 XBAR-RX" }, \ + { name " Mux", "I2S2", "I2S2 XBAR-RX" }, \ + { name " Mux", "I2S3", "I2S3 XBAR-RX" }, \ + { name " Mux", "I2S4", "I2S4 XBAR-RX" }, \ + { name " Mux", "I2S5", "I2S5 XBAR-RX" }, \ + { name " Mux", "DMIC1", "DMIC1 XBAR-RX" }, \ + { name " Mux", "DMIC2", "DMIC2 XBAR-RX" }, \ + { name " Mux", "DMIC3", "DMIC3 XBAR-RX" }, + +#define TEGRA186_ONLY_MUX_ROUTES(name) \ + { name " Mux", "ADMAIF11", "ADMAIF11 XBAR-RX" }, \ + { name " Mux", "ADMAIF12", "ADMAIF12 XBAR-RX" }, \ + { name " Mux", "ADMAIF13", "ADMAIF13 XBAR-RX" }, \ + { name " Mux", "ADMAIF14", "ADMAIF14 XBAR-RX" }, \ + { name " Mux", "ADMAIF15", "ADMAIF15 XBAR-RX" }, \ + { name " Mux", "ADMAIF16", "ADMAIF16 XBAR-RX" }, \ + { name " Mux", "ADMAIF17", "ADMAIF17 XBAR-RX" }, \ + { name " Mux", "ADMAIF18", "ADMAIF18 XBAR-RX" }, \ + { name " Mux", "ADMAIF19", "ADMAIF19 XBAR-RX" }, \ + { name " Mux", "ADMAIF20", "ADMAIF20 XBAR-RX" }, \ + { name " Mux", "I2S6", "I2S6 XBAR-RX" }, \ + { name " Mux", "DMIC4", "DMIC4 XBAR-RX" }, + +#define TEGRA210_MUX_ROUTES(name) \ + TEGRA_COMMON_MUX_ROUTES(name) + +#define TEGRA186_MUX_ROUTES(name) \ + TEGRA_COMMON_MUX_ROUTES(name) \ + TEGRA186_ONLY_MUX_ROUTES(name) + +/* Connect FEs with XBAR */ +#define TEGRA_FE_ROUTES(name) \ + { name " XBAR-Playback", NULL, name " Playback" }, \ + { name " XBAR-RX", NULL, name " XBAR-Playback"}, \ + { name " XBAR-Capture", NULL, name " XBAR-TX" }, \ + { name " Capture", NULL, name " XBAR-Capture" }, + +/* + * The number of entries in, and order of, this array is closely tied to the + * calculation of tegra210_ahub_codec.num_dapm_routes near the end of + * tegra210_ahub_probe() + */ +static const struct snd_soc_dapm_route tegra210_ahub_routes[] = { + TEGRA_FE_ROUTES("ADMAIF1") + TEGRA_FE_ROUTES("ADMAIF2") + TEGRA_FE_ROUTES("ADMAIF3") + TEGRA_FE_ROUTES("ADMAIF4") + TEGRA_FE_ROUTES("ADMAIF5") + TEGRA_FE_ROUTES("ADMAIF6") + TEGRA_FE_ROUTES("ADMAIF7") + TEGRA_FE_ROUTES("ADMAIF8") + TEGRA_FE_ROUTES("ADMAIF9") + TEGRA_FE_ROUTES("ADMAIF10") + TEGRA210_MUX_ROUTES("ADMAIF1") + TEGRA210_MUX_ROUTES("ADMAIF2") + TEGRA210_MUX_ROUTES("ADMAIF3") + TEGRA210_MUX_ROUTES("ADMAIF4") + TEGRA210_MUX_ROUTES("ADMAIF5") + TEGRA210_MUX_ROUTES("ADMAIF6") + TEGRA210_MUX_ROUTES("ADMAIF7") + TEGRA210_MUX_ROUTES("ADMAIF8") + TEGRA210_MUX_ROUTES("ADMAIF9") + TEGRA210_MUX_ROUTES("ADMAIF10") + TEGRA210_MUX_ROUTES("I2S1") + TEGRA210_MUX_ROUTES("I2S2") + TEGRA210_MUX_ROUTES("I2S3") + TEGRA210_MUX_ROUTES("I2S4") + TEGRA210_MUX_ROUTES("I2S5") +}; + +static const struct snd_soc_dapm_route tegra186_ahub_routes[] = { + TEGRA_FE_ROUTES("ADMAIF1") + TEGRA_FE_ROUTES("ADMAIF2") + TEGRA_FE_ROUTES("ADMAIF3") + TEGRA_FE_ROUTES("ADMAIF4") + TEGRA_FE_ROUTES("ADMAIF5") + TEGRA_FE_ROUTES("ADMAIF6") + TEGRA_FE_ROUTES("ADMAIF7") + TEGRA_FE_ROUTES("ADMAIF8") + TEGRA_FE_ROUTES("ADMAIF9") + TEGRA_FE_ROUTES("ADMAIF10") + TEGRA_FE_ROUTES("ADMAIF11") + TEGRA_FE_ROUTES("ADMAIF12") + TEGRA_FE_ROUTES("ADMAIF13") + TEGRA_FE_ROUTES("ADMAIF14") + TEGRA_FE_ROUTES("ADMAIF15") + TEGRA_FE_ROUTES("ADMAIF16") + TEGRA_FE_ROUTES("ADMAIF17") + TEGRA_FE_ROUTES("ADMAIF18") + TEGRA_FE_ROUTES("ADMAIF19") + TEGRA_FE_ROUTES("ADMAIF20") + TEGRA186_MUX_ROUTES("ADMAIF1") + TEGRA186_MUX_ROUTES("ADMAIF2") + TEGRA186_MUX_ROUTES("ADMAIF3") + TEGRA186_MUX_ROUTES("ADMAIF4") + TEGRA186_MUX_ROUTES("ADMAIF5") + TEGRA186_MUX_ROUTES("ADMAIF6") + TEGRA186_MUX_ROUTES("ADMAIF7") + TEGRA186_MUX_ROUTES("ADMAIF8") + TEGRA186_MUX_ROUTES("ADMAIF9") + TEGRA186_MUX_ROUTES("ADMAIF10") + TEGRA186_MUX_ROUTES("ADMAIF11") + TEGRA186_MUX_ROUTES("ADMAIF12") + TEGRA186_MUX_ROUTES("ADMAIF13") + TEGRA186_MUX_ROUTES("ADMAIF14") + TEGRA186_MUX_ROUTES("ADMAIF15") + TEGRA186_MUX_ROUTES("ADMAIF16") + TEGRA186_MUX_ROUTES("ADMAIF17") + TEGRA186_MUX_ROUTES("ADMAIF18") + TEGRA186_MUX_ROUTES("ADMAIF19") + TEGRA186_MUX_ROUTES("ADMAIF20") + TEGRA186_MUX_ROUTES("I2S1") + TEGRA186_MUX_ROUTES("I2S2") + TEGRA186_MUX_ROUTES("I2S3") + TEGRA186_MUX_ROUTES("I2S4") + TEGRA186_MUX_ROUTES("I2S5") + TEGRA186_MUX_ROUTES("I2S6") + TEGRA186_MUX_ROUTES("DSPK1") + TEGRA186_MUX_ROUTES("DSPK2") +}; + +static const struct snd_soc_component_driver tegra210_ahub_component = { + .dapm_widgets = tegra210_ahub_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra210_ahub_widgets), + .dapm_routes = tegra210_ahub_routes, + .num_dapm_routes = ARRAY_SIZE(tegra210_ahub_routes), +}; + +static const struct snd_soc_component_driver tegra186_ahub_component = { + .dapm_widgets = tegra186_ahub_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra186_ahub_widgets), + .dapm_routes = tegra186_ahub_routes, + .num_dapm_routes = ARRAY_SIZE(tegra186_ahub_routes), +}; + +static const struct regmap_config tegra210_ahub_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = TEGRA210_MAX_REGISTER_ADDR, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config tegra186_ahub_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = TEGRA186_MAX_REGISTER_ADDR, + .cache_type = REGCACHE_FLAT, +}; + +static const struct tegra_ahub_soc_data soc_data_tegra210 = { + .cmpnt_drv = &tegra210_ahub_component, + .dai_drv = tegra210_ahub_dais, + .num_dais = ARRAY_SIZE(tegra210_ahub_dais), + .regmap_config = &tegra210_ahub_regmap_config, + .mask[0] = TEGRA210_XBAR_REG_MASK_0, + .mask[1] = TEGRA210_XBAR_REG_MASK_1, + .mask[2] = TEGRA210_XBAR_REG_MASK_2, + .mask[3] = TEGRA210_XBAR_REG_MASK_3, + .reg_count = TEGRA210_XBAR_UPDATE_MAX_REG, +}; + +static const struct tegra_ahub_soc_data soc_data_tegra186 = { + .cmpnt_drv = &tegra186_ahub_component, + .dai_drv = tegra186_ahub_dais, + .num_dais = ARRAY_SIZE(tegra186_ahub_dais), + .regmap_config = &tegra186_ahub_regmap_config, + .mask[0] = TEGRA186_XBAR_REG_MASK_0, + .mask[1] = TEGRA186_XBAR_REG_MASK_1, + .mask[2] = TEGRA186_XBAR_REG_MASK_2, + .mask[3] = TEGRA186_XBAR_REG_MASK_3, + .reg_count = TEGRA186_XBAR_UPDATE_MAX_REG, +}; + +static const struct of_device_id tegra_ahub_of_match[] = { + { .compatible = "nvidia,tegra210-ahub", .data = &soc_data_tegra210 }, + { .compatible = "nvidia,tegra186-ahub", .data = &soc_data_tegra186 }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra_ahub_of_match); + +static int tegra_ahub_runtime_suspend(struct device *dev) +{ + struct tegra_ahub *ahub = dev_get_drvdata(dev); + + regcache_cache_only(ahub->regmap, true); + regcache_mark_dirty(ahub->regmap); + + clk_disable_unprepare(ahub->clk); + + return 0; +} + +static int tegra_ahub_runtime_resume(struct device *dev) +{ + struct tegra_ahub *ahub = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(ahub->clk); + if (err) { + dev_err(dev, "failed to enable AHUB clock, err: %d\n", err); + return err; + } + + regcache_cache_only(ahub->regmap, false); + regcache_sync(ahub->regmap); + + return 0; +} + +static int tegra_ahub_probe(struct platform_device *pdev) +{ + struct tegra_ahub *ahub; + void __iomem *regs; + int err; + + ahub = devm_kzalloc(&pdev->dev, sizeof(*ahub), GFP_KERNEL); + if (!ahub) + return -ENOMEM; + + ahub->soc_data = of_device_get_match_data(&pdev->dev); + + platform_set_drvdata(pdev, ahub); + + ahub->clk = devm_clk_get(&pdev->dev, "ahub"); + if (IS_ERR(ahub->clk)) { + dev_err(&pdev->dev, "can't retrieve AHUB clock\n"); + return PTR_ERR(ahub->clk); + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + ahub->regmap = devm_regmap_init_mmio(&pdev->dev, regs, + ahub->soc_data->regmap_config); + if (IS_ERR(ahub->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + return PTR_ERR(ahub->regmap); + } + + regcache_cache_only(ahub->regmap, true); + + err = devm_snd_soc_register_component(&pdev->dev, + ahub->soc_data->cmpnt_drv, + ahub->soc_data->dai_drv, + ahub->soc_data->num_dais); + if (err) { + dev_err(&pdev->dev, "can't register AHUB component, err: %d\n", + err); + return err; + } + + err = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + if (err) + return err; + + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int tegra_ahub_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra_ahub_pm_ops = { + SET_RUNTIME_PM_OPS(tegra_ahub_runtime_suspend, + tegra_ahub_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver tegra_ahub_driver = { + .probe = tegra_ahub_probe, + .remove = tegra_ahub_remove, + .driver = { + .name = "tegra210-ahub", + .of_match_table = tegra_ahub_of_match, + .pm = &tegra_ahub_pm_ops, + }, +}; +module_platform_driver(tegra_ahub_driver); + +MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); +MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>"); +MODULE_DESCRIPTION("Tegra210 ASoC AHUB driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_ahub.h b/sound/soc/tegra/tegra210_ahub.h new file mode 100644 index 000000000000..47802bbe17a9 --- /dev/null +++ b/sound/soc/tegra/tegra210_ahub.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_ahub.h - TEGRA210 AHUB + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_AHUB__H__ +#define __TEGRA210_AHUB__H__ + +/* Tegra210 specific */ +#define TEGRA210_XBAR_PART1_RX 0x200 +#define TEGRA210_XBAR_PART2_RX 0x400 +#define TEGRA210_XBAR_RX_STRIDE 0x4 +#define TEGRA210_XBAR_AUDIO_RX_COUNT 90 +#define TEGRA210_XBAR_REG_MASK_0 0xf1f03ff +#define TEGRA210_XBAR_REG_MASK_1 0x3f30031f +#define TEGRA210_XBAR_REG_MASK_2 0xff1cf313 +#define TEGRA210_XBAR_REG_MASK_3 0x0 +#define TEGRA210_XBAR_UPDATE_MAX_REG 3 +/* Tegra186 specific */ +#define TEGRA186_XBAR_PART3_RX 0x600 +#define TEGRA186_XBAR_AUDIO_RX_COUNT 115 +#define TEGRA186_XBAR_REG_MASK_0 0xf3fffff +#define TEGRA186_XBAR_REG_MASK_1 0x3f310f1f +#define TEGRA186_XBAR_REG_MASK_2 0xff3cf311 +#define TEGRA186_XBAR_REG_MASK_3 0x3f0f00ff +#define TEGRA186_XBAR_UPDATE_MAX_REG 4 + +#define TEGRA_XBAR_UPDATE_MAX_REG (TEGRA186_XBAR_UPDATE_MAX_REG) + +#define TEGRA186_MAX_REGISTER_ADDR (TEGRA186_XBAR_PART3_RX + \ + (TEGRA210_XBAR_RX_STRIDE * (TEGRA186_XBAR_AUDIO_RX_COUNT - 1))) + +#define TEGRA210_MAX_REGISTER_ADDR (TEGRA210_XBAR_PART2_RX + \ + (TEGRA210_XBAR_RX_STRIDE * (TEGRA210_XBAR_AUDIO_RX_COUNT - 1))) + +#define MUX_REG(id) (TEGRA210_XBAR_RX_STRIDE * (id)) + +#define MUX_VALUE(npart, nbit) (1 + (nbit) + (npart) * 32) + +#define SOC_VALUE_ENUM_WIDE(xreg, shift, xmax, xtexts, xvalues) \ + { \ + .reg = xreg, \ + .shift_l = shift, \ + .shift_r = shift, \ + .items = xmax, \ + .texts = xtexts, \ + .values = xvalues, \ + .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0 \ + } + +#define SOC_VALUE_ENUM_WIDE_DECL(name, xreg, shift, xtexts, xvalues) \ + static struct soc_enum name = \ + SOC_VALUE_ENUM_WIDE(xreg, shift, ARRAY_SIZE(xtexts), \ + xtexts, xvalues) + +#define MUX_ENUM_CTRL_DECL(ename, id) \ + SOC_VALUE_ENUM_WIDE_DECL(ename##_enum, MUX_REG(id), 0, \ + tegra210_ahub_mux_texts, \ + tegra210_ahub_mux_values); \ + static const struct snd_kcontrol_new ename##_control = \ + SOC_DAPM_ENUM_EXT("Route", ename##_enum, \ + tegra_ahub_get_value_enum, \ + tegra_ahub_put_value_enum) + +#define MUX_ENUM_CTRL_DECL_186(ename, id) \ + SOC_VALUE_ENUM_WIDE_DECL(ename##_enum, MUX_REG(id), 0, \ + tegra186_ahub_mux_texts, \ + tegra186_ahub_mux_values); \ + static const struct snd_kcontrol_new ename##_control = \ + SOC_DAPM_ENUM_EXT("Route", ename##_enum, \ + tegra_ahub_get_value_enum, \ + tegra_ahub_put_value_enum) + +#define WIDGETS(sname, ename) \ + SND_SOC_DAPM_AIF_IN(sname " XBAR-RX", NULL, 0, SND_SOC_NOPM, 0, 0), \ + SND_SOC_DAPM_AIF_OUT(sname " XBAR-TX", NULL, 0, SND_SOC_NOPM, 0, 0), \ + SND_SOC_DAPM_MUX(sname " Mux", SND_SOC_NOPM, 0, 0, \ + &ename##_control) + +#define TX_WIDGETS(sname) \ + SND_SOC_DAPM_AIF_IN(sname " XBAR-RX", NULL, 0, SND_SOC_NOPM, 0, 0), \ + SND_SOC_DAPM_AIF_OUT(sname " XBAR-TX", NULL, 0, SND_SOC_NOPM, 0, 0) + +#define DAI(sname) \ + { \ + .name = "XBAR-" #sname, \ + .playback = { \ + .stream_name = #sname " XBAR-Playback", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + .capture = { \ + .stream_name = #sname " XBAR-Capture", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + } + +struct tegra_ahub_soc_data { + const struct regmap_config *regmap_config; + const struct snd_soc_component_driver *cmpnt_drv; + struct snd_soc_dai_driver *dai_drv; + unsigned int mask[4]; + unsigned int reg_count; + unsigned int num_dais; +}; + +struct tegra_ahub { + const struct tegra_ahub_soc_data *soc_data; + struct regmap *regmap; + struct clk *clk; +}; + +#endif diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c new file mode 100644 index 000000000000..d682414ad90d --- /dev/null +++ b/sound/soc/tegra/tegra210_dmic.c @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_dmic.c - Tegra210 DMIC driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/math64.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <sound/core.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include "tegra210_dmic.h" +#include "tegra_cif.h" + +static const struct reg_default tegra210_dmic_reg_defaults[] = { + { TEGRA210_DMIC_TX_INT_MASK, 0x00000001 }, + { TEGRA210_DMIC_TX_CIF_CTRL, 0x00007700 }, + { TEGRA210_DMIC_CG, 0x1 }, + { TEGRA210_DMIC_CTRL, 0x00000301 }, + /* Below enables all filters - DCR, LP and SC */ + { TEGRA210_DMIC_DBG_CTRL, 0xe }, + /* Below as per latest POR value */ + { TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4, 0x0 }, + /* LP filter is configured for pass through and used to apply gain */ + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_0, 0x00800000 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_1, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_2, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_3, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_4, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_0, 0x00800000 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_1, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_2, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_3, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 0x0 }, +}; + +static int tegra210_dmic_runtime_suspend(struct device *dev) +{ + struct tegra210_dmic *dmic = dev_get_drvdata(dev); + + regcache_cache_only(dmic->regmap, true); + regcache_mark_dirty(dmic->regmap); + + clk_disable_unprepare(dmic->clk_dmic); + + return 0; +} + +static int tegra210_dmic_runtime_resume(struct device *dev) +{ + struct tegra210_dmic *dmic = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(dmic->clk_dmic); + if (err) { + dev_err(dev, "failed to enable DMIC clock, err: %d\n", err); + return err; + } + + regcache_cache_only(dmic->regmap, false); + regcache_sync(dmic->regmap); + + return 0; +} + +static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai); + unsigned int srate, clk_rate, channels; + struct tegra_cif_conf cif_conf; + unsigned long long gain_q23 = DEFAULT_GAIN_Q23; + int err; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + channels = params_channels(params); + + cif_conf.audio_ch = channels; + + switch (dmic->ch_select) { + case DMIC_CH_SELECT_LEFT: + case DMIC_CH_SELECT_RIGHT: + cif_conf.client_ch = 1; + break; + case DMIC_CH_SELECT_STEREO: + cif_conf.client_ch = 2; + break; + default: + dev_err(dai->dev, "invalid DMIC client channels\n"); + return -EINVAL; + } + + srate = params_rate(params); + + /* + * DMIC clock rate is a multiple of 'Over Sampling Ratio' and + * 'Sample Rate'. The supported OSR values are 64, 128 and 256. + */ + clk_rate = (DMIC_OSR_FACTOR << dmic->osr_val) * srate; + + err = clk_set_rate(dmic->clk_dmic, clk_rate); + if (err) { + dev_err(dai->dev, "can't set DMIC clock rate %u, err: %d\n", + clk_rate, err); + return err; + } + + regmap_update_bits(dmic->regmap, + /* Reg */ + TEGRA210_DMIC_CTRL, + /* Mask */ + TEGRA210_DMIC_CTRL_LRSEL_POLARITY_MASK | + TEGRA210_DMIC_CTRL_OSR_MASK | + TEGRA210_DMIC_CTRL_CHANNEL_SELECT_MASK, + /* Value */ + (dmic->lrsel << LRSEL_POL_SHIFT) | + (dmic->osr_val << OSR_SHIFT) | + ((dmic->ch_select + 1) << CH_SEL_SHIFT)); + + /* + * Use LP filter gain register to apply boost. + * Boost Gain Volume control has 100x factor. + */ + if (dmic->boost_gain) + gain_q23 = div_u64(gain_q23 * dmic->boost_gain, 100); + + regmap_write(dmic->regmap, TEGRA210_DMIC_LP_FILTER_GAIN, + (unsigned int)gain_q23); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + break; + case SNDRV_PCM_FORMAT_S32_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + break; + default: + dev_err(dai->dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + cif_conf.client_bits = TEGRA_ACIF_BITS_24; + cif_conf.mono_conv = dmic->mono_to_stereo; + cif_conf.stereo_conv = dmic->stereo_to_mono; + + tegra_set_cif(dmic->regmap, TEGRA210_DMIC_TX_CIF_CTRL, &cif_conf); + + return 0; +} + +static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); + + if (strstr(kcontrol->id.name, "Boost Gain Volume")) + ucontrol->value.integer.value[0] = dmic->boost_gain; + else if (strstr(kcontrol->id.name, "Channel Select")) + ucontrol->value.integer.value[0] = dmic->ch_select; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + ucontrol->value.integer.value[0] = dmic->mono_to_stereo; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + ucontrol->value.integer.value[0] = dmic->stereo_to_mono; + else if (strstr(kcontrol->id.name, "OSR Value")) + ucontrol->value.integer.value[0] = dmic->osr_val; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + ucontrol->value.integer.value[0] = dmic->lrsel; + + return 0; +} + +static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); + int value = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Boost Gain Volume")) + dmic->boost_gain = value; + else if (strstr(kcontrol->id.name, "Channel Select")) + dmic->ch_select = ucontrol->value.integer.value[0]; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + dmic->mono_to_stereo = value; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + dmic->stereo_to_mono = value; + else if (strstr(kcontrol->id.name, "OSR Value")) + dmic->osr_val = value; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + dmic->lrsel = value; + + return 0; +} + +static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { + .hw_params = tegra210_dmic_hw_params, +}; + +static struct snd_soc_dai_driver tegra210_dmic_dais[] = { + { + .name = "DMIC-CIF", + .capture = { + .stream_name = "CIF-Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + }, + { + .name = "DMIC-DAP", + .capture = { + .stream_name = "DAP-Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tegra210_dmic_dai_ops, + .symmetric_rates = 1, + }, +}; + +static const struct snd_soc_dapm_widget tegra210_dmic_widgets[] = { + SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_DMIC_ENABLE, 0, 0), + SND_SOC_DAPM_MIC("MIC", NULL), +}; + +static const struct snd_soc_dapm_route tegra210_dmic_routes[] = { + { "XBAR-RX", NULL, "XBAR-Capture" }, + { "XBAR-Capture", NULL, "CIF-Capture" }, + { "CIF-Capture", NULL, "TX" }, + { "TX", NULL, "DAP-Capture" }, + { "DAP-Capture", NULL, "MIC" }, +}; + +static const char * const tegra210_dmic_ch_select[] = { + "Left", "Right", "Stereo", +}; + +static const struct soc_enum tegra210_dmic_ch_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_ch_select), + tegra210_dmic_ch_select); + +static const char * const tegra210_dmic_mono_conv_text[] = { + "Zero", "Copy", +}; + +static const char * const tegra210_dmic_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const struct soc_enum tegra210_dmic_mono_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_mono_conv_text), + tegra210_dmic_mono_conv_text); + +static const struct soc_enum tegra210_dmic_stereo_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_stereo_conv_text), + tegra210_dmic_stereo_conv_text); + +static const char * const tegra210_dmic_osr_text[] = { + "OSR_64", "OSR_128", "OSR_256", +}; + +static const struct soc_enum tegra210_dmic_osr_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_osr_text), + tegra210_dmic_osr_text); + +static const char * const tegra210_dmic_lrsel_text[] = { + "Left", "Right", +}; + +static const struct soc_enum tegra210_dmic_lrsel_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_lrsel_text), + tegra210_dmic_lrsel_text); + +static const struct snd_kcontrol_new tegra210_dmic_controls[] = { + SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, + tegra210_dmic_get_control, tegra210_dmic_put_control), + SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, + tegra210_dmic_get_control, tegra210_dmic_put_control), + SOC_ENUM_EXT("Mono To Stereo", + tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, + tegra210_dmic_put_control), + SOC_ENUM_EXT("Stereo To Mono", + tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, + tegra210_dmic_put_control), + SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, + tegra210_dmic_get_control, tegra210_dmic_put_control), + SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, + tegra210_dmic_get_control, tegra210_dmic_put_control), +}; + +static const struct snd_soc_component_driver tegra210_dmic_compnt = { + .dapm_widgets = tegra210_dmic_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra210_dmic_widgets), + .dapm_routes = tegra210_dmic_routes, + .num_dapm_routes = ARRAY_SIZE(tegra210_dmic_routes), + .controls = tegra210_dmic_controls, + .num_controls = ARRAY_SIZE(tegra210_dmic_controls), +}; + +static bool tegra210_dmic_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_DMIC_TX_INT_MASK ... TEGRA210_DMIC_TX_CIF_CTRL: + case TEGRA210_DMIC_ENABLE ... TEGRA210_DMIC_CG: + case TEGRA210_DMIC_CTRL: + case TEGRA210_DMIC_DBG_CTRL: + case TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4 ... TEGRA210_DMIC_LP_BIQUAD_1_COEF_4: + return true; + default: + return false; + }; +} + +static bool tegra210_dmic_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra210_dmic_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA210_DMIC_TX_STATUS: + case TEGRA210_DMIC_TX_INT_STATUS: + case TEGRA210_DMIC_STATUS: + case TEGRA210_DMIC_INT_STATUS: + return true; + default: + return false; + }; +} + +static bool tegra210_dmic_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_DMIC_TX_STATUS: + case TEGRA210_DMIC_TX_INT_STATUS: + case TEGRA210_DMIC_TX_INT_SET: + case TEGRA210_DMIC_SOFT_RESET: + case TEGRA210_DMIC_STATUS: + case TEGRA210_DMIC_INT_STATUS: + return true; + default: + return false; + }; +} + +static const struct regmap_config tegra210_dmic_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, + .writeable_reg = tegra210_dmic_wr_reg, + .readable_reg = tegra210_dmic_rd_reg, + .volatile_reg = tegra210_dmic_volatile_reg, + .reg_defaults = tegra210_dmic_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra210_dmic_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static int tegra210_dmic_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra210_dmic *dmic; + void __iomem *regs; + int err; + + dmic = devm_kzalloc(dev, sizeof(*dmic), GFP_KERNEL); + if (!dmic) + return -ENOMEM; + + dmic->osr_val = DMIC_OSR_64; + dmic->ch_select = DMIC_CH_SELECT_STEREO; + dmic->lrsel = DMIC_LRSEL_LEFT; + dmic->boost_gain = 0; + dmic->stereo_to_mono = 0; /* "CH0" */ + + dev_set_drvdata(dev, dmic); + + dmic->clk_dmic = devm_clk_get(dev, "dmic"); + if (IS_ERR(dmic->clk_dmic)) { + dev_err(dev, "can't retrieve DMIC clock\n"); + return PTR_ERR(dmic->clk_dmic); + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + dmic->regmap = devm_regmap_init_mmio(dev, regs, + &tegra210_dmic_regmap_config); + if (IS_ERR(dmic->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(dmic->regmap); + } + + regcache_cache_only(dmic->regmap, true); + + err = devm_snd_soc_register_component(dev, &tegra210_dmic_compnt, + tegra210_dmic_dais, + ARRAY_SIZE(tegra210_dmic_dais)); + if (err) { + dev_err(dev, "can't register DMIC component, err: %d\n", err); + return err; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int tegra210_dmic_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra210_dmic_pm_ops = { + SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend, + tegra210_dmic_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id tegra210_dmic_of_match[] = { + { .compatible = "nvidia,tegra210-dmic" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra210_dmic_of_match); + +static struct platform_driver tegra210_dmic_driver = { + .driver = { + .name = "tegra210-dmic", + .of_match_table = tegra210_dmic_of_match, + .pm = &tegra210_dmic_pm_ops, + }, + .probe = tegra210_dmic_probe, + .remove = tegra210_dmic_remove, +}; +module_platform_driver(tegra210_dmic_driver) + +MODULE_AUTHOR("Rahul Mittal <rmittal@nvidia.com>"); +MODULE_DESCRIPTION("Tegra210 ASoC DMIC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_dmic.h b/sound/soc/tegra/tegra210_dmic.h new file mode 100644 index 000000000000..6418c223b1c8 --- /dev/null +++ b/sound/soc/tegra/tegra210_dmic.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_dmic.h - Definitions for Tegra210 DMIC driver + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_DMIC_H__ +#define __TEGRA210_DMIC_H__ + +/* Register offsets from DMIC BASE */ +#define TEGRA210_DMIC_TX_STATUS 0x0c +#define TEGRA210_DMIC_TX_INT_STATUS 0x10 +#define TEGRA210_DMIC_TX_INT_MASK 0x14 +#define TEGRA210_DMIC_TX_INT_SET 0x18 +#define TEGRA210_DMIC_TX_INT_CLEAR 0x1c +#define TEGRA210_DMIC_TX_CIF_CTRL 0x20 +#define TEGRA210_DMIC_ENABLE 0x40 +#define TEGRA210_DMIC_SOFT_RESET 0x44 +#define TEGRA210_DMIC_CG 0x48 +#define TEGRA210_DMIC_STATUS 0x4c +#define TEGRA210_DMIC_INT_STATUS 0x50 +#define TEGRA210_DMIC_CTRL 0x64 +#define TEGRA210_DMIC_DBG_CTRL 0x70 +#define TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4 0x88 +#define TEGRA210_DMIC_LP_FILTER_GAIN 0x8c +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_0 0x90 +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_1 0x94 +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_2 0x98 +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_3 0x9c +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_4 0xa0 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_0 0xa4 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_1 0xa8 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_2 0xac +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_3 0xb0 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_4 0xb4 + +/* Fields in TEGRA210_DMIC_CTRL */ +#define CH_SEL_SHIFT 8 +#define TEGRA210_DMIC_CTRL_CHANNEL_SELECT_MASK (0x3 << CH_SEL_SHIFT) +#define LRSEL_POL_SHIFT 4 +#define TEGRA210_DMIC_CTRL_LRSEL_POLARITY_MASK (0x1 << LRSEL_POL_SHIFT) +#define OSR_SHIFT 0 +#define TEGRA210_DMIC_CTRL_OSR_MASK (0x3 << OSR_SHIFT) + +#define DMIC_OSR_FACTOR 64 + +#define DEFAULT_GAIN_Q23 0x800000 + +/* Max boost gain factor used for mixer control */ +#define MAX_BOOST_GAIN 25599 + +enum tegra_dmic_ch_select { + DMIC_CH_SELECT_LEFT, + DMIC_CH_SELECT_RIGHT, + DMIC_CH_SELECT_STEREO, +}; + +enum tegra_dmic_osr { + DMIC_OSR_64, + DMIC_OSR_128, + DMIC_OSR_256, +}; + +enum tegra_dmic_lrsel { + DMIC_LRSEL_LEFT, + DMIC_LRSEL_RIGHT, +}; + +struct tegra210_dmic { + struct clk *clk_dmic; + struct regmap *regmap; + unsigned int mono_to_stereo; + unsigned int stereo_to_mono; + unsigned int boost_gain; + unsigned int ch_select; + unsigned int osr_val; + unsigned int lrsel; +}; + +#endif diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c new file mode 100644 index 000000000000..722092181583 --- /dev/null +++ b/sound/soc/tegra/tegra210_i2s.c @@ -0,0 +1,812 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_i2s.c - Tegra210 I2S driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <sound/core.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include "tegra210_i2s.h" +#include "tegra_cif.h" + +static const struct reg_default tegra210_i2s_reg_defaults[] = { + { TEGRA210_I2S_RX_INT_MASK, 0x00000003 }, + { TEGRA210_I2S_RX_CIF_CTRL, 0x00007700 }, + { TEGRA210_I2S_TX_INT_MASK, 0x00000003 }, + { TEGRA210_I2S_TX_CIF_CTRL, 0x00007700 }, + { TEGRA210_I2S_CG, 0x1 }, + { TEGRA210_I2S_TIMING, 0x0000001f }, + { TEGRA210_I2S_ENABLE, 0x1 }, + /* + * Below update does not have any effect on Tegra186 and Tegra194. + * On Tegra210, I2S4 has "i2s4a" and "i2s4b" pins and below update + * is required to select i2s4b for it to be functional for I2S + * operation. + */ + { TEGRA210_I2S_CYA, 0x1 }, +}; + +static void tegra210_i2s_set_slot_ctrl(struct regmap *regmap, + unsigned int total_slots, + unsigned int tx_slot_mask, + unsigned int rx_slot_mask) +{ + regmap_write(regmap, TEGRA210_I2S_SLOT_CTRL, total_slots - 1); + regmap_write(regmap, TEGRA210_I2S_TX_SLOT_CTRL, tx_slot_mask); + regmap_write(regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask); +} + +static int tegra210_i2s_set_clock_rate(struct device *dev, + unsigned int clock_rate) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int val; + int err; + + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); + + /* No need to set rates if I2S is being operated in slave */ + if (!(val & I2S_CTRL_MASTER_EN)) + return 0; + + err = clk_set_rate(i2s->clk_i2s, clock_rate); + if (err) { + dev_err(dev, "can't set I2S bit clock rate %u, err: %d\n", + clock_rate, err); + return err; + } + + if (!IS_ERR(i2s->clk_sync_input)) { + /* + * Other I/O modules in AHUB can use i2s bclk as reference + * clock. Below sets sync input clock rate as per bclk, + * which can be used as input to other I/O modules. + */ + err = clk_set_rate(i2s->clk_sync_input, clock_rate); + if (err) { + dev_err(dev, + "can't set I2S sync input rate %u, err = %d\n", + clock_rate, err); + return err; + } + } + + return 0; +} + +static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt, + bool is_playback) +{ + struct device *dev = compnt->dev; + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int reset_mask = I2S_SOFT_RESET_MASK; + unsigned int reset_en = I2S_SOFT_RESET_EN; + unsigned int reset_reg, cif_reg, stream_reg; + unsigned int cif_ctrl, stream_ctrl, i2s_ctrl, val; + int err; + + if (is_playback) { + reset_reg = TEGRA210_I2S_RX_SOFT_RESET; + cif_reg = TEGRA210_I2S_RX_CIF_CTRL; + stream_reg = TEGRA210_I2S_RX_CTRL; + } else { + reset_reg = TEGRA210_I2S_TX_SOFT_RESET; + cif_reg = TEGRA210_I2S_TX_CIF_CTRL; + stream_reg = TEGRA210_I2S_TX_CTRL; + } + + /* Store CIF and I2S control values */ + regmap_read(i2s->regmap, cif_reg, &cif_ctrl); + regmap_read(i2s->regmap, stream_reg, &stream_ctrl); + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &i2s_ctrl); + + /* Reset to make sure the previous transactions are clean */ + regmap_update_bits(i2s->regmap, reset_reg, reset_mask, reset_en); + + err = regmap_read_poll_timeout(i2s->regmap, reset_reg, val, + !(val & reset_mask & reset_en), + 10, 10000); + if (err) { + dev_err(dev, "timeout: failed to reset I2S for %s\n", + is_playback ? "playback" : "capture"); + return err; + } + + /* Restore CIF and I2S control values */ + regmap_write(i2s->regmap, cif_reg, cif_ctrl); + regmap_write(i2s->regmap, stream_reg, stream_ctrl); + regmap_write(i2s->regmap, TEGRA210_I2S_CTRL, i2s_ctrl); + + return 0; +} + +static int tegra210_i2s_init(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *compnt = snd_soc_dapm_to_component(w->dapm); + struct device *dev = compnt->dev; + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int val, status_reg; + bool is_playback; + int err; + + switch (w->reg) { + case TEGRA210_I2S_RX_ENABLE: + is_playback = true; + status_reg = TEGRA210_I2S_RX_STATUS; + break; + case TEGRA210_I2S_TX_ENABLE: + is_playback = false; + status_reg = TEGRA210_I2S_TX_STATUS; + break; + default: + return -EINVAL; + } + + /* Ensure I2S is in disabled state before new session */ + err = regmap_read_poll_timeout(i2s->regmap, status_reg, val, + !(val & I2S_EN_MASK & I2S_EN), + 10, 10000); + if (err) { + dev_err(dev, "timeout: previous I2S %s is still active\n", + is_playback ? "playback" : "capture"); + return err; + } + + return tegra210_i2s_sw_reset(compnt, is_playback); +} + +static int tegra210_i2s_runtime_suspend(struct device *dev) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + + regcache_cache_only(i2s->regmap, true); + regcache_mark_dirty(i2s->regmap); + + clk_disable_unprepare(i2s->clk_i2s); + + return 0; +} + +static int tegra210_i2s_runtime_resume(struct device *dev) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(i2s->clk_i2s); + if (err) { + dev_err(dev, "failed to enable I2S bit clock, err: %d\n", err); + return err; + } + + regcache_cache_only(i2s->regmap, false); + regcache_sync(i2s->regmap); + + return 0; +} + +static void tegra210_i2s_set_data_offset(struct tegra210_i2s *i2s, + unsigned int data_offset) +{ + /* Capture path */ + regmap_update_bits(i2s->regmap, TEGRA210_I2S_TX_CTRL, + I2S_CTRL_DATA_OFFSET_MASK, + data_offset << I2S_DATA_SHIFT); + + /* Playback path */ + regmap_update_bits(i2s->regmap, TEGRA210_I2S_RX_CTRL, + I2S_CTRL_DATA_OFFSET_MASK, + data_offset << I2S_DATA_SHIFT); +} + +static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt) +{ + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; + + mask = I2S_CTRL_MASTER_EN_MASK; + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + val = 0; + break; + case SND_SOC_DAIFMT_CBM_CFM: + val = I2S_CTRL_MASTER_EN; + break; + default: + return -EINVAL; + } + + mask |= I2S_CTRL_FRAME_FMT_MASK | I2S_CTRL_LRCK_POL_MASK; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + tegra210_i2s_set_data_offset(i2s, 1); + break; + case SND_SOC_DAIFMT_DSP_B: + val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + tegra210_i2s_set_data_offset(i2s, 0); + break; + /* I2S mode has data offset of 1 */ + case SND_SOC_DAIFMT_I2S: + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; + val |= I2S_CTRL_LRCK_POL_LOW; + tegra210_i2s_set_data_offset(i2s, 1); + break; + /* + * For RJ mode data offset is dependent on the sample size + * and the bclk ratio, and so is set when hw_params is called. + */ + case SND_SOC_DAIFMT_RIGHT_J: + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + break; + case SND_SOC_DAIFMT_LEFT_J: + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + tegra210_i2s_set_data_offset(i2s, 0); + break; + default: + return -EINVAL; + } + + mask |= I2S_CTRL_EDGE_CTRL_MASK; + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + val |= I2S_CTRL_EDGE_CTRL_POS_EDGE; + break; + case SND_SOC_DAIFMT_NB_IF: + val |= I2S_CTRL_EDGE_CTRL_POS_EDGE; + val ^= I2S_CTRL_LRCK_POL_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE; + break; + case SND_SOC_DAIFMT_IB_IF: + val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE; + val ^= I2S_CTRL_LRCK_POL_MASK; + break; + default: + return -EINVAL; + } + + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val); + + i2s->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + + return 0; +} + +static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + + /* Copy the required tx and rx mask */ + i2s->tx_mask = (tx_mask > DEFAULT_I2S_SLOT_MASK) ? + DEFAULT_I2S_SLOT_MASK : tx_mask; + i2s->rx_mask = (rx_mask > DEFAULT_I2S_SLOT_MASK) ? + DEFAULT_I2S_SLOT_MASK : rx_mask; + + return 0; +} + +static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, + unsigned int ratio) +{ + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + + i2s->bclk_ratio = ratio; + + return 0; +} + +static int tegra210_i2s_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); + long *uctl_val = &ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Loopback")) + *uctl_val = i2s->loopback; + else if (strstr(kcontrol->id.name, "FSYNC Width")) + *uctl_val = i2s->fsync_width; + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) + *uctl_val = i2s->stereo_to_mono[I2S_TX_PATH]; + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) + *uctl_val = i2s->mono_to_stereo[I2S_TX_PATH]; + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) + *uctl_val = i2s->stereo_to_mono[I2S_RX_PATH]; + else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) + *uctl_val = i2s->mono_to_stereo[I2S_RX_PATH]; + else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) + *uctl_val = i2s->rx_fifo_th; + else if (strstr(kcontrol->id.name, "BCLK Ratio")) + *uctl_val = i2s->bclk_ratio; + + return 0; +} + +static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); + int value = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Loopback")) { + i2s->loopback = value; + + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, + I2S_CTRL_LPBK_MASK, + i2s->loopback << I2S_CTRL_LPBK_SHIFT); + + } else if (strstr(kcontrol->id.name, "FSYNC Width")) { + /* + * Frame sync width is used only for FSYNC modes and not + * applicable for LRCK modes. Reset value for this field is "0", + * which means the width is one bit clock wide. + * The width requirement may depend on the codec and in such + * cases mixer control is used to update custom values. A value + * of "N" here means, width is "N + 1" bit clock wide. + */ + i2s->fsync_width = value; + + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, + I2S_CTRL_FSYNC_WIDTH_MASK, + i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); + + } else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) { + i2s->stereo_to_mono[I2S_TX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) { + i2s->mono_to_stereo[I2S_TX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) { + i2s->stereo_to_mono[I2S_RX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) { + i2s->mono_to_stereo[I2S_RX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) { + i2s->rx_fifo_th = value; + } else if (strstr(kcontrol->id.name, "BCLK Ratio")) { + i2s->bclk_ratio = value; + } + + return 0; +} + +static int tegra210_i2s_set_timing_params(struct device *dev, + unsigned int sample_size, + unsigned int srate, + unsigned int channels) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int val, bit_count, bclk_rate, num_bclk = sample_size; + int err; + + if (i2s->bclk_ratio) + num_bclk *= i2s->bclk_ratio; + + if (i2s->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) + tegra210_i2s_set_data_offset(i2s, num_bclk - sample_size); + + /* I2S bit clock rate */ + bclk_rate = srate * channels * num_bclk; + + err = tegra210_i2s_set_clock_rate(dev, bclk_rate); + if (err) { + dev_err(dev, "can't set I2S bit clock rate %u, err: %d\n", + bclk_rate, err); + return err; + } + + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); + + /* + * For LRCK mode, channel bit count depends on number of bit clocks + * on the left channel, where as for FSYNC mode bit count depends on + * the number of bit clocks in both left and right channels for DSP + * mode or the number of bit clocks in one TDM frame. + * + */ + switch (val & I2S_CTRL_FRAME_FMT_MASK) { + case I2S_CTRL_FRAME_FMT_LRCK_MODE: + bit_count = (bclk_rate / (srate * 2)) - 1; + break; + case I2S_CTRL_FRAME_FMT_FSYNC_MODE: + bit_count = (bclk_rate / srate) - 1; + + tegra210_i2s_set_slot_ctrl(i2s->regmap, channels, + i2s->tx_mask, i2s->rx_mask); + break; + default: + dev_err(dev, "invalid I2S frame format\n"); + return -EINVAL; + } + + if (bit_count > I2S_TIMING_CH_BIT_CNT_MASK) { + dev_err(dev, "invalid I2S channel bit count %u\n", bit_count); + return -EINVAL; + } + + regmap_write(i2s->regmap, TEGRA210_I2S_TIMING, + bit_count << I2S_TIMING_CH_BIT_CNT_SHIFT); + + return 0; +} + +static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->dev; + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int sample_size, channels, srate, val, reg, path; + struct tegra_cif_conf cif_conf; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + channels = params_channels(params); + if (channels < 1) { + dev_err(dev, "invalid I2S %d channel configuration\n", + channels); + return -EINVAL; + } + + cif_conf.audio_ch = channels; + cif_conf.client_ch = channels; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + val = I2S_BITS_8; + sample_size = 8; + cif_conf.audio_bits = TEGRA_ACIF_BITS_8; + cif_conf.client_bits = TEGRA_ACIF_BITS_8; + break; + case SNDRV_PCM_FORMAT_S16_LE: + val = I2S_BITS_16; + sample_size = 16; + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + cif_conf.client_bits = TEGRA_ACIF_BITS_16; + break; + case SNDRV_PCM_FORMAT_S32_LE: + val = I2S_BITS_32; + sample_size = 32; + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + cif_conf.client_bits = TEGRA_ACIF_BITS_32; + break; + default: + dev_err(dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + /* Program sample size */ + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, + I2S_CTRL_BIT_SIZE_MASK, val); + + srate = params_rate(params); + + /* For playback I2S RX-CIF and for capture TX-CIF is used */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + path = I2S_RX_PATH; + else + path = I2S_TX_PATH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + unsigned int max_th; + + /* FIFO threshold in terms of frames */ + max_th = (I2S_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1; + + if (i2s->rx_fifo_th > max_th) + i2s->rx_fifo_th = max_th; + + cif_conf.threshold = i2s->rx_fifo_th; + + reg = TEGRA210_I2S_RX_CIF_CTRL; + } else { + reg = TEGRA210_I2S_TX_CIF_CTRL; + } + + cif_conf.mono_conv = i2s->mono_to_stereo[path]; + cif_conf.stereo_conv = i2s->stereo_to_mono[path]; + + tegra_set_cif(i2s->regmap, reg, &cif_conf); + + return tegra210_i2s_set_timing_params(dev, sample_size, srate, + cif_conf.client_ch); +} + +static const struct snd_soc_dai_ops tegra210_i2s_dai_ops = { + .set_fmt = tegra210_i2s_set_fmt, + .hw_params = tegra210_i2s_hw_params, + .set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio, + .set_tdm_slot = tegra210_i2s_set_tdm_slot, +}; + +static struct snd_soc_dai_driver tegra210_i2s_dais[] = { + { + .name = "I2S-CIF", + .playback = { + .stream_name = "CIF-Playback", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "CIF-Capture", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + }, + { + .name = "I2S-DAP", + .playback = { + .stream_name = "DAP-Playback", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "DAP-Capture", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tegra210_i2s_dai_ops, + .symmetric_rates = 1, + }, +}; + +static const char * const tegra210_i2s_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const char * const tegra210_i2s_mono_conv_text[] = { + "Zero", "Copy", +}; + +static const struct soc_enum tegra210_i2s_mono_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_mono_conv_text), + tegra210_i2s_mono_conv_text); + +static const struct soc_enum tegra210_i2s_stereo_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_stereo_conv_text), + tegra210_i2s_stereo_conv_text); + +static const struct snd_kcontrol_new tegra210_i2s_controls[] = { + SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_control, + tegra210_i2s_put_control), + SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, tegra210_i2s_get_control, + tegra210_i2s_put_control), + SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1, + 0, tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, tegra210_i2s_get_control, + tegra210_i2s_put_control), +}; + +static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = { + SND_SOC_DAPM_AIF_IN_E("RX", NULL, 0, TEGRA210_I2S_RX_ENABLE, + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, TEGRA210_I2S_TX_ENABLE, + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MIC("MIC", NULL), + SND_SOC_DAPM_SPK("SPK", NULL), +}; + +static const struct snd_soc_dapm_route tegra210_i2s_routes[] = { + /* Playback route from XBAR */ + { "XBAR-Playback", NULL, "XBAR-TX" }, + { "CIF-Playback", NULL, "XBAR-Playback" }, + { "RX", NULL, "CIF-Playback" }, + { "DAP-Playback", NULL, "RX" }, + { "SPK", NULL, "DAP-Playback" }, + /* Capture route to XBAR */ + { "XBAR-RX", NULL, "XBAR-Capture" }, + { "XBAR-Capture", NULL, "CIF-Capture" }, + { "CIF-Capture", NULL, "TX" }, + { "TX", NULL, "DAP-Capture" }, + { "DAP-Capture", NULL, "MIC" }, +}; + +static const struct snd_soc_component_driver tegra210_i2s_cmpnt = { + .dapm_widgets = tegra210_i2s_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra210_i2s_widgets), + .dapm_routes = tegra210_i2s_routes, + .num_dapm_routes = ARRAY_SIZE(tegra210_i2s_routes), + .controls = tegra210_i2s_controls, + .num_controls = ARRAY_SIZE(tegra210_i2s_controls), + .non_legacy_dai_naming = 1, +}; + +static bool tegra210_i2s_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_I2S_RX_ENABLE ... TEGRA210_I2S_RX_SOFT_RESET: + case TEGRA210_I2S_RX_INT_MASK ... TEGRA210_I2S_RX_CLK_TRIM: + case TEGRA210_I2S_TX_ENABLE ... TEGRA210_I2S_TX_SOFT_RESET: + case TEGRA210_I2S_TX_INT_MASK ... TEGRA210_I2S_TX_CLK_TRIM: + case TEGRA210_I2S_ENABLE ... TEGRA210_I2S_CG: + case TEGRA210_I2S_CTRL ... TEGRA210_I2S_CYA: + return true; + default: + return false; + }; +} + +static bool tegra210_i2s_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra210_i2s_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA210_I2S_RX_STATUS: + case TEGRA210_I2S_RX_INT_STATUS: + case TEGRA210_I2S_RX_CIF_FIFO_STATUS: + case TEGRA210_I2S_TX_STATUS: + case TEGRA210_I2S_TX_INT_STATUS: + case TEGRA210_I2S_TX_CIF_FIFO_STATUS: + case TEGRA210_I2S_STATUS: + case TEGRA210_I2S_INT_STATUS: + return true; + default: + return false; + }; +} + +static bool tegra210_i2s_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_I2S_RX_STATUS: + case TEGRA210_I2S_RX_INT_STATUS: + case TEGRA210_I2S_RX_CIF_FIFO_STATUS: + case TEGRA210_I2S_TX_STATUS: + case TEGRA210_I2S_TX_INT_STATUS: + case TEGRA210_I2S_TX_CIF_FIFO_STATUS: + case TEGRA210_I2S_STATUS: + case TEGRA210_I2S_INT_STATUS: + case TEGRA210_I2S_RX_SOFT_RESET: + case TEGRA210_I2S_TX_SOFT_RESET: + return true; + default: + return false; + }; +} + +static const struct regmap_config tegra210_i2s_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_I2S_CYA, + .writeable_reg = tegra210_i2s_wr_reg, + .readable_reg = tegra210_i2s_rd_reg, + .volatile_reg = tegra210_i2s_volatile_reg, + .reg_defaults = tegra210_i2s_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra210_i2s_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static int tegra210_i2s_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra210_i2s *i2s; + void __iomem *regs; + int err; + + i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); + if (!i2s) + return -ENOMEM; + + i2s->rx_fifo_th = DEFAULT_I2S_RX_FIFO_THRESHOLD; + i2s->tx_mask = DEFAULT_I2S_SLOT_MASK; + i2s->rx_mask = DEFAULT_I2S_SLOT_MASK; + i2s->loopback = false; + + dev_set_drvdata(dev, i2s); + + i2s->clk_i2s = devm_clk_get(dev, "i2s"); + if (IS_ERR(i2s->clk_i2s)) { + dev_err(dev, "can't retrieve I2S bit clock\n"); + return PTR_ERR(i2s->clk_i2s); + } + + /* + * Not an error, as this clock is needed only when some other I/O + * requires input clock from current I2S instance, which is + * configurable from DT. + */ + i2s->clk_sync_input = devm_clk_get(dev, "sync_input"); + if (IS_ERR(i2s->clk_sync_input)) + dev_dbg(dev, "can't retrieve I2S sync input clock\n"); + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + i2s->regmap = devm_regmap_init_mmio(dev, regs, + &tegra210_i2s_regmap_config); + if (IS_ERR(i2s->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(i2s->regmap); + } + + regcache_cache_only(i2s->regmap, true); + + err = devm_snd_soc_register_component(dev, &tegra210_i2s_cmpnt, + tegra210_i2s_dais, + ARRAY_SIZE(tegra210_i2s_dais)); + if (err) { + dev_err(dev, "can't register I2S component, err: %d\n", err); + return err; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int tegra210_i2s_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra210_i2s_pm_ops = { + SET_RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend, + tegra210_i2s_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id tegra210_i2s_of_match[] = { + { .compatible = "nvidia,tegra210-i2s" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra210_i2s_of_match); + +static struct platform_driver tegra210_i2s_driver = { + .driver = { + .name = "tegra210-i2s", + .of_match_table = tegra210_i2s_of_match, + .pm = &tegra210_i2s_pm_ops, + }, + .probe = tegra210_i2s_probe, + .remove = tegra210_i2s_remove, +}; +module_platform_driver(tegra210_i2s_driver) + +MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>"); +MODULE_DESCRIPTION("Tegra210 ASoC I2S driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h new file mode 100644 index 000000000000..030d70c45e18 --- /dev/null +++ b/sound/soc/tegra/tegra210_i2s.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_i2s.h - Definitions for Tegra210 I2S driver + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_I2S_H__ +#define __TEGRA210_I2S_H__ + +/* Register offsets from I2S*_BASE */ +#define TEGRA210_I2S_RX_ENABLE 0x0 +#define TEGRA210_I2S_RX_SOFT_RESET 0x4 +#define TEGRA210_I2S_RX_STATUS 0x0c +#define TEGRA210_I2S_RX_INT_STATUS 0x10 +#define TEGRA210_I2S_RX_INT_MASK 0x14 +#define TEGRA210_I2S_RX_INT_SET 0x18 +#define TEGRA210_I2S_RX_INT_CLEAR 0x1c +#define TEGRA210_I2S_RX_CIF_CTRL 0x20 +#define TEGRA210_I2S_RX_CTRL 0x24 +#define TEGRA210_I2S_RX_SLOT_CTRL 0x28 +#define TEGRA210_I2S_RX_CLK_TRIM 0x2c +#define TEGRA210_I2S_RX_CYA 0x30 +#define TEGRA210_I2S_RX_CIF_FIFO_STATUS 0x34 +#define TEGRA210_I2S_TX_ENABLE 0x40 +#define TEGRA210_I2S_TX_SOFT_RESET 0x44 +#define TEGRA210_I2S_TX_STATUS 0x4c +#define TEGRA210_I2S_TX_INT_STATUS 0x50 +#define TEGRA210_I2S_TX_INT_MASK 0x54 +#define TEGRA210_I2S_TX_INT_SET 0x58 +#define TEGRA210_I2S_TX_INT_CLEAR 0x5c +#define TEGRA210_I2S_TX_CIF_CTRL 0x60 +#define TEGRA210_I2S_TX_CTRL 0x64 +#define TEGRA210_I2S_TX_SLOT_CTRL 0x68 +#define TEGRA210_I2S_TX_CLK_TRIM 0x6c +#define TEGRA210_I2S_TX_CYA 0x70 +#define TEGRA210_I2S_TX_CIF_FIFO_STATUS 0x74 +#define TEGRA210_I2S_ENABLE 0x80 +#define TEGRA210_I2S_SOFT_RESET 0x84 +#define TEGRA210_I2S_CG 0x88 +#define TEGRA210_I2S_STATUS 0x8c +#define TEGRA210_I2S_INT_STATUS 0x90 +#define TEGRA210_I2S_CTRL 0xa0 +#define TEGRA210_I2S_TIMING 0xa4 +#define TEGRA210_I2S_SLOT_CTRL 0xa8 +#define TEGRA210_I2S_CLK_TRIM 0xac +#define TEGRA210_I2S_CYA 0xb0 + +/* Bit fields, shifts and masks */ +#define I2S_DATA_SHIFT 8 +#define I2S_CTRL_DATA_OFFSET_MASK (0x7ff << I2S_DATA_SHIFT) + +#define I2S_EN_SHIFT 0 +#define I2S_EN_MASK BIT(I2S_EN_SHIFT) +#define I2S_EN BIT(I2S_EN_SHIFT) + +#define I2S_FSYNC_WIDTH_SHIFT 24 +#define I2S_CTRL_FSYNC_WIDTH_MASK (0xff << I2S_FSYNC_WIDTH_SHIFT) + +#define I2S_POS_EDGE 0 +#define I2S_NEG_EDGE 1 +#define I2S_EDGE_SHIFT 20 +#define I2S_CTRL_EDGE_CTRL_MASK BIT(I2S_EDGE_SHIFT) +#define I2S_CTRL_EDGE_CTRL_POS_EDGE (I2S_POS_EDGE << I2S_EDGE_SHIFT) +#define I2S_CTRL_EDGE_CTRL_NEG_EDGE (I2S_NEG_EDGE << I2S_EDGE_SHIFT) + +#define I2S_FMT_LRCK 0 +#define I2S_FMT_FSYNC 1 +#define I2S_FMT_SHIFT 12 +#define I2S_CTRL_FRAME_FMT_MASK (7 << I2S_FMT_SHIFT) +#define I2S_CTRL_FRAME_FMT_LRCK_MODE (I2S_FMT_LRCK << I2S_FMT_SHIFT) +#define I2S_CTRL_FRAME_FMT_FSYNC_MODE (I2S_FMT_FSYNC << I2S_FMT_SHIFT) + +#define I2S_CTRL_MASTER_EN_SHIFT 10 +#define I2S_CTRL_MASTER_EN_MASK BIT(I2S_CTRL_MASTER_EN_SHIFT) +#define I2S_CTRL_MASTER_EN BIT(I2S_CTRL_MASTER_EN_SHIFT) + +#define I2S_CTRL_LRCK_POL_SHIFT 9 +#define I2S_CTRL_LRCK_POL_MASK BIT(I2S_CTRL_LRCK_POL_SHIFT) +#define I2S_CTRL_LRCK_POL_LOW (0 << I2S_CTRL_LRCK_POL_SHIFT) +#define I2S_CTRL_LRCK_POL_HIGH BIT(I2S_CTRL_LRCK_POL_SHIFT) + +#define I2S_CTRL_LPBK_SHIFT 8 +#define I2S_CTRL_LPBK_MASK BIT(I2S_CTRL_LPBK_SHIFT) +#define I2S_CTRL_LPBK_EN BIT(I2S_CTRL_LPBK_SHIFT) + +#define I2S_BITS_8 1 +#define I2S_BITS_16 3 +#define I2S_BITS_32 7 +#define I2S_CTRL_BIT_SIZE_MASK 0x7 + +#define I2S_TIMING_CH_BIT_CNT_MASK 0x7ff +#define I2S_TIMING_CH_BIT_CNT_SHIFT 0 + +#define I2S_SOFT_RESET_SHIFT 0 +#define I2S_SOFT_RESET_MASK BIT(I2S_SOFT_RESET_SHIFT) +#define I2S_SOFT_RESET_EN BIT(I2S_SOFT_RESET_SHIFT) + +#define I2S_RX_FIFO_DEPTH 64 +#define DEFAULT_I2S_RX_FIFO_THRESHOLD 3 + +#define DEFAULT_I2S_SLOT_MASK 0xffff + +enum tegra210_i2s_path { + I2S_RX_PATH, + I2S_TX_PATH, + I2S_PATHS, +}; + +struct tegra210_i2s { + struct clk *clk_i2s; + struct clk *clk_sync_input; + struct regmap *regmap; + unsigned int stereo_to_mono[I2S_PATHS]; + unsigned int mono_to_stereo[I2S_PATHS]; + unsigned int dai_fmt; + unsigned int fsync_width; + unsigned int bclk_ratio; + unsigned int tx_mask; + unsigned int rx_mask; + unsigned int rx_fifo_th; + bool loopback; +}; + +#endif diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 635eacbd28d4..156e3b9d613c 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -643,8 +643,10 @@ static int tegra30_ahub_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put(dev); return ret; + } ret = regcache_sync(ahub->regmap_ahub); ret |= regcache_sync(ahub->regmap_apbif); pm_runtime_put(dev); diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index d59882ec48f1..db5a8587bfa4 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -567,8 +567,10 @@ static int tegra30_i2s_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put(dev); return ret; + } ret = regcache_sync(i2s->regmap); pm_runtime_put(dev); diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 2839c6cb8c38..8661877bf4c6 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -36,7 +36,7 @@ struct tegra_alc5632 { static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_cif.h b/sound/soc/tegra/tegra_cif.h new file mode 100644 index 000000000000..7cca8068f4b5 --- /dev/null +++ b/sound/soc/tegra/tegra_cif.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra_cif.h - TEGRA Audio CIF Programming + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA_CIF_H__ +#define __TEGRA_CIF_H__ + +#include <linux/regmap.h> + +#define TEGRA_ACIF_CTRL_FIFO_TH_SHIFT 24 +#define TEGRA_ACIF_CTRL_AUDIO_CH_SHIFT 20 +#define TEGRA_ACIF_CTRL_CLIENT_CH_SHIFT 16 +#define TEGRA_ACIF_CTRL_AUDIO_BITS_SHIFT 12 +#define TEGRA_ACIF_CTRL_CLIENT_BITS_SHIFT 8 +#define TEGRA_ACIF_CTRL_EXPAND_SHIFT 6 +#define TEGRA_ACIF_CTRL_STEREO_CONV_SHIFT 4 +#define TEGRA_ACIF_CTRL_REPLICATE_SHIFT 3 +#define TEGRA_ACIF_CTRL_TRUNCATE_SHIFT 1 +#define TEGRA_ACIF_CTRL_MONO_CONV_SHIFT 0 + +/* AUDIO/CLIENT_BITS values */ +#define TEGRA_ACIF_BITS_8 1 +#define TEGRA_ACIF_BITS_16 3 +#define TEGRA_ACIF_BITS_24 5 +#define TEGRA_ACIF_BITS_32 7 + +#define TEGRA_ACIF_UPDATE_MASK 0x3ffffffb + +struct tegra_cif_conf { + unsigned int threshold; + unsigned int audio_ch; + unsigned int client_ch; + unsigned int audio_bits; + unsigned int client_bits; + unsigned int expand; + unsigned int stereo_conv; + unsigned int replicate; + unsigned int truncate; + unsigned int mono_conv; +}; + +static inline void tegra_set_cif(struct regmap *regmap, unsigned int reg, + struct tegra_cif_conf *conf) +{ + unsigned int value; + + value = (conf->threshold << TEGRA_ACIF_CTRL_FIFO_TH_SHIFT) | + ((conf->audio_ch - 1) << TEGRA_ACIF_CTRL_AUDIO_CH_SHIFT) | + ((conf->client_ch - 1) << TEGRA_ACIF_CTRL_CLIENT_CH_SHIFT) | + (conf->audio_bits << TEGRA_ACIF_CTRL_AUDIO_BITS_SHIFT) | + (conf->client_bits << TEGRA_ACIF_CTRL_CLIENT_BITS_SHIFT) | + (conf->expand << TEGRA_ACIF_CTRL_EXPAND_SHIFT) | + (conf->stereo_conv << TEGRA_ACIF_CTRL_STEREO_CONV_SHIFT) | + (conf->replicate << TEGRA_ACIF_CTRL_REPLICATE_SHIFT) | + (conf->truncate << TEGRA_ACIF_CTRL_TRUNCATE_SHIFT) | + (conf->mono_conv << TEGRA_ACIF_CTRL_MONO_CONV_SHIFT); + + regmap_update_bits(regmap, reg, TEGRA_ACIF_UPDATE_MASK, value); +} + +#endif diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index ec9050516cd7..af3e9e6daa40 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -37,7 +37,7 @@ struct tegra_max98090 { static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index f246df8ecf7b..b3f36515cbc1 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -16,12 +16,12 @@ */ #include <linux/module.h> +#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/dmaengine_pcm.h> - #include "tegra_pcm.h" static const struct snd_pcm_hardware tegra_pcm_hardware = { @@ -67,6 +67,239 @@ void tegra_pcm_platform_unregister(struct device *dev) } EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister); +int tegra_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_dmaengine_dai_dma_data *dmap; + struct dma_chan *chan; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + int ret; + + if (rtd->dai_link->no_pcm) + return 0; + + dmap = snd_soc_dai_get_dma_data(cpu_dai, substream); + + /* Set HW params now that initialization is complete */ + snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); + + /* Ensure period size is multiple of 8 */ + ret = snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8); + if (ret) { + dev_err(rtd->dev, "failed to set constraint %d\n", ret); + return ret; + } + + chan = dma_request_slave_channel(cpu_dai->dev, dmap->chan_name); + if (!chan) { + dev_err(cpu_dai->dev, + "dmaengine request slave channel failed! (%s)\n", + dmap->chan_name); + return -ENODEV; + } + + ret = snd_dmaengine_pcm_open(substream, chan); + if (ret) { + dev_err(rtd->dev, + "dmaengine pcm open failed with err %d (%s)\n", ret, + dmap->chan_name); + + dma_release_channel(chan); + + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_open); + +int tegra_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + if (rtd->dai_link->no_pcm) + return 0; + + snd_dmaengine_pcm_close_release_chan(substream); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_close); + +int tegra_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_dmaengine_dai_dma_data *dmap; + struct dma_slave_config slave_config; + struct dma_chan *chan; + int ret; + + if (rtd->dai_link->no_pcm) + return 0; + + dmap = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); + if (!dmap) + return 0; + + chan = snd_dmaengine_pcm_get_chan(substream); + + ret = snd_hwparams_to_dma_slave_config(substream, params, + &slave_config); + if (ret) { + dev_err(rtd->dev, "hw params config failed with err %d\n", ret); + return ret; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.dst_addr = dmap->addr; + slave_config.dst_maxburst = 8; + } else { + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.src_addr = dmap->addr; + slave_config.src_maxburst = 8; + } + + ret = dmaengine_slave_config(chan, &slave_config); + if (ret < 0) { + dev_err(rtd->dev, "dma slave config failed with err %d\n", ret); + return ret; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_hw_params); + +int tegra_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + if (rtd->dai_link->no_pcm) + return 0; + + snd_pcm_set_runtime_buffer(substream, NULL); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_hw_free); + +int tegra_pcm_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + + if (rtd->dai_link->no_pcm) + return 0; + + return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area, + runtime->dma_addr, runtime->dma_bytes); +} +EXPORT_SYMBOL_GPL(tegra_pcm_mmap); + +snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + return snd_dmaengine_pcm_pointer(substream); +} +EXPORT_SYMBOL_GPL(tegra_pcm_pointer); + +static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, + size_t size) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + + buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + + buf->private_data = NULL; + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->bytes = size; + + return 0; +} + +static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + + substream = pcm->streams[stream].substream; + if (!substream) + return; + + buf = &substream->dma_buffer; + if (!buf->area) + return; + + dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr); + buf->area = NULL; +} + +static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd, + size_t size) +{ + struct snd_card *card = rtd->card->snd_card; + struct snd_pcm *pcm = rtd->pcm; + int ret; + + ret = dma_set_mask(card->dev, DMA_BIT_MASK(32)); + if (ret < 0) + return ret; + + ret = dma_set_coherent_mask(card->dev, DMA_BIT_MASK(32)); + if (ret < 0) + return ret; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + ret = tegra_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK, size); + if (ret) + goto err; + } + + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ret = tegra_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE, size); + if (ret) + goto err_free_play; + } + + return 0; + +err_free_play: + tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); +err: + return ret; +} + +int tegra_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + return tegra_pcm_dma_allocate(rtd, tegra_pcm_hardware.buffer_bytes_max); +} +EXPORT_SYMBOL_GPL(tegra_pcm_construct); + +void tegra_pcm_destruct(struct snd_soc_component *component, + struct snd_pcm *pcm) +{ + tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); + tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); +} +EXPORT_SYMBOL_GPL(tegra_pcm_destruct); + MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); MODULE_DESCRIPTION("Tegra PCM ASoC driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h index 0433372e68d4..4838cdcee20e 100644 --- a/sound/soc/tegra/tegra_pcm.h +++ b/sound/soc/tegra/tegra_pcm.h @@ -17,8 +17,27 @@ #ifndef __TEGRA_PCM_H__ #define __TEGRA_PCM_H__ -struct snd_dmaengine_pcm_config; +#include <sound/dmaengine_pcm.h> +#include <sound/asound.h> +int tegra_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd); +void tegra_pcm_destruct(struct snd_soc_component *component, + struct snd_pcm *pcm); +int tegra_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int tegra_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int tegra_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +int tegra_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int tegra_pcm_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma); +snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream); int tegra_pcm_platform_register(struct device *dev); int tegra_pcm_platform_register_with_chan_names(struct device *dev, struct snd_dmaengine_pcm_config *config, diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 201d132731f9..d66d8659396b 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -39,7 +39,7 @@ struct tegra_rt5640 { static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c index 8f71e21f6ee9..7504507dd8b8 100644 --- a/sound/soc/tegra/tegra_rt5677.c +++ b/sound/soc/tegra/tegra_rt5677.c @@ -41,7 +41,7 @@ struct tegra_rt5677 { static int tegra_rt5677_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index 692fcc3d7d6e..e1dc8e7d337a 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -35,7 +35,7 @@ struct tegra_sgtl5000 { static int tegra_sgtl5000_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_sgtl5000 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 2ee2ed190872..ec3ee0580867 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -39,7 +39,7 @@ struct tegra_wm8753 { static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index d3ead0213cef..ef6652aaac9b 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -44,7 +44,7 @@ struct tegra_wm8903 { static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 6dca6836aa04..cdb386d6e5c3 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -34,7 +34,7 @@ struct tegra_trimslice { static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index c5408c129f34..1e6ab87e4460 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig @@ -219,5 +219,14 @@ config SND_SOC_DM365_VOICE_CODEC_MODULE The is an internal symbol needed to ensure that the codec and MFD driver can be built as loadable modules if necessary. +config SND_SOC_J721E_EVM + tristate "SoC Audio support for j721e EVM" + depends on ARCH_K3_J721E_SOC || COMPILE_TEST + depends on I2C + select SND_SOC_PCM3168A_I2C + select SND_SOC_DAVINCI_MCASP + help + Say Y if you want to add support for SoC audio on j721e Common + Processor Board and Infotainment expansion board. endmenu diff --git a/sound/soc/ti/Makefile b/sound/soc/ti/Makefile index ea48c6679cc7..a21e5b0061de 100644 --- a/sound/soc/ti/Makefile +++ b/sound/soc/ti/Makefile @@ -34,6 +34,7 @@ snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o snd-soc-ams-delta-objs := ams-delta.o snd-soc-omap-hdmi-objs := omap-hdmi.o snd-soc-osk5912-objs := osk5912.o +snd-soc-j721e-evm-objs := j721e-evm.o obj-$(CONFIG_SND_SOC_DAVINCI_EVM) += snd-soc-davinci-evm.o obj-$(CONFIG_SND_SOC_NOKIA_N810) += snd-soc-n810.o @@ -44,3 +45,4 @@ obj-$(CONFIG_SND_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o obj-$(CONFIG_SND_SOC_OMAP_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_SOC_OMAP_HDMI) += snd-soc-omap-hdmi.o obj-$(CONFIG_SND_SOC_OMAP_OSK5912) += snd-soc-osk5912.o +obj-$(CONFIG_SND_SOC_J721E_EVM) += snd-soc-j721e-evm.o diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index e17cd5e939f0..5c47de96c529 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -420,7 +420,7 @@ static struct snd_soc_ops ams_delta_ops; * Shares hardware with codec config pulse generation */ static bool ams_delta_muted = 1; -static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute) +static int ams_delta_mute(struct snd_soc_dai *dai, int mute, int direction) { int apply; @@ -439,18 +439,19 @@ static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute) /* Our codec DAI probably doesn't have its own .ops structure */ static const struct snd_soc_dai_ops ams_delta_dai_ops = { - .digital_mute = ams_delta_digital_mute, + .mute_stream = ams_delta_mute, + .no_capture_mute = 1, }; /* Will be used if the codec ever has its own digital_mute function */ static int ams_delta_startup(struct snd_pcm_substream *substream) { - return ams_delta_digital_mute(NULL, 0); + return ams_delta_digital_mute(NULL, 0, substream->stream); } static void ams_delta_shutdown(struct snd_pcm_substream *substream) { - ams_delta_digital_mute(NULL, 1); + ams_delta_digital_mute(NULL, 1, substream->stream); } diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c index 2cfbeebdfb41..105e56ab9cdc 100644 --- a/sound/soc/ti/davinci-evm.c +++ b/sound/soc/ti/davinci-evm.c @@ -28,7 +28,7 @@ struct snd_soc_card_drvdata_davinci { static int evm_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *soc_card = rtd->card; struct snd_soc_card_drvdata_davinci *drvdata = snd_soc_card_get_drvdata(soc_card); @@ -41,7 +41,7 @@ static int evm_startup(struct snd_pcm_substream *substream) static void evm_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *soc_card = rtd->card; struct snd_soc_card_drvdata_davinci *drvdata = snd_soc_card_get_drvdata(soc_card); @@ -53,7 +53,7 @@ static void evm_shutdown(struct snd_pcm_substream *substream) static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_card *soc_card = rtd->card; diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index b93c1ee302c0..617440767c45 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -1623,12 +1623,14 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { .name = "davinci-mcasp.0", .probe = davinci_mcasp_dai_probe, .playback = { + .stream_name = "IIS Playback", .channels_min = 1, .channels_max = 32 * 16, .rates = DAVINCI_MCASP_RATES, .formats = DAVINCI_MCASP_PCM_FMTS, }, .capture = { + .stream_name = "IIS Capture", .channels_min = 1, .channels_max = 32 * 16, .rates = DAVINCI_MCASP_RATES, @@ -1642,6 +1644,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { .name = "davinci-mcasp.1", .probe = davinci_mcasp_dai_probe, .playback = { + .stream_name = "DIT Playback", .channels_min = 1, .channels_max = 384, .rates = DAVINCI_MCASP_RATES, diff --git a/sound/soc/ti/davinci-vcif.c b/sound/soc/ti/davinci-vcif.c index ee4d3ef821a1..f810123cc407 100644 --- a/sound/soc/ti/davinci-vcif.c +++ b/sound/soc/ti/davinci-vcif.c @@ -41,7 +41,7 @@ struct davinci_vcif_dev { static void davinci_vcif_start(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; @@ -60,7 +60,7 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream) static void davinci_vcif_stop(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c new file mode 100644 index 000000000000..cb074af47a7d --- /dev/null +++ b/sound/soc/ti/j721e-evm.c @@ -0,0 +1,896 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + */ + +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include "davinci-mcasp.h" + +/* + * Maximum number of configuration entries for prefixes: + * CPB: 2 (mcasp10 + codec) + * IVI: 3 (mcasp0 + 2x codec) + */ +#define J721E_CODEC_CONF_COUNT 5 + +#define J721E_AUDIO_DOMAIN_CPB 0 +#define J721E_AUDIO_DOMAIN_IVI 1 + +#define J721E_CLK_PARENT_48000 0 +#define J721E_CLK_PARENT_44100 1 + +#define J721E_MAX_CLK_HSDIV 128 +#define PCM1368A_MAX_SYSCLK 36864000 + +#define J721E_DAI_FMT (SND_SOC_DAIFMT_RIGHT_J | \ + SND_SOC_DAIFMT_NB_NF | \ + SND_SOC_DAIFMT_CBS_CFS) + +enum j721e_board_type { + J721E_BOARD_CPB = 1, + J721E_BOARD_CPB_IVI, +}; + +struct j721e_audio_match_data { + enum j721e_board_type board_type; + int num_links; + unsigned int pll_rates[2]; +}; + +static unsigned int ratios_for_pcm3168a[] = { + 256, + 512, + 768, +}; + +struct j721e_audio_clocks { + struct clk *target; + struct clk *parent[2]; +}; + +struct j721e_audio_domain { + struct j721e_audio_clocks codec; + struct j721e_audio_clocks mcasp; + int parent_clk_id; + + int active; + unsigned int active_link; + unsigned int rate; +}; + +struct j721e_priv { + struct device *dev; + struct snd_soc_card card; + struct snd_soc_dai_link *dai_links; + struct snd_soc_codec_conf codec_conf[J721E_CODEC_CONF_COUNT]; + struct snd_interval rate_range; + const struct j721e_audio_match_data *match_data; + u32 pll_rates[2]; + unsigned int hsdiv_rates[2]; + + struct j721e_audio_domain audio_domains[2]; + + struct mutex mutex; +}; + +static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets[] = { + SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL), + SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL), + SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL), + SND_SOC_DAPM_LINE("CPB Line Out", NULL), + SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL), + SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL), + SND_SOC_DAPM_LINE("CPB Line In", NULL), +}; + +static const struct snd_soc_dapm_route j721e_cpb_dapm_routes[] = { + {"CPB Stereo HP 1", NULL, "codec-1 AOUT1L"}, + {"CPB Stereo HP 1", NULL, "codec-1 AOUT1R"}, + {"CPB Stereo HP 2", NULL, "codec-1 AOUT2L"}, + {"CPB Stereo HP 2", NULL, "codec-1 AOUT2R"}, + {"CPB Stereo HP 3", NULL, "codec-1 AOUT3L"}, + {"CPB Stereo HP 3", NULL, "codec-1 AOUT3R"}, + {"CPB Line Out", NULL, "codec-1 AOUT4L"}, + {"CPB Line Out", NULL, "codec-1 AOUT4R"}, + + {"codec-1 AIN1L", NULL, "CPB Stereo Mic 1"}, + {"codec-1 AIN1R", NULL, "CPB Stereo Mic 1"}, + {"codec-1 AIN2L", NULL, "CPB Stereo Mic 2"}, + {"codec-1 AIN2R", NULL, "CPB Stereo Mic 2"}, + {"codec-1 AIN3L", NULL, "CPB Line In"}, + {"codec-1 AIN3R", NULL, "CPB Line In"}, +}; + +static const struct snd_soc_dapm_widget j721e_ivi_codec_a_dapm_widgets[] = { + SND_SOC_DAPM_LINE("IVI A Line Out 1", NULL), + SND_SOC_DAPM_LINE("IVI A Line Out 2", NULL), + SND_SOC_DAPM_LINE("IVI A Line Out 3", NULL), + SND_SOC_DAPM_LINE("IVI A Line Out 4", NULL), + SND_SOC_DAPM_MIC("IVI A Stereo Mic 1", NULL), + SND_SOC_DAPM_MIC("IVI A Stereo Mic 2", NULL), + SND_SOC_DAPM_LINE("IVI A Line In", NULL), +}; + +static const struct snd_soc_dapm_route j721e_codec_a_dapm_routes[] = { + {"IVI A Line Out 1", NULL, "codec-a AOUT1L"}, + {"IVI A Line Out 1", NULL, "codec-a AOUT1R"}, + {"IVI A Line Out 2", NULL, "codec-a AOUT2L"}, + {"IVI A Line Out 2", NULL, "codec-a AOUT2R"}, + {"IVI A Line Out 3", NULL, "codec-a AOUT3L"}, + {"IVI A Line Out 3", NULL, "codec-a AOUT3R"}, + {"IVI A Line Out 4", NULL, "codec-a AOUT4L"}, + {"IVI A Line Out 4", NULL, "codec-a AOUT4R"}, + + {"codec-a AIN1L", NULL, "IVI A Stereo Mic 1"}, + {"codec-a AIN1R", NULL, "IVI A Stereo Mic 1"}, + {"codec-a AIN2L", NULL, "IVI A Stereo Mic 2"}, + {"codec-a AIN2R", NULL, "IVI A Stereo Mic 2"}, + {"codec-a AIN3L", NULL, "IVI A Line In"}, + {"codec-a AIN3R", NULL, "IVI A Line In"}, +}; + +static const struct snd_soc_dapm_widget j721e_ivi_codec_b_dapm_widgets[] = { + SND_SOC_DAPM_LINE("IVI B Line Out 1", NULL), + SND_SOC_DAPM_LINE("IVI B Line Out 2", NULL), + SND_SOC_DAPM_LINE("IVI B Line Out 3", NULL), + SND_SOC_DAPM_LINE("IVI B Line Out 4", NULL), + SND_SOC_DAPM_MIC("IVI B Stereo Mic 1", NULL), + SND_SOC_DAPM_MIC("IVI B Stereo Mic 2", NULL), + SND_SOC_DAPM_LINE("IVI B Line In", NULL), +}; + +static const struct snd_soc_dapm_route j721e_codec_b_dapm_routes[] = { + {"IVI B Line Out 1", NULL, "codec-b AOUT1L"}, + {"IVI B Line Out 1", NULL, "codec-b AOUT1R"}, + {"IVI B Line Out 2", NULL, "codec-b AOUT2L"}, + {"IVI B Line Out 2", NULL, "codec-b AOUT2R"}, + {"IVI B Line Out 3", NULL, "codec-b AOUT3L"}, + {"IVI B Line Out 3", NULL, "codec-b AOUT3R"}, + {"IVI B Line Out 4", NULL, "codec-b AOUT4L"}, + {"IVI B Line Out 4", NULL, "codec-b AOUT4R"}, + + {"codec-b AIN1L", NULL, "IVI B Stereo Mic 1"}, + {"codec-b AIN1R", NULL, "IVI B Stereo Mic 1"}, + {"codec-b AIN2L", NULL, "IVI B Stereo Mic 2"}, + {"codec-b AIN2R", NULL, "IVI B Stereo Mic 2"}, + {"codec-b AIN3L", NULL, "IVI B Line In"}, + {"codec-b AIN3R", NULL, "IVI B Line In"}, +}; + +static int j721e_configure_refclk(struct j721e_priv *priv, + unsigned int audio_domain, unsigned int rate) +{ + struct j721e_audio_domain *domain = &priv->audio_domains[audio_domain]; + unsigned int scki; + int ret = -EINVAL; + int i, clk_id; + + if (!(rate % 8000) && priv->pll_rates[J721E_CLK_PARENT_48000]) + clk_id = J721E_CLK_PARENT_48000; + else if (!(rate % 11025) && priv->pll_rates[J721E_CLK_PARENT_44100]) + clk_id = J721E_CLK_PARENT_44100; + else + return ret; + + for (i = 0; i < ARRAY_SIZE(ratios_for_pcm3168a); i++) { + scki = ratios_for_pcm3168a[i] * rate; + + if (priv->pll_rates[clk_id] / scki <= J721E_MAX_CLK_HSDIV) { + ret = 0; + break; + } + } + + if (ret) { + dev_err(priv->dev, "No valid clock configuration for %u Hz\n", + rate); + return ret; + } + + if (priv->hsdiv_rates[domain->parent_clk_id] != scki) { + dev_dbg(priv->dev, + "%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n", + audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI", + rate, + clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15", + ratios_for_pcm3168a[i], scki); + + if (domain->parent_clk_id != clk_id) { + ret = clk_set_parent(domain->codec.target, + domain->codec.parent[clk_id]); + if (ret) + return ret; + + ret = clk_set_parent(domain->mcasp.target, + domain->mcasp.parent[clk_id]); + if (ret) + return ret; + + domain->parent_clk_id = clk_id; + } + + ret = clk_set_rate(domain->codec.target, scki); + if (ret) { + dev_err(priv->dev, "codec set rate failed for %u Hz\n", + scki); + return ret; + } + + ret = clk_set_rate(domain->mcasp.target, scki); + if (!ret) { + priv->hsdiv_rates[domain->parent_clk_id] = scki; + } else { + dev_err(priv->dev, "mcasp set rate failed for %u Hz\n", + scki); + return ret; + } + } + + return ret; +} + +static int j721e_rule_rate(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *t = rule->private; + + return snd_interval_refine(hw_param_interval(params, rule->var), t); +} + +static int j721e_audio_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + unsigned int active_rate; + int ret = 0; + int i; + + mutex_lock(&priv->mutex); + + domain->active++; + + if (priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate) + active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate; + else + active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].rate; + + if (active_rate) + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + active_rate); + else + ret = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + j721e_rule_rate, &priv->rate_range, + SNDRV_PCM_HW_PARAM_RATE, -1); + + mutex_unlock(&priv->mutex); + + if (ret) + return ret; + + /* Reset TDM slots to 32 */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + } + + return 0; +} + +static int j721e_audio_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct j721e_priv *priv = snd_soc_card_get_drvdata(card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + unsigned int sysclk_rate; + int slot_width = 32; + int ret; + int i; + + mutex_lock(&priv->mutex); + + if (domain->rate && domain->rate != params_rate(params)) { + ret = -EINVAL; + goto out; + } + + if (params_width(params) == 16) + slot_width = 16; + + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, slot_width); + if (ret && ret != -ENOTSUPP) + goto out; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, + slot_width); + if (ret && ret != -ENOTSUPP) + goto out; + } + + ret = j721e_configure_refclk(priv, domain_id, params_rate(params)); + if (ret) + goto out; + + sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id]; + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate, + SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) { + dev_err(priv->dev, + "codec set_sysclk failed for %u Hz\n", + sysclk_rate); + goto out; + } + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK, + sysclk_rate, SND_SOC_CLOCK_IN); + + if (ret && ret != -ENOTSUPP) { + dev_err(priv->dev, "mcasp set_sysclk failed for %u Hz\n", + sysclk_rate); + } else { + domain->rate = params_rate(params); + ret = 0; + } + +out: + mutex_unlock(&priv->mutex); + return ret; +} + +static void j721e_audio_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + + mutex_lock(&priv->mutex); + + domain->active--; + if (!domain->active) { + domain->rate = 0; + domain->active_link = 0; + } + + mutex_unlock(&priv->mutex); +} + +static const struct snd_soc_ops j721e_audio_ops = { + .startup = j721e_audio_startup, + .hw_params = j721e_audio_hw_params, + .shutdown = j721e_audio_shutdown, +}; + +static int j721e_audio_init(struct snd_soc_pcm_runtime *rtd) +{ + struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + unsigned int sysclk_rate; + int i, ret; + + /* Set up initial clock configuration */ + ret = j721e_configure_refclk(priv, domain_id, 48000); + if (ret) + return ret; + + sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id]; + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate, + SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK, + sysclk_rate, SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) + return ret; + + /* Set initial tdm slots */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + } + + return 0; +} + +static int j721e_audio_init_ivi(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dapm_context *dapm = &rtd->card->dapm; + + snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_a_dapm_widgets, + ARRAY_SIZE(j721e_ivi_codec_a_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, j721e_codec_a_dapm_routes, + ARRAY_SIZE(j721e_codec_a_dapm_routes)); + snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_b_dapm_widgets, + ARRAY_SIZE(j721e_ivi_codec_b_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, j721e_codec_b_dapm_routes, + ARRAY_SIZE(j721e_codec_b_dapm_routes)); + + return j721e_audio_init(rtd); +} + +static int j721e_get_clocks(struct device *dev, + struct j721e_audio_clocks *clocks, char *prefix) +{ + struct clk *parent; + char *clk_name; + int ret; + + clocks->target = devm_clk_get(dev, prefix); + if (IS_ERR(clocks->target)) { + ret = PTR_ERR(clocks->target); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to acquire %s: %d\n", + prefix, ret); + return ret; + } + + clk_name = kasprintf(GFP_KERNEL, "%s-48000", prefix); + if (clk_name) { + parent = devm_clk_get(dev, clk_name); + kfree(clk_name); + if (IS_ERR(parent)) { + ret = PTR_ERR(parent); + if (ret == -EPROBE_DEFER) + return ret; + + dev_dbg(dev, "no 48KHz parent for %s: %d\n", prefix, ret); + parent = NULL; + } + clocks->parent[J721E_CLK_PARENT_48000] = parent; + } else { + return -ENOMEM; + } + + clk_name = kasprintf(GFP_KERNEL, "%s-44100", prefix); + if (clk_name) { + parent = devm_clk_get(dev, clk_name); + kfree(clk_name); + if (IS_ERR(parent)) { + ret = PTR_ERR(parent); + if (ret == -EPROBE_DEFER) + return ret; + + dev_dbg(dev, "no 44.1KHz parent for %s: %d\n", prefix, ret); + parent = NULL; + } + clocks->parent[J721E_CLK_PARENT_44100] = parent; + } else { + return -ENOMEM; + } + + if (!clocks->parent[J721E_CLK_PARENT_44100] && + !clocks->parent[J721E_CLK_PARENT_48000]) { + dev_err(dev, "At least one parent clock is needed for %s\n", + prefix); + return -EINVAL; + } + + return 0; +} + +static const struct j721e_audio_match_data j721e_cpb_data = { + .board_type = J721E_BOARD_CPB, + .num_links = 2, /* CPB pcm3168a */ + .pll_rates = { + [J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */ + [J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */ + }, +}; + +static const struct j721e_audio_match_data j721e_cpb_ivi_data = { + .board_type = J721E_BOARD_CPB_IVI, + .num_links = 4, /* CPB pcm3168a + 2x pcm3168a on IVI */ + .pll_rates = { + [J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */ + [J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */ + }, +}; + +static const struct of_device_id j721e_audio_of_match[] = { + { + .compatible = "ti,j721e-cpb-audio", + .data = &j721e_cpb_data, + }, { + .compatible = "ti,j721e-cpb-ivi-audio", + .data = &j721e_cpb_ivi_data, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, j721e_audio_of_match); + +static int j721e_calculate_rate_range(struct j721e_priv *priv) +{ + const struct j721e_audio_match_data *match_data = priv->match_data; + struct j721e_audio_clocks *domain_clocks; + unsigned int min_rate, max_rate, pll_rate; + struct clk *pll; + + domain_clocks = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].mcasp; + + pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_44100]); + if (IS_ERR_OR_NULL(pll)) { + priv->pll_rates[J721E_CLK_PARENT_44100] = + match_data->pll_rates[J721E_CLK_PARENT_44100]; + } else { + priv->pll_rates[J721E_CLK_PARENT_44100] = clk_get_rate(pll); + clk_put(pll); + } + + pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_48000]); + if (IS_ERR_OR_NULL(pll)) { + priv->pll_rates[J721E_CLK_PARENT_48000] = + match_data->pll_rates[J721E_CLK_PARENT_48000]; + } else { + priv->pll_rates[J721E_CLK_PARENT_48000] = clk_get_rate(pll); + clk_put(pll); + } + + if (!priv->pll_rates[J721E_CLK_PARENT_44100] && + !priv->pll_rates[J721E_CLK_PARENT_48000]) { + dev_err(priv->dev, "At least one PLL is needed\n"); + return -EINVAL; + } + + if (priv->pll_rates[J721E_CLK_PARENT_44100]) + pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100]; + else + pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000]; + + min_rate = pll_rate / J721E_MAX_CLK_HSDIV; + min_rate /= ratios_for_pcm3168a[ARRAY_SIZE(ratios_for_pcm3168a) - 1]; + + if (priv->pll_rates[J721E_CLK_PARENT_48000]) + pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000]; + else + pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100]; + + if (pll_rate > PCM1368A_MAX_SYSCLK) + pll_rate = PCM1368A_MAX_SYSCLK; + + max_rate = pll_rate / ratios_for_pcm3168a[0]; + + snd_interval_any(&priv->rate_range); + priv->rate_range.min = min_rate; + priv->rate_range.max = max_rate; + + return 0; +} + +static int j721e_soc_probe_cpb(struct j721e_priv *priv, int *link_idx, + int *conf_idx) +{ + struct device_node *node = priv->dev->of_node; + struct snd_soc_dai_link_component *compnent; + struct device_node *dai_node, *codec_node; + struct j721e_audio_domain *domain; + int comp_count, comp_idx; + int ret; + + dai_node = of_parse_phandle(node, "ti,cpb-mcasp", 0); + if (!dai_node) { + dev_err(priv->dev, "CPB McASP node is not provided\n"); + return -EINVAL; + } + + codec_node = of_parse_phandle(node, "ti,cpb-codec", 0); + if (!codec_node) { + dev_err(priv->dev, "CPB codec node is not provided\n"); + return -EINVAL; + } + + domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB]; + ret = j721e_get_clocks(priv->dev, &domain->codec, "cpb-codec-scki"); + if (ret) + return ret; + + ret = j721e_get_clocks(priv->dev, &domain->mcasp, "cpb-mcasp-auxclk"); + if (ret) + return ret; + + /* + * Common Processor Board, two links + * Link 1: McASP10 -> pcm3168a_1 DAC + * Link 2: McASP10 <- pcm3168a_1 ADC + */ + comp_count = 6; + compnent = devm_kzalloc(priv->dev, comp_count * sizeof(*compnent), + GFP_KERNEL); + if (!compnent) + return -ENOMEM; + + comp_idx = 0; + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_codecs = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + + priv->dai_links[*link_idx].name = "CPB PCM3168A Playback"; + priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs->of_node = codec_node; + priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-dac"; + priv->dai_links[*link_idx].playback_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_codecs = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + + priv->dai_links[*link_idx].name = "CPB PCM3168A Capture"; + priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs->of_node = codec_node; + priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-adc"; + priv->dai_links[*link_idx].capture_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = codec_node; + priv->codec_conf[*conf_idx].name_prefix = "codec-1"; + (*conf_idx)++; + priv->codec_conf[*conf_idx].dlc.of_node = dai_node; + priv->codec_conf[*conf_idx].name_prefix = "McASP10"; + (*conf_idx)++; + + return 0; +} + +static int j721e_soc_probe_ivi(struct j721e_priv *priv, int *link_idx, + int *conf_idx) +{ + struct device_node *node = priv->dev->of_node; + struct snd_soc_dai_link_component *compnent; + struct device_node *dai_node, *codeca_node, *codecb_node; + struct j721e_audio_domain *domain; + int comp_count, comp_idx; + int ret; + + if (priv->match_data->board_type != J721E_BOARD_CPB_IVI) + return 0; + + dai_node = of_parse_phandle(node, "ti,ivi-mcasp", 0); + if (!dai_node) { + dev_err(priv->dev, "IVI McASP node is not provided\n"); + return -EINVAL; + } + + codeca_node = of_parse_phandle(node, "ti,ivi-codec-a", 0); + if (!codeca_node) { + dev_err(priv->dev, "IVI codec-a node is not provided\n"); + return -EINVAL; + } + + codecb_node = of_parse_phandle(node, "ti,ivi-codec-b", 0); + if (!codecb_node) { + dev_warn(priv->dev, "IVI codec-b node is not provided\n"); + return 0; + } + + domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_IVI]; + ret = j721e_get_clocks(priv->dev, &domain->codec, "ivi-codec-scki"); + if (ret) + return ret; + + ret = j721e_get_clocks(priv->dev, &domain->mcasp, "ivi-mcasp-auxclk"); + if (ret) + return ret; + + /* + * IVI extension, two links + * Link 1: McASP0 -> pcm3168a_a DAC + * \> pcm3168a_b DAC + * Link 2: McASP0 <- pcm3168a_a ADC + * \ pcm3168a_b ADC + */ + comp_count = 8; + compnent = devm_kzalloc(priv->dev, comp_count * sizeof(*compnent), + GFP_KERNEL); + if (!compnent) + return -ENOMEM; + + comp_idx = 0; + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx]; + priv->dai_links[*link_idx].num_codecs = 2; + comp_idx += 2; + + priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Playback"; + priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs[0].of_node = codeca_node; + priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-dac"; + priv->dai_links[*link_idx].codecs[1].of_node = codecb_node; + priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-dac"; + priv->dai_links[*link_idx].playback_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init_ivi; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx]; + priv->dai_links[*link_idx].num_codecs = 2; + + priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Capture"; + priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs[0].of_node = codeca_node; + priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-adc"; + priv->dai_links[*link_idx].codecs[1].of_node = codecb_node; + priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-adc"; + priv->dai_links[*link_idx].capture_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = codeca_node; + priv->codec_conf[*conf_idx].name_prefix = "codec-a"; + (*conf_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = codecb_node; + priv->codec_conf[*conf_idx].name_prefix = "codec-b"; + (*conf_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = dai_node; + priv->codec_conf[*conf_idx].name_prefix = "McASP0"; + (*conf_idx)++; + + return 0; +} + +static int j721e_soc_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct snd_soc_card *card; + const struct of_device_id *match; + struct j721e_priv *priv; + int link_cnt, conf_cnt, ret; + + if (!node) { + dev_err(&pdev->dev, "of node is missing.\n"); + return -ENODEV; + } + + match = of_match_node(j721e_audio_of_match, node); + if (!match) { + dev_err(&pdev->dev, "No compatible match found\n"); + return -ENODEV; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->match_data = match->data; + + priv->dai_links = devm_kcalloc(&pdev->dev, priv->match_data->num_links, + sizeof(*priv->dai_links), GFP_KERNEL); + if (!priv->dai_links) + return -ENOMEM; + + priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].parent_clk_id = -1; + priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].parent_clk_id = -1; + priv->dev = &pdev->dev; + card = &priv->card; + card->dev = &pdev->dev; + card->owner = THIS_MODULE; + card->dapm_widgets = j721e_cpb_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(j721e_cpb_dapm_widgets); + card->dapm_routes = j721e_cpb_dapm_routes; + card->num_dapm_routes = ARRAY_SIZE(j721e_cpb_dapm_routes); + card->fully_routed = 1; + + if (snd_soc_of_parse_card_name(card, "model")) { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + link_cnt = 0; + conf_cnt = 0; + ret = j721e_soc_probe_cpb(priv, &link_cnt, &conf_cnt); + if (ret) + return ret; + + ret = j721e_soc_probe_ivi(priv, &link_cnt, &conf_cnt); + if (ret) + return ret; + + card->dai_link = priv->dai_links; + card->num_links = link_cnt; + + card->codec_conf = priv->codec_conf; + card->num_configs = conf_cnt; + + ret = j721e_calculate_rate_range(priv); + if (ret) + return ret; + + snd_soc_card_set_drvdata(card, priv); + + mutex_init(&priv->mutex); + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", + ret); + + return ret; +} + +static struct platform_driver j721e_soc_driver = { + .driver = { + .name = "j721e-audio", + .pm = &snd_soc_pm_ops, + .of_match_table = of_match_ptr(j721e_audio_of_match), + }, + .probe = j721e_soc_probe, +}; + +module_platform_driver(j721e_soc_driver); + +MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); +MODULE_DESCRIPTION("ASoC machine driver for j721e Common Processor Board"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c index a1672b479cb7..2802a33b9c5f 100644 --- a/sound/soc/ti/n810.c +++ b/sound/soc/ti/n810.c @@ -84,7 +84,7 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) static int n810_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2); @@ -100,7 +100,7 @@ static void n810_shutdown(struct snd_pcm_substream *substream) static int n810_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int err; diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c index 61e45fea5dd8..16ea039ff865 100644 --- a/sound/soc/ti/omap-abe-twl6040.c +++ b/sound/soc/ti/omap-abe-twl6040.c @@ -45,7 +45,7 @@ static struct platform_device *dmic_codec_dev; static int omap_abe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); @@ -77,7 +77,7 @@ static const struct snd_soc_ops omap_abe_ops = { static int omap_abe_dmic_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index def2a0ce8886..3328c02f93c7 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -2,7 +2,7 @@ /* * omap-hdmi-audio.c -- OMAP4+ DSS HDMI audio support library * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Jyri Sarha <jsarha@ti.com> */ 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/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 32e3ccdbb7a2..6025b30bbe77 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -731,7 +731,7 @@ err_st: static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream, unsigned int packet_size) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); int words; @@ -896,7 +896,7 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay( struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); u16 fifo_use; diff --git a/sound/soc/ti/omap-twl4030.c b/sound/soc/ti/omap-twl4030.c index 92dbe2c67290..1da05a6cdc9f 100644 --- a/sound/soc/ti/omap-twl4030.c +++ b/sound/soc/ti/omap-twl4030.c @@ -2,7 +2,7 @@ /* * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec * - * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com * All rights reserved. * * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> @@ -38,7 +38,7 @@ struct omap_twl4030 { static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int fmt; switch (params_channels(params)) { diff --git a/sound/soc/ti/omap3pandora.c b/sound/soc/ti/omap3pandora.c index b04146311b31..a287e9747c2a 100644 --- a/sound/soc/ti/omap3pandora.c +++ b/sound/soc/ti/omap3pandora.c @@ -31,7 +31,7 @@ static struct regulator *omap3pandora_dac_reg; static int omap3pandora_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/ti/osk5912.c b/sound/soc/ti/osk5912.c index e01485cc51a1..40e29dda7e7a 100644 --- a/sound/soc/ti/osk5912.c +++ b/sound/soc/ti/osk5912.c @@ -38,7 +38,7 @@ static void osk_shutdown(struct snd_pcm_substream *substream) static int osk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int err; diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 2a714a004163..2176a95201bf 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -90,7 +90,7 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) static int rx51_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2); @@ -102,7 +102,7 @@ static int rx51_startup(struct snd_pcm_substream *substream) static int rx51_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* Set the codec system clock for DAC and ADC */ diff --git a/sound/soc/ti/sdma-pcm.c b/sound/soc/ti/sdma-pcm.c index 2b0bc234e1b6..9e7691103f05 100644 --- a/sound/soc/ti/sdma-pcm.c +++ b/sound/soc/ti/sdma-pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> */ diff --git a/sound/soc/ti/sdma-pcm.h b/sound/soc/ti/sdma-pcm.h index cb0627c8dd34..c19efb4c043d 100644 --- a/sound/soc/ti/sdma-pcm.h +++ b/sound/soc/ti/sdma-pcm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> */ diff --git a/sound/soc/ti/udma-pcm.c b/sound/soc/ti/udma-pcm.c index 39830caaaf7c..2ff0f518aba5 100644 --- a/sound/soc/ti/udma-pcm.c +++ b/sound/soc/ti/udma-pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> */ diff --git a/sound/soc/ti/udma-pcm.h b/sound/soc/ti/udma-pcm.h index 54111e7312c1..9ed588fd79b9 100644 --- a/sound/soc/ti/udma-pcm.h +++ b/sound/soc/ti/udma-pcm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com */ #ifndef __UDMA_PCM_H__ 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. * diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index d6bcd476df12..3c1628a3a1ac 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c @@ -108,7 +108,7 @@ static int uniphier_aiodma_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; int bytes = runtime->period_size * @@ -135,7 +135,7 @@ static int uniphier_aiodma_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; struct device *dev = &aio->chip->pdev->dev; @@ -171,7 +171,7 @@ static snd_pcm_uframes_t uniphier_aiodma_pointer( struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; int bytes = runtime->period_size * diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index 6aaa19829a73..2c39c7a2fd7d 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c @@ -190,7 +190,7 @@ static struct snd_kcontrol_new mop500_ab8500_ctrls[] = { static int mop500_ab8500_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* Set audio-clock source */ return mop500_ab8500_set_mclk(rtd->card->dev, @@ -199,7 +199,7 @@ static int mop500_ab8500_startup(struct snd_pcm_substream *substream) static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->card->dev; dev_dbg(dev, "%s: Enter\n", __func__); @@ -214,7 +214,7 @@ static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct device *dev = rtd->card->dev; @@ -338,7 +338,7 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); mutex_lock(&mop500_ab8500_params_lock); diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 394d8b2a4a16..fd0b88bb7921 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -395,7 +395,7 @@ static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) static void flush_fifo_rx(struct ux500_msp *msp) { - u32 reg_val_DR, reg_val_GCR, reg_val_FLR; + u32 reg_val_GCR, reg_val_FLR; u32 limit = 32; reg_val_GCR = readl(msp->registers + MSP_GCR); @@ -403,7 +403,7 @@ static void flush_fifo_rx(struct ux500_msp *msp) reg_val_FLR = readl(msp->registers + MSP_FLR); while (!(reg_val_FLR & RX_FIFO_EMPTY) && limit--) { - reg_val_DR = readl(msp->registers + MSP_DR); + readl(msp->registers + MSP_DR); reg_val_FLR = readl(msp->registers + MSP_FLR); } @@ -412,7 +412,7 @@ static void flush_fifo_rx(struct ux500_msp *msp) static void flush_fifo_tx(struct ux500_msp *msp) { - u32 reg_val_TSTDR, reg_val_GCR, reg_val_FLR; + u32 reg_val_GCR, reg_val_FLR; u32 limit = 32; reg_val_GCR = readl(msp->registers + MSP_GCR); @@ -421,7 +421,7 @@ static void flush_fifo_tx(struct ux500_msp *msp) reg_val_FLR = readl(msp->registers + MSP_FLR); while (!(reg_val_FLR & TX_FIFO_EMPTY) && limit--) { - reg_val_TSTDR = readl(msp->registers + MSP_TSTDR); + readl(msp->registers + MSP_TSTDR); reg_val_FLR = readl(msp->registers + MSP_FLR); } writel(0x0, msp->registers + MSP_ITCR); diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 39b96c132bc8..18191084b8b8 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -85,7 +85,7 @@ static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct msp_i2s_platform_data *pdata = asoc_rtd_to_cpu(rtd, 0)->dev->platform_data; struct snd_dmaengine_dai_dma_data *snd_dma_params; struct ux500_msp_dma_params *ste_dma_params; diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 68af2176b19c..aeb4b2c4d1d3 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -369,7 +369,7 @@ static int xtfpga_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); void *p; snd_soc_set_runtime_hwparams(substream, &xtfpga_pcm_hardware); |