diff options
author | Mark Brown <broonie@kernel.org> | 2023-11-28 15:24:41 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-11-28 15:24:41 +0300 |
commit | 4775073b90450cb581ba60be5cb6c587985a4152 (patch) | |
tree | dc4efb3bfe2fa32356e19120bd7ae6a124d8b877 /sound/soc/intel/boards/sof_rt5682.c | |
parent | b2b6b2d8f49b7e169765d283f394eb6b67d65c51 (diff) | |
parent | 8fa1116e1cae4858ab69d31da36f1fae9113c29d (diff) | |
download | linux-4775073b90450cb581ba60be5cb6c587985a4152.tar.xz |
ASoC: Intel: Link handling rework and fixes
Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:
SOF board updates for 6.8 including few small fix and the majority is to add
generic helpers for codec, amp, BT offload, HDMI-In and DAI link generation
among various machine drivers.
Diffstat (limited to 'sound/soc/intel/boards/sof_rt5682.c')
-rw-r--r-- | sound/soc/intel/boards/sof_rt5682.c | 328 |
1 files changed, 85 insertions, 243 deletions
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 9723479f43da..cd50f26d1edb 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -463,13 +463,6 @@ static struct snd_soc_ops sof_rt5682_ops = { .hw_params = sof_rt5682_hw_params, }; -static struct snd_soc_dai_link_component platform_component[] = { - { - /* name might be overridden during probe */ - .name = "0000:00:1f.3" - } -}; - static int sof_card_late_probe(struct snd_soc_card *card) { struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); @@ -570,69 +563,45 @@ static struct snd_soc_dai_link_component rt5650_components[] = { } }; -static struct snd_soc_dai_link * -sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec codec_type, - enum sof_ssp_codec amp_type, int ssp_codec, - int ssp_amp, int dmic_be_num, int hdmi_num, - bool idisp_codec, bool is_legacy_cpu) +static int +sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, + struct sof_card_private *ctx) { - struct snd_soc_dai_link_component *cpus; - struct snd_soc_dai_link *links; - int i; - int id = 0; int ret; - int hdmi_id_offset = 0; - - links = devm_kcalloc(dev, sof_audio_card_rt5682.num_links, - sizeof(struct snd_soc_dai_link), GFP_KERNEL); - cpus = devm_kcalloc(dev, sof_audio_card_rt5682.num_links, - sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); - if (!links || !cpus) - goto devm_err; - /* codec SSP */ - links[id].name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d-Codec", ssp_codec); - if (!links[id].name) - goto devm_err; + ret = sof_intel_board_set_dai_link(dev, card, ctx); + if (ret) + return ret; - links[id].id = id; + if (!ctx->codec_link) { + dev_err(dev, "codec link not available"); + return -EINVAL; + } - switch (codec_type) { + /* codec-specific fields for headphone codec */ + switch (ctx->codec_type) { case CODEC_RT5650: - links[id].codecs = &rt5650_components[0]; - links[id].num_codecs = 1; + ctx->codec_link->codecs = &rt5650_components[0]; + ctx->codec_link->num_codecs = 1; break; case CODEC_RT5682: - links[id].codecs = rt5682_component; - links[id].num_codecs = ARRAY_SIZE(rt5682_component); + ctx->codec_link->codecs = rt5682_component; + ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682_component); break; case CODEC_RT5682S: - links[id].codecs = rt5682s_component; - links[id].num_codecs = ARRAY_SIZE(rt5682s_component); + ctx->codec_link->codecs = rt5682s_component; + ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682s_component); break; default: - dev_err(dev, "invalid codec type %d\n", codec_type); - return NULL; + dev_err(dev, "invalid codec type %d\n", ctx->codec_type); + return -EINVAL; } - 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].dpcm_playback = 1; - links[id].dpcm_capture = 1; - links[id].no_pcm = 1; - links[id].cpus = &cpus[id]; - links[id].num_cpus = 1; - if (is_legacy_cpu) { - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "ssp%d-port", - ssp_codec); - if (!links[id].cpus->dai_name) - goto devm_err; - } else { + ctx->codec_link->init = sof_rt5682_codec_init; + ctx->codec_link->exit = sof_rt5682_codec_exit; + ctx->codec_link->ops = &sof_rt5682_ops; + + if (!ctx->rt5682.is_legacy_cpu) { /* * Currently, On SKL+ platforms MCLK will be turned off in sof * runtime suspended, and it will go into runtime suspended @@ -642,184 +611,66 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec codec_type, * avoid the noise. * It can be removed once we can control MCLK by driver. */ - links[id].ignore_pmdown_time = 1; - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d Pin", - ssp_codec); - if (!links[id].cpus->dai_name) - goto devm_err; - } - id++; - - /* dmic */ - if (dmic_be_num > 0) { - /* at least we have dmic01 */ - ret = sof_intel_board_set_dmic_link(dev, &links[id], id, - SOF_DMIC_01); - if (ret) - return NULL; - - id++; - } - - if (dmic_be_num > 1) { - /* set up 2 BE links at most */ - ret = sof_intel_board_set_dmic_link(dev, &links[id], id, - SOF_DMIC_16K); - if (ret) - return NULL; - - id++; - } - - /* HDMI */ - for (i = 1; i <= hdmi_num; i++) { - ret = sof_intel_board_set_intel_hdmi_link(dev, &links[id], id, - i, idisp_codec); - if (ret) - return NULL; - - id++; + ctx->codec_link->ignore_pmdown_time = 1; } - /* speaker amp */ - if (amp_type != CODEC_NONE) { - links[id].name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d-Codec", ssp_amp); - if (!links[id].name) - goto devm_err; - - links[id].id = id; - - switch (amp_type) { - case CODEC_MAX98357A: - max_98357a_dai_link(&links[id]); - break; - case CODEC_MAX98360A: - max_98360a_dai_link(&links[id]); - break; - case CODEC_MAX98373: - links[id].codecs = max_98373_components; - links[id].num_codecs = ARRAY_SIZE(max_98373_components); - links[id].init = max_98373_spk_codec_init; - links[id].ops = &max_98373_ops; - break; - case CODEC_MAX98390: - max_98390_dai_link(dev, &links[id]); - break; - case CODEC_RT1011: - sof_rt1011_dai_link(&links[id]); - break; - case CODEC_RT1015: - sof_rt1015_dai_link(&links[id]); - break; - case CODEC_RT1015P: - sof_rt1015p_dai_link(&links[id]); - break; - case CODEC_RT1019P: - sof_rt1019p_dai_link(&links[id]); - break; - case CODEC_RT5650: - /* use AIF2 to support speaker pipeline */ - links[id].codecs = &rt5650_components[1]; - links[id].num_codecs = 1; - links[id].init = rt5650_spk_init; - links[id].ops = &sof_rt5682_ops; - break; - default: - dev_err(dev, "invalid amp type %d\n", amp_type); - return NULL; - } - - links[id].platforms = platform_component; - links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].dpcm_playback = 1; - /* feedback stream or firmware-generated echo reference */ - links[id].dpcm_capture = 1; - - links[id].no_pcm = 1; - links[id].cpus = &cpus[id]; - links[id].num_cpus = 1; - if (is_legacy_cpu) { - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "ssp%d-port", - ssp_amp); - if (!links[id].cpus->dai_name) - goto devm_err; - - } else { - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d Pin", - ssp_amp); - if (!links[id].cpus->dai_name) - goto devm_err; - } - id++; - } + if (ctx->amp_type == CODEC_NONE) + return 0; - /* BT audio offload */ - if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { - int port = (sof_rt5682_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> - SOF_BT_OFFLOAD_SSP_SHIFT; - - links[id].id = id; - 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) - goto devm_err; - links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); - if (!links[id].name) - goto devm_err; - links[id].codecs = &snd_soc_dummy_dlc; - links[id].num_codecs = 1; - links[id].platforms = platform_component; - links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].dpcm_playback = 1; - links[id].dpcm_capture = 1; - links[id].no_pcm = 1; - links[id].num_cpus = 1; + if (!ctx->amp_link) { + dev_err(dev, "amp link not available"); + return -EINVAL; } - /* HDMI-In SSP */ - if (sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) { - unsigned long hdmi_in_ssp = (sof_rt5682_quirk & - SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) >> - SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; - int port = 0; - - for_each_set_bit(port, &hdmi_in_ssp, 32) { - 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 = &snd_soc_dummy_dlc; - links[id].num_codecs = 1; - 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++; - } + /* codec-specific fields for speaker amplifier */ + switch (ctx->amp_type) { + case CODEC_MAX98357A: + max_98357a_dai_link(ctx->amp_link); + break; + case CODEC_MAX98360A: + max_98360a_dai_link(ctx->amp_link); + break; + case CODEC_MAX98373: + ctx->amp_link->codecs = max_98373_components; + ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components); + ctx->amp_link->init = max_98373_spk_codec_init; + ctx->amp_link->ops = &max_98373_ops; + break; + case CODEC_MAX98390: + max_98390_dai_link(dev, ctx->amp_link); + break; + case CODEC_RT1011: + sof_rt1011_dai_link(ctx->amp_link); + break; + case CODEC_RT1015: + sof_rt1015_dai_link(ctx->amp_link); + break; + case CODEC_RT1015P: + sof_rt1015p_dai_link(ctx->amp_link); + break; + case CODEC_RT1019P: + sof_rt1019p_dai_link(ctx->amp_link); + break; + case CODEC_RT5650: + /* use AIF2 to support speaker pipeline */ + ctx->amp_link->codecs = &rt5650_components[1]; + ctx->amp_link->num_codecs = 1; + ctx->amp_link->init = rt5650_spk_init; + ctx->amp_link->ops = &sof_rt5682_ops; + break; + default: + dev_err(dev, "invalid amp type %d\n", ctx->amp_type); + return -EINVAL; } - return links; -devm_err: - return NULL; + return 0; } static int sof_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; - struct snd_soc_dai_link *dai_links; struct sof_card_private *ctx; - int ret, ssp_amp, ssp_codec; + int ret; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -885,34 +736,25 @@ static int sof_audio_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk); - ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >> - SOF_RT5682_SSP_AMP_SHIFT; + /* port number/mask of peripherals attached to ssp interface */ + ctx->ssp_mask_hdmi_in = (sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) >> + SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; - ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK; + ctx->ssp_bt = (sof_rt5682_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> + SOF_BT_OFFLOAD_SSP_SHIFT; - /* compute number of dai links */ - sof_audio_card_rt5682.num_links = 1 + ctx->dmic_be_num + ctx->hdmi_num; + ctx->ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >> + SOF_RT5682_SSP_AMP_SHIFT; - if (ctx->amp_type != CODEC_NONE) - sof_audio_card_rt5682.num_links++; + ctx->ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK; if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) - sof_audio_card_rt5682.num_links++; - - if (sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) - sof_audio_card_rt5682.num_links += - hweight32((sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) >> - SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT); - - dai_links = sof_card_dai_links_create(&pdev->dev, ctx->codec_type, - ctx->amp_type, ssp_codec, ssp_amp, - ctx->dmic_be_num, ctx->hdmi_num, - ctx->hdmi.idisp_codec, - ctx->rt5682.is_legacy_cpu); - if (!dai_links) - return -ENOMEM; + ctx->bt_offload_present = true; - sof_audio_card_rt5682.dai_link = dai_links; + /* update dai_link */ + ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_rt5682, ctx); + if (ret) + return ret; /* update codec_conf */ switch (ctx->amp_type) { |