diff options
author | Takashi Iwai <tiwai@suse.de> | 2017-02-20 23:43:40 +0300 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2017-02-20 23:43:40 +0300 |
commit | 4e25d30c8ddeae6ad0b68440aacadaacb14f8538 (patch) | |
tree | 08fe4ac15aec508b370262ad653c83a91be247b5 /sound/soc/intel/skylake | |
parent | d2bb390a2081a36ffe906724d2848d846f2aeb29 (diff) | |
parent | 141dee78c40ac2c43aa4ff306688d625e1c731de (diff) | |
download | linux-4e25d30c8ddeae6ad0b68440aacadaacb14f8538.tar.xz |
Merge tag 'asoc-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.11
Another release that's mainly focused on drivers rather than core
changes, highlights include:
- A huge batch of updates to the Intel drivers, mainly around
DisplayPort and HDMI with some additional board support too.
- Channel mapping support for HDMI.
- Support for AllWinner A31 and A33, Everest Semiconductor ES8328,
Nuvoton NAU8540.
Diffstat (limited to 'sound/soc/intel/skylake')
-rw-r--r-- | sound/soc/intel/skylake/bxt-sst.c | 64 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-messages.c | 7 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-nhlt.c | 58 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-pcm.c | 174 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-sst-dsp.h | 4 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-sst-ipc.h | 5 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.c | 97 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.h | 19 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-tplg-interface.h | 12 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl.c | 12 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl.h | 5 |
11 files changed, 279 insertions, 178 deletions
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 1f9f33d34000..15a063a403cc 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -23,7 +23,6 @@ #include "../common/sst-dsp.h" #include "../common/sst-dsp-priv.h" #include "skl-sst-ipc.h" -#include "skl-tplg-interface.h" #define BXT_BASEFW_TIMEOUT 3000 #define BXT_INIT_TIMEOUT 500 @@ -52,7 +51,7 @@ static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) } static int -bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo) +bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) { struct snd_dma_buffer dmab; struct skl_sst *skl = ctx->thread_context; @@ -61,11 +60,11 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo) int ret = 0, i, dma_id, stream_tag; /* library indices start from 1 to N. 0 represents base FW */ - for (i = 1; i < minfo->lib_count; i++) { - ret = request_firmware(&fw, minfo->lib[i].name, ctx->dev); + for (i = 1; i < lib_count; i++) { + ret = request_firmware(&fw, linfo[i].name, ctx->dev); if (ret < 0) { dev_err(ctx->dev, "Request lib %s failed:%d\n", - minfo->lib[i].name, ret); + linfo[i].name, ret); return ret; } @@ -96,7 +95,7 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo) ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i); if (ret < 0) dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n", - minfo->lib[i].name, ret); + linfo[i].name, ret); ctx->dsp_ops.trigger(ctx->dev, false, stream_tag); ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag); @@ -119,8 +118,7 @@ load_library_failed: static int sst_bxt_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) { - int stream_tag, ret, i; - u32 reg; + int stream_tag, ret; stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); if (stream_tag <= 0) { @@ -153,23 +151,13 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, } /* Step 4: Wait for DONE Bit */ - for (i = BXT_INIT_TIMEOUT; i > 0; --i) { - reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); - - if (reg & SKL_ADSP_REG_HIPCIE_DONE) { - sst_dsp_shim_update_bits_forced(ctx, - SKL_ADSP_REG_HIPCIE, + ret = sst_dsp_register_poll(ctx, SKL_ADSP_REG_HIPCIE, SKL_ADSP_REG_HIPCIE_DONE, - SKL_ADSP_REG_HIPCIE_DONE); - break; - } - mdelay(1); - } - if (!i) { - dev_info(ctx->dev, "Waiting for HIPCIE done, reg: 0x%x\n", reg); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCIE, - SKL_ADSP_REG_HIPCIE_DONE, - SKL_ADSP_REG_HIPCIE_DONE); + SKL_ADSP_REG_HIPCIE_DONE, + BXT_INIT_TIMEOUT, "HIPCIE Done"); + if (ret < 0) { + dev_err(ctx->dev, "Timout for Purge Request%d\n", ret); + goto base_fw_load_failed; } /* Step 5: power down core1 */ @@ -184,19 +172,10 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, skl_ipc_op_int_enable(ctx); /* Step 7: Wait for ROM init */ - for (i = BXT_INIT_TIMEOUT; i > 0; --i) { - if (SKL_FW_INIT == - (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & - SKL_FW_STS_MASK)) { - - dev_info(ctx->dev, "ROM loaded, continue FW loading\n"); - break; - } - mdelay(1); - } - if (!i) { - dev_err(ctx->dev, "Timeout for ROM init, HIPCIE: 0x%x\n", reg); - ret = -EIO; + ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, + SKL_FW_INIT, BXT_INIT_TIMEOUT, "ROM Load"); + if (ret < 0) { + dev_err(ctx->dev, "Timeout for ROM init, ret:%d\n", ret); goto base_fw_load_failed; } @@ -432,7 +411,6 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) int ret; struct skl_ipc_dxstate_info dx; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - struct skl_dfw_manifest *minfo = &skl->manifest; if (skl->fw_loaded == false) { skl->boot_complete = false; @@ -442,8 +420,9 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) return ret; } - if (minfo->lib_count > 1) { - ret = bxt_load_library(ctx, minfo); + if (skl->lib_count > 1) { + ret = bxt_load_library(ctx, skl->lib_info, + skl->lib_count); if (ret < 0) { dev_err(ctx->dev, "reload libs failed: %d\n", ret); return ret; @@ -640,8 +619,9 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) skl_dsp_init_core_state(sst); - if (ctx->manifest.lib_count > 1) { - ret = sst->fw_ops.load_library(sst, &ctx->manifest); + if (ctx->lib_count > 1) { + ret = sst->fw_ops.load_library(sst, ctx->lib_info, + ctx->lib_count); if (ret < 0) { dev_err(dev, "Load Library failed : %x\n", ret); return ret; diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index e79cbcf6e462..e66870474f10 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -220,6 +220,13 @@ static const struct skl_dsp_ops dsp_ops[] = { .init_fw = bxt_sst_init_fw, .cleanup = bxt_sst_dsp_cleanup }, + { + .id = 0x3198, + .loader_ops = bxt_get_loader_ops, + .init = bxt_sst_dsp_init, + .init_fw = bxt_sst_init_fw, + .cleanup = bxt_sst_dsp_cleanup + }, }; const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 3f8e6f0b7eb5..7eb9c419dc7f 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -102,14 +102,16 @@ static void dump_config(struct device *dev, u32 instance_id, u8 linktype, } static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, - u32 instance_id, u8 link_type, u8 dirn) + u32 instance_id, u8 link_type, u8 dirn, u8 dev_type) { - dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d\n", - epnt->virtual_bus_id, epnt->linktype, epnt->direction); + dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d dev_type = %d\n", + epnt->virtual_bus_id, epnt->linktype, + epnt->direction, epnt->device_type); if ((epnt->virtual_bus_id == instance_id) && (epnt->linktype == link_type) && - (epnt->direction == dirn)) + (epnt->direction == dirn) && + (epnt->device_type == dev_type)) return true; else return false; @@ -117,7 +119,8 @@ static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, - u8 s_fmt, u8 num_ch, u32 s_rate, u8 dirn) + u8 s_fmt, u8 num_ch, u32 s_rate, + u8 dirn, u8 dev_type) { struct nhlt_fmt *fmt; struct nhlt_endpoint *epnt; @@ -135,7 +138,8 @@ struct nhlt_specific_cfg dev_dbg(dev, "endpoint count =%d\n", nhlt->endpoint_count); for (j = 0; j < nhlt->endpoint_count; j++) { - if (skl_check_ep_match(dev, epnt, instance, link_type, dirn)) { + if (skl_check_ep_match(dev, epnt, instance, link_type, + dirn, dev_type)) { fmt = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size); sp_config = skl_get_specific_cfg(dev, fmt, num_ch, @@ -189,9 +193,9 @@ int skl_get_dmic_geo(struct skl *skl) return dmic_geo; } -static void skl_nhlt_trim_space(struct skl *skl) +static void skl_nhlt_trim_space(char *trim) { - char *s = skl->tplg_name; + char *s = trim; int cnt; int i; @@ -218,7 +222,43 @@ int skl_nhlt_update_topology_bin(struct skl *skl) skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id, nhlt->header.oem_revision, "-tplg.bin"); - skl_nhlt_trim_space(skl); + skl_nhlt_trim_space(skl->tplg_name); return 0; } + +static ssize_t skl_nhlt_platform_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pci_dev *pci = to_pci_dev(dev); + struct hdac_ext_bus *ebus = pci_get_drvdata(pci); + struct skl *skl = ebus_to_skl(ebus); + struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; + char platform_id[32]; + + sprintf(platform_id, "%x-%.6s-%.8s-%d", skl->pci_id, + nhlt->header.oem_id, nhlt->header.oem_table_id, + nhlt->header.oem_revision); + + skl_nhlt_trim_space(platform_id); + return sprintf(buf, "%s\n", platform_id); +} + +static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL); + +int skl_nhlt_create_sysfs(struct skl *skl) +{ + struct device *dev = &skl->pci->dev; + + if (sysfs_create_file(&dev->kobj, &dev_attr_platform_id.attr)) + dev_warn(dev, "Error creating sysfs entry\n"); + + return 0; +} + +void skl_nhlt_remove_sysfs(struct skl *skl) +{ + struct device *dev = &skl->pci->dev; + + sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); +} diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 6c6b63a6b338..e12520e142ff 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -137,6 +137,80 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, skl->supend_active--; } +int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + unsigned int format_val; + struct hdac_stream *hstream; + struct hdac_ext_stream *stream; + int err; + + hstream = snd_hdac_get_stream(bus, params->stream, + params->host_dma_id + 1); + if (!hstream) + return -EINVAL; + + stream = stream_to_hdac_ext_stream(hstream); + snd_hdac_ext_stream_decouple(ebus, stream, true); + + format_val = snd_hdac_calc_stream_format(params->s_freq, + params->ch, params->format, 32, 0); + + dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", + format_val, params->s_freq, params->ch, params->format); + + snd_hdac_stream_reset(hdac_stream(stream)); + err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); + if (err < 0) + return err; + + err = snd_hdac_stream_setup(hdac_stream(stream)); + if (err < 0) + return err; + + hdac_stream(stream)->prepared = 1; + + return 0; +} + +int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + unsigned int format_val; + struct hdac_stream *hstream; + struct hdac_ext_stream *stream; + struct hdac_ext_link *link; + + hstream = snd_hdac_get_stream(bus, params->stream, + params->link_dma_id + 1); + if (!hstream) + return -EINVAL; + + stream = stream_to_hdac_ext_stream(hstream); + snd_hdac_ext_stream_decouple(ebus, stream, true); + format_val = snd_hdac_calc_stream_format(params->s_freq, + params->ch, params->format, 24, 0); + + dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", + format_val, params->s_freq, params->ch, params->format); + + snd_hdac_ext_link_stream_reset(stream); + + snd_hdac_ext_link_stream_setup(stream, format_val); + + list_for_each_entry(link, &ebus->hlink_list, list) { + if (link->index == params->link_index) + snd_hdac_ext_link_set_stream_id(link, + hstream->stream_tag); + } + + stream->link_prepared = 1; + + return 0; +} + static int skl_pcm_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -188,32 +262,6 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, return 0; } -static int skl_get_format(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - struct skl_dma_params *dma_params; - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); - int format_val = 0; - - if ((ebus_to_hbus(ebus))->ppcap) { - struct snd_pcm_runtime *runtime = substream->runtime; - - format_val = snd_hdac_calc_stream_format(runtime->rate, - runtime->channels, - runtime->format, - 32, 0); - } else { - struct snd_soc_dai *codec_dai = rtd->codec_dai; - - dma_params = snd_soc_dai_get_dma_data(codec_dai, substream); - if (dma_params) - format_val = dma_params->format; - } - - return format_val; -} - static int skl_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -234,37 +282,19 @@ static int skl_be_prepare(struct snd_pcm_substream *substream, static int skl_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); struct skl *skl = get_skl_ctx(dai->dev); - unsigned int format_val; - int err; struct skl_module_cfg *mconfig; dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); - format_val = skl_get_format(substream, dai); - dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n", - hdac_stream(stream)->stream_tag, format_val); - snd_hdac_stream_reset(hdac_stream(stream)); - /* In case of XRUN recovery, reset the FW pipe to clean state */ if (mconfig && (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) skl_reset_pipe(skl->skl_sst, mconfig->pipe); - err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); - if (err < 0) - return err; - - err = snd_hdac_stream_setup(hdac_stream(stream)); - if (err < 0) - return err; - - hdac_stream(stream)->prepared = 1; - - return err; + return 0; } static int skl_pcm_hw_params(struct snd_pcm_substream *substream, @@ -295,6 +325,7 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream, p_params.s_freq = params_rate(params); p_params.host_dma_id = dma_id; p_params.stream = substream->stream; + p_params.format = params_format(params); m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream); if (m_cfg) @@ -438,7 +469,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: if (!w->ignore_suspend) { - skl_pcm_prepare(substream, dai); /* * enable DMA Resume enable bit for the stream, set the * dpib & lpib position to resume before starting the @@ -447,7 +477,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, snd_hdac_ext_stream_drsm_enable(ebus, true, hdac_stream(stream)->index); snd_hdac_ext_stream_set_dpibr(ebus, stream, - stream->dpib); + stream->lpib); snd_hdac_ext_stream_set_lpib(stream, stream->lpib); } @@ -459,7 +489,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, * pipeline is started but there is a delay in starting the * DMA channel on the host. */ - snd_hdac_ext_stream_decouple(ebus, stream, true); ret = skl_decoupled_trigger(substream, cmd); if (ret < 0) return ret; @@ -506,9 +535,10 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *link_dev; struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - struct hdac_ext_dma_params *dma_params; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct skl_pipe_params p_params = {0}; + struct hdac_ext_link *link; + int stream_tag; link_dev = snd_hdac_ext_stream_assign(ebus, substream, HDAC_EXT_STREAM_TYPE_LINK); @@ -517,16 +547,22 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); + link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); + if (!link) + return -EINVAL; + + stream_tag = hdac_stream(link_dev)->stream_tag; + /* set the stream tag in the codec dai dma params */ - dma_params = snd_soc_dai_get_dma_data(codec_dai, substream); - if (dma_params) - dma_params->stream_tag = hdac_stream(link_dev)->stream_tag; + snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 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; - p_params.link_dma_id = hdac_stream(link_dev)->stream_tag - 1; + p_params.link_dma_id = stream_tag - 1; + p_params.link_index = link->index; + p_params.format = params_format(params); return skl_tplg_be_update_params(dai, &p_params); } @@ -534,41 +570,15 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); - struct hdac_ext_stream *link_dev = - snd_soc_dai_get_dma_data(dai, substream); - unsigned int format_val = 0; - struct skl_dma_params *dma_params; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct hdac_ext_link *link; struct skl *skl = get_skl_ctx(dai->dev); struct skl_module_cfg *mconfig = NULL; - dma_params = (struct skl_dma_params *) - snd_soc_dai_get_dma_data(codec_dai, substream); - if (dma_params) - format_val = dma_params->format; - dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n", - hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name); - - link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); - if (!link) - return -EINVAL; - - snd_hdac_ext_link_stream_reset(link_dev); - /* In case of XRUN recovery, reset the FW pipe to clean state */ mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); - if (mconfig && (substream->runtime->status->state == - SNDRV_PCM_STATE_XRUN)) + if (mconfig && !mconfig->pipe->passthru && + (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) skl_reset_pipe(skl->skl_sst, mconfig->pipe); - snd_hdac_ext_link_stream_setup(link_dev, format_val); - - snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag); - link_dev->link_prepared = 1; - return 0; } @@ -583,10 +593,8 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: - skl_link_pcm_prepare(substream, dai); case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_hdac_ext_stream_decouple(ebus, stream, true); snd_hdac_ext_link_stream_start(link_dev); break; diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 7c272ba0f4b5..849410d0823e 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -19,7 +19,6 @@ #include <linux/interrupt.h> #include <sound/memalloc.h> #include "skl-sst-cldma.h" -#include "skl-tplg-interface.h" #include "skl-topology.h" struct sst_dsp; @@ -145,7 +144,7 @@ struct skl_dsp_fw_ops { int (*load_fw)(struct sst_dsp *ctx); /* FW module parser/loader */ int (*load_library)(struct sst_dsp *ctx, - struct skl_dfw_manifest *minfo); + struct skl_lib_info *linfo, int count); int (*parse_fw)(struct sst_dsp *ctx); int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id); int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id); @@ -236,5 +235,4 @@ int skl_get_pvt_instance_id_map(struct skl_sst *ctx, void skl_freeup_uuid_list(struct skl_sst *ctx); int skl_dsp_strip_extended_manifest(struct firmware *fw); - #endif /*__SKL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index cc40341233fa..9660ace379ab 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -97,8 +97,9 @@ struct skl_sst { /* multi-core */ struct skl_dsp_cores cores; - /* tplg manifest */ - struct skl_dfw_manifest manifest; + /* library info */ + struct skl_lib_info lib_info[SKL_MAX_LIB]; + int lib_count; /* Callback to update D0i3C register */ void (*update_d0i3c)(struct device *dev, bool enable); diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index bd313c907b20..ed58b5b3555a 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -330,6 +330,31 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx, multiplier; } +static u8 skl_tplg_be_dev_type(int dev_type) +{ + int ret; + + switch (dev_type) { + case SKL_DEVICE_BT: + ret = NHLT_DEVICE_BT; + break; + + case SKL_DEVICE_DMIC: + ret = NHLT_DEVICE_DMIC; + break; + + case SKL_DEVICE_I2S: + ret = NHLT_DEVICE_I2S; + break; + + default: + ret = NHLT_DEVICE_INVALID; + break; + } + + return ret; +} + static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, struct skl_sst *ctx) { @@ -338,6 +363,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, u32 ch, s_freq, s_fmt; struct nhlt_specific_cfg *cfg; struct skl *skl = get_skl_ctx(ctx->dev); + u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); /* check if we already have blob */ if (m_cfg->formats_config.caps_size > 0) @@ -374,7 +400,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, /* update the blob based on virtual bus_id and default params */ cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, - s_fmt, ch, s_freq, dir); + s_fmt, ch, s_freq, dir, dev_type); if (cfg) { m_cfg->formats_config.caps_size = cfg->size; m_cfg->formats_config.caps = (u32 *) &cfg->caps; @@ -496,6 +522,20 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) return 0; } +static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, + struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) +{ + switch (mcfg->dev_type) { + case SKL_DEVICE_HDAHOST: + return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params); + + case SKL_DEVICE_HDALINK: + return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params); + } + + return 0; +} + /* * Inside a pipe instance, we can have various modules. These modules need * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by @@ -535,6 +575,11 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) mconfig->m_state = SKL_MODULE_LOADED; } + /* prepare the DMA if the module is gateway cpr */ + ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig); + if (ret < 0) + return ret; + /* update blob if blob is null for be with default value */ skl_tplg_update_be_blob(w, ctx); @@ -974,7 +1019,6 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, struct skl_module_cfg *src_module = NULL, *dst_module; struct skl_sst *ctx = skl->skl_sst; struct skl_pipe *s_pipe = mconfig->pipe; - int ret = 0; if (s_pipe->state == SKL_PIPE_INVALID) return -EINVAL; @@ -996,7 +1040,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, src_module = dst_module; } - ret = skl_delete_pipe(ctx, mconfig->pipe); + skl_delete_pipe(ctx, mconfig->pipe); return skl_tplg_unload_pipe_modules(ctx, s_pipe); } @@ -1207,6 +1251,7 @@ static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, switch (mcfg->dev_type) { case SKL_DEVICE_HDALINK: pipe->p_params->link_dma_id = params->link_dma_id; + pipe->p_params->link_index = params->link_index; break; case SKL_DEVICE_HDAHOST: @@ -1220,6 +1265,7 @@ static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, pipe->p_params->ch = params->ch; pipe->p_params->s_freq = params->s_freq; pipe->p_params->stream = params->stream; + pipe->p_params->format = params->format; } else { memcpy(pipe->p_params, params, sizeof(*params)); @@ -1428,6 +1474,7 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, struct nhlt_specific_cfg *cfg; struct skl *skl = get_skl_ctx(dai->dev); int link_type = skl_tplg_be_link_type(mconfig->dev_type); + u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); skl_tplg_fill_dma_id(mconfig, params); @@ -1437,7 +1484,8 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, /* update the blob based on virtual bus_id*/ cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, params->s_fmt, params->ch, - params->s_freq, params->stream); + params->s_freq, params->stream, + dev_type); if (cfg) { mconfig->formats_config.caps_size = cfg->size; mconfig->formats_config.caps = (u32 *) &cfg->caps; @@ -2280,20 +2328,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, static int skl_tplg_fill_str_mfest_tkn(struct device *dev, struct snd_soc_tplg_vendor_string_elem *str_elem, - struct skl_dfw_manifest *minfo) + struct skl *skl) { int tkn_count = 0; static int ref_count; switch (str_elem->token) { case SKL_TKN_STR_LIB_NAME: - if (ref_count > minfo->lib_count - 1) { + if (ref_count > skl->skl_sst->lib_count - 1) { ref_count = 0; return -EINVAL; } - strncpy(minfo->lib[ref_count].name, str_elem->string, - ARRAY_SIZE(minfo->lib[ref_count].name)); + strncpy(skl->skl_sst->lib_info[ref_count].name, + str_elem->string, + ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); ref_count++; tkn_count++; break; @@ -2308,14 +2357,14 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev, static int skl_tplg_get_str_tkn(struct device *dev, struct snd_soc_tplg_vendor_array *array, - struct skl_dfw_manifest *minfo) + struct skl *skl) { int tkn_count = 0, ret; struct snd_soc_tplg_vendor_string_elem *str_elem; str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; while (tkn_count < array->num_elems) { - ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, minfo); + ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); str_elem++; if (ret < 0) @@ -2329,13 +2378,13 @@ static int skl_tplg_get_str_tkn(struct device *dev, static int skl_tplg_get_int_tkn(struct device *dev, struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl_dfw_manifest *minfo) + struct skl *skl) { int tkn_count = 0; switch (tkn_elem->token) { case SKL_TKN_U32_LIB_COUNT: - minfo->lib_count = tkn_elem->value; + skl->skl_sst->lib_count = tkn_elem->value; tkn_count++; break; @@ -2352,7 +2401,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, * type. */ static int skl_tplg_get_manifest_tkn(struct device *dev, - char *pvt_data, struct skl_dfw_manifest *minfo, + char *pvt_data, struct skl *skl, int block_size) { int tkn_count = 0, ret; @@ -2368,7 +2417,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, off += array->size; switch (array->type) { case SND_SOC_TPLG_TUPLE_TYPE_STRING: - ret = skl_tplg_get_str_tkn(dev, array, minfo); + ret = skl_tplg_get_str_tkn(dev, array, skl); if (ret < 0) return ret; @@ -2390,7 +2439,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, while (tkn_count <= array->num_elems - 1) { ret = skl_tplg_get_int_tkn(dev, - tkn_elem, minfo); + tkn_elem, skl); if (ret < 0) return ret; @@ -2411,7 +2460,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, * preceded by descriptors for type and size of data block. */ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, - struct device *dev, struct skl_dfw_manifest *minfo) + struct device *dev, struct skl *skl) { struct snd_soc_tplg_vendor_array *array; int num_blocks, block_size = 0, block_type, off = 0; @@ -2454,7 +2503,7 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, data = (manifest->priv.data + off); if (block_type == SKL_TYPE_TUPLE) { - ret = skl_tplg_get_manifest_tkn(dev, data, minfo, + ret = skl_tplg_get_manifest_tkn(dev, data, skl, block_size); if (ret < 0) @@ -2472,27 +2521,23 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, static int skl_manifest_load(struct snd_soc_component *cmpnt, struct snd_soc_tplg_manifest *manifest) { - struct skl_dfw_manifest *minfo; struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); struct hdac_bus *bus = ebus_to_hbus(ebus); struct skl *skl = ebus_to_skl(ebus); - int ret = 0; /* proceed only if we have private data defined */ if (manifest->priv.size == 0) return 0; - minfo = &skl->skl_sst->manifest; - - skl_tplg_get_manifest_data(manifest, bus->dev, minfo); + skl_tplg_get_manifest_data(manifest, bus->dev, skl); - if (minfo->lib_count > HDA_MAX_LIB) { + if (skl->skl_sst->lib_count > SKL_MAX_LIB) { dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", - minfo->lib_count); - ret = -EINVAL; + skl->skl_sst->lib_count); + return -EINVAL; } - return ret; + return 0; } static struct snd_soc_tplg_ops skl_tplg_ops = { diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 08d39280b07b..fefab0e99a3b 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -254,6 +254,8 @@ struct skl_pipe_params { u32 s_freq; u32 s_fmt; u8 linktype; + snd_pcm_format_t format; + int link_index; int stream; }; @@ -332,6 +334,19 @@ struct skl_pipeline { struct list_head node; }; +#define SKL_LIB_NAME_LENGTH 128 +#define SKL_MAX_LIB 16 + +struct skl_lib_info { + char name[SKL_LIB_NAME_LENGTH]; + const struct firmware *fw; +}; + +struct skl_manifest { + u32 lib_count; + struct skl_lib_info lib[SKL_MAX_LIB]; +}; + static inline struct skl *get_skl_ctx(struct device *dev) { struct hdac_ext_bus *ebus = dev_get_drvdata(dev); @@ -383,4 +398,8 @@ int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream); enum skl_bitdepth skl_get_bit_depth(int params); +int skl_pcm_host_dma_prepare(struct device *dev, + struct skl_pipe_params *params); +int skl_pcm_link_dma_prepare(struct device *dev, + struct skl_pipe_params *params); #endif diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 2f6281e056d6..7a2febf99019 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -157,18 +157,6 @@ struct skl_dfw_algo_data { char params[0]; } __packed; -#define LIB_NAME_LENGTH 128 -#define HDA_MAX_LIB 16 - -struct lib_info { - char name[LIB_NAME_LENGTH]; -} __packed; - -struct skl_dfw_manifest { - u32 lib_count; - struct lib_info lib[HDA_MAX_LIB]; -} __packed; - enum skl_tkn_dir { SKL_DIR_IN, SKL_DIR_OUT diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index da5db5098274..0c57d4eaae3a 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -732,6 +732,10 @@ static int skl_probe(struct pci_dev *pci, goto out_display_power_off; } + err = skl_nhlt_create_sysfs(skl); + if (err < 0) + goto out_nhlt_free; + skl_nhlt_update_topology_bin(skl); pci_set_drvdata(skl->pci, ebus); @@ -852,6 +856,7 @@ static void skl_remove(struct pci_dev *pci) skl_free_dsp(skl); skl_machine_device_unregister(skl); skl_dmic_device_unregister(skl); + skl_nhlt_remove_sysfs(skl); skl_nhlt_free(skl->nhlt); skl_free(ebus); dev_set_drvdata(&pci->dev, NULL); @@ -878,6 +883,10 @@ static struct sst_acpi_mach sst_kbl_devdata[] = { {} }; +static struct sst_acpi_mach sst_glk_devdata[] = { + { "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL }, +}; + /* PCI IDs */ static const struct pci_device_id skl_ids[] = { /* Sunrise Point-LP */ @@ -889,6 +898,9 @@ static const struct pci_device_id skl_ids[] = { /* KBL */ { PCI_DEVICE(0x8086, 0x9D71), .driver_data = (unsigned long)&sst_kbl_devdata}, + /* GLK */ + { PCI_DEVICE(0x8086, 0x3198), + .driver_data = (unsigned long)&sst_glk_devdata}, { 0, } }; MODULE_DEVICE_TABLE(pci, skl_ids); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 4986e3929dd3..bbef77d2b917 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -118,7 +118,8 @@ int skl_platform_register(struct device *dev); struct nhlt_acpi_table *skl_nhlt_init(struct device *dev); void skl_nhlt_free(struct nhlt_acpi_table *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); + u8 link_type, u8 s_fmt, u8 no_ch, + u32 s_rate, u8 dirn, u8 dev_type); int skl_get_dmic_geo(struct skl *skl); int skl_nhlt_update_topology_bin(struct skl *skl); @@ -130,5 +131,7 @@ int skl_resume_dsp(struct skl *skl); void skl_cleanup_resources(struct skl *skl); const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); void skl_update_d0i3c(struct device *dev, bool enable); +int skl_nhlt_create_sysfs(struct skl *skl); +void skl_nhlt_remove_sysfs(struct skl *skl); #endif /* __SOUND_SOC_SKL_H */ |