mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 13:23:35 -04:00
ASoC: Intel: updates for 6.10 - part5
Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>: This patchset corrects a couple of mistakes corrected, improves snd_soc_card allocation. The new functionality is mostly for SoundWire platforms, with new SKUs for Dell and Acer, and support for the Cirrus Logic bridge/sidecar amplifier topology.
This commit is contained in:
@@ -690,6 +690,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
|
||||
select SND_SOC_CS42L43_SDW
|
||||
select MFD_CS42L43
|
||||
select MFD_CS42L43_SDW
|
||||
select SND_SOC_CS35L56_SPI
|
||||
select SND_SOC_CS35L56_SDW
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_INTEL_HDA_DSP_COMMON
|
||||
|
||||
@@ -37,6 +37,7 @@ 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_maxim.o sof_sdw_rt_amp.o \
|
||||
bridge_cs35l56.o \
|
||||
sof_sdw_rt5682.o sof_sdw_rt700.o \
|
||||
sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \
|
||||
sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \
|
||||
|
||||
137
sound/soc/intel/boards/bridge_cs35l56.c
Normal file
137
sound/soc/intel/boards/bridge_cs35l56.c
Normal file
@@ -0,0 +1,137 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Intel SOF Machine Driver with Cirrus Logic CS35L56 Smart Amp
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include "sof_sdw_common.h"
|
||||
|
||||
static const struct snd_soc_dapm_widget bridge_widgets[] = {
|
||||
SND_SOC_DAPM_SPK("Bridge Speaker", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route bridge_map[] = {
|
||||
{"Bridge Speaker", NULL, "AMPL SPK"},
|
||||
{"Bridge Speaker", NULL, "AMPR SPK"},
|
||||
};
|
||||
|
||||
static const char * const bridge_cs35l56_name_prefixes[] = {
|
||||
"AMPL",
|
||||
"AMPR",
|
||||
};
|
||||
|
||||
static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int i, ret;
|
||||
unsigned int rx_mask = 3; // ASP RX1, RX2
|
||||
unsigned int tx_mask = 3; // ASP TX1, TX2
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"%s spk:cs35l56-bridge",
|
||||
card->components);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(&card->dapm, bridge_widgets,
|
||||
ARRAY_SIZE(bridge_widgets));
|
||||
if (ret) {
|
||||
dev_err(card->dev, "widgets addition failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_dapm_add_routes(&card->dapm, bridge_map, ARRAY_SIZE(bridge_map));
|
||||
if (ret) {
|
||||
dev_err(card->dev, "map addition failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 4 x 16-bit sample slots and FSYNC=48000, BCLK=3.072 MHz */
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai) {
|
||||
ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_mask, rx_mask, 4, 16);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 3072000, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
|
||||
ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, 4, 16);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_pcm_stream bridge_params = {
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.rate_min = 48000,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
};
|
||||
|
||||
SND_SOC_DAILINK_DEFS(bridge_dai,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("cs42l43-codec", "cs42l43-asp")),
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("spi-cs35l56-left", "cs35l56-asp1"),
|
||||
COMP_CODEC("spi-cs35l56-right", "cs35l56-asp1")),
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("cs42l43-codec")));
|
||||
|
||||
static const struct snd_soc_dai_link bridge_dai_template = {
|
||||
.name = "cs42l43-cs35l56",
|
||||
.init = bridge_cs35l56_asp_init,
|
||||
.c2c_params = &bridge_params,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBC_CFC,
|
||||
SND_SOC_DAILINK_REG(bridge_dai),
|
||||
};
|
||||
|
||||
int bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs)
|
||||
{
|
||||
if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
|
||||
(*num_dais)++;
|
||||
(*num_devs) += ARRAY_SIZE(bridge_cs35l56_name_prefixes);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf)
|
||||
{
|
||||
if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
|
||||
**dai_links = bridge_dai_template;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(bridge_cs35l56_name_prefixes); i++) {
|
||||
(*codec_conf)->dlc.name = (*dai_links)->codecs[i].name;
|
||||
(*codec_conf)->name_prefix = bridge_cs35l56_name_prefixes[i];
|
||||
(*codec_conf)++;
|
||||
}
|
||||
|
||||
(*dai_links)++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bridge_cs35l56_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
if (sof_sdw_quirk & SOF_SIDECAR_AMPS)
|
||||
info->amp_num += ARRAY_SIZE(bridge_cs35l56_name_prefixes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -28,6 +28,7 @@ struct skl_hda_hdmi_pcm {
|
||||
};
|
||||
|
||||
struct skl_hda_private {
|
||||
struct snd_soc_card card;
|
||||
struct list_head hdmi_pcm_list;
|
||||
int pcm_count;
|
||||
int dai_index;
|
||||
|
||||
@@ -92,19 +92,6 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_soc_card hda_soc_card = {
|
||||
.name = "hda-dsp",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = skl_hda_be_dai_links,
|
||||
.dapm_widgets = skl_hda_widgets,
|
||||
.dapm_routes = skl_hda_map,
|
||||
.add_dai_link = skl_hda_add_dai_link,
|
||||
.fully_routed = true,
|
||||
.late_probe = skl_hda_card_late_probe,
|
||||
};
|
||||
|
||||
static char hda_soc_components[30];
|
||||
|
||||
#define IDISP_DAI_COUNT 3
|
||||
#define HDAC_DAI_COUNT 2
|
||||
#define DMIC_DAI_COUNT 2
|
||||
@@ -115,9 +102,9 @@ static char hda_soc_components[30];
|
||||
|
||||
#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000
|
||||
|
||||
static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params)
|
||||
static int skl_hda_fill_card_info(struct snd_soc_card *card,
|
||||
struct snd_soc_acpi_mach_params *mach_params)
|
||||
{
|
||||
struct snd_soc_card *card = &hda_soc_card;
|
||||
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
u32 codec_count, codec_mask;
|
||||
@@ -199,6 +186,7 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_acpi_mach *mach;
|
||||
struct skl_hda_private *ctx;
|
||||
struct snd_soc_card *card;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "entry\n");
|
||||
@@ -213,32 +201,44 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
|
||||
if (!mach)
|
||||
return -EINVAL;
|
||||
|
||||
snd_soc_card_set_drvdata(&hda_soc_card, ctx);
|
||||
card = &ctx->card;
|
||||
card->name = "hda-dsp",
|
||||
card->owner = THIS_MODULE,
|
||||
card->dai_link = skl_hda_be_dai_links,
|
||||
card->dapm_widgets = skl_hda_widgets,
|
||||
card->dapm_routes = skl_hda_map,
|
||||
card->add_dai_link = skl_hda_add_dai_link,
|
||||
card->fully_routed = true,
|
||||
card->late_probe = skl_hda_card_late_probe,
|
||||
|
||||
ret = skl_hda_fill_card_info(&mach->mach_params);
|
||||
snd_soc_card_set_drvdata(card, ctx);
|
||||
|
||||
ret = skl_hda_fill_card_info(card, &mach->mach_params);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->pcm_count = hda_soc_card.num_links;
|
||||
ctx->pcm_count = card->num_links;
|
||||
ctx->dai_index = 1; /* hdmi codec dai name starts from index 1 */
|
||||
ctx->platform_name = mach->mach_params.platform;
|
||||
ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
|
||||
|
||||
hda_soc_card.dev = &pdev->dev;
|
||||
card->dev = &pdev->dev;
|
||||
if (!snd_soc_acpi_sof_parent(&pdev->dev))
|
||||
hda_soc_card.disable_route_checks = true;
|
||||
card->disable_route_checks = true;
|
||||
|
||||
if (mach->mach_params.dmic_num > 0) {
|
||||
snprintf(hda_soc_components, sizeof(hda_soc_components),
|
||||
"cfg-dmics:%d", mach->mach_params.dmic_num);
|
||||
hda_soc_card.components = hda_soc_components;
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"cfg-dmics:%d",
|
||||
mach->mach_params.dmic_num);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (!ret)
|
||||
skl_set_hda_codec_autosuspend_delay(&hda_soc_card);
|
||||
skl_set_hda_codec_autosuspend_delay(card);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ static void log_quirks(struct device *dev)
|
||||
dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n");
|
||||
if (sof_sdw_quirk & SOF_CODEC_SPKR)
|
||||
dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n");
|
||||
if (sof_sdw_quirk & SOF_SIDECAR_AMPS)
|
||||
dev_dbg(dev, "quirk SOF_SIDECAR_AMPS enabled\n");
|
||||
}
|
||||
|
||||
static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
|
||||
@@ -421,8 +423,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
RT711_JD2 |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
RT711_JD2),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
@@ -996,6 +997,8 @@ static struct sof_sdw_codec_info codec_info_list[] = {
|
||||
{
|
||||
.part_id = 0x4243,
|
||||
.codec_name = "cs42l43-codec",
|
||||
.count_sidecar = bridge_cs35l56_count_sidecar,
|
||||
.add_sidecar = bridge_cs35l56_add_sidecar,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, false},
|
||||
@@ -1024,7 +1027,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
|
||||
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
|
||||
.init = sof_sdw_cs42l43_spk_init,
|
||||
.rtd_init = cs42l43_spk_rtd_init,
|
||||
.quirk = SOF_CODEC_SPKR,
|
||||
.quirk = SOF_CODEC_SPKR | SOF_SIDECAR_AMPS,
|
||||
},
|
||||
},
|
||||
.dai_num = 4,
|
||||
@@ -1280,6 +1283,8 @@ struct sof_sdw_endpoint {
|
||||
|
||||
u32 link_mask;
|
||||
const char *codec_name;
|
||||
const char *name_prefix;
|
||||
bool include_sidecar;
|
||||
|
||||
struct sof_sdw_codec_info *codec_info;
|
||||
const struct sof_sdw_dai_info *dai_info;
|
||||
@@ -1335,17 +1340,18 @@ static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks,
|
||||
|
||||
static int parse_sdw_endpoints(struct snd_soc_card *card,
|
||||
struct sof_sdw_dailink *sof_dais,
|
||||
struct sof_sdw_endpoint *sof_ends)
|
||||
struct sof_sdw_endpoint *sof_ends,
|
||||
int *num_devs)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
|
||||
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
|
||||
struct snd_soc_codec_conf *codec_conf = card->codec_conf;
|
||||
const struct snd_soc_acpi_link_adr *adr_link;
|
||||
struct sof_sdw_endpoint *sof_end = sof_ends;
|
||||
int num_dais = 0;
|
||||
int i, j;
|
||||
int ret;
|
||||
|
||||
for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
|
||||
int num_link_dailinks = 0;
|
||||
@@ -1377,13 +1383,19 @@ static int parse_sdw_endpoints(struct snd_soc_card *card,
|
||||
if (!codec_name)
|
||||
return -ENOMEM;
|
||||
|
||||
codec_conf->dlc.name = codec_name;
|
||||
codec_conf->name_prefix = adr_dev->name_prefix;
|
||||
codec_conf++;
|
||||
|
||||
dev_dbg(dev, "Adding prefix %s for %s\n",
|
||||
adr_dev->name_prefix, codec_name);
|
||||
|
||||
sof_end->name_prefix = adr_dev->name_prefix;
|
||||
|
||||
if (codec_info->count_sidecar && codec_info->add_sidecar) {
|
||||
ret = codec_info->count_sidecar(card, &num_dais, num_devs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sof_end->include_sidecar = true;
|
||||
}
|
||||
|
||||
for (j = 0; j < adr_dev->num_endpoints; j++) {
|
||||
const struct snd_soc_acpi_endpoint *adr_end;
|
||||
const struct sof_sdw_dai_info *dai_info;
|
||||
@@ -1444,20 +1456,33 @@ static int parse_sdw_endpoints(struct snd_soc_card *card,
|
||||
ctx->append_dai_type |= (num_link_dailinks > 1);
|
||||
}
|
||||
|
||||
WARN_ON(codec_conf != card->codec_conf + card->num_configs);
|
||||
|
||||
return num_dais;
|
||||
}
|
||||
|
||||
static int create_sdw_dailink(struct snd_soc_card *card,
|
||||
struct sof_sdw_dailink *sof_dai,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
int *be_id)
|
||||
int *be_id, struct snd_soc_codec_conf **codec_conf)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct sof_sdw_endpoint *sof_end;
|
||||
int stream;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
|
||||
if (sof_end->name_prefix) {
|
||||
(*codec_conf)->dlc.name = sof_end->codec_name;
|
||||
(*codec_conf)->name_prefix = sof_end->name_prefix;
|
||||
(*codec_conf)++;
|
||||
}
|
||||
|
||||
if (sof_end->include_sidecar) {
|
||||
ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for_each_pcm_streams(stream) {
|
||||
static const char * const sdw_stream_name[] = {
|
||||
@@ -1570,7 +1595,8 @@ static int create_sdw_dailink(struct snd_soc_card *card,
|
||||
|
||||
static int create_sdw_dailinks(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links, int *be_id,
|
||||
struct sof_sdw_dailink *sof_dais)
|
||||
struct sof_sdw_dailink *sof_dais,
|
||||
struct snd_soc_codec_conf **codec_conf)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
int ret, i;
|
||||
@@ -1582,7 +1608,8 @@ static int create_sdw_dailinks(struct snd_soc_card *card,
|
||||
while (sof_dais->initialised) {
|
||||
int current_be_id;
|
||||
|
||||
ret = create_sdw_dailink(card, sof_dais, dai_links, ¤t_be_id);
|
||||
ret = create_sdw_dailink(card, sof_dais, dai_links,
|
||||
¤t_be_id, codec_conf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1752,17 +1779,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
goto err_dai;
|
||||
}
|
||||
|
||||
/* will be populated when acpi endpoints are parsed */
|
||||
codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
|
||||
if (!codec_conf) {
|
||||
ret = -ENOMEM;
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
card->codec_conf = codec_conf;
|
||||
card->num_configs = num_devs;
|
||||
|
||||
ret = parse_sdw_endpoints(card, sof_dais, sof_ends);
|
||||
ret = parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
|
||||
if (ret < 0)
|
||||
goto err_end;
|
||||
|
||||
@@ -1799,6 +1816,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
sdw_be_num, ssp_num, dmic_num,
|
||||
ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num);
|
||||
|
||||
codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
|
||||
if (!codec_conf) {
|
||||
ret = -ENOMEM;
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
/* allocate BE dailinks */
|
||||
num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
|
||||
dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
|
||||
@@ -1807,12 +1830,15 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
card->codec_conf = codec_conf;
|
||||
card->num_configs = num_devs;
|
||||
card->dai_link = dai_links;
|
||||
card->num_links = num_links;
|
||||
|
||||
/* SDW */
|
||||
if (sdw_be_num) {
|
||||
ret = create_sdw_dailinks(card, &dai_links, &be_id, sof_dais);
|
||||
ret = create_sdw_dailinks(card, &dai_links, &be_id,
|
||||
sof_dais, &codec_conf);
|
||||
if (ret)
|
||||
goto err_end;
|
||||
}
|
||||
@@ -1848,6 +1874,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
WARN_ON(codec_conf != card->codec_conf + card->num_configs);
|
||||
WARN_ON(dai_links != card->dai_link + card->num_links);
|
||||
|
||||
err_end:
|
||||
@@ -1879,15 +1906,6 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* SoC card */
|
||||
static const char sdw_card_long_name[] = "Intel Soundwire SOF";
|
||||
|
||||
static struct snd_soc_card card_sof_sdw = {
|
||||
.name = "soundwire",
|
||||
.owner = THIS_MODULE,
|
||||
.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)
|
||||
@@ -1939,20 +1957,24 @@ static void mc_dailink_exit_loop(struct snd_soc_card *card)
|
||||
|
||||
static int mc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &card_sof_sdw;
|
||||
struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
|
||||
struct snd_soc_card *card;
|
||||
struct mc_private *ctx;
|
||||
int amp_num = 0, i;
|
||||
int ret;
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
dev_dbg(&pdev->dev, "Entry\n");
|
||||
|
||||
dev_dbg(card->dev, "Entry\n");
|
||||
|
||||
ctx = devm_kzalloc(card->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
card = &ctx->card;
|
||||
card->dev = &pdev->dev;
|
||||
card->name = "soundwire",
|
||||
card->owner = THIS_MODULE,
|
||||
card->late_probe = sof_sdw_card_late_probe,
|
||||
|
||||
snd_soc_card_set_drvdata(card, ctx);
|
||||
|
||||
dmi_check_system(sof_sdw_quirk_table);
|
||||
@@ -1988,7 +2010,7 @@ static int mc_probe(struct platform_device *pdev)
|
||||
amp_num += codec_info_list[i].amp_num;
|
||||
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"cfg-amp:%d", amp_num);
|
||||
" cfg-amp:%d", amp_num);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2001,8 +2023,6 @@ static int mc_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
card->long_name = sdw_card_long_name;
|
||||
|
||||
/* Register the card */
|
||||
ret = devm_snd_soc_register_card(card->dev, card);
|
||||
if (ret) {
|
||||
|
||||
@@ -55,6 +55,16 @@ enum {
|
||||
#define SOF_SDW_NO_AGGREGATION BIT(14)
|
||||
/* If a CODEC has an optional speaker output, this quirk will enable it */
|
||||
#define SOF_CODEC_SPKR BIT(15)
|
||||
/*
|
||||
* If the CODEC has additional devices attached directly to it.
|
||||
*
|
||||
* For the cs42l43:
|
||||
* - 0 - No speaker output
|
||||
* - SOF_CODEC_SPKR - CODEC internal speaker
|
||||
* - SOF_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker
|
||||
* - SOF_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported
|
||||
*/
|
||||
#define SOF_SIDECAR_AMPS BIT(16)
|
||||
|
||||
/* BT audio offload: reserve 3 bits for future */
|
||||
#define SOF_BT_OFFLOAD_SSP_SHIFT 15
|
||||
@@ -98,9 +108,16 @@ struct sof_sdw_codec_info {
|
||||
const int dai_num;
|
||||
|
||||
int (*codec_card_late_probe)(struct snd_soc_card *card);
|
||||
|
||||
int (*count_sidecar)(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs);
|
||||
int (*add_sidecar)(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf);
|
||||
};
|
||||
|
||||
struct mc_private {
|
||||
struct snd_soc_card card;
|
||||
struct snd_soc_jack sdw_headset;
|
||||
struct sof_hdmi_private hdmi;
|
||||
struct device *headset_codec_dev; /* only one headset per card */
|
||||
@@ -170,6 +187,16 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||
bool playback);
|
||||
|
||||
/* CS AMP support */
|
||||
int bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs);
|
||||
int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf);
|
||||
int bridge_cs35l56_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
int sof_sdw_cs_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
|
||||
@@ -124,10 +124,14 @@ int cs42l43_spk_rtd_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:cs42l43-spk",
|
||||
card->components);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
if (!(sof_sdw_quirk & SOF_SIDECAR_AMPS)) {
|
||||
/* Will be set by the bridge code in this case */
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"%s spk:cs42l43-spk",
|
||||
card->components);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets,
|
||||
ARRAY_SIZE(cs42l43_spk_widgets));
|
||||
@@ -155,7 +159,7 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||
|
||||
info->amp_num++;
|
||||
|
||||
return 0;
|
||||
return bridge_cs35l56_spk_init(card, dai_links, info, playback);
|
||||
}
|
||||
|
||||
int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
||||
|
||||
@@ -130,6 +130,33 @@ static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
|
||||
{
|
||||
.adr = 0x000130025D131801ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &spk_l_endpoint,
|
||||
.name_prefix = "rt1318-1"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1318_2_group1_adr[] = {
|
||||
{
|
||||
.adr = 0x000232025D131801ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &spk_r_endpoint,
|
||||
.name_prefix = "rt1318-2"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt714_0_adr[] = {
|
||||
{
|
||||
.adr = 0x000030025D071401ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &single_endpoint,
|
||||
.name_prefix = "rt714"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt714_1_adr[] = {
|
||||
{
|
||||
.adr = 0x000130025D071401ull,
|
||||
@@ -195,6 +222,25 @@ static const struct snd_soc_acpi_link_adr lnl_3_in_1_sdca[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr lnl_sdw_rt1318_l12_rt714_l0[] = {
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(rt1318_1_group1_adr),
|
||||
.adr_d = rt1318_1_group1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(2),
|
||||
.num_adr = ARRAY_SIZE(rt1318_2_group1_adr),
|
||||
.adr_d = rt1318_2_group1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt714_0_adr),
|
||||
.adr_d = rt714_0_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
/* this table is used when there is no I2S codec present */
|
||||
struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
|
||||
/* mockup tests need to be first */
|
||||
@@ -240,6 +286,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-lnl-rt722-l0.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = GENMASK(2, 0),
|
||||
.links = lnl_sdw_rt1318_l12_rt714_l0,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-lnl-rt1318-l12-rt714-l0.tplg"
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_lnl_sdw_machines);
|
||||
|
||||
@@ -312,6 +312,15 @@ static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1318_1_single_adr[] = {
|
||||
{
|
||||
.adr = 0x000130025D131801,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &single_endpoint,
|
||||
.name_prefix = "rt1318"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
|
||||
{
|
||||
.adr = 0x000130025D131801ull,
|
||||
@@ -348,7 +357,7 @@ static const struct snd_soc_acpi_adr_device rt714_1_adr[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr mtl_712_only[] = {
|
||||
static const struct snd_soc_acpi_link_adr mtl_712_l0_1712_l3[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt712_0_single_adr),
|
||||
@@ -362,6 +371,15 @@ static const struct snd_soc_acpi_link_adr mtl_712_only[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr mtl_712_l0[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt712_0_single_adr),
|
||||
.adr_d = rt712_0_single_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
|
||||
{ /* Jack Playback Endpoint */
|
||||
.num = 0,
|
||||
@@ -559,6 +577,49 @@ static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12_rt1713_l3[] =
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1318_l1_rt1713_l3[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt713_0_single_adr),
|
||||
.adr_d = rt713_0_single_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(rt1318_1_single_adr),
|
||||
.adr_d = rt1318_1_single_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(3),
|
||||
.num_adr = ARRAY_SIZE(rt1713_3_single_adr),
|
||||
.adr_d = rt1713_3_single_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1318_l12_rt1713_l3[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt713_0_single_adr),
|
||||
.adr_d = rt713_0_single_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(rt1318_1_group1_adr),
|
||||
.adr_d = rt1318_1_group1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(2),
|
||||
.num_adr = ARRAY_SIZE(rt1318_2_group1_adr),
|
||||
.adr_d = rt1318_2_group1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(3),
|
||||
.num_adr = ARRAY_SIZE(rt1713_3_single_adr),
|
||||
.adr_d = rt1713_3_single_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
@@ -697,6 +758,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-mtl-rt713-l0-rt1316-l12-rt1713-l3.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = GENMASK(3, 0),
|
||||
.links = mtl_rt713_l0_rt1318_l12_rt1713_l3,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-mtl-rt713-l0-rt1318-l12-rt1713-l3.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = BIT(0) | BIT(1) | BIT(3),
|
||||
.links = mtl_rt713_l0_rt1318_l1_rt1713_l3,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-mtl-rt713-l0-rt1318-l1-rt1713-l3.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = GENMASK(2, 0),
|
||||
.links = mtl_rt713_l0_rt1316_l12,
|
||||
@@ -705,10 +778,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
|
||||
},
|
||||
{
|
||||
.link_mask = BIT(3) | BIT(0),
|
||||
.links = mtl_712_only,
|
||||
.links = mtl_712_l0_1712_l3,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-mtl-rt712-l0-rt1712-l3.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = BIT(0),
|
||||
.links = mtl_712_l0,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-mtl-rt712-l0.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = GENMASK(2, 0),
|
||||
.links = mtl_sdw_rt1318_l12_rt714_l0,
|
||||
|
||||
Reference in New Issue
Block a user