Merge remote-tracking branches 'asoc/topic/imx' and 'asoc/topic/intel' into asoc-next
This commit is contained in:
commit
8707344edd
|
@ -89,6 +89,7 @@ MODULE_DEVICE_TABLE(of, imx_spdif_dt_ids);
|
|||
static struct platform_driver imx_spdif_driver = {
|
||||
.driver = {
|
||||
.name = "imx-spdif",
|
||||
.pm = &snd_soc_pm_ops,
|
||||
.of_match_table = imx_spdif_dt_ids,
|
||||
},
|
||||
.probe = imx_spdif_audio_probe,
|
||||
|
|
|
@ -139,4 +139,18 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH
|
|||
config SND_SOC_INTEL_SKYLAKE
|
||||
tristate
|
||||
select SND_HDA_EXT_CORE
|
||||
select SND_SOC_TOPOLOGY
|
||||
select SND_SOC_INTEL_SST
|
||||
|
||||
config SND_SOC_INTEL_SKL_RT286_MACH
|
||||
tristate "ASoC Audio driver for SKL with RT286 I2S mode"
|
||||
depends on X86 && ACPI
|
||||
select SND_SOC_INTEL_SST
|
||||
select SND_SOC_INTEL_SKYLAKE
|
||||
select SND_SOC_RT286
|
||||
select SND_SOC_DMIC
|
||||
help
|
||||
This adds support for ASoC machine driver for Skylake platforms
|
||||
with RT286 I2S audio codec.
|
||||
Say Y if you have such a device
|
||||
If unsure select "N".
|
||||
|
|
|
@ -6,6 +6,7 @@ snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
|
|||
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
|
||||
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
|
||||
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
|
||||
snd-soc-skl_rt286-objs := skl_rt286.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
|
||||
|
@ -15,3 +16,4 @@ obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
|
|||
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Intel Skylake I2S Machine Driver
|
||||
*
|
||||
* Copyright (C) 2014-2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Modified from:
|
||||
* Intel Broadwell Wildcatpoint SST Audio
|
||||
*
|
||||
* Copyright (C) 2013, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include "../../codecs/rt286.h"
|
||||
|
||||
static struct snd_soc_jack skylake_headset;
|
||||
/* Headset jack detection DAPM pins */
|
||||
static struct snd_soc_jack_pin skylake_headset_pins[] = {
|
||||
{
|
||||
.pin = "Mic Jack",
|
||||
.mask = SND_JACK_MICROPHONE,
|
||||
},
|
||||
{
|
||||
.pin = "Headphone Jack",
|
||||
.mask = SND_JACK_HEADPHONE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new skylake_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Speaker"),
|
||||
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
|
||||
SOC_DAPM_PIN_SWITCH("Mic Jack"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget skylake_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_SPK("Speaker", NULL),
|
||||
SND_SOC_DAPM_MIC("Mic Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("DMIC2", NULL),
|
||||
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route skylake_rt286_map[] = {
|
||||
/* speaker */
|
||||
{"Speaker", NULL, "SPOR"},
|
||||
{"Speaker", NULL, "SPOL"},
|
||||
|
||||
/* HP jack connectors - unknown if we have jack deteck */
|
||||
{"Headphone Jack", NULL, "HPO Pin"},
|
||||
|
||||
/* other jacks */
|
||||
{"MIC1", NULL, "Mic Jack"},
|
||||
|
||||
/* digital mics */
|
||||
{"DMIC1 Pin", NULL, "DMIC2"},
|
||||
{"DMIC AIF", NULL, "SoC DMIC"},
|
||||
|
||||
/* CODEC BE connections */
|
||||
{ "AIF1 Playback", NULL, "ssp0 Tx"},
|
||||
{ "ssp0 Tx", NULL, "codec0_out"},
|
||||
{ "ssp0 Tx", NULL, "codec1_out"},
|
||||
|
||||
{ "codec0_in", NULL, "ssp0 Rx" },
|
||||
{ "codec1_in", NULL, "ssp0 Rx" },
|
||||
{ "ssp0 Rx", NULL, "AIF1 Capture" },
|
||||
|
||||
{ "dmic01_hifi", NULL, "DMIC01 Rx" },
|
||||
{ "DMIC01 Rx", NULL, "Capture" },
|
||||
|
||||
{ "hif1", NULL, "iDisp Tx"},
|
||||
{ "iDisp Tx", NULL, "iDisp_out"},
|
||||
|
||||
};
|
||||
|
||||
static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_card_jack_new(rtd->card, "Headset",
|
||||
SND_JACK_HEADSET | SND_JACK_BTN_0,
|
||||
&skylake_headset,
|
||||
skylake_headset_pins, ARRAY_SIZE(skylake_headset_pins));
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rt286_mic_detect(codec, &skylake_headset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int skylake_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);
|
||||
|
||||
/* The output is 48KHz, stereo, 16bits */
|
||||
rate->min = rate->max = 48000;
|
||||
channels->min = channels->max = 2;
|
||||
params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skylake_rt286_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;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000,
|
||||
SND_SOC_CLOCK_IN);
|
||||
if (ret < 0)
|
||||
dev_err(rtd->dev, "set codec sysclk failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_soc_ops skylake_rt286_ops = {
|
||||
.hw_params = skylake_rt286_hw_params,
|
||||
};
|
||||
|
||||
/* skylake digital audio interface glue - connects codec <--> CPU */
|
||||
static struct snd_soc_dai_link skylake_rt286_dais[] = {
|
||||
/* Front End DAI links */
|
||||
{
|
||||
.name = "Skl Audio Port",
|
||||
.stream_name = "Audio",
|
||||
.cpu_dai_name = "System Pin",
|
||||
.platform_name = "0000:00:1f.3",
|
||||
.nonatomic = 1,
|
||||
.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
|
||||
},
|
||||
.dpcm_playback = 1,
|
||||
},
|
||||
{
|
||||
.name = "Skl Audio Capture Port",
|
||||
.stream_name = "Audio Record",
|
||||
.cpu_dai_name = "System Pin",
|
||||
.platform_name = "0000:00:1f.3",
|
||||
.nonatomic = 1,
|
||||
.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
|
||||
},
|
||||
.dpcm_capture = 1,
|
||||
},
|
||||
{
|
||||
.name = "Skl Audio Reference cap",
|
||||
.stream_name = "refcap",
|
||||
.cpu_dai_name = "Reference Pin",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.platform_name = "0000:00:1f.3",
|
||||
.init = NULL,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = 1,
|
||||
.dynamic = 1,
|
||||
},
|
||||
|
||||
/* Back End DAI links */
|
||||
{
|
||||
/* SSP0 - Codec */
|
||||
.name = "SSP0-Codec",
|
||||
.be_id = 0,
|
||||
.cpu_dai_name = "SSP0 Pin",
|
||||
.platform_name = "0000:00:1f.3",
|
||||
.no_pcm = 1,
|
||||
.codec_name = "i2c-INT343A:00",
|
||||
.codec_dai_name = "rt286-aif1",
|
||||
.init = skylake_rt286_codec_init,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS,
|
||||
.ignore_suspend = 1,
|
||||
.ignore_pmdown_time = 1,
|
||||
.be_hw_params_fixup = skylake_ssp0_fixup,
|
||||
.ops = &skylake_rt286_ops,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
},
|
||||
{
|
||||
.name = "dmic01",
|
||||
.be_id = 1,
|
||||
.cpu_dai_name = "DMIC01 Pin",
|
||||
.codec_name = "dmic-codec",
|
||||
.codec_dai_name = "dmic-hifi",
|
||||
.platform_name = "0000:00:1f.3",
|
||||
.ignore_suspend = 1,
|
||||
.dpcm_capture = 1,
|
||||
.no_pcm = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/* skylake audio machine driver for SPT + RT286S */
|
||||
static struct snd_soc_card skylake_rt286 = {
|
||||
.name = "skylake-rt286",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = skylake_rt286_dais,
|
||||
.num_links = ARRAY_SIZE(skylake_rt286_dais),
|
||||
.controls = skylake_controls,
|
||||
.num_controls = ARRAY_SIZE(skylake_controls),
|
||||
.dapm_widgets = skylake_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(skylake_widgets),
|
||||
.dapm_routes = skylake_rt286_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(skylake_rt286_map),
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static int skylake_audio_probe(struct platform_device *pdev)
|
||||
{
|
||||
skylake_rt286.dev = &pdev->dev;
|
||||
|
||||
return devm_snd_soc_register_card(&pdev->dev, &skylake_rt286);
|
||||
}
|
||||
|
||||
static struct platform_driver skylake_audio = {
|
||||
.probe = skylake_audio_probe,
|
||||
.driver = {
|
||||
.name = "skl_alc286s_i2s",
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(skylake_audio)
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Omair Mohammed Abdullah <omair.m.abdullah@intel.com>");
|
||||
MODULE_DESCRIPTION("Intel SST Audio for Skylake");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:skl_alc286s_i2s");
|
|
@ -1,7 +1,11 @@
|
|||
snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o
|
||||
snd-soc-sst-dsp-objs := sst-dsp.o
|
||||
snd-soc-sst-acpi-objs := sst-acpi.o
|
||||
snd-soc-sst-ipc-objs := sst-ipc.o
|
||||
|
||||
ifneq ($(CONFIG_DW_DMAC_CORE),)
|
||||
snd-soc-sst-dsp-objs += sst-firmware.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o
|
||||
|
||||
|
|
|
@ -314,6 +314,7 @@ struct sst_dsp {
|
|||
int sst_state;
|
||||
struct skl_cl_dev cl_dev;
|
||||
u32 intr_status;
|
||||
const struct firmware *fw;
|
||||
};
|
||||
|
||||
/* Size optimised DRAM/IRAM memcpy */
|
||||
|
|
|
@ -420,6 +420,7 @@ void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sst_dsp_inbox_read);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
|
||||
struct sst_dsp *sst_dsp_new(struct device *dev,
|
||||
struct sst_dsp_device *sst_dev, struct sst_pdata *pdata)
|
||||
{
|
||||
|
@ -484,6 +485,7 @@ void sst_dsp_free(struct sst_dsp *sst)
|
|||
sst_dma_free(sst->dma);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sst_dsp_free);
|
||||
#endif
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Liam Girdwood");
|
||||
|
|
|
@ -216,10 +216,12 @@ struct sst_pdata {
|
|||
void *dsp;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
|
||||
/* Initialization */
|
||||
struct sst_dsp *sst_dsp_new(struct device *dev,
|
||||
struct sst_dsp_device *sst_dev, struct sst_pdata *pdata);
|
||||
void sst_dsp_free(struct sst_dsp *sst);
|
||||
#endif
|
||||
|
||||
/* SHIM Read / Write */
|
||||
void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <linux/acpi.h>
|
||||
|
||||
/* supported DMA engine drivers */
|
||||
#include <linux/platform_data/dma-dw.h>
|
||||
#include <linux/dma/dw.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
|
@ -169,12 +168,6 @@ static int block_list_prepare(struct sst_dsp *dsp,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct dw_dma_platform_data dw_pdata = {
|
||||
.is_private = 1,
|
||||
.chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
|
||||
.chan_priority = CHAN_PRIORITY_ASCENDING,
|
||||
};
|
||||
|
||||
static struct dw_dma_chip *dw_probe(struct device *dev, struct resource *mem,
|
||||
int irq)
|
||||
{
|
||||
|
@ -195,7 +188,8 @@ static struct dw_dma_chip *dw_probe(struct device *dev, struct resource *mem,
|
|||
return ERR_PTR(err);
|
||||
|
||||
chip->dev = dev;
|
||||
err = dw_dma_probe(chip, &dw_pdata);
|
||||
|
||||
err = dw_dma_probe(chip, NULL);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o
|
||||
snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \
|
||||
skl-topology.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
|
||||
|
||||
|
|
|
@ -54,6 +54,24 @@ static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define NOTIFICATION_PARAM_ID 3
|
||||
#define NOTIFICATION_MASK 0xf
|
||||
|
||||
/* disable notfication for underruns/overruns from firmware module */
|
||||
static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable)
|
||||
{
|
||||
struct notification_mask mask;
|
||||
struct skl_ipc_large_config_msg msg = {0};
|
||||
|
||||
mask.notify = NOTIFICATION_MASK;
|
||||
mask.enable = enable;
|
||||
|
||||
msg.large_param_id = NOTIFICATION_PARAM_ID;
|
||||
msg.param_data_size = sizeof(mask);
|
||||
|
||||
skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask);
|
||||
}
|
||||
|
||||
int skl_init_dsp(struct skl *skl)
|
||||
{
|
||||
void __iomem *mmio_base;
|
||||
|
@ -79,7 +97,10 @@ int skl_init_dsp(struct skl *skl)
|
|||
|
||||
ret = skl_sst_dsp_init(bus->dev, mmio_base, irq,
|
||||
loader_ops, &skl->skl_sst);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
skl_dsp_enable_notification(skl->skl_sst, false);
|
||||
dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
|
||||
|
||||
return ret;
|
||||
|
@ -122,6 +143,7 @@ int skl_suspend_dsp(struct skl *skl)
|
|||
int skl_resume_dsp(struct skl *skl)
|
||||
{
|
||||
struct skl_sst *ctx = skl->skl_sst;
|
||||
int ret;
|
||||
|
||||
/* if ppcap is not supported return 0 */
|
||||
if (!skl->ebus.ppcap)
|
||||
|
@ -131,7 +153,12 @@ int skl_resume_dsp(struct skl *skl)
|
|||
snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true);
|
||||
snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true);
|
||||
|
||||
return skl_dsp_wake(ctx->dsp);
|
||||
ret = skl_dsp_wake(ctx->dsp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
skl_dsp_enable_notification(skl->skl_sst, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum skl_bitdepth skl_get_bit_depth(int params)
|
||||
|
@ -294,6 +321,7 @@ static void skl_copy_copier_caps(struct skl_module_cfg *mconfig,
|
|||
(mconfig->formats_config.caps_size) / 4;
|
||||
}
|
||||
|
||||
#define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF
|
||||
/*
|
||||
* Calculate the gatewat settings required for copier module, type of
|
||||
* gateway and index of gateway to use
|
||||
|
@ -303,6 +331,7 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
|
|||
struct skl_cpr_cfg *cpr_mconfig)
|
||||
{
|
||||
union skl_connector_node_id node_id = {0};
|
||||
union skl_ssp_dma_node ssp_node = {0};
|
||||
struct skl_pipe_params *params = mconfig->pipe->p_params;
|
||||
|
||||
switch (mconfig->dev_type) {
|
||||
|
@ -320,9 +349,9 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
|
|||
(SKL_CONN_SOURCE == mconfig->hw_conn_type) ?
|
||||
SKL_DMA_I2S_LINK_OUTPUT_CLASS :
|
||||
SKL_DMA_I2S_LINK_INPUT_CLASS;
|
||||
node_id.node.vindex = params->host_dma_id +
|
||||
(mconfig->time_slot << 1) +
|
||||
(mconfig->vbus_id << 3);
|
||||
ssp_node.dma_node.time_slot_index = mconfig->time_slot;
|
||||
ssp_node.dma_node.i2s_instance = mconfig->vbus_id;
|
||||
node_id.node.vindex = ssp_node.val;
|
||||
break;
|
||||
|
||||
case SKL_DEVICE_DMIC:
|
||||
|
@ -339,13 +368,18 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
|
|||
node_id.node.vindex = params->link_dma_id;
|
||||
break;
|
||||
|
||||
default:
|
||||
case SKL_DEVICE_HDAHOST:
|
||||
node_id.node.dma_type =
|
||||
(SKL_CONN_SOURCE == mconfig->hw_conn_type) ?
|
||||
SKL_DMA_HDA_HOST_OUTPUT_CLASS :
|
||||
SKL_DMA_HDA_HOST_INPUT_CLASS;
|
||||
node_id.node.vindex = params->host_dma_id;
|
||||
break;
|
||||
|
||||
default:
|
||||
cpr_mconfig->gtw_cfg.node_id = SKL_NON_GATEWAY_CPR_NODE_ID;
|
||||
cpr_mconfig->cpr_feature_mask = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
cpr_mconfig->gtw_cfg.node_id = node_id.val;
|
||||
|
|
|
@ -25,7 +25,7 @@ static u8 OSC_UUID[16] = {0x6E, 0x88, 0x9F, 0xA6, 0xEB, 0x6C, 0x94, 0x45,
|
|||
|
||||
#define DSDT_NHLT_PATH "\\_SB.PCI0.HDAS"
|
||||
|
||||
void __iomem *skl_nhlt_init(struct device *dev)
|
||||
void *skl_nhlt_init(struct device *dev)
|
||||
{
|
||||
acpi_handle handle;
|
||||
union acpi_object *obj;
|
||||
|
@ -40,17 +40,17 @@ void __iomem *skl_nhlt_init(struct device *dev)
|
|||
if (obj && obj->type == ACPI_TYPE_BUFFER) {
|
||||
nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer;
|
||||
|
||||
return ioremap_cache(nhlt_ptr->min_addr, nhlt_ptr->length);
|
||||
return memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
|
||||
MEMREMAP_WB);
|
||||
}
|
||||
|
||||
dev_err(dev, "device specific method to extract NHLT blob failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void skl_nhlt_free(void __iomem *addr)
|
||||
void skl_nhlt_free(void *addr)
|
||||
{
|
||||
iounmap(addr);
|
||||
addr = NULL;
|
||||
memunmap(addr);
|
||||
}
|
||||
|
||||
static struct nhlt_specific_cfg *skl_get_specific_cfg(
|
||||
|
|
|
@ -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(¶ms->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[] = {
|
||||
|
@ -487,6 +539,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,
|
||||
|
@ -544,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);
|
||||
|
@ -618,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);
|
||||
|
@ -675,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 */
|
||||
|
@ -844,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,
|
||||
|
@ -857,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) {
|
||||
|
|
|
@ -175,7 +175,7 @@ static int skl_dsp_core_power_down(struct sst_dsp *ctx)
|
|||
/* poll with timeout to check if operation successful */
|
||||
return sst_dsp_register_poll(ctx,
|
||||
SKL_ADSP_REG_ADSPCS,
|
||||
SKL_ADSPCS_SPA_MASK,
|
||||
SKL_ADSPCS_CPA_MASK,
|
||||
0,
|
||||
SKL_DSP_PD_TO,
|
||||
"Power down");
|
||||
|
@ -262,6 +262,11 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
|
|||
val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
|
||||
ctx->intr_status = val;
|
||||
|
||||
if (val == 0xffffffff) {
|
||||
spin_unlock(&ctx->spinlock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (val & SKL_ADSPIS_IPC) {
|
||||
skl_ipc_int_disable(ctx);
|
||||
result = IRQ_WAKE_THREAD;
|
||||
|
|
|
@ -464,6 +464,18 @@ void skl_ipc_op_int_enable(struct sst_dsp *ctx)
|
|||
SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
|
||||
}
|
||||
|
||||
void skl_ipc_op_int_disable(struct sst_dsp *ctx)
|
||||
{
|
||||
/* disable IPC DONE interrupt */
|
||||
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
|
||||
SKL_ADSP_REG_HIPCCTL_DONE, 0);
|
||||
|
||||
/* Disable IPC BUSY interrupt */
|
||||
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
|
||||
SKL_ADSP_REG_HIPCCTL_BUSY, 0);
|
||||
|
||||
}
|
||||
|
||||
bool skl_ipc_int_status(struct sst_dsp *ctx)
|
||||
{
|
||||
return sst_dsp_shim_read_unlocked(ctx,
|
||||
|
|
|
@ -116,6 +116,7 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
|
|||
|
||||
void skl_ipc_int_enable(struct sst_dsp *dsp);
|
||||
void skl_ipc_op_int_enable(struct sst_dsp *ctx);
|
||||
void skl_ipc_op_int_disable(struct sst_dsp *ctx);
|
||||
void skl_ipc_int_disable(struct sst_dsp *dsp);
|
||||
|
||||
bool skl_ipc_int_status(struct sst_dsp *dsp);
|
||||
|
|
|
@ -70,15 +70,31 @@ static int skl_transfer_firmware(struct sst_dsp *ctx,
|
|||
static int skl_load_base_firmware(struct sst_dsp *ctx)
|
||||
{
|
||||
int ret = 0, i;
|
||||
const struct firmware *fw = NULL;
|
||||
struct skl_sst *skl = ctx->thread_context;
|
||||
u32 reg;
|
||||
|
||||
ret = request_firmware(&fw, "dsp_fw_release.bin", ctx->dev);
|
||||
skl->boot_complete = false;
|
||||
init_waitqueue_head(&skl->boot_wait);
|
||||
|
||||
if (ctx->fw == NULL) {
|
||||
ret = request_firmware(&ctx->fw, "dsp_fw_release.bin", ctx->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(ctx->dev, "Request firmware failed %d\n", ret);
|
||||
skl_dsp_disable_core(ctx);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
ret = skl_dsp_boot(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(ctx->dev, "Request firmware failed %d\n", ret);
|
||||
skl_dsp_disable_core(ctx);
|
||||
return -EIO;
|
||||
dev_err(ctx->dev, "Boot dsp core failed ret: %d", ret);
|
||||
goto skl_load_base_firmware_failed;
|
||||
}
|
||||
|
||||
ret = skl_cldma_prepare(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(ctx->dev, "CL dma prepare failed : %d", ret);
|
||||
goto skl_load_base_firmware_failed;
|
||||
}
|
||||
|
||||
/* enable Interrupt */
|
||||
|
@ -102,7 +118,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
|
|||
goto skl_load_base_firmware_failed;
|
||||
}
|
||||
|
||||
ret = skl_transfer_firmware(ctx, fw->data, fw->size);
|
||||
ret = skl_transfer_firmware(ctx, ctx->fw->data, ctx->fw->size);
|
||||
if (ret < 0) {
|
||||
dev_err(ctx->dev, "Transfer firmware failed%d\n", ret);
|
||||
goto skl_load_base_firmware_failed;
|
||||
|
@ -118,13 +134,12 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
|
|||
dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
|
||||
skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
|
||||
}
|
||||
release_firmware(fw);
|
||||
|
||||
return 0;
|
||||
|
||||
skl_load_base_firmware_failed:
|
||||
skl_dsp_disable_core(ctx);
|
||||
release_firmware(fw);
|
||||
release_firmware(ctx->fw);
|
||||
ctx->fw = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -172,6 +187,12 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx)
|
|||
}
|
||||
skl_dsp_set_state_locked(ctx, SKL_DSP_RESET);
|
||||
|
||||
/* disable Interrupt */
|
||||
ctx->cl_dev.ops.cl_cleanup_controller(ctx);
|
||||
skl_cldma_int_disable(ctx);
|
||||
skl_ipc_op_int_disable(ctx);
|
||||
skl_ipc_int_disable(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -235,22 +256,6 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
skl->boot_complete = false;
|
||||
init_waitqueue_head(&skl->boot_wait);
|
||||
|
||||
ret = skl_dsp_boot(sst);
|
||||
if (ret < 0) {
|
||||
dev_err(skl->dev, "Boot dsp core failed ret: %d", ret);
|
||||
goto free_ipc;
|
||||
}
|
||||
|
||||
ret = skl_cldma_prepare(sst);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "CL dma prepare failed : %d", ret);
|
||||
goto free_ipc;
|
||||
}
|
||||
|
||||
|
||||
ret = sst->fw_ops.load_fw(sst);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Load base fw failed : %d", ret);
|
||||
|
@ -262,7 +267,6 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|||
|
||||
return 0;
|
||||
|
||||
free_ipc:
|
||||
skl_ipc_free(&skl->ipc);
|
||||
return ret;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -129,6 +129,11 @@ struct skl_src_module_cfg {
|
|||
enum skl_s_freq src_cfg;
|
||||
} __packed;
|
||||
|
||||
struct notification_mask {
|
||||
u32 notify;
|
||||
u32 enable;
|
||||
} __packed;
|
||||
|
||||
struct skl_up_down_mixer_cfg {
|
||||
struct skl_base_cfg base_cfg;
|
||||
enum skl_ch_cfg out_ch_cfg;
|
||||
|
@ -153,8 +158,7 @@ enum skl_dma_type {
|
|||
union skl_ssp_dma_node {
|
||||
u8 val;
|
||||
struct {
|
||||
u8 dual_mono:1;
|
||||
u8 time_slot:3;
|
||||
u8 time_slot_index:4;
|
||||
u8 i2s_instance:4;
|
||||
} dma_node;
|
||||
};
|
||||
|
@ -263,6 +267,34 @@ struct skl_module_cfg {
|
|||
struct skl_specific_cfg formats_config;
|
||||
};
|
||||
|
||||
struct skl_pipeline {
|
||||
struct skl_pipe *pipe;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct skl_dapm_path_list {
|
||||
struct snd_soc_dapm_path *dapm_path;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
static inline struct skl *get_skl_ctx(struct device *dev)
|
||||
{
|
||||
struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
|
||||
|
||||
return ebus_to_skl(ebus);
|
||||
}
|
||||
|
||||
int skl_tplg_be_update_params(struct snd_soc_dai *dai,
|
||||
struct skl_pipe_params *params);
|
||||
void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai,
|
||||
struct skl_pipe_params *params, int stream);
|
||||
int skl_tplg_init(struct snd_soc_platform *platform,
|
||||
struct hdac_ext_bus *ebus);
|
||||
struct skl_module_cfg *skl_tplg_fe_get_cpr_module(
|
||||
struct snd_soc_dai *dai, int stream);
|
||||
int skl_tplg_update_pipe_params(struct device *dev,
|
||||
struct skl_module_cfg *mconfig, struct skl_pipe_params *params);
|
||||
|
||||
int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe);
|
||||
|
||||
int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
|
||||
|
|
|
@ -19,6 +19,29 @@
|
|||
#ifndef __HDA_TPLG_INTERFACE_H__
|
||||
#define __HDA_TPLG_INTERFACE_H__
|
||||
|
||||
/*
|
||||
* Default types range from 0~12. type can range from 0 to 0xff
|
||||
* SST types start at higher to avoid any overlapping in future
|
||||
*/
|
||||
#define SOC_CONTROL_TYPE_HDA_SST_ALGO_PARAMS 0x100
|
||||
#define SOC_CONTROL_TYPE_HDA_SST_MUX 0x101
|
||||
#define SOC_CONTROL_TYPE_HDA_SST_MIX 0x101
|
||||
#define SOC_CONTROL_TYPE_HDA_SST_BYTE 0x103
|
||||
|
||||
#define HDA_SST_CFG_MAX 900 /* size of copier cfg*/
|
||||
#define MAX_IN_QUEUE 8
|
||||
#define MAX_OUT_QUEUE 8
|
||||
|
||||
/* Event types goes here */
|
||||
/* Reserve event type 0 for no event handlers */
|
||||
enum skl_event_types {
|
||||
SKL_EVENT_NONE = 0,
|
||||
SKL_MIXER_EVENT,
|
||||
SKL_MUX_EVENT,
|
||||
SKL_VMIXER_EVENT,
|
||||
SKL_PGA_EVENT
|
||||
};
|
||||
|
||||
/**
|
||||
* enum skl_ch_cfg - channel configuration
|
||||
*
|
||||
|
@ -83,6 +106,66 @@ enum skl_dev_type {
|
|||
SKL_DEVICE_I2S = 0x2,
|
||||
SKL_DEVICE_SLIMBUS = 0x3,
|
||||
SKL_DEVICE_HDALINK = 0x4,
|
||||
SKL_DEVICE_HDAHOST = 0x5,
|
||||
SKL_DEVICE_NONE
|
||||
};
|
||||
|
||||
struct skl_dfw_module_pin {
|
||||
u16 module_id;
|
||||
u16 instance_id;
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_module_fmt {
|
||||
u32 channels;
|
||||
u32 freq;
|
||||
u32 bit_depth;
|
||||
u32 valid_bit_depth;
|
||||
u32 ch_cfg;
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_module_caps {
|
||||
u32 caps_size;
|
||||
u32 caps[HDA_SST_CFG_MAX];
|
||||
};
|
||||
|
||||
struct skl_dfw_pipe {
|
||||
u8 pipe_id;
|
||||
u8 pipe_priority;
|
||||
u16 conn_type;
|
||||
u32 memory_pages;
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_module {
|
||||
u16 module_id;
|
||||
u16 instance_id;
|
||||
u32 max_mcps;
|
||||
u8 core_id;
|
||||
u8 max_in_queue;
|
||||
u8 max_out_queue;
|
||||
u8 is_loadable;
|
||||
u8 conn_type;
|
||||
u8 dev_type;
|
||||
u8 hw_conn_type;
|
||||
u8 time_slot;
|
||||
u32 obs;
|
||||
u32 ibs;
|
||||
u32 params_fixup;
|
||||
u32 converter;
|
||||
u32 module_type;
|
||||
u32 vbus_id;
|
||||
u8 is_dynamic_in_pin;
|
||||
u8 is_dynamic_out_pin;
|
||||
struct skl_dfw_pipe pipe;
|
||||
struct skl_dfw_module_fmt in_fmt;
|
||||
struct skl_dfw_module_fmt out_fmt;
|
||||
struct skl_dfw_module_pin in_pin[MAX_IN_QUEUE];
|
||||
struct skl_dfw_module_pin out_pin[MAX_OUT_QUEUE];
|
||||
struct skl_dfw_module_caps caps;
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_algo_data {
|
||||
u32 max;
|
||||
char *params;
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -166,12 +166,20 @@ static int skl_runtime_suspend(struct device *dev)
|
|||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
|
||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||
struct skl *skl = ebus_to_skl(ebus);
|
||||
int ret;
|
||||
|
||||
dev_dbg(bus->dev, "in %s\n", __func__);
|
||||
|
||||
/* enable controller wake up event */
|
||||
snd_hdac_chip_updatew(bus, WAKEEN, 0, STATESTS_INT_MASK);
|
||||
|
||||
snd_hdac_ext_bus_link_power_down_all(ebus);
|
||||
|
||||
ret = skl_suspend_dsp(skl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
snd_hdac_bus_stop_chip(bus);
|
||||
snd_hdac_bus_enter_link_reset(bus);
|
||||
|
||||
|
@ -183,7 +191,7 @@ static int skl_runtime_resume(struct device *dev)
|
|||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
|
||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||
struct skl *hda = ebus_to_skl(ebus);
|
||||
struct skl *skl = ebus_to_skl(ebus);
|
||||
int status;
|
||||
|
||||
dev_dbg(bus->dev, "in %s\n", __func__);
|
||||
|
@ -191,12 +199,12 @@ static int skl_runtime_resume(struct device *dev)
|
|||
/* Read STATESTS before controller reset */
|
||||
status = snd_hdac_chip_readw(bus, STATESTS);
|
||||
|
||||
skl_init_pci(hda);
|
||||
skl_init_pci(skl);
|
||||
snd_hdac_bus_init_chip(bus, true);
|
||||
/* disable controller Wake Up event */
|
||||
snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0);
|
||||
|
||||
return 0;
|
||||
return skl_resume_dsp(skl);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
@ -453,21 +461,28 @@ static int skl_probe(struct pci_dev *pci,
|
|||
if (err < 0)
|
||||
goto out_free;
|
||||
|
||||
skl->nhlt = skl_nhlt_init(bus->dev);
|
||||
|
||||
if (skl->nhlt == NULL)
|
||||
goto out_free;
|
||||
|
||||
pci_set_drvdata(skl->pci, ebus);
|
||||
|
||||
/* check if dsp is there */
|
||||
if (ebus->ppcap) {
|
||||
/* TODO register with dsp IPC */
|
||||
dev_dbg(bus->dev, "Register dsp\n");
|
||||
err = skl_init_dsp(skl);
|
||||
if (err < 0) {
|
||||
dev_dbg(bus->dev, "error failed to register dsp\n");
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
if (ebus->mlcap)
|
||||
snd_hdac_ext_bus_get_ml_capabilities(ebus);
|
||||
|
||||
/* create device for soc dmic */
|
||||
err = skl_dmic_device_register(skl);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
goto out_dsp_free;
|
||||
|
||||
/* register platform dai and controls */
|
||||
err = skl_platform_register(bus->dev);
|
||||
|
@ -491,6 +506,8 @@ static int skl_probe(struct pci_dev *pci,
|
|||
skl_platform_unregister(bus->dev);
|
||||
out_dmic_free:
|
||||
skl_dmic_device_unregister(skl);
|
||||
out_dsp_free:
|
||||
skl_free_dsp(skl);
|
||||
out_free:
|
||||
skl->init_failed = 1;
|
||||
skl_free(ebus);
|
||||
|
@ -507,6 +524,7 @@ static void skl_remove(struct pci_dev *pci)
|
|||
pm_runtime_get_noresume(&pci->dev);
|
||||
pci_dev_put(pci);
|
||||
skl_platform_unregister(&pci->dev);
|
||||
skl_free_dsp(skl);
|
||||
skl_dmic_device_unregister(skl);
|
||||
skl_free(ebus);
|
||||
dev_set_drvdata(&pci->dev, NULL);
|
||||
|
|
|
@ -48,6 +48,13 @@
|
|||
#define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094
|
||||
#define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20
|
||||
|
||||
struct skl_dsp_resource {
|
||||
u32 max_mcps;
|
||||
u32 max_mem;
|
||||
u32 mcps;
|
||||
u32 mem;
|
||||
};
|
||||
|
||||
struct skl {
|
||||
struct hdac_ext_bus ebus;
|
||||
struct pci_dev *pci;
|
||||
|
@ -55,8 +62,12 @@ struct skl {
|
|||
unsigned int init_failed:1; /* delayed init failed */
|
||||
struct platform_device *dmic_dev;
|
||||
|
||||
void __iomem *nhlt; /* nhlt ptr */
|
||||
void *nhlt; /* nhlt ptr */
|
||||
struct skl_sst *skl_sst; /* sst skl ctx */
|
||||
|
||||
struct skl_dsp_resource resource;
|
||||
struct list_head ppl_list;
|
||||
struct list_head dapm_path_list;
|
||||
};
|
||||
|
||||
#define skl_to_ebus(s) (&(s)->ebus)
|
||||
|
@ -72,8 +83,8 @@ struct skl_dma_params {
|
|||
int skl_platform_unregister(struct device *dev);
|
||||
int skl_platform_register(struct device *dev);
|
||||
|
||||
void __iomem *skl_nhlt_init(struct device *dev);
|
||||
void skl_nhlt_free(void __iomem *addr);
|
||||
void *skl_nhlt_init(struct device *dev);
|
||||
void skl_nhlt_free(void *addr);
|
||||
struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
|
||||
u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn);
|
||||
|
||||
|
|
Loading…
Reference in New Issue