diff options
Diffstat (limited to 'sound/soc/intel/boards')
25 files changed, 738 insertions, 674 deletions
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index d96fc1313434..c10c37803c67 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -26,7 +26,7 @@ config SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES interface. If unsure select N. -if SND_SOC_INTEL_HASWELL +if SND_SOC_INTEL_CATPT config SND_SOC_INTEL_HASWELL_MACH tristate "Haswell Lynxpoint" @@ -40,9 +40,9 @@ config SND_SOC_INTEL_HASWELL_MACH Say Y or m if you have such a device. If unsure select "N". -endif ## SND_SOC_INTEL_HASWELL +endif ## SND_SOC_INTEL_CATPT -if SND_SOC_INTEL_HASWELL || SND_SOC_SOF_BROADWELL +if SND_SOC_INTEL_CATPT || SND_SOC_SOF_BROADWELL config SND_SOC_INTEL_BDW_RT5650_MACH tristate "Broadwell with RT5650 codec" @@ -83,32 +83,7 @@ config SND_SOC_INTEL_BROADWELL_MACH Ultrabook platforms. Say Y or m if you have such a device. This is a recommended option. If unsure select "N". -endif ## SND_SOC_INTEL_HASWELL || SND_SOC_SOF_BROADWELL - -if SND_SOC_INTEL_BAYTRAIL - -config SND_SOC_INTEL_BYT_MAX98090_MACH - tristate "Baytrail with MAX98090 codec" - depends on I2C - depends on X86_INTEL_LPSS || COMPILE_TEST - select SND_SOC_MAX98090 - help - This adds audio driver for Intel Baytrail platform based boards - with the MAX98090 audio codec. This driver is deprecated, use - SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH instead for better - functionality. - -config SND_SOC_INTEL_BYT_RT5640_MACH - tristate "Baytrail with RT5640 codec" - depends on I2C - depends on X86_INTEL_LPSS || COMPILE_TEST - select SND_SOC_RT5640 - help - This adds audio driver for Intel Baytrail platform based boards - with the RT5640 audio codec. This driver is deprecated, use - SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality. - -endif ## SND_SOC_INTEL_BAYTRAIL +endif ## SND_SOC_INTEL_CATPT || SND_SOC_SOF_BROADWELL if SND_SST_ATOM_HIFI2_PLATFORM || SND_SOC_SOF_BAYTRAIL @@ -569,9 +544,12 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_MAX98373_SDW select SND_SOC_RT700_SDW select SND_SOC_RT711_SDW + select SND_SOC_RT711_SDCA_SDW select SND_SOC_RT1308_SDW select SND_SOC_RT1308 + select SND_SOC_RT1316_SDW select SND_SOC_RT715_SDW + select SND_SOC_RT715_SDCA_SDW select SND_SOC_RT5682_SDW select SND_SOC_DMIC help diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index dc04acb911b6..a58e4d22e9c8 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -1,7 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only snd-soc-sst-haswell-objs := haswell.o -snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o -snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o snd-soc-sst-bdw-rt5650-mach-objs := bdw-rt5650.o snd-soc-sst-bdw-rt5677-mach-objs := bdw-rt5677.o snd-soc-sst-broadwell-objs := broadwell.o @@ -35,15 +33,14 @@ 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_sdw_rt1308.o sof_sdw_rt1316.o \ + sof_sdw_rt5682.o sof_sdw_rt700.o \ + sof_sdw_rt711.o sof_sdw_rt711_sdca.o \ + sof_sdw_rt715.o sof_sdw_rt715_sdca.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 -obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o -obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index ce7320916b22..aa420b201848 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -16,9 +16,6 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> -#include "../common/sst-dsp.h" -#include "../haswell/sst-haswell-ipc.h" - #include "../../codecs/rt5645.h" struct bdw_rt5650_priv { @@ -87,14 +84,14 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *chan = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); /* The ADSP will covert the FE rate to 48k, max 4-channels */ rate->min = rate->max = 48000; - channels->min = 2; - channels->max = 4; + chan->min = 2; + chan->max = 4; /* set SSP0 to 24 bit */ snd_mask_set_format(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), @@ -138,30 +135,6 @@ static struct snd_soc_ops bdw_rt5650_ops = { .hw_params = bdw_rt5650_hw_params, }; -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) -static int bdw_rt5650_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); - struct sst_pdata *pdata = dev_get_platdata(component->dev); - struct sst_hsw *broadwell = pdata->dsp; - int ret; - - /* Set ADSP SSP port settings - * clock_divider = 4 means BCLK = MCLK/5 = 24MHz/5 = 4.8MHz - */ - ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0, - SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, - SST_HSW_DEVICE_TDM_CLOCK_MASTER, 4); - if (ret < 0) { - dev_err(rtd->dev, "error: failed to set device config\n"); - return ret; - } - - return 0; -} -#endif - static const unsigned int channels[] = { 2, 4, }; @@ -251,21 +224,17 @@ SND_SOC_DAILINK_DEF(platform, SND_SOC_DAILINK_DEF(be, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5650:00", "rt5645-aif1"))); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#endif static struct snd_soc_dai_link bdw_rt5650_dais[] = { /* Front End DAI links */ { .name = "System PCM", .stream_name = "System Playback", + .nonatomic = 1, .dynamic = 1, .ops = &bdw_rt5650_fe_ops, -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) - .init = bdw_rt5650_rtd_init, -#endif .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST @@ -289,11 +258,7 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5650_init, -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) - SND_SOC_DAILINK_REG(dummy, be, dummy), -#else SND_SOC_DAILINK_REG(ssp0_port, be, platform), -#endif }, }; diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 86e427e3822f..7a3e773d0a1c 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -17,9 +17,6 @@ #include <sound/jack.h> #include <sound/soc-acpi.h> -#include "../common/sst-dsp.h" -#include "../haswell/sst-haswell-ipc.h" - #include "../../codecs/rt5677.h" struct bdw_rt5677_priv { @@ -140,13 +137,13 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *chan = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); /* The ADSP will covert the FE rate to 48k, stereo */ rate->min = rate->max = 48000; - channels->min = channels->max = 2; + chan->min = chan->max = 2; /* set SSP0 to 16 bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); @@ -201,27 +198,6 @@ static const struct snd_soc_ops bdw_rt5677_dsp_ops = { .hw_params = bdw_rt5677_dsp_hw_params, }; -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) -static int bdw_rt5677_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); - struct sst_pdata *pdata = dev_get_platdata(component->dev); - struct sst_hsw *broadwell = pdata->dsp; - int ret; - - /* Set ADSP SSP port settings */ - ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0, - SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, - SST_HSW_DEVICE_CLOCK_MASTER, 9); - if (ret < 0) { - dev_err(rtd->dev, "error: failed to set device config\n"); - return ret; - } - - return 0; -} -#endif - static const unsigned int channels[] = { 2, }; @@ -333,10 +309,8 @@ SND_SOC_DAILINK_DEF(platform, SND_SOC_DAILINK_DEF(be, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RT5677CE:00", "rt5677-aif1"))); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#endif /* Wake on voice interface */ SND_SOC_DAILINK_DEFS(dsp, @@ -349,10 +323,8 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { { .name = "System PCM", .stream_name = "System Playback/Capture", + .nonatomic = 1, .dynamic = 1, -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) - .init = bdw_rt5677_rtd_init, -#endif .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST @@ -387,11 +359,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .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 SND_SOC_DAILINK_REG(ssp0_port, be, platform), -#endif }, }; diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index f6399077d291..77c85f17aca6 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -14,9 +14,6 @@ #include <sound/pcm_params.h> #include <sound/soc-acpi.h> -#include "../common/sst-dsp.h" -#include "../haswell/sst-haswell-ipc.h" - #include "../../codecs/rt286.h" static struct snd_soc_jack broadwell_headset; @@ -87,13 +84,13 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *chan = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); /* The ADSP will covert the FE rate to 48k, stereo */ rate->min = rate->max = 48000; - channels->min = channels->max = 2; + chan->min = chan->max = 2; /* set SSP0 to 16 bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); @@ -122,27 +119,6 @@ static const struct snd_soc_ops broadwell_rt286_ops = { .hw_params = broadwell_rt286_hw_params, }; -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) -static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); - struct sst_pdata *pdata = dev_get_platdata(component->dev); - struct sst_hsw *broadwell = pdata->dsp; - int ret; - - /* Set ADSP SSP port settings */ - ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0, - SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, - SST_HSW_DEVICE_CLOCK_MASTER, 9); - if (ret < 0) { - dev_err(rtd->dev, "error: failed to set device config\n"); - return ret; - } - - return 0; -} -#endif - static const unsigned int channels[] = { 2, }; @@ -189,10 +165,8 @@ SND_SOC_DAILINK_DEF(platform, SND_SOC_DAILINK_DEF(codec, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00", "rt286-aif1"))); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#endif /* broadwell digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broadwell_rt286_dais[] = { @@ -200,10 +174,8 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { { .name = "System PCM", .stream_name = "System Playback/Capture", + .nonatomic = 1, .dynamic = 1, -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) - .init = broadwell_rtd_init, -#endif .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ops = &broadwell_fe_ops, .dpcm_playback = 1, @@ -213,6 +185,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { { .name = "Offload0", .stream_name = "Offload0 Playback", + .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, @@ -221,6 +194,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { { .name = "Offload1", .stream_name = "Offload1 Playback", + .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, @@ -229,6 +203,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { { .name = "Loopback PCM", .stream_name = "Loopback", + .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, @@ -248,11 +223,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { .ops = &broadwell_rt286_ops, .dpcm_playback = 1, .dpcm_capture = 1, -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) - SND_SOC_DAILINK_REG(dummy, codec, dummy), -#else SND_SOC_DAILINK_REG(ssp0_port, codec, platform), -#endif }, }; diff --git a/sound/soc/intel/boards/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c deleted file mode 100644 index f5097da28828..000000000000 --- a/sound/soc/intel/boards/byt-max98090.c +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Baytrail SST MAX98090 machine driver - * Copyright (c) 2014, Intel Corporation. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/acpi.h> -#include <linux/device.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> -#include <linux/slab.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include <sound/jack.h> -#include "../../codecs/max98090.h" - -struct byt_max98090_private { - struct snd_soc_jack jack; -}; - -static const struct snd_soc_dapm_widget byt_max98090_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Int Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), -}; - -static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { - {"IN34", NULL, "Headset Mic"}, - {"Headset Mic", NULL, "MICBIAS"}, - {"DMICL", NULL, "Int Mic"}, - {"Headphone", NULL, "HPL"}, - {"Headphone", NULL, "HPR"}, - {"Ext Spk", NULL, "SPKL"}, - {"Ext Spk", NULL, "SPKR"}, -}; - -static const struct snd_kcontrol_new byt_max98090_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Int Mic"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), -}; - -static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headphone", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static struct snd_soc_jack_gpio hs_jack_gpios[] = { - { - .name = "hp", - .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, - .debounce_time = 200, - }, - { - .name = "mic", - .invert = 1, - .report = SND_JACK_MICROPHONE, - .debounce_time = 200, - }, -}; - -static const struct acpi_gpio_params hp_gpios = { 0, 0, false }; -static const struct acpi_gpio_params mic_gpios = { 1, 0, false }; - -static const struct acpi_gpio_mapping acpi_byt_max98090_gpios[] = { - { "hp-gpios", &hp_gpios, 1 }, - { "mic-gpios", &mic_gpios, 1 }, - {}, -}; - -static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) -{ - int ret; - struct snd_soc_card *card = runtime->card; - struct byt_max98090_private *drv = snd_soc_card_get_drvdata(card); - struct snd_soc_jack *jack = &drv->jack; - - card->dapm.idle_bias_off = true; - - ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), - M98090_REG_SYSTEM_CLOCK, - 25000000, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "Can't set codec clock %d\n", ret); - return ret; - } - - /* Enable jack detection */ - ret = snd_soc_card_jack_new(runtime->card, "Headset", - SND_JACK_LINEOUT | SND_JACK_HEADSET, jack, - hs_jack_pins, ARRAY_SIZE(hs_jack_pins)); - if (ret) - return ret; - - return snd_soc_jack_add_gpiods(card->dev->parent, jack, - ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); -} - -SND_SOC_DAILINK_DEFS(baytrail, - DAILINK_COMP_ARRAY(COMP_CPU("baytrail-pcm-audio")), - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-193C9890:00", "HiFi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("baytrail-pcm-audio"))); - -static struct snd_soc_dai_link byt_max98090_dais[] = { - { - .name = "Baytrail Audio", - .stream_name = "Audio", - .init = byt_max98090_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - SND_SOC_DAILINK_REG(baytrail), - }, -}; - -static struct snd_soc_card byt_max98090_card = { - .name = "byt-max98090", - .owner = THIS_MODULE, - .dai_link = byt_max98090_dais, - .num_links = ARRAY_SIZE(byt_max98090_dais), - .dapm_widgets = byt_max98090_widgets, - .num_dapm_widgets = ARRAY_SIZE(byt_max98090_widgets), - .dapm_routes = byt_max98090_audio_map, - .num_dapm_routes = ARRAY_SIZE(byt_max98090_audio_map), - .controls = byt_max98090_controls, - .num_controls = ARRAY_SIZE(byt_max98090_controls), - .fully_routed = true, -}; - -static int byt_max98090_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct byt_max98090_private *priv; - int ret_val; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "allocation failed\n"); - return -ENOMEM; - } - - ret_val = devm_acpi_dev_add_driver_gpios(dev->parent, acpi_byt_max98090_gpios); - if (ret_val) - dev_dbg(dev, "Unable to add GPIO mapping table\n"); - - byt_max98090_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&byt_max98090_card, priv); - ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card); - if (ret_val) { - dev_err(&pdev->dev, - "snd_soc_register_card failed %d\n", ret_val); - return ret_val; - } - - return 0; -} - -static struct platform_driver byt_max98090_driver = { - .probe = byt_max98090_probe, - .driver = { - .name = "byt-max98090", - .pm = &snd_soc_pm_ops, - }, -}; -module_platform_driver(byt_max98090_driver) - -MODULE_DESCRIPTION("ASoC Intel(R) Baytrail Machine driver"); -MODULE_AUTHOR("Omair Md Abdullah, Jarkko Nikula"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:byt-max98090"); diff --git a/sound/soc/intel/boards/byt-rt5640.c b/sound/soc/intel/boards/byt-rt5640.c deleted file mode 100644 index 8851949f38e2..000000000000 --- a/sound/soc/intel/boards/byt-rt5640.c +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Baytrail SST RT5640 machine driver - * Copyright (c) 2014, Intel Corporation. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/acpi.h> -#include <linux/device.h> -#include <linux/dmi.h> -#include <linux/slab.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include <sound/jack.h> -#include "../../codecs/rt5640.h" - -#include "../common/sst-dsp.h" - -static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Internal Mic", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { - {"Headset Mic", NULL, "MICBIAS1"}, - {"IN2P", NULL, "Headset Mic"}, - {"Headphone", NULL, "HPOL"}, - {"Headphone", NULL, "HPOR"}, - {"Speaker", NULL, "SPOLP"}, - {"Speaker", NULL, "SPOLN"}, - {"Speaker", NULL, "SPORP"}, - {"Speaker", NULL, "SPORN"}, -}; - -static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { - {"DMIC1", NULL, "Internal Mic"}, -}; - -static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = { - {"DMIC2", NULL, "Internal Mic"}, -}; - -static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { - {"Internal Mic", NULL, "MICBIAS1"}, - {"IN1P", NULL, "Internal Mic"}, -}; - -enum { - BYT_RT5640_DMIC1_MAP, - BYT_RT5640_DMIC2_MAP, - BYT_RT5640_IN1_MAP, -}; - -#define BYT_RT5640_MAP(quirk) ((quirk) & 0xff) -#define BYT_RT5640_DMIC_EN BIT(16) - -static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | - BYT_RT5640_DMIC_EN; - -static const struct snd_kcontrol_new byt_rt5640_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Internal Mic"), - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - -static int byt_rt5640_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); - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, - params_rate(params) * 256, - SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(codec_dai->dev, "can't set codec clock %d\n", ret); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, - params_rate(params) * 64, - params_rate(params) * 256); - if (ret < 0) { - dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret); - return ret; - } - return 0; -} - -static int byt_rt5640_quirk_cb(const struct dmi_system_id *id) -{ - byt_rt5640_quirk = (unsigned long)id->driver_data; - return 1; -} - -static const struct dmi_system_id byt_rt5640_quirk_table[] = { - { - .callback = byt_rt5640_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"), - }, - .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, - }, - { - .callback = byt_rt5640_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "DellInc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), - }, - .driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP | - BYT_RT5640_DMIC_EN), - }, - {} -}; - -static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) -{ - int ret; - struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; - struct snd_soc_card *card = runtime->card; - const struct snd_soc_dapm_route *custom_map; - int num_routes; - - card->dapm.idle_bias_off = true; - - ret = snd_soc_add_card_controls(card, byt_rt5640_controls, - ARRAY_SIZE(byt_rt5640_controls)); - if (ret) { - dev_err(card->dev, "unable to add card controls\n"); - return ret; - } - - dmi_check_system(byt_rt5640_quirk_table); - switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { - case BYT_RT5640_IN1_MAP: - custom_map = byt_rt5640_intmic_in1_map; - num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map); - break; - case BYT_RT5640_DMIC2_MAP: - custom_map = byt_rt5640_intmic_dmic2_map; - num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); - break; - default: - custom_map = byt_rt5640_intmic_dmic1_map; - num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); - } - - ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); - if (ret) - return ret; - - if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) { - ret = rt5640_dmic_enable(component, 0, 0); - if (ret) - return ret; - } - - snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); - - return ret; -} - -static struct snd_soc_ops byt_rt5640_ops = { - .hw_params = byt_rt5640_hw_params, -}; - -SND_SOC_DAILINK_DEFS(audio, - DAILINK_COMP_ARRAY(COMP_CPU("baytrail-pcm-audio")), - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5640:00", "rt5640-aif1")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("baytrail-pcm-audio"))); - -static struct snd_soc_dai_link byt_rt5640_dais[] = { - { - .name = "Baytrail Audio", - .stream_name = "Audio", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - .init = byt_rt5640_init, - .ops = &byt_rt5640_ops, - SND_SOC_DAILINK_REG(audio), - }, -}; - -static struct snd_soc_card byt_rt5640_card = { - .name = "byt-rt5640", - .owner = THIS_MODULE, - .dai_link = byt_rt5640_dais, - .num_links = ARRAY_SIZE(byt_rt5640_dais), - .dapm_widgets = byt_rt5640_widgets, - .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), - .dapm_routes = byt_rt5640_audio_map, - .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), - .fully_routed = true, -}; - -static int byt_rt5640_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &byt_rt5640_card; - - card->dev = &pdev->dev; - return devm_snd_soc_register_card(&pdev->dev, card); -} - -static struct platform_driver byt_rt5640_audio = { - .probe = byt_rt5640_probe, - .driver = { - .name = "byt-rt5640", - .pm = &snd_soc_pm_ops, - }, -}; -module_platform_driver(byt_rt5640_audio) - -MODULE_DESCRIPTION("ASoC Intel(R) Baytrail Machine driver"); -MODULE_AUTHOR("Omair Md Abdullah, Jarkko Nikula"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:byt-rt5640"); diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 9cb42ba40c07..0b50b3646d55 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -99,7 +99,7 @@ static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), 50); - return ret; + return 0; } static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd, diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 7ae34b49815c..7ed869bf1a92 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -28,7 +28,6 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../atom/sst-atom-controls.h" -#include "../common/sst-dsp.h" #include "../common/soc-intel-quirks.h" /* jd-inv + terminating entry */ diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index fc202747ba83..9dadf6561444 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -28,7 +28,6 @@ #include <dt-bindings/sound/rt5640.h> #include "../../codecs/rt5640.h" #include "../atom/sst-atom-controls.h" -#include "../common/sst-dsp.h" #include "../common/soc-intel-quirks.h" enum { diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 744b7b5b8106..c55d1239e705 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -13,9 +13,6 @@ #include <sound/soc-acpi.h> #include <sound/pcm_params.h> -#include "../common/sst-dsp.h" -#include "../haswell/sst-haswell-ipc.h" - #include "../../codecs/rt5640.h" /* Haswell ULT platforms have a Headphone and Mic jack */ @@ -77,25 +74,6 @@ static const struct snd_soc_ops haswell_rt5640_ops = { .hw_params = haswell_rt5640_hw_params, }; -static int haswell_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); - struct sst_pdata *pdata = dev_get_platdata(component->dev); - struct sst_hsw *haswell = pdata->dsp; - int ret; - - /* Set ADSP SSP port settings */ - ret = sst_hsw_device_set_config(haswell, SST_HSW_DEVICE_SSP_0, - SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, - SST_HSW_DEVICE_CLOCK_MASTER, 9); - if (ret < 0) { - dev_err(rtd->dev, "failed to set device config\n"); - return ret; - } - - return 0; -} - SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); @@ -117,13 +95,16 @@ SND_SOC_DAILINK_DEF(codec, SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("haswell-pcm-audio"))); +SND_SOC_DAILINK_DEF(ssp0_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); + static struct snd_soc_dai_link haswell_rt5640_dais[] = { /* Front End DAI links */ { .name = "System", .stream_name = "System Playback/Capture", + .nonatomic = 1, .dynamic = 1, - .init = haswell_rtd_init, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, .dpcm_capture = 1, @@ -132,6 +113,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { { .name = "Offload0", .stream_name = "Offload0 Playback", + .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, @@ -140,6 +122,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { { .name = "Offload1", .stream_name = "Offload1 Playback", + .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_playback = 1, @@ -148,6 +131,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { { .name = "Loopback", .stream_name = "Loopback", + .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .dpcm_capture = 1, @@ -167,7 +151,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { .ops = &haswell_rt5640_ops, .dpcm_playback = 1, .dpcm_capture = 1, - SND_SOC_DAILINK_REG(dummy, codec, dummy), + SND_SOC_DAILINK_REG(ssp0_port, codec, platform), }, }; diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c index 244b57fba64c..91ad2a0ad1ce 100644 --- a/sound/soc/intel/boards/hda_dsp_common.c +++ b/sound/soc/intel/boards/hda_dsp_common.c @@ -10,12 +10,14 @@ #include "hda_dsp_common.h" +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + /* * Search card topology and return PCM device number * matching Nth HDMI device (zero-based index). */ -struct snd_pcm *hda_dsp_hdmi_pcm_handle(struct snd_soc_card *card, - int hdmi_idx) +static struct snd_pcm *hda_dsp_hdmi_pcm_handle(struct snd_soc_card *card, + int hdmi_idx) { struct snd_soc_pcm_runtime *rtd; struct snd_pcm *spcm; @@ -34,7 +36,6 @@ struct snd_pcm *hda_dsp_hdmi_pcm_handle(struct snd_soc_card *card, return NULL; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) /* * Search card topology and register HDMI PCM related controls * to codec driver. diff --git a/sound/soc/intel/boards/hda_dsp_common.h b/sound/soc/intel/boards/hda_dsp_common.h index 727edd256962..ea4ae9285cf0 100644 --- a/sound/soc/intel/boards/hda_dsp_common.h +++ b/sound/soc/intel/boards/hda_dsp_common.h @@ -15,9 +15,6 @@ #include <sound/hda_i915.h> #include "../../codecs/hdac_hda.h" -struct snd_pcm *hda_dsp_hdmi_pcm_handle(struct snd_soc_card *card, - int hdmi_idx); - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) int hda_dsp_hdmi_build_controls(struct snd_soc_card *card, struct snd_soc_component *comp); diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 0129d23694ed..ddbb9fe7cc06 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -119,6 +119,19 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { .driver_data = (void *)(SOF_RT5682_MCLK_EN | SOF_RT5682_SSP_CODEC(0)), }, + { + .callback = sof_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"), + DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"), + }, + .driver_data = (void *)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98373_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(2) | + SOF_RT5682_NUM_HDMIDEV(4)), + }, {} }; diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 2463d432bf4d..b29946eb4355 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -52,6 +52,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") + }, + .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX), + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") }, .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | @@ -123,56 +132,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, - - {} -}; - -static struct snd_soc_codec_conf codec_conf[] = { - { - .dlc = COMP_CODEC_CONF("sdw:0:25d:711:0"), - .name_prefix = "rt711", - }, - /* rt1308 w/ I2S connection */ - { - .dlc = COMP_CODEC_CONF("i2c-10EC1308:00"), - .name_prefix = "rt1308-1", - }, - /* rt1308 left on link 1 */ - { - .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0"), - .name_prefix = "rt1308-1", - }, - /* two 1308s on link1 with different unique id */ { - .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:0"), - .name_prefix = "rt1308-1", - }, - { - .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:2"), - .name_prefix = "rt1308-2", - }, - /* rt1308 right on link 2 */ - { - .dlc = COMP_CODEC_CONF("sdw:2:25d:1308:0"), - .name_prefix = "rt1308-2", - }, - { - .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", + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + SOF_SDW_FOUR_SPK), }, + + {} }; static struct snd_soc_dai_link_component dmic_component[] = { @@ -195,6 +165,84 @@ int sdw_startup(struct snd_pcm_substream *substream) return sdw_startup_stream(substream); } +int sdw_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct sdw_stream_runtime *sdw_stream; + struct snd_soc_dai *dai; + + /* Find stream from first CPU DAI */ + dai = asoc_rtd_to_cpu(rtd, 0); + + sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream); + + if (IS_ERR(sdw_stream)) { + dev_err(rtd->dev, "no stream found for DAI %s", dai->name); + return PTR_ERR(sdw_stream); + } + + return sdw_prepare_stream(sdw_stream); +} + +int sdw_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct sdw_stream_runtime *sdw_stream; + struct snd_soc_dai *dai; + int ret; + + /* Find stream from first CPU DAI */ + dai = asoc_rtd_to_cpu(rtd, 0); + + sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream); + + if (IS_ERR(sdw_stream)) { + dev_err(rtd->dev, "no stream found for DAI %s", dai->name); + return PTR_ERR(sdw_stream); + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + ret = sdw_enable_stream(sdw_stream); + break; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + ret = sdw_disable_stream(sdw_stream); + break; + default: + ret = -EINVAL; + break; + } + + if (ret) + dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret); + + return ret; +} + +int sdw_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct sdw_stream_runtime *sdw_stream; + struct snd_soc_dai *dai; + + /* Find stream from first CPU DAI */ + dai = asoc_rtd_to_cpu(rtd, 0); + + sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream); + + if (IS_ERR(sdw_stream)) { + dev_err(rtd->dev, "no stream found for DAI %s", dai->name); + return PTR_ERR(sdw_stream); + } + + return sdw_deprepare_stream(sdw_stream); +} + void sdw_shutdown(struct snd_pcm_substream *substream) { sdw_shutdown_stream(substream); @@ -202,25 +250,37 @@ void sdw_shutdown(struct snd_pcm_substream *substream) static const struct snd_soc_ops sdw_ops = { .startup = sdw_startup, + .prepare = sdw_prepare, + .trigger = sdw_trigger, + .hw_free = sdw_hw_free, .shutdown = sdw_shutdown, }; static struct sof_sdw_codec_info codec_info_list[] = { { - .id = 0x700, + .part_id = 0x700, .direction = {true, true}, .dai_name = "rt700-aif1", .init = sof_sdw_rt700_init, }, { - .id = 0x711, + .part_id = 0x711, + .version_id = 3, + .direction = {true, true}, + .dai_name = "rt711-sdca-aif1", + .init = sof_sdw_rt711_sdca_init, + .exit = sof_sdw_rt711_sdca_exit, + }, + { + .part_id = 0x711, + .version_id = 2, .direction = {true, true}, .dai_name = "rt711-aif1", .init = sof_sdw_rt711_init, .exit = sof_sdw_rt711_exit, }, { - .id = 0x1308, + .part_id = 0x1308, .acpi_id = "10EC1308", .direction = {true, false}, .dai_name = "rt1308-aif", @@ -228,38 +288,73 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt1308_init, }, { - .id = 0x715, + .part_id = 0x1316, + .direction = {true, true}, + .dai_name = "rt1316-aif", + .init = sof_sdw_rt1316_init, + }, + { + .part_id = 0x714, + .version_id = 3, + .direction = {false, true}, + .dai_name = "rt715-aif2", + .init = sof_sdw_rt715_sdca_init, + }, + { + .part_id = 0x715, + .version_id = 3, + .direction = {false, true}, + .dai_name = "rt715-aif2", + .init = sof_sdw_rt715_sdca_init, + }, + { + .part_id = 0x714, + .version_id = 2, .direction = {false, true}, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_init, }, { - .id = 0x8373, + .part_id = 0x715, + .version_id = 2, + .direction = {false, true}, + .dai_name = "rt715-aif2", + .init = sof_sdw_rt715_init, + }, + { + .part_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, + .part_id = 0x5682, .direction = {true, true}, .dai_name = "rt5682-sdw", .init = sof_sdw_rt5682_init, }, }; -static inline int find_codec_info_part(unsigned int part_id) +static inline int find_codec_info_part(u64 adr) { + unsigned int part_id, sdw_version; int i; + part_id = SDW_PART_ID(adr); + sdw_version = SDW_VERSION(adr); for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) - if (part_id == codec_info_list[i].id) - break; + /* + * A codec info is for all sdw version with the part id if + * version_id is not specified in the codec info. + */ + if (part_id == codec_info_list[i].part_id && + (!codec_info_list[i].version_id || + sdw_version == codec_info_list[i].version_id)) + return i; - if (i == ARRAY_SIZE(codec_info_list)) - return -EINVAL; + return -EINVAL; - return i; } static inline int find_codec_info_acpi(const u8 *acpi_id) @@ -305,13 +400,12 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links, for (link = links; link->num_adr; link++) { const struct snd_soc_acpi_endpoint *endpoint; - int part_id, codec_index; + int codec_index; int stream; u64 adr; adr = link->adr_d->adr; - part_id = SDW_PART_ID(adr); - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; @@ -400,10 +494,19 @@ static bool is_unique_device(const struct snd_soc_acpi_link_adr *link, static int create_codec_dai_name(struct device *dev, const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link_component *codec, - int offset) + int offset, + struct snd_soc_codec_conf *codec_conf, + int codec_count, + int *codec_conf_index) { int i; + /* sanity check */ + if (*codec_conf_index + link->num_adr > codec_count) { + dev_err(dev, "codec_conf: out-of-bounds access requested\n"); + return -EINVAL; + } + for (i = 0; i < link->num_adr; i++) { unsigned int sdw_version, unique_id, mfg_id; unsigned int link_id, part_id, class_id; @@ -439,12 +542,17 @@ static int create_codec_dai_name(struct device *dev, if (!codec[comp_index].name) return -ENOMEM; - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; codec[comp_index].dai_name = codec_info_list[codec_index].dai_name; + + codec_conf[*codec_conf_index].dlc = codec[comp_index]; + codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix; + + ++*codec_conf_index; } return 0; @@ -463,11 +571,9 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, * same group. */ for (i = 0; i < link->num_adr; i++) { - unsigned int part_id; int codec_index; - part_id = SDW_PART_ID(link->adr_d[i].adr); - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(link->adr_d[i].adr); if (codec_index < 0) return codec_index; @@ -565,13 +671,16 @@ static int create_sdw_dailink(struct device *dev, int *be_index, int sdw_be_num, int sdw_cpu_dai_num, struct snd_soc_dai_link_component *cpus, const struct snd_soc_acpi_link_adr *link, - int *cpu_id, bool *group_generated) + int *cpu_id, bool *group_generated, + struct snd_soc_codec_conf *codec_conf, + int codec_count, + int *codec_conf_index) { const struct snd_soc_acpi_link_adr *link_next; struct snd_soc_dai_link_component *codecs; int cpu_dai_id[SDW_MAX_CPU_DAIS]; int cpu_dai_num, cpu_dai_index; - unsigned int part_id, group_id; + unsigned int group_id; int codec_idx = 0; int i = 0, j = 0; int codec_index; @@ -603,7 +712,8 @@ static int create_sdw_dailink(struct device *dev, int *be_index, if (cpu_dai_id[i] != ffs(link_next->mask) - 1) continue; - ret = create_codec_dai_name(dev, link_next, codecs, codec_idx); + ret = create_codec_dai_name(dev, link_next, codecs, codec_idx, + codec_conf, codec_count, codec_conf_index); if (ret < 0) return ret; @@ -613,8 +723,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, } /* find codec info to create BE DAI */ - part_id = SDW_PART_ID(link->adr_d[0].adr); - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(link->adr_d[0].adr); if (codec_index < 0) return codec_index; @@ -701,6 +810,42 @@ static inline int get_next_be_id(struct snd_soc_dai_link *links, #define IDISP_CODEC_MASK 0x4 +static int sof_card_codec_conf_alloc(struct device *dev, + struct snd_soc_acpi_mach_params *mach_params, + struct snd_soc_codec_conf **codec_conf, + int *codec_conf_count) +{ + const struct snd_soc_acpi_link_adr *adr_link; + struct snd_soc_codec_conf *c_conf; + int num_codecs = 0; + int i; + + adr_link = mach_params->links; + if (!adr_link) + return -EINVAL; + + /* generate DAI links by each sdw link */ + for (; adr_link->num_adr; adr_link++) { + for (i = 0; i < adr_link->num_adr; i++) { + if (!adr_link->adr_d[i].name_prefix) { + dev_err(dev, "codec 0x%llx does not have a name prefix\n", + adr_link->adr_d[i].adr); + return -EINVAL; + } + } + num_codecs += adr_link->num_adr; + } + + c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL); + if (!c_conf) + return -ENOMEM; + + *codec_conf = c_conf; + *codec_conf_count = num_codecs; + + return 0; +} + static int sof_card_dai_links_create(struct device *dev, struct snd_soc_acpi_mach *mach, struct snd_soc_card *card) @@ -712,6 +857,9 @@ static int sof_card_dai_links_create(struct device *dev, struct snd_soc_acpi_mach_params *mach_params; const struct snd_soc_acpi_link_adr *adr_link; struct snd_soc_dai_link_component *cpus; + struct snd_soc_codec_conf *codec_conf; + int codec_conf_count; + int codec_conf_index = 0; bool group_generated[SDW_MAX_GROUPS]; int ssp_codec_index, ssp_mask; struct snd_soc_dai_link *links; @@ -724,12 +872,21 @@ static int sof_card_dai_links_create(struct device *dev, int comp_num; int ret; + mach_params = &mach->mach_params; + + /* allocate codec conf, will be populated when dailinks are created */ + ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count); + if (ret < 0) + return ret; + /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) codec_info_list[i].amp_num = 0; - hdmi_num = sof_sdw_quirk & SOF_SDW_TGL_HDMI ? - SOF_TGL_HDMI_COUNT : SOF_PRE_TGL_HDMI_COUNT; + if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) + hdmi_num = SOF_TGL_HDMI_COUNT; + else + hdmi_num = SOF_PRE_TGL_HDMI_COUNT; ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); /* @@ -742,7 +899,6 @@ static int sof_card_dai_links_create(struct device *dev, ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0; comp_num = hdmi_num + ssp_num; - mach_params = &mach->mach_params; ret = get_sdw_dailink_info(mach_params->links, &sdw_be_num, &sdw_cpu_dai_num); if (ret < 0) { @@ -806,7 +962,9 @@ static int sof_card_dai_links_create(struct device *dev, ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num, sdw_cpu_dai_num, cpus, adr_link, - &cpu_id, group_generated); + &cpu_id, group_generated, + codec_conf, codec_conf_count, + &codec_conf_index); if (ret < 0) { dev_err(dev, "failed to create dai link %d", be_id); return -ENOMEM; @@ -937,6 +1095,9 @@ DMIC: card->dai_link = links; card->num_links = num_links; + card->codec_conf = codec_conf; + card->num_configs = codec_conf_count; + return 0; } @@ -963,8 +1124,6 @@ static struct snd_soc_card card_sof_sdw = { .name = "soundwire", .owner = THIS_MODULE, .late_probe = sof_sdw_card_late_probe, - .codec_conf = codec_conf, - .num_configs = ARRAY_SIZE(codec_conf), }; static int mc_probe(struct platform_device *pdev) @@ -1032,12 +1191,43 @@ static int mc_probe(struct platform_device *pdev) return ret; } +static int mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_dai_link *link; + int ret; + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (!codec_info_list[i].exit) + continue; + /* + * We don't need to call .exit function if there is no matched + * dai link found. + */ + for_each_card_prelinks(card, j, link) { + if (!strcmp(link->codecs[0].dai_name, + codec_info_list[i].dai_name)) { + ret = codec_info_list[i].exit(&pdev->dev, link); + if (ret) + dev_warn(&pdev->dev, + "codec exit failed %d\n", + ret); + break; + } + } + } + + return 0; +} + static struct platform_driver sof_sdw_driver = { .driver = { .name = "sof_sdw", .pm = &snd_soc_pm_ops, }, .probe = mc_probe, + .remove = mc_remove, }; module_platform_driver(sof_sdw_driver); diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 12e32439ba46..f3cb6796363e 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -51,7 +51,8 @@ enum { #define SOF_SDW_NO_AGGREGATION BIT(12) struct sof_sdw_codec_info { - const int id; + const int part_id; + const int version_id; int amp_num; const u8 acpi_id[ACPI_ID_LEN]; const bool direction[2]; // playback & capture support @@ -63,6 +64,7 @@ struct sof_sdw_codec_info { struct sof_sdw_codec_info *info, bool playback); + int (*exit)(struct device *dev, struct snd_soc_dai_link *dai_link); bool late_probe; int (*codec_card_late_probe)(struct snd_soc_card *card); }; @@ -77,6 +79,9 @@ struct mc_private { extern unsigned long sof_sdw_quirk; int sdw_startup(struct snd_pcm_substream *substream); +int sdw_prepare(struct snd_pcm_substream *substream); +int sdw_trigger(struct snd_pcm_substream *substream, int cmd); +int sdw_hw_free(struct snd_pcm_substream *substream); void sdw_shutdown(struct snd_pcm_substream *substream); /* generic HDMI support */ @@ -94,6 +99,13 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, bool playback); int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link); +/* RT711-SDCA support */ +int sof_sdw_rt711_sdca_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_sdca_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, struct snd_soc_dai_link *dai_links, @@ -108,12 +120,24 @@ int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link, struct sof_sdw_codec_info *info, bool playback); +/* RT1316 support */ +int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + /* RT715 support */ int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); +/* RT715-SDCA support */ +int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + 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, diff --git a/sound/soc/intel/boards/sof_sdw_dmic.c b/sound/soc/intel/boards/sof_sdw_dmic.c index 89b0824b2381..19df0f7a1d85 100644 --- a/sound/soc/intel/boards/sof_sdw_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_dmic.c @@ -7,6 +7,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget dmic_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 6437872a9b3d..cfdf970c5800 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -6,8 +6,10 @@ #include <linux/device.h> #include <linux/errno.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include "sof_sdw_common.h" #include "sof_maxim_common.h" @@ -53,9 +55,43 @@ static int spk_init(struct snd_soc_pcm_runtime *rtd) return ret; } +static int max98373_sdw_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + /* enable max98373 first */ + ret = max98373_trigger(substream, cmd); + if (ret < 0) + break; + + ret = sdw_trigger(substream, cmd); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = sdw_trigger(substream, cmd); + if (ret < 0) + break; + + ret = max98373_trigger(substream, cmd); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + static const struct snd_soc_ops max_98373_sdw_ops = { .startup = sdw_startup, - .trigger = max98373_trigger, + .prepare = sdw_prepare, + .trigger = max98373_sdw_trigger, + .hw_free = sdw_hw_free, .shutdown = sdw_shutdown, }; diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index 3655e890acec..0d476f6f6313 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -7,8 +7,10 @@ #include <linux/device.h> #include <linux/errno.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include "sof_sdw_common.h" #include "../../codecs/rt1308.h" @@ -130,6 +132,10 @@ int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link, struct sof_sdw_codec_info *info, bool playback) { + /* Count amp number and do init on playback link only. */ + if (!playback) + return 0; + info->amp_num++; if (info->amp_num == 1) dai_links->init = first_spk_init; diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c new file mode 100644 index 000000000000..d6e1ebf18d57 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt1316.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt1316 - Helpers to handle RT1316 from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <sound/control.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> +#include "sof_sdw_common.h" + +static const struct snd_soc_dapm_widget rt1316_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +/* + * dapm routes for rt1316 will be registered dynamically according + * to the number of rt1316 used. The first two entries will be registered + * for one codec case, and the last two entries are also registered + * if two 1316s are used. + */ +static const struct snd_soc_dapm_route rt1316_map[] = { + { "Speaker", NULL, "rt1316-1 SPOL" }, + { "Speaker", NULL, "rt1316-1 SPOR" }, + { "Speaker", NULL, "rt1316-2 SPOL" }, + { "Speaker", NULL, "rt1316-2 SPOR" }, +}; + +static const struct snd_kcontrol_new rt1316_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static int first_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:rt1316", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt1316_controls, + ARRAY_SIZE(rt1316_controls)); + if (ret) { + dev_err(card->dev, "rt1316 controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt1316_widgets, + ARRAY_SIZE(rt1316_widgets)); + if (ret) { + dev_err(card->dev, "rt1316 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map, 2); + if (ret) + dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); + + return ret; +} + +static int second_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map + 2, 2); + if (ret) + dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); + + return ret; +} + +static int all_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + ret = first_spk_init(rtd); + if (ret) + return ret; + + return second_spk_init(rtd); +} + +int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* Count amp number and do init on playback link only. */ + if (!playback) + return 0; + + info->amp_num++; + if (info->amp_num == 1) + dai_links->init = first_spk_init; + + if (info->amp_num == 2) { + /* + * if two 1316s are in one dai link, the init function + * in this dai link will be first set for the first speaker, + * and it should be reset to initialize all speakers when + * the second speaker is found. + */ + if (dai_links->init) + dai_links->init = all_spk_init; + else + dai_links->init = second_spk_init; + } + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index da354ba83939..5fa1a59615b6 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -10,8 +10,10 @@ #include <linux/input.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include <sound/jack.h> #include "sof_sdw_common.h" diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 5f50491ba5ee..21e7e4a81779 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -8,8 +8,10 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/input.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include <sound/jack.h> #include "sof_sdw_common.h" @@ -21,9 +23,9 @@ static const struct snd_soc_dapm_widget rt700_widgets[] = { static const struct snd_soc_dapm_route rt700_map[] = { /* Headphones */ - { "Headphones", NULL, "HP" }, - { "Speaker", NULL, "SPK" }, - { "MIC2", NULL, "AMIC" }, + { "Headphones", NULL, "rt700 HP" }, + { "Speaker", NULL, "rt700 SPK" }, + { "rt700 MIC2", NULL, "AMIC" }, }; static const struct snd_kcontrol_new rt700_controls[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 606009fa3901..04074c09dded 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -10,8 +10,10 @@ #include <linux/input.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include <sound/jack.h> #include "sof_sdw_common.h" diff --git a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c new file mode 100644 index 000000000000..19496f0f9110 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt711_sdca - Helpers to handle RT711-SDCA from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/input.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/control.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> +#include <sound/jack.h> +#include "sof_sdw_common.h" + +/* + * Note this MUST be called before snd_soc_register_card(), so that the props + * are in place before the codec component driver's probe function parses them. + */ +static int rt711_sdca_add_codec_device_props(const char *sdw_dev_name) +{ + struct property_entry props[MAX_NO_PROPS] = {}; + struct device *sdw_dev; + int ret; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name); + if (!sdw_dev) + return -EPROBE_DEFER; + + if (SOF_RT711_JDSRC(sof_sdw_quirk)) { + props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", + SOF_RT711_JDSRC(sof_sdw_quirk)); + } + + ret = device_add_properties(sdw_dev, props); + put_device(sdw_dev); + + return ret; +} + +static const struct snd_soc_dapm_widget rt711_sdca_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route rt711_sdca_map[] = { + /* Headphones */ + { "Headphone", NULL, "rt711 HP" }, + { "rt711 MIC2", NULL, "Headset Mic" }, +}; + +static const struct snd_kcontrol_new rt711_sdca_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_jack_pin rt711_sdca_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + struct snd_soc_jack *jack; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s hs:rt711-sdca", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt711_sdca_controls, + ARRAY_SIZE(rt711_sdca_controls)); + if (ret) { + dev_err(card->dev, "rt711-sdca controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt711_sdca_widgets, + ARRAY_SIZE(rt711_sdca_widgets)); + if (ret) { + dev_err(card->dev, "rt711-sdca widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt711_sdca_map, + ARRAY_SIZE(rt711_sdca_map)); + + if (ret) { + dev_err(card->dev, "rt711-sdca map addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + &ctx->sdw_headset, + rt711_sdca_jack_pins, + ARRAY_SIZE(rt711_sdca_jack_pins)); + if (ret) { + dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n", + ret); + return ret; + } + + jack = &ctx->sdw_headset; + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, jack, NULL); + + if (ret) + dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n", + ret); + + return ret; +} + +int sof_sdw_rt711_sdca_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_sdca_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 ret; + + /* + * headset should be initialized once. + * Do it with dai link for playback. + */ + if (!playback) + return 0; + + ret = rt711_sdca_add_codec_device_props(dai_links->codecs[0].name); + if (ret < 0) + return ret; + + dai_links->init = rt711_sdca_rtd_init; + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c new file mode 100644 index 000000000000..c056e56a139b --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt715_sdca - Helpers to handle RT715-SDCA 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" + +static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:rt715-sdca", + card->components); + if (!card->components) + return -ENOMEM; + + return 0; +} + +int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* + * DAI ID is fixed at SDW_DMIC_DAI_ID for 715-SDCA to + * keep sdw DMIC and HDMI setting static in UCM + */ + if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX) + dai_links->id = SDW_DMIC_DAI_ID; + + dai_links->init = rt715_sdca_rtd_init; + + return 0; +} |