summaryrefslogtreecommitdiff
path: root/sound/soc/intel/boards/bdw-rt5677.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/boards/bdw-rt5677.c')
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c215
1 files changed, 152 insertions, 63 deletions
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c
index efcfd906c856..408d20ed8cee 100644
--- a/sound/soc/intel/boards/bdw-rt5677.c
+++ b/sound/soc/intel/boards/bdw-rt5677.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* ASoC machine driver for Intel Broadwell platforms with RT5677 codec
*
* Copyright (c) 2014, The Chromium OS Authors. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/acpi.h>
@@ -26,9 +15,7 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/jack.h>
-
-#include "../common/sst-dsp.h"
-#include "../haswell/sst-haswell-ipc.h"
+#include <sound/soc-acpi.h>
#include "../../codecs/rt5677.h"
@@ -40,8 +27,7 @@ struct bdw_rt5677_priv {
static int bdw_rt5677_event_hp(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_card *card = snd_soc_dapm_to_card(w->dapm);
struct bdw_rt5677_priv *bdw_rt5677 = snd_soc_card_get_drvdata(card);
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -84,6 +70,11 @@ static const struct snd_soc_dapm_route bdw_rt5677_map[] = {
/* CODEC BE connections */
{"SSP0 CODEC IN", NULL, "AIF1 Capture"},
{"AIF1 Playback", NULL, "SSP0 CODEC OUT"},
+ {"DSP Capture", NULL, "DSP Buffer"},
+
+ /* DSP Clock Connections */
+ { "DSP Buffer", NULL, "SSP0 CODEC IN" },
+ { "SSP0 CODEC IN", NULL, "DSPTX" },
};
static const struct snd_kcontrol_new bdw_rt5677_controls[] = {
@@ -145,13 +136,13 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_interval *rate = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_RATE);
- struct snd_interval *channels = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_CHANNELS);
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *chan = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
- /* The ADSP will covert the FE rate to 48k, stereo */
+ /* The ADSP will convert the FE rate to 48k, stereo */
rate->min = rate->max = 48000;
- channels->min = channels->max = 2;
+ chan->min = chan->max = 2;
/* set SSP0 to 16 bit */
params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
@@ -161,8 +152,8 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
int ret;
ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_MCLK, 24576000,
@@ -175,35 +166,68 @@ static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream,
return ret;
}
-static const struct snd_soc_ops bdw_rt5677_ops = {
- .hw_params = bdw_rt5677_hw_params,
-};
-
-static int bdw_rt5677_rtd_init(struct snd_soc_pcm_runtime *rtd)
+static int bdw_rt5677_dsp_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
- struct sst_pdata *pdata = dev_get_platdata(component->dev);
- struct sst_hsw *broadwell = pdata->dsp;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
int ret;
- /* Set ADSP SSP port settings */
- ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0,
- SST_HSW_DEVICE_MCLK_FREQ_24_MHZ,
- SST_HSW_DEVICE_CLOCK_MASTER, 9);
+ ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_PLL1, 24576000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set codec sysclk configuration\n");
+ return ret;
+ }
+ ret = snd_soc_dai_set_pll(codec_dai, 0, RT5677_PLL1_S_MCLK,
+ 24000000, 24576000);
if (ret < 0) {
- dev_err(rtd->dev, "error: failed to set device config\n");
+ dev_err(rtd->dev, "can't set codec pll configuration\n");
return ret;
}
return 0;
}
+static const struct snd_soc_ops bdw_rt5677_ops = {
+ .hw_params = bdw_rt5677_hw_params,
+};
+
+static const struct snd_soc_ops bdw_rt5677_dsp_ops = {
+ .hw_params = bdw_rt5677_dsp_hw_params,
+};
+
+static const unsigned int channels[] = {
+ 2,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+};
+
+static int bdw_rt5677_fe_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /* Board supports stereo configuration only */
+ runtime->hw.channels_max = 2;
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+}
+
+static const struct snd_soc_ops bdw_rt5677_fe_ops = {
+ .startup = bdw_rt5677_fe_startup,
+};
+
static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
{
struct bdw_rt5677_priv *bdw_rt5677 =
snd_soc_card_get_drvdata(rtd->card);
- struct snd_soc_component *component = rtd->codec_dai->component;
- struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
int ret;
ret = devm_acpi_dev_add_driver_gpios(component->dev, bdw_rt5677_gpios);
@@ -216,17 +240,22 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
rt5677_sel_asrc_clk_src(component, RT5677_DA_STEREO_FILTER |
RT5677_AD_STEREO1_FILTER | RT5677_I2S1_SOURCE,
RT5677_CLK_SEL_I2S1_ASRC);
+ /* Enable codec ASRC function for Mono ADC L.
+ * The ASRC clock source is clk_sys2_asrc.
+ */
+ rt5677_sel_asrc_clk_src(component, RT5677_AD_MONO_L_FILTER,
+ RT5677_CLK_SEL_SYS2);
/* Request rt5677 GPIO for headphone amp control */
- bdw_rt5677->gpio_hp_en = devm_gpiod_get(component->dev, "headphone-enable",
- GPIOD_OUT_LOW);
+ bdw_rt5677->gpio_hp_en = gpiod_get(component->dev, "headphone-enable",
+ GPIOD_OUT_LOW);
if (IS_ERR(bdw_rt5677->gpio_hp_en)) {
dev_err(component->dev, "Can't find HP_AMP_SHDN_L gpio\n");
return PTR_ERR(bdw_rt5677->gpio_hp_en);
}
/* Create and initialize headphone jack */
- if (!snd_soc_card_jack_new(rtd->card, "Headphone Jack",
+ if (!snd_soc_card_jack_new_pins(rtd->card, "Headphone Jack",
SND_JACK_HEADPHONE, &headphone_jack,
&headphone_jack_pin, 1)) {
headphone_jack_gpio.gpiod_dev = component->dev;
@@ -238,7 +267,7 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
}
/* Create and initialize mic jack */
- if (!snd_soc_card_jack_new(rtd->card, "Mic Jack",
+ if (!snd_soc_card_jack_new_pins(rtd->card, "Mic Jack",
SND_JACK_MICROPHONE, &mic_jack,
&mic_jack_pin, 1)) {
mic_jack_gpio.gpiod_dev = component->dev;
@@ -253,24 +282,63 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
+static void bdw_rt5677_exit(struct snd_soc_pcm_runtime *rtd)
+{
+ struct bdw_rt5677_priv *bdw_rt5677 =
+ snd_soc_card_get_drvdata(rtd->card);
+
+ /*
+ * The .exit() can be reached without going through the .init()
+ * so explicitly test if the gpiod is valid
+ */
+ if (!IS_ERR_OR_NULL(bdw_rt5677->gpio_hp_en))
+ gpiod_put(bdw_rt5677->gpio_hp_en);
+}
+
/* broadwell digital audio interface glue - connects codec <--> CPU */
+SND_SOC_DAILINK_DEF(dummy,
+ DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
+SND_SOC_DAILINK_DEF(fe,
+ DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
+
+SND_SOC_DAILINK_DEF(platform,
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("haswell-pcm-audio")));
+
+SND_SOC_DAILINK_DEF(be,
+ DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RT5677CE:00", "rt5677-aif1")));
+
+SND_SOC_DAILINK_DEF(ssp0_port,
+ DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port")));
+
+/* Wake on voice interface */
+SND_SOC_DAILINK_DEFS(dsp,
+ DAILINK_COMP_ARRAY(COMP_CPU("spi-RT5677AA:00")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RT5677CE:00", "rt5677-dspbuffer")),
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("spi-RT5677AA:00")));
+
static struct snd_soc_dai_link bdw_rt5677_dais[] = {
/* Front End DAI links */
{
.name = "System PCM",
.stream_name = "System Playback/Capture",
- .cpu_dai_name = "System Pin",
- .platform_name = "haswell-pcm-audio",
+ .nonatomic = 1,
.dynamic = 1,
- .codec_name = "snd-soc-dummy",
- .codec_dai_name = "snd-soc-dummy-dai",
- .init = bdw_rt5677_rtd_init,
.trigger = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
- .dpcm_capture = 1,
- .dpcm_playback = 1,
+ .ops = &bdw_rt5677_fe_ops,
+ SND_SOC_DAILINK_REG(fe, dummy, platform),
+ },
+
+ /* Non-DPCM links */
+ {
+ .name = "Codec DSP",
+ .stream_name = "Wake on Voice",
+ .capture_only = 1,
+ .ops = &bdw_rt5677_dsp_ops,
+ SND_SOC_DAILINK_REG(dsp),
},
/* Back End DAI links */
@@ -278,20 +346,16 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
/* SSP0 - Codec */
.name = "Codec",
.id = 0,
- .cpu_dai_name = "snd-soc-dummy-dai",
- .platform_name = "snd-soc-dummy",
+ .nonatomic = 1,
.no_pcm = 1,
- .codec_name = "i2c-RT5677CE:00",
- .codec_dai_name = "rt5677-aif1",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
- .ignore_suspend = 1,
+ SND_SOC_DAIFMT_CBC_CFC,
.ignore_pmdown_time = 1,
.be_hw_params_fixup = broadwell_ssp0_fixup,
.ops = &bdw_rt5677_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.init = bdw_rt5677_init,
+ .exit = bdw_rt5677_exit,
+ SND_SOC_DAILINK_REG(ssp0_port, be, platform),
},
};
@@ -301,7 +365,7 @@ static int bdw_rt5677_suspend_pre(struct snd_soc_card *card)
struct snd_soc_dapm_context *dapm;
if (bdw_rt5677->component) {
- dapm = snd_soc_component_get_dapm(bdw_rt5677->component);
+ dapm = snd_soc_component_to_dapm(bdw_rt5677->component);
snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
}
return 0;
@@ -313,15 +377,23 @@ static int bdw_rt5677_resume_post(struct snd_soc_card *card)
struct snd_soc_dapm_context *dapm;
if (bdw_rt5677->component) {
- dapm = snd_soc_component_get_dapm(bdw_rt5677->component);
+ dapm = snd_soc_component_to_dapm(bdw_rt5677->component);
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
}
return 0;
}
+/* use space before codec name to simplify card ID, and simplify driver name */
+#define SOF_CARD_NAME "bdw rt5677" /* card name will be 'sof-bdw rt5677' */
+#define SOF_DRIVER_NAME "SOF"
+
+#define CARD_NAME "bdw-rt5677"
+#define DRIVER_NAME NULL /* card name will be used for driver name */
+
/* ASoC machine driver for Broadwell DSP + RT5677 */
static struct snd_soc_card bdw_rt5677_card = {
- .name = "bdw-rt5677",
+ .name = CARD_NAME,
+ .driver_name = DRIVER_NAME,
.owner = THIS_MODULE,
.dai_link = bdw_rt5677_dais,
.num_links = ARRAY_SIZE(bdw_rt5677_dais),
@@ -339,15 +411,31 @@ 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;
+ int ret;
bdw_rt5677_card.dev = &pdev->dev;
/* Allocate driver private struct */
bdw_rt5677 = devm_kzalloc(&pdev->dev, sizeof(struct bdw_rt5677_priv),
GFP_KERNEL);
- if (!bdw_rt5677) {
- dev_err(&pdev->dev, "Can't allocate bdw_rt5677\n");
+ if (!bdw_rt5677)
return -ENOMEM;
+
+ /* override platform name, if required */
+ mach = pdev->dev.platform_data;
+ ret = snd_soc_fixup_dai_links_platform_name(&bdw_rt5677_card,
+ mach->mach_params.platform);
+ if (ret)
+ return ret;
+
+ /* set card and driver name */
+ if (snd_soc_acpi_sof_parent(&pdev->dev)) {
+ bdw_rt5677_card.name = SOF_CARD_NAME;
+ bdw_rt5677_card.driver_name = SOF_DRIVER_NAME;
+ } else {
+ bdw_rt5677_card.name = CARD_NAME;
+ bdw_rt5677_card.driver_name = DRIVER_NAME;
}
snd_soc_card_set_drvdata(&bdw_rt5677_card, bdw_rt5677);
@@ -359,6 +447,7 @@ static struct platform_driver bdw_rt5677_audio = {
.probe = bdw_rt5677_probe,
.driver = {
.name = "bdw-rt5677",
+ .pm = &snd_soc_pm_ops
},
};