aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/skylake/skl-pcm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 11:04:07 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 11:04:07 -0800
commit0280d1a099da1d211e76ec47cc0944c993a36316 (patch)
tree7a2961ded372ca6b6fa88d83a46a5bb5d40abbe4 /sound/soc/intel/skylake/skl-pcm.c
parentMerge tag 'backlight-for-linus-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight (diff)
parentALSA: hda - Add Intel Lewisburg device IDs Audio (diff)
downloadlinux-dev-0280d1a099da1d211e76ec47cc0944c993a36316.tar.xz
linux-dev-0280d1a099da1d211e76ec47cc0944c993a36316.zip
Merge tag 'sound-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "Here is the first batch of updates for sound system on 4.4-rc1. Again at this time, the update looks fairly calm; no big changes in either ALSA core or ASoC infrastructures, rather all small cleanups, in addition to the new stuff as usual. The biggest changes are about Firewire sound devices. It gained lots of new device support, and MIDI functionality. Also there are updates for a few still working-in-progress stuff (topology API and ASoC skylake), too. But overall, this update should give no big surprise. Some highlights are below: Core: - A few more Kconfig items for tinification; it's marked as EXPERT, so normal user should't be bothered :) - Refactoring with a new PCM hw_constraint helper - Removal of unused transfer_ack_{begin,end} PCM callbacks Firewire: - Restructuring of code subtree, lots of refactoring - Support AMDTP variants - New driver for Digidesign 002/003 family - Adds support for TASCAM FireOne to ALSA OXFW driver - Add MIDI support to TASCAM and Digi00x devices HD-Audio: - Automated modalias generation for codec drivers, finally - Improvement on heuristics for setting mixer name - A few fixes for longstanding bugs on Creative CA0132 cards - Addition of audio rate callback with i915 communication - Fix suspend issue on recent Dell XPS - Intel Lewisburg controller support ASoC: - Updates to the topology userspace interface - Big updates to the Renesas support (rcar) - More updates for supporting Intel Sky Lake systems - New drivers for Asahi Kasei Microdevices AK4613, Allwinnner A10, Cirrus Logic WM8998, Dialog DA7219, Nuvoton NAU8825, Rockchip S/PDIF, and Atmel class D amplifier USB-Audio: - A fix for newer Roland MIDI devices - Quirks and workarounds for Zoom R16/24 device Misc: - A few fixes for some old Cirrus CS46xx PCI sound boards - Yet another fixes for some old ESS Maestro3 PCI sound boards" * tag 'sound-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (330 commits) ALSA: hda - Add Intel Lewisburg device IDs Audio ALSA: hda - Apply pin fixup for HP ProBook 6550b ALSA: hda - Fix lost 4k BDL boundary workaround ALSA: maestro3: Fix Allegro mute until master volume/mute is touched ALSA: maestro3: Enable docking support for Dell Latitude C810 ALSA: firewire-digi00x: add another rawmidi character device for MIDI control ports ALSA: firewire-digi00x: add MIDI operations for MIDI control port ALSA: firewire-digi00x: rename identifiers of MIDI operation for physical ports ALSA: cs46xx: Fix suspend for all channels ALSA: cs46xx: Fix Duplicate front for CS4294 and CS4298 codecs ALSA: DocBook: Add soc-ops.c and soc-compress.c ALSA: hda - Add / fix kernel doc comments ALSA: Constify ratden/ratnum constraints ALSA: hda - Disable 64bit address for Creative HDA controllers ALSA: hda/realtek - Dell XPS one ALC3260 speaker no sound after resume back ALSA: hda/ca0132 - Convert leftover pr_info() and pr_err() ASoC: fsl: Use #ifdef instead of #if for CONFIG_PM_SLEEP ASoC: rt5645: Sort the order for register bit defines ASoC: dwc: add check for master/slave format ASoC: rt5645: Add the HWEQ for the speaker output ...
Diffstat (limited to 'sound/soc/intel/skylake/skl-pcm.c')
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c176
1 files changed, 114 insertions, 62 deletions
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index 7d617bf493bc..a2f94ce1679d 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -24,6 +24,7 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "skl.h"
+#include "skl-topology.h"
#define HDA_MONO 1
#define HDA_STEREO 2
@@ -115,7 +116,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
ret = pm_runtime_get_sync(dai->dev);
- if (ret)
+ if (ret < 0)
return ret;
stream = snd_hdac_ext_stream_assign(ebus, substream,
@@ -214,6 +215,8 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct skl_pipe_params p_params = {0};
+ struct skl_module_cfg *m_cfg;
int ret, dma_id;
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
@@ -228,6 +231,16 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
dma_id = hdac_stream(stream)->stream_tag - 1;
dev_dbg(dai->dev, "dma_id=%d\n", dma_id);
+ p_params.s_fmt = snd_pcm_format_width(params_format(params));
+ p_params.ch = params_channels(params);
+ p_params.s_freq = params_rate(params);
+ p_params.host_dma_id = dma_id;
+ p_params.stream = substream->stream;
+
+ m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
+ if (m_cfg)
+ skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params);
+
return 0;
}
@@ -268,6 +281,46 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
return skl_substream_free_pages(ebus_to_hbus(ebus), substream);
}
+static int skl_be_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct skl_pipe_params p_params = {0};
+
+ p_params.s_fmt = snd_pcm_format_width(params_format(params));
+ p_params.ch = params_channels(params);
+ p_params.s_freq = params_rate(params);
+ p_params.stream = substream->stream;
+ skl_tplg_be_update_params(dai, &p_params);
+
+ return 0;
+}
+
+static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct skl *skl = get_skl_ctx(dai->dev);
+ struct skl_sst *ctx = skl->skl_sst;
+ struct skl_module_cfg *mconfig;
+
+ mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
+ if (!mconfig)
+ return -EIO;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ return skl_run_pipe(ctx, mconfig->pipe);
+
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ return skl_stop_pipe(ctx, mconfig->pipe);
+
+ default:
+ return 0;
+ }
+}
+
static int skl_link_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -277,9 +330,8 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
struct skl_dma_params *dma_params;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- int dma_id;
+ struct skl_pipe_params p_params = {0};
- pr_debug("%s\n", __func__);
link_dev = snd_hdac_ext_stream_assign(ebus, substream,
HDAC_EXT_STREAM_TYPE_LINK);
if (!link_dev)
@@ -293,7 +345,14 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
if (dma_params)
dma_params->stream_tag = hdac_stream(link_dev)->stream_tag;
snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params);
- dma_id = hdac_stream(link_dev)->stream_tag - 1;
+
+ p_params.s_fmt = snd_pcm_format_width(params_format(params));
+ p_params.ch = params_channels(params);
+ p_params.s_freq = params_rate(params);
+ p_params.stream = substream->stream;
+ p_params.link_dma_id = hdac_stream(link_dev)->stream_tag - 1;
+
+ skl_tplg_be_update_params(dai, &p_params);
return 0;
}
@@ -308,27 +367,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
unsigned int format_val = 0;
struct skl_dma_params *dma_params;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_pcm_hw_params *params;
- struct snd_interval *channels, *rate;
struct hdac_ext_link *link;
- dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
if (link_dev->link_prepared) {
dev_dbg(dai->dev, "already stream is prepared - returning\n");
return 0;
}
- params = devm_kzalloc(dai->dev, sizeof(*params), GFP_KERNEL);
- if (params == NULL)
- return -ENOMEM;
-
- channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- channels->min = channels->max = substream->runtime->channels;
- rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- rate->min = rate->max = substream->runtime->rate;
- snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
- SNDRV_PCM_HW_PARAM_FIRST_MASK],
- substream->runtime->format);
-
dma_params = (struct skl_dma_params *)
snd_soc_dai_get_dma_data(codec_dai, substream);
@@ -399,13 +443,13 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-static int skl_hda_be_startup(struct snd_pcm_substream *substream,
+static int skl_be_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
return pm_runtime_get_sync(dai->dev);
}
-static void skl_hda_be_shutdown(struct snd_pcm_substream *substream,
+static void skl_be_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
pm_runtime_mark_last_busy(dai->dev);
@@ -418,20 +462,28 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = {
.prepare = skl_pcm_prepare,
.hw_params = skl_pcm_hw_params,
.hw_free = skl_pcm_hw_free,
+ .trigger = skl_pcm_trigger,
};
static struct snd_soc_dai_ops skl_dmic_dai_ops = {
- .startup = skl_hda_be_startup,
- .shutdown = skl_hda_be_shutdown,
+ .startup = skl_be_startup,
+ .hw_params = skl_be_hw_params,
+ .shutdown = skl_be_shutdown,
+};
+
+static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
+ .startup = skl_be_startup,
+ .hw_params = skl_be_hw_params,
+ .shutdown = skl_be_shutdown,
};
static struct snd_soc_dai_ops skl_link_dai_ops = {
- .startup = skl_hda_be_startup,
+ .startup = skl_be_startup,
.prepare = skl_link_pcm_prepare,
.hw_params = skl_link_hw_params,
.hw_free = skl_link_hw_free,
.trigger = skl_link_pcm_trigger,
- .shutdown = skl_hda_be_shutdown,
+ .shutdown = skl_be_shutdown,
};
static struct snd_soc_dai_driver skl_platform_dai[] = {
@@ -488,6 +540,24 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
},
/* BE CPU Dais */
{
+ .name = "SSP0 Pin",
+ .ops = &skl_be_ssp_dai_ops,
+ .playback = {
+ .stream_name = "ssp0 Tx",
+ .channels_min = HDA_STEREO,
+ .channels_max = HDA_STEREO,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "ssp0 Rx",
+ .channels_min = HDA_STEREO,
+ .channels_max = HDA_STEREO,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+},
+{
.name = "iDisp Pin",
.ops = &skl_link_dai_ops,
.playback = {
@@ -510,17 +580,6 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
},
},
{
- .name = "DMIC23 Pin",
- .ops = &skl_dmic_dai_ops,
- .capture = {
- .stream_name = "DMIC23 Rx",
- .channels_min = HDA_STEREO,
- .channels_max = HDA_STEREO,
- .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
- },
-},
-{
.name = "HD-Codec Pin",
.ops = &skl_link_dai_ops,
.playback = {
@@ -538,28 +597,6 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
},
-{
- .name = "HD-Codec-SPK Pin",
- .ops = &skl_link_dai_ops,
- .playback = {
- .stream_name = "HD-Codec-SPK Tx",
- .channels_min = HDA_STEREO,
- .channels_max = HDA_STEREO,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
-},
-{
- .name = "HD-Codec-AMIC Pin",
- .ops = &skl_link_dai_ops,
- .capture = {
- .stream_name = "HD-Codec-AMIC Rx",
- .channels_min = HDA_STEREO,
- .channels_max = HDA_STEREO,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
-},
};
static int skl_platform_open(struct snd_pcm_substream *substream)
@@ -577,7 +614,7 @@ static int skl_platform_open(struct snd_pcm_substream *substream)
return 0;
}
-static int skl_pcm_trigger(struct snd_pcm_substream *substream,
+static int skl_coupled_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct hdac_ext_bus *ebus = get_bus_ctx(substream);
@@ -651,7 +688,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream,
return 0;
}
-static int skl_dsp_trigger(struct snd_pcm_substream *substream,
+static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct hdac_ext_bus *ebus = get_bus_ctx(substream);
@@ -708,9 +745,9 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
struct hdac_ext_bus *ebus = get_bus_ctx(substream);
if (ebus->ppcap)
- return skl_dsp_trigger(substream, cmd);
+ return skl_decoupled_trigger(substream, cmd);
else
- return skl_pcm_trigger(substream, cmd);
+ return skl_coupled_trigger(substream, cmd);
}
/* calculate runtime delay from LPIB */
@@ -877,7 +914,17 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
return retval;
}
+static int skl_platform_soc_probe(struct snd_soc_platform *platform)
+{
+ struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev);
+
+ if (ebus->ppcap)
+ return skl_tplg_init(platform, ebus);
+
+ return 0;
+}
static struct snd_soc_platform_driver skl_platform_drv = {
+ .probe = skl_platform_soc_probe,
.ops = &skl_platform_ops,
.pcm_new = skl_pcm_new,
.pcm_free = skl_pcm_free,
@@ -890,6 +937,11 @@ static const struct snd_soc_component_driver skl_component = {
int skl_platform_register(struct device *dev)
{
int ret;
+ struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
+ struct skl *skl = ebus_to_skl(ebus);
+
+ INIT_LIST_HEAD(&skl->ppl_list);
+ INIT_LIST_HEAD(&skl->dapm_path_list);
ret = snd_soc_register_platform(dev, &skl_platform_drv);
if (ret) {