ASoC: Intel: machine driver updates for 6.5

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

An unusually large set of patches to deal with new SoundWire-based
platforms.

The bulk of the patches addresses support for MTL using RT712, RT713,
MAX98363, CS42L42 jack codec and amplifiers. The sof_sdw machine
driver had to be updated to remove limitations on number of codecs per
links, dai types, dai naming, etc. We also moved parts of the Realtek
and Maxim support in common code to avoid duplication.

Community users also reported two Dell SKUs which were not supported
in the mainline due to hardware permutations.
This commit is contained in:
Mark Brown 2023-06-06 16:41:59 +01:00
commit 59960e67b9
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
15 changed files with 1045 additions and 226 deletions

View file

@ -662,11 +662,14 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST
depends on SOUNDWIRE
select SND_SOC_MAX98363
select SND_SOC_MAX98373_I2C
select SND_SOC_MAX98373_SDW
select SND_SOC_RT700_SDW
select SND_SOC_RT711_SDW
select SND_SOC_RT711_SDCA_SDW
select SND_SOC_RT712_SDCA_SDW
select SND_SOC_RT712_SDCA_DMIC_SDW
select SND_SOC_RT1308_SDW
select SND_SOC_RT1308
select SND_SOC_RT1316_SDW
@ -674,6 +677,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
select SND_SOC_RT715_SDW
select SND_SOC_RT715_SDCA_SDW
select SND_SOC_RT5682_SDW
select SND_SOC_CS42L42_SDW
select SND_SOC_DMIC
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_MAXIM_COMMON

View file

@ -37,11 +37,13 @@ snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o
snd-soc-ehl-rt5660-objs := ehl_rt5660.o
snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o
snd-soc-sof-sdw-objs += sof_sdw.o \
sof_sdw_max98373.o sof_sdw_rt_amp.o \
sof_sdw_maxim.o sof_sdw_rt_amp.o \
sof_sdw_rt5682.o sof_sdw_rt700.o \
sof_sdw_rt711.o sof_sdw_rt711_sdca.o \
sof_sdw_rt715.o sof_sdw_rt715_sdca.o \
sof_sdw_dmic.o sof_sdw_hdmi.o
sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \
sof_sdw_rt712_sdca.o sof_sdw_rt715.o \
sof_sdw_rt715_sdca.o sof_sdw_dmic.o \
sof_sdw_cs42l42.o \
sof_sdw_hdmi.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o

View file

