From 6e27a09261f11b9b8d19eb33571d540b355fef27 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Wed, 25 Jul 2018 19:45:47 -0400 Subject: [PATCH 01/21] ASoC: SOF: Define sof_create_platform_device Define a function sof_create_platform_device() to register the platform device "sof-audio". And SOF PCI, ACPI, SPI probe function will all use this function in their firmware request callback function. Signed-off-by: Mengdong Lin Signed-off-by: Keyon Jie --- sound/soc/sof/sof-acpi-dev.c | 9 ++------- sound/soc/sof/sof-pci-dev.c | 9 ++------- sound/soc/sof/sof-priv.h | 5 +++++ sound/soc/sof/sof-spi-dev.c | 9 ++------- sound/soc/sof/utils.c | 19 +++++++++++++++++++ 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index d635e6bda64bb3..860da8e565525d 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -149,13 +149,8 @@ static void sof_acpi_fw_cb(const struct firmware *fw, void *context) } /* register PCM and DAI driver */ - priv->pdev_pcm = - platform_device_register_data(dev, "sof-audio", -1, - sof_pdata, sizeof(*sof_pdata)); - if (IS_ERR(priv->pdev_pcm)) { - dev_err(dev, "Cannot register device sof-audio. Error %d\n", - (int)PTR_ERR(priv->pdev_pcm)); - } + sof_create_platform_device(priv); + return; } static const struct dev_pm_ops sof_acpi_pm = { diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index c8bf16f75b8416..196ca9cb50a0e1 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -142,13 +142,8 @@ static void sof_pci_fw_cb(const struct firmware *fw, void *context) } /* register PCM and DAI driver */ - priv->pdev_pcm = - platform_device_register_data(dev, "sof-audio", -1, - sof_pdata, sizeof(*sof_pdata)); - if (IS_ERR(priv->pdev_pcm)) { - dev_err(dev, "Cannot register device sof-audio. Error %d\n", - (int)PTR_ERR(priv->pdev_pcm)); - } + sof_create_platform_device(priv); + return; } static const struct dev_pm_ops sof_pci_pm = { diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index ba46c85a77eb35..7c97f9e69f87bc 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -522,4 +522,9 @@ static inline void sof_oops(struct snd_sof_dev *sdev, void *oops) } extern const struct sof_arch_ops sof_xtensa_arch_ops; + +/* + * Utilities + */ +int sof_create_platform_device(struct sof_platform_priv *priv); #endif diff --git a/sound/soc/sof/sof-spi-dev.c b/sound/soc/sof/sof-spi-dev.c index fb94f24b824076..78a493cf5d90ce 100644 --- a/sound/soc/sof/sof-spi-dev.c +++ b/sound/soc/sof/sof-spi-dev.c @@ -34,13 +34,8 @@ static void sof_spi_fw_cb(const struct firmware *fw, void *context) } /* register PCM and DAI driver */ - priv->pdev_pcm = - platform_device_register_data(dev, "sof-audio", -1, - sof_pdata, sizeof(*sof_pdata)); - if (IS_ERR(priv->pdev_pcm)) { - dev_err(dev, "Cannot register device sof-audio. Error %d\n", - (int)PTR_ERR(priv->pdev_pcm)); - } + sof_create_platform_device(priv); + return; } static const struct dev_pm_ops sof_spi_pm = { diff --git a/sound/soc/sof/utils.c b/sound/soc/sof/utils.c index 91c8417500af8c..afeec6b93817e6 100644 --- a/sound/soc/sof/utils.c +++ b/sound/soc/sof/utils.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include "sof-priv.h" @@ -47,3 +48,21 @@ int sof_bes_setup(struct device *dev, struct snd_sof_dsp_ops *ops, } EXPORT_SYMBOL(sof_bes_setup); +/* register sof platform device */ +int sof_create_platform_device(struct sof_platform_priv *priv) +{ + struct snd_sof_pdata *sof_pdata = priv->sof_pdata; + struct device *dev = sof_pdata->dev; + + priv->pdev_pcm = + platform_device_register_data(dev, "sof-audio", -1, + sof_pdata, sizeof(*sof_pdata)); + if (IS_ERR(priv->pdev_pcm)) { + dev_err(dev, "Cannot register device sof-audio. Error %d\n", + (int)PTR_ERR(priv->pdev_pcm)); + return PTR_ERR(priv->pdev_pcm); + } + + return 0; +} +EXPORT_SYMBOL(sof_create_platform_device); From 7c4d24da903bf3fe69a78e4cc9cde38957d6f924 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Aug 2018 13:16:42 +0800 Subject: [PATCH 02/21] ASoC: SOF: refine and cleanup for request_firmware 1. unify to request firmware in ops.load_firmware(). 2. fix request twice issue for skl+ platforms. Signed-off-by: Keyon Jie --- sound/soc/sof/core.c | 2 +- sound/soc/sof/intel/hda-loader.c | 19 +++-------------- sound/soc/sof/intel/hda.h | 3 +-- sound/soc/sof/loader.c | 35 ++++++++++++++++++++++++-------- sound/soc/sof/pm.c | 2 +- sound/soc/sof/sof-acpi-dev.c | 29 ++++---------------------- sound/soc/sof/sof-pci-dev.c | 28 +++---------------------- sound/soc/sof/sof-priv.h | 6 +++--- sound/soc/sof/sof-spi-dev.c | 29 ++++++-------------------- 9 files changed, 49 insertions(+), 104 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 924220c55b3c6c..e62cbc38ad284e 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -292,7 +292,7 @@ static int sof_probe(struct platform_device *pdev) } /* load the firmware */ - ret = snd_sof_load_firmware(sdev, plat_data->fw, true); + ret = snd_sof_load_firmware(sdev, true); if (ret < 0) { dev_err(sdev->dev, "error: failed to load DSP firmware %d\n", ret); diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 3d43c4232a0a18..61aceb220f605b 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -298,28 +298,15 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, int tag) return status; } -int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, const struct firmware *fw, - bool first_boot) +int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, bool first_boot) { struct snd_sof_pdata *plat_data = dev_get_platdata(sdev->dev); - int ret; /* set code loading condition to true */ sdev->code_loading = 1; - ret = request_firmware(&plat_data->fw, - plat_data->machine->sof_fw_filename, sdev->dev); - - if (ret < 0) { - dev_err(sdev->dev, "error: request firmware failed err: %d\n", - ret); - return -EINVAL; - } - - if (!plat_data->fw) - return -EINVAL; - - return ret; + return request_firmware(&plat_data->fw, + plat_data->machine->sof_fw_filename, sdev->dev); } int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 56efa7714788a7..33c3d22b3e3210 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -458,8 +458,7 @@ int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); /* * DSP Code loader. */ -int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, const struct firmware *fw, - bool first_boot); +int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, bool first_boot); int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev); /* diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 210a8d30989f21..12f88fd2f13016 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "sof-priv.h" #include "ops.h" @@ -208,42 +209,60 @@ static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw) } int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev, - const struct firmware *fw, bool first_boot) + bool first_boot) { + struct snd_sof_pdata *plat_data = dev_get_platdata(sdev->dev); int ret; + /* set code loading condition to true */ + sdev->code_loading = 1; + + ret = request_firmware(&plat_data->fw, + plat_data->machine->sof_fw_filename, sdev->dev); + + if (ret < 0) { + dev_err(sdev->dev, "error: request firmware failed err: %d\n", + ret); + return ret; + } + /* make sure the FW header and file is valid */ - ret = check_header(sdev, fw); + ret = check_header(sdev, plat_data->fw); if (ret < 0) { dev_err(sdev->dev, "error: invalid FW header\n"); - return ret; + goto error; } /* prepare the DSP for FW loading */ ret = snd_sof_dsp_reset(sdev); if (ret < 0) { dev_err(sdev->dev, "error: failed to reset DSP\n"); - return ret; + goto error; } /* parse and load firmware modules to DSP */ - ret = load_modules(sdev, fw); + ret = load_modules(sdev, plat_data->fw); if (ret < 0) { dev_err(sdev->dev, "error: invalid FW modules\n"); - return ret; + goto error; } + return 0; + +error: + release_firmware(plat_data->fw); return ret; + } EXPORT_SYMBOL(snd_sof_load_firmware_memcpy); int snd_sof_load_firmware(struct snd_sof_dev *sdev, - const struct firmware *fw, bool first_boot) + bool first_boot) { dev_dbg(sdev->dev, "loading firmware\n"); if (sdev->ops->load_firmware) - return sdev->ops->load_firmware(sdev, fw, first_boot); + return sdev->ops->load_firmware(sdev, first_boot); return 0; } EXPORT_SYMBOL(snd_sof_load_firmware); diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 75c1a71feb7981..3e7dee9da87782 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -223,7 +223,7 @@ static int sof_resume(struct device *dev) } /* load the firmware */ - ret = snd_sof_load_firmware(sdev, sdev->pdata->fw, false); + ret = snd_sof_load_firmware(sdev, false); if (ret < 0) { dev_err(sdev->dev, "error: failed to load DSP firmware after resume %d\n", diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 860da8e565525d..0599f998a8a2b0 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -134,25 +134,6 @@ static struct platform_device * return pdev; } -static void sof_acpi_fw_cb(const struct firmware *fw, void *context) -{ - struct sof_platform_priv *priv = context; - struct snd_sof_pdata *sof_pdata = priv->sof_pdata; - const struct snd_soc_acpi_mach *mach = sof_pdata->machine; - struct device *dev = sof_pdata->dev; - - sof_pdata->fw = fw; - if (!fw) { - dev_err(dev, "Cannot load firmware %s\n", - mach->sof_fw_filename); - return; - } - - /* register PCM and DAI driver */ - sof_create_platform_device(priv); - return; -} - static const struct dev_pm_ops sof_acpi_pm = { SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, @@ -286,14 +267,12 @@ static int sof_acpi_probe(struct platform_device *pdev) dev_dbg(dev, "created machine %s\n", dev_name(&sof_pdata->pdev_mach->dev)); - /* continue SST probing after firmware is loaded */ - dev_info(dev, "info: loading firmware %s\n", mach->sof_fw_filename); - ret = request_firmware_nowait(THIS_MODULE, true, mach->sof_fw_filename, - dev, GFP_KERNEL, priv, sof_acpi_fw_cb); + /* register sof-audio platform driver */ + ret = sof_create_platform_device(priv); if (ret) { platform_device_unregister(sof_pdata->pdev_mach); - dev_err(dev, "error: failed to load firmware %s\n", - mach->sof_fw_filename); + dev_err(dev, "error: failed to create platform device!\n"); + return ret; } /* allow runtime_pm */ diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 196ca9cb50a0e1..3b9755b39f549f 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -127,25 +127,6 @@ static const struct sof_dev_desc icl_desc = { }; #endif -static void sof_pci_fw_cb(const struct firmware *fw, void *context) -{ - struct sof_platform_priv *priv = context; - struct snd_sof_pdata *sof_pdata = priv->sof_pdata; - const struct snd_soc_acpi_mach *mach = sof_pdata->machine; - struct device *dev = sof_pdata->dev; - - sof_pdata->fw = fw; - if (!fw) { - dev_err(dev, "Cannot load firmware %s\n", - mach->sof_fw_filename); - return; - } - - /* register PCM and DAI driver */ - sof_create_platform_device(priv); - return; -} - static const struct dev_pm_ops sof_pci_pm = { SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, @@ -277,14 +258,11 @@ static int sof_pci_probe(struct pci_dev *pci, dev_dbg(dev, "created machine %s\n", dev_name(&sof_pdata->pdev_mach->dev)); - /* continue probing after firmware is loaded */ - dev_info(dev, "info: loading firmware %s\n", mach->sof_fw_filename); - ret = request_firmware_nowait(THIS_MODULE, true, mach->sof_fw_filename, - dev, GFP_KERNEL, priv, sof_pci_fw_cb); + /* register sof-audio platform driver */ + ret = sof_create_platform_device(priv); if (ret) { platform_device_unregister(sof_pdata->pdev_mach); - dev_err(dev, "error: failed to load firmware %s\n", - mach->sof_fw_filename); + dev_err(dev, "error: failed to create platform device!\n"); goto release_regions; } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 7c97f9e69f87bc..5738e9c597687f 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -141,7 +141,7 @@ struct snd_sof_dsp_ops { /* FW loading */ int (*load_firmware)(struct snd_sof_dev *sof_dev, - const struct firmware *fw, bool first_boot); + bool first_boot); int (*load_module)(struct snd_sof_dev *sof_dev, struct snd_sof_mod_hdr *hdr); int (*fw_ready)(struct snd_sof_dev *sdev, u32 msg_id); @@ -397,9 +397,9 @@ int snd_sof_create_page_table(struct snd_sof_dev *sdev, * Firmware loading. */ int snd_sof_load_firmware(struct snd_sof_dev *sdev, - const struct firmware *fw, bool first_boot); + bool first_boot); int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev, - const struct firmware *fw, bool first_boot); + bool first_boot); int snd_sof_run_firmware(struct snd_sof_dev *sdev); int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, struct snd_sof_mod_hdr *module); diff --git a/sound/soc/sof/sof-spi-dev.c b/sound/soc/sof/sof-spi-dev.c index 78a493cf5d90ce..4368b6138b57d5 100644 --- a/sound/soc/sof/sof-spi-dev.c +++ b/sound/soc/sof/sof-spi-dev.c @@ -19,25 +19,6 @@ #include #include "sof-priv.h" -static void sof_spi_fw_cb(const struct firmware *fw, void *context) -{ - struct sof_platform_priv *priv = context; - struct snd_sof_pdata *sof_pdata = priv->sof_pdata; - const struct snd_sof_machine *mach = sof_pdata->machine; - struct device *dev = sof_pdata->dev; - - sof_pdata->fw = fw; - if (!fw) { - dev_err(dev, "Cannot load firmware %s\n", - mach->sof_fw_filename); - return; - } - - /* register PCM and DAI driver */ - sof_create_platform_device(priv); - return; -} - static const struct dev_pm_ops sof_spi_pm = { SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, @@ -96,11 +77,13 @@ static int sof_spi_probe(struct spi_device *spi) dev_dbg(dev, "created machine %s\n", dev_name(&sof_pdata->pdev_mach->dev)); - /* continue probing after firmware is loaded */ - ret = request_firmware_nowait(THIS_MODULE, true, mach->sof_fw_filename, - dev, GFP_KERNEL, priv, sof_spi_fw_cb); - if (ret) + /* register sof-audio platform driver */ + ret = sof_create_platform_device(priv); + if (ret) { platform_device_unregister(sof_pdata->pdev_mach); + dev_err(dev, "error: failed to create platform device!\n"); + return ret; + } /* allow runtime_pm */ pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY); From c176a3f982214494a8b011c2137a9640d8d7721b Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 10 Aug 2018 19:27:19 +0800 Subject: [PATCH 03/21] ASoC: SOF: bypass ADSP for Force legacy HDA mode Define a new kernel config item SND_SOC_SOF_FORCE_LEGACY_HDA, which depends on SND_SOC_SOF_HDA. To test SOF in legacy HDA mode, we can enable both SND_SOC_SOF_HDA and SND_SOC_SOF_FORCE_LEGACY_HDA. And then SOF will bypass audio DSP and not firmware will be downloaded. Signed-off-by: Mengdong Lin Signed-off-by: Keyon Jie --- sound/soc/sof/core.c | 9 +++++++++ sound/soc/sof/intel/Kconfig | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index e62cbc38ad284e..c4b057993f92af 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -291,6 +291,8 @@ static int sof_probe(struct platform_device *pdev) goto ipc_err; } +/* bypass DSP if in force legacy hda debug mode */ +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA /* load the firmware */ ret = snd_sof_load_firmware(sdev, true); if (ret < 0) { @@ -306,6 +308,7 @@ static int sof_probe(struct platform_device *pdev) ret); goto fw_run_err; } +#endif /* now register audio DSP platform driver */ ret = snd_soc_register_platform(&pdev->dev, &sdev->plat_drv); @@ -324,6 +327,8 @@ static int sof_probe(struct platform_device *pdev) goto comp_err; } +/* bypass DSP if in force legacy hda debug mode */ +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA /* init DMA trace */ ret = snd_sof_init_trace(sdev); if (ret < 0) { @@ -331,6 +336,7 @@ static int sof_probe(struct platform_device *pdev) dev_warn(sdev->dev, "warning: failed to initialize trace %d\n", ret); } +#endif /* autosuspend sof device */ pm_runtime_mark_last_busy(sdev->dev); @@ -346,9 +352,12 @@ static int sof_probe(struct platform_device *pdev) snd_soc_unregister_component(&pdev->dev); snd_sof_free_topology(sdev); fw_run_err: +/* bypass DSP if in force legacy hda debug mode */ +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA snd_sof_fw_unload(sdev); fw_load_err: snd_sof_ipc_free(sdev); +#endif ipc_err: snd_sof_free_debug(sdev); dbg_err: diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index d777ddd80d893e..111206ba034605 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -113,4 +113,15 @@ config SND_SOC_SOF_HDA Say Y if you want to enble HDA links with SOF. If unsure select "N". +config SND_SOC_SOF_FORCE_LEGACY_HDA + bool "SOF force legacy hda and bypass DSP" + depends on SND_SOC_SOF_HDA + depends on SND_SOC_SOF_DEBUG + help + This forces the driver to use HDA legacy mode, and bypasses + the embedded DSP in HD-A controller on Intel SKL+ platforms. + This is designed for debugging only. + Say Y if you do wan't to use this mode. + If unsure select "N". + endif ## SND_SOC_SOF_INTEL From 2c361f59b7b38a09c127e0086a3048b451647097 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 10 Aug 2018 19:29:08 +0800 Subject: [PATCH 04/21] ASoC: SOF: add pointer callback for dsp_ops Signed-off-by: Keyon Jie --- sound/soc/sof/ops.h | 12 ++++++++++++ sound/soc/sof/sof-priv.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 0d6fa6ef1a3e8b..21f84cc3251167 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "sof-priv.h" @@ -265,6 +266,17 @@ snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev, return 0; } +/* host stream pointer */ +static inline snd_pcm_uframes_t +snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + if (sdev->ops && sdev->ops->pcm_pointer) + return sdev->ops->pcm_pointer(sdev, substream); + else + return 0; +} + int snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar, u32 offset, u32 mask, u32 value); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 5738e9c597687f..ef177a886777df 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -139,6 +139,10 @@ struct snd_sof_dsp_ops { int (*pcm_trigger)(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, int cmd); + /* host stream pointer */ + snd_pcm_uframes_t (*pcm_pointer)(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream); + /* FW loading */ int (*load_firmware)(struct snd_sof_dev *sof_dev, bool first_boot); From 3b7dab1020be4fc76667f44da9dc9c5e0106ddb3 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Aug 2018 18:11:01 +0800 Subject: [PATCH 05/21] ASoC: SOF: HDA: add pcm_pointer callback Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda-pcm.c | 33 +++++++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 7a53166bbb7723..481921443c6e3d 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,38 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, return hda_dsp_stream_trigger(sdev, stream, cmd); } +snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + struct hdac_stream *hstream = substream->runtime->private_data; + struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream); + struct hdac_bus *bus = sof_to_bus(sdev); + snd_pcm_uframes_t pos = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, + AZX_REG_VS_SDXDPIB_XBASE + + (AZX_REG_VS_SDXDPIB_XINTERVAL * + hstream->index)); + } else { + udelay(20); + snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, + AZX_REG_VS_SDXDPIB_XBASE + + (AZX_REG_VS_SDXDPIB_XINTERVAL * + hstream->index)); + pos = snd_hdac_stream_get_pos_posbuf(hstream); + } + + if (pos >= hstream->bufsize) + pos = 0; + + pos = bytes_to_frames(substream->runtime, pos); + + dev_dbg(sdev->dev, "PCM: stream %d dir %d position %lu\n", + hstream->index, substream->stream, pos); + return pos; +} + int hda_dsp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 33c3d22b3e3210..e5afdeb0726ca4 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -408,6 +408,8 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params); int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream); /* * DSP Stream Operations. From 748035c846c21a3e940202692e05368f6dd3c2de Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Aug 2018 18:12:38 +0800 Subject: [PATCH 06/21] ASoC: SOF: apl: add pcm_pointer callback to dsp_ops Signed-off-by: Keyon Jie --- sound/soc/sof/intel/apl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index d3816b99498584..b0e8255883870a 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -81,6 +81,7 @@ struct snd_sof_dsp_ops sof_apl_ops = { .pcm_close = hda_dsp_pcm_close, .pcm_hw_params = hda_dsp_pcm_hw_params, .pcm_trigger = hda_dsp_pcm_trigger, + .pcm_pointer = hda_dsp_pcm_pointer, /* firmware loading */ .load_firmware = hda_dsp_cl_load_fw, From a36a21b3c8b553c8abe05de0028ce26db153e3b3 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Aug 2018 18:44:43 +0800 Subject: [PATCH 07/21] ASoC: SOF: HACK to use DPIB position update for hda legacy mode Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda.c | 4 +++- sound/soc/sof/pcm.c | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 52c6010d67b7e1..c81db941e6d3f2 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -561,6 +561,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) goto free_streams; } +/* don't need ipc handler for legacy HDA mode */ +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq); ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_ipc_irq_handler, chip->ops->irq_thread, IRQF_SHARED, @@ -570,7 +572,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->ipc_irq); goto free_hda_irq; } - +#endif pci_set_master(pci); synchronize_irq(pci->irq); diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index a4a14acaa442c0..cb73d45605288c 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -323,6 +323,7 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_sof_dev *sdev = snd_soc_platform_get_drvdata(rtd->platform); +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA struct snd_sof_pcm *spcm = rtd->sof; snd_pcm_uframes_t host = 0, dai = 0; @@ -338,8 +339,10 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) dev_dbg(sdev->dev, "PCM: stream %d dir %d DMA position %lu DAI position %lu\n", spcm->pcm.pcm_id, substream->stream, host, dai); - return host; +#else + return snd_sof_pcm_platform_pointer(sdev, substream); +#endif } static int sof_pcm_open(struct snd_pcm_substream *substream) From 3d706890f0f91b09251de476d51060f4f72416fb Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Aug 2018 18:46:00 +0800 Subject: [PATCH 08/21] ASoC: SOF: HACK to use coupled mode for hda leagacy Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda-stream.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index f77421e2e831bb..fc9ea09297fc9d 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -322,8 +322,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, /* decouple host and link DMA */ mask = 0x1 << hstream->index; snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA mask, mask); - +#else + /* temporary using coupled mode */ + mask, 0); +#endif if (!dmab) { dev_err(sdev->dev, "error: no dma buffer allocated!\n"); return -ENODEV; @@ -526,6 +530,7 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) !s->running || (sd_status & SOF_HDA_CL_DMA_SD_INT_MASK) == 0) continue; + snd_pcm_period_elapsed(s->substream); } } From 6f2dcae7cb1ba92043a818a1aea9f59959b7d4d1 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Aug 2018 18:46:55 +0800 Subject: [PATCH 09/21] ASoC: SOF: HACK to disable ipc sending for hda legacy mode Signed-off-by: Keyon Jie --- sound/soc/sof/ipc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 908f6c9de85154..80ab906d60606b 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -264,6 +264,10 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, struct snd_sof_ipc_msg *msg; unsigned long flags; + /* todo: fix me: temporary disable ipc message sending */ +#ifdef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA + return 0; +#endif spin_lock_irqsave(&sdev->ipc_lock, flags); /* get an empty message */ From d36b009fe15e5c3a4dc8a1a60ada4f33519f7184 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 9 Aug 2018 17:50:49 +0800 Subject: [PATCH 10/21] ASoC: Intel: bxt-tdf8532: add hdmi support Signed-off-by: Keyon Jie --- sound/soc/intel/boards/bxt_tdf8532.c | 128 ++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/bxt_tdf8532.c b/sound/soc/intel/boards/bxt_tdf8532.c index ebb8bfe19b9d2f..e70b0ab93624d5 100644 --- a/sound/soc/intel/boards/bxt_tdf8532.c +++ b/sound/soc/intel/boards/bxt_tdf8532.c @@ -10,6 +10,19 @@ #include #include #include +#include +#include "../../codecs/hdac_hdmi.h" + +struct bxt_hdmi_pcm { + struct list_head head; + struct snd_soc_dai *codec_dai; + int device; +}; + +struct bxt_sof_private { + struct list_head hdmi_pcm_list; +}; + static const struct snd_kcontrol_new broxton_tdf8532_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), @@ -29,6 +42,7 @@ static const struct snd_soc_dapm_widget broxton_tdf8532_widgets[] = { }; static const struct snd_soc_dapm_route broxton_tdf8532_map[] = { +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA /* Speaker BE connections */ { "Speaker", NULL, "ssp4 Tx"}, { "ssp4 Tx", NULL, "codec0_out"}, @@ -65,8 +79,52 @@ static const struct snd_soc_dapm_route broxton_tdf8532_map[] = { { "ModemUl", NULL, "ssp3 Tx"}, { "ssp3 Tx", NULL, "Modem_ssp3_out"}, + +#else + { "hifi3", NULL, "iDisp3 Tx"}, + { "hifi2", NULL, "iDisp2 Tx"}, + { "hifi1", NULL, "iDisp1 Tx"}, +#endif }; +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack broxton_headset; +static struct snd_soc_jack broxton_hdmi[3]; + +#define NAME_SIZE 32 +static int bxt_card_late_probe(struct snd_soc_card *card) +{ + struct bxt_sof_private *ctx = snd_soc_card_get_drvdata(card); + struct bxt_hdmi_pcm *pcm; + struct snd_soc_component *component = NULL; + int err, i = 0; + char jack_name[NAME_SIZE]; + + list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + component = pcm->codec_dai->component; + snprintf(jack_name, sizeof(jack_name), + "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, &broxton_hdmi[i], + NULL, 0); + + if (err) + return err; + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &broxton_hdmi[i]); + if (err < 0) + return err; + + i++; + } + + if (!component) + return -EINVAL; + + return hdac_hdmi_jack_port_init(component, &card->dapm); +} + static int bxt_tdf8532_ssp2_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -79,8 +137,28 @@ static int bxt_tdf8532_ssp2_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct bxt_sof_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *dai = rtd->codec_dai; + struct bxt_hdmi_pcm *pcm; + + pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); + if (!pcm) + return -ENOMEM; + + pcm->device = dai->id; + pcm->codec_dai = dai; + + list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); + + return 0; +} + + /* broxton digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA /* Probe DAI links*/ { .name = "Bxt Compress Probe playback", @@ -211,8 +289,6 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { .cpu_dai_name = "iDisp1 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi1", -// .codec_name = "i2c-INT34C3:00", -// .codec_dai_name = "tdf8532-hifi", .platform_name = "0000:00:0e.0", .dpcm_playback = 1, .no_pcm = 1, @@ -237,6 +313,42 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { .dpcm_playback = 1, .no_pcm = 1, }, +#else + /* Back End DAI links */ + { + .name = "iDisp1", + .id = 0, + .cpu_dai_name = "iDisp1 Pin", + .codec_name = "ehdaudio0D2", + .codec_dai_name = "intel-hdmi-hifi1", + .platform_name = "sof-audio", + .init = broxton_hdmi_init, + .dpcm_playback = 1, + .no_pcm = 1, + }, + { + .name = "iDisp2", + .id = 1, + .cpu_dai_name = "iDisp2 Pin", + .codec_name = "ehdaudio0D2", + .codec_dai_name = "intel-hdmi-hifi2", + .platform_name = "sof-audio", + .init = broxton_hdmi_init, + .dpcm_playback = 1, + .no_pcm = 1, + }, + { + .name = "iDisp3", + .id = 2, + .cpu_dai_name = "iDisp3 Pin", + .codec_name = "ehdaudio0D2", + .codec_dai_name = "intel-hdmi-hifi3", + .platform_name = "sof-audio", + .init = broxton_hdmi_init, + .dpcm_playback = 1, + .no_pcm = 1, + }, +#endif }; #if !IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL) @@ -261,6 +373,7 @@ static struct snd_soc_card broxton_tdf8532 = { .dapm_routes = broxton_tdf8532_map, .num_dapm_routes = ARRAY_SIZE(broxton_tdf8532_map), .fully_routed = true, + .late_probe = bxt_card_late_probe, #if !IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL) .add_dai_link = bxt_add_dai_link, #endif @@ -268,8 +381,19 @@ static struct snd_soc_card broxton_tdf8532 = { static int broxton_tdf8532_audio_probe(struct platform_device *pdev) { + struct bxt_sof_private *ctx; + dev_info(&pdev->dev, "%s registering %s\n", __func__, pdev->name); broxton_tdf8532.dev = &pdev->dev; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); + if (!ctx) + return -ENOMEM; + + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); + + snd_soc_card_set_drvdata(&broxton_tdf8532, ctx); + return snd_soc_register_card(&broxton_tdf8532); } From 356a728aaa12ebea81c13a71d328ca86678ae3d2 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 10 Aug 2018 19:30:30 +0800 Subject: [PATCH 11/21] [HACK]ASoC: SOF: topology: temporary ignore hw_config for legacy hda mode Signed-off-by: Mengdong Lin Signed-off-by: Keyon Jie --- sound/soc/sof/topology.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 702d8a2eaa9509..c2c570cb00f67c 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1779,6 +1779,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, if (!link->no_pcm) return 0; +#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA /* only support 1 config atm */ if (le32_to_cpu(cfg->num_hw_configs) != 1) { dev_err(sdev->dev, "error: unexpected DAI config count %d\n", @@ -1831,6 +1832,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, } if (ret < 0) return ret; +#endif /* set config for all DAI's with name matching the link name */ list_for_each_entry(dai, &sdev->dai_list, list) { From d75c2937bf9383ea86b7fa4e5b437ca503bf195a Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 10 Aug 2018 20:03:40 +0800 Subject: [PATCH 12/21] ASoC: temporary disable PM as it will lead to calltrace Signed-off-by: Keyon Jie --- sound/soc/sof/sof-pci-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 3b9755b39f549f..db70d977ffd070 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -352,7 +352,7 @@ static struct pci_driver snd_sof_pci_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, +// .pm = &sof_pci_pm, }, }; module_pci_driver(snd_sof_pci_driver); From 95387e2344909f9fa46c026ec2ca1781a365da87 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 13 Aug 2018 13:42:11 +0800 Subject: [PATCH 13/21] ASoC: SOF: intel: clear TCSEL after synchronize_irq Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index c81db941e6d3f2..a0c28d7c49d137 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -524,12 +524,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) goto err; } - /* - * clear TCSEL to clear playback on some HD Audio - * codecs. PCI TCSEL is defined in the Intel manuals. - */ - snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); - /* * register our IRQ * let's try to enable msi firstly @@ -576,6 +570,13 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) pci_set_master(pci); synchronize_irq(pci->irq); + /* + * clear TCSEL to clear playback on some HD Audio + * codecs. PCI TCSEL is defined in the Intel manuals. + */ + snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); + + /* init HDA capabilities */ ret = hda_init_caps(sdev); if (ret < 0) From 7f556f0bb905c5c9df2239103a3f4dab21128943 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 17 Aug 2018 15:08:09 +0800 Subject: [PATCH 14/21] ASoC: SOF: topology: only give warning and continue parsing when num_hw_configs is not 1 Signed-off-by: Keyon Jie --- sound/soc/sof/topology.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index c2c570cb00f67c..c71183dec58d0c 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1779,13 +1779,10 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, if (!link->no_pcm) return 0; -#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA - /* only support 1 config atm */ - if (le32_to_cpu(cfg->num_hw_configs) != 1) { - dev_err(sdev->dev, "error: unexpected DAI config count %d\n", + /* usually we use 1 config, but for HDA it may be 0 ATM */ + if (le32_to_cpu(cfg->num_hw_configs) != 1) + dev_warn(sdev->dev, "warn: unexpected DAI config count %d!\n", le32_to_cpu(cfg->num_hw_configs)); - return -EINVAL; - } /* check we have some tokens - we need at least DAI type */ if (le32_to_cpu(private->size) == 0) { @@ -1832,7 +1829,6 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, } if (ret < 0) return ret; -#endif /* set config for all DAI's with name matching the link name */ list_for_each_entry(dai, &sdev->dai_list, list) { From 456e8c3679c67a8e6fc82955d1bcf000ad84507d Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 17 Aug 2018 15:23:54 +0800 Subject: [PATCH 15/21] ASoC: SOF: PCM: do nothing for HDA dai_link fixup() Signed-off-by: Keyon Jie --- sound/soc/sof/pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index cb73d45605288c..d4e21ae6911819 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -633,7 +633,8 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, /* TODO: add any other DMIC specific fixups */ break; case SOF_DAI_INTEL_HDA: - /* fallthrough */ + /* do nothing for HDA dai_link */ + break; default: dev_err(sdev->dev, "error: invalid DAI type %d\n", dai->dai_config.type); From caa51af112a3f2b30bce67d101a33826c51d2202 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 17 Aug 2018 15:46:43 +0800 Subject: [PATCH 16/21] ASoC: SOF: use dsp .pointer() callback if we have when USE_POS_BUF is defined Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda-stream.c | 2 ++ sound/soc/sof/ipc.c | 2 ++ sound/soc/sof/pcm.c | 10 ++++++---- sound/soc/sof/sof-priv.h | 2 ++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index fc9ea09297fc9d..10b0350c819747 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -530,7 +530,9 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) !s->running || (sd_status & SOF_HDA_CL_DMA_SD_INT_MASK) == 0) continue; +#ifdef USE_POS_BUF snd_pcm_period_elapsed(s->substream); +#endif } } diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 80ab906d60606b..76cb30123880ec 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -537,7 +537,9 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id) posn.host_posn, posn.dai_posn, posn.wallclock); memcpy(&spcm->stream[direction].posn, &posn, sizeof(posn)); +#ifndef USE_POS_BUF snd_pcm_period_elapsed(spcm->stream[direction].substream); +#endif } /* DSP notifies host of an XRUN within FW */ diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d4e21ae6911819..b9f155aa8b38f7 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -323,7 +323,6 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_sof_dev *sdev = snd_soc_platform_get_drvdata(rtd->platform); -#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA struct snd_sof_pcm *spcm = rtd->sof; snd_pcm_uframes_t host = 0, dai = 0; @@ -331,6 +330,12 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) if (rtd->dai_link->no_pcm) return 0; +#ifdef USE_POS_BUF + /* if have dsp ops pointer callback, use that directly */ + if (sdev->ops && sdev->ops->pcm_pointer) + return sdev->ops->pcm_pointer(sdev, substream); +#endif + /* read position from DSP */ host = bytes_to_frames(substream->runtime, spcm->stream[substream->stream].posn.host_posn); @@ -340,9 +345,6 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) dev_dbg(sdev->dev, "PCM: stream %d dir %d DMA position %lu DAI position %lu\n", spcm->pcm.pcm_id, substream->stream, host, dai); return host; -#else - return snd_sof_pcm_platform_pointer(sdev, substream); -#endif } static int sof_pcm_open(struct snd_pcm_substream *substream) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index ef177a886777df..d60269505da6cd 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -26,6 +26,8 @@ #include #include "../../pci/hda/hda_codec.h" +//#define USE_POS_BUF + /* debug flags */ #define SOF_DBG_REGS BIT(1) #define SOF_DBG_MBOX BIT(2) From 45b7db3780bc4c523347fd8538a7126c7c437c1e Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Thu, 23 Aug 2018 13:25:32 +0800 Subject: [PATCH 17/21] ALSA: HDA: Fix several mismatch for register mask and value E.g. for snd_hdac_ext_link_clear_stream_id(), we should set (1 << stream) as mask, and 0 as value, here correct it and several similar mismatches. And, here also remove unreadable register_mask usage for those mask value updating. Signed-off-by: Keyon Jie --- sound/hda/ext/hdac_ext_stream.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 1bd27576db98d5..a835558ddbc9b5 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -146,7 +146,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple); */ void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *stream) { - snd_hdac_updatel(stream->pplc_addr, AZX_REG_PPLCCTL, 0, AZX_PPLCCTL_RUN); + snd_hdac_updatel(stream->pplc_addr, AZX_REG_PPLCCTL, + AZX_PPLCCTL_RUN, AZX_PPLCCTL_RUN); } EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_start); @@ -171,7 +172,8 @@ void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *stream) snd_hdac_ext_link_stream_clear(stream); - snd_hdac_updatel(stream->pplc_addr, AZX_REG_PPLCCTL, 0, AZX_PPLCCTL_STRST); + snd_hdac_updatel(stream->pplc_addr, AZX_REG_PPLCCTL, + AZX_PPLCCTL_STRST, AZX_PPLCCTL_STRST); udelay(3); timeout = 50; do { @@ -242,7 +244,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_link_set_stream_id); void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link, int stream) { - snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, 0, (1 << stream)); + snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, (1 << stream), 0); } EXPORT_SYMBOL_GPL(snd_hdac_ext_link_clear_stream_id); @@ -415,7 +417,6 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *bus, bool enable, int index) { u32 mask = 0; - u32 register_mask = 0; if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL\n"); @@ -424,12 +425,8 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *bus, mask |= (1 << index); - register_mask = readl(bus->spbcap + AZX_REG_SPB_SPBFCCTL); - - mask |= register_mask; - if (enable) - snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, 0, mask); + snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, mask); else snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0); } @@ -503,7 +500,6 @@ void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus, bool enable, int index) { u32 mask = 0; - u32 register_mask = 0; if (!bus->drsmcap) { dev_err(bus->dev, "Address of DRSM capability is NULL\n"); @@ -512,12 +508,8 @@ void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus, mask |= (1 << index); - register_mask = readl(bus->drsmcap + AZX_REG_SPB_SPBFCCTL); - - mask |= register_mask; - if (enable) - snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, 0, mask); + snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, mask); else snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, 0); } From 71f91bb7eacc4a82c2367c369fad240d9767ffe3 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 24 Aug 2018 14:39:57 +0800 Subject: [PATCH 18/21] ASoC: SOF: hda-dai: add ops for hda link dais. Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda-dai.c | 184 ++++++++++++++++++++++++++++++++-- sound/soc/sof/intel/hda.h | 4 + 2 files changed, 179 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index d5067db0d9f5c6..1065f2cb294eac 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -9,12 +9,170 @@ */ #include +#include +#include #include "../sof-priv.h" #include "hda.h" #define SKL_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + +struct hda_pipe_params { + u8 host_dma_id; + u8 link_dma_id; + u32 ch; + u32 s_freq; + u32 s_fmt; + u8 linktype; + snd_pcm_format_t format; + int link_index; + int stream; + unsigned int host_bps; + unsigned int link_bps; +}; + +/* TODO: add hda dai params in tplg, and configure this in topology parsing */ +static int hda_link_dma_params(struct hdac_ext_stream *stream, + struct hda_pipe_params *params) +{ + struct hdac_stream *hstream = &stream->hstream; + struct hdac_bus *bus = hstream->bus; + unsigned int format_val; + struct hdac_ext_link *link; + + snd_hdac_ext_stream_decouple(bus, stream, true); + snd_hdac_ext_link_stream_reset(stream); + + format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch, + params->format, params->link_bps, 0); + + dev_dbg(bus->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_setup(stream, format_val); + + list_for_each_entry(link, &bus->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 hda_link_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct hdac_stream *hstream = substream->runtime->private_data; + struct hdac_bus *bus = hstream->bus; + struct hdac_ext_stream *link_dev; + struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct hda_pipe_params p_params = {0}; + struct hdac_ext_link *link; + int stream_tag; + + link_dev = snd_hdac_ext_stream_assign(bus, substream, + HDAC_EXT_STREAM_TYPE_LINK); + if (!link_dev) + return -EBUSY; + + snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); + + link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); + if (!link) + return -EINVAL; + + stream_tag = hdac_stream(link_dev)->stream_tag; + + /* set the stream tag in the codec dai dma params */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0); + else + snd_soc_dai_set_tdm_slot(codec_dai, 0, stream_tag, 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 = stream_tag - 1; + p_params.link_index = link->index; + p_params.format = params_format(params); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + p_params.link_bps = codec_dai->driver->playback.sig_bits; + else + p_params.link_bps = codec_dai->driver->capture.sig_bits; + + return hda_link_dma_params(link_dev, &p_params); +} + +static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct hdac_ext_stream *link_dev = + snd_soc_dai_get_dma_data(dai, substream); + struct hdac_stream *hstream = substream->runtime->private_data; + struct hdac_bus *bus = hstream->bus; + struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream); + + dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); + switch (cmd) { + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_hdac_ext_link_stream_start(link_dev); + break; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + snd_hdac_ext_link_stream_clear(link_dev); + if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) + snd_hdac_ext_stream_decouple(bus, stream, false); + break; + + default: + return -EINVAL; + } + return 0; +} + +static int hda_link_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct hdac_stream *hstream = substream->runtime->private_data; + struct hdac_bus *bus = hstream->bus; + struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct hdac_ext_stream *link_dev = + snd_soc_dai_get_dma_data(dai, substream); + struct hdac_ext_link *link; + + link = snd_hdac_ext_bus_get_link(bus, rtd->codec_dai->component->name); + if (!link) + return -EINVAL; + + snd_hdac_ext_link_clear_stream_id(link, + hdac_stream(link_dev)->stream_tag); + snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); + + link_dev->link_prepared = 0; + + return 0; +} + +static const struct snd_soc_dai_ops hda_link_dai_ops = { + .hw_params = hda_link_hw_params, + .hw_free = hda_link_hw_free, + .trigger = hda_link_pcm_trigger, +}; +#endif + /* * common dai driver for skl+ platforms. * some products who use this DAI array only physically have a subset of @@ -73,40 +231,48 @@ struct snd_soc_dai_driver skl_dai[] = { .capture = SOF_DAI_STREAM("DMIC16k Rx", 1, 4, SNDRV_PCM_RATE_16000, SKL_FORMATS), }, +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) { .name = "iDisp1 Pin", + .ops = &hda_link_dai_ops, .playback = SOF_DAI_STREAM("iDisp1 Tx", 1, 8, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), }, { .name = "iDisp2 Pin", + .ops = &hda_link_dai_ops, .playback = SOF_DAI_STREAM("iDisp2 Tx", 1, 8, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), }, { .name = "iDisp3 Pin", + .ops = &hda_link_dai_ops, .playback = SOF_DAI_STREAM("iDisp3 Tx", 1, 8, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), }, { - .name = "Analog Codec DAI", - .playback = SOF_DAI_STREAM("Analog Codec Playback", 1, 16, + .name = "Analog CPU DAI", + .ops = &hda_link_dai_ops, + .playback = SOF_DAI_STREAM("Analog CPU Playback", 1, 16, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), - .capture = SOF_DAI_STREAM("Analog Codec Capture", 1, 16, + .capture = SOF_DAI_STREAM("Analog CPU Capture", 1, 16, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), }, { - .name = "Digital Codec DAI", - .playback = SOF_DAI_STREAM("Digital Codec Playback", 1, 16, + .name = "Digital CPU DAI", + .ops = &hda_link_dai_ops, + .playback = SOF_DAI_STREAM("Digital CPU Playback", 1, 16, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), - .capture = SOF_DAI_STREAM("Digital Codec Capture", 1, 16, + .capture = SOF_DAI_STREAM("Digital CPU Capture", 1, 16, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), }, { - .name = "Alt Analog Codec DAI", - .playback = SOF_DAI_STREAM("Alt Analog Codec Playback", 1, 16, + .name = "Alt Analog CPU DAI", + .ops = &hda_link_dai_ops, + .playback = SOF_DAI_STREAM("Alt Analog CPU Playback", 1, 16, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), - .capture = SOF_DAI_STREAM("Alt Analog Codec Capture", 1, 16, + .capture = SOF_DAI_STREAM("Alt Analog CPU Capture", 1, 16, SNDRV_PCM_RATE_8000_192000, SKL_FORMATS), }, +#endif }; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index e5afdeb0726ca4..8c05e8fa778e58 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -314,7 +314,11 @@ (HDA_DSP_BDL_SIZE / sizeof(struct sof_intel_dsp_bdl)) /* Number of DAIs */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #define SOF_SKL_NUM_DAIS 14 +#else +#define SOF_SKL_NUM_DAIS 8 +#endif struct sof_intel_dsp_bdl { u32 addr_l; From 209d6f5a6ebd5e267e5acb66c5fdc528bfa3ed83 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 24 Aug 2018 19:54:13 +0800 Subject: [PATCH 19/21] debug: hack to use bxt_tdf8532 for leafhill hdmi debug Signed-off-by: Keyon Jie --- sound/Makefile | 2 +- sound/soc/intel/boards/bxt_tdf8532.c | 23 ++++++++++++------- .../intel/common/soc-acpi-intel-bxt-match.c | 7 ++++-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/sound/Makefile b/sound/Makefile index 99d8c31262c8fc..3a37ffbb755f91 100644 --- a/sound/Makefile +++ b/sound/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for the Linux sound card driver # - +export KBUILD_CFLAGS += -DDEBUG obj-$(CONFIG_SOUND) += soundcore.o obj-$(CONFIG_DMASOUND) += oss/dmasound/ obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ diff --git a/sound/soc/intel/boards/bxt_tdf8532.c b/sound/soc/intel/boards/bxt_tdf8532.c index e70b0ab93624d5..21e5b9d82ab684 100644 --- a/sound/soc/intel/boards/bxt_tdf8532.c +++ b/sound/soc/intel/boards/bxt_tdf8532.c @@ -42,7 +42,8 @@ static const struct snd_soc_dapm_widget broxton_tdf8532_widgets[] = { }; static const struct snd_soc_dapm_route broxton_tdf8532_map[] = { -#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA +//#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA +#if 1 /* Speaker BE connections */ { "Speaker", NULL, "ssp4 Tx"}, { "ssp4 Tx", NULL, "codec0_out"}, @@ -80,7 +81,7 @@ static const struct snd_soc_dapm_route broxton_tdf8532_map[] = { { "ModemUl", NULL, "ssp3 Tx"}, { "ssp3 Tx", NULL, "Modem_ssp3_out"}, -#else +//#else { "hifi3", NULL, "iDisp3 Tx"}, { "hifi2", NULL, "iDisp2 Tx"}, { "hifi1", NULL, "iDisp1 Tx"}, @@ -158,7 +159,8 @@ static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) /* broxton digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { -#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA +//#ifndef CONFIG_SND_SOC_SOF_FORCE_LEGACY_HDA +#if 0 /* Probe DAI links*/ { .name = "Bxt Compress Probe playback", @@ -263,8 +265,10 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { .name = "SSP4-Codec", .id = 4, .cpu_dai_name = "SSP4 Pin", - .codec_name = "i2c-INT34C3:00", - .codec_dai_name = "tdf8532-hifi", +// .codec_name = "i2c-INT34C3:00", +// .codec_dai_name = "tdf8532-hifi", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", .platform_name = "0000:00:0e.0", .ignore_suspend = 1, .dpcm_playback = 1, @@ -290,6 +294,7 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi1", .platform_name = "0000:00:0e.0", + .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, }, @@ -300,6 +305,7 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi2", .platform_name = "0000:00:0e.0", + .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, }, @@ -310,6 +316,7 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi3", .platform_name = "0000:00:0e.0", + .init = broxton_hdmi_init, .dpcm_playback = 1, .no_pcm = 1, }, @@ -317,7 +324,7 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { /* Back End DAI links */ { .name = "iDisp1", - .id = 0, + .id = 6, .cpu_dai_name = "iDisp1 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi1", @@ -328,7 +335,7 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { }, { .name = "iDisp2", - .id = 1, + .id = 7, .cpu_dai_name = "iDisp2 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi2", @@ -339,7 +346,7 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = { }, { .name = "iDisp3", - .id = 2, + .id = 8, .cpu_dai_name = "iDisp3 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi3", diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index 333ae36f3fb06e..0923e78f7f5978 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c @@ -17,8 +17,11 @@ static struct snd_soc_acpi_codecs bxt_codecs = { struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = { { .id = "INT343A", - .drv_name = "bxt_alc298s_i2s", - .fw_filename = "intel/dsp_fw_bxtn.bin", +// .drv_name = "bxt_alc298s_i2s", +// .fw_filename = "intel/dsp_fw_bxtn.bin", + .drv_name = "bxt_tdf8532", + .sof_fw_filename = "intel/sof-apl.ri", + .sof_tplg_filename = "intel/sof-apl-tdf8532.tplg", }, { .id = "DLGS7219", From 599324c567e6a8b90337bd39a59c4a88def4edbc Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 27 Aug 2018 18:29:03 +0800 Subject: [PATCH 20/21] ASoC: SOF: hda: replace registers rw with io_ops Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda-stream.c | 45 ++++++++++++-------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 10b0350c819747..668b87d5f99b14 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -464,16 +464,15 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) { - struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; - struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_bus *bus = (struct hdac_bus *)context; u32 status; - if (!pm_runtime_active(sdev->dev)) + if (!pm_runtime_active(bus->dev)) return IRQ_NONE; spin_lock(&bus->reg_lock); - status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS); + status = snd_hdac_chip_readl(bus, INTSTS); if (status == 0 || status == 0xffffffff) { spin_unlock(&bus->reg_lock); return IRQ_NONE; @@ -481,54 +480,40 @@ irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* clear rirb int */ - status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_RIRBSTS); + status = snd_hdac_chip_readb(bus, RIRBSTS); if (status & RIRB_INT_MASK) { if (status & RIRB_INT_RESPONSE) snd_hdac_bus_update_rirb(bus); - snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_RIRBSTS, - RIRB_INT_MASK); + snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); } #endif spin_unlock(&bus->reg_lock); - return snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS) - & SOF_HDA_INT_ALL_STREAM ? IRQ_WAKE_THREAD : IRQ_HANDLED; + return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED; } irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) { - struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; - struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_bus *bus = (struct hdac_bus *)context; struct hdac_stream *s; - int sd_offset; - //struct sof_intel_hda_dev *hdev = sdev->hda; - u32 status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS); + u32 status = snd_hdac_chip_readl(bus, INTSTS); u32 sd_status; /* check streams */ list_for_each_entry(s, &bus->stream_list, list) { if (status & (1 << s->index) - && !s->opened) { - sd_offset = SOF_STREAM_SD_OFFSET(s); - sd_status = - snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS) & - 0xff; - - dev_dbg(sdev->dev, "stream %d status 0x%x\n", + && s->opened) { + sd_status = snd_hdac_stream_readb(s, SD_STS); + + dev_dbg(bus->dev, "stream %d status 0x%x\n", s->index, sd_status); - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS, - SOF_HDA_CL_DMA_SD_INT_MASK, - SOF_HDA_CL_DMA_SD_INT_MASK); + snd_hdac_stream_writeb(s, SD_STS, SD_INT_MASK); if (!s->substream || !s->running || - (sd_status & SOF_HDA_CL_DMA_SD_INT_MASK) == 0) + (sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0) continue; #ifdef USE_POS_BUF snd_pcm_period_elapsed(s->substream); @@ -631,6 +616,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) hstream = &stream->hstream; hstream->bus = bus; + hstream->sd_int_sta_mask = 1 << i; hstream->index = i; sd_offset = SOF_STREAM_SD_OFFSET(hstream); hstream->sd_addr = sdev->bar[HDA_DSP_HDA_BAR] + sd_offset; @@ -689,6 +675,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) hstream = &stream->hstream; hstream->bus = bus; + hstream->sd_int_sta_mask = 1 << i; hstream->index = i; sd_offset = SOF_STREAM_SD_OFFSET(hstream); hstream->sd_addr = sdev->bar[HDA_DSP_HDA_BAR] + sd_offset; From 992fb07d2a74884a90f56932655634adc4dc0b42 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 27 Aug 2018 18:34:56 +0800 Subject: [PATCH 21/21] ASoC: SOF: hda: request hda irq with different dev_id Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index a0c28d7c49d137..dfab9a2a1b77ba 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -545,10 +545,11 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->ipc_irq = sdev->hda->irq; } + bus = sof_to_bus(sdev); dev_dbg(sdev->dev, "using HDA IRQ %d\n", sdev->hda->irq); ret = request_threaded_irq(sdev->hda->irq, hda_dsp_stream_interrupt, hda_dsp_stream_threaded_handler, - IRQF_SHARED, "AudioHDA", sdev); + IRQF_SHARED, "AudioHDA", bus); if (ret < 0) { dev_err(sdev->dev, "error: failed to register HDA IRQ %d\n", sdev->hda->irq); @@ -590,7 +591,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) } /* clear stream status */ - bus = sof_to_bus(sdev); list_for_each_entry(stream, &bus->stream_list, list) { sd_offset = SOF_STREAM_SD_OFFSET(stream); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -638,7 +638,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) free_ipc_irq: free_irq(sdev->ipc_irq, sdev); free_hda_irq: - free_irq(sdev->hda->irq, sdev); + free_irq(sdev->hda->irq, bus); pci_free_irq_vectors(pci); free_streams: hda_dsp_stream_free(sdev); @@ -651,6 +651,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) int hda_dsp_remove(struct snd_sof_dev *sdev) { + struct hdac_bus *bus = sof_to_bus(sdev); struct pci_dev *pci = sdev->pci; const struct sof_intel_dsp_desc *chip = sdev->hda->desc; @@ -671,7 +672,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) SOF_HDA_PPCTL_GPROCEN, 0); free_irq(sdev->ipc_irq, sdev); - free_irq(sdev->pci->irq, sdev); + free_irq(sdev->pci->irq, bus); pci_free_irq_vectors(pci); hda_dsp_stream_free(sdev);