Commit 551fb559 authored by Brent Lu's avatar Brent Lu Committed by Mark Brown

ASoC: Intel: sof_realtek_common: support 4xALC1011 amplifier

Add support for boards with four ALC1011 amplifiers. Configuration is
copied from cml_rt1011_rt5682 machine driver for backward
compatibility with existing cml devices.
Reviewed-by: default avatarChao Song <chao.song@linux.intel.com>
Signed-off-by: default avatarBrent Lu <brent.lu@intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20240411220347.131267-10-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent fe18a4be
......@@ -15,10 +15,40 @@
#include "../../codecs/rt1011.h"
#include "../../codecs/rt1015.h"
#include "../../codecs/rt1308.h"
#include "../common/soc-intel-quirks.h"
#include "sof_realtek_common.h"
/*
* Current only 2-amp configuration is supported for rt1011
* Common structures and functions
*/
static const struct snd_kcontrol_new realtek_4spk_kcontrols[] = {
SOC_DAPM_PIN_SWITCH("WL Ext Spk"),
SOC_DAPM_PIN_SWITCH("WR Ext Spk"),
SOC_DAPM_PIN_SWITCH("TL Ext Spk"),
SOC_DAPM_PIN_SWITCH("TR Ext Spk"),
};
static const struct snd_soc_dapm_widget realtek_4spk_widgets[] = {
SND_SOC_DAPM_SPK("WL Ext Spk", NULL),
SND_SOC_DAPM_SPK("WR Ext Spk", NULL),
SND_SOC_DAPM_SPK("TL Ext Spk", NULL),
SND_SOC_DAPM_SPK("TR Ext Spk", NULL),
};
/* helper function to get the number of specific codec */
static unsigned int get_num_codecs(const char *hid)
{
struct acpi_device *adev;
unsigned int dev_num = 0;
for_each_acpi_dev_match(adev, hid, NULL, -1)
dev_num++;
return dev_num;
}
/*
* Realtek ALC1011
*/
static const struct snd_soc_dapm_route speaker_map_lr[] = {
/* speaker */
......@@ -26,16 +56,14 @@ static const struct snd_soc_dapm_route speaker_map_lr[] = {
{ "Right Spk", NULL, "Right SPO" },
};
/*
* Make sure device's Unique ID follows this configuration:
*
* Two speakers:
* 0: left, 1: right
* Four speakers:
* 0: Woofer left, 1: Woofer right
* 2: Tweeter left, 3: Tweeter right
*/
static struct snd_soc_codec_conf rt1011_codec_confs[] = {
static const struct snd_soc_dapm_route rt1011_4spk_routes[] = {
{"WL Ext Spk", NULL, "WL SPO" },
{"WR Ext Spk", NULL, "WR SPO" },
{"TL Ext Spk", NULL, "TL SPO" },
{"TR Ext Spk", NULL, "TR SPO" },
};
static struct snd_soc_codec_conf rt1011_2spk_codec_confs[] = {
{
.dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
.name_prefix = "Left",
......@@ -46,6 +74,25 @@ static struct snd_soc_codec_conf rt1011_codec_confs[] = {
},
};
static struct snd_soc_codec_conf rt1011_4spk_codec_confs[] = {
{
.dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
.name_prefix = "WL",
},
{
.dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME),
.name_prefix = "WR",
},
{
.dlc = COMP_CODEC_CONF(RT1011_DEV2_NAME),
.name_prefix = "TL",
},
{
.dlc = COMP_CODEC_CONF(RT1011_DEV3_NAME),
.name_prefix = "TR",
},
};
static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
{
.name = RT1011_DEV0_NAME,
......@@ -55,6 +102,14 @@ static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
.name = RT1011_DEV1_NAME,
.dai_name = RT1011_CODEC_DAI,
},
{
.name = RT1011_DEV2_NAME,
.dai_name = RT1011_CODEC_DAI,
},
{
.name = RT1011_DEV3_NAME,
.dai_name = RT1011_CODEC_DAI,
},
};
static const struct {
......@@ -63,6 +118,8 @@ static const struct {
} rt1011_tdm_mask[] = {
{.tx = 0x4, .rx = 0x1},
{.tx = 0x8, .rx = 0x2},
{.tx = 0x1, .rx = 0x1},
{.tx = 0x2, .rx = 0x2},
};
static int rt1011_hw_params(struct snd_pcm_substream *substream,
......@@ -118,28 +175,109 @@ static const struct snd_soc_ops rt1011_ops = {
static int rt1011_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID);
int ret;
ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr,
ARRAY_SIZE(speaker_map_lr));
if (ret)
dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
switch (num_codecs) {
case 2:
if (!soc_intel_is_cml()) {
ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr,
ARRAY_SIZE(speaker_map_lr));
if (ret) {
dev_err(rtd->dev, "fail to add rt1011 routes, ret %d\n",
ret);
return ret;
}
break;
}
/*
* register speaker widgets "WL Ext Spk" and "WR Ext Spk" to
* keep backward compatible with cml devices
*/
fallthrough;
case 4:
ret = snd_soc_dapm_new_controls(&card->dapm, realtek_4spk_widgets,
num_codecs);
if (ret) {
dev_err(rtd->dev, "fail to add rt1011 widgets, ret %d\n",
ret);
return ret;
}
ret = snd_soc_add_card_controls(card, realtek_4spk_kcontrols,
num_codecs);
if (ret) {
dev_err(rtd->dev, "fail to add rt1011 controls, ret %d\n",
ret);
return ret;
}
ret = snd_soc_dapm_add_routes(&card->dapm, rt1011_4spk_routes,
num_codecs);
if (ret) {
dev_err(rtd->dev, "fail to add rt1011 routes, ret %d\n",
ret);
return ret;
}
break;
default:
dev_err(rtd->dev, "rt1011: invalid num_codecs %d\n", num_codecs);
return -EINVAL;
}
return ret;
}
void sof_rt1011_dai_link(struct snd_soc_dai_link *link)
void sof_rt1011_dai_link(struct device *dev, struct snd_soc_dai_link *link)
{
unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID);
link->codecs = rt1011_dai_link_components;
link->num_codecs = ARRAY_SIZE(rt1011_dai_link_components);
switch (num_codecs) {
case 2:
case 4:
link->num_codecs = num_codecs;
break;
default:
dev_err(dev, "rt1011: invalid num_codecs %d\n", num_codecs);
break;
}
link->init = rt1011_init;
link->ops = &rt1011_ops;
}
EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
void sof_rt1011_codec_conf(struct snd_soc_card *card)
void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card)
{
card->codec_conf = rt1011_codec_confs;
card->num_configs = ARRAY_SIZE(rt1011_codec_confs);
unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID);
switch (num_codecs) {
case 2:
if (soc_intel_is_cml()) {
/*
* use name prefix 'WL' and 'WR' for speaker widgets to
* keep backward compatible with cml devices
*/
card->codec_conf = rt1011_4spk_codec_confs;
} else {
card->codec_conf = rt1011_2spk_codec_confs;
}
card->num_configs = num_codecs;
break;
case 4:
card->codec_conf = rt1011_4spk_codec_confs;
card->num_configs = ARRAY_SIZE(rt1011_4spk_codec_confs);
break;
default:
dev_err(dev, "rt1011: invalid num_codecs %d\n", num_codecs);
break;
}
}
EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
......
......@@ -23,8 +23,8 @@
#define RT1011_DEV2_NAME "i2c-" RT1011_ACPI_HID ":02"
#define RT1011_DEV3_NAME "i2c-" RT1011_ACPI_HID ":03"
void sof_rt1011_dai_link(struct snd_soc_dai_link *link);
void sof_rt1011_codec_conf(struct snd_soc_card *card);
void sof_rt1011_dai_link(struct device *dev, struct snd_soc_dai_link *link);
void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card);
/*
* Realtek ALC1015 (AUTO)
......
......@@ -576,7 +576,7 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card,
max_98390_dai_link(dev, ctx->amp_link);
break;
case CODEC_RT1011:
sof_rt1011_dai_link(ctx->amp_link);
sof_rt1011_dai_link(dev, ctx->amp_link);
break;
case CODEC_RT1015:
sof_rt1015_dai_link(ctx->amp_link);
......@@ -683,7 +683,7 @@ static int sof_audio_probe(struct platform_device *pdev)
max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
break;
case CODEC_RT1011:
sof_rt1011_codec_conf(&sof_audio_card_rt5682);
sof_rt1011_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
break;
case CODEC_RT1015:
sof_rt1015_codec_conf(&sof_audio_card_rt5682);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment