diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 77947060379fd7..e39ec40106c81e 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -322,6 +322,11 @@ static const struct config_entry config_table[] = { .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x43c8, }, + { + .flags = FLAG_SOF, + .device = 0xa0c8, + .codec_hid = "ESSX8336", + }, #endif /* Elkhart Lake */ diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 124cdcad319e5d..c69f0d85a7bdfa 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -23,6 +23,9 @@ #define SOF_ES8336_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0)) #define SOF_ES8336_SSP_CODEC_MASK (GENMASK(3, 0)) +#define SOF_ES8336_TGL_GPIO_QUIRK BIT(4) +#define SOF_ES8336_ENABLE_DMIC BIT(5) + static unsigned long quirk; static int quirk_override = -1; @@ -37,12 +40,19 @@ struct sof_es8336_private { }; static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, false }; - static const struct acpi_gpio_mapping acpi_es8336_gpios[] = { { "pa-enable-gpios", &pa_enable_gpio, 1 }, { } }; +static const struct acpi_gpio_params quirk_pa_enable_gpio = { 1, 0, false }; +static const struct acpi_gpio_mapping quirk_acpi_es8336_gpios[] = { + { "pa-enable-gpios", &quirk_pa_enable_gpio, 1 }, + { } +}; + +static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios; + static void log_quirks(struct device *dev) { dev_info(dev, "quirk SSP%ld", SOF_ES8336_SSP_CODEC(quirk)); @@ -75,6 +85,10 @@ static const struct snd_soc_dapm_widget sof_es8316_widgets[] = { SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), }; +static const struct snd_soc_dapm_widget dmic_widgets[] = { + SND_SOC_DAPM_MIC("SoC DMIC", NULL), +}; + static const struct snd_soc_dapm_route sof_es8316_audio_map[] = { {"Headphone", NULL, "HPOL"}, {"Headphone", NULL, "HPOR"}, @@ -93,6 +107,11 @@ static const struct snd_soc_dapm_route sof_es8316_intmic_in1_map[] = { {"MIC2", NULL, "Headset Mic"}, }; +static const struct snd_soc_dapm_route dmic_map[] = { + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, +}; + static const struct snd_kcontrol_new sof_es8316_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), SOC_DAPM_PIN_SWITCH("Headphone"), @@ -111,6 +130,26 @@ static struct snd_soc_jack_pin sof_es8316_jack_pins[] = { }, }; +static int dmic_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_card *card = runtime->card; + int ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, + ARRAY_SIZE(dmic_widgets)); + if (ret) { + dev_err(card->dev, "DMic widget addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map, + ARRAY_SIZE(dmic_map)); + if (ret) + dev_err(card->dev, "DMic map addition failed: %d\n", ret); + + return ret; +} + static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime) { struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component; @@ -152,14 +191,35 @@ static void sof_es8316_exit(struct snd_soc_pcm_runtime *rtd) snd_soc_component_set_jack(component, NULL, NULL); } +static int sof_es8336_quirk_cb(const struct dmi_system_id *id) +{ + quirk = (unsigned long)id->driver_data; + + if (quirk & SOF_ES8336_TGL_GPIO_QUIRK) + gpio_mapping = quirk_acpi_es8336_gpios; + + return 1; +} + static const struct dmi_system_id sof_es8336_quirk_table[] = { { + .callback = sof_es8336_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "CHUWI Innovation And Technology"), DMI_MATCH(DMI_BOARD_NAME, "Hi10 X"), }, .driver_data = (void *)SOF_ES8336_SSP_CODEC(2) }, + { + .callback = sof_es8336_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"), + DMI_MATCH(DMI_BOARD_NAME, "WN1"), + }, + .driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) | + SOF_ES8336_TGL_GPIO_QUIRK | + SOF_ES8336_ENABLE_DMIC) + }, {} }; @@ -202,6 +262,13 @@ static struct snd_soc_dai_link_component platform_component[] = { SND_SOC_DAILINK_DEF(ssp1_codec, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi"))); +static struct snd_soc_dai_link_component dmic_component[] = { + { + .name = "dmic-codec", + .dai_name = "dmic-hifi", + } +}; + /* SoC card */ static struct snd_soc_card sof_es8336_card = { .name = "essx8336", /* sof- prefix added automatically */ @@ -216,11 +283,14 @@ static struct snd_soc_card sof_es8336_card = { .num_links = 1, }; -static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, int ssp_codec) +static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, + int ssp_codec, + int dmic_be_num) { struct snd_soc_dai_link_component *cpus; struct snd_soc_dai_link *links; int id = 0; + int i; links = devm_kcalloc(dev, sof_es8336_card.num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL); @@ -258,7 +328,38 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, in id++; + /* dmic */ + if (dmic_be_num > 0) { + /* at least we have dmic01 */ + links[id].name = "dmic01"; + links[id].cpus = &cpus[id]; + links[id].cpus->dai_name = "DMIC01 Pin"; + links[id].init = dmic_init; + if (dmic_be_num > 1) { + /* set up 2 BE links at most */ + links[id + 1].name = "dmic16k"; + links[id + 1].cpus = &cpus[id + 1]; + links[id + 1].cpus->dai_name = "DMIC16k Pin"; + dmic_be_num = 2; + } + } + + for (i = 0; i < dmic_be_num; i++) { + links[id].id = id; + links[id].num_cpus = 1; + links[id].codecs = dmic_component; + links[id].num_codecs = ARRAY_SIZE(dmic_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].ignore_suspend = 1; + links[id].dpcm_capture = 1; + links[id].no_pcm = 1; + + id++; + } + return links; + devm_err: return NULL; } @@ -271,11 +372,11 @@ static int sof_es8336_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snd_soc_card *card; struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; - const struct dmi_system_id *dmi_id; struct sof_es8336_private *priv; struct acpi_device *adev; struct snd_soc_dai_link *dai_links; struct device *codec_dev; + int dmic_be_num; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -287,12 +388,11 @@ static int sof_es8336_probe(struct platform_device *pdev) card = &sof_es8336_card; card->dev = dev; - dmi_id = dmi_first_match(sof_es8336_quirk_table); - if (dmi_id) { - quirk = (unsigned long)dmi_id->driver_data; - } else { + if (!dmi_check_system(sof_es8336_quirk_table)) quirk = SOF_ES8336_SSP_CODEC(2); - } + + if (quirk & SOF_ES8336_ENABLE_DMIC) + dmic_be_num = 2; if (quirk_override != -1) { dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n", @@ -301,8 +401,10 @@ static int sof_es8336_probe(struct platform_device *pdev) } log_quirks(dev); + sof_es8336_card.num_links += dmic_be_num; dai_links = sof_card_dai_links_create(dev, - SOF_ES8336_SSP_CODEC(quirk)); + SOF_ES8336_SSP_CODEC(quirk), + dmic_be_num); if (!dai_links) return -ENOMEM; @@ -327,7 +429,7 @@ static int sof_es8336_probe(struct platform_device *pdev) if (!codec_dev) return -EPROBE_DEFER; - ret = devm_acpi_dev_add_driver_gpios(codec_dev, acpi_es8336_gpios); + ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping); if (ret) dev_warn(codec_dev, "unable to add GPIO mapping table\n"); diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 785d5f5f8a9c9c..f8ee4efe199883 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -355,6 +355,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = { .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg", }, + { + .id = "ESSX8336", + .drv_name = "sof-essx8336", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-es8336.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);