aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/boards
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/boards')
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c14
-rw-r--r--sound/soc/intel/boards/broadwell.c18
-rw-r--r--sound/soc/intel/boards/bxt_da7219_max98357a.c114
-rw-r--r--sound/soc/intel/boards/bxt_rt298.c13
-rw-r--r--sound/soc/intel/boards/bytcht_da7213.c8
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c336
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c23
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c180
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c12
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c12
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c9
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c30
-rw-r--r--sound/soc/intel/boards/glk_rt5682_max98357a.c68
-rw-r--r--sound/soc/intel/boards/haswell.c17
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c207
16 files changed, 861 insertions, 201 deletions
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 0a7e40d06395..12d6b73e9531 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -293,6 +293,7 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH
depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_DA7219
select SND_SOC_MAX98927
+ select SND_SOC_MAX98373
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c
index efcfd906c856..1844c88ea4e2 100644
--- a/sound/soc/intel/boards/bdw-rt5677.c
+++ b/sound/soc/intel/boards/bdw-rt5677.c
@@ -26,6 +26,7 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/jack.h>
+#include <sound/soc-acpi.h>
#include "../common/sst-dsp.h"
#include "../haswell/sst-haswell-ipc.h"
@@ -339,6 +340,9 @@ static struct snd_soc_card bdw_rt5677_card = {
static int bdw_rt5677_probe(struct platform_device *pdev)
{
struct bdw_rt5677_priv *bdw_rt5677;
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name = NULL;
+ int ret;
bdw_rt5677_card.dev = &pdev->dev;
@@ -350,6 +354,16 @@ static int bdw_rt5677_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ if (mach) /* extra check since legacy does not pass parameters */
+ platform_name = mach->mach_params.platform;
+
+ ret = snd_soc_fixup_dai_links_platform_name(&bdw_rt5677_card,
+ platform_name);
+ if (ret)
+ return ret;
+
snd_soc_card_set_drvdata(&bdw_rt5677_card, bdw_rt5677);
return devm_snd_soc_register_card(&pdev->dev, &bdw_rt5677_card);
diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c
index 68e6543e6cb0..b86c746d9b7a 100644
--- a/sound/soc/intel/boards/broadwell.c
+++ b/sound/soc/intel/boards/broadwell.c
@@ -21,6 +21,7 @@
#include <sound/soc.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
+#include <sound/soc-acpi.h>
#include "../common/sst-dsp.h"
#include "../haswell/sst-haswell-ipc.h"
@@ -192,7 +193,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
.stream_name = "Loopback",
.cpu_dai_name = "Loopback Pin",
.platform_name = "haswell-pcm-audio",
- .dynamic = 0,
+ .dynamic = 1,
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
@@ -267,7 +268,22 @@ static struct snd_soc_card broadwell_rt286 = {
static int broadwell_audio_probe(struct platform_device *pdev)
{
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name = NULL;
+ int ret;
+
broadwell_rt286.dev = &pdev->dev;
+
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ if (mach) /* extra check since legacy does not pass parameters */
+ platform_name = mach->mach_params.platform;
+
+ ret = snd_soc_fixup_dai_links_platform_name(&broadwell_rt286,
+ platform_name);
+ if (ret)
+ return ret;
+
return devm_snd_soc_register_card(&pdev->dev, &broadwell_rt286);
}
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c
index 6f052fc8d1e2..5cadb7f654f3 100644
--- a/sound/soc/intel/boards/bxt_da7219_max98357a.c
+++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c
@@ -16,6 +16,8 @@
* GNU General Public License for more details.
*/
+#include <asm/cpu_device_id.h>
+#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
@@ -23,6 +25,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include "../../codecs/hdac_hdmi.h"
#include "../../codecs/da7219.h"
#include "../../codecs/da7219-aad.h"
@@ -48,6 +51,7 @@ struct bxt_card_private {
enum {
BXT_DPCM_AUDIO_PB = 0,
BXT_DPCM_AUDIO_CP,
+ BXT_DPCM_AUDIO_HS_PB,
BXT_DPCM_AUDIO_REF_CP,
BXT_DPCM_AUDIO_DMIC_CP,
BXT_DPCM_AUDIO_HDMI1_PB,
@@ -102,7 +106,7 @@ static const struct snd_soc_dapm_widget broxton_widgets[] = {
platform_clock_control, SND_SOC_DAPM_POST_PMD|SND_SOC_DAPM_PRE_PMU),
};
-static const struct snd_soc_dapm_route broxton_map[] = {
+static const struct snd_soc_dapm_route audio_map[] = {
/* HP jack connectors - unknown if we have jack detection */
{"Headphone Jack", NULL, "HPL"},
{"Headphone Jack", NULL, "HPR"},
@@ -117,15 +121,6 @@ static const struct snd_soc_dapm_route broxton_map[] = {
{"DMic", NULL, "SoC DMIC"},
/* CODEC BE connections */
- {"HiFi Playback", NULL, "ssp5 Tx"},
- {"ssp5 Tx", NULL, "codec0_out"},
-
- {"Playback", NULL, "ssp1 Tx"},
- {"ssp1 Tx", NULL, "codec1_out"},
-
- {"codec0_in", NULL, "ssp1 Rx"},
- {"ssp1 Rx", NULL, "Capture"},
-
{"HDMI1", NULL, "hif5-0 Output"},
{"HDMI2", NULL, "hif6-0 Output"},
{"HDMI2", NULL, "hif7-0 Output"},
@@ -145,6 +140,28 @@ static const struct snd_soc_dapm_route broxton_map[] = {
{ "Headset Mic", NULL, "Platform Clock" },
};
+static const struct snd_soc_dapm_route broxton_map[] = {
+ {"HiFi Playback", NULL, "ssp5 Tx"},
+ {"ssp5 Tx", NULL, "codec0_out"},
+
+ {"Playback", NULL, "ssp1 Tx"},
+ {"ssp1 Tx", NULL, "codec1_out"},
+
+ {"codec0_in", NULL, "ssp1 Rx"},
+ {"ssp1 Rx", NULL, "Capture"},
+};
+
+static const struct snd_soc_dapm_route gemini_map[] = {
+ {"HiFi Playback", NULL, "ssp1 Tx"},
+ {"ssp1 Tx", NULL, "codec0_out"},
+
+ {"Playback", NULL, "ssp2 Tx"},
+ {"ssp2 Tx", NULL, "codec1_out"},
+
+ {"codec0_in", NULL, "ssp2 Rx"},
+ {"ssp2 Rx", NULL, "Capture"},
+};
+
static int broxton_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -192,6 +209,12 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
+ snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
+ snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
+ snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_3,
+ KEY_VOICECOMMAND);
+
da7219_aad_jack_det(component, &broxton_headset);
snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
@@ -383,6 +406,20 @@ static struct snd_soc_dai_link broxton_dais[] = {
.dpcm_capture = 1,
.ops = &broxton_da7219_fe_ops,
},
+ [BXT_DPCM_AUDIO_HS_PB] = {
+ .name = "Bxt Audio Headset Playback",
+ .stream_name = "Headset Playback",
+ .cpu_dai_name = "System Pin2",
+ .platform_name = "0000:00:0e.0",
+ .dynamic = 1,
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .nonatomic = 1,
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+ .dpcm_playback = 1,
+ .ops = &broxton_da7219_fe_ops,
+ },
[BXT_DPCM_AUDIO_REF_CP] =
{
.name = "Bxt Audio Reference cap",
@@ -531,6 +568,11 @@ static struct snd_soc_dai_link broxton_dais[] = {
},
};
+static const struct x86_cpu_id glk_ids[] = {
+ { X86_VENDOR_INTEL, 6, 0x7A }, /* Geminilake CPU_ID */
+ {}
+};
+
#define NAME_SIZE 32
static int bxt_card_late_probe(struct snd_soc_card *card)
{
@@ -540,6 +582,13 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
int err, i = 0;
char jack_name[NAME_SIZE];
+ if (x86_match_cpu(glk_ids))
+ snd_soc_dapm_add_routes(&card->dapm, gemini_map,
+ ARRAY_SIZE(gemini_map));
+ else
+ snd_soc_dapm_add_routes(&card->dapm, broxton_map,
+ ARRAY_SIZE(broxton_map));
+
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
component = pcm->codec_dai->component;
snprintf(jack_name, sizeof(jack_name),
@@ -575,8 +624,8 @@ static struct snd_soc_card broxton_audio_card = {
.num_controls = ARRAY_SIZE(broxton_controls),
.dapm_widgets = broxton_widgets,
.num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
- .dapm_routes = broxton_map,
- .num_dapm_routes = ARRAY_SIZE(broxton_map),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
.fully_routed = true,
.late_probe = bxt_card_late_probe,
};
@@ -584,6 +633,9 @@ static struct snd_soc_card broxton_audio_card = {
static int broxton_audio_probe(struct platform_device *pdev)
{
struct bxt_card_private *ctx;
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
+ int ret;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -593,16 +645,52 @@ static int broxton_audio_probe(struct platform_device *pdev)
broxton_audio_card.dev = &pdev->dev;
snd_soc_card_set_drvdata(&broxton_audio_card, ctx);
+ if (x86_match_cpu(glk_ids)) {
+ unsigned int i;
+
+ broxton_audio_card.name = "glkda7219max";
+ /* Fixup the SSP entries for geminilake */
+ for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) {
+ /* MAXIM_CODEC is connected to SSP1. */
+ if (!strcmp(broxton_dais[i].codec_dai_name,
+ BXT_MAXIM_CODEC_DAI)) {
+ broxton_dais[i].name = "SSP1-Codec";
+ broxton_dais[i].cpu_dai_name = "SSP1 Pin";
+ }
+ /* DIALOG_CODE is connected to SSP2 */
+ else if (!strcmp(broxton_dais[i].codec_dai_name,
+ BXT_DIALOG_CODEC_DAI)) {
+ broxton_dais[i].name = "SSP2-Codec";
+ broxton_dais[i].cpu_dai_name = "SSP2 Pin";
+ }
+ }
+ }
+
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ platform_name = mach->mach_params.platform;
+
+ ret = snd_soc_fixup_dai_links_platform_name(&broxton_audio_card,
+ platform_name);
+ if (ret)
+ return ret;
return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card);
}
+static const struct platform_device_id bxt_board_ids[] = {
+ { .name = "bxt_da7219_max98357a" },
+ { .name = "glk_da7219_max98357a" },
+ { }
+};
+
static struct platform_driver broxton_audio = {
.probe = broxton_audio_probe,
.driver = {
.name = "bxt_da7219_max98357a",
.pm = &snd_soc_pm_ops,
},
+ .id_table = bxt_board_ids,
};
module_platform_driver(broxton_audio)
@@ -612,5 +700,7 @@ MODULE_AUTHOR("Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>");
MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com>");
MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>");
+MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:bxt_da7219_max98357a");
+MODULE_ALIAS("platform:glk_da7219_max98357a");
diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c
index 27308337ab12..e91057f83d20 100644
--- a/sound/soc/intel/boards/bxt_rt298.c
+++ b/sound/soc/intel/boards/bxt_rt298.c
@@ -21,6 +21,7 @@
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
#include "../../codecs/hdac_hdmi.h"
@@ -576,6 +577,9 @@ static int broxton_audio_probe(struct platform_device *pdev)
struct bxt_rt286_private *ctx;
struct snd_soc_card *card =
(struct snd_soc_card *)pdev->id_entry->driver_data;
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
+ int ret;
int i;
for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) {
@@ -602,6 +606,15 @@ static int broxton_audio_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
snd_soc_card_set_drvdata(card, ctx);
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ platform_name = mach->mach_params.platform;
+
+ ret = snd_soc_fixup_dai_links_platform_name(card,
+ platform_name);
+ if (ret)
+ return ret;
+
return devm_snd_soc_register_card(&pdev->dev, card);
}
diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c
index 2179dedb28ad..b8e884803777 100644
--- a/sound/soc/intel/boards/bytcht_da7213.c
+++ b/sound/soc/intel/boards/bytcht_da7213.c
@@ -225,6 +225,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
const char *i2c_name = NULL;
int dai_index = 0;
int ret_val = 0;
@@ -250,6 +251,13 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
dailink[dai_index].codec_name = codec_name;
}
+ /* override plaform name, if required */
+ platform_name = mach->mach_params.platform;
+
+ ret_val = snd_soc_fixup_dai_links_platform_name(card, platform_name);
+ if (ret_val)
+ return ret_val;
+
ret_val = devm_snd_soc_register_card(&pdev->dev, card);
if (ret_val) {
dev_err(&pdev->dev,
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index adc26dfc7d65..d2a7e6ba11ae 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -19,13 +19,20 @@
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/device.h>
#include <linux/slab.h>
+#include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
#include <asm/platform_sst_audio.h>
-#include <linux/clk.h>
+#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -35,27 +42,96 @@
struct byt_cht_es8316_private {
struct clk *mclk;
+ struct snd_soc_jack jack;
+ struct gpio_desc *speaker_en_gpio;
+ bool speaker_en;
};
+enum {
+ BYT_CHT_ES8316_INTMIC_IN1_MAP,
+ BYT_CHT_ES8316_INTMIC_IN2_MAP,
+};
+
+#define BYT_CHT_ES8316_MAP(quirk) ((quirk) & GENMASK(3, 0))
+#define BYT_CHT_ES8316_SSP0 BIT(16)
+#define BYT_CHT_ES8316_MONO_SPEAKER BIT(17)
+
+static int quirk;
+
+static int quirk_override = -1;
+module_param_named(quirk, quirk_override, int, 0444);
+MODULE_PARM_DESC(quirk, "Board-specific quirk override");
+
+static void log_quirks(struct device *dev)
+{
+ if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN1_MAP)
+ dev_info(dev, "quirk IN1_MAP enabled");
+ if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN2_MAP)
+ dev_info(dev, "quirk IN2_MAP enabled");
+ if (quirk & BYT_CHT_ES8316_SSP0)
+ dev_info(dev, "quirk SSP0 enabled");
+ if (quirk & BYT_CHT_ES8316_MONO_SPEAKER)
+ dev_info(dev, "quirk MONO_SPEAKER enabled\n");
+}
+
+static int byt_cht_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_card *card = w->dapm->card;
+ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ priv->speaker_en = true;
+ else
+ priv->speaker_en = false;
+
+ gpiod_set_value_cansleep(priv->speaker_en_gpio, priv->speaker_en);
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget byt_cht_es8316_widgets[] = {
+ SND_SOC_DAPM_SPK("Speaker", NULL),
SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Internal Mic", NULL),
- /*
- * The codec supports two analog microphone inputs. I have only
- * tested MIC1. A DMIC route could also potentially be added
- * if such functionality is found on another platform.
- */
- SND_SOC_DAPM_MIC("Microphone 1", NULL),
- SND_SOC_DAPM_MIC("Microphone 2", NULL),
+ SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
+ byt_cht_es8316_speaker_power_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
};
static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = {
- {"MIC1", NULL, "Microphone 1"},
- {"MIC2", NULL, "Microphone 2"},
-
{"Headphone", NULL, "HPOL"},
{"Headphone", NULL, "HPOR"},
+ /*
+ * There is no separate speaker output instead the speakers are muxed to
+ * the HP outputs. The mux is controlled by the "Speaker Power" supply.
+ */
+ {"Speaker", NULL, "HPOL"},
+ {"Speaker", NULL, "HPOR"},
+ {"Speaker", NULL, "Speaker Power"},
+};
+
+static const struct snd_soc_dapm_route byt_cht_es8316_intmic_in1_map[] = {
+ {"MIC1", NULL, "Internal Mic"},
+ {"MIC2", NULL, "Headset Mic"},
+};
+
+static const struct snd_soc_dapm_route byt_cht_es8316_intmic_in2_map[] = {
+ {"MIC2", NULL, "Internal Mic"},
+ {"MIC1", NULL, "Headset Mic"},
+};
+
+static const struct snd_soc_dapm_route byt_cht_es8316_ssp0_map[] = {
+ {"Playback", NULL, "ssp0 Tx"},
+ {"ssp0 Tx", NULL, "modem_out"},
+ {"modem_in", NULL, "ssp0 Rx"},
+ {"ssp0 Rx", NULL, "Capture"},
+};
+
+static const struct snd_soc_dapm_route byt_cht_es8316_ssp2_map[] = {
{"Playback", NULL, "ssp2 Tx"},
{"ssp2 Tx", NULL, "codec_out0"},
{"ssp2 Tx", NULL, "codec_out1"},
@@ -65,19 +141,60 @@ static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = {
};
static const struct snd_kcontrol_new byt_cht_es8316_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Speaker"),
SOC_DAPM_PIN_SWITCH("Headphone"),
- SOC_DAPM_PIN_SWITCH("Microphone 1"),
- SOC_DAPM_PIN_SWITCH("Microphone 2"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Internal Mic"),
+};
+
+static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ {
+ .pin = "Headphone",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
};
static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
{
+ struct snd_soc_component *codec = runtime->codec_dai->component;
struct snd_soc_card *card = runtime->card;
struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+ const struct snd_soc_dapm_route *custom_map;
+ int num_routes;
int ret;
card->dapm.idle_bias_off = true;
+ switch (BYT_CHT_ES8316_MAP(quirk)) {
+ case BYT_CHT_ES8316_INTMIC_IN1_MAP:
+ default:
+ custom_map = byt_cht_es8316_intmic_in1_map;
+ num_routes = ARRAY_SIZE(byt_cht_es8316_intmic_in1_map);
+ break;
+ case BYT_CHT_ES8316_INTMIC_IN2_MAP:
+ custom_map = byt_cht_es8316_intmic_in2_map;
+ num_routes = ARRAY_SIZE(byt_cht_es8316_intmic_in2_map);
+ break;
+ }
+ ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
+ if (ret)
+ return ret;
+
+ if (quirk & BYT_CHT_ES8316_SSP0) {
+ custom_map = byt_cht_es8316_ssp0_map;
+ num_routes = ARRAY_SIZE(byt_cht_es8316_ssp0_map);
+ } else {
+ custom_map = byt_cht_es8316_ssp2_map;
+ num_routes = ARRAY_SIZE(byt_cht_es8316_ssp2_map);
+ }
+ ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
+ if (ret)
+ return ret;
+
/*
* The firmware might enable the clock at boot (this information
* may or may not be reflected in the enable clock register).
@@ -105,6 +222,18 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
return ret;
}
+ ret = snd_soc_card_jack_new(card, "Headset",
+ SND_JACK_HEADSET | SND_JACK_BTN_0,
+ &priv->jack, byt_cht_es8316_jack_pins,
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+ return ret;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
return 0;
}
@@ -123,14 +252,21 @@ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
- int ret;
+ int ret, bits;
/* The DSP will covert the FE rate to 48k, stereo */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
- /* set SSP2 to 24-bit */
- params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+ if (quirk & BYT_CHT_ES8316_SSP0) {
+ /* set SSP0 to 16-bit */
+ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
+ bits = 16;
+ } else {
+ /* set SSP2 to 24-bit */
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+ bits = 24;
+ }
/*
* Default mode for SSP configuration is TDM 4 slot, override config
@@ -147,7 +283,7 @@ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
return ret;
}
- ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
+ ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits);
if (ret < 0) {
dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
return ret;
@@ -218,6 +354,59 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
/* SoC card */
+static char codec_name[SND_ACPI_I2C_ID_LEN];
+static char long_name[50]; /* = "bytcht-es8316-*-spk-*-mic" */
+
+static int byt_cht_es8316_suspend(struct snd_soc_card *card)
+{
+ struct snd_soc_component *component;
+
+ for_each_card_components(card, component) {
+ if (!strcmp(component->name, codec_name)) {
+ dev_dbg(component->dev, "disabling jack detect before suspend\n");
+ snd_soc_component_set_jack(component, NULL, NULL);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int byt_cht_es8316_resume(struct snd_soc_card *card)
+{
+ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+ struct snd_soc_component *component;
+
+ for_each_card_components(card, component) {
+ if (!strcmp(component->name, codec_name)) {
+ dev_dbg(component->dev, "re-enabling jack detect after resume\n");
+ snd_soc_component_set_jack(component, &priv->jack, NULL);
+ break;
+ }
+ }
+
+ /*
+ * Some Cherry Trail boards with an ES8316 codec have a bug in their
+ * ACPI tables where the MSSL1680 touchscreen's _PS0 and _PS3 methods
+ * wrongly also set the speaker-enable GPIO to 1/0. Testing has shown
+ * that this really is a bug and the GPIO has no influence on the
+ * touchscreen at all.
+ *
+ * The silead.c touchscreen driver does not support runtime suspend, so
+ * the GPIO can only be changed underneath us during a system suspend.
+ * This resume() function runs from a pm complete() callback, and thus
+ * is guaranteed to run after the touchscreen driver/ACPI-subsys has
+ * brought the touchscreen back up again (and thus changed the GPIO).
+ *
+ * So to work around this we pass GPIOD_FLAGS_BIT_NONEXCLUSIVE when
+ * requesting the GPIO and we set its value here to undo any changes
+ * done by the touchscreen's broken _PS0 ACPI method.
+ */
+ gpiod_set_value_cansleep(priv->speaker_en_gpio, priv->speaker_en);
+
+ return 0;
+}
+
static struct snd_soc_card byt_cht_es8316_card = {
.name = "bytcht-es8316",
.owner = THIS_MODULE,
@@ -230,24 +419,40 @@ static struct snd_soc_card byt_cht_es8316_card = {
.controls = byt_cht_es8316_controls,
.num_controls = ARRAY_SIZE(byt_cht_es8316_controls),
.fully_routed = true,
+ .suspend_pre = byt_cht_es8316_suspend,
+ .resume_post = byt_cht_es8316_resume,
};
-static char codec_name[SND_ACPI_I2C_ID_LEN];
+static const struct x86_cpu_id baytrail_cpu_ids[] = {
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Valleyview */
+ {}
+};
+
+static const struct acpi_gpio_params first_gpio = { 0, 0, false };
+
+static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = {
+ { "speaker-enable-gpios", &first_gpio, 1 },
+ { },
+};
static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
{
+ static const char * const mic_name[] = { "in1", "in2" };
struct byt_cht_es8316_private *priv;
+ struct device *dev = &pdev->dev;
struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
const char *i2c_name = NULL;
+ struct device *codec_dev;
int dai_index = 0;
int i;
int ret = 0;
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- mach = (&pdev->dev)->platform_data;
+ mach = dev->platform_data;
/* fix index of codec dai */
for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) {
if (!strcmp(byt_cht_es8316_dais[i].codec_name,
@@ -265,26 +470,94 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
byt_cht_es8316_dais[dai_index].codec_name = codec_name;
}
- /* register the soc card */
- byt_cht_es8316_card.dev = &pdev->dev;
- snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
+ /* override plaform name, if required */
+ platform_name = mach->mach_params.platform;
- priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
+ ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card,
+ platform_name);
+ if (ret)
+ return ret;
+
+ /* Check for BYTCR or other platform and setup quirks */
+ if (x86_match_cpu(baytrail_cpu_ids) &&
+ mach->mach_params.acpi_ipc_irq_index == 0) {
+ /* On BYTCR default to SSP0, internal-mic-in2-map, mono-spk */
+ quirk = BYT_CHT_ES8316_SSP0 | BYT_CHT_ES8316_INTMIC_IN2_MAP |
+ BYT_CHT_ES8316_MONO_SPEAKER;
+ } else {
+ /* Others default to internal-mic-in1-map, mono-speaker */
+ quirk = BYT_CHT_ES8316_INTMIC_IN1_MAP |
+ BYT_CHT_ES8316_MONO_SPEAKER;
+ }
+ if (quirk_override != -1) {
+ dev_info(dev, "Overriding quirk 0x%x => 0x%x\n", quirk,
+ quirk_override);
+ quirk = quirk_override;
+ }
+ log_quirks(dev);
+
+ if (quirk & BYT_CHT_ES8316_SSP0)
+ byt_cht_es8316_dais[dai_index].cpu_dai_name = "ssp0-port";
+
+ /* get the clock */
+ priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
if (IS_ERR(priv->mclk)) {
ret = PTR_ERR(priv->mclk);
- dev_err(&pdev->dev,
- "Failed to get MCLK from pmc_plt_clk_3: %d\n",
- ret);
+ dev_err(dev, "clk_get pmc_plt_clk_3 failed: %d\n", ret);
return ret;
}
- ret = devm_snd_soc_register_card(&pdev->dev, &byt_cht_es8316_card);
+ /* get speaker enable GPIO */
+ codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
+
+ devm_acpi_dev_add_driver_gpios(codec_dev, byt_cht_es8316_gpios);
+ priv->speaker_en_gpio =
+ gpiod_get_index(codec_dev, "speaker-enable", 0,
+ /* see comment in byt_cht_es8316_resume */
+ GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
+ put_device(codec_dev);
+
+ if (IS_ERR(priv->speaker_en_gpio)) {
+ ret = PTR_ERR(priv->speaker_en_gpio);
+ switch (ret) {
+ case -ENOENT:
+ priv->speaker_en_gpio = NULL;
+ break;
+ default:
+ dev_err(dev, "get speaker GPIO failed: %d\n", ret);
+ /* fall through */
+ case -EPROBE_DEFER:
+ return ret;
+ }
+ }
+
+ /* register the soc card */
+ snprintf(long_name, sizeof(long_name), "bytcht-es8316-%s-spk-%s-mic",
+ (quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "mono" : "stereo",
+ mic_name[BYT_CHT_ES8316_MAP(quirk)]);
+ byt_cht_es8316_card.long_name = long_name;
+ byt_cht_es8316_card.dev = dev;
+ snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
+
+ ret = devm_snd_soc_register_card(dev, &byt_cht_es8316_card);
if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);
+ gpiod_put(priv->speaker_en_gpio);
+ dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, &byt_cht_es8316_card);
- return ret;
+ return 0;
+}
+
+static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+
+ gpiod_put(priv->speaker_en_gpio);
+ return 0;
}
static struct platform_driver snd_byt_cht_es8316_mc_driver = {
@@ -292,6 +565,7 @@ static struct platform_driver snd_byt_cht_es8316_mc_driver = {
.name = "bytcht_es8316",
},
.probe = snd_byt_cht_es8316_mc_probe,
+ .remove = snd_byt_cht_es8316_mc_remove,
};
module_platform_driver(snd_byt_cht_es8316_mc_driver);
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index a22366ce33c4..940eb27158da 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -431,6 +431,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
+ {
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
@@ -1137,10 +1149,11 @@ struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
{
- const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" };
+ static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" };
const struct dmi_system_id *dmi_id;
struct byt_rt5640_private *priv;
struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
const char *i2c_name = NULL;
int ret_val = 0;
int dai_index = 0;
@@ -1305,6 +1318,14 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
byt_rt5640_card.long_name = byt_rt5640_long_name;
+ /* override plaform name, if required */
+ platform_name = mach->mach_params.platform;
+
+ ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,
+ platform_name);
+ if (ret_val)
+ return ret_val;
+
ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
if (ret_val) {
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index e528995668b7..b0a4d297176e 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -91,13 +91,20 @@ enum {
struct byt_rt5651_private {
struct clk *mclk;
struct gpio_desc *ext_amp_gpio;
+ struct gpio_desc *hp_detect;
struct snd_soc_jack jack;
};
+static const struct acpi_gpio_mapping *byt_rt5651_gpios;
+
/* Default: jack-detect on JD1_1, internal mic on in2, headsetmic on in3 */
static unsigned long byt_rt5651_quirk = BYT_RT5651_DEFAULT_QUIRKS |
BYT_RT5651_IN2_MAP;
+static unsigned int quirk_override;
+module_param_named(quirk, quirk_override, uint, 0444);
+MODULE_PARM_DESC(quirk, "Board-specific quirk override");
+
static void log_quirks(struct device *dev)
{
if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP)
@@ -266,7 +273,7 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
{"DMIC L1", NULL, "Internal Mic"},
{"DMIC R1", NULL, "Internal Mic"},
- {"IN3P", NULL, "Headset Mic"},
+ {"IN2P", NULL, "Headset Mic"},
};
static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
@@ -360,6 +367,22 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
return byt_rt5651_prepare_and_enable_pll1(codec_dai, rate, bclk_ratio);
}
+static const struct acpi_gpio_params pov_p1006w_hp_detect = { 1, 0, false };
+static const struct acpi_gpio_params pov_p1006w_ext_amp_en = { 2, 0, true };
+
+static const struct acpi_gpio_mapping byt_rt5651_pov_p1006w_gpios[] = {
+ { "hp-detect-gpios", &pov_p1006w_hp_detect, 1, },
+ { "ext-amp-enable-gpios", &pov_p1006w_ext_amp_en, 1, },
+ { },
+};
+
+static int byt_rt5651_pov_p1006w_quirk_cb(const struct dmi_system_id *id)
+{
+ byt_rt5651_quirk = (unsigned long)id->driver_data;
+ byt_rt5651_gpios = byt_rt5651_pov_p1006w_gpios;
+ return 1;
+}
+
static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
{
byt_rt5651_quirk = (unsigned long)id->driver_data;
@@ -436,6 +459,23 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
BYT_RT5651_IN1_MAP),
},
{
+ /* Point of View mobii wintab p1006w (v1.0) */
+ .callback = byt_rt5651_pov_p1006w_quirk_cb,
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
+ /* Note 105b is Foxcon's USB/PCI vendor id */
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "105B"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"),
+ },
+ .driver_data = (void *)(BYT_RT5651_DMIC_MAP |
+ BYT_RT5651_OVCD_TH_2000UA |
+ BYT_RT5651_OVCD_SF_0P75 |
+ BYT_RT5651_DMIC_EN |
+ BYT_RT5651_MCLK_EN |
+ BYT_RT5651_SSP0_AIF1),
+ },
+ {
/* VIOS LTH17 */
.callback = byt_rt5651_quirk_cb,
.matches = {
@@ -495,6 +535,7 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
const struct snd_soc_dapm_route *custom_map;
int num_routes;
+ int report;
int ret;
card->dapm.idle_bias_off = true;
@@ -578,20 +619,27 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
dev_err(card->dev, "unable to set MCLK rate\n");
}
- if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
+ report = 0;
+ if (BYT_RT5651_JDSRC(byt_rt5651_quirk))
+ report = SND_JACK_HEADSET | SND_JACK_BTN_0;
+ else if (priv->hp_detect)
+ report = SND_JACK_HEADSET;
+
+ if (report) {
ret = snd_soc_card_jack_new(runtime->card, "Headset",
- SND_JACK_HEADSET | SND_JACK_BTN_0,
- &priv->jack, bytcr_jack_pins,
+ report, &priv->jack, bytcr_jack_pins,
ARRAY_SIZE(bytcr_jack_pins));
if (ret) {
dev_err(runtime->dev, "jack creation failed %d\n", ret);
return ret;
}
- snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
- KEY_PLAYPAUSE);
+ if (report & SND_JACK_BTN_0)
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
+ KEY_PLAYPAUSE);
- ret = snd_soc_component_set_jack(codec, &priv->jack, NULL);
+ ret = snd_soc_component_set_jack(codec, &priv->jack,
+ priv->hp_detect);
if (ret)
return ret;
}
@@ -763,7 +811,8 @@ static int byt_rt5651_resume(struct snd_soc_card *card)
for_each_card_components(card, component) {
if (!strcmp(component->name, byt_rt5651_codec_name)) {
dev_dbg(component->dev, "re-enabling jack detect after resume\n");
- snd_soc_component_set_jack(component, &priv->jack, NULL);
+ snd_soc_component_set_jack(component, &priv->jack,
+ priv->hp_detect);
break;
}
}
@@ -795,74 +844,18 @@ static const struct x86_cpu_id cherrytrail_cpu_ids[] = {
{}
};
-static const struct acpi_gpio_params first_gpio = { 0, 0, false };
-static const struct acpi_gpio_params second_gpio = { 1, 0, false };
-
-static const struct acpi_gpio_mapping byt_rt5651_amp_en_first[] = {
- { "ext-amp-enable-gpios", &first_gpio, 1 },
- { },
-};
+static const struct acpi_gpio_params ext_amp_enable_gpios = { 0, 0, false };
-static const struct acpi_gpio_mapping byt_rt5651_amp_en_second[] = {
- { "ext-amp-enable-gpios", &second_gpio, 1 },
+static const struct acpi_gpio_mapping cht_rt5651_gpios[] = {
+ /*
+ * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources,
+ * other boards may have I2cSerialBusV2, GpioInt, GpioIo instead.
+ * We want the GpioIo one for the ext-amp-enable-gpio.
+ */
+ { "ext-amp-enable-gpios", &ext_amp_enable_gpios, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
{ },
};
-/*
- * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources, other
- * boards may have I2cSerialBusV2, GpioInt, GpioIo instead. We want the
- * GpioIo one for the ext-amp-enable-gpio and both count for the index in
- * acpi_gpio_params index. So we have 2 different mappings and the code
- * below figures out which one to use.
- */
-struct byt_rt5651_acpi_resource_data {
- int gpio_count;
- int gpio_int_idx;
-};
-
-static int snd_byt_rt5651_acpi_resource(struct acpi_resource *ares, void *arg)
-{
- struct byt_rt5651_acpi_resource_data *data = arg;
-
- if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
- return 0;
-
- if (ares->data.gpio.connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
- data->gpio_int_idx = data->gpio_count;
-
- data->gpio_count++;
- return 0;
-}
-
-static void snd_byt_rt5651_mc_add_amp_en_gpio_mapping(struct device *codec)
-{
- struct byt_rt5651_acpi_resource_data data = { 0, -1 };
- LIST_HEAD(resources);
- int ret;
-
- ret = acpi_dev_get_resources(ACPI_COMPANION(codec), &resources,
- snd_byt_rt5651_acpi_resource, &data);
- if (ret < 0) {
- dev_warn(codec, "Failed to get ACPI resources, not adding external amplifier GPIO mapping\n");
- return;
- }
-
- /* All info we need is gathered during the walk */
- acpi_dev_free_resource_list(&resources);
-
- switch (data.gpio_int_idx) {
- case 0:
- devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_second);
- break;
- case 1:
- devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_first);
- break;
- default:
- dev_warn(codec, "Unknown GpioInt index %d, not adding external amplifier GPIO mapping\n",
- data.gpio_int_idx);
- }
-}
-
struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
u64 aif_value; /* 1: AIF1, 2: AIF2 */
u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
@@ -870,9 +863,10 @@ struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
{
- const char * const mic_name[] = { "dmic", "in1", "in2", "in12" };
+ static const char * const mic_name[] = { "dmic", "in1", "in2", "in12" };
struct byt_rt5651_private *priv;
struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
struct device *codec_dev;
const char *i2c_name = NULL;
const char *hp_swapped;
@@ -973,6 +967,12 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
/* check quirks before creating card */
dmi_check_system(byt_rt5651_quirk_table);
+ if (quirk_override) {
+ dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n",
+ (unsigned int)byt_rt5651_quirk, quirk_override);
+ byt_rt5651_quirk = quirk_override;
+ }
+
/* Must be called before register_card, also see declaration comment. */
ret_val = byt_rt5651_add_codec_device_props(codec_dev);
if (ret_val) {
@@ -981,8 +981,11 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
}
/* Cherry Trail devices use an external amplifier enable gpio */
- if (x86_match_cpu(cherrytrail_cpu_ids)) {
- snd_byt_rt5651_mc_add_amp_en_gpio_mapping(codec_dev);
+ if (x86_match_cpu(cherrytrail_cpu_ids) && !byt_rt5651_gpios)
+ byt_rt5651_gpios = cht_rt5651_gpios;
+
+ if (byt_rt5651_gpios) {
+ devm_acpi_dev_add_driver_gpios(codec_dev, byt_rt5651_gpios);
priv->ext_amp_gpio = devm_fwnode_get_index_gpiod_from_child(
&pdev->dev, "ext-amp-enable", 0,
codec_dev->fwnode,
@@ -1002,6 +1005,25 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
return ret_val;
}
}
+ priv->hp_detect = devm_fwnode_get_index_gpiod_from_child(
+ &pdev->dev, "hp-detect", 0,
+ codec_dev->fwnode,
+ GPIOD_IN, "hp-detect");
+ if (IS_ERR(priv->hp_detect)) {
+ ret_val = PTR_ERR(priv->hp_detect);
+ switch (ret_val) {
+ case -ENOENT:
+ priv->hp_detect = NULL;
+ break;
+ default:
+ dev_err(&pdev->dev, "Failed to get hp-detect GPIO: %d\n",
+ ret_val);
+ /* fall through */
+ case -EPROBE_DEFER:
+ put_device(codec_dev);
+ return ret_val;
+ }
+ }
}
put_device(codec_dev);
@@ -1060,6 +1082,14 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)], hp_swapped);
byt_rt5651_card.long_name = byt_rt5651_long_name;
+ /* override plaform name, if required */
+ platform_name = mach->mach_params.platform;
+
+ ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card,
+ platform_name);
+ if (ret_val)
+ return ret_val;
+
ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
if (ret_val) {
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
index 08a5152e635a..3263b0495853 100644
--- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c
+++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
@@ -28,6 +28,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include <sound/jack.h>
#include "../../codecs/max98090.h"
#include "../atom/sst-atom-controls.h"
@@ -420,6 +421,8 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
int ret_val = 0;
struct cht_mc_private *drv;
const char *mclk_name;
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
int quirks = 0;
dmi_id = dmi_first_match(cht_max98090_quirk_table);
@@ -442,6 +445,15 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
dev_dbg(dev, "Unable to add GPIO mapping table\n");
}
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ platform_name = mach->mach_params.platform;
+
+ ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
+ platform_name);
+ if (ret_val)
+ return ret_val;
+
/* register the soc card */
snd_soc_card_cht.dev = &pdev->dev;
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c
index 30c46977d53c..02c2fa239331 100644
--- a/sound/soc/intel/boards/cht_bsw_nau8824.c
+++ b/sound/soc/intel/boards/cht_bsw_nau8824.c
@@ -25,6 +25,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include <sound/jack.h>
#include <linux/input.h>
#include "../atom/sst-atom-controls.h"
@@ -246,6 +247,8 @@ static struct snd_soc_card snd_soc_card_cht = {
static int snd_cht_mc_probe(struct platform_device *pdev)
{
struct cht_mc_private *drv;
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
int ret_val;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
@@ -253,6 +256,15 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
return -ENOMEM;
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ platform_name = mach->mach_params.platform;
+
+ ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
+ platform_name);
+ if (ret_val)
+ return ret_val;
+
/* register the soc card */
snd_soc_card_cht.dev = &pdev->dev;
ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index 250a356a0cbf..cbc2d458483f 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -530,6 +530,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = snd_soc_cards[0].soc_card;
struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
struct cht_mc_private *drv;
const char *i2c_name = NULL;
bool found = false;
@@ -663,6 +664,14 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
cht_rt5645_cpu_dai_name;
}
+ /* override plaform name, if required */
+ platform_name = mach->mach_params.platform;
+
+ ret_val = snd_soc_fixup_dai_links_platform_name(card,
+ platform_name);
+ if (ret_val)
+ return ret_val;
+
drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
if (IS_ERR(drv->mclk)) {
dev_err(&pdev->dev,
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index 9de64f447e7b..3d5a2b3a06f0 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -400,6 +400,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
int ret_val = 0;
struct cht_mc_private *drv;
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
+ const char *platform_name;
const char *i2c_name;
int i;
@@ -410,22 +411,27 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
strcpy(drv->codec_name, RT5672_I2C_DEFAULT);
/* fixup codec name based on HID */
- if (mach) {
- i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
- if (i2c_name) {
- snprintf(drv->codec_name, sizeof(drv->codec_name),
- "i2c-%s", i2c_name);
- for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
- if (!strcmp(cht_dailink[i].codec_name,
- RT5672_I2C_DEFAULT)) {
- cht_dailink[i].codec_name =
- drv->codec_name;
- break;
- }
+ i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
+ if (i2c_name) {
+ snprintf(drv->codec_name, sizeof(drv->codec_name),
+ "i2c-%s", i2c_name);
+ for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
+ if (!strcmp(cht_dailink[i].codec_name,
+ RT5672_I2C_DEFAULT)) {
+ cht_dailink[i].codec_name = drv->codec_name;
+ break;
}
}
}
+ /* override plaform name, if required */
+ platform_name = mach->mach_params.platform;
+
+ ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
+ platform_name);
+ if (ret_val)
+ return ret_val;
+
drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
if (IS_ERR(drv->mclk)) {
dev_err(&pdev->dev,
diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c
index c74c4f17316f..d17126f7757c 100644
--- a/sound/soc/intel/boards/glk_rt5682_max98357a.c
+++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c
@@ -16,6 +16,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include "../skylake/skl.h"
#include "../../codecs/rt5682.h"
#include "../../codecs/hdac_hdmi.h"
@@ -55,39 +56,6 @@ enum {
GLK_DPCM_AUDIO_HDMI3_PB,
};
-static int platform_clock_control(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *k, int event)
-{
- struct snd_soc_dapm_context *dapm = w->dapm;
- struct snd_soc_card *card = dapm->card;
- struct snd_soc_dai *codec_dai;
- int ret = 0;
-
- codec_dai = snd_soc_card_get_codec_dai(card, GLK_REALTEK_CODEC_DAI);
- if (!codec_dai) {
- dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
- return -EIO;
- }
-
- if (SND_SOC_DAPM_EVENT_OFF(event)) {
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
- if (ret)
- dev_err(card->dev, "failed to stop sysclk: %d\n", ret);
- } else if (SND_SOC_DAPM_EVENT_ON(event)) {
- ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
- GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
- if (ret < 0) {
- dev_err(card->dev, "can't set codec pll: %d\n", ret);
- return ret;
- }
- }
-
- if (ret)
- dev_err(card->dev, "failed to start internal clk: %d\n", ret);
-
- return ret;
-}
-
static const struct snd_kcontrol_new geminilake_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -102,14 +70,10 @@ static const struct snd_soc_dapm_widget geminilake_widgets[] = {
SND_SOC_DAPM_SPK("HDMI1", NULL),
SND_SOC_DAPM_SPK("HDMI2", NULL),
SND_SOC_DAPM_SPK("HDMI3", NULL),
- SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
- platform_clock_control, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_route geminilake_map[] = {
/* HP jack connectors - unknown if we have jack detection */
- { "Headphone Jack", NULL, "Platform Clock" },
{ "Headphone Jack", NULL, "HPOL" },
{ "Headphone Jack", NULL, "HPOR" },
@@ -117,7 +81,6 @@ static const struct snd_soc_dapm_route geminilake_map[] = {
{ "Spk", NULL, "Speaker" },
/* other jacks */
- { "Headset Mic", NULL, "Platform Clock" },
{ "IN1P", NULL, "Headset Mic" },
/* digital mics */
@@ -164,7 +127,7 @@ static int geminilake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
/* set SSP to 24 bit */
snd_mask_none(fmt);
- snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
+ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
return 0;
}
@@ -177,6 +140,13 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_jack *jack;
int ret;
+ ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
+ GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+ return ret;
+ }
+
/* Configure sysclk for codec */
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
@@ -602,6 +572,10 @@ static struct snd_soc_card glk_audio_card_rt5682_m98357a = {
static int geminilake_audio_probe(struct platform_device *pdev)
{
struct glk_card_private *ctx;
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
+ struct snd_soc_card *card;
+ int ret;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -609,11 +583,19 @@ static int geminilake_audio_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
- glk_audio_card_rt5682_m98357a.dev = &pdev->dev;
- snd_soc_card_set_drvdata(&glk_audio_card_rt5682_m98357a, ctx);
+ card = &glk_audio_card_rt5682_m98357a;
+ card->dev = &pdev->dev;
+ snd_soc_card_set_drvdata(card, ctx);
+
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ platform_name = mach->mach_params.platform;
+
+ ret = snd_soc_fixup_dai_links_platform_name(card, platform_name);
+ if (ret)
+ return ret;
- return devm_snd_soc_register_card(&pdev->dev,
- &glk_audio_card_rt5682_m98357a);
+ return devm_snd_soc_register_card(&pdev->dev, card);
}
static const struct platform_device_id glk_board_ids[] = {
diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c
index eab1f439dd3f..971226d42042 100644
--- a/sound/soc/intel/boards/haswell.c
+++ b/sound/soc/intel/boards/haswell.c
@@ -19,6 +19,7 @@
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include <sound/pcm_params.h>
#include "../common/sst-dsp.h"
@@ -146,7 +147,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = {
.stream_name = "Loopback",
.cpu_dai_name = "Loopback Pin",
.platform_name = "haswell-pcm-audio",
- .dynamic = 0,
+ .dynamic = 1,
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
@@ -189,8 +190,22 @@ static struct snd_soc_card haswell_rt5640 = {
static int haswell_audio_probe(struct platform_device *pdev)
{
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name = NULL;
+ int ret;
+
haswell_rt5640.dev = &pdev->dev;
+ /* override plaform name, if required */
+ mach = (&pdev->dev)->platform_data;
+ if (mach) /* extra check since legacy does not pass parameters */
+ platform_name = mach->mach_params.platform;
+
+ ret = snd_soc_fixup_dai_links_platform_name(&haswell_rt5640,
+ platform_name);
+ if (ret)
+ return ret;
+
return devm_snd_soc_register_card(&pdev->dev, &haswell_rt5640);
}
diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c
index 723a4935ed76..2768a572d065 100644
--- a/sound/soc/intel/boards/kbl_da7219_max98927.c
+++ b/sound/soc/intel/boards/kbl_da7219_max98927.c
@@ -2,7 +2,7 @@
// Copyright(c) 2018 Intel Corporation.
/*
- * Intel Kabylake I2S Machine Driver with MAX98927 & DA7219 Codecs
+ * Intel Kabylake I2S Machine Driver with MAX98927, MAX98373 & DA7219 Codecs
*
* Modified from:
* Intel Kabylake I2S Machine driver supporting MAX98927 and
@@ -24,8 +24,14 @@
#define KBL_DIALOG_CODEC_DAI "da7219-hifi"
#define MAX98927_CODEC_DAI "max98927-aif1"
-#define MAXIM_DEV0_NAME "i2c-MX98927:00"
-#define MAXIM_DEV1_NAME "i2c-MX98927:01"
+#define MAX98927_DEV0_NAME "i2c-MX98927:00"
+#define MAX98927_DEV1_NAME "i2c-MX98927:01"
+
+#define MAX98373_CODEC_DAI "max98373-aif1"
+#define MAX98373_DEV0_NAME "i2c-MX98373:00"
+#define MAX98373_DEV1_NAME "i2c-MX98373:01"
+
+
#define DUAL_CHANNEL 2
#define QUAD_CHANNEL 4
#define NAME_SIZE 32
@@ -176,20 +182,38 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
for (j = 0; j < runtime->num_codecs; j++) {
struct snd_soc_dai *codec_dai = runtime->codec_dais[j];
- if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) {
+ if (!strcmp(codec_dai->component->name, MAX98927_DEV0_NAME)) {
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16);
if (ret < 0) {
dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret);
return ret;
}
}
- if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
+ if (!strcmp(codec_dai->component->name, MAX98927_DEV1_NAME)) {
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16);
if (ret < 0) {
dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret);
return ret;
}
}
+ if (!strcmp(codec_dai->component->name, MAX98373_DEV0_NAME)) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ 0x03, 3, 8, 24);
+ if (ret < 0) {
+ dev_err(runtime->dev,
+ "DEV0 TDM slot err:%d\n", ret);
+ return ret;
+ }
+ }
+ if (!strcmp(codec_dai->component->name, MAX98373_DEV1_NAME)) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ 0x0C, 3, 8, 24);
+ if (ret < 0) {
+ dev_err(runtime->dev,
+ "DEV0 TDM slot err:%d\n", ret);
+ return ret;
+ }
+ }
}
return 0;
@@ -213,6 +237,25 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link;
/*
+ * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE,
+ * where as kblda7219m98927 & kblmax98927 supports S16_LE by default.
+ * Skipping the port wise FE and BE configuration for kblda7219m98373 &
+ * kblmax98373 as the topology (FE & BE) supports S24_LE only.
+ */
+
+ if (!strcmp(rtd->card->name, "kblda7219m98373") ||
+ !strcmp(rtd->card->name, "kblmax98373")) {
+ /* The ADSP will convert the FE rate to 48k, stereo */
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = DUAL_CHANNEL;
+
+ /* set SSP to 24 bit */
+ snd_mask_none(fmt);
+ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
+ return 0;
+ }
+
+ /*
* The ADSP will convert the FE rate to 48k, stereo, 24 bit
*/
if (!strcmp(fe_dai_link->name, "Kbl Audio Port") ||
@@ -221,7 +264,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
snd_mask_none(fmt);
- snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
+ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
}
/*
@@ -229,7 +272,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
* thus changing the mask here
*/
if (!strcmp(be_dai_link->name, "SSP0-Codec"))
- snd_mask_set(fmt, SNDRV_PCM_FORMAT_S16_LE);
+ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
return 0;
}
@@ -352,20 +395,31 @@ static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
static int kbl_fe_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_rt = substream->private_data;
/*
* On this platform for PCM device we support,
* 48Khz
* stereo
- * 16 bit audio
*/
runtime->hw.channels_max = DUAL_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
-
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
- snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+ /*
+ * Setup S24_LE (32 bit container and 24 bit valid data) for
+ * kblda7219m98373 & kblmax98373. For kblda7219m98927 &
+ * kblmax98927 keeping it as 16/16 due to topology FW dependency.
+ */
+ if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
+ !strcmp(soc_rt->card->name, "kblmax98373")) {
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+
+ } else {
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+ }
snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
@@ -398,11 +452,23 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_rt = substream->private_data;
runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels_quad);
+ /*
+ * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE.
+ * The DMIC also configured for S24_LE. Forcing the DMIC format to
+ * S24_LE due to the topology FW dependency.
+ */
+ if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
+ !strcmp(soc_rt->card->name, "kblmax98373")) {
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+ }
+
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
}
@@ -448,29 +514,55 @@ static struct snd_soc_ops skylake_refcap_ops = {
static struct snd_soc_codec_conf max98927_codec_conf[] = {
{
- .dev_name = MAXIM_DEV0_NAME,
+ .dev_name = MAX98927_DEV0_NAME,
+ .name_prefix = "Right",
+ },
+
+ {
+ .dev_name = MAX98927_DEV1_NAME,
+ .name_prefix = "Left",
+ },
+};
+
+static struct snd_soc_codec_conf max98373_codec_conf[] = {
+
+ {
+ .dev_name = MAX98373_DEV0_NAME,
.name_prefix = "Right",
},
{
- .dev_name = MAXIM_DEV1_NAME,
+ .dev_name = MAX98373_DEV1_NAME,
.name_prefix = "Left",
},
};
-static struct snd_soc_dai_link_component ssp0_codec_components[] = {
+static struct snd_soc_dai_link_component max98927_ssp0_codec_components[] = {
{ /* Left */
- .name = MAXIM_DEV0_NAME,
+ .name = MAX98927_DEV0_NAME,
.dai_name = MAX98927_CODEC_DAI,
},
{ /* For Right */
- .name = MAXIM_DEV1_NAME,
+ .name = MAX98927_DEV1_NAME,
.dai_name = MAX98927_CODEC_DAI,
},
};
+static struct snd_soc_dai_link_component max98373_ssp0_codec_components[] = {
+ { /* Left */
+ .name = MAX98373_DEV0_NAME,
+ .dai_name = MAX98373_CODEC_DAI,
+ },
+
+ { /* For Right */
+ .name = MAX98373_DEV1_NAME,
+ .dai_name = MAX98373_CODEC_DAI,
+ },
+
+};
+
/* kabylake digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link kabylake_dais[] = {
/* Front End DAI links */
@@ -607,8 +699,8 @@ static struct snd_soc_dai_link kabylake_dais[] = {
.cpu_dai_name = "SSP0 Pin",
.platform_name = "0000:00:1f.3",
.no_pcm = 1,
- .codecs = ssp0_codec_components,
- .num_codecs = ARRAY_SIZE(ssp0_codec_components),
+ .codecs = max98927_ssp0_codec_components,
+ .num_codecs = ARRAY_SIZE(max98927_ssp0_codec_components),
.dai_fmt = SND_SOC_DAIFMT_DSP_B |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
@@ -683,7 +775,7 @@ static struct snd_soc_dai_link kabylake_dais[] = {
};
/* kabylake digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link kabylake_max98927_dais[] = {
+static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = {
/* Front End DAI links */
[KBL_DPCM_AUDIO_PB] = {
.name = "Kbl Audio Port",
@@ -802,8 +894,8 @@ static struct snd_soc_dai_link kabylake_max98927_dais[] = {
.cpu_dai_name = "SSP0 Pin",
.platform_name = "0000:00:1f.3",
.no_pcm = 1,
- .codecs = ssp0_codec_components,
- .num_codecs = ARRAY_SIZE(ssp0_codec_components),
+ .codecs = max98927_ssp0_codec_components,
+ .num_codecs = ARRAY_SIZE(max98927_ssp0_codec_components),
.dai_fmt = SND_SOC_DAIFMT_DSP_B |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
@@ -917,8 +1009,8 @@ static struct snd_soc_card kbl_audio_card_da7219_m98927 = {
static struct snd_soc_card kbl_audio_card_max98927 = {
.name = "kblmax98927",
.owner = THIS_MODULE,
- .dai_link = kabylake_max98927_dais,
- .num_links = ARRAY_SIZE(kabylake_max98927_dais),
+ .dai_link = kabylake_max98_927_373_dais,
+ .num_links = ARRAY_SIZE(kabylake_max98_927_373_dais),
.controls = kabylake_controls,
.num_controls = ARRAY_SIZE(kabylake_controls),
.dapm_widgets = kabylake_widgets,
@@ -931,9 +1023,46 @@ static struct snd_soc_card kbl_audio_card_max98927 = {
.late_probe = kabylake_card_late_probe,
};
+static struct snd_soc_card kbl_audio_card_da7219_m98373 = {
+ .name = "kblda7219m98373",
+ .owner = THIS_MODULE,
+ .dai_link = kabylake_dais,
+ .num_links = ARRAY_SIZE(kabylake_dais),
+ .controls = kabylake_controls,
+ .num_controls = ARRAY_SIZE(kabylake_controls),
+ .dapm_widgets = kabylake_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets),
+ .dapm_routes = kabylake_map,
+ .num_dapm_routes = ARRAY_SIZE(kabylake_map),
+ .codec_conf = max98373_codec_conf,
+ .num_configs = ARRAY_SIZE(max98373_codec_conf),
+ .fully_routed = true,
+ .late_probe = kabylake_card_late_probe,
+};
+
+static struct snd_soc_card kbl_audio_card_max98373 = {
+ .name = "kblmax98373",
+ .owner = THIS_MODULE,
+ .dai_link = kabylake_max98_927_373_dais,
+ .num_links = ARRAY_SIZE(kabylake_max98_927_373_dais),
+ .controls = kabylake_controls,
+ .num_controls = ARRAY_SIZE(kabylake_controls),
+ .dapm_widgets = kabylake_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets),
+ .dapm_routes = kabylake_map,
+ .num_dapm_routes = ARRAY_SIZE(kabylake_map),
+ .codec_conf = max98373_codec_conf,
+ .num_configs = ARRAY_SIZE(max98373_codec_conf),
+ .fully_routed = true,
+ .late_probe = kabylake_card_late_probe,
+};
+
static int kabylake_audio_probe(struct platform_device *pdev)
{
struct kbl_codec_private *ctx;
+ struct snd_soc_dai_link *kbl_dai_link;
+ struct snd_soc_dai_link_component **codecs;
+ int i = 0;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -944,6 +1073,22 @@ static int kabylake_audio_probe(struct platform_device *pdev)
kabylake_audio_card =
(struct snd_soc_card *)pdev->id_entry->driver_data;
+ kbl_dai_link = kabylake_audio_card->dai_link;
+
+ /* Update codecs for SSP0 with max98373 codec info */
+ if (!strcmp(pdev->name, "kbl_da7219_max98373") ||
+ (!strcmp(pdev->name, "kbl_max98373"))) {
+ for (i = 0; i < kabylake_audio_card->num_links; ++i) {
+ if (strcmp(kbl_dai_link[i].name, "SSP0-Codec"))
+ continue;
+
+ codecs = &(kbl_dai_link[i].codecs);
+ *codecs = max98373_ssp0_codec_components;
+ kbl_dai_link[i].num_codecs =
+ ARRAY_SIZE(max98373_ssp0_codec_components);
+ break;
+ }
+ }
kabylake_audio_card->dev = &pdev->dev;
snd_soc_card_set_drvdata(kabylake_audio_card, ctx);
@@ -961,13 +1106,23 @@ static const struct platform_device_id kbl_board_ids[] = {
.driver_data =
(kernel_ulong_t)&kbl_audio_card_max98927,
},
+ {
+ .name = "kbl_da7219_max98373",
+ .driver_data =
+ (kernel_ulong_t)&kbl_audio_card_da7219_m98373,
+ },
+ {
+ .name = "kbl_max98373",
+ .driver_data =
+ (kernel_ulong_t)&kbl_audio_card_max98373,
+ },
{ }
};
static struct platform_driver kabylake_audio = {
.probe = kabylake_audio_probe,
.driver = {
- .name = "kbl_da7219_max98927",
+ .name = "kbl_da7219_max98_927_373",
.pm = &snd_soc_pm_ops,
},
.id_table = kbl_board_ids,
@@ -976,8 +1131,10 @@ static struct platform_driver kabylake_audio = {
module_platform_driver(kabylake_audio)
/* Module information */
-MODULE_DESCRIPTION("Audio KabyLake Machine driver for MAX98927 & DA7219");
+MODULE_DESCRIPTION("Audio KabyLake Machine driver for MAX98927/MAX98373 & DA7219");
MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:kbl_da7219_max98927");
MODULE_ALIAS("platform:kbl_max98927");
+MODULE_ALIAS("platform:kbl_da7219_max98373");
+MODULE_ALIAS("platform:kbl_max98373");