diff options
Diffstat (limited to 'sound/soc/intel/boards')
40 files changed, 697 insertions, 182 deletions
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; |