From: Yong Zhi <yong.zhi@xxxxxxxxx> Add Maxim MAX98360A plug-and-play Class-D amplifier support on SSP1, new card ID is sofda7219max98360a, name sof-da7219max98360a. Signed-off-by: Yong Zhi <yong.zhi@xxxxxxxxx> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@xxxxxxxxxxxxxxx> --- sound/soc/intel/boards/Kconfig | 4 +- sound/soc/intel/boards/sof_da7219_max98373.c | 74 +++++++++++++++++-- .../intel/common/soc-acpi-intel-jsl-match.c | 19 ++++- 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 6833ef548710..ab4ce652cc1a 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -507,7 +507,7 @@ endif ## SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK if SND_SOC_SOF_JASPERLAKE config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH - tristate "SOF with DA7219 and MAX98373 in I2S Mode" + tristate "SOF with DA7219 and MAX98373/MAX98360A in I2S Mode" depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI @@ -516,7 +516,7 @@ config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH select SND_SOC_DMIC help This adds support for ASoC machine driver for SOF platforms - with DA7219 + MAX98373 I2S audio codec. + with DA7219 + MAX98373/MAX98360A I2S audio codec. Say Y if you have such a device. If unsure select "N". diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index 8c657da5fcf0..7847dd44f41b 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -2,7 +2,7 @@ // Copyright(c) 2019 Intel Corporation. /* - * Intel SOF Machine driver for DA7219 + MAX98373 codec + * Intel SOF Machine driver for DA7219 + MAX98373/MAX98360A codec */ #include <linux/input.h> @@ -69,11 +69,14 @@ static const struct snd_kcontrol_new controls[] = { SOC_DAPM_PIN_SWITCH("Right Spk"), }; +static const struct snd_kcontrol_new m98360a_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + static const struct snd_soc_dapm_widget widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), @@ -83,15 +86,23 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Headphone Jack", NULL, "HPL" }, { "Headphone Jack", NULL, "HPR" }, - { "Left Spk", NULL, "Left BE_OUT" }, - { "Right Spk", NULL, "Right BE_OUT" }, - { "MIC", NULL, "Headset Mic" }, { "Headphone Jack", NULL, "Platform Clock" }, { "Headset Mic", NULL, "Platform Clock" }, }; +/* For MAX98373 amp */ +static const struct snd_soc_dapm_widget max98373_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route max98373_map[] = { + { "Left Spk", NULL, "Left BE_OUT" }, + { "Right Spk", NULL, "Right BE_OUT" }, +}; + static struct snd_soc_jack headset; static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) @@ -133,6 +144,21 @@ static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } +static int speaker_amp_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + /* Add widgets */ + ret = snd_soc_dapm_new_controls(&rtd->card->dapm, max98373_widgets, + ARRAY_SIZE(max98373_widgets)); + if (ret) + return ret; + + /* Add routes */ + return snd_soc_dapm_add_routes(&rtd->card->dapm, max98373_map, + ARRAY_SIZE(max98373_map)); +} + static int ssp1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -223,6 +249,8 @@ SND_SOC_DAILINK_DEF(ssp1_amps, DAILINK_COMP_ARRAY( /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, MAX98373_CODEC_DAI), /* Right */ COMP_CODEC(MAXIM_DEV1_NAME, MAX98373_CODEC_DAI))); +/* For the driver-less spk amp */ +SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); @@ -254,6 +282,7 @@ static struct snd_soc_dai_link dais[] = { .id = 0, .ignore_pmdown_time = 1, .no_pcm = 1, + .init = speaker_amp_init, .dpcm_playback = 1, .dpcm_capture = 1, /* IV feedback */ .ops = &ssp1_ops, @@ -320,6 +349,21 @@ static struct snd_soc_card card_da7219_m98373 = { .late_probe = card_late_probe, }; +static struct snd_soc_card card_da7219_m98360a = { + .name = "da7219max98360a", + .owner = THIS_MODULE, + .dai_link = dais, + .num_links = ARRAY_SIZE(dais), + .controls = m98360a_controls, + .num_controls = ARRAY_SIZE(m98360a_controls), + .dapm_widgets = widgets, + .num_dapm_widgets = ARRAY_SIZE(widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), + .fully_routed = true, + .late_probe = card_late_probe, +}; + static int audio_probe(struct platform_device *pdev) { static struct snd_soc_card *card; @@ -331,6 +375,17 @@ static int audio_probe(struct platform_device *pdev) if (!ctx) return -ENOMEM; + /* By default dais[0] is configured for max98373 */ + if (!strcmp(pdev->name, "sof_da7219_max98360a")) { + dais[0] = (struct snd_soc_dai_link) { + .name = "SSP1-Codec", + .id = 0, + .no_pcm = 1, + .dpcm_playback = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(ssp1_pin, dummy, platform) }; + } + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); card = (struct snd_soc_card *)pdev->id_entry->driver_data; card->dev = &pdev->dev; @@ -351,13 +406,17 @@ static const struct platform_device_id board_ids[] = { .name = "sof_da7219_max98373", .driver_data = (kernel_ulong_t)&card_da7219_m98373, }, + { + .name = "sof_da7219_max98360a", + .driver_data = (kernel_ulong_t)&card_da7219_m98360a, + }, { } }; static struct platform_driver audio = { .probe = audio_probe, .driver = { - .name = "sof_da7219_max98373", + .name = "sof_da7219_max98_360a_373", .pm = &snd_soc_pm_ops, }, .id_table = board_ids, @@ -368,4 +427,5 @@ module_platform_driver(audio) MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver"); MODULE_AUTHOR("Yong Zhi <yong.zhi@xxxxxxxxx>"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sof_da7219_max98360a"); MODULE_ALIAS("platform:sof_da7219_max98373"); diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index ed2b125f6a11..70f01495a166 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -9,13 +9,30 @@ #include <sound/soc-acpi.h> #include <sound/soc-acpi-intel-match.h> +static struct snd_soc_acpi_codecs jsl_7219_98373_codecs = { + .num_codecs = 1, + .codecs = {"MX98373"} +}; + +/* + * When adding new entry to the snd_soc_acpi_intel_jsl_machines array, + * use .quirk_data member to distinguish different machine driver, + * and keep ACPI .id field unchanged for the common codec. + */ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { { .id = "DLGS7219", .drv_name = "sof_da7219_max98373", - .machine_quirk = snd_soc_acpi_codec_list, .sof_fw_filename = "sof-jsl.ri", .sof_tplg_filename = "sof-jsl-da7219.tplg", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &jsl_7219_98373_codecs, + }, + { + .id = "DLGS7219", + .drv_name = "sof_da7219_max98360a", + .sof_fw_filename = "sof-jsl.ri", + .sof_tplg_filename = "sof-jsl-da7219-mx98360a.tplg", }, {}, }; -- 2.20.1