diff options
Diffstat (limited to 'sound/soc')
479 files changed, 14197 insertions, 4353 deletions
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 151f05a68435..918812763884 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -155,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 9859a133b90c..ff5cc9bbec29 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -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 7031869a023a..cdff739924e2 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1017,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); @@ -1108,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; } @@ -1138,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_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 2985f8bf30b2..922cd0176e1f 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -394,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; @@ -418,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_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-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 33058518c3da..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]; 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/gx-card.c b/sound/soc/meson/gx-card.c index fdd2d5303b2a..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]; diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c index c734131ff0d6..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; 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 f1d641cd48da..2fe1b2ec7c8f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -551,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); } @@ -690,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); } @@ -948,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 */ @@ -1211,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, @@ -1333,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); } } @@ -1350,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); } @@ -1641,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) { @@ -2381,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[] = { @@ -2507,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); @@ -2531,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; } @@ -2549,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) @@ -2565,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 cecbbed2de9d..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 */ @@ -516,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; @@ -535,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; @@ -554,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 74baf1fce053..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; @@ -2897,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); @@ -2963,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/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); |