summaryrefslogtreecommitdiff
path: root/sound/soc/intel/skylake/skl-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/skylake/skl-pcm.c')
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c131
1 files changed, 116 insertions, 15 deletions
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index 0ebea34a4988..1dd97479e0c0 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -33,7 +33,7 @@
#define HDA_STEREO 2
#define HDA_QUAD 4
-static struct snd_pcm_hardware azx_pcm_hw = {
+static const struct snd_pcm_hardware azx_pcm_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -355,7 +355,8 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
}
mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
- skl_tplg_d0i3_put(skl, mconfig->d0i3_caps);
+ if (mconfig)
+ skl_tplg_d0i3_put(skl, mconfig->d0i3_caps);
kfree(dma_params);
}
@@ -628,7 +629,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops skl_pcm_dai_ops = {
+static const struct snd_soc_dai_ops skl_pcm_dai_ops = {
.startup = skl_pcm_open,
.shutdown = skl_pcm_close,
.prepare = skl_pcm_prepare,
@@ -637,22 +638,22 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = {
.trigger = skl_pcm_trigger,
};
-static struct snd_soc_dai_ops skl_dmic_dai_ops = {
+static const struct snd_soc_dai_ops skl_dmic_dai_ops = {
.hw_params = skl_be_hw_params,
};
-static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
+static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
.hw_params = skl_be_hw_params,
};
-static struct snd_soc_dai_ops skl_link_dai_ops = {
+static const struct snd_soc_dai_ops skl_link_dai_ops = {
.prepare = skl_link_pcm_prepare,
.hw_params = skl_link_hw_params,
.hw_free = skl_link_hw_free,
.trigger = skl_link_pcm_trigger,
};
-static struct snd_soc_dai_driver skl_platform_dai[] = {
+static struct snd_soc_dai_driver skl_fe_dai[] = {
{
.name = "System Pin",
.ops = &skl_pcm_dai_ops,
@@ -675,6 +676,32 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
},
},
{
+ .name = "System Pin2",
+ .ops = &skl_pcm_dai_ops,
+ .playback = {
+ .stream_name = "Headset Playback",
+ .channels_min = HDA_MONO,
+ .channels_max = HDA_STEREO,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ },
+},
+{
+ .name = "Echoref Pin",
+ .ops = &skl_pcm_dai_ops,
+ .capture = {
+ .stream_name = "Echoreference Capture",
+ .channels_min = HDA_STEREO,
+ .channels_max = HDA_STEREO,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ },
+},
+{
.name = "Reference Pin",
.ops = &skl_pcm_dai_ops,
.capture = {
@@ -770,8 +797,10 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
.sig_bits = 32,
},
},
+};
/* BE CPU Dais */
+static struct snd_soc_dai_driver skl_platform_dai[] = {
{
.name = "SSP0 Pin",
.ops = &skl_be_ssp_dai_ops,
@@ -949,6 +978,14 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
},
};
+int skl_dai_load(struct snd_soc_component *cmp,
+ struct snd_soc_dai_driver *pcm_dai)
+{
+ pcm_dai->ops = &skl_pcm_dai_ops;
+
+ return 0;
+}
+
static int skl_platform_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -1194,8 +1231,11 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
{
struct skl_sst *ctx = skl->skl_sst;
+ struct skl_module_inst_id *pin_id;
+ uuid_le *uuid_mod, *uuid_tplg;
+ struct skl_module *skl_module;
struct uuid_module *module;
- uuid_le *uuid_mod;
+ int i, ret = -EIO;
uuid_mod = (uuid_le *)mconfig->guid;
@@ -1207,12 +1247,45 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
list_for_each_entry(module, &ctx->uuid_list, list) {
if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
mconfig->id.module_id = module->id;
- mconfig->is_loadable = module->is_loadable;
- return 0;
+ if (mconfig->module)
+ mconfig->module->loadable = module->is_loadable;
+ ret = 0;
+ break;
+ }
+ }
+
+ if (ret)
+ return ret;
+
+ uuid_mod = &module->uuid;
+ ret = -EIO;
+ for (i = 0; i < skl->nr_modules; i++) {
+ skl_module = skl->modules[i];
+ uuid_tplg = &skl_module->uuid;
+ if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) {
+ mconfig->module = skl_module;
+ ret = 0;
+ break;
+ }
+ }
+ if (skl->nr_modules && ret)
+ return ret;
+
+ list_for_each_entry(module, &ctx->uuid_list, list) {
+ for (i = 0; i < MAX_IN_QUEUE; i++) {
+ pin_id = &mconfig->m_in_pin[i].id;
+ if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
+ pin_id->module_id = module->id;
+ }
+
+ for (i = 0; i < MAX_OUT_QUEUE; i++) {
+ pin_id = &mconfig->m_out_pin[i].id;
+ if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
+ pin_id->module_id = module->id;
}
}
- return -EIO;
+ return 0;
}
static int skl_populate_modules(struct skl *skl)
@@ -1284,7 +1357,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
return 0;
}
-static struct snd_soc_platform_driver skl_platform_drv = {
+static const struct snd_soc_platform_driver skl_platform_drv = {
.probe = skl_platform_soc_probe,
.ops = &skl_platform_ops,
.pcm_new = skl_pcm_new,
@@ -1300,6 +1373,8 @@ 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);
+ struct snd_soc_dai_driver *dais;
+ int num_dais = ARRAY_SIZE(skl_platform_dai);
INIT_LIST_HEAD(&skl->ppl_list);
INIT_LIST_HEAD(&skl->bind_list);
@@ -1309,14 +1384,38 @@ int skl_platform_register(struct device *dev)
dev_err(dev, "soc platform registration failed %d\n", ret);
return ret;
}
+
+ skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai),
+ GFP_KERNEL);
+ if (!skl->dais) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ if (!skl->use_tplg_pcm) {
+ dais = krealloc(skl->dais, sizeof(skl_fe_dai) +
+ sizeof(skl_platform_dai), GFP_KERNEL);
+ if (!dais) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ skl->dais = dais;
+ memcpy(&skl->dais[ARRAY_SIZE(skl_platform_dai)], skl_fe_dai,
+ sizeof(skl_fe_dai));
+ num_dais += ARRAY_SIZE(skl_fe_dai);
+ }
+
ret = snd_soc_register_component(dev, &skl_component,
- skl_platform_dai,
- ARRAY_SIZE(skl_platform_dai));
+ skl->dais, num_dais);
if (ret) {
dev_err(dev, "soc component registration failed %d\n", ret);
- snd_soc_unregister_platform(dev);
+ goto err;
}
+ return 0;
+err:
+ snd_soc_unregister_platform(dev);
return ret;
}
@@ -1336,5 +1435,7 @@ int skl_platform_unregister(struct device *dev)
snd_soc_unregister_component(dev);
snd_soc_unregister_platform(dev);
+ kfree(skl->dais);
+
return 0;
}