From: Muralidhar Reddy <muralidhar.reddy@xxxxxxxxx> Adding support for 2 streams of HDMI-In capture via I2S in CBP_CFP configuration (codec provides bit clock and frame sync). Reviewed-by: Bard Liao <yung-chuan.liao@xxxxxxxxxxxxxxx> Signed-off-by: Muralidhar Reddy <muralidhar.reddy@xxxxxxxxx> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@xxxxxxxxxxxxxxx> --- sound/soc/intel/boards/sof_es8336.c | 126 +++++++++++++++--- .../intel/common/soc-acpi-intel-adl-match.c | 12 ++ 2 files changed, 118 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index d70d8255b8c7..f6a003d2da29 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -28,6 +28,24 @@ #define SOF_ES8336_SSP_CODEC_MASK (GENMASK(3, 0)) #define SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK BIT(4) + +/* HDMI capture*/ +#define SOF_SSP_HDMI_CAPTURE_PRESENT BIT(14) +#define SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT 15 +#define SOF_NO_OF_HDMI_CAPTURE_SSP_MASK (GENMASK(16, 15)) +#define SOF_NO_OF_HDMI_CAPTURE_SSP(quirk) \ + (((quirk) << SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT) & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) + +#define SOF_HDMI_CAPTURE_1_SSP_SHIFT 7 +#define SOF_HDMI_CAPTURE_1_SSP_MASK (GENMASK(9, 7)) +#define SOF_HDMI_CAPTURE_1_SSP(quirk) \ + (((quirk) << SOF_HDMI_CAPTURE_1_SSP_SHIFT) & SOF_HDMI_CAPTURE_1_SSP_MASK) + +#define SOF_HDMI_CAPTURE_2_SSP_SHIFT 10 +#define SOF_HDMI_CAPTURE_2_SSP_MASK (GENMASK(12, 10)) +#define SOF_HDMI_CAPTURE_2_SSP(quirk) \ + (((quirk) << SOF_HDMI_CAPTURE_2_SSP_SHIFT) & SOF_HDMI_CAPTURE_2_SSP_MASK) + #define SOF_ES8336_ENABLE_DMIC BIT(5) #define SOF_ES8336_JD_INVERTED BIT(6) #define SOF_ES8336_HEADPHONE_GPIO BIT(7) @@ -345,6 +363,13 @@ static struct snd_soc_dai_link_component dmic_component[] = { } }; +static struct snd_soc_dai_link_component dummy_component[] = { + { + .name = "snd-soc-dummy", + .dai_name = "snd-soc-dummy-dai", + } +}; + static int sof_es8336_late_probe(struct snd_soc_card *card) { struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); @@ -496,6 +521,37 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, id++; } + /* HDMI-In SSP */ + if (quirk & SOF_SSP_HDMI_CAPTURE_PRESENT) { + int num_of_hdmi_ssp = (quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >> + SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; + + for (i = 1; i <= num_of_hdmi_ssp; i++) { + int port = (i == 1 ? (quirk & SOF_HDMI_CAPTURE_1_SSP_MASK) >> + SOF_HDMI_CAPTURE_1_SSP_SHIFT : + (quirk & SOF_HDMI_CAPTURE_2_SSP_MASK) >> + SOF_HDMI_CAPTURE_2_SSP_SHIFT); + + links[id].cpus = &cpus[id]; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", port); + if (!links[id].cpus->dai_name) + return NULL; + links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", port); + if (!links[id].name) + return NULL; + links[id].id = id + hdmi_id_offset; + links[id].codecs = dummy_component; + links[id].num_codecs = ARRAY_SIZE(dummy_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].dpcm_capture = 1; + links[id].no_pcm = 1; + links[id].num_cpus = 1; + id++; + } + } + return links; devm_err: @@ -531,29 +587,38 @@ static int sof_es8336_probe(struct platform_device *pdev) card = &sof_es8336_card; card->dev = dev; + if (pdev->id_entry && pdev->id_entry->driver_data) + quirk = (unsigned long)pdev->id_entry->driver_data; + /* check GPIO DMI quirks */ dmi_check_system(sof_es8336_quirk_table); - if (!mach->mach_params.i2s_link_mask) { - dev_warn(dev, "No I2S link information provided, using SSP0. This may need to be modified with the quirk module parameter\n"); - } else { - /* - * Set configuration based on platform NHLT. - * In this machine driver, we can only support one SSP for the - * ES8336 link, the else-if below are intentional. - * In some cases multiple SSPs can be reported by NHLT, starting MSB-first - * seems to pick the right connection. - */ - unsigned long ssp = 0; - - if (mach->mach_params.i2s_link_mask & BIT(2)) - ssp = SOF_ES8336_SSP_CODEC(2); - else if (mach->mach_params.i2s_link_mask & BIT(1)) - ssp = SOF_ES8336_SSP_CODEC(1); - else if (mach->mach_params.i2s_link_mask & BIT(0)) - ssp = SOF_ES8336_SSP_CODEC(0); - - quirk |= ssp; + /* Use NHLT configuration only for Non-HDMI capture use case. + * Because more than one SSP will be enabled for HDMI capture hence wrong codec + * SSP will be set. + */ + if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER) { + if (!mach->mach_params.i2s_link_mask) { + dev_warn(dev, "No I2S link information provided, using SSP0. This may need to be modified with the quirk module parameter\n"); + } else { + /* + * Set configuration based on platform NHLT. + * In this machine driver, we can only support one SSP for the + * ES8336 link, the else-if below are intentional. + * In some cases multiple SSPs can be reported by NHLT, starting MSB-first + * seems to pick the right connection. + */ + unsigned long ssp = 0; + + if (mach->mach_params.i2s_link_mask & BIT(2)) + ssp = SOF_ES8336_SSP_CODEC(2); + else if (mach->mach_params.i2s_link_mask & BIT(1)) + ssp = SOF_ES8336_SSP_CODEC(1); + else if (mach->mach_params.i2s_link_mask & BIT(0)) + ssp = SOF_ES8336_SSP_CODEC(0); + + quirk |= ssp; + } } if (mach->mach_params.dmic_num) @@ -570,6 +635,11 @@ static int sof_es8336_probe(struct platform_device *pdev) dmic_be_num = 2; sof_es8336_card.num_links += dmic_be_num + hdmi_num; + + if (quirk & SOF_SSP_HDMI_CAPTURE_PRESENT) + sof_es8336_card.num_links += (quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >> + SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; + dai_links = sof_card_dai_links_create(dev, SOF_ES8336_SSP_CODEC(quirk), dmic_be_num, hdmi_num); @@ -691,6 +761,21 @@ static int sof_es8336_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id board_ids[] = { + { + .name = "adl_es83x6_c1_h02", + .driver_data = (kernel_ulong_t)(SOF_ES8336_SSP_CODEC(1) | + SOF_NO_OF_HDMI_CAPTURE_SSP(2) | + SOF_HDMI_CAPTURE_1_SSP(0) | + SOF_HDMI_CAPTURE_2_SSP(2) | + SOF_SSP_HDMI_CAPTURE_PRESENT | + SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK | + SOF_ES8336_JD_INVERTED), + }, + { } +}; +MODULE_DEVICE_TABLE(platform, board_ids); + static struct platform_driver sof_es8336_driver = { .driver = { .name = "sof-essx8336", @@ -698,6 +783,7 @@ static struct platform_driver sof_es8336_driver = { }, .probe = sof_es8336_probe, .remove = sof_es8336_remove, + .id_table = board_ids, }; module_platform_driver(sof_es8336_driver); diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 8fccd22b5953..9990d5502d26 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -440,6 +440,11 @@ static const struct snd_soc_acpi_codecs adl_max98390_amp = { .codecs = {"MX98390"} }; +static const struct snd_soc_acpi_codecs adl_lt6911_hdmi = { + .num_codecs = 1, + .codecs = {"INTC10B0"} +}; + struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { { .comp_ids = &adl_rt5682_rt5682s_hp, @@ -520,6 +525,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .drv_name = "adl_cs35l41", .sof_tplg_filename = "sof-adl-cs35l41.tplg", }, + { + .comp_ids = &essx_83x6, + .drv_name = "adl_es83x6_c1_h02", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &adl_lt6911_hdmi, + .sof_tplg_filename = "sof-adl-es83x6-ssp1-hdmi-ssp02.tplg", + }, { .comp_ids = &essx_83x6, .drv_name = "sof-essx8336", -- 2.34.1