@ -1119,6 +1119,17 @@ static const struct platform_device_id board_ids[] = {
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT),
},
{
.name = "rpl_rt1019_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1019_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT),
},
{
.name = "mtl_mx98357_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |

View file

@ -22,11 +22,16 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override");
#define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0)
#define SDW_MAX_LINKS 4
/* To store SDW Pin index for each SoundWire link */
static unsigned int sdw_pin_index[SDW_MAX_LINKS];
static void log_quirks(struct device *dev)
{
if (SOF_RT711_JDSRC(sof_sdw_quirk))
if (SOF_JACK_JDSRC(sof_sdw_quirk))
dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
SOF_RT711_JDSRC(sof_sdw_quirk));
SOF_JACK_JDSRC(sof_sdw_quirk));
if (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n");
if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
@ -371,6 +376,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
RT711_JD2 |
SOF_SDW_FOUR_SPK),
},
{
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"),
},
/* No Jack */
.driver_data = (void *)SOF_SDW_TGL_HDMI,
},
{
.callback = sof_sdw_quirk_cb,
.matches = {
@ -381,6 +395,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
RT711_JD2),
},
/* RaptorLake devices */
{
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA")
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
RT711_JD2 |
SOF_SDW_FOUR_SPK),
},
{
.callback = sof_sdw_quirk_cb,
.matches = {
@ -437,6 +461,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
},
.driver_data = (void *)(RT711_JD2_100K),
},
{
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
},
.driver_data = (void *)(SOF_SDW_PCH_DMIC),
},
/* LunarLake devices */
{
.callback = sof_sdw_quirk_cb,
@ -563,134 +595,323 @@ static const struct snd_soc_ops sdw_ops = {
static struct sof_sdw_codec_info codec_info_list[] = {
{
.part_id = 0x700,
.direction = {true, true},
.dai_name = "rt700-aif1",
.init = sof_sdw_rt700_init,
.codec_type = SOF_SDW_CODEC_TYPE_JACK,
.dais = {
{
.direction = {true, true},
.dai_name = "rt700-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt700_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x711,
.version_id = 3,
.direction = {true, true},
.dai_name = "rt711-sdca-aif1",
.init = sof_sdw_rt711_sdca_init,
.exit = sof_sdw_rt711_sdca_exit,
.codec_type = SOF_SDW_CODEC_TYPE_JACK,
.dais = {
{
.direction = {true, true},
.dai_name = "rt711-sdca-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt_sdca_jack_init,
.exit = sof_sdw_rt_sdca_jack_exit,
},
},
.dai_num = 1,
},
{
.part_id = 0x711,
.version_id = 2,
.direction = {true, true},
.dai_name = "rt711-aif1",
.init = sof_sdw_rt711_init,
.exit = sof_sdw_rt711_exit,
.codec_type = SOF_SDW_CODEC_TYPE_JACK,
.dais = {
{
.direction = {true, true},
.dai_name = "rt711-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt711_init,
.exit = sof_sdw_rt711_exit,
},
},
.dai_num = 1,
},
{
.part_id = 0x712,
.version_id = 3,
.dais = {
{
.direction = {true, true},
.dai_name = "rt712-sdca-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt_sdca_jack_init,
.exit = sof_sdw_rt_sdca_jack_exit,
},
{
.direction = {true, false},
.dai_name = "rt712-sdca-aif2",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
.init = sof_sdw_rt712_spk_init,
},
},
.dai_num = 2,
},
{
.part_id = 0x1712,
.version_id = 3,
.dais = {
{
.direction = {false, true},
.dai_name = "rt712-sdca-dmic-aif1",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
.init = sof_sdw_rt712_sdca_dmic_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x713,
.version_id = 3,
.dais = {
{
.direction = {true, true},
.dai_name = "rt712-sdca-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt_sdca_jack_init,
.exit = sof_sdw_rt_sdca_jack_exit,
},
},
.dai_num = 1,
},
{
.part_id = 0x1713,
.version_id = 3,
.dais = {
{
.direction = {false, true},
.dai_name = "rt712-sdca-dmic-aif1",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
.init = sof_sdw_rt712_sdca_dmic_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x1308,
.acpi_id = "10EC1308",
.direction = {true, false},
.dai_name = "rt1308-aif",
.dais = {
{
.direction = {true, false},
.dai_name = "rt1308-aif",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
},
},
.dai_num = 1,
.ops = &sof_sdw_rt1308_i2s_ops,
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
},
{
.part_id = 0x1316,
.direction = {true, true},
.dai_name = "rt1316-aif",
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
.dais = {
{
.direction = {true, true},
.dai_name = "rt1316-aif",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
},
},
.dai_num = 1,
},
{
.part_id = 0x1318,
.direction = {true, true},
.dai_name = "rt1318-aif",
.init = sof_sdw_rt_amp_init,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
.dais = {
{
.direction = {true, true},
.dai_name = "rt1318-aif",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
},
},
.dai_num = 1,
},
{
.part_id = 0x714,
.version_id = 3,
.direction = {false, true},
.ignore_pch_dmic = true,
.dai_name = "rt715-aif2",
.init = sof_sdw_rt715_sdca_init,
.codec_type = SOF_SDW_CODEC_TYPE_MIC,
.dais = {
{
.direction = {false, true},
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
.init = sof_sdw_rt715_sdca_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x715,
.version_id = 3,
.direction = {false, true},
.ignore_pch_dmic = true,
.dai_name = "rt715-aif2",
.init = sof_sdw_rt715_sdca_init,
.codec_type = SOF_SDW_CODEC_TYPE_MIC,
.dais = {
{
.direction = {false, true},
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
.init = sof_sdw_rt715_sdca_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x714,
.version_id = 2,
.direction = {false, true},
.ignore_pch_dmic = true,
.dai_name = "rt715-aif2",
.init = sof_sdw_rt715_init,
.codec_type = SOF_SDW_CODEC_TYPE_MIC,
.dais = {
{
.direction = {false, true},
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
.init = sof_sdw_rt715_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x715,
.version_id = 2,
.direction = {false, true},
.ignore_pch_dmic = true,
.dai_name = "rt715-aif2",
.init = sof_sdw_rt715_init,
.codec_type = SOF_SDW_CODEC_TYPE_MIC,
.dais = {
{
.direction = {false, true},
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
.init = sof_sdw_rt715_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x8373,
.direction = {true, true},
.dai_name = "max98373-aif1",
.init = sof_sdw_mx8373_init,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
.dais = {
{
.direction = {true, true},
.dai_name = "max98373-aif1",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
.init = sof_sdw_maxim_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x8363,
.dais = {
{
.direction = {true, false},
.dai_name = "max98363-aif1",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
.init = sof_sdw_maxim_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x5682,
.direction = {true, true},
.dai_name = "rt5682-sdw",
.init = sof_sdw_rt5682_init,
.codec_type = SOF_SDW_CODEC_TYPE_JACK,
.dais = {
{
.direction = {true, true},
.dai_name = "rt5682-sdw",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt5682_init,
},
},
.dai_num = 1,
},
{
.part_id = 0x4242,
.dais = {
{
.direction = {true, true},
.dai_name = "cs42l42-sdw",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_cs42l42_init,
},
},
.dai_num = 1,
},
{
.part_id = 0xaaaa, /* generic codec mockup */
.version_id = 0,
.direction = {true, true},
.dai_name = "sdw-mockup-aif1",
.init = NULL,
.codec_type = SOF_SDW_CODEC_TYPE_JACK,
.dais = {
{
.direction = {true, true},
.dai_name = "sdw-mockup-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = NULL,
},
},
.dai_num = 1,
},
{
.part_id = 0xaa55, /* headset codec mockup */
.version_id = 0,
.direction = {true, true},
.dai_name = "sdw-mockup-aif1",
.init = NULL,
.codec_type = SOF_SDW_CODEC_TYPE_JACK,
.dais = {
{
.direction = {true, true},
.dai_name = "sdw-mockup-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = NULL,
},
},
.dai_num = 1,
},
{
.part_id = 0x55aa, /* amplifier mockup */
.version_id = 0,
.direction = {true, false},
.dai_name = "sdw-mockup-aif1",
.init = NULL,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
.dais = {
{
.direction = {true, false},
.dai_name = "sdw-mockup-aif1",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
.init = NULL,
},
},
.dai_num = 1,
},
{
.part_id = 0x5555,
.version_id = 0,
.direction = {false, true},
.dai_name = "sdw-mockup-aif1",
.codec_type = SOF_SDW_CODEC_TYPE_MIC,
.dais = {
{
.dai_name = "sdw-mockup-aif1",
.direction = {false, true},
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
.init = NULL,
},
},
.dai_num = 1,
},
};
@ -742,10 +963,10 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li
int *sdw_be_num, int *sdw_cpu_dai_num)
{
const struct snd_soc_acpi_link_adr *link;
int _codec_type = SOF_SDW_CODEC_TYPE_JACK;
bool group_visited[SDW_MAX_GROUPS];
bool no_aggregation;
int i;
int j;
no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
*sdw_cpu_dai_num = 0;
@ -759,6 +980,7 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li
for (link = links; link->num_adr; link++) {
const struct snd_soc_acpi_endpoint *endpoint;
struct sof_sdw_codec_info *codec_info;
int codec_index;
int stream;
u64 adr;
@ -768,26 +990,23 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li
codec_index = find_codec_info_part(adr);
if (codec_index < 0)
return codec_index;
if (codec_info_list[codec_index].codec_type < _codec_type)
dev_warn(dev,
"Unexpected address table ordering. Expected order: jack -> amp -> mic\n");
_codec_type = codec_info_list[codec_index].codec_type;
codec_info = &codec_info_list[codec_index];
endpoint = link->adr_d[i].endpoints;
/* count DAI number for playback and capture */
for_each_pcm_streams(stream) {
if (!codec_info_list[codec_index].direction[stream])
continue;
for (j = 0; j < codec_info->dai_num; j++) {
/* count DAI number for playback and capture */
for_each_pcm_streams(stream) {
if (!codec_info->dais[j].direction[stream])
continue;
(*sdw_cpu_dai_num)++;
(*sdw_cpu_dai_num)++;
/* count BE for each non-aggregated slave or group */
if (!endpoint->aggregated || no_aggregation ||
!group_visited[endpoint->group_id])
(*sdw_be_num)++;
/* count BE for each non-aggregated slave or group */
if (!endpoint->aggregated || no_aggregation ||
!group_visited[endpoint->group_id])
(*sdw_be_num)++;
}
}
if (endpoint->aggregated)
@ -863,7 +1082,8 @@ static int create_codec_dai_name(struct device *dev,
struct snd_soc_codec_conf *codec_conf,
int codec_count,
int *codec_conf_index,
int adr_index)
int adr_index,
int dai_index)
{
int _codec_index = -1;
int i;
@ -919,7 +1139,7 @@ static int create_codec_dai_name(struct device *dev,
_codec_index = codec_index;
codec[comp_index].dai_name =
codec_info_list[codec_index].dai_name;
codec_info_list[codec_index].dais[dai_index].dai_name;
codec_conf[*codec_conf_index].dlc = codec[comp_index];
codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix;
@ -933,7 +1153,7 @@ static int create_codec_dai_name(struct device *dev,
static int set_codec_init_func(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
bool playback, int group_id, int adr_index)
bool playback, int group_id, int adr_index, int dai_index)
{
int i = adr_index;
@ -953,11 +1173,13 @@ static int set_codec_init_func(struct snd_soc_card *card,
if (codec_index < 0)
return codec_index;
/* The group_id is > 0 iff the codec is aggregated */
if (link->adr_d[i].endpoints->group_id != group_id)
continue;
if (codec_info_list[codec_index].init)
codec_info_list[codec_index].init(card,
if (codec_info_list[codec_index].dais[dai_index].init)
codec_info_list[codec_index].dais[dai_index].init(card,
link,
dai_links,
&codec_info_list[codec_index],
@ -1072,19 +1294,21 @@ static int create_sdw_dailink(struct snd_soc_card *card,
int codec_count, int *link_id,
int *codec_conf_index,
bool *ignore_pch_dmic,
bool append_codec_type,
int adr_index)
bool append_dai_type,
int adr_index,
int dai_index)
{
const struct snd_soc_acpi_link_adr *link_next;
struct snd_soc_dai_link_component *codecs;
struct sof_sdw_codec_info *codec_info;
int cpu_dai_id[SDW_MAX_CPU_DAIS];
int cpu_dai_num, cpu_dai_index;
unsigned int group_id;
int codec_idx = 0;
int i = 0, j = 0;
int codec_index;
int codec_num;
int stream;
int i = 0;
int ret;
int k;
@ -1112,7 +1336,8 @@ static int create_sdw_dailink(struct snd_soc_card *card,
continue;
ret = create_codec_dai_name(dev, link_next, codecs, codec_idx,
codec_conf, codec_count, codec_conf_index, adr_index);
codec_conf, codec_count, codec_conf_index,
adr_index, dai_index);
if (ret < 0)
return ret;
@ -1125,23 +1350,11 @@ static int create_sdw_dailink(struct snd_soc_card *card,
codec_index = find_codec_info_part(link->adr_d[adr_index].adr);
if (codec_index < 0)
return codec_index;
codec_info = &codec_info_list[codec_index];
if (codec_info_list[codec_index].ignore_pch_dmic)
if (codec_info->ignore_pch_dmic)
*ignore_pch_dmic = true;
/* Shift the first amplifier's *link_id to SDW_AMP_DAI_ID */
if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_AMP &&
*link_id < SDW_AMP_DAI_ID)
*link_id = SDW_AMP_DAI_ID;
/*
* DAI ID is fixed at SDW_DMIC_DAI_ID for MICs to
* keep sdw DMIC and HDMI setting static in UCM
*/
if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_MIC &&
*link_id < SDW_DMIC_DAI_ID)
*link_id = SDW_DMIC_DAI_ID;
cpu_dai_index = *cpu_id;
for_each_pcm_streams(stream) {
char *name, *cpu_name;
@ -1153,14 +1366,20 @@ static int create_sdw_dailink(struct snd_soc_card *card,
"SDW%d-Capture-%s",
};
if (!codec_info_list[codec_index].direction[stream])
if (!codec_info->dais[dai_index].direction[stream])
continue;
*link_id = codec_info->dais[dai_index].dailink[stream];
if (*link_id < 0) {
dev_err(dev, "Invalid dailink id %d\n", *link_id);
return -EINVAL;
}
/* create stream name according to first link id */
if (append_codec_type) {
if (append_dai_type) {
name = devm_kasprintf(dev, GFP_KERNEL,
sdw_stream_name[stream + 2], cpu_dai_id[0],
type_strings[codec_info_list[codec_index].codec_type]);
type_strings[codec_info->dais[dai_index].dai_type]);
} else {
name = devm_kasprintf(dev, GFP_KERNEL,
sdw_stream_name[stream], cpu_dai_id[0]);
@ -1175,7 +1394,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
for (k = 0; k < cpu_dai_num; k++) {
cpu_name = devm_kasprintf(dev, GFP_KERNEL,
"SDW%d Pin%d", cpu_dai_id[k],
j + SDW_INTEL_BIDIR_PDI_BASE);
sdw_pin_index[cpu_dai_id[k]]++);
if (!cpu_name)
return -ENOMEM;
@ -1217,14 +1436,13 @@ static int create_sdw_dailink(struct snd_soc_card *card,
dai_links[*link_index].nonatomic = true;
ret = set_codec_init_func(card, link, dai_links + (*link_index)++,
playback, group_id, adr_index);
playback, group_id, adr_index, dai_index);
if (ret < 0) {
dev_err(dev, "failed to init codec %d", codec_index);
return ret;
}
*cpu_id += cpu_dai_num;
j++;
}
return 0;
@ -1240,6 +1458,7 @@ static int sof_card_codec_conf_alloc(struct device *dev,
const struct snd_soc_acpi_link_adr *adr_link;
struct snd_soc_codec_conf *c_conf;
int num_codecs = 0;
int codec_index;
int i;
adr_link = mach_params->links;
@ -1254,8 +1473,11 @@ static int sof_card_codec_conf_alloc(struct device *dev,
adr_link->adr_d[i].adr);
return -EINVAL;
}
codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
if (codec_index < 0)
return codec_index;
num_codecs += codec_info_list[codec_index].dai_num;
}
num_codecs += adr_link->num_adr;
}
c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL);
@ -1280,7 +1502,7 @@ static int sof_card_dai_links_create(struct device *dev,
const struct snd_soc_acpi_link_adr *adr_link;
struct snd_soc_dai_link_component *cpus;
struct snd_soc_codec_conf *codec_conf;
bool append_codec_type = false;
bool append_dai_type = false;
bool ignore_pch_dmic = false;
int codec_conf_count;
int codec_conf_index = 0;
@ -1292,6 +1514,7 @@ static int sof_card_dai_links_create(struct device *dev,
int total_cpu_dai_num;
int sdw_cpu_dai_num;
int i, j, be_id = 0;
int codec_index;
int cpu_id = 0;
int comp_num;
int ret;
@ -1372,6 +1595,9 @@ static int sof_card_dai_links_create(struct device *dev,
for (i = 0; i < SDW_MAX_GROUPS; i++)
group_generated[i] = false;
for (i = 0; i < SDW_MAX_LINKS; i++)
sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE;
for (; adr_link->num_adr; adr_link++) {
/*
* If there are two or more different devices on the same sdw link, we have to
@ -1380,12 +1606,20 @@ static int sof_card_dai_links_create(struct device *dev,
* snd_soc_acpi_adr_device array. They won't be described in different adr_links.
*/
for (i = 0; i < adr_link->num_adr; i++) {
/* find codec info to get dai_num */
codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
if (codec_index < 0)
return codec_index;
if (codec_info_list[codec_index].dai_num > 1) {
append_dai_type = true;
goto out;
}
for (j = 0; j < i; j++) {
if ((SDW_PART_ID(adr_link->adr_d[i].adr) !=
SDW_PART_ID(adr_link->adr_d[j].adr)) ||
(SDW_MFG_ID(adr_link->adr_d[i].adr) !=
SDW_MFG_ID(adr_link->adr_d[i].adr))) {
append_codec_type = true;
append_dai_type = true;
goto out;
}
}
@ -1410,15 +1644,22 @@ static int sof_card_dai_links_create(struct device *dev,
group_generated[endpoint->group_id])
continue;
ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num,
sdw_cpu_dai_num, cpus, adr_link,
&cpu_id, group_generated,
codec_conf, codec_conf_count,
&be_id, &codec_conf_index,
&ignore_pch_dmic, append_codec_type, i);
if (ret < 0) {
dev_err(dev, "failed to create dai link %d", link_index);
return ret;
/* find codec info to get dai_num */
codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
if (codec_index < 0)
return codec_index;
for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) {
ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num,
sdw_cpu_dai_num, cpus, adr_link,
&cpu_id, group_generated,
codec_conf, codec_conf_count,
&be_id, &codec_conf_index,
&ignore_pch_dmic, append_dai_type, i, j);
if (ret < 0) {
dev_err(dev, "failed to create dai link %d", link_index);
return ret;
}
}
}
}
@ -1457,18 +1698,19 @@ static int sof_card_dai_links_create(struct device *dev,
return -ENOMEM;
ssp_components->name = codec_name;
ssp_components->dai_name = info->dai_name;
/* TODO: support multi codec dai on SSP when it is needed */
ssp_components->dai_name = info->dais[0].dai_name;
cpus[cpu_id].dai_name = cpu_name;
playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
init_dai_link(dev, links + link_index, be_id, name,
playback, capture,
cpus + cpu_id, 1,
ssp_components, 1,
NULL, info->ops);
ret = info->init(card, NULL, links + link_index, info, 0);
ret = info->dais[0].init(card, NULL, links + link_index, info, 0);
if (ret < 0)
return ret;
@ -1598,6 +1840,24 @@ static struct snd_soc_card card_sof_sdw = {
.late_probe = sof_sdw_card_late_probe,
};
/* helper to get the link that the codec DAI is used */
static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card,
const char *dai_name)
{
struct snd_soc_dai_link *link;
int i;
int j;
for_each_card_prelinks(card, i, link) {
for (j = 0; j < link->num_codecs; j++) {
/* Check each codec in a link */
if (!strcmp(link->codecs[j].dai_name, dai_name))
return link;
}
}
return NULL;
}
static void mc_dailink_exit_loop(struct snd_soc_card *card)
{
struct snd_soc_dai_link *link;
@ -1605,16 +1865,18 @@ static void mc_dailink_exit_loop(struct snd_soc_card *card)
int i, j;
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
if (!codec_info_list[i].exit)
continue;
/*
* We don't need to call .exit function if there is no matched
* dai link found.
*/
for_each_card_prelinks(card, j, link) {
if (!strcmp(link->codecs[0].dai_name,
codec_info_list[i].dai_name)) {
ret = codec_info_list[i].exit(card, link);
for (j = 0; j < codec_info_list[i].dai_num; j++) {
/* Check each dai in codec_info_lis to see if it is used in the link */
if (!codec_info_list[i].dais[j].exit)
continue;
/*
* We don't need to call .exit function if there is no matched
* dai link found.
*/
link = mc_find_codec_dai_used(card, codec_info_list[i].dais[j].dai_name);
if (link) {
/* Do the .exit function if the codec dai is used in the link */
ret = codec_info_list[i].dais[j].exit(card, link);
if (ret)
dev_warn(card->dev,
"codec exit failed %d\n",

View file

@ -15,7 +15,11 @@
#define MAX_NO_PROPS 2
#define MAX_HDMI_NUM 4
#define SDW_AMP_DAI_ID 2
#define SDW_UNUSED_DAI_ID -1
#define SDW_JACK_OUT_DAI_ID 0
#define SDW_JACK_IN_DAI_ID 1
#define SDW_AMP_OUT_DAI_ID 2
#define SDW_AMP_IN_DAI_ID 3
#define SDW_DMIC_DAI_ID 4
#define SDW_MAX_CPU_DAIS 16
#define SDW_INTEL_BIDIR_PDI_BASE 2
@ -37,7 +41,7 @@ enum {
SOF_I2S_SSP5 = BIT(5),
};
#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
#define SOF_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
#define SOF_SDW_FOUR_SPK BIT(4)
#define SOF_SDW_TGL_HDMI BIT(5)
#define SOF_SDW_PCH_DMIC BIT(6)
@ -52,28 +56,37 @@ enum {
(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(18)
#define SOF_SDW_CODEC_TYPE_JACK 0
#define SOF_SDW_CODEC_TYPE_AMP 1
#define SOF_SDW_CODEC_TYPE_MIC 2
#define SOF_SDW_DAI_TYPE_JACK 0
#define SOF_SDW_DAI_TYPE_AMP 1
#define SOF_SDW_DAI_TYPE_MIC 2
struct sof_sdw_codec_info {
const int part_id;
const int version_id;
const int codec_type;
int amp_num;
const u8 acpi_id[ACPI_ID_LEN];
const bool direction[2]; // playback & capture support
const bool ignore_pch_dmic;
#define SOF_SDW_MAX_DAI_NUM 3
struct sof_sdw_codec_info;
struct sof_sdw_dai_info {
const bool direction[2]; /* playback & capture support */
const char *dai_name;
const struct snd_soc_ops *ops;
const int dai_type;
const int dailink[2]; /* dailink id for each direction */
int (*init)(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
};
struct sof_sdw_codec_info {
const int part_id;
const int version_id;
int amp_num;
const u8 acpi_id[ACPI_ID_LEN];
const bool ignore_pch_dmic;
const struct snd_soc_ops *ops;
struct sof_sdw_dai_info dais[SOF_SDW_MAX_DAI_NUM];
const int dai_num;
int (*codec_card_late_probe)(struct snd_soc_card *card);
};
@ -110,12 +123,30 @@ int sof_sdw_rt711_init(struct snd_soc_card *card,
int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
/* RT711-SDCA support */
int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
/* RT712-SDCA support */
int sof_sdw_rt712_sdca_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
int sof_sdw_rt712_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
int sof_sdw_rt712_spk_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
int sof_sdw_rt712_sdca_dmic_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
/* RT700 support */
int sof_sdw_rt700_init(struct snd_soc_card *card,
@ -151,12 +182,12 @@ int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
struct sof_sdw_codec_info *info,
bool playback);
/* MAX98373 support */
int sof_sdw_mx8373_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
/* MAXIM codec support */
int sof_sdw_maxim_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
/* RT5682 support */
int sof_sdw_rt5682_init(struct snd_soc_card *card,
@ -165,4 +196,11 @@ int sof_sdw_rt5682_init(struct snd_soc_card *card,
struct sof_sdw_codec_info *info,
bool playback);
/* CS42L42 support */
int sof_sdw_cs42l42_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
#endif

View file

@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2023 Intel Corporation
/*
* sof_sdw_cs42l42 - Helpers to handle CS42L42 from generic machine driver
*/
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <sound/control.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget cs42l42_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
};
static const struct snd_soc_dapm_route cs42l42_map[] = {
/* HP jack connectors - unknown if we have jack detection */
{"Headphone", NULL, "cs42l42 HP"},
/* other jacks */
{"cs42l42 HS", NULL, "Headset Mic"},
};
static const struct snd_kcontrol_new cs42l42_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
};
static struct snd_soc_jack_pin cs42l42_jack_pins[] = {
{
.pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
},
{
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
},
};
static int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
struct snd_soc_jack *jack;
int ret;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s hs:cs42l42",
card->components);
if (!card->components)
return -ENOMEM;
ret = snd_soc_add_card_controls(card, cs42l42_controls,
ARRAY_SIZE(cs42l42_controls));
if (ret) {
dev_err(card->dev, "cs42l42 control addition failed: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_new_controls(&card->dapm, cs42l42_widgets,
ARRAY_SIZE(cs42l42_widgets));
if (ret) {
dev_err(card->dev, "cs42l42 widgets addition failed: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_add_routes(&card->dapm, cs42l42_map,
ARRAY_SIZE(cs42l42_map));
if (ret) {
dev_err(card->dev, "cs42l42 map addition failed: %d\n", ret);
return ret;
}
ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
SND_JACK_BTN_3,
&ctx->sdw_headset,
cs42l42_jack_pins,
ARRAY_SIZE(cs42l42_jack_pins));
if (ret) {
dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n",
ret);
return ret;
}
jack = &ctx->sdw_headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret)
dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n",
ret);
return ret;
}
int sof_sdw_cs42l42_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
{
/*
* headset should be initialized once.
* Do it with dai link for playback.
*/
if (!playback)
return 0;
dai_links->init = cs42l42_rtd_init;
return 0;
}

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
//
// sof_sdw_max98373 - Helpers to handle 2x MAX98373
// sof_sdw_maxim - Helpers to handle maxim codecs
// codec devices from generic machine driver
#include <linux/device.h>
@ -13,12 +13,16 @@
#include "sof_sdw_common.h"
#include "sof_maxim_common.h"
static const struct snd_soc_dapm_widget mx8373_widgets[] = {
static int maxim_part_id;
#define SOF_SDW_PART_ID_MAX98363 0x8363
#define SOF_SDW_PART_ID_MAX98373 0x8373
static const struct snd_soc_dapm_widget maxim_widgets[] = {
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
};
static const struct snd_kcontrol_new mx8373_controls[] = {
static const struct snd_kcontrol_new maxim_controls[] = {
SOC_DAPM_PIN_SWITCH("Left Spk"),
SOC_DAPM_PIN_SWITCH("Right Spk"),
};
@ -29,22 +33,25 @@ static int spk_init(struct snd_soc_pcm_runtime *rtd)
int ret;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s spk:mx8373",
card->components);
"%s spk:mx%04x",
card->components, maxim_part_id);
if (!card->components)
return -ENOMEM;
ret = snd_soc_add_card_controls(card, mx8373_controls,
ARRAY_SIZE(mx8373_controls));
dev_dbg(card->dev, "soundwire maxim card components assigned : %s\n",
card->components);
ret = snd_soc_add_card_controls(card, maxim_controls,
ARRAY_SIZE(maxim_controls));
if (ret) {
dev_err(card->dev, "mx8373 ctrls addition failed: %d\n", ret);
dev_err(card->dev, "mx%04x ctrls addition failed: %d\n", maxim_part_id, ret);
return ret;
}
ret = snd_soc_dapm_new_controls(&card->dapm, mx8373_widgets,
ARRAY_SIZE(mx8373_widgets));
ret = snd_soc_dapm_new_controls(&card->dapm, maxim_widgets,
ARRAY_SIZE(maxim_widgets));
if (ret) {
dev_err(card->dev, "mx8373 widgets addition failed: %d\n", ret);
dev_err(card->dev, "mx%04x widgets addition failed: %d\n", maxim_part_id, ret);
return ret;
}
@ -130,19 +137,30 @@ static int mx8373_sdw_late_probe(struct snd_soc_card *card)
return snd_soc_dapm_sync(dapm);
}
int sof_sdw_mx8373_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
int sof_sdw_maxim_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
{
info->amp_num++;
if (info->amp_num == 2)
dai_links->init = spk_init;
info->codec_card_late_probe = mx8373_sdw_late_probe;
dai_links->ops = &max_98373_sdw_ops;
maxim_part_id = info->part_id;
switch (maxim_part_id) {
case SOF_SDW_PART_ID_MAX98363:
/* Default ops are set in function init_dai_link.
* called as part of function create_sdw_dailink
*/
break;
case SOF_SDW_PART_ID_MAX98373:
info->codec_card_late_probe = mx8373_sdw_late_probe;
dai_links->ops = &max_98373_sdw_ops;
break;
default:
dev_err(card->dev, "Invalid maxim_part_id %#x\n", maxim_part_id);
return -EINVAL;
}
return 0;
}

View file

@ -27,9 +27,9 @@ static int rt711_add_codec_device_props(struct device *sdw_dev)
struct fwnode_handle *fwnode;
int ret;
if (!SOF_RT711_JDSRC(sof_sdw_quirk))
if (!SOF_JACK_JDSRC(sof_sdw_quirk))
return 0;
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_JACK_JDSRC(sof_sdw_quirk));
fwnode = fwnode_create_software_node(props, NULL);
if (IS_ERR(fwnode))

View file

@ -0,0 +1,102 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2023 Intel Corporation
/*
* sof_sdw_rt712_sdca - Helpers to handle RT712-SDCA from generic machine driver
*/
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <sound/control.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget rt712_spk_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
};
/*
* dapm routes for rt712 spk will be registered dynamically according
* to the number of rt712 spk used. The first two entries will be registered
* for one codec case, and the last two entries are also registered
* if two rt712s are used.
*/
static const struct snd_soc_dapm_route rt712_spk_map[] = {
{ "Speaker", NULL, "rt712 SPOL" },
{ "Speaker", NULL, "rt712 SPOR" },
};
static const struct snd_kcontrol_new rt712_spk_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
};
static int rt712_spk_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s spk:rt712",
card->components);
if (!card->components)
return -ENOMEM;
ret = snd_soc_add_card_controls(card, rt712_spk_controls,
ARRAY_SIZE(rt712_spk_controls));
if (ret) {
dev_err(card->dev, "rt712 spk controls addition failed: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_new_controls(&card->dapm, rt712_spk_widgets,
ARRAY_SIZE(rt712_spk_widgets));
if (ret) {
dev_err(card->dev, "rt712 spk widgets addition failed: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_add_routes(&card->dapm, rt712_spk_map, ARRAY_SIZE(rt712_spk_map));
if (ret)
dev_err(rtd->dev, "failed to add SPK map: %d\n", ret);
return ret;
}
int sof_sdw_rt712_spk_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
{
dai_links->init = rt712_spk_init;
return 0;
}
static int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s mic:rt712-sdca-dmic",
card->components);
if (!card->components)
return -ENOMEM;
return 0;
}
int sof_sdw_rt712_sdca_dmic_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
{
dai_links->init = rt712_sdca_dmic_rtd_init;
return 0;
}

View file

@ -21,16 +21,16 @@
* Note this MUST be called before snd_soc_register_card(), so that the props
* are in place before the codec component driver's probe function parses them.
*/
static int rt711_sdca_add_codec_device_props(struct device *sdw_dev)
static int rt_sdca_jack_add_codec_device_props(struct device *sdw_dev)
{
struct property_entry props[MAX_NO_PROPS] = {};
struct fwnode_handle *fwnode;
int ret;
if (!SOF_RT711_JDSRC(sof_sdw_quirk))
if (!SOF_JACK_JDSRC(sof_sdw_quirk))
return 0;
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_JACK_JDSRC(sof_sdw_quirk));
fwnode = fwnode_create_software_node(props, NULL);
if (IS_ERR(fwnode))
@ -43,23 +43,27 @@ static int rt711_sdca_add_codec_device_props(struct device *sdw_dev)
return ret;
}
static const struct snd_soc_dapm_widget rt711_sdca_widgets[] = {
static const struct snd_soc_dapm_widget rt_sdca_jack_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
};
static const struct snd_soc_dapm_route rt711_sdca_map[] = {
/* Headphones */
{ "Headphone", NULL, "rt711 HP" },
{ "rt711 MIC2", NULL, "Headset Mic" },
};
static const struct snd_kcontrol_new rt711_sdca_controls[] = {
static const struct snd_soc_dapm_route rt712_sdca_map[] = {
{ "Headphone", NULL, "rt712 HP" },
{ "rt712 MIC2", NULL, "Headset Mic" },
};
static const struct snd_kcontrol_new rt_sdca_jack_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
};
static struct snd_soc_jack_pin rt711_sdca_jack_pins[] = {
static struct snd_soc_jack_pin rt_sdca_jack_pins[] = {
{
.pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
@ -70,7 +74,7 @@ static struct snd_soc_jack_pin rt711_sdca_jack_pins[] = {
},
};
static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
static int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
@ -80,30 +84,38 @@ static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
int ret;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s hs:rt711-sdca",
card->components);
"%s hs:%s-sdca",
card->components, component->name_prefix);
if (!card->components)
return -ENOMEM;
ret = snd_soc_add_card_controls(card, rt711_sdca_controls,
ARRAY_SIZE(rt711_sdca_controls));
ret = snd_soc_add_card_controls(card, rt_sdca_jack_controls,
ARRAY_SIZE(rt_sdca_jack_controls));
if (ret) {
dev_err(card->dev, "rt711-sdca controls addition failed: %d\n", ret);
dev_err(card->dev, "rt sdca jack controls addition failed: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_new_controls(&card->dapm, rt711_sdca_widgets,
ARRAY_SIZE(rt711_sdca_widgets));
ret = snd_soc_dapm_new_controls(&card->dapm, rt_sdca_jack_widgets,
ARRAY_SIZE(rt_sdca_jack_widgets));
if (ret) {
dev_err(card->dev, "rt711-sdca widgets addition failed: %d\n", ret);
dev_err(card->dev, "rt sdca jack widgets addition failed: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_add_routes(&card->dapm, rt711_sdca_map,
ARRAY_SIZE(rt711_sdca_map));
if (strstr(component->name_prefix, "rt711")) {
ret = snd_soc_dapm_add_routes(&card->dapm, rt711_sdca_map,
ARRAY_SIZE(rt711_sdca_map));
} else if (strstr(component->name_prefix, "rt712")) {
ret = snd_soc_dapm_add_routes(&card->dapm, rt712_sdca_map,
ARRAY_SIZE(rt712_sdca_map));
} else {
dev_err(card->dev, "%s is not supported\n", component->name_prefix);
return -EINVAL;
}
if (ret) {
dev_err(card->dev, "rt711-sdca map addition failed: %d\n", ret);
dev_err(card->dev, "rt sdca jack map addition failed: %d\n", ret);
return ret;
}
@ -112,8 +124,8 @@ static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
SND_JACK_BTN_3,
&ctx->sdw_headset,
rt711_sdca_jack_pins,
ARRAY_SIZE(rt711_sdca_jack_pins));
rt_sdca_jack_pins,
ARRAY_SIZE(rt_sdca_jack_pins));
if (ret) {
dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n",
ret);
@ -136,24 +148,27 @@ static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
if (!ctx->headset_codec_dev)
return 0;
if (!SOF_JACK_JDSRC(sof_sdw_quirk))
return 0;
device_remove_software_node(ctx->headset_codec_dev);
put_device(ctx->headset_codec_dev);
return 0;
}
int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
{
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
struct device *sdw_dev;
@ -170,14 +185,14 @@ int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
if (!sdw_dev)
return -EPROBE_DEFER;
ret = rt711_sdca_add_codec_device_props(sdw_dev);
ret = rt_sdca_jack_add_codec_device_props(sdw_dev);
if (ret < 0) {
put_device(sdw_dev);
return ret;
}
ctx->headset_codec_dev = sdw_dev;
dai_links->init = rt711_sdca_rtd_init;
dai_links->init = rt_sdca_jack_rtd_init;
return 0;
}

View file

@ -463,6 +463,15 @@ static const struct platform_device_id board_ids[] = {
SOF_SSP_BT_OFFLOAD_PRESENT |
SOF_CS35L41_SPEAKER_AMP_PRESENT),
},
{
.name = "adl_lt6911_hdmi_ssp",
.driver_data = (kernel_ulong_t)(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_NO_OF_HDMI_PLAYBACK(3) |
SOF_HDMI_PLAYBACK_PRESENT),
},
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
@ -478,7 +487,7 @@ static struct platform_driver sof_ssp_amp_driver = {
module_platform_driver(sof_ssp_amp_driver);
MODULE_DESCRIPTION("ASoC Intel(R) SOF Amplifier Machine driver");
MODULE_AUTHOR("balamurugan.c <balamurugan.c@intel.com>");
MODULE_AUTHOR("Balamurugan C <balamurugan.c@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);

View file

@ -133,6 +133,15 @@ static const struct snd_soc_acpi_adr_device rt1316_1_group2_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device rt1316_1_single_adr[] = {
{
.adr = 0x000130025D131601ull,
.num_endpoints = 1,
.endpoints = &single_endpoint,
.name_prefix = "rt1316-1"
}
};
static const struct snd_soc_acpi_adr_device rt1316_2_single_adr[] = {
{
.adr = 0x000230025D131601ull,
@ -312,6 +321,20 @@ static const struct snd_soc_acpi_link_adr adl_sdw_rt1316_link12_rt714_link0[] =
{}
};
static const struct snd_soc_acpi_link_adr adl_sdw_rt1316_link1_rt714_link0[] = {
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(rt1316_1_single_adr),
.adr_d = rt1316_1_single_adr,
},
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt714_0_adr),
.adr_d = rt714_0_adr,
},
{}
};
static const struct snd_soc_acpi_link_adr adl_sdw_rt1316_link2_rt714_link3[] = {
{
.mask = BIT(2),
@ -557,12 +580,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
.quirk_data = &adl_max98360a_amp,
.sof_tplg_filename = "sof-adl-max98360a-cs42l42.tplg",
},
/* place amp-only boards in the end of table */
{
.id = "CSC3541",
.drv_name = "adl_cs35l41",
.sof_tplg_filename = "sof-adl-cs35l41.tplg",
},
{
.comp_ids = &essx_83x6,
.drv_name = "adl_es83x6_c1_h02",
@ -578,6 +595,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
/* place amp-only boards in the end of table */
{
.id = "CSC3541",
.drv_name = "adl_cs35l41",
.sof_tplg_filename = "sof-adl-cs35l41.tplg",
},
{
.id = "INTC10B0",
.drv_name = "adl_lt6911_hdmi_ssp",
.sof_tplg_filename = "sof-adl-nocodec-hdmi-ssp02.tplg"
},
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_adl_machines);
@ -620,6 +648,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-adl-rt1316-l2-mono-rt714-l3.tplg",
},
{
.link_mask = 0x3, /* rt1316 on link1 & rt714 on link0 */
.links = adl_sdw_rt1316_link1_rt714_link0,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-adl-rt1316-l1-mono-rt714-l0.tplg",
},
{
.link_mask = 0x7, /* rt714 on link0 & two rt1316s on link1 and link2 */
.links = adl_sdw_rt1316_link12_rt714_link0,

View file

@ -65,6 +65,21 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint rt712_endpoints[] = {
{
.num = 0,
.aggregated = 0,
.group_position = 0,
.group_id = 0,
},
{
.num = 1,
.aggregated = 0,
.group_position = 0,
.group_id = 0,
},
};
static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
{
.adr = 0x000030025D071101ull,
@ -74,6 +89,24 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device rt712_0_single_adr[] = {
{
.adr = 0x000030025D071201ull,
.num_endpoints = ARRAY_SIZE(rt712_endpoints),
.endpoints = rt712_endpoints,
.name_prefix = "rt712"
}
};
static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = {
{
.adr = 0x000330025D171201ull,
.num_endpoints = 1,
.endpoints = &single_endpoint,
.name_prefix = "rt712-dmic"
}
};
static const struct snd_soc_acpi_adr_device mx8373_0_adr[] = {
{
.adr = 0x000023019F837300ull,
@ -125,6 +158,20 @@ static const struct snd_soc_acpi_adr_device rt714_1_adr[] = {
}
};
static const struct snd_soc_acpi_link_adr mtl_712_only[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt712_0_single_adr),
.adr_d = rt712_0_single_adr,
},
{
.mask = BIT(3),
.num_adr = ARRAY_SIZE(rt1712_3_single_adr),
.adr_d = rt1712_3_single_adr,
},
{}
};
static const struct snd_soc_acpi_link_adr rt5682_link2_max98373_link0[] = {
/* Expected order: jack -> amp */
{
@ -173,6 +220,45 @@ static const struct snd_soc_acpi_link_adr mtl_3_in_1_sdca[] = {
{}
};
static const struct snd_soc_acpi_adr_device mx8363_2_adr[] = {
{
.adr = 0x000230019F836300ull,
.num_endpoints = 1,
.endpoints = &spk_l_endpoint,
.name_prefix = "Left"
},
{
.adr = 0x000231019F836300ull,
.num_endpoints = 1,
.endpoints = &spk_r_endpoint,
.name_prefix = "Right"
}
};
static const struct snd_soc_acpi_adr_device cs42l42_0_adr[] = {
{
.adr = 0x00001001FA424200ull,
.num_endpoints = 1,
.endpoints = &single_endpoint,
.name_prefix = "cs42l42"
}
};
static const struct snd_soc_acpi_link_adr cs42l42_link0_max98363_link2[] = {
/* Expected order: jack -> amp */
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(cs42l42_0_adr),
.adr_d = cs42l42_0_adr,
},
{
.mask = BIT(2),
.num_adr = ARRAY_SIZE(mx8363_2_adr),
.adr_d = mx8363_2_adr,
},
{}
};
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
/* mockup tests need to be first */
@ -194,6 +280,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-rt715-rt711-rt1308-mono.tplg",
},
{
.link_mask = BIT(3) | BIT(0),
.links = mtl_712_only,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-rt712-l0-rt1712-l3.tplg",
},
{
.link_mask = GENMASK(3, 0),
.links = mtl_3_in_1_sdca,
@ -212,6 +304,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-sdw-rt5682-l2-max98373-l0.tplg",
},
{
.link_mask = BIT(0) | BIT(2),
.links = cs42l42_link0_max98363_link2,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-sdw-cs42l42-l0-max98363-l2.tplg",
},
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_sdw_machines);

View file

@ -179,6 +179,30 @@ static const struct snd_soc_acpi_link_adr rpl_sdca_3_in_1[] = {
{}
};
static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1316_link12_rt714_link3[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt711_sdca_0_adr),
.adr_d = rt711_sdca_0_adr,
},
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(rt1316_1_group1_adr),
.adr_d = rt1316_1_group1_adr,
},
{
.mask = BIT(2),
.num_adr = ARRAY_SIZE(rt1316_2_group1_adr),
.adr_d = rt1316_2_group1_adr,
},
{
.mask = BIT(3),
.num_adr = ARRAY_SIZE(rt714_3_adr),
.adr_d = rt714_3_adr,
},
{}
};
static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link2_rt1316_link01_rt714_link3[] = {
{
.mask = BIT(2),
@ -308,6 +332,11 @@ static const struct snd_soc_acpi_codecs rpl_max98373_amp = {
.codecs = {"MX98373"}
};
static const struct snd_soc_acpi_codecs rpl_rt1019p_amp = {
.num_codecs = 1,
.codecs = {"RTL1019"}
};
struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
{
.comp_ids = &rpl_rt5682_hp,
@ -323,6 +352,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
.quirk_data = &rpl_max98373_amp,
.sof_tplg_filename = "sof-rpl-max98373-nau8825.tplg",
},
{
.comp_ids = &rpl_rt5682_hp,
.drv_name = "rpl_rt1019_rt5682",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rpl_rt1019p_amp,
.sof_tplg_filename = "sof-rpl-rt1019-rt5682.tplg",
},
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines);
@ -341,6 +377,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-rpl-rt711-l2-rt1316-l01-rt714-l3.tplg",
},
{
.link_mask = 0xF, /* 4 active links required */
.links = rpl_sdw_rt711_link0_rt1316_link12_rt714_link3,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-rpl-rt711-l0-rt1316-l12-rt714-l3.tplg",
},
{
.link_mask = 0xF, /* 4 active links required */
.links = rpl_sdw_rt711_link0_rt1318_link12_rt714_link3,

View file

@ -41,6 +41,21 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint rt712_endpoints[] = {
{
.num = 0,
.aggregated = 0,
.group_position = 0,
.group_id = 0,
},
{
.num = 1,
.aggregated = 0,
.group_position = 0,
.group_id = 0,
},
};
static const struct snd_soc_acpi_adr_device rt711_0_adr[] = {
{
.adr = 0x000020025D071100ull,
@ -170,6 +185,24 @@ static const struct snd_soc_acpi_adr_device rt1316_1_single_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device rt712_0_single_adr[] = {
{
.adr = 0x000030025D071201ull,
.num_endpoints = ARRAY_SIZE(rt712_endpoints),
.endpoints = rt712_endpoints,
.name_prefix = "rt712"
}
};
static const struct snd_soc_acpi_adr_device rt1712_1_single_adr[] = {
{
.adr = 0x000130025D171201ull,
.num_endpoints = 1,
.endpoints = &single_endpoint,
.name_prefix = "rt712-dmic"
}
};
static const struct snd_soc_acpi_adr_device rt1316_1_group1_adr[] = {
{
.adr = 0x000131025D131601ull, /* unique ID is set for some reason */
@ -353,6 +386,20 @@ static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca_mono[] = {
{}
};
static const struct snd_soc_acpi_link_adr tgl_712_only[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt712_0_single_adr),
.adr_d = rt712_0_single_adr,
},
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(rt1712_1_single_adr),
.adr_d = rt1712_1_single_adr,
},
{}
};
static const struct snd_soc_acpi_codecs tgl_max98373_amp = {
.num_codecs = 1,
.codecs = {"MX98373"}
@ -435,6 +482,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-tgl-rt715-rt711-rt1308-mono.tplg",
},
{
.link_mask = 0xF, /* 4 active links required */
.links = tgl_712_only,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-tgl-rt712.tplg",
},
{
.link_mask = 0x7,
.links = tgl_sdw_rt711_link1_rt1308_link2_rt715_link0,