mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 18:23:53 +08:00
7de9a47c89
Add support for using snd-hda-codec-hdmi driver for HDMI/DP instead of ASoC hdac-hdmi. This is aligned with how other HDA codecs are already handled. When snd-hda-codec-hdmi is used, the PCM device numbers are parsed from card topology and passed to the codec driver. This needs to be done at runtime as topology changes may affect PCM device allocation. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Takashi Iwai <tiwai@suse.de> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20191029134017.18901-4-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
172 lines
4.2 KiB
C
172 lines
4.2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
// Copyright(c) 2015-18 Intel Corporation.
|
|
|
|
/*
|
|
* Common functions used in different Intel machine drivers
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <sound/core.h>
|
|
#include <sound/jack.h>
|
|
#include <sound/pcm.h>
|
|
#include <sound/pcm_params.h>
|
|
#include <sound/soc.h>
|
|
#include "../../codecs/hdac_hdmi.h"
|
|
#include "skl_hda_dsp_common.h"
|
|
|
|
#include <sound/hda_codec.h>
|
|
#include "../../codecs/hdac_hda.h"
|
|
|
|
#define NAME_SIZE 32
|
|
|
|
int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device)
|
|
{
|
|
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
|
|
struct skl_hda_hdmi_pcm *pcm;
|
|
char dai_name[NAME_SIZE];
|
|
|
|
pcm = devm_kzalloc(card->dev, sizeof(*pcm), GFP_KERNEL);
|
|
if (!pcm)
|
|
return -ENOMEM;
|
|
|
|
snprintf(dai_name, sizeof(dai_name), "intel-hdmi-hifi%d",
|
|
ctx->dai_index);
|
|
pcm->codec_dai = snd_soc_card_get_codec_dai(card, dai_name);
|
|
if (!pcm->codec_dai)
|
|
return -EINVAL;
|
|
|
|
pcm->device = device;
|
|
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
|
|
|
|
return 0;
|
|
}
|
|
|
|
SND_SOC_DAILINK_DEFS(idisp1,
|
|
DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")),
|
|
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
|
|
|
|
SND_SOC_DAILINK_DEFS(idisp2,
|
|
DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")),
|
|
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
|
|
|
|
SND_SOC_DAILINK_DEFS(idisp3,
|
|
DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")),
|
|
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
|
|
|
|
SND_SOC_DAILINK_DEF(analog_cpu,
|
|
DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI")));
|
|
SND_SOC_DAILINK_DEF(analog_codec,
|
|
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI")));
|
|
|
|
SND_SOC_DAILINK_DEF(digital_cpu,
|
|
DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI")));
|
|
SND_SOC_DAILINK_DEF(digital_codec,
|
|
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI")));
|
|
|
|
SND_SOC_DAILINK_DEF(dmic_pin,
|
|
DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
|
|
|
|
SND_SOC_DAILINK_DEF(dmic_codec,
|
|
DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
|
|
|
|
SND_SOC_DAILINK_DEF(dmic16k,
|
|
DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
|
|
|
|
SND_SOC_DAILINK_DEF(platform,
|
|
DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
|
|
|
|
/* skl_hda_digital audio interface glue - connects codec <--> CPU */
|
|
struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS] = {
|
|
/* Back End DAI links */
|
|
{
|
|
.name = "iDisp1",
|
|
.id = 1,
|
|
.dpcm_playback = 1,
|
|
.no_pcm = 1,
|
|
SND_SOC_DAILINK_REG(idisp1),
|
|
},
|
|
{
|
|
.name = "iDisp2",
|
|
.id = 2,
|
|
.dpcm_playback = 1,
|
|
.no_pcm = 1,
|
|
SND_SOC_DAILINK_REG(idisp2),
|
|
},
|
|
{
|
|
.name = "iDisp3",
|
|
.id = 3,
|
|
.dpcm_playback = 1,
|
|
.no_pcm = 1,
|
|
SND_SOC_DAILINK_REG(idisp3),
|
|
},
|
|
{
|
|
.name = "Analog Playback and Capture",
|
|
.id = 4,
|
|
.dpcm_playback = 1,
|
|
.dpcm_capture = 1,
|
|
.no_pcm = 1,
|
|
SND_SOC_DAILINK_REG(analog_cpu, analog_codec, platform),
|
|
},
|
|
{
|
|
.name = "Digital Playback and Capture",
|
|
.id = 5,
|
|
.dpcm_playback = 1,
|
|
.dpcm_capture = 1,
|
|
.no_pcm = 1,
|
|
SND_SOC_DAILINK_REG(digital_cpu, digital_codec, platform),
|
|
},
|
|
{
|
|
.name = "dmic01",
|
|
.id = 6,
|
|
.dpcm_capture = 1,
|
|
.no_pcm = 1,
|
|
SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
|
|
},
|
|
{
|
|
.name = "dmic16k",
|
|
.id = 7,
|
|
.dpcm_capture = 1,
|
|
.no_pcm = 1,
|
|
SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
|
|
},
|
|
};
|
|
|
|
int skl_hda_hdmi_jack_init(struct snd_soc_card *card)
|
|
{
|
|
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
|
|
struct snd_soc_component *component = NULL;
|
|
struct skl_hda_hdmi_pcm *pcm;
|
|
char jack_name[NAME_SIZE];
|
|
int err;
|
|
|
|
if (ctx->common_hdmi_codec_drv)
|
|
return skl_hda_hdmi_build_controls(card);
|
|
|
|
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
|
component = pcm->codec_dai->component;
|
|
snprintf(jack_name, sizeof(jack_name),
|
|
"HDMI/DP, pcm=%d Jack", pcm->device);
|
|
err = snd_soc_card_jack_new(card, jack_name,
|
|
SND_JACK_AVOUT, &pcm->hdmi_jack,
|
|
NULL, 0);
|
|
|
|
if (err)
|
|
return err;
|
|
|
|
err = snd_jack_add_new_kctl(pcm->hdmi_jack.jack,
|
|
jack_name, SND_JACK_AVOUT);
|
|
if (err)
|
|
dev_warn(component->dev, "failed creating Jack kctl\n");
|
|
|
|
err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
|
|
&pcm->hdmi_jack);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (!component)
|
|
return -EINVAL;
|
|
|
|
return hdac_hdmi_jack_port_init(component, &card->dapm);
|
|
}
|