Commit 5a7d9aaf authored by Mark Brown's avatar Mark Brown

ASoC: Intel: machine driver update

Merge series from Bard Liao <yung-chuan.liao@linux.intel.com>:

Some cleanups from Brent Lu for I2S platforms. And minor additions for
RVPs and Chromebooks.
parents 925819c7 5f017134
......@@ -38,6 +38,12 @@ config SND_SOC_INTEL_SOF_REALTEK_COMMON
config SND_SOC_INTEL_SOF_CIRRUS_COMMON
tristate
config SND_SOC_INTEL_SOF_NUVOTON_COMMON
tristate
config SND_SOC_INTEL_SOF_SSP_COMMON
tristate
if SND_SOC_INTEL_CATPT
config SND_SOC_INTEL_HASWELL_MACH
......@@ -493,6 +499,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_REALTEK_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON
help
This adds support for ASoC machine driver for SOF platforms
with rt5650 or rt5682 codec.
......@@ -510,6 +517,7 @@ config SND_SOC_INTEL_SOF_CS42L42_MACH
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON
help
This adds support for ASoC machine driver for SOF platforms
with cs42l42 codec.
......@@ -560,7 +568,9 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_NUVOTON_COMMON
select SND_SOC_INTEL_SOF_REALTEK_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON
help
This adds support for ASoC machine driver for SOF platforms
with nau8825 codec.
......@@ -600,25 +610,24 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH
endif ## SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK
if SND_SOC_SOF_JASPERLAKE
config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH
tristate "SOF with DA7219 and MAX98373/MAX98360A in I2S Mode"
config SND_SOC_INTEL_SOF_DA7219_MACH
tristate "SOF with DA7219 codec in I2S Mode"
depends on I2C && ACPI
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_MAX98373_I2C
select SND_SOC_DMIC
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON
help
This adds support for ASoC machine driver for SOF platforms
with DA7219 + MAX98373/MAX98360A I2S audio codec.
with Dialog DA7219 I2S audio codec.
Say Y if you have such a device.
If unsure select "N".
endif ## SND_SOC_SOF_JASPERLAKE
if SND_SOC_SOF_HDA_LINK
config SND_SOC_INTEL_SOF_SSP_AMP_MACH
......@@ -632,6 +641,7 @@ config SND_SOC_INTEL_SOF_SSP_AMP_MACH
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_REALTEK_COMMON
select SND_SOC_INTEL_SOF_CIRRUS_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON
help
This adds support for ASoC machine driver for SOF platforms
with RT1308/CS35L41 I2S audio codec.
......
......@@ -23,6 +23,7 @@ snd-soc-sof_rt5682-objs := sof_rt5682.o
snd-soc-sof_cs42l42-objs := sof_cs42l42.o
snd-soc-sof_es8336-objs := sof_es8336.o
snd-soc-sof_nau8825-objs := sof_nau8825.o
snd-soc-sof_da7219-objs := sof_da7219.o
snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o
snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o
snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o
......@@ -33,7 +34,6 @@ snd-soc-skl_rt286-objs := skl_rt286.o
snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o
snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o
snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
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 \
......@@ -48,6 +48,7 @@ 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
obj-$(CONFIG_SND_SOC_INTEL_SOF_NAU8825_MACH) += snd-soc-sof_nau8825.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_DA7219_MACH) += snd-soc-sof_da7219.o
obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-hsw-rt5640.o
obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o
obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
......@@ -78,7 +79,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH) += snd-soc-skl_hda_dsp.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH) += snd-soc-sof_da7219_max98373.o
obj-$(CONFIG_SND_SOC_INTEL_EHL_RT5660_MACH) += snd-soc-ehl-rt5660.o
obj-$(CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH) += snd-soc-sof-sdw.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_AMP_MACH) += snd-soc-sof-ssp-amp.o
......@@ -95,3 +95,9 @@ obj-$(CONFIG_SND_SOC_INTEL_SOF_REALTEK_COMMON) += snd-soc-intel-sof-realtek-comm
snd-soc-intel-sof-cirrus-common-objs += sof_cirrus_common.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_CIRRUS_COMMON) += snd-soc-intel-sof-cirrus-common.o
snd-soc-intel-sof-nuvoton-common-objs += sof_nuvoton_common.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_NUVOTON_COMMON) += snd-soc-intel-sof-nuvoton-common.o
snd-soc-intel-sof-ssp-common-objs += sof_ssp_common.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) += snd-soc-intel-sof-ssp-common.o
......@@ -9,15 +9,16 @@
#define __SOF_CIRRUS_COMMON_H
#include <sound/soc.h>
#include "sof_ssp_common.h"
/*
* Cirrus Logic CS35L41/CS35L53
*/
#define CS35L41_CODEC_DAI "cs35l41-pcm"
#define CS35L41_DEV0_NAME "i2c-CSC3541:00"
#define CS35L41_DEV1_NAME "i2c-CSC3541:01"
#define CS35L41_DEV2_NAME "i2c-CSC3541:02"
#define CS35L41_DEV3_NAME "i2c-CSC3541:03"
#define CS35L41_DEV0_NAME "i2c-" CS35L41_ACPI_HID ":00"
#define CS35L41_DEV1_NAME "i2c-" CS35L41_ACPI_HID ":01"
#define CS35L41_DEV2_NAME "i2c-" CS35L41_ACPI_HID ":02"
#define CS35L41_DEV3_NAME "i2c-" CS35L41_ACPI_HID ":03"
void cs35l41_set_dai_link(struct snd_soc_dai_link *link);
void cs35l41_set_codec_conf(struct snd_soc_card *card);
......
......@@ -23,12 +23,12 @@
#include "../common/soc-intel-quirks.h"
#include "hda_dsp_common.h"
#include "sof_maxim_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
#define SOF_CS42L42_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
#define SOF_CS42L42_SSP_CODEC_MASK (GENMASK(2, 0))
#define SOF_SPEAKER_AMP_PRESENT BIT(3)
#define SOF_CS42L42_SSP_AMP_SHIFT 4
#define SOF_CS42L42_SSP_AMP_MASK (GENMASK(6, 4))
#define SOF_CS42L42_SSP_AMP(quirk) \
......@@ -46,8 +46,6 @@
#define SOF_CS42L42_SSP_BT_MASK (GENMASK(28, 26))
#define SOF_CS42L42_SSP_BT(quirk) \
(((quirk) << SOF_CS42L42_SSP_BT_SHIFT) & SOF_CS42L42_SSP_BT_MASK)
#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(29)
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(30)
enum {
LINK_NONE = 0,
......@@ -83,6 +81,8 @@ struct sof_card_private {
struct snd_soc_jack headset_jack;
struct list_head hdmi_pcm_list;
bool common_hdmi_codec_drv;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
};
static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
......@@ -299,12 +299,13 @@ static struct snd_soc_dai_link_component dmic_component[] = {
static int create_spk_amp_dai_links(struct device *dev,
struct snd_soc_dai_link *links,
struct snd_soc_dai_link_component *cpus,
int *id, int ssp_amp)
int *id, enum sof_ssp_codec amp_type,
int ssp_amp)
{
int ret = 0;
/* speaker amp */
if (!(sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT))
if (amp_type == CODEC_NONE)
return 0;
links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
......@@ -316,14 +317,16 @@ static int create_spk_amp_dai_links(struct device *dev,
links[*id].id = *id;
if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
switch (amp_type) {
case CODEC_MAX98357A:
max_98357a_dai_link(&links[*id]);
} else if (sof_cs42l42_quirk & SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
break;
case CODEC_MAX98360A:
max_98360a_dai_link(&links[*id]);
} else {
dev_err(dev, "no amp defined\n");
ret = -EINVAL;
goto devm_err;
break;
default:
dev_err(dev, "invalid amp type %d\n", amp_type);
return -EINVAL;
}
links[*id].platforms = platform_component;
......@@ -528,12 +531,10 @@ static int create_bt_offload_dai_links(struct device *dev,
return -ENOMEM;
}
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
int ssp_codec,
int ssp_amp,
int ssp_bt,
int dmic_be_num,
int hdmi_num)
static struct snd_soc_dai_link *
sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
int ssp_codec, int ssp_amp, int ssp_bt,
int dmic_be_num, int hdmi_num)
{
struct snd_soc_dai_link_component *cpus;
struct snd_soc_dai_link *links;
......@@ -561,7 +562,8 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
}
break;
case LINK_SPK:
ret = create_spk_amp_dai_links(dev, links, cpus, &id, ssp_amp);
ret = create_spk_amp_dai_links(dev, links, cpus, &id,
amp_type, ssp_amp);
if (ret < 0) {
dev_err(dev, "fail to create spk amp dai links, ret %d\n",
ret);
......@@ -624,6 +626,9 @@ static int sof_audio_probe(struct platform_device *pdev)
mach = pdev->dev.platform_data;
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
if (soc_intel_is_glk()) {
dmic_be_num = 1;
hdmi_num = 3;
......@@ -649,13 +654,14 @@ static int sof_audio_probe(struct platform_device *pdev)
/* compute number of dai links */
sof_audio_card_cs42l42.num_links = 1 + dmic_be_num + hdmi_num;
if (sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT)
if (ctx->amp_type != CODEC_NONE)
sof_audio_card_cs42l42.num_links++;
if (sof_cs42l42_quirk & SOF_BT_OFFLOAD_PRESENT)
sof_audio_card_cs42l42.num_links++;
dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
ssp_bt, dmic_be_num, hdmi_num);
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type,
ssp_codec, ssp_amp, ssp_bt,
dmic_be_num, hdmi_num);
if (!dai_links)
return -ENOMEM;
......@@ -683,24 +689,18 @@ static const struct platform_device_id board_ids[] = {
{
.name = "glk_cs4242_mx98357a",
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98357A_SPEAKER_AMP_PRESENT |
SOF_CS42L42_SSP_AMP(1)) |
SOF_CS42L42_DAILINK(LINK_SPK, LINK_HP, LINK_DMIC, LINK_HDMI, LINK_NONE),
},
{
.name = "jsl_cs4242_mx98360a",
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_CS42L42_SSP_AMP(1)) |
SOF_CS42L42_DAILINK(LINK_HP, LINK_DMIC, LINK_HDMI, LINK_SPK, LINK_NONE),
},
{
.name = "adl_mx98360a_cs4242",
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_CS42L42_SSP_AMP(1) |
SOF_CS42L42_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_PRESENT |
......@@ -727,3 +727,4 @@ MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);
......@@ -2,7 +2,7 @@
// Copyright(c) 2019 Intel Corporation.
/*
* Intel SOF Machine driver for DA7219 + MAX98373/MAX98360A codec
* Intel SOF Machine driver for Dialog headphone codec
*/
#include <linux/input.h>
......@@ -13,13 +13,16 @@
#include <linux/platform_device.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/sof.h>
#include "../../codecs/da7219.h"
#include "hda_dsp_common.h"
#include "sof_maxim_common.h"
#include "sof_ssp_common.h"
/* Board Quirks */
#define SOF_DA7219_JSL_BOARD BIT(2)
#define DIALOG_CODEC_DAI "da7219-hifi"
#define MAX98373_CODEC_DAI "max98373-aif1"
#define MAXIM_DEV0_NAME "i2c-MX98373:00"
#define MAXIM_DEV1_NAME "i2c-MX98373:01"
struct hdmi_pcm {
struct list_head head;
......@@ -28,9 +31,13 @@ struct hdmi_pcm {
};
struct card_private {
struct snd_soc_jack headset;
struct snd_soc_jack headset_jack;
struct list_head hdmi_pcm_list;
struct snd_soc_jack hdmi[3];
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
unsigned int pll_bypass:1;
};
static int platform_clock_control(struct snd_soc_dapm_widget *w,
......@@ -38,9 +45,14 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct card_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *codec_dai;
int ret = 0;
if (ctx->pll_bypass)
return ret;
/* PLL SRM mode */
codec_dai = snd_soc_card_get_codec_dai(card, DIALOG_CODEC_DAI);
if (!codec_dai) {
dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
......@@ -53,6 +65,8 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
if (ret)
dev_err(card->dev, "failed to stop PLL: %d\n", ret);
} else if (SND_SOC_DAPM_EVENT_ON(event)) {
dev_dbg(card->dev, "pll srm mode\n");
ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM,
0, DA7219_PLL_FREQ_OUT_98304);
if (ret)
......@@ -70,14 +84,6 @@ static const struct snd_kcontrol_new controls[] = {
SOC_DAPM_PIN_SWITCH("Right Spk"),
};
static const struct snd_kcontrol_new m98360a_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Line Out"),
SOC_DAPM_PIN_SWITCH("Spk"),
};
/* For MAX98373 amp */
static const struct snd_soc_dapm_widget widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
......@@ -103,40 +109,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{ "Headset Mic", NULL, "Platform Clock" },
{ "Line Out", NULL, "Platform Clock" },
{ "Left Spk", NULL, "Left BE_OUT" },
{ "Right Spk", NULL, "Right BE_OUT" },
/* digital mics */
{"DMic", NULL, "SoC DMIC"},
};
/* For MAX98360A amp */
static const struct snd_soc_dapm_widget max98360a_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_LINE("Line Out", NULL),
SND_SOC_DAPM_SPK("Spk", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
};
static const struct snd_soc_dapm_route max98360a_map[] = {
{ "Headphone Jack", NULL, "HPL" },
{ "Headphone Jack", NULL, "HPR" },
{ "MIC", NULL, "Headset Mic" },
{ "Headphone Jack", NULL, "Platform Clock" },
{ "Headset Mic", NULL, "Platform Clock" },
{ "Line Out", NULL, "Platform Clock" },
{"Spk", NULL, "Speaker"},
/* digital mics */
{"DMic", NULL, "SoC DMIC"},
};
......@@ -156,23 +128,44 @@ static struct snd_soc_jack_pin jack_pins[] = {
},
};
static struct snd_soc_jack headset;
static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct card_private *ctx = snd_soc_card_get_drvdata(rtd->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;
struct snd_soc_jack *jack = &ctx->headset_jack;
int mclk_rate, ret;
mclk_rate = sof_dai_get_mclk(rtd);
if (mclk_rate <= 0) {
dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_rate);
return -EINVAL;
}
/* Configure sysclk for codec */
ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24000000,
ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, mclk_rate,
SND_SOC_CLOCK_IN);
if (ret) {
dev_err(rtd->dev, "can't set codec sysclk configuration\n");
dev_err(rtd->dev, "fail to set sysclk, ret %d\n", ret);
return ret;
}
/*
* Use PLL bypass mode if MCLK is available, be sure to set the
* frequency of MCLK to 12.288 or 24.576MHz on topology side.
*/
if (mclk_rate == 12288000 || mclk_rate == 24576000) {
/* PLL bypass mode */
dev_dbg(rtd->dev, "pll bypass mode, mclk rate %d\n", mclk_rate);
ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
if (ret) {
dev_err(rtd->dev, "fail to set pll, ret %d\n", ret);
return ret;
}
ctx->pll_bypass = 1;
}
/*
* Headset buttons map to the google Reference headset.
* These can be configured by userspace.
......@@ -181,25 +174,27 @@ static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
SND_JACK_BTN_3 | SND_JACK_LINEOUT,
&headset,
jack_pins,
ARRAY_SIZE(jack_pins));
jack, jack_pins, ARRAY_SIZE(jack_pins));
if (ret) {
dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
return ret;
}
jack = &headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
snd_soc_component_set_jack(component, jack, NULL);
ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret) {
dev_err(rtd->dev, "fail to set component jack, ret %d\n", ret);
return ret;
}
return ret;
}
static int ssp1_hw_params(struct snd_pcm_substream *substream,
static int max98373_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream);
......@@ -208,7 +203,7 @@ static int ssp1_hw_params(struct snd_pcm_substream *substream,
for (j = 0; j < runtime->dai_link->num_codecs; j++) {
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, j);
if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) {
if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) {
/* vmon_slot_no = 0 imon_slot_no = 1 for TX slots */
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 3, 4, 16);
if (ret < 0) {
......@@ -216,7 +211,7 @@ static int ssp1_hw_params(struct snd_pcm_substream *substream,
return ret;
}
}
if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) {
/* vmon_slot_no = 2 imon_slot_no = 3 for TX slots */
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC, 3, 4, 16);
if (ret < 0) {
......@@ -229,19 +224,8 @@ static int ssp1_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static struct snd_soc_ops ssp1_ops = {
.hw_params = ssp1_hw_params,
};
static struct snd_soc_codec_conf max98373_codec_conf[] = {
{
.dlc = COMP_CODEC_CONF(MAXIM_DEV0_NAME),
.name_prefix = "Right",
},
{
.dlc = COMP_CODEC_CONF(MAXIM_DEV1_NAME),
.name_prefix = "Left",
},
static const struct snd_soc_ops max98373_ops = {
.hw_params = max98373_hw_params,
};
static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
......@@ -285,13 +269,11 @@ SND_SOC_DAILINK_DEF(ssp0_codec,
SND_SOC_DAILINK_DEF(ssp1_pin,
DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
SND_SOC_DAILINK_DEF(ssp1_amps,
DAILINK_COMP_ARRAY(
/* Left */ COMP_CODEC(MAXIM_DEV0_NAME, MAX98373_CODEC_DAI),
/* Right */ COMP_CODEC(MAXIM_DEV1_NAME, MAX98373_CODEC_DAI)));
SND_SOC_DAILINK_DEF(ssp1_m98360a,
DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
SND_SOC_DAILINK_DEF(ssp2_pin,
DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin")));
SND_SOC_DAILINK_DEF(dummy_codec,
DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")));
SND_SOC_DAILINK_DEF(dmic_pin,
DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
......@@ -316,10 +298,15 @@ SND_SOC_DAILINK_DEF(idisp3_pin,
SND_SOC_DAILINK_DEF(idisp3_codec,
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
SND_SOC_DAILINK_DEF(idisp4_pin,
DAILINK_COMP_ARRAY(COMP_CPU("iDisp4 Pin")));
SND_SOC_DAILINK_DEF(idisp4_codec,
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi4")));
SND_SOC_DAILINK_DEF(platform, /* subject to be overridden during probe */
DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
static struct snd_soc_dai_link dais[] = {
static struct snd_soc_dai_link jsl_dais[] = {
/* Back End DAI links */
{
.name = "SSP1-Codec",
......@@ -328,8 +315,7 @@ static struct snd_soc_dai_link dais[] = {
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1, /* IV feedback */
.ops = &ssp1_ops,
SND_SOC_DAILINK_REG(ssp1_pin, ssp1_amps, platform),
SND_SOC_DAILINK_REG(ssp1_pin, max_98373_components, platform),
},
{
.name = "SSP0-Codec",
......@@ -383,83 +369,197 @@ static struct snd_soc_dai_link dais[] = {
}
};
static struct snd_soc_card card_da7219_m98373 = {
.name = "da7219max",
static struct snd_soc_dai_link adl_dais[] = {
/* Back End DAI links */
{
.name = "SSP0-Codec",
.id = 0,
.no_pcm = 1,
.init = da7219_codec_init,
.ignore_pmdown_time = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
},
{
.name = "dmic01",
.id = 1,
.ignore_suspend = 1,
.dpcm_capture = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
},
{
.name = "dmic16k",
.id = 2,
.ignore_suspend = 1,
.dpcm_capture = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform),
},
{
.name = "iDisp1",
.id = 3,
.init = hdmi_init,
.dpcm_playback = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
},
{
.name = "iDisp2",
.id = 4,
.init = hdmi_init,
.dpcm_playback = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
},
{
.name = "iDisp3",
.id = 5,
.init = hdmi_init,
.dpcm_playback = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
},
{
.name = "iDisp4",
.id = 6,
.init = hdmi_init,
.dpcm_playback = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp4_pin, idisp4_codec, platform),
},
{
.name = "SSP1-Codec",
.id = 7,
.no_pcm = 1,
.dpcm_playback = 1,
/* feedback stream or firmware-generated echo reference */
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(ssp1_pin, max_98373_components, platform),
},
{
.name = "SSP2-BT",
.id = 8,
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(ssp2_pin, dummy_codec, platform),
},
};
static struct snd_soc_card card_da7219 = {
.name = "da7219", /* the sof- prefix is added by the core */
.owner = THIS_MODULE,
.dai_link = dais,
.num_links = ARRAY_SIZE(dais),
.controls = controls,
.num_controls = ARRAY_SIZE(controls),
.dapm_widgets = widgets,
.num_dapm_widgets = ARRAY_SIZE(widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
.codec_conf = max98373_codec_conf,
.num_configs = ARRAY_SIZE(max98373_codec_conf),
.fully_routed = true,
.late_probe = card_late_probe,
};
static struct snd_soc_card card_da7219_m98360a = {
.name = "da7219max98360a",
.owner = THIS_MODULE,
.dai_link = dais,
.num_links = ARRAY_SIZE(dais),
.controls = m98360a_controls,
.num_controls = ARRAY_SIZE(m98360a_controls),
.dapm_widgets = max98360a_widgets,
.num_dapm_widgets = ARRAY_SIZE(max98360a_widgets),
.dapm_routes = max98360a_map,
.num_dapm_routes = ARRAY_SIZE(max98360a_map),
.fully_routed = true,
.late_probe = card_late_probe,
};
static int audio_probe(struct platform_device *pdev)
{
static struct snd_soc_card *card;
struct snd_soc_acpi_mach *mach;
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
struct snd_soc_dai_link *dai_links;
struct card_private *ctx;
int ret;
unsigned long board_quirk = 0;
int ret, amp_idx;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
/* By default dais[0] is configured for max98373 */
if (!strcmp(pdev->name, "sof_da7219_mx98360a")) {
dais[0] = (struct snd_soc_dai_link) {
.name = "SSP1-Codec",
.id = 0,
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_pmdown_time = 1,
SND_SOC_DAILINK_REG(ssp1_pin, ssp1_m98360a, platform) };
if (pdev->id_entry && pdev->id_entry->driver_data)
board_quirk = (unsigned long)pdev->id_entry->driver_data;
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
if (board_quirk & SOF_DA7219_JSL_BOARD) {
/* backward-compatible with existing devices */
switch (ctx->amp_type) {
case CODEC_MAX98360A:
card_da7219.name = devm_kstrdup(&pdev->dev,
"da7219max98360a",
GFP_KERNEL);
break;
case CODEC_MAX98373:
card_da7219.name = devm_kstrdup(&pdev->dev, "da7219max",
GFP_KERNEL);
break;
default:
break;
}
dai_links = jsl_dais;
amp_idx = 0;
card_da7219.num_links = ARRAY_SIZE(jsl_dais);
} else {
dai_links = adl_dais;
amp_idx = 7;
card_da7219.num_links = ARRAY_SIZE(adl_dais);
}
dev_dbg(&pdev->dev, "board_quirk = %lx\n", board_quirk);
/* speaker amp */
switch (ctx->amp_type) {
case CODEC_MAX98360A:
max_98360a_dai_link(&dai_links[amp_idx]);
break;
case CODEC_MAX98373:
dai_links[amp_idx].codecs = max_98373_components;
dai_links[amp_idx].num_codecs = ARRAY_SIZE(max_98373_components);
dai_links[amp_idx].init = max_98373_spk_codec_init;
if (board_quirk & SOF_DA7219_JSL_BOARD) {
dai_links[amp_idx].ops = &max98373_ops; /* use local ops */
} else {
/* TBD: implement the amp for later platform */
dev_err(&pdev->dev, "max98373 not support yet\n");
return -EINVAL;
}
max_98373_set_codec_conf(&card_da7219);
break;
default:
dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
return -EINVAL;
}
card_da7219.dai_link = dai_links;
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
card = (struct snd_soc_card *)pdev->id_entry->driver_data;
card->dev = &pdev->dev;
mach = pdev->dev.platform_data;
ret = snd_soc_fixup_dai_links_platform_name(card,
card_da7219.dev = &pdev->dev;
ret = snd_soc_fixup_dai_links_platform_name(&card_da7219,
mach->mach_params.platform);
if (ret)
return ret;
snd_soc_card_set_drvdata(card, ctx);
snd_soc_card_set_drvdata(&card_da7219, ctx);
return devm_snd_soc_register_card(&pdev->dev, card);
return devm_snd_soc_register_card(&pdev->dev, &card_da7219);
}
static const struct platform_device_id board_ids[] = {
{
.name = "sof_da7219_mx98373",
.driver_data = (kernel_ulong_t)&card_da7219_m98373,
.name = "jsl_mx98373_da7219",
.driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD),
},
{
.name = "jsl_mx98360_da7219",
.driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD),
},
{
.name = "sof_da7219_mx98360a",
.driver_data = (kernel_ulong_t)&card_da7219_m98360a,
.name = "adl_mx98360_da7219",
/* no quirk needed for this board */
},
{ }
};
......@@ -468,7 +568,7 @@ MODULE_DEVICE_TABLE(platform, board_ids);
static struct platform_driver audio = {
.probe = audio_probe,
.driver = {
.name = "sof_da7219_max98_360a_373",
.name = "sof_da7219",
.pm = &snd_soc_pm_ops,
},
.id_table = board_ids,
......@@ -476,7 +576,10 @@ static struct platform_driver audio = {
module_platform_driver(audio)
/* Module information */
MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver");
MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver for Dialog codec");
MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);
......@@ -11,10 +11,14 @@
#define __SOF_MAXIM_COMMON_H
#include <sound/soc.h>
#include "sof_ssp_common.h"
/*
* Maxim MAX98373
*/
#define MAX_98373_CODEC_DAI "max98373-aif1"
#define MAX_98373_DEV0_NAME "i2c-MX98373:00"
#define MAX_98373_DEV1_NAME "i2c-MX98373:01"
#define MAX_98373_DEV0_NAME "i2c-" MAX_98373_ACPI_HID ":00"
#define MAX_98373_DEV1_NAME "i2c-" MAX_98373_ACPI_HID ":01"
extern struct snd_soc_dai_link_component max_98373_components[2];
extern struct snd_soc_ops max_98373_ops;
......@@ -27,7 +31,6 @@ int max_98373_trigger(struct snd_pcm_substream *substream, int cmd);
/*
* Maxim MAX98390
*/
#define MAX_98390_ACPI_HID "MX98390"
#define MAX_98390_CODEC_DAI "max98390-aif1"
#define MAX_98390_DEV0_NAME "i2c-" MAX_98390_ACPI_HID ":00"
#define MAX_98390_DEV1_NAME "i2c-" MAX_98390_ACPI_HID ":01"
......@@ -41,8 +44,8 @@ void max_98390_set_codec_conf(struct device *dev, struct snd_soc_card *card);
* Maxim MAX98357A/MAX98360A
*/
#define MAX_98357A_CODEC_DAI "HiFi"
#define MAX_98357A_DEV0_NAME "MX98357A:00"
#define MAX_98360A_DEV0_NAME "MX98360A:00"
#define MAX_98357A_DEV0_NAME MAX_98357A_ACPI_HID ":00"
#define MAX_98360A_DEV0_NAME MAX_98360A_ACPI_HID ":00"
void max_98357a_dai_link(struct snd_soc_dai_link *link);
void max_98360a_dai_link(struct snd_soc_dai_link *link);
......
......@@ -23,12 +23,13 @@
#include "hda_dsp_common.h"
#include "sof_realtek_common.h"
#include "sof_maxim_common.h"
#include "sof_nuvoton_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
#define SOF_NAU8825_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
#define SOF_NAU8825_SSP_CODEC_MASK (GENMASK(2, 0))
#define SOF_SPEAKER_AMP_PRESENT BIT(3)
#define SOF_NAU8825_SSP_AMP_SHIFT 4
#define SOF_NAU8825_SSP_AMP_MASK (GENMASK(6, 4))
#define SOF_NAU8825_SSP_AMP(quirk) \
......@@ -44,11 +45,6 @@
#define SOF_BT_OFFLOAD_SSP(quirk) \
(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(13)
#define SOF_RT1019P_SPEAKER_AMP_PRESENT BIT(14)
#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(15)
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(16)
#define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(17)
#define SOF_NAU8318_SPEAKER_AMP_PRESENT BIT(18)
static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0);
......@@ -62,6 +58,8 @@ struct sof_card_private {
struct clk *mclk;
struct snd_soc_jack sof_headset;
struct list_head hdmi_pcm_list;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
};
static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
......@@ -192,7 +190,7 @@ static int sof_card_late_probe(struct snd_soc_card *card)
struct sof_hdmi_pcm *pcm;
int err;
if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
if (ctx->amp_type == CODEC_MAX98373) {
/* Disable Left and Right Spk pin after boot */
snd_soc_dapm_disable_pin(dapm, "Left Spk");
snd_soc_dapm_disable_pin(dapm, "Right Spk");
......@@ -216,10 +214,6 @@ static const struct snd_kcontrol_new sof_controls[] = {
SOC_DAPM_PIN_SWITCH("Right Spk"),
};
static const struct snd_kcontrol_new speaker_controls[] = {
SOC_DAPM_PIN_SWITCH("Spk"),
};
static const struct snd_soc_dapm_widget sof_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
......@@ -227,10 +221,6 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
SND_SOC_DAPM_SPK("Right Spk", NULL),
};
static const struct snd_soc_dapm_widget speaker_widgets[] = {
SND_SOC_DAPM_SPK("Spk", NULL),
};
static const struct snd_soc_dapm_widget dmic_widgets[] = {
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
};
......@@ -244,44 +234,11 @@ static const struct snd_soc_dapm_route sof_map[] = {
{ "MIC", NULL, "Headset Mic" },
};
static const struct snd_soc_dapm_route speaker_map[] = {
/* speaker */
{ "Spk", NULL, "Speaker" },
};
static const struct snd_soc_dapm_route dmic_map[] = {
/* digital mics */
{"DMic", NULL, "SoC DMIC"},
};
static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
ret = snd_soc_dapm_new_controls(&card->dapm, speaker_widgets,
ARRAY_SIZE(speaker_widgets));
if (ret) {
dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
/* Don't need to add routes if widget addition failed */
return ret;
}
ret = snd_soc_add_card_controls(card, speaker_controls,
ARRAY_SIZE(speaker_controls));
if (ret) {
dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
return ret;
}
ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
ARRAY_SIZE(speaker_map));
if (ret)
dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
return ret;
}
static int dmic_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
......@@ -332,25 +289,10 @@ static struct snd_soc_dai_link_component dmic_component[] = {
}
};
static struct snd_soc_dai_link_component rt1019p_component[] = {
{
.name = "RTL1019:00",
.dai_name = "HiFi",
}
};
static struct snd_soc_dai_link_component nau8318_components[] = {
{
.name = "NVTN2012:00",
.dai_name = "nau8315-hifi",
}
};
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
int ssp_codec,
int ssp_amp,
int dmic_be_num,
int hdmi_num)
static struct snd_soc_dai_link *
sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
int ssp_codec, int ssp_amp, int dmic_be_num,
int hdmi_num)
{
struct snd_soc_dai_link_component *idisp_components;
struct snd_soc_dai_link_component *cpus;
......@@ -463,35 +405,36 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
}
/* speaker amp */
if (sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT) {
if (amp_type != CODEC_NONE) {
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
"SSP%d-Codec", ssp_amp);
if (!links[id].name)
goto devm_err;
links[id].id = id;
if (sof_nau8825_quirk & SOF_RT1019P_SPEAKER_AMP_PRESENT) {
links[id].codecs = rt1019p_component;
links[id].num_codecs = ARRAY_SIZE(rt1019p_component);
links[id].init = speaker_codec_init;
} else if (sof_nau8825_quirk &
SOF_MAX98373_SPEAKER_AMP_PRESENT) {
switch (amp_type) {
case CODEC_MAX98360A:
max_98360a_dai_link(&links[id]);
break;
case CODEC_MAX98373:
links[id].codecs = max_98373_components;
links[id].num_codecs = ARRAY_SIZE(max_98373_components);
links[id].init = max_98373_spk_codec_init;
links[id].ops = &max_98373_ops;
} else if (sof_nau8825_quirk &
SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
max_98360a_dai_link(&links[id]);
} else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
break;
case CODEC_NAU8318:
nau8318_set_dai_link(&links[id]);
break;
case CODEC_RT1015P:
sof_rt1015p_dai_link(&links[id]);
} else if (sof_nau8825_quirk &
SOF_NAU8318_SPEAKER_AMP_PRESENT) {
links[id].codecs = nau8318_components;
links[id].num_codecs = ARRAY_SIZE(nau8318_components);
links[id].init = speaker_codec_init;
} else {
goto devm_err;
break;
case CODEC_RT1019P:
sof_rt1019p_dai_link(&links[id]);
break;
default:
dev_err(dev, "invalid amp type %d\n", amp_type);
return NULL;
}
links[id].platforms = platform_component;
......@@ -557,11 +500,8 @@ static int sof_audio_probe(struct platform_device *pdev)
mach = pdev->dev.platform_data;
/* A speaker amp might not be present when the quirk claims one is.
* Detect this via whether the machine driver match includes quirk_data.
*/
if ((sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
sof_nau8825_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
dev_dbg(&pdev->dev, "sof_nau8825_quirk = %lx\n", sof_nau8825_quirk);
......@@ -581,24 +521,39 @@ static int sof_audio_probe(struct platform_device *pdev)
/* compute number of dai links */
sof_audio_card_nau8825.num_links = 1 + dmic_be_num + hdmi_num;
if (sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT)
if (ctx->amp_type != CODEC_NONE)
sof_audio_card_nau8825.num_links++;
if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
max_98373_set_codec_conf(&sof_audio_card_nau8825);
else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
sof_rt1015p_codec_conf(&sof_audio_card_nau8825);
if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
sof_audio_card_nau8825.num_links++;
dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
dmic_be_num, hdmi_num);
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type,
ssp_codec, ssp_amp, dmic_be_num,
hdmi_num);
if (!dai_links)
return -ENOMEM;
sof_audio_card_nau8825.dai_link = dai_links;
/* update codec_conf */
switch (ctx->amp_type) {
case CODEC_MAX98373:
max_98373_set_codec_conf(&sof_audio_card_nau8825);
break;
case CODEC_RT1015P:
sof_rt1015p_codec_conf(&sof_audio_card_nau8825);
break;
case CODEC_NONE:
case CODEC_MAX98360A:
case CODEC_NAU8318:
case CODEC_RT1019P:
/* no codec conf required */
break;
default:
dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
return -EINVAL;
}
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
sof_audio_card_nau8825.dev = &pdev->dev;
......@@ -627,16 +582,12 @@ static const struct platform_device_id board_ids[] = {
{
.name = "adl_rt1019p_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1019P_SPEAKER_AMP_PRESENT |
SOF_NAU8825_SSP_AMP(2) |
SOF_NAU8825_NUM_HDMIDEV(4)),
},
{
.name = "adl_max98373_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98373_SPEAKER_AMP_PRESENT |
SOF_NAU8825_SSP_AMP(1) |
SOF_NAU8825_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -646,8 +597,6 @@ static const struct platform_device_id board_ids[] = {
/* The limitation of length of char array, shorten the name */
.name = "adl_mx98360a_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_NAU8825_SSP_AMP(1) |
SOF_NAU8825_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -657,8 +606,6 @@ static const struct platform_device_id board_ids[] = {
{
.name = "adl_rt1015p_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1015P_SPEAKER_AMP_PRESENT |
SOF_NAU8825_SSP_AMP(1) |
SOF_NAU8825_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -667,8 +614,6 @@ static const struct platform_device_id board_ids[] = {
{
.name = "adl_nau8318_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_NAU8318_SPEAKER_AMP_PRESENT |
SOF_NAU8825_SSP_AMP(1) |
SOF_NAU8825_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -677,8 +622,6 @@ static const struct platform_device_id board_ids[] = {
{
.name = "rpl_max98373_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98373_SPEAKER_AMP_PRESENT |
SOF_NAU8825_SSP_AMP(1) |
SOF_NAU8825_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -687,8 +630,6 @@ static const struct platform_device_id board_ids[] = {
{
.name = "rpl_nau8318_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_NAU8318_SPEAKER_AMP_PRESENT |
SOF_NAU8825_SSP_AMP(1) |
SOF_NAU8825_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -712,7 +653,10 @@ module_platform_driver(sof_audio)
MODULE_DESCRIPTION("SOF Audio Machine driver for NAU8825");
MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>");
MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_NUVOTON_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);
// SPDX-License-Identifier: GPL-2.0-only
/*
* This file defines data structures and functions used in Machine
* Driver for Intel platforms with Nuvoton Codecs.
*
* Copyright 2023 Intel Corporation.
*/
#include <linux/module.h>
#include <sound/sof.h>
#include "sof_nuvoton_common.h"
/*
* Nuvoton NAU8318
*/
static const struct snd_kcontrol_new nau8318_kcontrols[] = {
SOC_DAPM_PIN_SWITCH("Spk"),
};
static const struct snd_soc_dapm_widget nau8318_widgets[] = {
SND_SOC_DAPM_SPK("Spk", NULL),
};
static const struct snd_soc_dapm_route nau8318_routes[] = {
{ "Spk", NULL, "Speaker" },
};
static struct snd_soc_dai_link_component nau8318_components[] = {
{
.name = NAU8318_DEV0_NAME,
.dai_name = NAU8318_CODEC_DAI,
}
};
static int nau8318_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
ret = snd_soc_dapm_new_controls(&card->dapm, nau8318_widgets,
ARRAY_SIZE(nau8318_widgets));
if (ret) {
dev_err(rtd->dev, "fail to add nau8318 widgets, ret %d\n", ret);
return ret;
}
ret = snd_soc_add_card_controls(card, nau8318_kcontrols,
ARRAY_SIZE(nau8318_kcontrols));
if (ret) {
dev_err(rtd->dev, "fail to add nau8318 kcontrols, ret %d\n", ret);
return ret;
}
ret = snd_soc_dapm_add_routes(&card->dapm, nau8318_routes,
ARRAY_SIZE(nau8318_routes));
if (ret) {
dev_err(rtd->dev, "fail to add nau8318 routes, ret %d\n", ret);
return ret;
}
return ret;
}
void nau8318_set_dai_link(struct snd_soc_dai_link *link)
{
link->codecs = nau8318_components;
link->num_codecs = ARRAY_SIZE(nau8318_components);
link->init = nau8318_init;
}
EXPORT_SYMBOL_NS(nau8318_set_dai_link, SND_SOC_INTEL_SOF_NUVOTON_COMMON);
MODULE_DESCRIPTION("ASoC Intel SOF Nuvoton helpers");
MODULE_LICENSE("GPL");
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* This file defines data structures used in Machine Driver for Intel
* platforms with Nuvoton Codecs.
*
* Copyright 2023 Intel Corporation.
*/
#ifndef __SOF_NUVOTON_COMMON_H
#define __SOF_NUVOTON_COMMON_H
#include <sound/soc.h>
#include "sof_ssp_common.h"
/*
* Nuvoton NAU8318
*/
#define NAU8318_CODEC_DAI "nau8315-hifi"
#define NAU8318_DEV0_NAME "i2c-" NAU8318_ACPI_HID ":00"
void nau8318_set_dai_link(struct snd_soc_dai_link *link);
#endif /* __SOF_NUVOTON_COMMON_H */
......@@ -11,36 +11,53 @@
#define __SOF_REALTEK_COMMON_H
#include <sound/soc.h>
#include "sof_ssp_common.h"
/*
* Realtek ALC1011
*/
#define RT1011_CODEC_DAI "rt1011-aif"
#define RT1011_DEV0_NAME "i2c-10EC1011:00"
#define RT1011_DEV1_NAME "i2c-10EC1011:01"
#define RT1011_DEV2_NAME "i2c-10EC1011:02"
#define RT1011_DEV3_NAME "i2c-10EC1011:03"
#define RT1011_DEV0_NAME "i2c-" RT1011_ACPI_HID ":00"
#define RT1011_DEV1_NAME "i2c-" RT1011_ACPI_HID ":01"
#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);
/*
* Realtek ALC1015 (AUTO)
*/
#define RT1015P_CODEC_DAI "HiFi"
#define RT1015P_DEV0_NAME "RTL1015:00"
#define RT1015P_DEV1_NAME "RTL1015:01"
#define RT1015P_DEV0_NAME RT1015P_ACPI_HID ":00"
#define RT1015P_DEV1_NAME RT1015P_ACPI_HID ":01"
void sof_rt1015p_dai_link(struct snd_soc_dai_link *link);
void sof_rt1015p_codec_conf(struct snd_soc_card *card);
/*
* Realtek ALC1015 (I2C)
*/
#define RT1015_CODEC_DAI "rt1015-aif"
#define RT1015_DEV0_NAME "i2c-10EC1015:00"
#define RT1015_DEV1_NAME "i2c-10EC1015:01"
#define RT1015_DEV0_NAME "i2c-" RT1015_ACPI_HID ":00"
#define RT1015_DEV1_NAME "i2c-" RT1015_ACPI_HID ":01"
void sof_rt1015_dai_link(struct snd_soc_dai_link *link);
void sof_rt1015_codec_conf(struct snd_soc_card *card);
/*
* Realtek ALC1308
*/
#define RT1308_CODEC_DAI "rt1308-aif"
#define RT1308_DEV0_NAME "i2c-10EC1308:00"
#define RT1308_DEV0_NAME "i2c-" RT1308_ACPI_HID ":00"
void sof_rt1308_dai_link(struct snd_soc_dai_link *link);
/*
* Realtek ALC1019
*/
#define RT1019P_CODEC_DAI "HiFi"
#define RT1019P_DEV0_NAME "RTL1019:00"
#define RT1019P_DEV0_NAME RT1019P_ACPI_HID ":00"
void sof_rt1019p_dai_link(struct snd_soc_dai_link *link);
......
......@@ -28,14 +28,13 @@
#include "hda_dsp_common.h"
#include "sof_maxim_common.h"
#include "sof_realtek_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
#define SOF_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
#define SOF_RT5682_SSP_CODEC_MASK (GENMASK(2, 0))
#define SOF_RT5682_MCLK_EN BIT(3)
#define SOF_RT5682_MCLK_24MHZ BIT(4)
#define SOF_SPEAKER_AMP_PRESENT BIT(5)
#define SOF_RT5682_SSP_AMP_SHIFT 6
#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6))
#define SOF_RT5682_SSP_AMP(quirk) \
......@@ -45,11 +44,6 @@
#define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10))
#define SOF_RT5682_NUM_HDMIDEV(quirk) \
((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK)
#define SOF_RT1011_SPEAKER_AMP_PRESENT BIT(13)
#define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(14)
#define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(16)
#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(17)
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(18)
/* BT audio offload: reserve 3 bits for future */
#define SOF_BT_OFFLOAD_SSP_SHIFT 19
......@@ -57,10 +51,6 @@
#define SOF_BT_OFFLOAD_SSP(quirk) \
(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(22)
#define SOF_RT5682S_HEADPHONE_CODEC_PRESENT BIT(23)
#define SOF_MAX98390_SPEAKER_AMP_PRESENT BIT(24)
#define SOF_RT1019_SPEAKER_AMP_PRESENT BIT(26)
#define SOF_RT5650_HEADPHONE_CODEC_PRESENT BIT(27)
/* HDMI capture*/
#define SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT 27
......@@ -87,6 +77,8 @@ struct sof_card_private {
struct list_head hdmi_pcm_list;
bool common_hdmi_codec_drv;
bool idisp_codec;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
};
static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
......@@ -119,35 +111,15 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(1)),
},
{
/*
* Dooly is hatch family but using rt1015 amp so it
* requires a quirk before "Google_Hatch".
*/
.callback = sof_rt5682_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "Dooly"),
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1015_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{
.callback = sof_rt5682_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{
......@@ -167,8 +139,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98373_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
......@@ -181,8 +151,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98373_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
......@@ -194,8 +162,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98390_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
......@@ -207,8 +173,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
......@@ -220,10 +184,22 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(0) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_RT5682_NUM_HDMIDEV(3) |
SOF_BT_OFFLOAD_SSP(1) |
SOF_SSP_BT_OFFLOAD_PRESENT
),
},
{
.callback = sof_rt5682_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_DISCRETE_I2S_BT"),
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
SOF_RT5682_SSP_AMP(0) |
SOF_RT5682_NUM_HDMIDEV(3) |
SOF_BT_OFFLOAD_SSP(1) |
SOF_SSP_BT_OFFLOAD_PRESENT
),
......@@ -236,8 +212,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1019_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(0) |
SOF_RT5682_NUM_HDMIDEV(3)
),
......@@ -249,9 +223,8 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(0) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_RT5682_NUM_HDMIDEV(3) |
SOF_BT_OFFLOAD_SSP(1) |
SOF_SSP_BT_OFFLOAD_PRESENT
),
......@@ -295,51 +268,69 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
struct snd_soc_jack *jack;
int extra_jack_data;
int ret;
int ret, mclk_freq;
/* need to enable ASRC function for 24MHz mclk rate */
if ((sof_rt5682_quirk & SOF_RT5682_MCLK_EN) &&
(sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)) {
if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
rt5682s_sel_asrc_clk_src(component,
RT5682S_DA_STEREO1_FILTER |
RT5682S_AD_STEREO1_FILTER,
RT5682S_CLK_SEL_I2S1_ASRC);
else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) {
rt5645_sel_asrc_clk_src(component,
RT5645_DA_STEREO_FILTER |
RT5645_AD_STEREO_FILTER,
RT5645_CLK_SEL_I2S1_ASRC);
rt5645_sel_asrc_clk_src(component,
RT5645_DA_MONO_L_FILTER |
RT5645_DA_MONO_R_FILTER,
RT5645_CLK_SEL_I2S2_ASRC);
} else
rt5682_sel_asrc_clk_src(component,
RT5682_DA_STEREO1_FILTER |
RT5682_AD_STEREO1_FILTER,
RT5682_CLK_SEL_I2S1_ASRC);
}
if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
mclk_freq = sof_dai_get_mclk(rtd);
if (mclk_freq <= 0) {
dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_freq);
return -EINVAL;
}
if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
/*
* The firmware might enable the clock at
* boot (this information may or may not
* be reflected in the enable clock register).
* To change the rate we must disable the clock
* first to cover these cases. Due to common
* clock framework restrictions that do not allow
* to disable a clock that has not been enabled,
* we need to enable the clock first.
*/
ret = clk_prepare_enable(ctx->mclk);
if (!ret)
clk_disable_unprepare(ctx->mclk);
/* need to enable ASRC function for 24MHz mclk rate */
if (mclk_freq == 24000000) {
dev_info(rtd->dev, "enable ASRC\n");
switch (ctx->codec_type) {
case CODEC_RT5650:
rt5645_sel_asrc_clk_src(component,
RT5645_DA_STEREO_FILTER |
RT5645_AD_STEREO_FILTER,
RT5645_CLK_SEL_I2S1_ASRC);
rt5645_sel_asrc_clk_src(component,
RT5645_DA_MONO_L_FILTER |
RT5645_DA_MONO_R_FILTER,
RT5645_CLK_SEL_I2S2_ASRC);
break;
case CODEC_RT5682:
rt5682_sel_asrc_clk_src(component,
RT5682_DA_STEREO1_FILTER |
RT5682_AD_STEREO1_FILTER,
RT5682_CLK_SEL_I2S1_ASRC);
break;
case CODEC_RT5682S:
rt5682s_sel_asrc_clk_src(component,
RT5682S_DA_STEREO1_FILTER |
RT5682S_AD_STEREO1_FILTER,
RT5682S_CLK_SEL_I2S1_ASRC);
break;
default:
dev_err(rtd->dev, "invalid codec type %d\n",
ctx->codec_type);
return -EINVAL;
}
}
if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
/*
* The firmware might enable the clock at
* boot (this information may or may not
* be reflected in the enable clock register).
* To change the rate we must disable the clock
* first to cover these cases. Due to common
* clock framework restrictions that do not allow
* to disable a clock that has not been enabled,
* we need to enable the clock first.
*/
ret = clk_prepare_enable(ctx->mclk);
if (!ret)
clk_disable_unprepare(ctx->mclk);
ret = clk_set_rate(ctx->mclk, 19200000);
ret = clk_set_rate(ctx->mclk, 19200000);
if (ret)
dev_err(rtd->dev, "unable to set MCLK rate\n");
if (ret)
dev_err(rtd->dev, "unable to set MCLK rate\n");
}
}
/*
......@@ -365,7 +356,7 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) {
if (ctx->codec_type == CODEC_RT5650) {
extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0;
ret = snd_soc_component_set_jack(component, jack, &extra_jack_data);
} else
......@@ -404,55 +395,86 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
}
}
if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
pll_source = RT5682S_PLL_S_MCLK;
else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT)
switch (ctx->codec_type) {
case CODEC_RT5650:
pll_source = RT5645_PLL1_S_MCLK;
else
break;
case CODEC_RT5682:
pll_source = RT5682_PLL1_S_MCLK;
break;
case CODEC_RT5682S:
pll_source = RT5682S_PLL_S_MCLK;
break;
default:
dev_err(rtd->dev, "invalid codec type %d\n",
ctx->codec_type);
return -EINVAL;
}
/* get the tplg configured mclk. */
pll_in = sof_dai_get_mclk(rtd);
/* mclk from the quirk is the first choice */
if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ) {
if (pll_in != 24000000)
dev_warn(rtd->dev, "configure wrong mclk in tplg, please use 24MHz.\n");
pll_in = 24000000;
} else if (pll_in == 0) {
/* use default mclk if not specified correct in topology */
pll_in = 19200000;
} else if (pll_in < 0) {
return pll_in;
if (pll_in <= 0) {
dev_err(rtd->dev, "invalid mclk freq %d\n", pll_in);
return -EINVAL;
}
} else {
if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
pll_source = RT5682S_PLL_S_BCLK1;
else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT)
switch (ctx->codec_type) {
case CODEC_RT5650:
pll_source = RT5645_PLL1_S_BCLK1;
else
break;
case CODEC_RT5682:
pll_source = RT5682_PLL1_S_BCLK1;
break;
case CODEC_RT5682S:
pll_source = RT5682S_PLL_S_BCLK1;
break;
default:
dev_err(rtd->dev, "invalid codec type %d\n",
ctx->codec_type);
return -EINVAL;
}
pll_in = params_rate(params) * 50;
}
if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {
pll_id = RT5682S_PLL2;
clk_id = RT5682S_SCLK_S_PLL2;
} else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) {
switch (ctx->codec_type) {
case CODEC_RT5650:
pll_id = 0; /* not used in codec driver */
clk_id = RT5645_SCLK_S_PLL1;
} else {
break;
case CODEC_RT5682:
pll_id = RT5682_PLL1;
clk_id = RT5682_SCLK_S_PLL1;
break;
case CODEC_RT5682S:
pll_id = RT5682S_PLL2;
clk_id = RT5682S_SCLK_S_PLL2;
break;
default:
dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type);
return -EINVAL;
}
pll_out = params_rate(params) * 512;
/* when MCLK is 512FS, no need to set PLL configuration additionally. */
if (pll_in == pll_out)
clk_id = RT5682S_SCLK_S_MCLK;
else {
if (pll_in == pll_out) {
switch (ctx->codec_type) {
case CODEC_RT5650:
clk_id = RT5645_SCLK_S_MCLK;
break;
case CODEC_RT5682:
clk_id = RT5682_SCLK_S_MCLK;
break;
case CODEC_RT5682S:
clk_id = RT5682S_SCLK_S_MCLK;
break;
default:
dev_err(rtd->dev, "invalid codec type %d\n",
ctx->codec_type);
return -EINVAL;
}
} else {
/* Configure pll for codec */
ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in,
pll_out);
......@@ -500,7 +522,7 @@ static int sof_card_late_probe(struct snd_soc_card *card)
struct sof_hdmi_pcm *pcm;
int err;
if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
if (ctx->amp_type == CODEC_MAX98373) {
/* Disable Left and Right Spk pin after boot */
snd_soc_dapm_disable_pin(dapm, "Left Spk");
snd_soc_dapm_disable_pin(dapm, "Right Spk");
......@@ -664,12 +686,11 @@ static struct snd_soc_dai_link_component dmic_component[] = {
#define IDISP_CODEC_MASK 0x4
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
int ssp_codec,
int ssp_amp,
int dmic_be_num,
int hdmi_num,
bool idisp_codec)
static struct snd_soc_dai_link *
sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec codec_type,
enum sof_ssp_codec amp_type, int ssp_codec,
int ssp_amp, int dmic_be_num, int hdmi_num,
bool idisp_codec)
{
struct snd_soc_dai_link_component *idisp_components;
struct snd_soc_dai_link_component *cpus;
......@@ -691,16 +712,25 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
goto devm_err;
links[id].id = id;
if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {
links[id].codecs = rt5682s_component;
links[id].num_codecs = ARRAY_SIZE(rt5682s_component);
} else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) {
switch (codec_type) {
case CODEC_RT5650:
links[id].codecs = &rt5650_components[0];
links[id].num_codecs = 1;
} else {
break;
case CODEC_RT5682:
links[id].codecs = rt5682_component;
links[id].num_codecs = ARRAY_SIZE(rt5682_component);
break;
case CODEC_RT5682S:
links[id].codecs = rt5682s_component;
links[id].num_codecs = ARRAY_SIZE(rt5682s_component);
break;
default:
dev_err(dev, "invalid codec type %d\n", codec_type);
return NULL;
}
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].init = sof_rt5682_codec_init;
......@@ -811,42 +841,54 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
}
/* speaker amp */
if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) {
if (amp_type != CODEC_NONE) {
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
"SSP%d-Codec", ssp_amp);
if (!links[id].name)
goto devm_err;
links[id].id = id;
if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
sof_rt1015_dai_link(&links[id]);
} else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
sof_rt1015p_dai_link(&links[id]);
} else if (sof_rt5682_quirk & SOF_RT1019_SPEAKER_AMP_PRESENT) {
sof_rt1019p_dai_link(&links[id]);
} else if (sof_rt5682_quirk &
SOF_MAX98373_SPEAKER_AMP_PRESENT) {
switch (amp_type) {
case CODEC_MAX98357A:
max_98357a_dai_link(&links[id]);
break;
case CODEC_MAX98360A:
max_98360a_dai_link(&links[id]);
break;
case CODEC_MAX98373:
links[id].codecs = max_98373_components;
links[id].num_codecs = ARRAY_SIZE(max_98373_components);
links[id].init = max_98373_spk_codec_init;
links[id].ops = &max_98373_ops;
} else if (sof_rt5682_quirk &
SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
max_98360a_dai_link(&links[id]);
} else if (sof_rt5682_quirk &
SOF_RT1011_SPEAKER_AMP_PRESENT) {
sof_rt1011_dai_link(&links[id]);
} else if (sof_rt5682_quirk &
SOF_MAX98390_SPEAKER_AMP_PRESENT) {
break;
case CODEC_MAX98390:
max_98390_dai_link(dev, &links[id]);
} else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) {
break;
case CODEC_RT1011:
sof_rt1011_dai_link(&links[id]);
break;
case CODEC_RT1015:
sof_rt1015_dai_link(&links[id]);
break;
case CODEC_RT1015P:
sof_rt1015p_dai_link(&links[id]);
break;
case CODEC_RT1019P:
sof_rt1019p_dai_link(&links[id]);
break;
case CODEC_RT5650:
/* use AIF2 to support speaker pipeline */
links[id].codecs = &rt5650_components[1];
links[id].num_codecs = 1;
links[id].init = rt5650_spk_init;
links[id].ops = &sof_rt5682_ops;
} else {
max_98357a_dai_link(&links[id]);
break;
default:
dev_err(dev, "invalid amp type %d\n", amp_type);
return NULL;
}
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].dpcm_playback = 1;
......@@ -949,20 +991,16 @@ static int sof_audio_probe(struct platform_device *pdev)
mach = pdev->dev.platform_data;
/* A speaker amp might not be present when the quirk claims one is.
* Detect this via whether the machine driver match includes quirk_data.
*/
if ((sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
sof_rt5682_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
/* Detect the headset codec variant */
if (acpi_dev_present("RTL5682", NULL, -1))
sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT;
else if (acpi_dev_present("10EC5650", NULL, -1)) {
sof_rt5682_quirk |= SOF_RT5650_HEADPHONE_CODEC_PRESENT;
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
if (ctx->codec_type == CODEC_RT5650) {
sof_audio_card_rt5682.name = devm_kstrdup(&pdev->dev, "rt5650",
GFP_KERNEL);
/* create speaker dai link also */
if (ctx->amp_type == CODEC_NONE)
ctx->amp_type = CODEC_RT5650;
}
if (soc_intel_is_byt() || soc_intel_is_cht()) {
......@@ -1015,19 +1053,9 @@ static int sof_audio_probe(struct platform_device *pdev)
/* compute number of dai links */
sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
if (ctx->amp_type != CODEC_NONE)
sof_audio_card_rt5682.num_links++;
if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
max_98373_set_codec_conf(&sof_audio_card_rt5682);
else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT)
sof_rt1011_codec_conf(&sof_audio_card_rt5682);
else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
else if (sof_rt5682_quirk & SOF_MAX98390_SPEAKER_AMP_PRESENT) {
max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
}
if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
sof_audio_card_rt5682.num_links++;
......@@ -1036,15 +1064,43 @@ static int sof_audio_probe(struct platform_device *pdev)
hweight32((sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) >>
SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT);
dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
dmic_be_num, hdmi_num, ctx->idisp_codec);
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->codec_type,
ctx->amp_type, ssp_codec, ssp_amp,
dmic_be_num, hdmi_num,
ctx->idisp_codec);
if (!dai_links)
return -ENOMEM;
sof_audio_card_rt5682.dai_link = dai_links;
if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT)
/* update codec_conf */
switch (ctx->amp_type) {
case CODEC_MAX98373:
max_98373_set_codec_conf(&sof_audio_card_rt5682);
break;
case CODEC_MAX98390:
max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
break;
case CODEC_RT1011:
sof_rt1011_codec_conf(&sof_audio_card_rt5682);
break;
case CODEC_RT1015:
sof_rt1015_codec_conf(&sof_audio_card_rt5682);
break;
case CODEC_RT1015P:
sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
break;
case CODEC_NONE:
case CODEC_MAX98357A:
case CODEC_MAX98360A:
case CODEC_RT1019P:
case CODEC_RT5650:
/* no codec conf required */
break;
default:
dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
return -EINVAL;
}
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
......@@ -1071,50 +1127,42 @@ static const struct platform_device_id board_ids[] = {
{
.name = "cml_rt1015_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1015_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{
.name = "jsl_rt5682_rt1015",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1015_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{
.name = "jsl_rt5682_mx98360",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{
.name = "jsl_rt5682_rt1015p",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1015P_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{
.name = "jsl_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0)),
},
{
.name = "jsl_rt5650",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_RT5682_SSP_AMP(1)),
},
{
.name = "tgl_mx98357_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -1124,8 +1172,6 @@ static const struct platform_device_id board_ids[] = {
.name = "tgl_rt1011_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1011_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -1135,8 +1181,6 @@ static const struct platform_device_id board_ids[] = {
.name = "tgl_mx98373_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98373_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -1146,8 +1190,6 @@ static const struct platform_device_id board_ids[] = {
.name = "adl_mx98373_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98373_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -1157,7 +1199,6 @@ static const struct platform_device_id board_ids[] = {
.name = "adl_mx98357_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
......@@ -1165,8 +1206,6 @@ static const struct platform_device_id board_ids[] = {
.name = "adl_max98390_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98390_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -1176,8 +1215,6 @@ static const struct platform_device_id board_ids[] = {
.name = "adl_mx98360_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -1195,8 +1232,6 @@ static const struct platform_device_id board_ids[] = {
.name = "adl_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) |
......@@ -1210,11 +1245,19 @@ static const struct platform_device_id board_ids[] = {
/* SSP 0 and SSP 2 are used for HDMI IN */
SOF_HDMI_CAPTURE_SSP_MASK(0x5)),
},
{
.name = "adl_rt5650",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT),
},
{
.name = "rpl_mx98357_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
......@@ -1222,8 +1265,6 @@ static const struct platform_device_id board_ids[] = {
.name = "rpl_mx98360_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_SSP(2) |
......@@ -1233,20 +1274,25 @@ static const struct platform_device_id board_ids[] = {
.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 = "rpl_rt5682_c1_h02",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(1) |
SOF_RT5682_NUM_HDMIDEV(3) |
/* SSP 0 and SSP 2 are used for HDMI IN */
SOF_HDMI_CAPTURE_SSP_MASK(0x5)),
},
{
.name = "mtl_mx98357_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4) |
SOF_RT5682_NUM_HDMIDEV(3) |
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT),
},
......@@ -1254,28 +1300,16 @@ static const struct platform_device_id board_ids[] = {
.name = "mtl_mx98360_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4)),
SOF_RT5682_NUM_HDMIDEV(3)),
},
{
.name = "mtl_rt1019_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1019_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(0) |
SOF_RT5682_NUM_HDMIDEV(3)),
},
{
.name = "jsl_rt5650",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
......@@ -1300,3 +1334,4 @@ MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);
......@@ -21,6 +21,7 @@
#include "hda_dsp_common.h"
#include "sof_realtek_common.h"
#include "sof_cirrus_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
......@@ -59,10 +60,6 @@
#define SOF_BT_OFFLOAD_SSP(quirk) \
(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
/* Speaker amplifiers */
#define SOF_RT1308_SPEAKER_AMP_PRESENT BIT(21)
#define SOF_CS35L41_SPEAKER_AMP_PRESENT BIT(22)
/* Default: SSP2 */
static unsigned long sof_ssp_amp_quirk = SOF_AMPLIFIER_SSP(2);
......@@ -77,6 +74,7 @@ struct sof_card_private {
struct list_head hdmi_pcm_list;
bool common_hdmi_codec_drv;
bool idisp_codec;
enum sof_ssp_codec amp_type;
};
static const struct dmi_system_id chromebook_platforms[] = {
......@@ -188,16 +186,22 @@ static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
#define IDISP_CODEC_MASK 0x4
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
int ssp_codec,
int dmic_be_num,
int hdmi_num,
bool idisp_codec)
/* BE ID defined in sof-tgl-rt1308-hdmi-ssp.m4 */
#define HDMI_IN_BE_ID 0
#define SPK_BE_ID 2
#define DMIC01_BE_ID 3
#define INTEL_HDMI_BE_ID 5
static struct snd_soc_dai_link *
sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
int ssp_codec, int dmic_be_num, int hdmi_num,
bool idisp_codec)
{
struct snd_soc_dai_link_component *idisp_components;
struct snd_soc_dai_link_component *cpus;
struct snd_soc_dai_link *links;
int i, id = 0;
bool fixed_be = false;
links = devm_kcalloc(dev, sof_ssp_amp_card.num_links,
sizeof(struct snd_soc_dai_link), GFP_KERNEL);
......@@ -211,6 +215,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
int num_of_hdmi_ssp = (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >>
SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT;
/* the topology supports HDMI-IN uses fixed BE ID for DAI links */
fixed_be = true;
for (i = 1; i <= num_of_hdmi_ssp; i++) {
int port = (i == 1 ? (sof_ssp_amp_quirk & SOF_HDMI_CAPTURE_1_SSP_MASK) >>
SOF_HDMI_CAPTURE_1_SSP_SHIFT :
......@@ -225,7 +232,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", port);
if (!links[id].name)
return NULL;
links[id].id = id;
links[id].id = fixed_be ? (HDMI_IN_BE_ID + i - 1) : id;
links[id].codecs = &asoc_dummy_dlc;
links[id].num_codecs = 1;
links[id].platforms = platform_component;
......@@ -238,29 +245,39 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
}
/* codec SSP */
links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec);
if (!links[id].name)
return NULL;
if (amp_type != CODEC_NONE) {
links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec);
if (!links[id].name)
return NULL;
links[id].id = fixed_be ? SPK_BE_ID : id;
switch (amp_type) {
case CODEC_CS35L41:
cs35l41_set_dai_link(&links[id]);
break;
case CODEC_RT1308:
sof_rt1308_dai_link(&links[id]);
break;
default:
dev_err(dev, "invalid amp type %d\n", amp_type);
return NULL;
}
links[id].id = id;
if (sof_ssp_amp_quirk & SOF_RT1308_SPEAKER_AMP_PRESENT) {
sof_rt1308_dai_link(&links[id]);
} else if (sof_ssp_amp_quirk & SOF_CS35L41_SPEAKER_AMP_PRESENT) {
cs35l41_set_dai_link(&links[id]);
}
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].dpcm_playback = 1;
/* feedback from amplifier or firmware-generated echo reference */
links[id].dpcm_capture = 1;
links[id].no_pcm = 1;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_codec);
if (!links[id].cpus->dai_name)
return NULL;
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].dpcm_playback = 1;
/* feedback from amplifier or firmware-generated echo reference */
links[id].dpcm_capture = 1;
links[id].no_pcm = 1;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_codec);
if (!links[id].cpus->dai_name)
return NULL;
id++;
id++;
}
/* dmic */
if (dmic_be_num > 0) {
......@@ -278,7 +295,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
}
for (i = 0; i < dmic_be_num; i++) {
links[id].id = id;
links[id].id = fixed_be ? (DMIC01_BE_ID + i) : id;
links[id].num_cpus = 1;
links[id].codecs = dmic_component;
links[id].num_codecs = ARRAY_SIZE(dmic_component);
......@@ -307,7 +324,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
if (!links[id].name)
goto devm_err;
links[id].id = id;
links[id].id = fixed_be ? (INTEL_HDMI_BE_ID + i - 1) : id;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
......@@ -385,13 +402,18 @@ static int sof_ssp_amp_probe(struct platform_device *pdev)
mach = pdev->dev.platform_data;
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
if (dmi_check_system(chromebook_platforms) || mach->mach_params.dmic_num > 0)
dmic_be_num = 2;
ssp_codec = sof_ssp_amp_quirk & SOF_AMPLIFIER_SSP_MASK;
/* set number of dai links */
sof_ssp_amp_card.num_links = 1 + dmic_be_num;
sof_ssp_amp_card.num_links = dmic_be_num;
if (ctx->amp_type != CODEC_NONE)
sof_ssp_amp_card.num_links++;
if (sof_ssp_amp_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT)
sof_ssp_amp_card.num_links += (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >>
......@@ -413,15 +435,26 @@ static int sof_ssp_amp_probe(struct platform_device *pdev)
if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
sof_ssp_amp_card.num_links++;
dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, dmic_be_num, hdmi_num, ctx->idisp_codec);
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type,
ssp_codec, dmic_be_num, hdmi_num,
ctx->idisp_codec);
if (!dai_links)
return -ENOMEM;
sof_ssp_amp_card.dai_link = dai_links;
/* update codec_conf */
if (sof_ssp_amp_quirk & SOF_CS35L41_SPEAKER_AMP_PRESENT) {
switch (ctx->amp_type) {
case CODEC_CS35L41:
cs35l41_set_codec_conf(&sof_ssp_amp_card);
break;
case CODEC_NONE:
case CODEC_RT1308:
/* no codec conf required */
break;
default:
dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
return -EINVAL;
}
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
......@@ -451,8 +484,7 @@ static const struct platform_device_id board_ids[] = {
SOF_NO_OF_HDMI_CAPTURE_SSP(2) |
SOF_HDMI_CAPTURE_1_SSP(1) |
SOF_HDMI_CAPTURE_2_SSP(5) |
SOF_SSP_HDMI_CAPTURE_PRESENT |
SOF_RT1308_SPEAKER_AMP_PRESENT),
SOF_SSP_HDMI_CAPTURE_PRESENT),
},
{
.name = "adl_cs35l41",
......@@ -460,8 +492,7 @@ static const struct platform_device_id board_ids[] = {
SOF_NO_OF_HDMI_PLAYBACK(4) |
SOF_HDMI_PLAYBACK_PRESENT |
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT |
SOF_CS35L41_SPEAKER_AMP_PRESENT),
SOF_SSP_BT_OFFLOAD_PRESENT),
},
{
.name = "adl_lt6911_hdmi_ssp",
......@@ -502,3 +533,4 @@ MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_CIRRUS_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2023 Intel Corporation. All rights reserved.
#include <linux/device.h>
#include <sound/soc-acpi.h>
#include "sof_ssp_common.h"
/*
* Codec probe function
*/
#define CODEC_MAP_ENTRY(n, h, t) \
{ \
.name = n, \
.acpi_hid = h, \
.codec_type = t, \
}
struct codec_map {
const char *name;
const char *acpi_hid;
enum sof_ssp_codec codec_type;
};
static const struct codec_map codecs[] = {
/* Cirrus Logic */
CODEC_MAP_ENTRY("CS42L42", CS42L42_ACPI_HID, CODEC_CS42L42),
/* Dialog */
CODEC_MAP_ENTRY("DA7219", DA7219_ACPI_HID, CODEC_DA7219),
/* Everest */
CODEC_MAP_ENTRY("ES8316", ES8316_ACPI_HID, CODEC_ES8316),
CODEC_MAP_ENTRY("ES8326", ES8326_ACPI_HID, CODEC_ES8326),
CODEC_MAP_ENTRY("ES8336", ES8336_ACPI_HID, CODEC_ES8336),
/* Nuvoton */
CODEC_MAP_ENTRY("NAU8825", NAU8825_ACPI_HID, CODEC_NAU8825),
/* Realtek */
CODEC_MAP_ENTRY("RT5650", RT5650_ACPI_HID, CODEC_RT5650),
CODEC_MAP_ENTRY("RT5682", RT5682_ACPI_HID, CODEC_RT5682),
CODEC_MAP_ENTRY("RT5682S", RT5682S_ACPI_HID, CODEC_RT5682S),
};
static const struct codec_map amps[] = {
/* Cirrus Logic */
CODEC_MAP_ENTRY("CS35L41", CS35L41_ACPI_HID, CODEC_CS35L41),
/* Maxim */
CODEC_MAP_ENTRY("MAX98357A", MAX_98357A_ACPI_HID, CODEC_MAX98357A),
CODEC_MAP_ENTRY("MAX98360A", MAX_98360A_ACPI_HID, CODEC_MAX98360A),
CODEC_MAP_ENTRY("MAX98373", MAX_98373_ACPI_HID, CODEC_MAX98373),
CODEC_MAP_ENTRY("MAX98390", MAX_98390_ACPI_HID, CODEC_MAX98390),
/* Nuvoton */
CODEC_MAP_ENTRY("NAU8318", NAU8318_ACPI_HID, CODEC_NAU8318),
/* Realtek */
CODEC_MAP_ENTRY("RT1011", RT1011_ACPI_HID, CODEC_RT1011),
CODEC_MAP_ENTRY("RT1015", RT1015_ACPI_HID, CODEC_RT1015),
CODEC_MAP_ENTRY("RT1015P", RT1015P_ACPI_HID, CODEC_RT1015P),
CODEC_MAP_ENTRY("RT1019P", RT1019P_ACPI_HID, CODEC_RT1019P),
CODEC_MAP_ENTRY("RT1308", RT1308_ACPI_HID, CODEC_RT1308),
};
enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(codecs); i++) {
if (!acpi_dev_present(codecs[i].acpi_hid, NULL, -1))
continue;
dev_dbg(dev, "codec %s found\n", codecs[i].name);
return codecs[i].codec_type;
}
return CODEC_NONE;
}
EXPORT_SYMBOL_NS(sof_ssp_detect_codec_type, SND_SOC_INTEL_SOF_SSP_COMMON);
enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(amps); i++) {
if (!acpi_dev_present(amps[i].acpi_hid, NULL, -1))
continue;
dev_dbg(dev, "amp %s found\n", amps[i].name);
return amps[i].codec_type;
}
return CODEC_NONE;
}
EXPORT_SYMBOL_NS(sof_ssp_detect_amp_type, SND_SOC_INTEL_SOF_SSP_COMMON);
MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2023 Intel Corporation.
*/
#ifndef __SOF_SSP_COMMON_H
#define __SOF_SSP_COMMON_H
/* Cirrus Logic */
#define CS35L41_ACPI_HID "CSC3541"
#define CS42L42_ACPI_HID "10134242"
/* Dialog */
#define DA7219_ACPI_HID "DLGS7219"
/* Everest */
#define ES8316_ACPI_HID "ESSX8316"
#define ES8326_ACPI_HID "ESSX8326"
#define ES8336_ACPI_HID "ESSX8336"
#define MAX_98357A_ACPI_HID "MX98357A"
#define MAX_98360A_ACPI_HID "MX98360A"
#define MAX_98373_ACPI_HID "MX98373"
#define MAX_98390_ACPI_HID "MX98390"
/* Nuvoton */
#define NAU8318_ACPI_HID "NVTN2012"
#define NAU8825_ACPI_HID "10508825"
/* Realtek */
#define RT1011_ACPI_HID "10EC1011"
#define RT1015_ACPI_HID "10EC1015"
#define RT1015P_ACPI_HID "RTL1015"
#define RT1019P_ACPI_HID "RTL1019"
#define RT1308_ACPI_HID "10EC1308"
#define RT5650_ACPI_HID "10EC5650"
#define RT5682_ACPI_HID "10EC5682"
#define RT5682S_ACPI_HID "RTL5682"
enum sof_ssp_codec {
CODEC_NONE,
/* headphone codec */
CODEC_CS42L42,
CODEC_DA7219,
CODEC_ES8316,
CODEC_ES8326,
CODEC_ES8336,
CODEC_NAU8825,
CODEC_RT5650,
CODEC_RT5682,
CODEC_RT5682S,
/* speaker amplifier */
CODEC_CS35L41,
CODEC_MAX98357A,
CODEC_MAX98360A,
CODEC_MAX98373,
CODEC_MAX98390,
CODEC_NAU8318,
CODEC_RT1011,
CODEC_RT1015,
CODEC_RT1015P,
CODEC_RT1019P,
CODEC_RT1308,
};
enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev);
enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev);
#endif /* __SOF_SSP_COMMON_H */
......@@ -492,6 +492,11 @@ static const struct snd_soc_acpi_codecs adl_nau8318_amp = {
.codecs = {"NVTN2012"}
};
static struct snd_soc_acpi_codecs adl_rt5650_amp = {
.num_codecs = 1,
.codecs = {"10EC5650"}
};
struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
{
.comp_ids = &adl_rt5682_rt5682s_hp,
......@@ -602,6 +607,20 @@ 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,
},
{
.id = "10EC5650",
.drv_name = "adl_rt5650",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_rt5650_amp,
.sof_tplg_filename = "sof-adl-rt5650.tplg",
},
{
.id = "DLGS7219",
.drv_name = "adl_mx98360_da7219",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_max98360a_amp,
.sof_tplg_filename = "sof-adl-max98360a-da7219.tplg",
},
/* place amp-only boards in the end of table */
{
.id = "CSC3541",
......
......@@ -14,7 +14,7 @@ static const struct snd_soc_acpi_codecs essx_83x6 = {
.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
};
static const struct snd_soc_acpi_codecs jsl_7219_98373_codecs = {
static const struct snd_soc_acpi_codecs mx98373_spk = {
.num_codecs = 1,
.codecs = {"MX98373"}
};
......@@ -52,14 +52,16 @@ static const struct snd_soc_acpi_codecs rt5682_rt5682s_hp = {
struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
{
.id = "DLGS7219",
.drv_name = "sof_da7219_mx98373",
.sof_tplg_filename = "sof-jsl-da7219.tplg",
.drv_name = "jsl_mx98373_da7219",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &jsl_7219_98373_codecs,
.quirk_data = &mx98373_spk,
.sof_tplg_filename = "sof-jsl-da7219.tplg",
},
{
.id = "DLGS7219",
.drv_name = "sof_da7219_mx98360a",
.drv_name = "jsl_mx98360_da7219",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &mx98360a_spk,
.sof_tplg_filename = "sof-jsl-da7219-mx98360a.tplg",
},
{
......
......@@ -402,6 +402,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
.quirk_data = &rpl_rt1019p_amp,
.sof_tplg_filename = "sof-rpl-rt1019-rt5682.tplg",
},
{
.comp_ids = &rpl_rt5682_hp,
.drv_name = "rpl_rt5682_c1_h02",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rpl_lt6911_hdmi,
.sof_tplg_filename = "sof-rpl-rt5682-ssp1-hdmi-ssp02.tplg",
},
{
.comp_ids = &rpl_essx_83x6,
.drv_name = "rpl_es83x6_c1_h02",
......
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