From 179d5811c2fcadf3f07032bb76ed47c59b91ce1d Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 26 Nov 2019 08:53:02 -0600 Subject: ASoC: SOF: Intel: make common HDMI driver default Use the common HDMI driver by default if the codec driver is selected in kernel build. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191126145304.24204-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index cc09bb606f7d..56a837d2cb95 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -319,6 +319,7 @@ config SND_SOC_SOF_HDA_COMMON_HDMI_CODEC bool "SOF common HDA HDMI codec driver" depends on SND_SOC_SOF_HDA_LINK depends on SND_HDA_CODEC_HDMI + default SND_HDA_CODEC_HDMI help This adds support for HDMI audio by using the common HDA HDMI/DisplayPort codec driver. -- cgit v1.2.3 From 7c11af9fcdc425b80f140a218d4fef9f17734bfc Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 4 Dec 2019 15:28:59 -0600 Subject: ASoC: SOF: Intel: hda: solve MSI issues by merging ipc and stream irq handlers The existing code uses two handlers for a shared edge-based MSI interrupts. In corner cases, interrupts are lost, leading to IPC timeouts. Those timeouts do not appear in legacy mode. This patch merges the two handlers and threads into a single one, and simplifies the mask/unmask operations by using a single top-level mask (Global Interrupt Enable). The handler only checks for interrupt sources using the Global Interrupt Status (GIS) field, and all the actual work happens in the thread. This also enables us to remove the use of spin locks. Stream events are prioritized over IPC ones. This patch was tested with HDaudio and SoundWire platforms, and all known IPC timeout issues are solved in MSI mode. The SoundWire-specific patches will be provided in follow-up patches, where the SoundWire interrupts are handled in the same thread as IPC and stream interrupts. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204212859.13239-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 1 - sound/soc/sof/intel/cnl.c | 5 --- sound/soc/sof/intel/hda-ipc.c | 23 +++----------- sound/soc/sof/intel/hda-stream.c | 20 ++++++------ sound/soc/sof/intel/hda.c | 69 ++++++++++++++++++++++++++++------------ sound/soc/sof/intel/hda.h | 11 ++++--- 6 files changed, 70 insertions(+), 59 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 7daa8eb456c8..6f45e14f2b2e 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -41,7 +41,6 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .block_write = sof_block_write, /* doorbell */ - .irq_handler = hda_dsp_ipc_irq_handler, .irq_thread = hda_dsp_ipc_irq_thread, /* ipc */ diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 0e1e265f3f3b..9bd169e2691e 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -106,10 +106,6 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) "nothing to do in IPC IRQ thread\n"); } - /* re-enable IPC interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, - HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); - return IRQ_HANDLED; } @@ -231,7 +227,6 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .block_write = sof_block_write, /* doorbell */ - .irq_handler = hda_dsp_ipc_irq_handler, .irq_thread = cnl_ipc_irq_thread, /* ipc */ diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 0fd2153c1769..1837f66e361f 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -230,22 +230,15 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) "nothing to do in IPC IRQ thread\n"); } - /* re-enable IPC interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, - HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); - return IRQ_HANDLED; } -/* is this IRQ for ADSP ? - we only care about IPC here */ -irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context) +/* Check if an IPC IRQ occurred */ +bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev) { - struct snd_sof_dev *sdev = context; - int ret = IRQ_NONE; + bool ret = false; u32 irq_status; - spin_lock(&sdev->hw_lock); - /* store status */ irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); dev_vdbg(sdev->dev, "irq handler: irq_status:0x%x\n", irq_status); @@ -255,16 +248,10 @@ irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context) goto out; /* IPC message ? */ - if (irq_status & HDA_DSP_ADSPIS_IPC) { - /* disable IPC interrupt */ - snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, - HDA_DSP_REG_ADSPIC, - HDA_DSP_ADSPIC_IPC, 0); - ret = IRQ_WAKE_THREAD; - } + if (irq_status & HDA_DSP_ADSPIS_IPC) + ret = true; out: - spin_unlock(&sdev->hw_lock); return ret; } diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 29ab43281670..927a36f92c24 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -549,22 +549,23 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, return 0; } -irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) +bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev) { - struct hdac_bus *bus = context; - int ret = IRQ_WAKE_THREAD; + struct hdac_bus *bus = sof_to_bus(sdev); + bool ret = false; u32 status; - spin_lock(&bus->reg_lock); + /* The function can be called at irq thread, so use spin_lock_irq */ + spin_lock_irq(&bus->reg_lock); status = snd_hdac_chip_readl(bus, INTSTS); dev_vdbg(bus->dev, "stream irq, INTSTS status: 0x%x\n", status); - /* Register inaccessible, ignore it.*/ - if (status == 0xffffffff) - ret = IRQ_NONE; + /* if Register inaccessible, ignore it.*/ + if (status != 0xffffffff) + ret = true; - spin_unlock(&bus->reg_lock); + spin_unlock_irq(&bus->reg_lock); return ret; } @@ -602,7 +603,8 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) { - struct hdac_bus *bus = context; + struct snd_sof_dev *sdev = context; + struct hdac_bus *bus = sof_to_bus(sdev); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) u32 rirb_status; #endif diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 91bd88fddac7..4596239c63d8 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -499,6 +499,49 @@ static const struct sof_intel_dsp_desc return chip_info; } +static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context) +{ + struct snd_sof_dev *sdev = context; + + /* + * Get global interrupt status. It includes all hardware interrupt + * sources in the Intel HD Audio controller. + */ + if (snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS) & + SOF_HDA_INTSTS_GIS) { + + /* disable GIE interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_INTCTL, + SOF_HDA_INT_GLOBAL_EN, + 0); + + return IRQ_WAKE_THREAD; + } + + return IRQ_NONE; +} + +static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context) +{ + struct snd_sof_dev *sdev = context; + + /* deal with streams and controller first */ + if (hda_dsp_check_stream_irq(sdev)) + hda_dsp_stream_threaded_handler(irq, sdev); + + if (hda_dsp_check_ipc_irq(sdev)) + sof_ops(sdev)->irq_thread(irq, sdev); + + /* enable GIE interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_INTCTL, + SOF_HDA_INT_GLOBAL_EN, + SOF_HDA_INT_GLOBAL_EN); + + return IRQ_HANDLED; +} + int hda_dsp_probe(struct snd_sof_dev *sdev) { struct pci_dev *pci = to_pci_dev(sdev->dev); @@ -603,9 +646,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) */ if (hda_use_msi && pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) > 0) { dev_info(sdev->dev, "use msi interrupt mode\n"); - hdev->irq = pci_irq_vector(pci, 0); - /* ipc irq number is the same of hda irq */ - sdev->ipc_irq = hdev->irq; + sdev->ipc_irq = pci_irq_vector(pci, 0); /* initialised to "false" by kzalloc() */ sdev->msi_enabled = true; } @@ -616,28 +657,17 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * in IO-APIC mode, hda->irq and ipc_irq are using the same * irq number of pci->irq */ - hdev->irq = pci->irq; sdev->ipc_irq = pci->irq; } - dev_dbg(sdev->dev, "using HDA IRQ %d\n", hdev->irq); - ret = request_threaded_irq(hdev->irq, hda_dsp_stream_interrupt, - hda_dsp_stream_threaded_handler, - IRQF_SHARED, "AudioHDA", bus); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to register HDA IRQ %d\n", - hdev->irq); - goto free_irq_vector; - } - dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq); - ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_ipc_irq_handler, - sof_ops(sdev)->irq_thread, IRQF_SHARED, - "AudioDSP", sdev); + ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_interrupt_handler, + hda_dsp_interrupt_thread, + IRQF_SHARED, "AudioDSP", sdev); if (ret < 0) { dev_err(sdev->dev, "error: failed to register IPC IRQ %d\n", sdev->ipc_irq); - goto free_hda_irq; + goto free_irq_vector; } pci_set_master(pci); @@ -668,8 +698,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) free_ipc_irq: free_irq(sdev->ipc_irq, sdev); -free_hda_irq: - free_irq(hdev->irq, bus); free_irq_vector: if (sdev->msi_enabled) pci_free_irq_vectors(pci); @@ -715,7 +743,6 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) SOF_HDA_PPCTL_GPROCEN, 0); free_irq(sdev->ipc_irq, sdev); - free_irq(hda->irq, bus); if (sdev->msi_enabled) pci_free_irq_vectors(pci); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 18d7e72bf9b7..63df888dddb6 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -43,11 +43,14 @@ /* SOF_HDA_GCTL register bist */ #define SOF_HDA_GCTL_RESET BIT(0) -/* SOF_HDA_INCTL and SOF_HDA_INTSTS regs */ +/* SOF_HDA_INCTL regs */ #define SOF_HDA_INT_GLOBAL_EN BIT(31) #define SOF_HDA_INT_CTRL_EN BIT(30) #define SOF_HDA_INT_ALL_STREAM 0xff +/* SOF_HDA_INTSTS regs */ +#define SOF_HDA_INTSTS_GIS BIT(31) + #define SOF_HDA_MAX_CAPS 10 #define SOF_HDA_CAP_ID_OFF 16 #define SOF_HDA_CAP_ID_MASK GENMASK(SOF_HDA_CAP_ID_OFF + 11,\ @@ -406,8 +409,6 @@ struct sof_intel_hda_dev { /* the maximum number of streams (playback + capture) supported */ u32 stream_max; - int irq; - /* PM related */ bool l1_support_changed;/* during suspend, is L1SEN changed or not */ @@ -511,11 +512,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params); int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream, int cmd); -irqreturn_t hda_dsp_stream_interrupt(int irq, void *context); irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context); int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, struct hdac_stream *stream); +bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev); +bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev); struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction); @@ -540,7 +542,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev); int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev); int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id); -irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context); irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); -- cgit v1.2.3 From 8cd9956f61c65022209ce6d1e55ed12aea12357d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 4 Dec 2019 15:15:44 -0600 Subject: ASoC: intel/skl/hda - export number of digital microphones via control components It is required for the auto-detection in the user space (for UCM). Signed-off-by: Jaroslav Kysela Signed-off-by: Pierre-Louis Bossart Cc: Mark Brown Link: https://lore.kernel.org/r/20191204211556.12671-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_generic.c | 8 ++++++++ sound/soc/sof/intel/hda.c | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 4e45901e3a2f..11eaee9ae41f 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -100,6 +100,8 @@ static struct snd_soc_card hda_soc_card = { .late_probe = skl_hda_card_late_probe, }; +static char hda_soc_components[30]; + #define IDISP_DAI_COUNT 3 #define HDAC_DAI_COUNT 2 #define DMIC_DAI_COUNT 2 @@ -183,6 +185,12 @@ static int skl_hda_audio_probe(struct platform_device *pdev) hda_soc_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&hda_soc_card, ctx); + if (mach->mach_params.dmic_num > 0) { + snprintf(hda_soc_components, sizeof(hda_soc_components), + "cfg-dmics:%d", mach->mach_params.dmic_num); + hda_soc_card.components = hda_soc_components; + } + return devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); } diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 4596239c63d8..98512a338748 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -351,7 +351,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) const char *tplg_filename; const char *idisp_str; const char *dmic_str; - int dmic_num; + int dmic_num = 0; int codec_num = 0; int i; #endif @@ -472,6 +472,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) mach_params->codec_mask = bus->codec_mask; mach_params->platform = dev_name(sdev->dev); mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi; + mach_params->dmic_num = dmic_num; } /* create codec instances */ -- cgit v1.2.3 From 78fd4ffd75eed354c1c8b567dd0b384053c933da Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:47 -0600 Subject: ASoC: SOF: topology: remove snd_sof_init_topology() Remove snd_sof_init_topology() as it is never used. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 2 -- sound/soc/sof/topology.c | 9 --------- 2 files changed, 11 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index c7c2c70ee4d0..31f0eb31598a 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -585,8 +585,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_ipc *ipc, * There is no snd_sof_free_topology since topology components will * be freed by snd_soc_unregister_component, */ -int snd_sof_init_topology(struct snd_sof_dev *sdev, - struct snd_soc_tplg_ops *ops); int snd_sof_load_topology(struct snd_sof_dev *sdev, const char *file); int snd_sof_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index d82ab981e840..b8701d3407ad 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3463,15 +3463,6 @@ static struct snd_soc_tplg_ops sof_tplg_ops = { .bytes_ext_ops_count = ARRAY_SIZE(sof_bytes_ext_ops), }; -int snd_sof_init_topology(struct snd_sof_dev *sdev, - struct snd_soc_tplg_ops *ops) -{ - /* TODO: support linked list of topologies */ - sdev->tplg_ops = ops; - return 0; -} -EXPORT_SYMBOL(snd_sof_init_topology); - int snd_sof_load_topology(struct snd_sof_dev *sdev, const char *file) { const struct firmware *fw; -- cgit v1.2.3 From 3e62579436c6a7fc35de7318e6c5f495b8d0046c Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:48 -0600 Subject: ASoC: SOF: core: modify the signature for snd_sof_create_page_table Modify the signature for snd_sof_create_page_table to take struct device pointer as an argument instead of struct snd_sof_dev as this will be used by both the SOF core device and its clients. Also, move the definition out of core.c to utils.c. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 59 ----------------------------------------------- sound/soc/sof/pcm.c | 2 +- sound/soc/sof/sof-priv.h | 2 +- sound/soc/sof/trace.c | 4 ++-- sound/soc/sof/utils.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 63 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 805918d3bcc0..6a7f342203e9 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include "sof-priv.h" @@ -213,64 +212,6 @@ out: } EXPORT_SYMBOL(snd_sof_get_status); -/* - * Generic buffer page table creation. - * Take the each physical page address and drop the least significant unused - * bits from each (based on PAGE_SIZE). Then pack valid page address bits - * into compressed page table. - */ - -int snd_sof_create_page_table(struct snd_sof_dev *sdev, - struct snd_dma_buffer *dmab, - unsigned char *page_table, size_t size) -{ - int i, pages; - - pages = snd_sgbuf_aligned_pages(size); - - dev_dbg(sdev->dev, "generating page table for %p size 0x%zx pages %d\n", - dmab->area, size, pages); - - for (i = 0; i < pages; i++) { - /* - * The number of valid address bits for each page is 20. - * idx determines the byte position within page_table - * where the current page's address is stored - * in the compressed page_table. - * This can be calculated by multiplying the page number by 2.5. - */ - u32 idx = (5 * i) >> 1; - u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT; - u8 *pg_table; - - dev_vdbg(sdev->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn); - - pg_table = (u8 *)(page_table + idx); - - /* - * pagetable compression: - * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 - * ___________pfn 0__________ __________pfn 1___________ _pfn 2... - * .... .... .... .... .... .... .... .... .... .... .... - * It is created by: - * 1. set current location to 0, PFN index i to 0 - * 2. put pfn[i] at current location in Little Endian byte order - * 3. calculate an intermediate value as - * x = (pfn[i+1] << 4) | (pfn[i] & 0xf) - * 4. put x at offset (current location + 2) in LE byte order - * 5. increment current location by 5 bytes, increment i by 2 - * 6. continue to (2) - */ - if (i & 1) - put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4, - pg_table); - else - put_unaligned_le32(pfn, pg_table); - } - - return pages; -} - /* * SOF Driver enumeration. */ diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 549238a98b2a..9fd73ef08904 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -33,7 +33,7 @@ static int create_page_table(struct snd_soc_component *component, if (!spcm) return -EINVAL; - return snd_sof_create_page_table(sdev, dmab, + return snd_sof_create_page_table(sdev->dev, dmab, spcm->stream[stream].page_table.area, size); } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 31f0eb31598a..18dd832f2053 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -499,7 +499,7 @@ int snd_sof_set_d0_substate(struct snd_sof_dev *sdev, void snd_sof_new_platform_drv(struct snd_sof_dev *sdev); -int snd_sof_create_page_table(struct snd_sof_dev *sdev, +int snd_sof_create_page_table(struct device *dev, struct snd_dma_buffer *dmab, unsigned char *page_table, size_t size); diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index b0e4556c8536..4bb65030819d 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -250,8 +250,8 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev) } /* create compressed page table for audio firmware */ - ret = snd_sof_create_page_table(sdev, &sdev->dmatb, sdev->dmatp.area, - sdev->dmatb.bytes); + ret = snd_sof_create_page_table(sdev->dev, &sdev->dmatb, + sdev->dmatp.area, sdev->dmatb.bytes); if (ret < 0) goto table_err; diff --git a/sound/soc/sof/utils.c b/sound/soc/sof/utils.c index 2ac4c3da0320..9831eb57df6c 100644 --- a/sound/soc/sof/utils.c +++ b/sound/soc/sof/utils.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include "sof-priv.h" @@ -110,3 +111,62 @@ void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest, memcpy_fromio(dest, src, size); } EXPORT_SYMBOL(sof_block_read); + +/* + * Generic buffer page table creation. + * Take the each physical page address and drop the least significant unused + * bits from each (based on PAGE_SIZE). Then pack valid page address bits + * into compressed page table. + */ + +int snd_sof_create_page_table(struct device *dev, + struct snd_dma_buffer *dmab, + unsigned char *page_table, size_t size) +{ + int i, pages; + + pages = snd_sgbuf_aligned_pages(size); + + dev_dbg(dev, "generating page table for %p size 0x%zx pages %d\n", + dmab->area, size, pages); + + for (i = 0; i < pages; i++) { + /* + * The number of valid address bits for each page is 20. + * idx determines the byte position within page_table + * where the current page's address is stored + * in the compressed page_table. + * This can be calculated by multiplying the page number by 2.5. + */ + u32 idx = (5 * i) >> 1; + u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT; + u8 *pg_table; + + dev_vdbg(dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn); + + pg_table = (u8 *)(page_table + idx); + + /* + * pagetable compression: + * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 + * ___________pfn 0__________ __________pfn 1___________ _pfn 2... + * .... .... .... .... .... .... .... .... .... .... .... + * It is created by: + * 1. set current location to 0, PFN index i to 0 + * 2. put pfn[i] at current location in Little Endian byte order + * 3. calculate an intermediate value as + * x = (pfn[i+1] << 4) | (pfn[i] & 0xf) + * 4. put x at offset (current location + 2) in LE byte order + * 5. increment current location by 5 bytes, increment i by 2 + * 6. continue to (2) + */ + if (i & 1) + put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4, + pg_table); + else + put_unaligned_le32(pfn, pg_table); + } + + return pages; +} +EXPORT_SYMBOL(snd_sof_create_page_table); -- cgit v1.2.3 From 8c583f526ee9df5c6693f54ac272b7e103b5f1d2 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:49 -0600 Subject: ASoC: SOF: core: move check for runtime callbacks to core For some platforms, the refcount is explicitly incremented to prevent it from entering runtime suspend. This should be be done during probe in the core instead of being done in the PCM driver. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 8 ++++++++ sound/soc/sof/pcm.c | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 6a7f342203e9..d8446fb9fdde 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -355,6 +355,14 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "created machine %s\n", dev_name(&plat_data->pdev_mach->dev)); + /* + * Some platforms in SOF, ex: BYT, may not have their platform PM + * callbacks set. Increment the usage count so as to + * prevent the device from entering runtime suspend. + */ + if (!sof_ops(sdev)->runtime_suspend || !sof_ops(sdev)->runtime_resume) + pm_runtime_get_noresume(sdev->dev); + if (plat_data->sof_probe_complete) plat_data->sof_probe_complete(sdev->dev); diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 9fd73ef08904..a9c47f6bf657 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -741,14 +741,6 @@ static int sof_pcm_probe(struct snd_soc_component *component) return ret; } - /* - * Some platforms in SOF, ex: BYT, may not have their platform PM - * callbacks set. Increment the usage count so as to - * prevent the device from entering runtime suspend. - */ - if (!sof_ops(sdev)->runtime_suspend || !sof_ops(sdev)->runtime_resume) - pm_runtime_get_noresume(sdev->dev); - return ret; } -- cgit v1.2.3 From 03eec9b4eb897dde5985579508c978e7a29052bd Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:50 -0600 Subject: ASoC: SOF: Introduce default_fw_filename member in sof_dev_desc Currently the FW filename is obtained from the ACPI matching table when determining which machine driver to use. In preparation for making the machine driver ACPI match optional for Device Tree platforms and moving the machine driver selection out of the SOF core, this patch introduces the default_fw_filename member in struct sof_dev_desc. Once the machine driver selection is moved out of SOF core, the nocodec_fw_filename will become obsolete and will be removed. Signed-off-by: Ranjani Sridharan Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 3 +++ sound/soc/sof/sof-acpi-dev.c | 5 +++++ sound/soc/sof/sof-of-dev.c | 1 + sound/soc/sof/sof-pci-dev.c | 9 +++++++++ 4 files changed, 18 insertions(+) (limited to 'sound/soc/sof') diff --git a/include/sound/sof.h b/include/sound/sof.h index 479101736ee0..1723478db4a2 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -91,6 +91,9 @@ struct sof_dev_desc { const char *default_fw_path; const char *default_tplg_path; + /* default firmware name */ + const char *default_fw_filename; + const struct snd_sof_dsp_ops *ops; const struct sof_arch_ops *arch_ops; }; diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index df318f50dd0b..22e13ef09811 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -45,6 +45,7 @@ static const struct sof_dev_desc sof_acpi_haswell_desc = { .chip_info = &hsw_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-hsw.ri", .nocodec_fw_filename = "sof-hsw.ri", .nocodec_tplg_filename = "sof-hsw-nocodec.tplg", .ops = &sof_hsw_ops, @@ -62,6 +63,7 @@ static const struct sof_dev_desc sof_acpi_broadwell_desc = { .chip_info = &bdw_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-bdw.ri", .nocodec_fw_filename = "sof-bdw.ri", .nocodec_tplg_filename = "sof-bdw-nocodec.tplg", .ops = &sof_bdw_ops, @@ -81,6 +83,7 @@ static const struct sof_dev_desc sof_acpi_baytrailcr_desc = { .chip_info = &byt_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-byt.ri", .nocodec_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt-nocodec.tplg", .ops = &sof_byt_ops, @@ -96,6 +99,7 @@ static const struct sof_dev_desc sof_acpi_baytrail_desc = { .chip_info = &byt_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-byt.ri", .nocodec_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt-nocodec.tplg", .ops = &sof_byt_ops, @@ -111,6 +115,7 @@ static const struct sof_dev_desc sof_acpi_cherrytrail_desc = { .chip_info = &cht_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-cht.ri", .nocodec_fw_filename = "sof-cht.ri", .nocodec_tplg_filename = "sof-cht-nocodec.tplg", .ops = &sof_cht_ops, diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 28a9692974e5..81deb5582d77 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -19,6 +19,7 @@ extern struct snd_sof_dsp_ops sof_imx8_ops; static struct sof_dev_desc sof_of_imx8qxp_desc = { .default_fw_path = "imx/sof", .default_tplg_path = "imx/sof-tplg", + .default_fw_filename = "sof-imx8.ri", .nocodec_fw_filename = "sof-imx8.ri", .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", .ops = &sof_imx8_ops, diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index bbeffd932de7..046bd57657ca 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -47,6 +47,7 @@ static const struct sof_dev_desc bxt_desc = { .chip_info = &apl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-apl.ri", .nocodec_fw_filename = "sof-apl.ri", .nocodec_tplg_filename = "sof-apl-nocodec.tplg", .ops = &sof_apl_ops, @@ -65,6 +66,7 @@ static const struct sof_dev_desc glk_desc = { .chip_info = &apl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-glk.ri", .nocodec_fw_filename = "sof-glk.ri", .nocodec_tplg_filename = "sof-glk-nocodec.tplg", .ops = &sof_apl_ops, @@ -93,6 +95,7 @@ static const struct sof_dev_desc tng_desc = { .chip_info = &tng_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-byt.ri", .nocodec_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt.tplg", .ops = &sof_tng_ops, @@ -111,6 +114,7 @@ static const struct sof_dev_desc cnl_desc = { .chip_info = &cnl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-cnl.ri", .nocodec_fw_filename = "sof-cnl.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, @@ -129,6 +133,7 @@ static const struct sof_dev_desc cfl_desc = { .chip_info = &cnl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-cfl.ri", .nocodec_fw_filename = "sof-cfl.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, @@ -149,6 +154,7 @@ static const struct sof_dev_desc cml_desc = { .chip_info = &cnl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-cml.ri", .nocodec_fw_filename = "sof-cml.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, @@ -167,6 +173,7 @@ static const struct sof_dev_desc icl_desc = { .chip_info = &icl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-icl.ri", .nocodec_fw_filename = "sof-icl.ri", .nocodec_tplg_filename = "sof-icl-nocodec.tplg", .ops = &sof_cnl_ops, @@ -185,6 +192,7 @@ static const struct sof_dev_desc tgl_desc = { .chip_info = &tgl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-tgl.ri", .nocodec_fw_filename = "sof-tgl.ri", .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", .ops = &sof_cnl_ops, @@ -203,6 +211,7 @@ static const struct sof_dev_desc ehl_desc = { .chip_info = &ehl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-ehl.ri", .nocodec_fw_filename = "sof-ehl.ri", .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", .ops = &sof_cnl_ops, -- cgit v1.2.3 From ee1e79b72e3cf5eac42ba9de827536f91d4c04e2 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:51 -0600 Subject: ASoC: SOF: partition audio-related parts from SOF core Move all the audio-specific code in the core, audio-specific logic in the top-level PM callbacks and the core header files into a separate file (sof-audio.*) in preparation for adding an audio client device. In the process of moving all structure definitions for widget, routes, pcm's etc, the snd_sof_dev member in all these structs is replaced with the snd_soc_component member. Also, use the component device instead of the snd_sof_dev device wherever possible in the PCM component driver, control IO functions and the topology parser as the component device will be moved over to the client device later on. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Makefile | 2 +- sound/soc/sof/control.c | 55 +++--- sound/soc/sof/core.c | 120 ------------- sound/soc/sof/intel/hda-dai.c | 1 + sound/soc/sof/intel/hda-pcm.c | 4 +- sound/soc/sof/intel/hda-stream.c | 1 + sound/soc/sof/ipc.c | 16 +- sound/soc/sof/pcm.c | 123 ++++++------- sound/soc/sof/pm.c | 219 +---------------------- sound/soc/sof/sof-audio.c | 362 ++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.h | 207 ++++++++++++++++++++++ sound/soc/sof/sof-priv.h | 187 -------------------- sound/soc/sof/topology.c | 365 +++++++++++++++++++-------------------- 13 files changed, 861 insertions(+), 801 deletions(-) create mode 100644 sound/soc/sof/sof-audio.c create mode 100644 sound/soc/sof/sof-audio.h (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index b0a6f01bdc44..0a8bc72c28a5 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ - control.o trace.o utils.o + control.o trace.o utils.o sof-audio.o snd-sof-pci-objs := sof-pci-dev.o snd-sof-acpi-objs := sof-acpi-dev.o diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 7baf7f1507c3..dfc412e2d956 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -13,6 +13,7 @@ #include #include #include "sof-priv.h" +#include "sof-audio.h" static void update_mute_led(struct snd_sof_control *scontrol, struct snd_kcontrol *kcontrol, @@ -88,7 +89,7 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; bool change = false; @@ -104,8 +105,8 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, } /* notify DSP of mixer updates */ - if (pm_runtime_active(sdev->dev)) - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + if (pm_runtime_active(scomp->dev)) + snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_SET_VALUE, SOF_CTRL_TYPE_VALUE_CHAN_GET, SOF_CTRL_CMD_VOLUME, @@ -135,7 +136,7 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; bool change = false; @@ -153,8 +154,8 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, update_mute_led(scontrol, kcontrol, ucontrol); /* notify DSP of mixer updates */ - if (pm_runtime_active(sdev->dev)) - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + if (pm_runtime_active(scomp->dev)) + snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_SET_VALUE, SOF_CTRL_TYPE_VALUE_CHAN_GET, SOF_CTRL_CMD_SWITCH, @@ -185,7 +186,7 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; struct snd_sof_control *scontrol = se->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; bool change = false; @@ -200,8 +201,8 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, } /* notify DSP of enum updates */ - if (pm_runtime_active(sdev->dev)) - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + if (pm_runtime_active(scomp->dev)) + snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_SET_VALUE, SOF_CTRL_TYPE_VALUE_CHAN_GET, SOF_CTRL_CMD_ENUM, @@ -216,14 +217,14 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_abi_hdr *data = cdata->data; size_t size; int ret = 0; if (be->max > sizeof(ucontrol->value.bytes.data)) { - dev_err_ratelimited(sdev->dev, + dev_err_ratelimited(scomp->dev, "error: data max %d exceeds ucontrol data array size\n", be->max); return -EINVAL; @@ -231,7 +232,7 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, size = data->size + sizeof(*data); if (size > be->max) { - dev_err_ratelimited(sdev->dev, + dev_err_ratelimited(scomp->dev, "error: DSP sent %zu bytes max is %d\n", size, be->max); ret = -EINVAL; @@ -251,20 +252,20 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_abi_hdr *data = cdata->data; size_t size = data->size + sizeof(*data); if (be->max > sizeof(ucontrol->value.bytes.data)) { - dev_err_ratelimited(sdev->dev, + dev_err_ratelimited(scomp->dev, "error: data max %d exceeds ucontrol data array size\n", be->max); return -EINVAL; } if (size > be->max) { - dev_err_ratelimited(sdev->dev, + dev_err_ratelimited(scomp->dev, "error: size too big %zu bytes max is %d\n", size, be->max); return -EINVAL; @@ -274,8 +275,8 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, memcpy(data, ucontrol->value.bytes.data, size); /* notify DSP of byte control updates */ - if (pm_runtime_active(sdev->dev)) - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + if (pm_runtime_active(scomp->dev)) + snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_SET_DATA, SOF_CTRL_TYPE_DATA_SET, scontrol->cmd, @@ -291,7 +292,7 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct snd_ctl_tlv header; const struct snd_ctl_tlv __user *tlvd = @@ -307,14 +308,14 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, /* be->max is coming from topology */ if (header.length > be->max) { - dev_err_ratelimited(sdev->dev, "error: Bytes data size %d exceeds max %d.\n", + dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n", header.length, be->max); return -EINVAL; } /* Check that header id matches the command */ if (header.numid != scontrol->cmd) { - dev_err_ratelimited(sdev->dev, + dev_err_ratelimited(scomp->dev, "error: incorrect numid %d\n", header.numid); return -EINVAL; @@ -324,26 +325,26 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, return -EFAULT; if (cdata->data->magic != SOF_ABI_MAGIC) { - dev_err_ratelimited(sdev->dev, + dev_err_ratelimited(scomp->dev, "error: Wrong ABI magic 0x%08x.\n", cdata->data->magic); return -EINVAL; } if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { - dev_err_ratelimited(sdev->dev, "error: Incompatible ABI version 0x%08x.\n", + dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n", cdata->data->abi); return -EINVAL; } if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) { - dev_err_ratelimited(sdev->dev, "error: Mismatch in ABI data size (truncated?).\n"); + dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n"); return -EINVAL; } /* notify DSP of byte control updates */ - if (pm_runtime_active(sdev->dev)) - snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + if (pm_runtime_active(scomp->dev)) + snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_SET_DATA, SOF_CTRL_TYPE_DATA_SET, scontrol->cmd, @@ -359,7 +360,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct snd_ctl_tlv header; struct snd_ctl_tlv __user *tlvd = @@ -382,7 +383,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, /* check data size doesn't exceed max coming from topology */ if (data_size > be->max) { - dev_err_ratelimited(sdev->dev, "error: user data size %d exceeds max size %d.\n", + dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %d.\n", data_size, be->max); ret = -EINVAL; goto out; diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index d8446fb9fdde..9832322adbec 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -24,126 +24,6 @@ MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)"); #define TIMEOUT_DEFAULT_IPC_MS 500 #define TIMEOUT_DEFAULT_BOOT_MS 2000 -/* - * Generic object lookup APIs. - */ - -struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_sof_dev *sdev, - const char *name) -{ - struct snd_sof_pcm *spcm; - - list_for_each_entry(spcm, &sdev->pcm_list, list) { - /* match with PCM dai name */ - if (strcmp(spcm->pcm.dai_name, name) == 0) - return spcm; - - /* match with playback caps name if set */ - if (*spcm->pcm.caps[0].name && - !strcmp(spcm->pcm.caps[0].name, name)) - return spcm; - - /* match with capture caps name if set */ - if (*spcm->pcm.caps[1].name && - !strcmp(spcm->pcm.caps[1].name, name)) - return spcm; - } - - return NULL; -} - -struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev, - unsigned int comp_id, - int *direction) -{ - struct snd_sof_pcm *spcm; - - list_for_each_entry(spcm, &sdev->pcm_list, list) { - if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].comp_id == comp_id) { - *direction = SNDRV_PCM_STREAM_PLAYBACK; - return spcm; - } - if (spcm->stream[SNDRV_PCM_STREAM_CAPTURE].comp_id == comp_id) { - *direction = SNDRV_PCM_STREAM_CAPTURE; - return spcm; - } - } - - return NULL; -} - -struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_sof_dev *sdev, - unsigned int pcm_id) -{ - struct snd_sof_pcm *spcm; - - list_for_each_entry(spcm, &sdev->pcm_list, list) { - if (le32_to_cpu(spcm->pcm.pcm_id) == pcm_id) - return spcm; - } - - return NULL; -} - -struct snd_sof_widget *snd_sof_find_swidget(struct snd_sof_dev *sdev, - const char *name) -{ - struct snd_sof_widget *swidget; - - list_for_each_entry(swidget, &sdev->widget_list, list) { - if (strcmp(name, swidget->widget->name) == 0) - return swidget; - } - - return NULL; -} - -/* find widget by stream name and direction */ -struct snd_sof_widget *snd_sof_find_swidget_sname(struct snd_sof_dev *sdev, - const char *pcm_name, int dir) -{ - struct snd_sof_widget *swidget; - enum snd_soc_dapm_type type; - - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - type = snd_soc_dapm_aif_in; - else - type = snd_soc_dapm_aif_out; - - list_for_each_entry(swidget, &sdev->widget_list, list) { - if (!strcmp(pcm_name, swidget->widget->sname) && swidget->id == type) - return swidget; - } - - return NULL; -} - -struct snd_sof_dai *snd_sof_find_dai(struct snd_sof_dev *sdev, - const char *name) -{ - struct snd_sof_dai *dai; - - list_for_each_entry(dai, &sdev->dai_list, list) { - if (dai->name && (strcmp(name, dai->name) == 0)) - return dai; - } - - return NULL; -} - -bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev) -{ - struct snd_sof_pcm *spcm; - - list_for_each_entry(spcm, &sdev->pcm_list, list) { - if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored || - spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored) - return true; - } - - return false; -} - /* * FW Panic/fault handling. */ diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 8796f385be76..2d9ac0035bd2 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -11,6 +11,7 @@ #include #include #include "../sof-priv.h" +#include "../sof-audio.h" #include "hda.h" #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 575f5f5877d8..23872f6e708d 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -17,6 +17,7 @@ #include #include +#include "../sof-audio.h" #include "../ops.h" #include "hda.h" @@ -147,12 +148,13 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *scomp = sdev->component; struct hdac_stream *hstream = substream->runtime->private_data; struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct snd_sof_pcm *spcm; snd_pcm_uframes_t pos; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(scomp, rtd); if (!spcm) { dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n", rtd->dai_link->id); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 927a36f92c24..c0ab9bb2a797 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -20,6 +20,7 @@ #include #include #include "../ops.h" +#include "../sof-audio.h" #include "hda.h" /* diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 5994e1073364..293c5ae8e882 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -15,6 +15,7 @@ #include #include "sof-priv.h" +#include "sof-audio.h" #include "ops.h" static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_id); @@ -412,12 +413,13 @@ static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_id) static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id) { + struct snd_soc_component *scomp = sdev->component; struct snd_sof_pcm_stream *stream; struct sof_ipc_stream_posn posn; struct snd_sof_pcm *spcm; int direction; - spcm = snd_sof_find_spcm_comp(sdev, msg_id, &direction); + spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction); if (!spcm) { dev_err(sdev->dev, "error: period elapsed for unknown stream, msg_id %d\n", @@ -441,12 +443,13 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id) /* DSP notifies host of an XRUN within FW */ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id) { + struct snd_soc_component *scomp = sdev->component; struct snd_sof_pcm_stream *stream; struct sof_ipc_stream_posn posn; struct snd_sof_pcm *spcm; int direction; - spcm = snd_sof_find_spcm_comp(sdev, msg_id, &direction); + spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction); if (!spcm) { dev_err(sdev->dev, "error: XRUN for unknown stream, msg_id %d\n", msg_id); @@ -488,10 +491,11 @@ static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd) } /* get stream position IPC - use faster MMIO method if available on platform */ -int snd_sof_ipc_stream_posn(struct snd_sof_dev *sdev, +int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm, int direction, struct sof_ipc_stream_posn *posn) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc_stream stream; int err; @@ -620,15 +624,15 @@ static int sof_set_get_large_ctrl_data(struct snd_sof_dev *sdev, /* * IPC get()/set() for kcontrols. */ -int snd_sof_ipc_set_get_comp_data(struct snd_sof_ipc *ipc, - struct snd_sof_control *scontrol, +int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, u32 ipc_cmd, enum sof_ipc_ctrl_type ctrl_type, enum sof_ipc_ctrl_cmd ctrl_cmd, bool send) { + struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; - struct snd_sof_dev *sdev = ipc->sdev; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_ctrl_data_params sparams; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index a9c47f6bf657..54ec78799c30 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -14,38 +14,38 @@ #include #include #include "sof-priv.h" +#include "sof-audio.h" #include "ops.h" -#define DRV_NAME "sof-audio-component" - /* Create DMA buffer page table for DSP */ static int create_page_table(struct snd_soc_component *component, struct snd_pcm_substream *substream, unsigned char *dma_area, size_t size) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream); int stream = substream->stream; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; - return snd_sof_create_page_table(sdev->dev, dmab, + return snd_sof_create_page_table(component->dev, dmab, spcm->stream[stream].page_table.area, size); } static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream *substream, const struct sof_ipc_pcm_params_reply *reply) { - struct snd_sof_dev *sdev = spcm->sdev; + struct snd_soc_component *scomp = spcm->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + /* validate offset */ int ret = snd_sof_ipc_pcm_params(sdev, substream, reply); if (ret < 0) - dev_err(sdev->dev, "error: got wrong reply for PCM %d\n", + dev_err(scomp->dev, "error: got wrong reply for PCM %d\n", spcm->pcm.pcm_id); return ret; @@ -70,13 +70,12 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_pcm *spcm; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) { - dev_err(sdev->dev, + dev_err(component->dev, "error: period elapsed for unknown stream!\n"); return; } @@ -110,11 +109,11 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, if (rtd->dai_link->no_pcm) return 0; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; - dev_dbg(sdev->dev, "pcm: hw params stream %d dir %d\n", + dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); memset(&pcm, 0, sizeof(pcm)); @@ -122,7 +121,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, /* allocate audio buffer pages */ ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); if (ret < 0) { - dev_err(sdev->dev, "error: could not allocate %d bytes for PCM %d\n", + dev_err(component->dev, "error: could not allocate %d bytes for PCM %d\n", params_buffer_bytes(params), spcm->pcm.pcm_id); return ret; } @@ -187,17 +186,17 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, params, &pcm.params); if (ret < 0) { - dev_err(sdev->dev, "error: platform hw params failed\n"); + dev_err(component->dev, "error: platform hw params failed\n"); return ret; } - dev_dbg(sdev->dev, "stream_tag %d", pcm.params.stream_tag); + dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag); /* send IPC to the DSP */ ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), &ipc_params_reply, sizeof(ipc_params_reply)); if (ret < 0) { - dev_err(sdev->dev, "error: hw params ipc failed for stream %d\n", + dev_err(component->dev, "error: hw params ipc failed for stream %d\n", pcm.params.stream_tag); return ret; } @@ -247,12 +246,12 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, if (rtd->dai_link->no_pcm) return 0; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; - dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, - substream->stream); + dev_dbg(component->dev, "pcm: free stream %d dir %d\n", + spcm->pcm.pcm_id, substream->stream); if (spcm->prepared[substream->stream]) { ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); @@ -266,7 +265,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, ret = snd_sof_pcm_platform_hw_free(sdev, substream); if (ret < 0) { - dev_err(sdev->dev, "error: platform hw free failed\n"); + dev_err(component->dev, "error: platform hw free failed\n"); err = ret; } @@ -277,7 +276,6 @@ static int sof_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int ret; @@ -285,21 +283,22 @@ static int sof_pcm_prepare(struct snd_soc_component *component, if (rtd->dai_link->no_pcm) return 0; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; if (spcm->prepared[substream->stream]) return 0; - dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id, - substream->stream); + dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n", + spcm->pcm.pcm_id, substream->stream); /* set hw_params */ ret = sof_pcm_hw_params(component, substream, &spcm->params[substream->stream]); if (ret < 0) { - dev_err(sdev->dev, "error: set pcm hw_params after resume\n"); + dev_err(component->dev, + "error: set pcm hw_params after resume\n"); return ret; } @@ -326,11 +325,11 @@ static int sof_pcm_trigger(struct snd_soc_component *component, if (rtd->dai_link->no_pcm) return 0; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; - dev_dbg(sdev->dev, "pcm: trigger stream %d dir %d cmd %d\n", + dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n", spcm->pcm.pcm_id, substream->stream, cmd); stream.hdr.size = sizeof(stream); @@ -359,7 +358,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, /* set up hw_params */ ret = sof_pcm_prepare(component, substream); if (ret < 0) { - dev_err(sdev->dev, + dev_err(component->dev, "error: failed to set up hw_params upon resume\n"); return ret; } @@ -396,7 +395,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component, reset_hw_params = true; break; default: - dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd); + dev_err(component->dev, "error: unhandled trigger cmd %d\n", + cmd); return -EINVAL; } @@ -438,7 +438,7 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, if (sof_ops(sdev)->pcm_pointer) return sof_ops(sdev)->pcm_pointer(sdev, substream); - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; @@ -448,7 +448,8 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, dai = bytes_to_frames(substream->runtime, spcm->stream[substream->stream].posn.dai_posn); - dev_dbg(sdev->dev, "PCM: stream %d dir %d DMA position %lu DAI position %lu\n", + dev_dbg(component->dev, + "PCM: stream %d dir %d DMA position %lu DAI position %lu\n", spcm->pcm.pcm_id, substream->stream, host, dai); return host; @@ -469,12 +470,12 @@ static int sof_pcm_open(struct snd_soc_component *component, if (rtd->dai_link->no_pcm) return 0; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; - dev_dbg(sdev->dev, "pcm: open stream %d dir %d\n", spcm->pcm.pcm_id, - substream->stream); + dev_dbg(component->dev, "pcm: open stream %d dir %d\n", + spcm->pcm.pcm_id, substream->stream); INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work, sof_pcm_period_elapsed_work); @@ -504,13 +505,13 @@ static int sof_pcm_open(struct snd_soc_component *component, */ runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max); - dev_dbg(sdev->dev, "period min %zd max %zd bytes\n", + dev_dbg(component->dev, "period min %zd max %zd bytes\n", runtime->hw.period_bytes_min, runtime->hw.period_bytes_max); - dev_dbg(sdev->dev, "period count %d max %d\n", + dev_dbg(component->dev, "period count %d max %d\n", runtime->hw.periods_min, runtime->hw.periods_max); - dev_dbg(sdev->dev, "buffer max %zd bytes\n", + dev_dbg(component->dev, "buffer max %zd bytes\n", runtime->hw.buffer_bytes_max); /* set wait time - TODO: come from topology */ @@ -523,7 +524,7 @@ static int sof_pcm_open(struct snd_soc_component *component, ret = snd_sof_pcm_platform_open(sdev, substream); if (ret < 0) - dev_err(sdev->dev, "error: pcm open failed %d\n", ret); + dev_err(component->dev, "error: pcm open failed %d\n", ret); return ret; } @@ -540,16 +541,16 @@ static int sof_pcm_close(struct snd_soc_component *component, if (rtd->dai_link->no_pcm) return 0; - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; - dev_dbg(sdev->dev, "pcm: close stream %d dir %d\n", spcm->pcm.pcm_id, - substream->stream); + dev_dbg(component->dev, "pcm: close stream %d dir %d\n", + spcm->pcm.pcm_id, substream->stream); err = snd_sof_pcm_platform_close(sdev, substream); if (err < 0) { - dev_err(sdev->dev, "error: pcm close failed %d\n", + dev_err(component->dev, "error: pcm close failed %d\n", err); /* * keep going, no point in preventing the close @@ -575,14 +576,14 @@ static int sof_pcm_new(struct snd_soc_component *component, int stream = SNDRV_PCM_STREAM_PLAYBACK; /* find SOF PCM for this RTD */ - spcm = snd_sof_find_spcm_dai(sdev, rtd); + spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) { - dev_warn(sdev->dev, "warn: can't find PCM with DAI ID %d\n", + dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n", rtd->dai_link->id); return 0; } - dev_dbg(sdev->dev, "creating new PCM %s\n", spcm->pcm.pcm_name); + dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name); /* do we need to pre-allocate playback audio buffer pages */ if (!spcm->pcm.playback) @@ -591,7 +592,8 @@ static int sof_pcm_new(struct snd_soc_component *component, caps = &spcm->pcm.caps[stream]; /* pre-allocate playback audio buffer pages */ - dev_dbg(sdev->dev, "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n", + dev_dbg(component->dev, + "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n", caps->name, caps->buffer_size_min, caps->buffer_size_max); snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream, @@ -608,7 +610,8 @@ capture: caps = &spcm->pcm.caps[stream]; /* pre-allocate capture audio buffer pages */ - dev_dbg(sdev->dev, "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n", + dev_dbg(component->dev, + "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n", caps->name, caps->buffer_size_min, caps->buffer_size_max); snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream, @@ -629,14 +632,14 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = - snd_sof_find_dai(sdev, (char *)rtd->dai_link->name); + snd_sof_find_dai(component, (char *)rtd->dai_link->name); /* no topology exists for this BE, try a common configuration */ if (!dai) { - dev_warn(sdev->dev, "warning: no topology found for BE DAI %s config\n", + dev_warn(component->dev, + "warning: no topology found for BE DAI %s config\n", rtd->dai_link->name); /* set 48k, stereo, 16bits by default */ @@ -666,7 +669,7 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); break; default: - dev_err(sdev->dev, "error: No available DAI format!\n"); + dev_err(component->dev, "error: No available DAI format!\n"); return -EINVAL; } @@ -678,9 +681,9 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = dai->dai_config->ssp.tdm_slots; channels->max = dai->dai_config->ssp.tdm_slots; - dev_dbg(sdev->dev, + dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(sdev->dev, + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", channels->min, channels->max); @@ -688,7 +691,7 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, case SOF_DAI_INTEL_DMIC: /* DMIC only supports 16 or 32 bit formats */ if (dai->comp_dai.config.frame_fmt == SOF_IPC_FRAME_S24_4LE) { - dev_err(sdev->dev, + dev_err(component->dev, "error: invalid fmt %d for DAI type %d\n", dai->comp_dai.config.frame_fmt, dai->dai_config->type); @@ -704,12 +707,12 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = dai->dai_config->esai.tdm_slots; channels->max = dai->dai_config->esai.tdm_slots; - dev_dbg(sdev->dev, + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", channels->min, channels->max); break; default: - dev_err(sdev->dev, "error: invalid DAI type %d\n", + dev_err(component->dev, "error: invalid DAI type %d\n", dai->dai_config->type); break; } @@ -734,9 +737,9 @@ static int sof_pcm_probe(struct snd_soc_component *component) if (!tplg_filename) return -ENOMEM; - ret = snd_sof_load_topology(sdev, tplg_filename); + ret = snd_sof_load_topology(component, tplg_filename); if (ret < 0) { - dev_err(sdev->dev, "error: failed to load DSP topology %d\n", + dev_err(component->dev, "error: failed to load DSP topology %d\n", ret); return ret; } diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 0fd5567237a8..d1a7b98886d1 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -10,192 +10,7 @@ #include "ops.h" #include "sof-priv.h" - -static int sof_restore_kcontrols(struct snd_sof_dev *sdev) -{ - struct snd_sof_control *scontrol; - int ipc_cmd, ctrl_type; - int ret = 0; - - /* restore kcontrol values */ - list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { - /* reset readback offset for scontrol after resuming */ - scontrol->readback_offset = 0; - - /* notify DSP of kcontrol values */ - switch (scontrol->cmd) { - case SOF_CTRL_CMD_VOLUME: - case SOF_CTRL_CMD_ENUM: - case SOF_CTRL_CMD_SWITCH: - ipc_cmd = SOF_IPC_COMP_SET_VALUE; - ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET; - ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - ipc_cmd, ctrl_type, - scontrol->cmd, - true); - break; - case SOF_CTRL_CMD_BINARY: - ipc_cmd = SOF_IPC_COMP_SET_DATA; - ctrl_type = SOF_CTRL_TYPE_DATA_SET; - ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, - ipc_cmd, ctrl_type, - scontrol->cmd, - true); - break; - - default: - break; - } - - if (ret < 0) { - dev_err(sdev->dev, - "error: failed kcontrol value set for widget: %d\n", - scontrol->comp_id); - - return ret; - } - } - - return 0; -} - -static int sof_restore_pipelines(struct snd_sof_dev *sdev) -{ - struct snd_sof_widget *swidget; - struct snd_sof_route *sroute; - struct sof_ipc_pipe_new *pipeline; - struct snd_sof_dai *dai; - struct sof_ipc_comp_dai *comp_dai; - struct sof_ipc_cmd_hdr *hdr; - int ret; - - /* restore pipeline components */ - list_for_each_entry_reverse(swidget, &sdev->widget_list, list) { - struct sof_ipc_comp_reply r; - - /* skip if there is no private data */ - if (!swidget->private) - continue; - - switch (swidget->id) { - case snd_soc_dapm_dai_in: - case snd_soc_dapm_dai_out: - dai = swidget->private; - comp_dai = &dai->comp_dai; - ret = sof_ipc_tx_message(sdev->ipc, - comp_dai->comp.hdr.cmd, - comp_dai, sizeof(*comp_dai), - &r, sizeof(r)); - break; - case snd_soc_dapm_scheduler: - - /* - * During suspend, all DSP cores are powered off. - * Therefore upon resume, create the pipeline comp - * and power up the core that the pipeline is - * scheduled on. - */ - pipeline = swidget->private; - ret = sof_load_pipeline_ipc(sdev, pipeline, &r); - break; - default: - hdr = swidget->private; - ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, - swidget->private, hdr->size, - &r, sizeof(r)); - break; - } - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to load widget type %d with ID: %d\n", - swidget->widget->id, swidget->comp_id); - - return ret; - } - } - - /* restore pipeline connections */ - list_for_each_entry_reverse(sroute, &sdev->route_list, list) { - struct sof_ipc_pipe_comp_connect *connect; - struct sof_ipc_reply reply; - - /* skip if there's no private data */ - if (!sroute->private) - continue; - - connect = sroute->private; - - /* send ipc */ - ret = sof_ipc_tx_message(sdev->ipc, - connect->hdr.cmd, - connect, sizeof(*connect), - &reply, sizeof(reply)); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to load route sink %s control %s source %s\n", - sroute->route->sink, - sroute->route->control ? sroute->route->control - : "none", - sroute->route->source); - - return ret; - } - } - - /* restore dai links */ - list_for_each_entry_reverse(dai, &sdev->dai_list, list) { - struct sof_ipc_reply reply; - struct sof_ipc_dai_config *config = dai->dai_config; - - if (!config) { - dev_err(sdev->dev, "error: no config for DAI %s\n", - dai->name); - continue; - } - - /* - * The link DMA channel would be invalidated for running - * streams but not for streams that were in the PAUSED - * state during suspend. So invalidate it here before setting - * the dai config in the DSP. - */ - if (config->type == SOF_DAI_INTEL_HDA) - config->hda.link_dma_ch = DMA_CHAN_INVALID; - - ret = sof_ipc_tx_message(sdev->ipc, - config->hdr.cmd, config, - config->hdr.size, - &reply, sizeof(reply)); - - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to set dai config for %s\n", - dai->name); - - return ret; - } - } - - /* complete pipeline */ - list_for_each_entry(swidget, &sdev->widget_list, list) { - switch (swidget->id) { - case snd_soc_dapm_scheduler: - swidget->complete = - snd_sof_complete_pipeline(sdev, swidget); - break; - default: - break; - } - } - - /* restore pipeline kcontrols */ - ret = sof_restore_kcontrols(sdev); - if (ret < 0) - dev_err(sdev->dev, - "error: restoring kcontrols after resume\n"); - - return ret; -} +#include "sof-audio.h" static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd) { @@ -213,34 +28,6 @@ static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd) sizeof(pm_ctx), &reply, sizeof(reply)); } -static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) -{ - struct snd_pcm_substream *substream; - struct snd_sof_pcm *spcm; - snd_pcm_state_t state; - int dir; - - /* - * SOF requires hw_params to be set-up internally upon resume. - * So, set the flag to indicate this for those streams that - * have been suspended. - */ - list_for_each_entry(spcm, &sdev->pcm_list, list) { - for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) { - substream = spcm->stream[dir].substream; - if (!substream || !substream->runtime) - continue; - - state = substream->runtime->status->state; - if (state == SNDRV_PCM_STATE_SUSPENDED) - spcm->prepared[dir] = false; - } - } - - /* set internal flag for BE */ - return snd_sof_dsp_hw_params_upon_resume(sdev); -} - #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) static void sof_cache_debugfs(struct snd_sof_dev *sdev) { @@ -311,7 +98,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) } /* restore pipelines */ - ret = sof_restore_pipelines(sdev); + ret = sof_restore_pipelines(sdev->dev); if (ret < 0) { dev_err(sdev->dev, "error: failed to restore pipeline after resume %d\n", @@ -346,7 +133,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) /* set restore_stream for all streams during system suspend */ if (!runtime_suspend) { - ret = sof_set_hw_params_upon_resume(sdev); + ret = sof_set_hw_params_upon_resume(sdev->dev); if (ret < 0) { dev_err(sdev->dev, "error: setting hw_params flag during suspend %d\n", diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c new file mode 100644 index 000000000000..bf99d040c9c1 --- /dev/null +++ b/sound/soc/sof/sof-audio.c @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan +// + +#include "sof-audio.h" +#include "ops.h" + +bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev) +{ + struct snd_sof_pcm *spcm; + + list_for_each_entry(spcm, &sdev->pcm_list, list) { + if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored || + spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored) + return true; + } + + return false; +} + +int sof_set_hw_params_upon_resume(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + struct snd_pcm_substream *substream; + struct snd_sof_pcm *spcm; + snd_pcm_state_t state; + int dir; + + /* + * SOF requires hw_params to be set-up internally upon resume. + * So, set the flag to indicate this for those streams that + * have been suspended. + */ + list_for_each_entry(spcm, &sdev->pcm_list, list) { + for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) { + substream = spcm->stream[dir].substream; + if (!substream || !substream->runtime) + continue; + + state = substream->runtime->status->state; + if (state == SNDRV_PCM_STATE_SUSPENDED) + spcm->prepared[dir] = false; + } + } + + /* set internal flag for BE */ + return snd_sof_dsp_hw_params_upon_resume(sdev); +} + +static int sof_restore_kcontrols(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + struct snd_sof_control *scontrol; + int ipc_cmd, ctrl_type; + int ret = 0; + + /* restore kcontrol values */ + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { + /* reset readback offset for scontrol after resuming */ + scontrol->readback_offset = 0; + + /* notify DSP of kcontrol values */ + switch (scontrol->cmd) { + case SOF_CTRL_CMD_VOLUME: + case SOF_CTRL_CMD_ENUM: + case SOF_CTRL_CMD_SWITCH: + ipc_cmd = SOF_IPC_COMP_SET_VALUE; + ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET; + ret = snd_sof_ipc_set_get_comp_data(scontrol, + ipc_cmd, ctrl_type, + scontrol->cmd, + true); + break; + case SOF_CTRL_CMD_BINARY: + ipc_cmd = SOF_IPC_COMP_SET_DATA; + ctrl_type = SOF_CTRL_TYPE_DATA_SET; + ret = snd_sof_ipc_set_get_comp_data(scontrol, + ipc_cmd, ctrl_type, + scontrol->cmd, + true); + break; + + default: + break; + } + + if (ret < 0) { + dev_err(dev, + "error: failed kcontrol value set for widget: %d\n", + scontrol->comp_id); + + return ret; + } + } + + return 0; +} + +int sof_restore_pipelines(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + struct snd_sof_widget *swidget; + struct snd_sof_route *sroute; + struct sof_ipc_pipe_new *pipeline; + struct snd_sof_dai *dai; + struct sof_ipc_comp_dai *comp_dai; + struct sof_ipc_cmd_hdr *hdr; + int ret; + + /* restore pipeline components */ + list_for_each_entry_reverse(swidget, &sdev->widget_list, list) { + struct sof_ipc_comp_reply r; + + /* skip if there is no private data */ + if (!swidget->private) + continue; + + switch (swidget->id) { + case snd_soc_dapm_dai_in: + case snd_soc_dapm_dai_out: + dai = swidget->private; + comp_dai = &dai->comp_dai; + ret = sof_ipc_tx_message(sdev->ipc, + comp_dai->comp.hdr.cmd, + comp_dai, sizeof(*comp_dai), + &r, sizeof(r)); + break; + case snd_soc_dapm_scheduler: + + /* + * During suspend, all DSP cores are powered off. + * Therefore upon resume, create the pipeline comp + * and power up the core that the pipeline is + * scheduled on. + */ + pipeline = swidget->private; + ret = sof_load_pipeline_ipc(dev, pipeline, &r); + break; + default: + hdr = swidget->private; + ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, + swidget->private, hdr->size, + &r, sizeof(r)); + break; + } + if (ret < 0) { + dev_err(dev, + "error: failed to load widget type %d with ID: %d\n", + swidget->widget->id, swidget->comp_id); + + return ret; + } + } + + /* restore pipeline connections */ + list_for_each_entry_reverse(sroute, &sdev->route_list, list) { + struct sof_ipc_pipe_comp_connect *connect; + struct sof_ipc_reply reply; + + /* skip if there's no private data */ + if (!sroute->private) + continue; + + connect = sroute->private; + + /* send ipc */ + ret = sof_ipc_tx_message(sdev->ipc, + connect->hdr.cmd, + connect, sizeof(*connect), + &reply, sizeof(reply)); + if (ret < 0) { + dev_err(dev, + "error: failed to load route sink %s control %s source %s\n", + sroute->route->sink, + sroute->route->control ? sroute->route->control + : "none", + sroute->route->source); + + return ret; + } + } + + /* restore dai links */ + list_for_each_entry_reverse(dai, &sdev->dai_list, list) { + struct sof_ipc_reply reply; + struct sof_ipc_dai_config *config = dai->dai_config; + + if (!config) { + dev_err(dev, "error: no config for DAI %s\n", + dai->name); + continue; + } + + /* + * The link DMA channel would be invalidated for running + * streams but not for streams that were in the PAUSED + * state during suspend. So invalidate it here before setting + * the dai config in the DSP. + */ + if (config->type == SOF_DAI_INTEL_HDA) + config->hda.link_dma_ch = DMA_CHAN_INVALID; + + ret = sof_ipc_tx_message(sdev->ipc, + config->hdr.cmd, config, + config->hdr.size, + &reply, sizeof(reply)); + + if (ret < 0) { + dev_err(dev, + "error: failed to set dai config for %s\n", + dai->name); + + return ret; + } + } + + /* complete pipeline */ + list_for_each_entry(swidget, &sdev->widget_list, list) { + switch (swidget->id) { + case snd_soc_dapm_scheduler: + swidget->complete = + snd_sof_complete_pipeline(dev, swidget); + break; + default: + break; + } + } + + /* restore pipeline kcontrols */ + ret = sof_restore_kcontrols(dev); + if (ret < 0) + dev_err(dev, + "error: restoring kcontrols after resume\n"); + + return ret; +} + +/* + * Generic object lookup APIs. + */ + +struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp, + const char *name) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_pcm *spcm; + + list_for_each_entry(spcm, &sdev->pcm_list, list) { + /* match with PCM dai name */ + if (strcmp(spcm->pcm.dai_name, name) == 0) + return spcm; + + /* match with playback caps name if set */ + if (*spcm->pcm.caps[0].name && + !strcmp(spcm->pcm.caps[0].name, name)) + return spcm; + + /* match with capture caps name if set */ + if (*spcm->pcm.caps[1].name && + !strcmp(spcm->pcm.caps[1].name, name)) + return spcm; + } + + return NULL; +} + +struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, + unsigned int comp_id, + int *direction) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_pcm *spcm; + int dir; + + list_for_each_entry(spcm, &sdev->pcm_list, list) { + dir = SNDRV_PCM_STREAM_PLAYBACK; + if (spcm->stream[dir].comp_id == comp_id) { + *direction = dir; + return spcm; + } + + dir = SNDRV_PCM_STREAM_CAPTURE; + if (spcm->stream[dir].comp_id == comp_id) { + *direction = dir; + return spcm; + } + } + + return NULL; +} + +struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp, + unsigned int pcm_id) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_pcm *spcm; + + list_for_each_entry(spcm, &sdev->pcm_list, list) { + if (le32_to_cpu(spcm->pcm.pcm_id) == pcm_id) + return spcm; + } + + return NULL; +} + +struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp, + const char *name) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_widget *swidget; + + list_for_each_entry(swidget, &sdev->widget_list, list) { + if (strcmp(name, swidget->widget->name) == 0) + return swidget; + } + + return NULL; +} + +/* find widget by stream name and direction */ +struct snd_sof_widget * +snd_sof_find_swidget_sname(struct snd_soc_component *scomp, + const char *pcm_name, int dir) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_widget *swidget; + enum snd_soc_dapm_type type; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + type = snd_soc_dapm_aif_in; + else + type = snd_soc_dapm_aif_out; + + list_for_each_entry(swidget, &sdev->widget_list, list) { + if (!strcmp(pcm_name, swidget->widget->sname) && + swidget->id == type) + return swidget; + } + + return NULL; +} + +struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, + const char *name) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_dai *dai; + + list_for_each_entry(dai, &sdev->dai_list, list) { + if (dai->name && (strcmp(name, dai->name) == 0)) + return dai; + } + + return NULL; +} + diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h new file mode 100644 index 000000000000..5703698633af --- /dev/null +++ b/sound/soc/sof/sof-audio.h @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Ranjani Sridharan + */ + +#ifndef __SOUND_SOC_SOF_AUDIO_H +#define __SOUND_SOC_SOF_AUDIO_H + +#include +#include +#include /* needs to be included before control.h */ +#include +#include +#include +#include "sof-priv.h" + +#define SOF_AUDIO_PCM_DRV_NAME "sof-audio-component" + +/* max number of FE PCMs before BEs */ +#define SOF_BE_PCM_BASE 16 + +#define DMA_CHAN_INVALID 0xFFFFFFFF + +/* PCM stream, mapped to FW component */ +struct snd_sof_pcm_stream { + u32 comp_id; + struct snd_dma_buffer page_table; + struct sof_ipc_stream_posn posn; + struct snd_pcm_substream *substream; + struct work_struct period_elapsed_work; + bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */ + /* + * flag to indicate that the DSP pipelines should be kept + * active or not while suspending the stream + */ + bool suspend_ignored; +}; + +/* ALSA SOF PCM device */ +struct snd_sof_pcm { + struct snd_soc_component *scomp; + struct snd_soc_tplg_pcm pcm; + struct snd_sof_pcm_stream stream[2]; + struct list_head list; /* list in sdev pcm list */ + struct snd_pcm_hw_params params[2]; + bool prepared[2]; /* PCM_PARAMS set successfully */ +}; + +struct snd_sof_led_control { + unsigned int use_led; + unsigned int direction; + unsigned int led_value; +}; + +/* ALSA SOF Kcontrol device */ +struct snd_sof_control { + struct snd_soc_component *scomp; + int comp_id; + int min_volume_step; /* min volume step for volume_table */ + int max_volume_step; /* max volume step for volume_table */ + int num_channels; + u32 readback_offset; /* offset to mmapped data if used */ + struct sof_ipc_ctrl_data *control_data; + u32 size; /* cdata size */ + enum sof_ipc_ctrl_cmd cmd; + u32 *volume_table; /* volume table computed from tlv data*/ + + struct list_head list; /* list in sdev control list */ + + struct snd_sof_led_control led_ctl; +}; + +/* ASoC SOF DAPM widget */ +struct snd_sof_widget { + struct snd_soc_component *scomp; + int comp_id; + int pipeline_id; + int complete; + int id; + + struct snd_soc_dapm_widget *widget; + struct list_head list; /* list in sdev widget list */ + + void *private; /* core does not touch this */ +}; + +/* ASoC SOF DAPM route */ +struct snd_sof_route { + struct snd_soc_component *scomp; + + struct snd_soc_dapm_route *route; + struct list_head list; /* list in sdev route list */ + + void *private; +}; + +/* ASoC DAI device */ +struct snd_sof_dai { + struct snd_soc_component *scomp; + const char *name; + const char *cpu_dai_name; + + struct sof_ipc_comp_dai comp_dai; + struct sof_ipc_dai_config *dai_config; + struct list_head list; /* list in sdev dai list */ +}; + +/* + * Kcontrols. + */ + +int snd_sof_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_enum_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_enum_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, + const unsigned int __user *binary_data, + unsigned int size); +int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, + unsigned int __user *binary_data, + unsigned int size); + +/* + * Topology. + * There is no snd_sof_free_topology since topology components will + * be freed by snd_soc_unregister_component, + */ +int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file); +int snd_sof_complete_pipeline(struct device *dev, + struct snd_sof_widget *swidget); + +int sof_load_pipeline_ipc(struct device *dev, + struct sof_ipc_pipe_new *pipeline, + struct sof_ipc_comp_reply *r); + +/* + * Stream IPC + */ +int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp, + struct snd_sof_pcm *spcm, int direction, + struct sof_ipc_stream_posn *posn); + +struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp, + const char *name); +struct snd_sof_widget * +snd_sof_find_swidget_sname(struct snd_soc_component *scomp, + const char *pcm_name, int dir); +struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, + const char *name); + +static inline +struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_soc_component *scomp, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + + struct snd_sof_pcm *spcm = NULL; + + list_for_each_entry(spcm, &sdev->pcm_list, list) { + if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id) + return spcm; + } + + return NULL; +} + +struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp, + const char *name); +struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, + unsigned int comp_id, + int *direction); +struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp, + unsigned int pcm_id); +void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream); + +/* + * Mixer IPC + */ +int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, + u32 ipc_cmd, + enum sof_ipc_ctrl_type ctrl_type, + enum sof_ipc_ctrl_cmd ctrl_cmd, + bool send); + +/* PM */ +int sof_restore_pipelines(struct device *dev); +int sof_set_hw_params_upon_resume(struct device *dev); +bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev); + +#endif diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 18dd832f2053..eae1fc209a65 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -12,20 +12,11 @@ #define __SOUND_SOC_SOF_PRIV_H #include - #include -#include -#include - #include -#include /* needs to be included before control.h */ -#include -#include #include #include -#include #include - #include /* debug flags */ @@ -48,9 +39,6 @@ extern int sof_core_debug; /* DMA buffer size for trace */ #define DMA_BUF_SIZE_FOR_TRACE (PAGE_SIZE * 16) -/* max number of FE PCMs before BEs */ -#define SOF_BE_PCM_BASE 16 - #define SOF_IPC_DSP_REPLY 0 #define SOF_IPC_HOST_REPLY 1 @@ -66,8 +54,6 @@ extern int sof_core_debug; (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \ IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)) -#define DMA_CHAN_INVALID 0xFFFFFFFF - /* DSP D0ix sub-state */ enum sof_d0_substate { SOF_DSP_D0I0 = 0, /* DSP default D0 substate */ @@ -303,90 +289,6 @@ struct snd_sof_ipc_msg { bool ipc_complete; }; -/* PCM stream, mapped to FW component */ -struct snd_sof_pcm_stream { - u32 comp_id; - struct snd_dma_buffer page_table; - struct sof_ipc_stream_posn posn; - struct snd_pcm_substream *substream; - struct work_struct period_elapsed_work; - bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */ - /* - * flag to indicate that the DSP pipelines should be kept - * active or not while suspending the stream - */ - bool suspend_ignored; -}; - -/* ALSA SOF PCM device */ -struct snd_sof_pcm { - struct snd_sof_dev *sdev; - struct snd_soc_tplg_pcm pcm; - struct snd_sof_pcm_stream stream[2]; - struct list_head list; /* list in sdev pcm list */ - struct snd_pcm_hw_params params[2]; - bool prepared[2]; /* PCM_PARAMS set successfully */ -}; - -struct snd_sof_led_control { - unsigned int use_led; - unsigned int direction; - unsigned int led_value; -}; - -/* ALSA SOF Kcontrol device */ -struct snd_sof_control { - struct snd_sof_dev *sdev; - int comp_id; - int min_volume_step; /* min volume step for volume_table */ - int max_volume_step; /* max volume step for volume_table */ - int num_channels; - u32 readback_offset; /* offset to mmaped data if used */ - struct sof_ipc_ctrl_data *control_data; - u32 size; /* cdata size */ - enum sof_ipc_ctrl_cmd cmd; - u32 *volume_table; /* volume table computed from tlv data*/ - - struct list_head list; /* list in sdev control list */ - - struct snd_sof_led_control led_ctl; -}; - -/* ASoC SOF DAPM widget */ -struct snd_sof_widget { - struct snd_sof_dev *sdev; - int comp_id; - int pipeline_id; - int complete; - int id; - - struct snd_soc_dapm_widget *widget; - struct list_head list; /* list in sdev widget list */ - - void *private; /* core does not touch this */ -}; - -/* ASoC SOF DAPM route */ -struct snd_sof_route { - struct snd_sof_dev *sdev; - - struct snd_soc_dapm_route *route; - struct list_head list; /* list in sdev route list */ - - void *private; -}; - -/* ASoC DAI device */ -struct snd_sof_dai { - struct snd_sof_dev *sdev; - const char *name; - const char *cpu_dai_name; - - struct sof_ipc_comp_dai comp_dai; - struct sof_ipc_dai_config *dai_config; - struct list_head list; /* list in sdev dai list */ -}; - /* * SOF Device Level. */ @@ -531,67 +433,6 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev); int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes); -struct snd_sof_widget *snd_sof_find_swidget(struct snd_sof_dev *sdev, - const char *name); -struct snd_sof_widget *snd_sof_find_swidget_sname(struct snd_sof_dev *sdev, - const char *pcm_name, - int dir); -struct snd_sof_dai *snd_sof_find_dai(struct snd_sof_dev *sdev, - const char *name); - -static inline -struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_sof_dev *sdev, - struct snd_soc_pcm_runtime *rtd) -{ - struct snd_sof_pcm *spcm = NULL; - - list_for_each_entry(spcm, &sdev->pcm_list, list) { - if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id) - return spcm; - } - - return NULL; -} - -bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev); - -struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_sof_dev *sdev, - const char *name); -struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev, - unsigned int comp_id, - int *direction); -struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_sof_dev *sdev, - unsigned int pcm_id); -void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream); - -/* - * Stream IPC - */ -int snd_sof_ipc_stream_posn(struct snd_sof_dev *sdev, - struct snd_sof_pcm *spcm, int direction, - struct sof_ipc_stream_posn *posn); - -/* - * Mixer IPC - */ -int snd_sof_ipc_set_get_comp_data(struct snd_sof_ipc *ipc, - struct snd_sof_control *scontrol, u32 ipc_cmd, - enum sof_ipc_ctrl_type ctrl_type, - enum sof_ipc_ctrl_cmd ctrl_cmd, - bool send); - -/* - * Topology. - * There is no snd_sof_free_topology since topology components will - * be freed by snd_soc_unregister_component, - */ -int snd_sof_load_topology(struct snd_sof_dev *sdev, const char *file); -int snd_sof_complete_pipeline(struct snd_sof_dev *sdev, - struct snd_sof_widget *swidget); - -int sof_load_pipeline_ipc(struct snd_sof_dev *sdev, - struct sof_ipc_pipe_new *pipeline, - struct sof_ipc_comp_reply *r); /* * Trace/debug @@ -623,40 +464,12 @@ void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev); */ extern struct snd_compr_ops sof_compressed_ops; -/* - * Kcontrols. - */ - -int snd_sof_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, - const unsigned int __user *binary_data, - unsigned int size); -int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, - unsigned int __user *binary_data, - unsigned int size); - /* * DSP Architectures. */ static inline void sof_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack, u32 stack_words) { - if (sof_arch_ops(sdev)->dsp_stack) sof_arch_ops(sdev)->dsp_stack(sdev, oops, stack, stack_words); } diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index b8701d3407ad..1ae06a1f9b0b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -13,6 +13,7 @@ #include #include #include "sof-priv.h" +#include "sof-audio.h" #include "ops.h" #define COMP_ID_UNASSIGNED 0xffffffff @@ -53,7 +54,8 @@ struct sof_widget_data { static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) { struct sof_ipc_pcm_params_reply ipc_params_reply; - struct snd_sof_dev *sdev = swidget->sdev; + struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc_pcm_params pcm; struct snd_pcm_hw_params *params; struct snd_sof_pcm *spcm; @@ -62,9 +64,9 @@ static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) memset(&pcm, 0, sizeof(pcm)); /* get runtime PCM params using widget's stream name */ - spcm = snd_sof_find_spcm_name(sdev, swidget->widget->sname); + spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); if (!spcm) { - dev_err(sdev->dev, "error: cannot find PCM for %s\n", + dev_err(scomp->dev, "error: cannot find PCM for %s\n", swidget->widget->name); return -EINVAL; } @@ -102,7 +104,7 @@ static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), &ipc_params_reply, sizeof(ipc_params_reply)); if (ret < 0) - dev_err(sdev->dev, "error: pcm params failed for %s\n", + dev_err(scomp->dev, "error: pcm params failed for %s\n", swidget->widget->name); return ret; @@ -111,7 +113,8 @@ static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) /* send stream trigger ipc */ static int ipc_trigger(struct snd_sof_widget *swidget, int cmd) { - struct snd_sof_dev *sdev = swidget->sdev; + struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc_stream stream; struct sof_ipc_reply reply; int ret = 0; @@ -125,7 +128,7 @@ static int ipc_trigger(struct snd_sof_widget *swidget, int cmd) ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, sizeof(stream), &reply, sizeof(reply)); if (ret < 0) - dev_err(sdev->dev, "error: failed to trigger %s\n", + dev_err(scomp->dev, "error: failed to trigger %s\n", swidget->widget->name); return ret; @@ -135,23 +138,23 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { struct snd_sof_widget *swidget = w->dobj.private; + struct snd_soc_component *scomp; int stream = SNDRV_PCM_STREAM_CAPTURE; - struct snd_sof_dev *sdev; struct snd_sof_pcm *spcm; int ret = 0; if (!swidget) return 0; - sdev = swidget->sdev; + scomp = swidget->scomp; - dev_dbg(sdev->dev, "received event %d for widget %s\n", + dev_dbg(scomp->dev, "received event %d for widget %s\n", event, w->name); /* get runtime PCM params using widget's stream name */ - spcm = snd_sof_find_spcm_name(sdev, swidget->widget->sname); + spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); if (!spcm) { - dev_err(sdev->dev, "error: cannot find PCM for %s\n", + dev_err(scomp->dev, "error: cannot find PCM for %s\n", swidget->widget->name); return -EINVAL; } @@ -160,14 +163,14 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: if (spcm->stream[stream].suspend_ignored) { - dev_dbg(sdev->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n"); + dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n"); return 0; } /* set pcm params */ ret = ipc_pcm_params(swidget, stream); if (ret < 0) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: failed to set pcm params for widget %s\n", swidget->widget->name); break; @@ -176,27 +179,27 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w, /* start trigger */ ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_START); if (ret < 0) - dev_err(sdev->dev, + dev_err(scomp->dev, "error: failed to trigger widget %s\n", swidget->widget->name); break; case SND_SOC_DAPM_POST_PMD: if (spcm->stream[stream].suspend_ignored) { - dev_dbg(sdev->dev, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n"); + dev_dbg(scomp->dev, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n"); return 0; } /* stop trigger */ ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP); if (ret < 0) - dev_err(sdev->dev, + dev_err(scomp->dev, "error: failed to trigger widget %s\n", swidget->widget->name); /* pcm free */ ret = ipc_trigger(swidget, SOF_IPC_STREAM_PCM_FREE); if (ret < 0) - dev_err(sdev->dev, + dev_err(scomp->dev, "error: failed to trigger widget %s\n", swidget->widget->name); break; @@ -838,7 +841,7 @@ static void sof_parse_word_tokens(struct snd_soc_component *scomp, /* check if array index is valid */ if (!index || *index == 0) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: invalid array offset\n"); continue; } else { @@ -866,7 +869,6 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, struct snd_soc_tplg_vendor_array *array, int priv_size) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); int asize; while (priv_size > 0) { @@ -874,7 +876,7 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, /* validate asize */ if (asize < 0) { /* FIXME: A zero-size array makes no sense */ - dev_err(sdev->dev, "error: invalid array size 0x%x\n", + dev_err(scomp->dev, "error: invalid array size 0x%x\n", asize); return -EINVAL; } @@ -882,7 +884,7 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, /* make sure there is enough data before parsing */ priv_size -= asize; if (priv_size < 0) { - dev_err(sdev->dev, "error: invalid array size 0x%x\n", + dev_err(scomp->dev, "error: invalid array size 0x%x\n", asize); return -EINVAL; } @@ -905,7 +907,7 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, array); break; default: - dev_err(sdev->dev, "error: unknown token type %d\n", + dev_err(scomp->dev, "error: unknown token type %d\n", array->type); return -EINVAL; } @@ -920,9 +922,7 @@ static int sof_parse_tokens(struct snd_soc_component *scomp, static void sof_dbg_comp_config(struct snd_soc_component *scomp, struct sof_ipc_comp_config *config) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - - dev_dbg(sdev->dev, " config: periods snk %d src %d fmt %d\n", + dev_dbg(scomp->dev, " config: periods snk %d src %d fmt %d\n", config->periods_sink, config->periods_source, config->frame_fmt); } @@ -974,7 +974,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, /* extract tlv data */ if (get_tlv_data(kc->tlv.p, tlv) < 0) { - dev_err(sdev->dev, "error: invalid TLV data\n"); + dev_err(scomp->dev, "error: invalid TLV data\n"); ret = -EINVAL; goto out_free; } @@ -982,7 +982,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, /* set up volume table */ ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1); if (ret < 0) { - dev_err(sdev->dev, "error: setting up volume table\n"); + dev_err(scomp->dev, "error: setting up volume table\n"); goto out_free; } @@ -999,12 +999,12 @@ skip: ARRAY_SIZE(led_tokens), mc->priv.array, le32_to_cpu(mc->priv.size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse led tokens failed %d\n", + dev_err(scomp->dev, "error: parse led tokens failed %d\n", le32_to_cpu(mc->priv.size)); goto out_free_table; } - dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", + dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d\n", scontrol->comp_id, scontrol->num_channels); return ret; @@ -1043,7 +1043,7 @@ static int sof_control_load_enum(struct snd_soc_component *scomp, scontrol->cmd = SOF_CTRL_CMD_ENUM; - dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n", + dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n", scontrol->comp_id, scontrol->num_channels, scontrol->comp_id); return 0; @@ -1067,7 +1067,7 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp, le32_to_cpu(control->priv.size); if (scontrol->size > max_size) { - dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n", + dev_err(scomp->dev, "err: bytes data size %d exceeds max %d.\n", scontrol->size, max_size); ret = -EINVAL; goto out; @@ -1083,7 +1083,7 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp, scontrol->comp_id = sdev->next_comp_id; scontrol->cmd = SOF_CTRL_CMD_BINARY; - dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", + dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d\n", scontrol->comp_id, scontrol->num_channels); if (le32_to_cpu(control->priv.size) > 0) { @@ -1091,14 +1091,14 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp, le32_to_cpu(control->priv.size)); if (cdata->data->magic != SOF_ABI_MAGIC) { - dev_err(sdev->dev, "error: Wrong ABI magic 0x%08x.\n", + dev_err(scomp->dev, "error: Wrong ABI magic 0x%08x.\n", cdata->data->magic); ret = -EINVAL; goto out_free; } if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: Incompatible ABI version 0x%08x.\n", cdata->data->abi); ret = -EINVAL; @@ -1106,7 +1106,7 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp, } if (cdata->data->size + sizeof(const struct sof_abi_hdr) != le32_to_cpu(control->priv.size)) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: Conflict in bytes vs. priv size.\n"); ret = -EINVAL; goto out_free; @@ -1134,14 +1134,14 @@ static int sof_control_load(struct snd_soc_component *scomp, int index, struct snd_sof_control *scontrol; int ret = -EINVAL; - dev_dbg(sdev->dev, "tplg: load control type %d name : %s\n", + dev_dbg(scomp->dev, "tplg: load control type %d name : %s\n", hdr->type, hdr->name); scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL); if (!scontrol) return -ENOMEM; - scontrol->sdev = sdev; + scontrol->scomp = scomp; switch (le32_to_cpu(hdr->ops.info)) { case SND_SOC_TPLG_CTL_VOLSW: @@ -1170,7 +1170,7 @@ static int sof_control_load(struct snd_soc_component *scomp, int index, case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: case SND_SOC_TPLG_DAPM_CTL_PIN: default: - dev_warn(sdev->dev, "control type not supported %d:%d:%d\n", + dev_warn(scomp->dev, "control type not supported %d:%d:%d\n", hdr->ops.get, hdr->ops.put, hdr->ops.info); kfree(scontrol); return 0; @@ -1193,7 +1193,7 @@ static int sof_control_unload(struct snd_soc_component *scomp, struct sof_ipc_free fcomp; struct snd_sof_control *scontrol = dobj->private; - dev_dbg(sdev->dev, "tplg: unload control name : %s\n", scomp->name); + dev_dbg(scomp->dev, "tplg: unload control name : %s\n", scomp->name); fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_FREE; fcomp.hdr.size = sizeof(fcomp); @@ -1217,12 +1217,11 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp, struct snd_soc_tplg_dapm_widget *tw, struct snd_sof_dai *dai) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_card *card = scomp->card; struct snd_soc_pcm_runtime *rtd; list_for_each_entry(rtd, &card->rtd_list, list) { - dev_vdbg(sdev->dev, "tplg: check widget: %s stream: %s dai stream: %s\n", + dev_vdbg(scomp->dev, "tplg: check widget: %s stream: %s dai stream: %s\n", w->name, w->sname, rtd->dai_link->stream_name); if (!w->sname || !rtd->dai_link->stream_name) @@ -1236,13 +1235,13 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp, case snd_soc_dapm_dai_out: rtd->cpu_dai->capture_widget = w; dai->name = rtd->dai_link->name; - dev_dbg(sdev->dev, "tplg: connected widget %s -> DAI link %s\n", + dev_dbg(scomp->dev, "tplg: connected widget %s -> DAI link %s\n", w->name, rtd->dai_link->name); break; case snd_soc_dapm_dai_in: rtd->cpu_dai->playback_widget = w; dai->name = rtd->dai_link->name; - dev_dbg(sdev->dev, "tplg: connected widget %s -> DAI link %s\n", + dev_dbg(scomp->dev, "tplg: connected widget %s -> DAI link %s\n", w->name, rtd->dai_link->name); break; default: @@ -1252,7 +1251,7 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp, /* check we have a connection */ if (!dai->name) { - dev_err(sdev->dev, "error: can't connect DAI %s stream %s\n", + dev_err(scomp->dev, "error: can't connect DAI %s stream %s\n", w->name, w->sname); return -EINVAL; } @@ -1284,7 +1283,7 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index, ARRAY_SIZE(dai_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse dai tokens failed %d\n", + dev_err(scomp->dev, "error: parse dai tokens failed %d\n", le32_to_cpu(private->size)); return ret; } @@ -1293,12 +1292,12 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse dai.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse dai.cfg tokens failed %d\n", private->size); return ret; } - dev_dbg(sdev->dev, "dai %s: type %d index %d\n", + dev_dbg(scomp->dev, "dai %s: type %d index %d\n", swidget->widget->name, comp_dai.type, comp_dai.dai_index); sof_dbg_comp_config(scomp, &comp_dai.config); @@ -1306,7 +1305,7 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index, &comp_dai, sizeof(comp_dai), r, sizeof(*r)); if (ret == 0 && dai) { - dai->sdev = sdev; + dai->scomp = scomp; memcpy(&dai->comp_dai, &comp_dai, sizeof(comp_dai)); } @@ -1342,13 +1341,13 @@ static int sof_widget_load_buffer(struct snd_soc_component *scomp, int index, ARRAY_SIZE(buffer_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse buffer tokens failed %d\n", + dev_err(scomp->dev, "error: parse buffer tokens failed %d\n", private->size); kfree(buffer); return ret; } - dev_dbg(sdev->dev, "buffer %s: size %d caps 0x%x\n", + dev_dbg(scomp->dev, "buffer %s: size %d caps 0x%x\n", swidget->widget->name, buffer->size, buffer->caps); swidget->private = buffer; @@ -1356,7 +1355,7 @@ static int sof_widget_load_buffer(struct snd_soc_component *scomp, int index, ret = sof_ipc_tx_message(sdev->ipc, buffer->comp.hdr.cmd, buffer, sizeof(*buffer), r, sizeof(*r)); if (ret < 0) { - dev_err(sdev->dev, "error: buffer %s load failed\n", + dev_err(scomp->dev, "error: buffer %s load failed\n", swidget->widget->name); kfree(buffer); } @@ -1365,16 +1364,16 @@ static int sof_widget_load_buffer(struct snd_soc_component *scomp, int index, } /* bind PCM ID to host component ID */ -static int spcm_bind(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, +static int spcm_bind(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm, int dir) { struct snd_sof_widget *host_widget; - host_widget = snd_sof_find_swidget_sname(sdev, + host_widget = snd_sof_find_swidget_sname(scomp, spcm->pcm.caps[dir].name, dir); if (!host_widget) { - dev_err(sdev->dev, "can't find host comp to bind pcm\n"); + dev_err(scomp->dev, "can't find host comp to bind pcm\n"); return -EINVAL; } @@ -1415,7 +1414,7 @@ static int sof_widget_load_pcm(struct snd_soc_component *scomp, int index, ARRAY_SIZE(pcm_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse host tokens failed %d\n", + dev_err(scomp->dev, "error: parse host tokens failed %d\n", private->size); goto err; } @@ -1424,12 +1423,12 @@ static int sof_widget_load_pcm(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse host.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse host.cfg tokens failed %d\n", le32_to_cpu(private->size)); goto err; } - dev_dbg(sdev->dev, "loaded host %s\n", swidget->widget->name); + dev_dbg(scomp->dev, "loaded host %s\n", swidget->widget->name); sof_dbg_comp_config(scomp, &host->config); swidget->private = host; @@ -1446,24 +1445,25 @@ err: /* * Pipeline Topology */ -int sof_load_pipeline_ipc(struct snd_sof_dev *sdev, +int sof_load_pipeline_ipc(struct device *dev, struct sof_ipc_pipe_new *pipeline, struct sof_ipc_comp_reply *r) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct sof_ipc_pm_core_config pm_core_config; int ret; ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, sizeof(*pipeline), r, sizeof(*r)); if (ret < 0) { - dev_err(sdev->dev, "error: load pipeline ipc failure\n"); + dev_err(dev, "error: load pipeline ipc failure\n"); return ret; } /* power up the core that this pipeline is scheduled on */ ret = snd_sof_dsp_core_power_up(sdev, 1 << pipeline->core); if (ret < 0) { - dev_err(sdev->dev, "error: powering up pipeline schedule core %d\n", + dev_err(dev, "error: powering up pipeline schedule core %d\n", pipeline->core); return ret; } @@ -1487,7 +1487,7 @@ int sof_load_pipeline_ipc(struct snd_sof_dev *sdev, &pm_core_config, sizeof(pm_core_config), &pm_core_config, sizeof(pm_core_config)); if (ret < 0) - dev_err(sdev->dev, "error: core enable ipc failure\n"); + dev_err(dev, "error: core enable ipc failure\n"); return ret; } @@ -1497,7 +1497,6 @@ static int sof_widget_load_pipeline(struct snd_soc_component *scomp, struct snd_soc_tplg_dapm_widget *tw, struct sof_ipc_comp_reply *r) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &tw->priv; struct sof_ipc_pipe_new *pipeline; struct snd_sof_widget *comp_swidget; @@ -1514,9 +1513,9 @@ static int sof_widget_load_pipeline(struct snd_soc_component *scomp, pipeline->comp_id = swidget->comp_id; /* component at start of pipeline is our stream id */ - comp_swidget = snd_sof_find_swidget(sdev, tw->sname); + comp_swidget = snd_sof_find_swidget(scomp, tw->sname); if (!comp_swidget) { - dev_err(sdev->dev, "error: widget %s refers to non existent widget %s\n", + dev_err(scomp->dev, "error: widget %s refers to non existent widget %s\n", tw->name, tw->sname); ret = -EINVAL; goto err; @@ -1524,26 +1523,26 @@ static int sof_widget_load_pipeline(struct snd_soc_component *scomp, pipeline->sched_id = comp_swidget->comp_id; - dev_dbg(sdev->dev, "tplg: pipeline id %d comp %d scheduling comp id %d\n", + dev_dbg(scomp->dev, "tplg: pipeline id %d comp %d scheduling comp id %d\n", pipeline->pipeline_id, pipeline->comp_id, pipeline->sched_id); ret = sof_parse_tokens(scomp, pipeline, sched_tokens, ARRAY_SIZE(sched_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse pipeline tokens failed %d\n", + dev_err(scomp->dev, "error: parse pipeline tokens failed %d\n", private->size); goto err; } - dev_dbg(sdev->dev, "pipeline %s: period %d pri %d mips %d core %d frames %d\n", + dev_dbg(scomp->dev, "pipeline %s: period %d pri %d mips %d core %d frames %d\n", swidget->widget->name, pipeline->period, pipeline->priority, pipeline->period_mips, pipeline->core, pipeline->frames_per_sched); swidget->private = pipeline; /* send ipc's to create pipeline comp and power up schedule core */ - ret = sof_load_pipeline_ipc(sdev, pipeline, r); + ret = sof_load_pipeline_ipc(scomp->dev, pipeline, r); if (ret >= 0) return ret; err: @@ -1581,7 +1580,7 @@ static int sof_widget_load_mixer(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse mixer.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse mixer.cfg tokens failed %d\n", private->size); kfree(mixer); return ret; @@ -1628,7 +1627,7 @@ static int sof_widget_load_mux(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse mux.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse mux.cfg tokens failed %d\n", private->size); kfree(mux); return ret; @@ -1668,7 +1667,7 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, return -ENOMEM; if (!le32_to_cpu(tw->num_kcontrols)) { - dev_err(sdev->dev, "error: invalid kcontrol count %d for volume\n", + dev_err(scomp->dev, "error: invalid kcontrol count %d for volume\n", tw->num_kcontrols); ret = -EINVAL; goto err; @@ -1686,7 +1685,7 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, ARRAY_SIZE(volume_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse volume tokens failed %d\n", + dev_err(scomp->dev, "error: parse volume tokens failed %d\n", private->size); goto err; } @@ -1694,7 +1693,7 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse volume.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse volume.cfg tokens failed %d\n", le32_to_cpu(private->size)); goto err; } @@ -1754,7 +1753,7 @@ static int sof_widget_load_src(struct snd_soc_component *scomp, int index, ARRAY_SIZE(src_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse src tokens failed %d\n", + dev_err(scomp->dev, "error: parse src tokens failed %d\n", private->size); goto err; } @@ -1763,12 +1762,12 @@ static int sof_widget_load_src(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse src.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse src.cfg tokens failed %d\n", le32_to_cpu(private->size)); goto err; } - dev_dbg(sdev->dev, "src %s: source rate %d sink rate %d\n", + dev_dbg(scomp->dev, "src %s: source rate %d sink rate %d\n", swidget->widget->name, src->source_rate, src->sink_rate); sof_dbg_comp_config(scomp, &src->config); @@ -1813,7 +1812,7 @@ static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index, ARRAY_SIZE(tone_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse tone tokens failed %d\n", + dev_err(scomp->dev, "error: parse tone tokens failed %d\n", le32_to_cpu(private->size)); goto err; } @@ -1822,12 +1821,12 @@ static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse tone.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse tone.cfg tokens failed %d\n", le32_to_cpu(private->size)); goto err; } - dev_dbg(sdev->dev, "tone %s: frequency %d amplitude %d\n", + dev_dbg(scomp->dev, "tone %s: frequency %d amplitude %d\n", swidget->widget->name, tone->frequency, tone->amplitude); sof_dbg_comp_config(scomp, &tone->config); @@ -1842,7 +1841,7 @@ err: return ret; } -static int sof_get_control_data(struct snd_sof_dev *sdev, +static int sof_get_control_data(struct snd_soc_component *scomp, struct snd_soc_dapm_widget *widget, struct sof_widget_data *wdata, size_t *size) @@ -1872,14 +1871,14 @@ static int sof_get_control_data(struct snd_sof_dev *sdev, wdata[i].control = se->dobj.private; break; default: - dev_err(sdev->dev, "error: unknown kcontrol type %d in widget %s\n", + dev_err(scomp->dev, "error: unknown kcontrol type %d in widget %s\n", widget->dobj.widget.kcontrol_type, widget->name); return -EINVAL; } if (!wdata[i].control) { - dev_err(sdev->dev, "error: no scontrol for widget %s\n", + dev_err(scomp->dev, "error: no scontrol for widget %s\n", widget->name); return -EINVAL; } @@ -1932,7 +1931,7 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, int i; if (type == SOF_COMP_NONE) { - dev_err(sdev->dev, "error: invalid process comp type %d\n", + dev_err(scomp->dev, "error: invalid process comp type %d\n", type); return -EINVAL; } @@ -1947,7 +1946,7 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, return -ENOMEM; /* get possible component controls and get size of all pdata */ - ret = sof_get_control_data(sdev, widget, wdata, + ret = sof_get_control_data(scomp, widget, wdata, &ipc_data_size); if (ret < 0) @@ -1982,7 +1981,7 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(comp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse process.cfg tokens failed %d\n", + dev_err(scomp->dev, "error: parse process.cfg tokens failed %d\n", le32_to_cpu(private->size)); goto err; } @@ -2010,7 +2009,7 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, ipc_size, r, sizeof(*r)); if (ret < 0) { - dev_err(sdev->dev, "error: create process failed\n"); + dev_err(scomp->dev, "error: create process failed\n"); goto err; } @@ -2021,13 +2020,13 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, /* send control data with large message supported method */ for (i = 0; i < widget->num_kcontrols; i++) { wdata[i].control->readback_offset = 0; - ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, wdata[i].control, + ret = snd_sof_ipc_set_get_comp_data(wdata[i].control, wdata[i].ipc_cmd, wdata[i].ctrl_type, wdata[i].control->cmd, true); if (ret != 0) { - dev_err(sdev->dev, "error: send control failed\n"); + dev_err(scomp->dev, "error: send control failed\n"); break; } } @@ -2050,14 +2049,13 @@ static int sof_widget_load_process(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_dapm_widget *tw, struct sof_ipc_comp_reply *r) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &tw->priv; struct sof_ipc_comp_process config; int ret; /* check we have some tokens - we need at least process type */ if (le32_to_cpu(private->size) == 0) { - dev_err(sdev->dev, "error: process tokens not found\n"); + dev_err(scomp->dev, "error: process tokens not found\n"); return -EINVAL; } @@ -2068,7 +2066,7 @@ static int sof_widget_load_process(struct snd_soc_component *scomp, int index, ARRAY_SIZE(process_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse process tokens failed %d\n", + dev_err(scomp->dev, "error: parse process tokens failed %d\n", le32_to_cpu(private->size)); return ret; } @@ -2077,14 +2075,14 @@ static int sof_widget_load_process(struct snd_soc_component *scomp, int index, ret = sof_process_load(scomp, index, swidget, tw, r, find_process_comp_type(config.type)); if (ret < 0) { - dev_err(sdev->dev, "error: process loading failed\n"); + dev_err(scomp->dev, "error: process loading failed\n"); return ret; } return 0; } -static int sof_widget_bind_event(struct snd_sof_dev *sdev, +static int sof_widget_bind_event(struct snd_soc_component *scomp, struct snd_sof_widget *swidget, u16 event_type) { @@ -2110,7 +2108,7 @@ static int sof_widget_bind_event(struct snd_sof_dev *sdev, break; } - dev_err(sdev->dev, + dev_err(scomp->dev, "error: invalid event type %d for widget %s\n", event_type, swidget->widget->name); return -EINVAL; @@ -2132,7 +2130,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, if (!swidget) return -ENOMEM; - swidget->sdev = sdev; + swidget->scomp = scomp; swidget->widget = w; swidget->comp_id = sdev->next_comp_id++; swidget->complete = 0; @@ -2141,7 +2139,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, swidget->private = NULL; memset(&reply, 0, sizeof(reply)); - dev_dbg(sdev->dev, "tplg: ready widget id %d pipe %d type %d name : %s stream %s\n", + dev_dbg(scomp->dev, "tplg: ready widget id %d pipe %d type %d name : %s stream %s\n", swidget->comp_id, index, swidget->id, tw->name, strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 ? tw->sname : "none"); @@ -2212,14 +2210,14 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, case snd_soc_dapm_dai_link: case snd_soc_dapm_kcontrol: default: - dev_warn(sdev->dev, "warning: widget type %d name %s not handled\n", + dev_warn(scomp->dev, "warning: widget type %d name %s not handled\n", swidget->id, tw->name); break; } /* check IPC reply */ if (ret < 0 || reply.rhdr.error < 0) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: DSP failed to add widget id %d type %d name : %s stream %s reply %d\n", tw->shift, swidget->id, tw->name, strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 @@ -2230,10 +2228,10 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, /* bind widget to external event */ if (tw->event_type) { - ret = sof_widget_bind_event(sdev, swidget, + ret = sof_widget_bind_event(scomp, swidget, le16_to_cpu(tw->event_type)); if (ret) { - dev_err(sdev->dev, "error: widget event binding failed\n"); + dev_err(scomp->dev, "error: widget event binding failed\n"); kfree(swidget->private); kfree(swidget); return ret; @@ -2301,7 +2299,7 @@ static int sof_widget_unload(struct snd_soc_component *scomp, pipeline = swidget->private; ret = snd_sof_dsp_core_power_down(sdev, 1 << pipeline->core); if (ret < 0) - dev_err(sdev->dev, "error: powering down pipeline schedule core %d\n", + dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n", pipeline->core); /* update enabled cores mask */ @@ -2329,7 +2327,7 @@ static int sof_widget_unload(struct snd_soc_component *scomp, scontrol = sbe->dobj.private; break; default: - dev_warn(sdev->dev, "unsupported kcontrol_type\n"); + dev_warn(scomp->dev, "unsupported kcontrol_type\n"); goto out; } kfree(scontrol->control_data); @@ -2372,12 +2370,12 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index, if (!spcm) return -ENOMEM; - spcm->sdev = sdev; + spcm->scomp = scomp; spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].comp_id = COMP_ID_UNASSIGNED; spcm->stream[SNDRV_PCM_STREAM_CAPTURE].comp_id = COMP_ID_UNASSIGNED; spcm->pcm = *pcm; - dev_dbg(sdev->dev, "tplg: load pcm %s\n", pcm->dai_name); + dev_dbg(scomp->dev, "tplg: load pcm %s\n", pcm->dai_name); dai_drv->dobj.private = spcm; list_add(&spcm->list, &sdev->pcm_list); @@ -2386,7 +2384,7 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(stream_tokens), private->array, le32_to_cpu(private->size)); if (ret) { - dev_err(sdev->dev, "error: parse stream tokens failed %d\n", + dev_err(scomp->dev, "error: parse stream tokens failed %d\n", le32_to_cpu(private->size)); return ret; } @@ -2395,7 +2393,7 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index, if (!spcm->pcm.playback) goto capture; - dev_vdbg(sdev->dev, "tplg: pcm %s stream tokens: playback d0i3:%d\n", + dev_vdbg(scomp->dev, "tplg: pcm %s stream tokens: playback d0i3:%d\n", spcm->pcm.pcm_name, spcm->stream[0].d0i3_compatible); caps = &spcm->pcm.caps[stream]; @@ -2404,16 +2402,16 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index, ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev, PAGE_SIZE, &spcm->stream[stream].page_table); if (ret < 0) { - dev_err(sdev->dev, "error: can't alloc page table for %s %d\n", + dev_err(scomp->dev, "error: can't alloc page table for %s %d\n", caps->name, ret); return ret; } /* bind pcm to host comp */ - ret = spcm_bind(sdev, spcm, stream); + ret = spcm_bind(scomp, spcm, stream); if (ret) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: can't bind pcm to host\n"); goto free_playback_tables; } @@ -2425,7 +2423,7 @@ capture: if (!spcm->pcm.capture) return ret; - dev_vdbg(sdev->dev, "tplg: pcm %s stream tokens: capture d0i3:%d\n", + dev_vdbg(scomp->dev, "tplg: pcm %s stream tokens: capture d0i3:%d\n", spcm->pcm.pcm_name, spcm->stream[1].d0i3_compatible); caps = &spcm->pcm.caps[stream]; @@ -2434,15 +2432,15 @@ capture: ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev, PAGE_SIZE, &spcm->stream[stream].page_table); if (ret < 0) { - dev_err(sdev->dev, "error: can't alloc page table for %s %d\n", + dev_err(scomp->dev, "error: can't alloc page table for %s %d\n", caps->name, ret); goto free_playback_tables; } /* bind pcm to host comp */ - ret = spcm_bind(sdev, spcm, stream); + ret = spcm_bind(scomp, spcm, stream); if (ret) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: can't bind pcm to host\n"); snd_dma_free_pages(&spcm->stream[stream].page_table); goto free_playback_tables; @@ -2568,7 +2566,7 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(ssp_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse ssp tokens failed %d\n", + dev_err(scomp->dev, "error: parse ssp tokens failed %d\n", le32_to_cpu(private->size)); return ret; } @@ -2582,7 +2580,7 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, config->ssp.rx_slots = le32_to_cpu(hw_config->rx_slots); config->ssp.tx_slots = le32_to_cpu(hw_config->tx_slots); - dev_dbg(sdev->dev, "tplg: config SSP%d fmt 0x%x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d\n", + dev_dbg(scomp->dev, "tplg: config SSP%d fmt 0x%x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d\n", config->dai_index, config->format, config->ssp.mclk_rate, config->ssp.bclk_rate, config->ssp.fsync_rate, config->ssp.sample_valid_bits, @@ -2591,13 +2589,13 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, /* validate SSP fsync rate and channel count */ if (config->ssp.fsync_rate < 8000 || config->ssp.fsync_rate > 192000) { - dev_err(sdev->dev, "error: invalid fsync rate for SSP%d\n", + dev_err(scomp->dev, "error: invalid fsync rate for SSP%d\n", config->dai_index); return -EINVAL; } if (config->ssp.tdm_slots < 1 || config->ssp.tdm_slots > 8) { - dev_err(sdev->dev, "error: invalid channel count for SSP%d\n", + dev_err(scomp->dev, "error: invalid channel count for SSP%d\n", config->dai_index); return -EINVAL; } @@ -2608,7 +2606,7 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, sizeof(reply)); if (ret < 0) { - dev_err(sdev->dev, "error: failed to set DAI config for SSP%d\n", + dev_err(scomp->dev, "error: failed to set DAI config for SSP%d\n", config->dai_index); return ret; } @@ -2616,7 +2614,7 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) - dev_err(sdev->dev, "error: failed to save DAI config for SSP%d\n", + dev_err(scomp->dev, "error: failed to save DAI config for SSP%d\n", config->dai_index); return ret; @@ -2655,7 +2653,7 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(esai_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse esai tokens failed %d\n", + dev_err(scomp->dev, "error: parse esai tokens failed %d\n", le32_to_cpu(private->size)); return ret; } @@ -2669,14 +2667,14 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, config->esai.rx_slots = le32_to_cpu(hw_config->rx_slots); config->esai.tx_slots = le32_to_cpu(hw_config->tx_slots); - dev_info(sdev->dev, + dev_info(scomp->dev, "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", config->dai_index, config->format, config->esai.mclk_rate, config->esai.tdm_slot_width, config->esai.tdm_slots, config->esai.mclk_id); if (config->esai.tdm_slots < 1 || config->esai.tdm_slots > 8) { - dev_err(sdev->dev, "error: invalid channel count for ESAI%d\n", + dev_err(scomp->dev, "error: invalid channel count for ESAI%d\n", config->dai_index); return -EINVAL; } @@ -2686,7 +2684,7 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, config->hdr.cmd, config, size, &reply, sizeof(reply)); if (ret < 0) { - dev_err(sdev->dev, "error: failed to set DAI config for ESAI%d\n", + dev_err(scomp->dev, "error: failed to set DAI config for ESAI%d\n", config->dai_index); return ret; } @@ -2694,7 +2692,7 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) - dev_err(sdev->dev, "error: failed to save DAI config for ESAI%d\n", + dev_err(scomp->dev, "error: failed to save DAI config for ESAI%d\n", config->dai_index); return ret; @@ -2727,7 +2725,7 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(dmic_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse dmic tokens failed %d\n", + dev_err(scomp->dev, "error: parse dmic tokens failed %d\n", le32_to_cpu(private->size)); return ret; } @@ -2762,7 +2760,7 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(dmic_pdm_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse dmic pdm tokens failed %d\n", + dev_err(scomp->dev, "error: parse dmic pdm tokens failed %d\n", le32_to_cpu(private->size)); goto err; } @@ -2771,27 +2769,27 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ipc_config->hdr.size = size; /* debug messages */ - dev_dbg(sdev->dev, "tplg: config DMIC%d driver version %d\n", + dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n", ipc_config->dai_index, ipc_config->dmic.driver_ipc_version); - dev_dbg(sdev->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n", + dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n", ipc_config->dmic.pdmclk_min, ipc_config->dmic.pdmclk_max, ipc_config->dmic.duty_min); - dev_dbg(sdev->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n", + dev_dbg(scomp->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n", ipc_config->dmic.duty_max, ipc_config->dmic.fifo_fs, ipc_config->dmic.num_pdm_active); - dev_dbg(sdev->dev, "fifo word length %hd\n", + dev_dbg(scomp->dev, "fifo word length %hd\n", ipc_config->dmic.fifo_bits); for (j = 0; j < ipc_config->dmic.num_pdm_active; j++) { - dev_dbg(sdev->dev, "pdm %hd mic a %hd mic b %hd\n", + dev_dbg(scomp->dev, "pdm %hd mic a %hd mic b %hd\n", ipc_config->dmic.pdm[j].id, ipc_config->dmic.pdm[j].enable_mic_a, ipc_config->dmic.pdm[j].enable_mic_b); - dev_dbg(sdev->dev, "pdm %hd polarity a %hd polarity b %hd\n", + dev_dbg(scomp->dev, "pdm %hd polarity a %hd polarity b %hd\n", ipc_config->dmic.pdm[j].id, ipc_config->dmic.pdm[j].polarity_mic_a, ipc_config->dmic.pdm[j].polarity_mic_b); - dev_dbg(sdev->dev, "pdm %hd clk_edge %hd skew %hd\n", + dev_dbg(scomp->dev, "pdm %hd clk_edge %hd skew %hd\n", ipc_config->dmic.pdm[j].id, ipc_config->dmic.pdm[j].clk_edge, ipc_config->dmic.pdm[j].skew); @@ -2808,7 +2806,7 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, sizeof(reply)); if (ret < 0) { - dev_err(sdev->dev, + dev_err(scomp->dev, "error: failed to set DAI config for DMIC%d\n", config->dai_index); goto err; @@ -2817,7 +2815,7 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, ipc_config); if (ret < 0) - dev_err(sdev->dev, "error: failed to save DAI config for DMIC%d\n", + dev_err(scomp->dev, "error: failed to save DAI config for DMIC%d\n", config->dai_index); err: @@ -2908,21 +2906,21 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(hda_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse hda tokens failed %d\n", + dev_err(scomp->dev, "error: parse hda tokens failed %d\n", le32_to_cpu(private->size)); return ret; } dai = snd_soc_find_dai(link->cpus); if (!dai) { - dev_err(sdev->dev, "error: failed to find dai %s in %s", + dev_err(scomp->dev, "error: failed to find dai %s in %s", link->cpus->dai_name, __func__); return -EINVAL; } ret = sof_link_hda_process(sdev, link, config); if (ret < 0) - dev_err(sdev->dev, "error: failed to process hda dai link %s", + dev_err(scomp->dev, "error: failed to process hda dai link %s", link->name); return ret; @@ -2948,7 +2946,7 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index, sizeof(reply)); if (ret < 0) { - dev_err(sdev->dev, "error: failed to set DAI config for ALH %d\n", + dev_err(scomp->dev, "error: failed to set DAI config for ALH %d\n", config->dai_index); return ret; } @@ -2956,7 +2954,7 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index, /* set config for all DAI's with name matching the link name */ ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) - dev_err(sdev->dev, "error: failed to save DAI config for ALH %d\n", + dev_err(scomp->dev, "error: failed to save DAI config for ALH %d\n", config->dai_index); return ret; @@ -2967,7 +2965,6 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; struct sof_ipc_dai_config config; struct snd_soc_tplg_hw_config *hw_config; @@ -2976,10 +2973,10 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, int i = 0; if (!link->platforms) { - dev_err(sdev->dev, "error: no platforms\n"); + dev_err(scomp->dev, "error: no platforms\n"); return -EINVAL; } - link->platforms->name = dev_name(sdev->dev); + link->platforms->name = dev_name(scomp->dev); /* * Set nonatomic property for FE dai links as their trigger action @@ -2998,7 +2995,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, /* check we have some tokens - we need at least DAI type */ if (le32_to_cpu(private->size) == 0) { - dev_err(sdev->dev, "error: expected tokens for DAI, none found\n"); + dev_err(scomp->dev, "error: expected tokens for DAI, none found\n"); return -EINVAL; } @@ -3010,7 +3007,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, ARRAY_SIZE(dai_link_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { - dev_err(sdev->dev, "error: parse link tokens failed %d\n", + dev_err(scomp->dev, "error: parse link tokens failed %d\n", le32_to_cpu(private->size)); return ret; } @@ -3022,12 +3019,12 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, num_hw_configs = le32_to_cpu(cfg->num_hw_configs); if (!num_hw_configs) { if (config.type != SOF_DAI_INTEL_HDA) { - dev_err(sdev->dev, "error: unexpected DAI config count %d!\n", + dev_err(scomp->dev, "error: unexpected DAI config count %d!\n", le32_to_cpu(cfg->num_hw_configs)); return -EINVAL; } } else { - dev_dbg(sdev->dev, "tplg: %d hw_configs found, default id: %d!\n", + dev_dbg(scomp->dev, "tplg: %d hw_configs found, default id: %d!\n", cfg->num_hw_configs, le32_to_cpu(cfg->default_hw_config_id)); for (i = 0; i < num_hw_configs; i++) { @@ -3036,7 +3033,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, } if (i == num_hw_configs) { - dev_err(sdev->dev, "error: default hw_config id: %d not found!\n", + dev_err(scomp->dev, "error: default hw_config id: %d not found!\n", le32_to_cpu(cfg->default_hw_config_id)); return -EINVAL; } @@ -3075,7 +3072,8 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, &config); break; default: - dev_err(sdev->dev, "error: invalid DAI type %d\n", config.type); + dev_err(scomp->dev, "error: invalid DAI type %d\n", + config.type); ret = -EINVAL; break; } @@ -3123,7 +3121,7 @@ static int sof_link_unload(struct snd_soc_component *scomp, goto found; } - dev_err(sdev->dev, "error: failed to find dai %s in %s", + dev_err(scomp->dev, "error: failed to find dai %s in %s", link->name, __func__); return -EINVAL; found: @@ -3138,7 +3136,7 @@ found: ret = sof_link_hda_unload(sdev, link); break; default: - dev_err(sdev->dev, "error: invalid DAI type %d\n", + dev_err(scomp->dev, "error: invalid DAI type %d\n", sof_dai->dai_config->type); ret = -EINVAL; break; @@ -3164,7 +3162,7 @@ static int sof_route_load(struct snd_soc_component *scomp, int index, if (!sroute) return -ENOMEM; - sroute->sdev = sdev; + sroute->scomp = scomp; connect = kzalloc(sizeof(*connect), GFP_KERNEL); if (!connect) { @@ -3175,14 +3173,14 @@ static int sof_route_load(struct snd_soc_component *scomp, int index, connect->hdr.size = sizeof(*connect); connect->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT; - dev_dbg(sdev->dev, "sink %s control %s source %s\n", + dev_dbg(scomp->dev, "sink %s control %s source %s\n", route->sink, route->control ? route->control : "none", route->source); /* source component */ - source_swidget = snd_sof_find_swidget(sdev, (char *)route->source); + source_swidget = snd_sof_find_swidget(scomp, (char *)route->source); if (!source_swidget) { - dev_err(sdev->dev, "error: source %s not found\n", + dev_err(scomp->dev, "error: source %s not found\n", route->source); ret = -EINVAL; goto err; @@ -3201,9 +3199,9 @@ static int sof_route_load(struct snd_soc_component *scomp, int index, connect->source_id = source_swidget->comp_id; /* sink component */ - sink_swidget = snd_sof_find_swidget(sdev, (char *)route->sink); + sink_swidget = snd_sof_find_swidget(scomp, (char *)route->sink); if (!sink_swidget) { - dev_err(sdev->dev, "error: sink %s not found\n", + dev_err(scomp->dev, "error: sink %s not found\n", route->sink); ret = -EINVAL; goto err; @@ -3227,7 +3225,7 @@ static int sof_route_load(struct snd_soc_component *scomp, int index, */ if (source_swidget->id != snd_soc_dapm_buffer && sink_swidget->id != snd_soc_dapm_buffer) { - dev_dbg(sdev->dev, "warning: neither Linked source component %s nor sink component %s is of buffer type, ignoring link\n", + dev_dbg(scomp->dev, "warning: neither Linked source component %s nor sink component %s is of buffer type, ignoring link\n", route->source, route->sink); ret = 0; goto err; @@ -3239,7 +3237,7 @@ static int sof_route_load(struct snd_soc_component *scomp, int index, /* check IPC return value */ if (ret < 0) { - dev_err(sdev->dev, "error: failed to add route sink %s control %s source %s\n", + dev_err(scomp->dev, "error: failed to add route sink %s control %s source %s\n", route->sink, route->control ? route->control : "none", route->source); @@ -3248,7 +3246,7 @@ static int sof_route_load(struct snd_soc_component *scomp, int index, /* check IPC reply */ if (reply.error < 0) { - dev_err(sdev->dev, "error: DSP failed to add route sink %s control %s source %s result %d\n", + dev_err(scomp->dev, "error: DSP failed to add route sink %s control %s source %s result %d\n", route->sink, route->control ? route->control : "none", route->source, reply.error); @@ -3275,8 +3273,9 @@ err: /* Function to set the initial value of SOF kcontrols. * The value will be stored in scontrol->control_data */ -static int snd_sof_cache_kcontrol_val(struct snd_sof_dev *sdev) +static int snd_sof_cache_kcontrol_val(struct snd_soc_component *scomp) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_control *scontrol = NULL; int ipc_cmd, ctrl_type; int ret = 0; @@ -3296,33 +3295,34 @@ static int snd_sof_cache_kcontrol_val(struct snd_sof_dev *sdev) ctrl_type = SOF_CTRL_TYPE_DATA_GET; break; default: - dev_err(sdev->dev, + dev_err(scomp->dev, "error: Invalid scontrol->cmd: %d\n", scontrol->cmd); return -EINVAL; } - ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, + ret = snd_sof_ipc_set_get_comp_data(scontrol, ipc_cmd, ctrl_type, scontrol->cmd, false); if (ret < 0) { - dev_warn(sdev->dev, - "error: kcontrol value get for widget: %d\n", - scontrol->comp_id); + dev_warn(scomp->dev, + "error: kcontrol value get for widget: %d\n", + scontrol->comp_id); } } return ret; } -int snd_sof_complete_pipeline(struct snd_sof_dev *sdev, +int snd_sof_complete_pipeline(struct device *dev, struct snd_sof_widget *swidget) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct sof_ipc_pipe_ready ready; struct sof_ipc_reply reply; int ret; - dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n", + dev_dbg(dev, "tplg: complete pipeline %s id %d\n", swidget->widget->name, swidget->comp_id); memset(&ready, 0, sizeof(ready)); @@ -3352,7 +3352,7 @@ static void sof_complete(struct snd_soc_component *scomp) switch (swidget->id) { case snd_soc_dapm_scheduler: swidget->complete = - snd_sof_complete_pipeline(sdev, swidget); + snd_sof_complete_pipeline(scomp->dev, swidget); break; default: break; @@ -3362,14 +3362,13 @@ static void sof_complete(struct snd_soc_component *scomp) * cache initial values of SOF kcontrols by reading DSP value over * IPC. It may be overwritten by alsa-mixer after booting up */ - snd_sof_cache_kcontrol_val(sdev); + snd_sof_cache_kcontrol_val(scomp); } /* manifest - optional to inform component of manifest */ static int sof_manifest(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_manifest *man) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); u32 size; u32 abi_version; @@ -3377,16 +3376,16 @@ static int sof_manifest(struct snd_soc_component *scomp, int index, /* backward compatible with tplg without ABI info */ if (!size) { - dev_dbg(sdev->dev, "No topology ABI info\n"); + dev_dbg(scomp->dev, "No topology ABI info\n"); return 0; } if (size != SOF_TPLG_ABI_SIZE) { - dev_err(sdev->dev, "error: invalid topology ABI size\n"); + dev_err(scomp->dev, "error: invalid topology ABI size\n"); return -EINVAL; } - dev_info(sdev->dev, + dev_info(scomp->dev, "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n", man->priv.data[0], man->priv.data[1], man->priv.data[2], SOF_ABI_MAJOR, SOF_ABI_MINOR, @@ -3397,15 +3396,15 @@ static int sof_manifest(struct snd_soc_component *scomp, int index, man->priv.data[2]); if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, abi_version)) { - dev_err(sdev->dev, "error: incompatible topology ABI version\n"); + dev_err(scomp->dev, "error: incompatible topology ABI version\n"); return -EINVAL; } if (abi_version > SOF_ABI_VERSION) { if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) { - dev_warn(sdev->dev, "warn: topology ABI is more recent than kernel\n"); + dev_warn(scomp->dev, "warn: topology ABI is more recent than kernel\n"); } else { - dev_err(sdev->dev, "error: topology ABI is more recent than kernel\n"); + dev_err(scomp->dev, "error: topology ABI is more recent than kernel\n"); return -EINVAL; } } @@ -3463,25 +3462,25 @@ static struct snd_soc_tplg_ops sof_tplg_ops = { .bytes_ext_ops_count = ARRAY_SIZE(sof_bytes_ext_ops), }; -int snd_sof_load_topology(struct snd_sof_dev *sdev, const char *file) +int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) { const struct firmware *fw; int ret; - dev_dbg(sdev->dev, "loading topology:%s\n", file); + dev_dbg(scomp->dev, "loading topology:%s\n", file); - ret = request_firmware(&fw, file, sdev->dev); + ret = request_firmware(&fw, file, scomp->dev); if (ret < 0) { - dev_err(sdev->dev, "error: tplg request firmware %s failed err: %d\n", + dev_err(scomp->dev, "error: tplg request firmware %s failed err: %d\n", file, ret); return ret; } - ret = snd_soc_tplg_component_load(sdev->component, + ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw, SND_SOC_TPLG_INDEX_ALL); if (ret < 0) { - dev_err(sdev->dev, "error: tplg component load failed %d\n", + dev_err(scomp->dev, "error: tplg component load failed %d\n", ret); ret = -EINVAL; } -- cgit v1.2.3 From 80acdd4f8ff763183dc1cd7f1cd31db9eaaecdc8 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:52 -0600 Subject: ASoC: SOF: intel: hda: Modify signature for hda_codec_probe_bus() The machine driver selection for HDA platforms will be consolidated and moved out of the SOF DSP probe callback. In preparation for that, modify the signature for hda_codec_probe_bus() to pass the hda_codec_use_common_hdmi as a variable while probing the HDA codecs. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 16 ++++++---------- sound/soc/sof/intel/hda.c | 2 +- sound/soc/sof/intel/hda.h | 3 ++- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 827f84a0722e..65761e095184 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -80,12 +80,11 @@ EXPORT_SYMBOL(hda_codec_jack_wake_enable); EXPORT_SYMBOL(hda_codec_jack_check); /* probe individual codec */ -static int hda_codec_probe(struct snd_sof_dev *sdev, int address) +static int hda_codec_probe(struct snd_sof_dev *sdev, int address, + bool hda_codec_use_common_hdmi) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) struct hdac_hda_priv *hda_priv; - struct snd_soc_acpi_mach_params *mach_params = NULL; - struct snd_sof_pdata *pdata = sdev->pdata; #endif struct hda_bus *hbus = sof_to_hbus(sdev); struct hdac_device *hdev; @@ -115,10 +114,6 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) if (ret < 0) return ret; - if (pdata->machine) - mach_params = (struct snd_soc_acpi_mach_params *) - &pdata->machine->mach_params; - if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) hda_priv->need_display_power = true; @@ -126,7 +121,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) * if common HDMI codec driver is not used, codec load * is skipped here and hdac_hdmi is used instead */ - if ((mach_params && mach_params->common_hdmi_codec_drv) || + if (hda_codec_use_common_hdmi || (resp & 0xFFFF0000) != IDISP_VID_INTEL) { hdev->type = HDA_DEV_LEGACY; hda_codec_load_module(&hda_priv->codec); @@ -145,7 +140,8 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) } /* Codec initialization */ -int hda_codec_probe_bus(struct snd_sof_dev *sdev) +int hda_codec_probe_bus(struct snd_sof_dev *sdev, + bool hda_codec_use_common_hdmi) { struct hdac_bus *bus = sof_to_bus(sdev); int i, ret; @@ -156,7 +152,7 @@ int hda_codec_probe_bus(struct snd_sof_dev *sdev) if (!(bus->codec_mask & (1 << i))) continue; - ret = hda_codec_probe(sdev, i); + ret = hda_codec_probe(sdev, i, hda_codec_use_common_hdmi); if (ret < 0) { dev_err(bus->dev, "error: codec #%d probe error, ret: %d\n", i, ret); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 98512a338748..bfdb817b3780 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -476,7 +476,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) } /* create codec instances */ - hda_codec_probe_bus(sdev); + hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi); hda_codec_i915_put(sdev); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 63df888dddb6..4a6f76572658 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -575,7 +575,8 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev); /* * HDA Codec operations. */ -int hda_codec_probe_bus(struct snd_sof_dev *sdev); +int hda_codec_probe_bus(struct snd_sof_dev *sdev, + bool hda_codec_use_common_hdmi); void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev); void hda_codec_jack_check(struct snd_sof_dev *sdev); -- cgit v1.2.3 From 285880a23d105e5d34b311b0c44061dffb07e405 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 4 Dec 2019 15:15:53 -0600 Subject: ASoC: SOF: Make creation of machine device from SOF core optional Currently, SOF probes machine drivers by creating a platform device and passing the machine description as private data. This is driven by the ACPI restrictions. Ideally, ACPI tables should contain the description for the machine driver. This is not possible because ACPI tables are frozen and used on multiple OS-es (e.g Windows). In the case of Device Tree we don't have this restriction, so we choose to probe the machine drivers by creating a DT node as is the standard ALSA way. This patch makes the probing of machine drivers from SOF core optional allowing for Device Tree platforms to decouple the SOF core from machine driver probing. Along with this, it also consolidates the machine driver selection for Intel platforms by defining optional ops for selecting the machine driver based on the ACPI match for HDA and non-HDA platforms and setting the mach params. Signed-off-by: Daniel Baluta Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 59 +---------- sound/soc/sof/intel/apl.c | 7 ++ sound/soc/sof/intel/bdw.c | 33 +++++++ sound/soc/sof/intel/byt.c | 45 +++++++++ sound/soc/sof/intel/cnl.c | 7 ++ sound/soc/sof/intel/hda.c | 227 ++++++++++++++++++++++++------------------- sound/soc/sof/intel/hda.h | 5 + sound/soc/sof/nocodec.c | 1 - sound/soc/sof/ops.h | 34 +++++++ sound/soc/sof/sof-acpi-dev.c | 29 +----- sound/soc/sof/sof-audio.c | 80 +++++++++++++++ sound/soc/sof/sof-audio.h | 4 + sound/soc/sof/sof-of-dev.c | 22 +---- sound/soc/sof/sof-pci-dev.c | 28 +----- sound/soc/sof/sof-priv.h | 11 +++ 15 files changed, 361 insertions(+), 231 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 9832322adbec..e258f6a8e7a5 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -92,47 +92,9 @@ out: } EXPORT_SYMBOL(snd_sof_get_status); -/* - * SOF Driver enumeration. - */ -static int sof_machine_check(struct snd_sof_dev *sdev) -{ - struct snd_sof_pdata *plat_data = sdev->pdata; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) - struct snd_soc_acpi_mach *machine; - int ret; -#endif - - if (plat_data->machine) - return 0; - -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) - dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); - return -ENODEV; -#else - /* fallback to nocodec mode */ - dev_warn(sdev->dev, "No ASoC machine driver found - using nocodec\n"); - machine = devm_kzalloc(sdev->dev, sizeof(*machine), GFP_KERNEL); - if (!machine) - return -ENOMEM; - - ret = sof_nocodec_setup(sdev->dev, plat_data, machine, - plat_data->desc, plat_data->desc->ops); - if (ret < 0) - return ret; - - plat_data->machine = machine; - - return 0; -#endif -} - static int sof_probe_continue(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; - const char *drv_name; - const void *mach; - int size; int ret; /* probe the DSP hardware */ @@ -218,22 +180,9 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) goto fw_run_err; } - drv_name = plat_data->machine->drv_name; - mach = (const void *)plat_data->machine; - size = sizeof(*plat_data->machine); - - /* register machine driver, pass machine info as pdata */ - plat_data->pdev_mach = - platform_device_register_data(sdev->dev, drv_name, - PLATFORM_DEVID_NONE, mach, size); - - if (IS_ERR(plat_data->pdev_mach)) { - ret = PTR_ERR(plat_data->pdev_mach); + ret = snd_sof_machine_register(sdev, plat_data); + if (ret < 0) goto fw_run_err; - } - - dev_dbg(sdev->dev, "created machine %s\n", - dev_name(&plat_data->pdev_mach->dev)); /* * Some platforms in SOF, ex: BYT, may not have their platform PM @@ -363,9 +312,7 @@ int snd_sof_device_remove(struct device *dev) * will remove the component driver and unload the topology * before freeing the snd_card. */ - if (!IS_ERR_OR_NULL(pdata->pdev_mach)) - platform_device_unregister(pdata->pdev_mach); - + snd_sof_machine_unregister(sdev, pdata); /* * Unregistering the machine driver results in unloading the topology. * Some widgets, ex: scheduler, attempt to power down the core they are diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 6f45e14f2b2e..aeed1422900b 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -17,6 +17,7 @@ #include "../sof-priv.h" #include "hda.h" +#include "../sof-audio.h" static const struct snd_sof_debugfs_map apl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, @@ -52,6 +53,12 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .ipc_msg_data = hda_ipc_msg_data, .ipc_pcm_params = hda_ipc_pcm_params, + /* machine driver */ + .machine_select = hda_machine_select, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + .set_mach_params = hda_set_mach_params, + /* debug */ .debug_map = apl_dsp_debugfs, .debug_map_count = ARRAY_SIZE(apl_dsp_debugfs), diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 141dad554764..c09885c0eb7d 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -17,6 +17,7 @@ #include #include "../ops.h" #include "shim.h" +#include "../sof-audio.h" /* BARs */ #define BDW_DSP_BAR 0 @@ -536,6 +537,32 @@ static int bdw_probe(struct snd_sof_dev *sdev) return ret; } +static void bdw_machine_select(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_soc_acpi_mach *mach; + + mach = snd_soc_acpi_find_machine(desc->machines); + if (!mach) { + dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n"); + return; + } + + sof_pdata->tplg_filename = mach->sof_tplg_filename; + mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc; + sof_pdata->machine = mach; +} + +static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach, + struct device *dev) +{ + struct snd_soc_acpi_mach_params *mach_params; + + mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; + mach_params->platform = dev_name(dev); +} + /* Broadwell DAIs */ static struct snd_soc_dai_driver bdw_dai[] = { { @@ -574,6 +601,12 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_select = bdw_machine_select, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + .set_mach_params = bdw_set_mach_params, + /* debug */ .debug_map = bdw_debugfs, .debug_map_count = ARRAY_SIZE(bdw_debugfs), diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 2abf80b3eb52..2f5db1a8c701 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -17,6 +17,7 @@ #include #include "../ops.h" #include "shim.h" +#include "../sof-audio.h" /* DSP memories */ #define IRAM_OFFSET 0x0C0000 @@ -382,6 +383,32 @@ static int byt_reset(struct snd_sof_dev *sdev) return 0; } +static void byt_machine_select(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_soc_acpi_mach *mach; + + mach = snd_soc_acpi_find_machine(desc->machines); + if (!mach) { + dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n"); + return; + } + + sof_pdata->tplg_filename = mach->sof_tplg_filename; + mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc; + sof_pdata->machine = mach; +} + +static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach, + struct device *dev) +{ + struct snd_soc_acpi_mach_params *mach_params; + + mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; + mach_params->platform = dev_name(dev); +} + /* Baytrail DAIs */ static struct snd_soc_dai_driver byt_dai[] = { { @@ -514,6 +541,12 @@ const struct snd_sof_dsp_ops sof_tng_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_select = byt_machine_select, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + .set_mach_params = byt_set_mach_params, + /* debug */ .debug_map = byt_debugfs, .debug_map_count = ARRAY_SIZE(byt_debugfs), @@ -682,6 +715,12 @@ const struct snd_sof_dsp_ops sof_byt_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_select = byt_machine_select, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + .set_mach_params = byt_set_mach_params, + /* debug */ .debug_map = byt_debugfs, .debug_map_count = ARRAY_SIZE(byt_debugfs), @@ -748,6 +787,12 @@ const struct snd_sof_dsp_ops sof_cht_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_select = byt_machine_select, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + .set_mach_params = byt_set_mach_params, + /* debug */ .debug_map = cht_debugfs, .debug_map_count = ARRAY_SIZE(cht_debugfs), diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 9bd169e2691e..6b44f6d02082 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -18,6 +18,7 @@ #include "../ops.h" #include "hda.h" #include "hda-ipc.h" +#include "../sof-audio.h" static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, @@ -238,6 +239,12 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .ipc_msg_data = hda_ipc_msg_data, .ipc_pcm_params = hda_ipc_pcm_params, + /* machine driver */ + .machine_select = hda_machine_select, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + .set_mach_params = hda_set_mach_params, + /* debug */ .debug_map = cnl_dsp_debugfs, .debug_map_count = ARRAY_SIZE(cnl_dsp_debugfs), diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index bfdb817b3780..8d27846d9048 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -344,16 +344,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) struct hdac_bus *bus = sof_to_bus(sdev); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) struct hdac_ext_link *hlink; - struct snd_soc_acpi_mach_params *mach_params; - struct snd_soc_acpi_mach *hda_mach; - struct snd_sof_pdata *pdata = sdev->pdata; - struct snd_soc_acpi_mach *mach; - const char *tplg_filename; - const char *idisp_str; - const char *dmic_str; - int dmic_num = 0; - int codec_num = 0; - int i; #endif int ret = 0; @@ -387,94 +377,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); - /* codec detection */ - if (!bus->codec_mask) { - dev_info(bus->dev, "no hda codecs found!\n"); - } else { - dev_info(bus->dev, "hda codecs found, mask %lx\n", - bus->codec_mask); - - for (i = 0; i < HDA_MAX_CODECS; i++) { - if (bus->codec_mask & (1 << i)) - codec_num++; - } - - /* - * If no machine driver is found, then: - * - * hda machine driver is used if : - * 1. there is one HDMI codec and one external HDAudio codec - * 2. only HDMI codec - */ - if (!pdata->machine && codec_num <= 2 && - HDA_IDISP_CODEC(bus->codec_mask)) { - hda_mach = snd_soc_acpi_intel_hda_machines; - pdata->machine = hda_mach; - - /* topology: use the info from hda_machines */ - pdata->tplg_filename = - hda_mach->sof_tplg_filename; - - /* - * firmware: pick the first in machine list, - * or use nocodec firmware name if list is empty - */ - mach = pdata->desc->machines; - if (mach->id[0]) - pdata->fw_filename = mach->sof_fw_filename; - else - pdata->fw_filename = - pdata->desc->nocodec_fw_filename; - - dev_info(bus->dev, "using HDA machine driver %s now\n", - hda_mach->drv_name); - - if (codec_num == 1) - idisp_str = "-idisp"; - else - idisp_str = ""; - - /* first check NHLT for DMICs */ - dmic_num = check_nhlt_dmic(sdev); - - /* allow for module parameter override */ - if (hda_dmic_num != -1) - dmic_num = hda_dmic_num; - - switch (dmic_num) { - case 2: - dmic_str = "-2ch"; - break; - case 4: - dmic_str = "-4ch"; - break; - default: - dmic_num = 0; - dmic_str = ""; - break; - } - - tplg_filename = pdata->tplg_filename; - tplg_filename = fixup_tplg_name(sdev, tplg_filename, - idisp_str, dmic_str); - if (!tplg_filename) { - hda_codec_i915_exit(sdev); - return ret; - } - pdata->tplg_filename = tplg_filename; - } - } - - /* used by hda machine driver to create dai links */ - if (pdata->machine) { - mach_params = (struct snd_soc_acpi_mach_params *) - &pdata->machine->mach_params; - mach_params->codec_mask = bus->codec_mask; - mach_params->platform = dev_name(sdev->dev); - mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi; - mach_params->dmic_num = dmic_num; - } - /* create codec instances */ hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi); @@ -763,4 +665,133 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +static int hda_generic_machine_select(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + struct snd_soc_acpi_mach_params *mach_params; + struct snd_soc_acpi_mach *hda_mach; + struct snd_sof_pdata *pdata = sdev->pdata; + const char *tplg_filename; + const char *idisp_str; + const char *dmic_str; + int dmic_num = 0; + int codec_num = 0; + int i; + + /* codec detection */ + if (!bus->codec_mask) { + dev_info(bus->dev, "no hda codecs found!\n"); + } else { + dev_info(bus->dev, "hda codecs found, mask %lx\n", + bus->codec_mask); + + for (i = 0; i < HDA_MAX_CODECS; i++) { + if (bus->codec_mask & (1 << i)) + codec_num++; + } + + /* + * If no machine driver is found, then: + * + * hda machine driver is used if : + * 1. there is one HDMI codec and one external HDAudio codec + * 2. only HDMI codec + */ + if (!pdata->machine && codec_num <= 2 && + HDA_IDISP_CODEC(bus->codec_mask)) { + hda_mach = snd_soc_acpi_intel_hda_machines; + + /* topology: use the info from hda_machines */ + pdata->tplg_filename = + hda_mach->sof_tplg_filename; + + dev_info(bus->dev, "using HDA machine driver %s now\n", + hda_mach->drv_name); + + if (codec_num == 1) + idisp_str = "-idisp"; + else + idisp_str = ""; + + /* first check NHLT for DMICs */ + dmic_num = check_nhlt_dmic(sdev); + + /* allow for module parameter override */ + if (hda_dmic_num != -1) + dmic_num = hda_dmic_num; + + switch (dmic_num) { + case 2: + dmic_str = "-2ch"; + break; + case 4: + dmic_str = "-4ch"; + break; + default: + dmic_num = 0; + dmic_str = ""; + break; + } + + tplg_filename = pdata->tplg_filename; + tplg_filename = fixup_tplg_name(sdev, tplg_filename, + idisp_str, dmic_str); + if (!tplg_filename) + return -EINVAL; + + pdata->machine = hda_mach; + pdata->tplg_filename = tplg_filename; + } + } + + /* used by hda machine driver to create dai links */ + if (pdata->machine) { + mach_params = (struct snd_soc_acpi_mach_params *) + &pdata->machine->mach_params; + mach_params->codec_mask = bus->codec_mask; + mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi; + mach_params->dmic_num = dmic_num; + } + + return 0; +} +#else +static int hda_generic_machine_select(struct snd_sof_dev *sdev) +{ + return 0; +} +#endif + +void hda_set_mach_params(const struct snd_soc_acpi_mach *mach, + struct device *dev) +{ + struct snd_soc_acpi_mach_params *mach_params; + + mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; + mach_params->platform = dev_name(dev); +} + +void hda_machine_select(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_soc_acpi_mach *mach; + + mach = snd_soc_acpi_find_machine(desc->machines); + if (mach) { + sof_pdata->tplg_filename = mach->sof_tplg_filename; + sof_pdata->machine = mach; + } + + /* + * Choose HDA generic machine driver if mach is NULL. + * Otherwise, set certain mach params. + */ + hda_generic_machine_select(sdev); + + if (!sof_pdata->machine) + dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n"); +} + MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 4a6f76572658..01529c7058f3 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -624,4 +624,9 @@ extern const struct sof_intel_dsp_desc tgl_chip_info; extern const struct sof_intel_dsp_desc ehl_chip_info; extern const struct sof_intel_dsp_desc jsl_chip_info; +/* machine driver select */ +void hda_machine_select(struct snd_sof_dev *sdev); +void hda_set_mach_params(const struct snd_soc_acpi_mach *mach, + struct device *dev); + #endif diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 3d128e5a132c..0a2167f19f25 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -77,7 +77,6 @@ int sof_nocodec_setup(struct device *dev, sof_pdata->drv_name = "sof-nocodec"; mach->drv_name = "sof-nocodec"; - sof_pdata->fw_filename = desc->nocodec_fw_filename; sof_pdata->tplg_filename = desc->nocodec_tplg_filename; /* create dummy BE dai_links */ diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 93512dcbaacd..e929a6e0058f 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -391,6 +391,40 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev, return 0; } +/* machine driver */ +static inline int +snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata) +{ + if (sof_ops(sdev) && sof_ops(sdev)->machine_register) + return sof_ops(sdev)->machine_register(sdev, pdata); + + return 0; +} + +static inline void +snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) +{ + if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister) + sof_ops(sdev)->machine_unregister(sdev, pdata); +} + +static inline void +snd_sof_machine_select(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev) && sof_ops(sdev)->machine_select) + sof_ops(sdev)->machine_select(sdev); +} + +static inline void +snd_sof_set_mach_params(const struct snd_soc_acpi_mach *mach, + struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + + if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params) + sof_ops(sdev)->set_mach_params(mach, dev); +} + static inline const struct snd_sof_dsp_ops *sof_get_ops(const struct sof_dev_desc *d, const struct sof_ops_table mach_ops[], int asize) diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 22e13ef09811..8174b9a7da95 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -145,7 +145,6 @@ static int sof_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct sof_dev_desc *desc; - struct snd_soc_acpi_mach *mach; struct snd_sof_pdata *sof_pdata; const struct snd_sof_dsp_ops *ops; int ret; @@ -172,35 +171,9 @@ static int sof_acpi_probe(struct platform_device *pdev) return -ENODEV; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) - /* force nocodec mode */ - dev_warn(dev, "Force to use nocodec mode\n"); - mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL); - if (!mach) - return -ENOMEM; - ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops); - if (ret < 0) - return ret; -#else - /* find machine */ - mach = snd_soc_acpi_find_machine(desc->machines); - if (!mach) { - dev_warn(dev, "warning: No matching ASoC machine driver found\n"); - } else { - sof_pdata->fw_filename = mach->sof_fw_filename; - sof_pdata->tplg_filename = mach->sof_tplg_filename; - } -#endif - - if (mach) { - mach->mach_params.platform = dev_name(dev); - mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc; - } - - sof_pdata->machine = mach; sof_pdata->desc = desc; sof_pdata->dev = &pdev->dev; - sof_pdata->platform = dev_name(dev); + sof_pdata->fw_filename = desc->default_fw_filename; /* alternate fw and tplg filenames ? */ if (fw_path) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index bf99d040c9c1..9c3851bfe788 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -360,3 +360,83 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, return NULL; } +/* + * SOF Driver enumeration. + */ +int sof_machine_check(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_soc_acpi_mach *mach; + int ret; + + /* force nocodec mode */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) + dev_warn(sdev->dev, "Force to use nocodec mode\n"); + goto nocodec; +#endif + + /* find machine */ + snd_sof_machine_select(sdev); + if (sof_pdata->machine) { + snd_sof_set_mach_params(sof_pdata->machine, sdev->dev); + return 0; + } + +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) + dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); + return -ENODEV; +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) +nocodec: +#endif + /* select nocodec mode */ + dev_warn(sdev->dev, "Using nocodec machine driver\n"); + mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL); + if (!mach) + return -ENOMEM; + + ret = sof_nocodec_setup(sdev->dev, sof_pdata, mach, desc, desc->ops); + if (ret < 0) + return ret; + + sof_pdata->machine = mach; + snd_sof_set_mach_params(sof_pdata->machine, sdev->dev); + + return 0; +} +EXPORT_SYMBOL(sof_machine_check); + +int sof_machine_register(struct snd_sof_dev *sdev, void *pdata) +{ + struct snd_sof_pdata *plat_data = (struct snd_sof_pdata *)pdata; + const char *drv_name; + const void *mach; + int size; + + drv_name = plat_data->machine->drv_name; + mach = (const void *)plat_data->machine; + size = sizeof(*plat_data->machine); + + /* register machine driver, pass machine info as pdata */ + plat_data->pdev_mach = + platform_device_register_data(sdev->dev, drv_name, + PLATFORM_DEVID_NONE, mach, size); + if (IS_ERR(plat_data->pdev_mach)) + return PTR_ERR(plat_data->pdev_mach); + + dev_dbg(sdev->dev, "created machine %s\n", + dev_name(&plat_data->pdev_mach->dev)); + + return 0; +} +EXPORT_SYMBOL(sof_machine_register); + +void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) +{ + struct snd_sof_pdata *plat_data = (struct snd_sof_pdata *)pdata; + + if (!IS_ERR_OR_NULL(plat_data->pdev_mach)) + platform_device_unregister(plat_data->pdev_mach); +} +EXPORT_SYMBOL(sof_machine_unregister); diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 5703698633af..a62fb2da6a6e 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -204,4 +204,8 @@ int sof_restore_pipelines(struct device *dev); int sof_set_hw_params_upon_resume(struct device *dev); bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev); +/* Machine driver enumeration */ +int sof_machine_register(struct snd_sof_dev *sdev, void *pdata); +void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata); + #endif diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 81deb5582d77..170a5839150f 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -44,8 +44,6 @@ static int sof_of_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct sof_dev_desc *desc; - /*TODO: create a generic snd_soc_xxx_mach */ - struct snd_soc_acpi_mach *mach; struct snd_sof_pdata *sof_pdata; const struct snd_sof_dsp_ops *ops; int ret; @@ -67,27 +65,9 @@ static int sof_of_probe(struct platform_device *pdev) return -ENODEV; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) - /* force nocodec mode */ - dev_warn(dev, "Force to use nocodec mode\n"); - mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL); - if (!mach) - return -ENOMEM; - ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops); - if (ret < 0) - return ret; -#else - /* TODO: implement case where we actually have a codec */ - return -ENODEV; -#endif - - if (mach) - mach->mach_params.platform = dev_name(dev); - - sof_pdata->machine = mach; sof_pdata->desc = desc; sof_pdata->dev = &pdev->dev; - sof_pdata->platform = dev_name(dev); + sof_pdata->fw_filename = desc->default_fw_filename; /* TODO: read alternate fw and tplg filenames from DT */ sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 046bd57657ca..1c7b87392708 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -275,7 +275,6 @@ static int sof_pci_probe(struct pci_dev *pci, struct device *dev = &pci->dev; const struct sof_dev_desc *desc = (const struct sof_dev_desc *)pci_id->driver_data; - struct snd_soc_acpi_mach *mach; struct snd_sof_pdata *sof_pdata; const struct snd_sof_dsp_ops *ops; int ret; @@ -306,35 +305,10 @@ static int sof_pci_probe(struct pci_dev *pci, if (ret < 0) return ret; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) - /* force nocodec mode */ - dev_warn(dev, "Force to use nocodec mode\n"); - mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL); - if (!mach) { - ret = -ENOMEM; - goto release_regions; - } - ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops); - if (ret < 0) - goto release_regions; - -#else - /* find machine */ - mach = snd_soc_acpi_find_machine(desc->machines); - if (!mach) { - dev_warn(dev, "warning: No matching ASoC machine driver found\n"); - } else { - mach->mach_params.platform = dev_name(dev); - sof_pdata->fw_filename = mach->sof_fw_filename; - sof_pdata->tplg_filename = mach->sof_tplg_filename; - } -#endif /* CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE */ - sof_pdata->name = pci_name(pci); - sof_pdata->machine = mach; sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data; sof_pdata->dev = dev; - sof_pdata->platform = dev_name(dev); + sof_pdata->fw_filename = desc->default_fw_filename; /* alternate fw and tplg filenames ? */ if (fw_path) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index eae1fc209a65..54dd6d4b4c12 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -202,6 +202,15 @@ struct snd_sof_dsp_ops { int (*get_window_offset)(struct snd_sof_dev *sdev, u32 id);/* mandatory for common loader code */ + /* machine driver ops */ + int (*machine_register)(struct snd_sof_dev *sdev, + void *pdata); /* optional */ + void (*machine_unregister)(struct snd_sof_dev *sdev, + void *pdata); /* optional */ + void (*machine_select)(struct snd_sof_dev *sdev); /* optional */ + void (*set_mach_params)(const struct snd_soc_acpi_mach *mach, + struct device *dev); /* optional */ + /* DAI ops */ struct snd_soc_dai_driver *drv; int num_drv; @@ -511,4 +520,6 @@ int intel_pcm_open(struct snd_sof_dev *sdev, int intel_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); +int sof_machine_check(struct snd_sof_dev *sdev); + #endif -- cgit v1.2.3 From f4e4113b2aec2d344276ac07f78e80460eb8ebf8 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:54 -0600 Subject: ASoC: SOF: remove nocodec_fw_filename Remove nocodec_fw_filename from struct sof_dev_desc as it is not longer needed. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 1 - sound/soc/sof/sof-acpi-dev.c | 5 ----- sound/soc/sof/sof-of-dev.c | 1 - sound/soc/sof/sof-pci-dev.c | 10 ---------- 4 files changed, 17 deletions(-) (limited to 'sound/soc/sof') diff --git a/include/sound/sof.h b/include/sound/sof.h index 1723478db4a2..98a757d3a67d 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -84,7 +84,6 @@ struct sof_dev_desc { const void *chip_info; /* defaults for no codec mode */ - const char *nocodec_fw_filename; const char *nocodec_tplg_filename; /* defaults paths for firmware and topology files */ diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 8174b9a7da95..9c0a4eed5cc8 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -46,7 +46,6 @@ static const struct sof_dev_desc sof_acpi_haswell_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-hsw.ri", - .nocodec_fw_filename = "sof-hsw.ri", .nocodec_tplg_filename = "sof-hsw-nocodec.tplg", .ops = &sof_hsw_ops, .arch_ops = &sof_xtensa_arch_ops @@ -64,7 +63,6 @@ static const struct sof_dev_desc sof_acpi_broadwell_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-bdw.ri", - .nocodec_fw_filename = "sof-bdw.ri", .nocodec_tplg_filename = "sof-bdw-nocodec.tplg", .ops = &sof_bdw_ops, .arch_ops = &sof_xtensa_arch_ops @@ -84,7 +82,6 @@ static const struct sof_dev_desc sof_acpi_baytrailcr_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-byt.ri", - .nocodec_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt-nocodec.tplg", .ops = &sof_byt_ops, .arch_ops = &sof_xtensa_arch_ops @@ -100,7 +97,6 @@ static const struct sof_dev_desc sof_acpi_baytrail_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-byt.ri", - .nocodec_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt-nocodec.tplg", .ops = &sof_byt_ops, .arch_ops = &sof_xtensa_arch_ops @@ -116,7 +112,6 @@ static const struct sof_dev_desc sof_acpi_cherrytrail_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-cht.ri", - .nocodec_fw_filename = "sof-cht.ri", .nocodec_tplg_filename = "sof-cht-nocodec.tplg", .ops = &sof_cht_ops, .arch_ops = &sof_xtensa_arch_ops diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 170a5839150f..39ea8af6213f 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -20,7 +20,6 @@ static struct sof_dev_desc sof_of_imx8qxp_desc = { .default_fw_path = "imx/sof", .default_tplg_path = "imx/sof-tplg", .default_fw_filename = "sof-imx8.ri", - .nocodec_fw_filename = "sof-imx8.ri", .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", .ops = &sof_imx8_ops, }; diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 1c7b87392708..5f08a9ca6bf8 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -48,7 +48,6 @@ static const struct sof_dev_desc bxt_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-apl.ri", - .nocodec_fw_filename = "sof-apl.ri", .nocodec_tplg_filename = "sof-apl-nocodec.tplg", .ops = &sof_apl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -67,7 +66,6 @@ static const struct sof_dev_desc glk_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-glk.ri", - .nocodec_fw_filename = "sof-glk.ri", .nocodec_tplg_filename = "sof-glk-nocodec.tplg", .ops = &sof_apl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -96,7 +94,6 @@ static const struct sof_dev_desc tng_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-byt.ri", - .nocodec_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt.tplg", .ops = &sof_tng_ops, .arch_ops = &sof_xtensa_arch_ops @@ -115,7 +112,6 @@ static const struct sof_dev_desc cnl_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-cnl.ri", - .nocodec_fw_filename = "sof-cnl.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -134,7 +130,6 @@ static const struct sof_dev_desc cfl_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-cfl.ri", - .nocodec_fw_filename = "sof-cfl.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -155,7 +150,6 @@ static const struct sof_dev_desc cml_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-cml.ri", - .nocodec_fw_filename = "sof-cml.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -174,7 +168,6 @@ static const struct sof_dev_desc icl_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-icl.ri", - .nocodec_fw_filename = "sof-icl.ri", .nocodec_tplg_filename = "sof-icl-nocodec.tplg", .ops = &sof_cnl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -193,7 +186,6 @@ static const struct sof_dev_desc tgl_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-tgl.ri", - .nocodec_fw_filename = "sof-tgl.ri", .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", .ops = &sof_cnl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -212,7 +204,6 @@ static const struct sof_dev_desc ehl_desc = { .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", .default_fw_filename = "sof-ehl.ri", - .nocodec_fw_filename = "sof-ehl.ri", .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", .ops = &sof_cnl_ops, .arch_ops = &sof_xtensa_arch_ops @@ -230,7 +221,6 @@ static const struct sof_dev_desc jsl_desc = { .chip_info = &jsl_chip_info, .default_fw_path = "intel/sof", .default_tplg_path = "intel/sof-tplg", - .nocodec_fw_filename = "sof-jsl.ri", .nocodec_tplg_filename = "sof-jsl-nocodec.tplg", .ops = &sof_cnl_ops, .arch_ops = &sof_xtensa_arch_ops -- cgit v1.2.3 From 5ad1cece81db9b389526499ae2e784013c85f136 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 4 Dec 2019 15:15:55 -0600 Subject: ASoC: SOF: Remove unused drv_name in sof_pdata This field is only set but never used. Let's remove it to make code cleaner. Signed-off-by: Daniel Baluta Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 1 - sound/soc/sof/nocodec.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/include/sound/sof.h b/include/sound/sof.h index 98a757d3a67d..96625355aa94 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -22,7 +22,6 @@ struct snd_sof_dsp_ops; */ struct snd_sof_pdata { const struct firmware *fw; - const char *drv_name; const char *name; const char *platform; diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 0a2167f19f25..56d887545da3 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -74,8 +74,6 @@ int sof_nocodec_setup(struct device *dev, if (!mach) return -EINVAL; - sof_pdata->drv_name = "sof-nocodec"; - mach->drv_name = "sof-nocodec"; sof_pdata->tplg_filename = desc->nocodec_tplg_filename; -- cgit v1.2.3 From d612b455f120d05a42c95ccd7469fa13efb8d307 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 4 Dec 2019 15:15:56 -0600 Subject: ASoC: SOF: nocodec: Amend arguments for sof_nocodec_setup() Set the drv_name and tplg_filename for nocodec machine driver in sof_machine_check(). This means the sof_nocodec_setup() does not need the mach, plat_data or desc arguments any longer. Signed-off-by: Daniel Baluta Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191204211556.12671-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 3 --- sound/soc/sof/nocodec.c | 9 --------- sound/soc/sof/sof-audio.c | 5 ++++- 3 files changed, 4 insertions(+), 13 deletions(-) (limited to 'sound/soc/sof') diff --git a/include/sound/sof.h b/include/sound/sof.h index 96625355aa94..6ea74f1a9ec2 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -97,8 +97,5 @@ struct sof_dev_desc { }; int sof_nocodec_setup(struct device *dev, - struct snd_sof_pdata *sof_pdata, - struct snd_soc_acpi_mach *mach, - const struct sof_dev_desc *desc, const struct snd_sof_dsp_ops *ops); #endif diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 56d887545da3..2233146386cc 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -63,20 +63,11 @@ static int sof_nocodec_bes_setup(struct device *dev, } int sof_nocodec_setup(struct device *dev, - struct snd_sof_pdata *sof_pdata, - struct snd_soc_acpi_mach *mach, - const struct sof_dev_desc *desc, const struct snd_sof_dsp_ops *ops) { struct snd_soc_dai_link *links; int ret; - if (!mach) - return -EINVAL; - - mach->drv_name = "sof-nocodec"; - sof_pdata->tplg_filename = desc->nocodec_tplg_filename; - /* create dummy BE dai_links */ links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * ops->num_drv, GFP_KERNEL); diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 9c3851bfe788..0d8f65b9ae25 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -396,7 +396,10 @@ nocodec: if (!mach) return -ENOMEM; - ret = sof_nocodec_setup(sdev->dev, sof_pdata, mach, desc, desc->ops); + mach->drv_name = "sof-nocodec"; + sof_pdata->tplg_filename = desc->nocodec_tplg_filename; + + ret = sof_nocodec_setup(sdev->dev, desc->ops); if (ret < 0) return ret; -- cgit v1.2.3 From 433363e779ecb772c2e9ffea5c9f266115c24441 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Mon, 9 Dec 2019 18:48:47 -0600 Subject: ASoC: SOF: Add asynchronous sample rate converter topology support This patch adds into SOF topology the handling of ASRC DAPM type, adds the tokens to configure the ASRC, and implement component IPC into the driver. Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191210004854.16845-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 27 ++++++++++++++ include/uapi/sound/sof/abi.h | 2 +- include/uapi/sound/sof/tokens.h | 6 ++++ sound/soc/sof/topology.c | 78 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index c47b36240920..8e76178fedf0 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -36,6 +36,7 @@ enum sof_comp_type { SOF_COMP_KPB, /* A key phrase buffer component */ SOF_COMP_SELECTOR, /**< channel selector component */ SOF_COMP_DEMUX, + SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ /* keep FILEREAD/FILEWRITE as the last ones */ SOF_COMP_FILEREAD = 10000, /**< host test based file IO */ SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */ @@ -147,6 +148,32 @@ struct sof_ipc_comp_src { uint32_t rate_mask; /**< SOF_RATE_ supported rates */ } __packed; +/* generic ASRC component */ +struct sof_ipc_comp_asrc { + struct sof_ipc_comp comp; + struct sof_ipc_comp_config config; + /* either source or sink rate must be non zero */ + uint32_t source_rate; /**< Define fixed source rate or */ + /**< use 0 to indicate need to get */ + /**< the rate from stream */ + uint32_t sink_rate; /**< Define fixed sink rate or */ + /**< use 0 to indicate need to get */ + /**< the rate from stream */ + uint32_t asynchronous_mode; /**< synchronous 0, asynchronous 1 */ + /**< When 1 the ASRC tracks and */ + /**< compensates for drift. */ + uint32_t operation_mode; /**< push 0, pull 1, In push mode the */ + /**< ASRC consumes a defined number */ + /**< of frames at input, with varying */ + /**< number of frames at output. */ + /**< In pull mode the ASRC outputs */ + /**< a defined number of frames while */ + /**< number of input frames varies. */ + + /* reserved for future use */ + uint32_t reserved[4]; +} __attribute__((packed)); + /* generic MUX component */ struct sof_ipc_comp_mux { struct sof_ipc_comp comp; diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index ebfdc20ca081..c0ef1643c753 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 11 +#define SOF_ABI_MINOR 12 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 76883e6fb750..a9a5c4d0a892 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -57,6 +57,12 @@ #define SOF_TKN_SRC_RATE_IN 300 #define SOF_TKN_SRC_RATE_OUT 301 +/* ASRC */ +#define SOF_TKN_ASRC_RATE_IN 320 +#define SOF_TKN_ASRC_RATE_OUT 321 +#define SOF_TKN_ASRC_ASYNCHRONOUS_MODE 322 +#define SOF_TKN_ASRC_OPERATION_MODE 323 + /* PCM */ #define SOF_TKN_PCM_DMAC_CONFIG 353 diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 1ae06a1f9b0b..215f4d23ddfe 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -573,6 +573,20 @@ static const struct sof_topology_token src_tokens[] = { offsetof(struct sof_ipc_comp_src, sink_rate), 0}, }; +/* ASRC */ +static const struct sof_topology_token asrc_tokens[] = { + {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_comp_asrc, source_rate), 0}, + {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_comp_asrc, sink_rate), 0}, + {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + get_token_u32, + offsetof(struct sof_ipc_comp_asrc, asynchronous_mode), 0}, + {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + get_token_u32, + offsetof(struct sof_ipc_comp_asrc, operation_mode), 0}, +}; + /* Tone */ static const struct sof_topology_token tone_tokens[] = { }; @@ -1782,6 +1796,67 @@ err: return ret; } +/* + * ASRC Topology + */ + +static int sof_widget_load_asrc(struct snd_soc_component *scomp, int index, + struct snd_sof_widget *swidget, + struct snd_soc_tplg_dapm_widget *tw, + struct sof_ipc_comp_reply *r) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_private *private = &tw->priv; + struct sof_ipc_comp_asrc *asrc; + int ret; + + asrc = kzalloc(sizeof(*asrc), GFP_KERNEL); + if (!asrc) + return -ENOMEM; + + /* configure ASRC IPC message */ + asrc->comp.hdr.size = sizeof(*asrc); + asrc->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + asrc->comp.id = swidget->comp_id; + asrc->comp.type = SOF_COMP_ASRC; + asrc->comp.pipeline_id = index; + asrc->config.hdr.size = sizeof(asrc->config); + + ret = sof_parse_tokens(scomp, asrc, asrc_tokens, + ARRAY_SIZE(asrc_tokens), private->array, + le32_to_cpu(private->size)); + if (ret != 0) { + dev_err(scomp->dev, "error: parse asrc tokens failed %d\n", + private->size); + goto err; + } + + ret = sof_parse_tokens(scomp, &asrc->config, comp_tokens, + ARRAY_SIZE(comp_tokens), private->array, + le32_to_cpu(private->size)); + if (ret != 0) { + dev_err(scomp->dev, "error: parse asrc.cfg tokens failed %d\n", + le32_to_cpu(private->size)); + goto err; + } + + dev_dbg(scomp->dev, "asrc %s: source rate %d sink rate %d " + "asynch %d operation %d\n", + swidget->widget->name, asrc->source_rate, asrc->sink_rate, + asrc->asynchronous_mode, asrc->operation_mode); + sof_dbg_comp_config(scomp, &asrc->config); + + swidget->private = asrc; + + ret = sof_ipc_tx_message(sdev->ipc, asrc->comp.hdr.cmd, asrc, + sizeof(*asrc), r, sizeof(*r)); + if (ret >= 0) + return ret; +err: + kfree(asrc); + return ret; +} + /* * Signal Generator Topology */ @@ -2195,6 +2270,9 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, case snd_soc_dapm_src: ret = sof_widget_load_src(scomp, index, swidget, tw, &reply); break; + case snd_soc_dapm_asrc: + ret = sof_widget_load_asrc(scomp, index, swidget, tw, &reply); + break; case snd_soc_dapm_siggen: ret = sof_widget_load_siggen(scomp, index, swidget, tw, &reply); break; -- cgit v1.2.3 From 4f6250b82cb8f950a1b1bea62843a88bbb208187 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 9 Dec 2019 18:48:51 -0600 Subject: ASoC: SOF: Intel: add codec_mask module parameter Add a module parameter 'codec_mask' to filter out unwanted HDA codecs from driver probe. E.g. on most systems, codec_mask=4 will limit to HDMI audio and exclude any external HDA codecs. Similar to 'probe_mask' module parameter of snd-hda-intel. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191210004854.16845-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index df1909e1d950..871b71a15a63 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -15,11 +15,18 @@ * Hardware interface for generic Intel audio DSP HDA IP */ +#include #include #include #include "../ops.h" #include "hda.h" +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +static int hda_codec_mask = -1; +module_param_named(codec_mask, hda_codec_mask, int, 0444); +MODULE_PARM_DESC(codec_mask, "SOF HDA codec mask for probing"); +#endif + /* * HDA Operations. */ @@ -206,6 +213,12 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); } + + if (hda_codec_mask != -1) { + bus->codec_mask &= hda_codec_mask; + dev_dbg(bus->dev, "filtered codec_mask = 0x%lx\n", + bus->codec_mask); + } #endif /* clear stream status */ -- cgit v1.2.3 From 2aae447a4c100d2a7b7cae26b1df8b329e730d8b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 9 Dec 2019 18:48:53 -0600 Subject: ASoC: SOF: Intel: byt: fixup topology filename for BYT-CR On Baytrail-CR, SSP0 needs to be used instead of SSP2. The substitution is assumed to be done in the topology file. When Baytrail-CR is detected, add -ssp0 suffix to the topology file name so that the topology code picks up the correct file. Tested on Asus T100TAF Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191210004854.16845-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 2f5db1a8c701..ec6ca863243c 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -18,6 +18,7 @@ #include "../ops.h" #include "shim.h" #include "../sof-audio.h" +#include "../../intel/common/soc-intel-quirks.h" /* DSP memories */ #define IRAM_OFFSET 0x0C0000 @@ -383,11 +384,37 @@ static int byt_reset(struct snd_sof_dev *sdev) return 0; } +static const char *fixup_tplg_name(struct snd_sof_dev *sdev, + const char *sof_tplg_filename, + const char *ssp_str) +{ + const char *tplg_filename = NULL; + char *filename; + char *split_ext; + + filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL); + if (!filename) + return NULL; + + /* this assumes a .tplg extension */ + split_ext = strsep(&filename, "."); + if (split_ext) { + tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, + "%s-%s.tplg", + split_ext, ssp_str); + if (!tplg_filename) + return NULL; + } + return tplg_filename; +} + static void byt_machine_select(struct snd_sof_dev *sdev) { struct snd_sof_pdata *sof_pdata = sdev->pdata; const struct sof_dev_desc *desc = sof_pdata->desc; struct snd_soc_acpi_mach *mach; + struct platform_device *pdev; + const char *tplg_filename; mach = snd_soc_acpi_find_machine(desc->machines); if (!mach) { @@ -395,7 +422,25 @@ static void byt_machine_select(struct snd_sof_dev *sdev) return; } - sof_pdata->tplg_filename = mach->sof_tplg_filename; + pdev = to_platform_device(sdev->dev); + if (soc_intel_is_byt_cr(pdev)) { + dev_dbg(sdev->dev, + "BYT-CR detected, SSP0 used instead of SSP2\n"); + + tplg_filename = fixup_tplg_name(sdev, + mach->sof_tplg_filename, + "ssp0"); + } else { + tplg_filename = mach->sof_tplg_filename; + } + + if (!tplg_filename) { + dev_dbg(sdev->dev, + "error: no topology filename\n"); + return; + } + + sof_pdata->tplg_filename = tplg_filename; mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc; sof_pdata->machine = mach; } -- cgit v1.2.3 From 620ea8d26b99a5857b12a26f3673ad1fcd8abe9f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Dec 2019 15:53:59 +0100 Subject: ASoC: SOF: Drop superfluous ioctl PCM ops ASoC PCM core deals the empty ioctl field now as default. Let's kill the redundant lines. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20191210145406.21419-17-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 54ec78799c30..67ba317942d3 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -766,7 +766,6 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->remove = sof_pcm_remove; pd->open = sof_pcm_open; pd->close = sof_pcm_close; - pd->ioctl = snd_soc_pcm_lib_ioctl; pd->hw_params = sof_pcm_hw_params; pd->prepare = sof_pcm_prepare; pd->hw_free = sof_pcm_hw_free; -- cgit v1.2.3 From 57e960f0020ec46db277426762ba5ffe77e03e3c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Dec 2019 18:20:19 +0100 Subject: ASoC: SOF: Use managed buffer allocation Clean up the drivers with the new managed buffer allocation API. The superfluous snd_pcm_lib_malloc_pages() and snd_pcm_lib_free_pages() calls are dropped. Cc: Pierre-Louis Bossart Cc: Ranjani Sridharan Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20191211172019.23206-2-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 67ba317942d3..86829e5bd62d 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -118,20 +118,8 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, memset(&pcm, 0, sizeof(pcm)); - /* allocate audio buffer pages */ - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (ret < 0) { - dev_err(component->dev, "error: could not allocate %d bytes for PCM %d\n", - params_buffer_bytes(params), spcm->pcm.pcm_id); - return ret; - } - if (ret) { - /* - * ret == 1 means the buffer is changed - * create compressed page table for audio firmware - * ret == 0 means the buffer is not changed - * so no need to regenerate the page table - */ + /* create compressed page table for audio firmware */ + if (runtime->buffer_changed) { ret = create_page_table(component, substream, runtime->dma_area, runtime->dma_bytes); if (ret < 0) @@ -259,8 +247,6 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, err = ret; } - snd_pcm_lib_free_pages(substream); - cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); ret = snd_sof_pcm_platform_hw_free(sdev, substream); @@ -596,10 +582,10 @@ static int sof_pcm_new(struct snd_soc_component *component, "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n", caps->name, caps->buffer_size_min, caps->buffer_size_max); - snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream, - SNDRV_DMA_TYPE_DEV_SG, sdev->dev, - le32_to_cpu(caps->buffer_size_min), - le32_to_cpu(caps->buffer_size_max)); + snd_pcm_set_managed_buffer(pcm->streams[stream].substream, + SNDRV_DMA_TYPE_DEV_SG, sdev->dev, + le32_to_cpu(caps->buffer_size_min), + le32_to_cpu(caps->buffer_size_max)); capture: stream = SNDRV_PCM_STREAM_CAPTURE; @@ -614,10 +600,10 @@ capture: "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n", caps->name, caps->buffer_size_min, caps->buffer_size_max); - snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream, - SNDRV_DMA_TYPE_DEV_SG, sdev->dev, - le32_to_cpu(caps->buffer_size_min), - le32_to_cpu(caps->buffer_size_max)); + snd_pcm_set_managed_buffer(pcm->streams[stream].substream, + SNDRV_DMA_TYPE_DEV_SG, sdev->dev, + le32_to_cpu(caps->buffer_size_min), + le32_to_cpu(caps->buffer_size_max)); return 0; } -- cgit v1.2.3 From f4483a0fda1df3e5b4f25de647b8777d2481f08c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:24 -0600 Subject: ASoC: SOF: Intel: add module namespace for legacy IPC The legacy IPC routines are only used by broadwell and baytrail modules, import them as needed and make sure other modules cannot load them. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 1 + sound/soc/sof/intel/byt.c | 1 + sound/soc/sof/intel/intel-ipc.c | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index c09885c0eb7d..39d1c8c7cddf 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -642,3 +642,4 @@ const struct sof_intel_dsp_desc bdw_chip_info = { EXPORT_SYMBOL(bdw_chip_info); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index d43098a962c0..b214b12fdcda 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -877,3 +877,4 @@ EXPORT_SYMBOL(cht_chip_info); #endif /* CONFIG_SND_SOC_SOF_BAYTRAIL */ MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); diff --git a/sound/soc/sof/intel/intel-ipc.c b/sound/soc/sof/intel/intel-ipc.c index 4edd92151fd5..e935f70d611b 100644 --- a/sound/soc/sof/intel/intel-ipc.c +++ b/sound/soc/sof/intel/intel-ipc.c @@ -39,7 +39,7 @@ void intel_ipc_msg_data(struct snd_sof_dev *sdev, sof_mailbox_read(sdev, stream->posn_offset, p, sz); } } -EXPORT_SYMBOL(intel_ipc_msg_data); +EXPORT_SYMBOL_NS(intel_ipc_msg_data, SND_SOC_SOF_INTEL_HIFI_EP_IPC); int intel_ipc_pcm_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, @@ -60,7 +60,7 @@ int intel_ipc_pcm_params(struct snd_sof_dev *sdev, return 0; } -EXPORT_SYMBOL(intel_ipc_pcm_params); +EXPORT_SYMBOL_NS(intel_ipc_pcm_params, SND_SOC_SOF_INTEL_HIFI_EP_IPC); int intel_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) @@ -75,7 +75,7 @@ int intel_pcm_open(struct snd_sof_dev *sdev, return 0; } -EXPORT_SYMBOL(intel_pcm_open); +EXPORT_SYMBOL_NS(intel_pcm_open, SND_SOC_SOF_INTEL_HIFI_EP_IPC); int intel_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) @@ -87,6 +87,6 @@ int intel_pcm_close(struct snd_sof_dev *sdev, return 0; } -EXPORT_SYMBOL(intel_pcm_close); +EXPORT_SYMBOL_NS(intel_pcm_close, SND_SOC_SOF_INTEL_HIFI_EP_IPC); MODULE_LICENSE("Dual BSD/GPL"); -- cgit v1.2.3 From e42b19450866fbd447e459d8935c208e3888705a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:25 -0600 Subject: ASoC: SOF: Intel: add namespaces for BAYTRAIL and MERRIFIELD Define separate namespaces and include them in ACPI and PCI top-level modules. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 12 ++++++------ sound/soc/sof/sof-acpi-dev.c | 1 + sound/soc/sof/sof-pci-dev.c | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index b214b12fdcda..07634873deb6 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -619,13 +619,13 @@ const struct snd_sof_dsp_ops sof_tng_ops = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, }; -EXPORT_SYMBOL(sof_tng_ops); +EXPORT_SYMBOL_NS(sof_tng_ops, SND_SOC_SOF_MERRIFIELD); const struct sof_intel_dsp_desc tng_chip_info = { .cores_num = 1, .cores_mask = 1, }; -EXPORT_SYMBOL(tng_chip_info); +EXPORT_SYMBOL_NS(tng_chip_info, SND_SOC_SOF_MERRIFIELD); #endif /* CONFIG_SND_SOC_SOF_MERRIFIELD */ @@ -793,13 +793,13 @@ const struct snd_sof_dsp_ops sof_byt_ops = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, }; -EXPORT_SYMBOL(sof_byt_ops); +EXPORT_SYMBOL_NS(sof_byt_ops, SND_SOC_SOF_BAYTRAIL); const struct sof_intel_dsp_desc byt_chip_info = { .cores_num = 1, .cores_mask = 1, }; -EXPORT_SYMBOL(byt_chip_info); +EXPORT_SYMBOL_NS(byt_chip_info, SND_SOC_SOF_BAYTRAIL); /* cherrytrail and braswell ops */ const struct snd_sof_dsp_ops sof_cht_ops = { @@ -866,13 +866,13 @@ const struct snd_sof_dsp_ops sof_cht_ops = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, }; -EXPORT_SYMBOL(sof_cht_ops); +EXPORT_SYMBOL_NS(sof_cht_ops, SND_SOC_SOF_BAYTRAIL); const struct sof_intel_dsp_desc cht_chip_info = { .cores_num = 1, .cores_mask = 1, }; -EXPORT_SYMBOL(cht_chip_info); +EXPORT_SYMBOL_NS(cht_chip_info, SND_SOC_SOF_BAYTRAIL); #endif /* CONFIG_SND_SOC_SOF_BAYTRAIL */ diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 9c0a4eed5cc8..6d44d5802e29 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -240,3 +240,4 @@ static struct platform_driver snd_sof_acpi_driver = { module_platform_driver(snd_sof_acpi_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_BAYTRAIL); diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 5f08a9ca6bf8..0c67e5d7dc33 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -415,3 +415,4 @@ static struct pci_driver snd_sof_pci_driver = { module_pci_driver(snd_sof_pci_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_MERRIFIELD); -- cgit v1.2.3 From 8caa99bb5d8007fdd206ed6ba2fe4f881b1552c7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:26 -0600 Subject: ASoC: SOF: Intel: add namespace for BROADWELL Define namespace and include it in ACPI top-level module. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 4 ++-- sound/soc/sof/sof-acpi-dev.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 39d1c8c7cddf..f017089c7b2d 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -633,13 +633,13 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, }; -EXPORT_SYMBOL(sof_bdw_ops); +EXPORT_SYMBOL_NS(sof_bdw_ops, SND_SOC_SOF_BROADWELL); const struct sof_intel_dsp_desc bdw_chip_info = { .cores_num = 1, .cores_mask = 1, }; -EXPORT_SYMBOL(bdw_chip_info); +EXPORT_SYMBOL_NS(bdw_chip_info, SND_SOC_SOF_BROADWELL); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 6d44d5802e29..d8ed6bfa5ce7 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -241,3 +241,4 @@ module_platform_driver(snd_sof_acpi_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_BAYTRAIL); +MODULE_IMPORT_NS(SND_SOC_SOF_BROADWELL); -- cgit v1.2.3 From 1fa44098b683312b426bd05f1bfc0b5b1fa7860a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:27 -0600 Subject: ASoC: SOF: remove references to Haswell There are no known commercial devices using Haswell, and there is no support for Haswell in SOF so remove remaining definitions and structures. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 2 +- sound/soc/sof/intel/shim.h | 6 ++---- sound/soc/sof/sof-acpi-dev.c | 20 -------------------- 3 files changed, 3 insertions(+), 25 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 71a0fc075a63..827b0ec92522 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -28,7 +28,7 @@ config SND_SOC_SOF_ACPI select IOSF_MBI if X86 && PCI help This adds support for ACPI enumeration. This option is required - to enable Intel Haswell/Broadwell/Baytrail/Cherrytrail devices + to enable Intel Broadwell/Baytrail/Cherrytrail devices Say Y if you need this option If unsure select "N". diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index f7a3f62e45d4..daaf3364c177 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -12,7 +12,7 @@ #define __SOF_INTEL_SHIM_H /* - * SHIM registers for BYT, BSW, CHT, HSW, BDW + * SHIM registers for BYT, BSW, CHT, BDW */ #define SHIM_CSR (SHIM_OFFSET + 0x00) @@ -38,7 +38,7 @@ #define SHIM_PWMCTRL 0x1000 /* - * SST SHIM register bits for BYT, BSW, CHT HSW, BDW + * SST SHIM register bits for BYT, BSW, CHT, BDW * Register bit naming and functionaility can differ between devices. */ @@ -169,13 +169,11 @@ struct sof_intel_dsp_desc { extern const struct snd_sof_dsp_ops sof_tng_ops; extern const struct snd_sof_dsp_ops sof_byt_ops; extern const struct snd_sof_dsp_ops sof_cht_ops; -extern const struct snd_sof_dsp_ops sof_hsw_ops; extern const struct snd_sof_dsp_ops sof_bdw_ops; extern const struct sof_intel_dsp_desc byt_chip_info; extern const struct sof_intel_dsp_desc cht_chip_info; extern const struct sof_intel_dsp_desc bdw_chip_info; -extern const struct sof_intel_dsp_desc hsw_chip_info; extern const struct sof_intel_dsp_desc tng_chip_info; struct sof_intel_stream { diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index d8ed6bfa5ce7..9100d7c70bb2 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -35,23 +35,6 @@ MODULE_PARM_DESC(sof_acpi_debug, "SOF ACPI debug options (0x0 all off)"); #define SOF_ACPI_DISABLE_PM_RUNTIME BIT(0) -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HASWELL) -static const struct sof_dev_desc sof_acpi_haswell_desc = { - .machines = snd_soc_acpi_intel_haswell_machines, - .resindex_lpe_base = 0, - .resindex_pcicfg_base = 1, - .resindex_imr_base = -1, - .irqindex_host_ipc = 0, - .chip_info = &hsw_chip_info, - .default_fw_path = "intel/sof", - .default_tplg_path = "intel/sof-tplg", - .default_fw_filename = "sof-hsw.ri", - .nocodec_tplg_filename = "sof-hsw-nocodec.tplg", - .ops = &sof_hsw_ops, - .arch_ops = &sof_xtensa_arch_ops -}; -#endif - #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) static const struct sof_dev_desc sof_acpi_broadwell_desc = { .machines = snd_soc_acpi_intel_broadwell_machines, @@ -213,9 +196,6 @@ static int sof_acpi_remove(struct platform_device *pdev) } static const struct acpi_device_id sof_acpi_match[] = { -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HASWELL) - { "INT33C8", (unsigned long)&sof_acpi_haswell_desc }, -#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) { "INT3438", (unsigned long)&sof_acpi_broadwell_desc }, #endif -- cgit v1.2.3 From cf5629e4594c2164aa629d21a749c65ad594de95 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:28 -0600 Subject: ASoC: SOF: Intel: add namespace for HDA_COMMON Define namespace and include it in PCI top-level module. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 4 ++-- sound/soc/sof/intel/cnl.c | 12 ++++++------ sound/soc/sof/sof-pci-dev.c | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index aeed1422900b..97831d2c9df6 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -112,7 +112,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; -EXPORT_SYMBOL(sof_apl_ops); +EXPORT_SYMBOL_NS(sof_apl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc apl_chip_info = { /* Apollolake */ @@ -128,4 +128,4 @@ const struct sof_intel_dsp_desc apl_chip_info = { .ssp_count = APL_SSP_COUNT, .ssp_base_offset = APL_SSP_BASE_OFFSET, }; -EXPORT_SYMBOL(apl_chip_info); +EXPORT_SYMBOL_NS(apl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 6b44f6d02082..b27088e67c7b 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -298,7 +298,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; -EXPORT_SYMBOL(sof_cnl_ops); +EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc cnl_chip_info = { /* Cannonlake */ @@ -317,7 +317,7 @@ const struct sof_intel_dsp_desc cnl_chip_info = { .ssp_count = CNL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; -EXPORT_SYMBOL(cnl_chip_info); +EXPORT_SYMBOL_NS(cnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc icl_chip_info = { /* Icelake */ @@ -336,7 +336,7 @@ const struct sof_intel_dsp_desc icl_chip_info = { .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; -EXPORT_SYMBOL(icl_chip_info); +EXPORT_SYMBOL_NS(icl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc tgl_chip_info = { /* Tigerlake */ @@ -352,7 +352,7 @@ const struct sof_intel_dsp_desc tgl_chip_info = { .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; -EXPORT_SYMBOL(tgl_chip_info); +EXPORT_SYMBOL_NS(tgl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc ehl_chip_info = { /* Elkhartlake */ @@ -368,7 +368,7 @@ const struct sof_intel_dsp_desc ehl_chip_info = { .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; -EXPORT_SYMBOL(ehl_chip_info); +EXPORT_SYMBOL_NS(ehl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc jsl_chip_info = { /* Jasperlake */ @@ -385,4 +385,4 @@ const struct sof_intel_dsp_desc jsl_chip_info = { .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; -EXPORT_SYMBOL(jsl_chip_info); +EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 0c67e5d7dc33..20638f666189 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -416,3 +416,4 @@ module_pci_driver(snd_sof_pci_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_MERRIFIELD); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); -- cgit v1.2.3 From 6ca5cecbd1c1758666ab79446f19e0e61ed11444 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 17 Dec 2019 18:26:09 -0600 Subject: ASoC: SOF: Introduce state machine for FW boot Add a state machine for FW boot to track the different stages of FW boot and replace the boot_complete field with fw_state field in struct snd_sof_dev. This will be used to determine the actions to be performed during system suspend. One of the main motivations for adding this change is the fact that errors during the top-level SOF device probe cannot be propagated and therefore suspending the SOF device normally during system suspend could potentially run into errors. For example, with the current flow, if the FW boot failed for some reason and the system suspends, the SOF device suspend could fail because the CTX_SAVE IPC would be attempted even though the FW never really booted successfully causing it to time out. Another scenario that the state machine fixes is when the runtime suspend for the SOF device fails and the DSP is powered down nevertheless, the CTX_SAVE IPC during system suspend would timeout because the DSP is already powered down. Reviewed-by: Curtis Malainey Reviewed-by: Daniel Baluta Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191218002616.7652-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 50 +++++++++++++++++++++++++++++++++++++++- sound/soc/sof/intel/hda-loader.c | 1 - sound/soc/sof/intel/hda.c | 4 ++-- sound/soc/sof/ipc.c | 17 ++++---------- sound/soc/sof/loader.c | 19 ++++++++++----- sound/soc/sof/pm.c | 21 ++++++++++++++++- sound/soc/sof/sof-priv.h | 11 ++++++++- 7 files changed, 99 insertions(+), 24 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index e258f6a8e7a5..44f9c04d54aa 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -92,6 +92,46 @@ out: } EXPORT_SYMBOL(snd_sof_get_status); +/* + * FW Boot State Transition Diagram + * + * +-----------------------------------------------------------------------+ + * | | + * ------------------ ------------------ | + * | | | | | + * | BOOT_FAILED | | READY_FAILED |-------------------------+ | + * | | | | | | + * ------------------ ------------------ | | + * ^ ^ | | + * | | | | + * (FW Boot Timeout) (FW_READY FAIL) | | + * | | | | + * | | | | + * ------------------ | ------------------ | | + * | | | | | | | + * | IN_PROGRESS |---------------+------------->| COMPLETE | | | + * | | (FW Boot OK) (FW_READY OK) | | | | + * ------------------ ------------------ | | + * ^ | | | + * | | | | + * (FW Loading OK) (System Suspend/Runtime Suspend) + * | | | | + * | | | | + * ------------------ ------------------ | | | + * | | | |<-----+ | | + * | PREPARE | | NOT_STARTED |<---------------------+ | + * | | | |<---------------------------+ + * ------------------ ------------------ + * | ^ | ^ + * | | | | + * | +-----------------------+ | + * | (DSP Probe OK) | + * | | + * | | + * +------------------------------------+ + * (System Suspend/Runtime Suspend) + */ + static int sof_probe_continue(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; @@ -104,6 +144,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) return ret; } + sdev->fw_state = SOF_FW_BOOT_PREPARE; + /* check machine info */ ret = sof_machine_check(sdev); if (ret < 0) { @@ -143,7 +185,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) goto fw_load_err; } - /* boot the firmware */ + sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS; + + /* + * Boot the firmware. The FW boot status will be modified + * in snd_sof_run_firmware() depending on the outcome. + */ ret = snd_sof_run_firmware(sdev); if (ret < 0) { dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n", @@ -254,6 +301,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) sdev->pdata = plat_data; sdev->first_boot = true; + sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; dev_set_drvdata(dev, sdev); /* check all mandatory ops */ diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index b1783360fe10..1782f5092639 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -295,7 +295,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) /* init for booting wait */ init_waitqueue_head(&sdev->boot_wait); - sdev->boot_complete = false; /* prepare DMA for code loader stream */ tag = cl_stream_prepare(sdev, 0x40, stripped_firmware.size, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8d27846d9048..3335e0076180 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -168,7 +168,7 @@ void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags) panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_ADSP_ERROR_CODE_SKL + 0x4); - if (sdev->boot_complete) { + if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) { hda_dsp_get_registers(sdev, &xoops, &panic_info, stack, HDA_DSP_STACK_DUMP_SIZE); snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, @@ -195,7 +195,7 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) HDA_DSP_SRAM_REG_FW_STATUS); panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP); - if (sdev->boot_complete) { + if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) { hda_dsp_get_registers(sdev, &xoops, &panic_info, stack, HDA_DSP_STACK_DUMP_SIZE); snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 293c5ae8e882..6186c7ff0447 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -347,19 +347,12 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) break; case SOF_IPC_FW_READY: /* check for FW boot completion */ - if (!sdev->boot_complete) { + if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS) { err = sof_ops(sdev)->fw_ready(sdev, cmd); - if (err < 0) { - /* - * this indicates a mismatch in ABI - * between the driver and fw - */ - dev_err(sdev->dev, "error: ABI mismatch %d\n", - err); - } else { - /* firmware boot completed OK */ - sdev->boot_complete = true; - } + if (err < 0) + sdev->fw_state = SOF_FW_BOOT_READY_FAILED; + else + sdev->fw_state = SOF_FW_BOOT_COMPLETE; /* wake up firmware loader */ wake_up(&sdev->boot_wait); diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 432d12bd4937..31847aa3975d 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -512,7 +512,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) int init_core_mask; init_waitqueue_head(&sdev->boot_wait); - sdev->boot_complete = false; /* create read-only fw_version debugfs to store boot version info */ if (sdev->first_boot) { @@ -544,19 +543,27 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) init_core_mask = ret; - /* now wait for the DSP to boot */ - ret = wait_event_timeout(sdev->boot_wait, sdev->boot_complete, + /* + * now wait for the DSP to boot. There are 3 possible outcomes: + * 1. Boot wait times out indicating FW boot failure. + * 2. FW boots successfully and fw_ready op succeeds. + * 3. FW boots but fw_ready op fails. + */ + ret = wait_event_timeout(sdev->boot_wait, + sdev->fw_state > SOF_FW_BOOT_IN_PROGRESS, msecs_to_jiffies(sdev->boot_timeout)); if (ret == 0) { dev_err(sdev->dev, "error: firmware boot failure\n"); snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX | SOF_DBG_TEXT | SOF_DBG_PCI); - /* after this point FW_READY msg should be ignored */ - sdev->boot_complete = true; + sdev->fw_state = SOF_FW_BOOT_FAILED; return -EIO; } - dev_info(sdev->dev, "firmware boot complete\n"); + if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) + dev_info(sdev->dev, "firmware boot complete\n"); + else + return -EIO; /* FW boots but fw_ready op failed */ /* perform post fw run operations */ ret = snd_sof_dsp_post_fw_run(sdev); diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index d1a7b98886d1..84290bbeebdd 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -70,6 +70,8 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } + sdev->fw_state = SOF_FW_BOOT_PREPARE; + /* load the firmware */ ret = snd_sof_load_firmware(sdev); if (ret < 0) { @@ -79,7 +81,12 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } - /* boot the firmware */ + sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS; + + /* + * Boot the firmware. The FW boot status will be modified + * in snd_sof_run_firmware() depending on the outcome. + */ ret = snd_sof_run_firmware(sdev); if (ret < 0) { dev_err(sdev->dev, @@ -128,6 +135,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) if (!sof_ops(sdev)->suspend) return 0; + if (sdev->fw_state != SOF_FW_BOOT_COMPLETE) + goto power_down; + /* release trace */ snd_sof_release_trace(sdev); @@ -165,6 +175,12 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ret); } +power_down: + + /* return if the DSP was not probed successfully */ + if (sdev->fw_state == SOF_FW_BOOT_NOT_STARTED) + return 0; + /* power down all DSP cores */ if (runtime_suspend) ret = snd_sof_dsp_runtime_suspend(sdev); @@ -175,6 +191,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) "error: failed to power down DSP during suspend %d\n", ret); + /* reset FW state */ + sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; + return ret; } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 54dd6d4b4c12..220b35141c34 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -298,6 +298,15 @@ struct snd_sof_ipc_msg { bool ipc_complete; }; +enum snd_sof_fw_state { + SOF_FW_BOOT_NOT_STARTED = 0, + SOF_FW_BOOT_PREPARE, + SOF_FW_BOOT_IN_PROGRESS, + SOF_FW_BOOT_FAILED, + SOF_FW_BOOT_READY_FAILED, /* firmware booted but fw_ready op failed */ + SOF_FW_BOOT_COMPLETE, +}; + /* * SOF Device Level. */ @@ -319,7 +328,7 @@ struct snd_sof_dev { /* DSP firmware boot */ wait_queue_head_t boot_wait; - u32 boot_complete; + enum snd_sof_fw_state fw_state; u32 first_boot; /* work queue in case the probe is implemented in two steps */ -- cgit v1.2.3 From 59283959e82bd272a5e15e4ed5274cdd059fb532 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Tue, 17 Dec 2019 18:26:11 -0600 Subject: ASoC: SOF: log compiler name and version information Log information about used compilator and optimization level in sof firmware to host system. It will be helful to catch some compiler dependent bugs. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191218002616.7652-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 39 +++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-priv.h | 1 + 2 files changed, 40 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 31847aa3975d..235be4fc0862 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -32,6 +32,42 @@ static int get_ext_windows(struct snd_sof_dev *sdev, return 0; } +static int get_cc_info(struct snd_sof_dev *sdev, + struct sof_ipc_ext_data_hdr *ext_hdr) +{ + int ret; + + struct sof_ipc_cc_version *cc = + container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); + + dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", + cc->name, cc->major, cc->minor, cc->micro, cc->desc, + cc->optim); + + /* create read-only cc_version debugfs to store compiler version info */ + /* use local copy of the cc_version to prevent data corruption */ + if (sdev->first_boot) { + sdev->cc_version = devm_kmalloc(sdev->dev, cc->ext_hdr.hdr.size, + GFP_KERNEL); + + if (!sdev->cc_version) + return -ENOMEM; + + memcpy(sdev->cc_version, cc, cc->ext_hdr.hdr.size); + ret = snd_sof_debugfs_buf_item(sdev, sdev->cc_version, + cc->ext_hdr.hdr.size, + "cc_version", 0444); + + /* errors are only due to memory allocation, not debugfs */ + if (ret < 0) { + dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n"); + return ret; + } + } + + return 0; +} + /* parse the extended FW boot data structures from FW boot message */ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) { @@ -65,6 +101,9 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) case SOF_IPC_EXT_WINDOW: ret = get_ext_windows(sdev, ext_hdr); break; + case SOF_IPC_EXT_CC_INFO: + ret = get_cc_info(sdev, ext_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown ext header type %d size 0x%x\n", ext_hdr->type, ext_hdr->hdr.size); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 220b35141c34..3f1e1eb7c55f 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -361,6 +361,7 @@ struct snd_sof_dev { struct snd_dma_buffer dmab_bdl; struct sof_ipc_fw_ready fw_ready; struct sof_ipc_fw_version fw_version; + struct sof_ipc_cc_version *cc_version; /* topology */ struct snd_soc_tplg_ops *tplg_ops; -- cgit v1.2.3 From 91dce767cd0b08be9f1c87bb2de8e63391a72692 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 17 Dec 2019 18:26:13 -0600 Subject: ASoC: SOF: Intel: drop HDA codec upon probe failure In case a HDA codec probe fails, do not raise error immediately, but instead remove the codec from bus->codec_mask and continue probe for other codecs. This allows for more robust behaviour in cases where one codec in the system is faulty. SOF driver load can still proceed with the codecs that can be probed successfully. Probe may still fail if suitable machine driver is not found, but in many cases the generic HDA machine driver can operate with a subset of codecs. Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191218002616.7652-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 12 +++++------- sound/soc/sof/intel/hda.h | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 65761e095184..d7855b1f8e2e 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -140,8 +140,8 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, } /* Codec initialization */ -int hda_codec_probe_bus(struct snd_sof_dev *sdev, - bool hda_codec_use_common_hdmi) +void hda_codec_probe_bus(struct snd_sof_dev *sdev, + bool hda_codec_use_common_hdmi) { struct hdac_bus *bus = sof_to_bus(sdev); int i, ret; @@ -154,13 +154,11 @@ int hda_codec_probe_bus(struct snd_sof_dev *sdev, ret = hda_codec_probe(sdev, i, hda_codec_use_common_hdmi); if (ret < 0) { - dev_err(bus->dev, "error: codec #%d probe error, ret: %d\n", - i, ret); - return ret; + dev_warn(bus->dev, "codec #%d probe error, ret: %d\n", + i, ret); + bus->codec_mask &= ~BIT(i); } } - - return 0; } EXPORT_SYMBOL(hda_codec_probe_bus); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 01529c7058f3..47408ec0de40 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -575,8 +575,8 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev); /* * HDA Codec operations. */ -int hda_codec_probe_bus(struct snd_sof_dev *sdev, - bool hda_codec_use_common_hdmi); +void hda_codec_probe_bus(struct snd_sof_dev *sdev, + bool hda_codec_use_common_hdmi); void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev); void hda_codec_jack_check(struct snd_sof_dev *sdev); -- cgit v1.2.3 From d88cbd6feaf4b5de07d91f531112cf57ce821d78 Mon Sep 17 00:00:00 2001 From: Guido Roncarolo Date: Tue, 17 Dec 2019 18:26:16 -0600 Subject: ASoC: SOF: imx: Read SAI parameters and send them to DSP Follow example from Intel SSP. Signed-off-by: Guido Roncarolo Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191218002616.7652-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 8 ++++++ sound/soc/sof/topology.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 86829e5bd62d..9bb6388742e1 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -693,6 +693,14 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = dai->dai_config->esai.tdm_slots; channels->max = dai->dai_config->esai.tdm_slots; + dev_dbg(component->dev, + "channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; + case SOF_DAI_IMX_SAI: + channels->min = dai->dai_config->sai.tdm_slots; + channels->max = dai->dai_config->sai.tdm_slots; + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", channels->min, channels->max); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index e06fa7c7e502..9f4f8868b386 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -695,6 +695,13 @@ static const struct sof_topology_token esai_tokens[] = { offsetof(struct sof_ipc_dai_esai_params, mclk_id), 0}, }; +/* SAI */ +static const struct sof_topology_token sai_tokens[] = { + {SOF_TKN_IMX_SAI_MCLK_ID, + SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, + offsetof(struct sof_ipc_dai_sai_params, mclk_id), 0}, +}; + /* * DMIC PDM Tokens * SOF_TKN_INTEL_DMIC_PDM_CTRL_ID should be the first token @@ -2704,8 +2711,66 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_hw_config *hw_config, struct sof_ipc_dai_config *config) { - /*TODO: Add implementation */ - return 0; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_private *private = &cfg->priv; + struct sof_ipc_reply reply; + u32 size = sizeof(*config); + int ret; + + /* handle master/slave and inverted clocks */ + sof_dai_set_format(hw_config, config); + + /* init IPC */ + memset(&config->sai, 0, sizeof(struct sof_ipc_dai_sai_params)); + config->hdr.size = size; + + ret = sof_parse_tokens(scomp, &config->sai, sai_tokens, + ARRAY_SIZE(sai_tokens), private->array, + le32_to_cpu(private->size)); + if (ret != 0) { + dev_err(scomp->dev, "error: parse sai tokens failed %d\n", + le32_to_cpu(private->size)); + return ret; + } + + config->sai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); + config->sai.mclk_direction = hw_config->mclk_direction; + + config->sai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); + config->sai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); + config->sai.rx_slots = le32_to_cpu(hw_config->rx_slots); + config->sai.tx_slots = le32_to_cpu(hw_config->tx_slots); + + dev_info(scomp->dev, + "tplg: config SAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", + config->dai_index, config->format, + config->sai.mclk_rate, config->sai.tdm_slot_width, + config->sai.tdm_slots, config->sai.mclk_id); + + if (config->sai.tdm_slots < 1 || config->sai.tdm_slots > 8) { + dev_err(scomp->dev, "error: invalid channel count for SAI%d\n", + config->dai_index); + return -EINVAL; + } + + /* send message to DSP */ + ret = sof_ipc_tx_message(sdev->ipc, + config->hdr.cmd, config, size, &reply, + sizeof(reply)); + + if (ret < 0) { + dev_err(scomp->dev, "error: failed to set DAI config for SAI%d\n", + config->dai_index); + return ret; + } + + /* set config for all DAI's with name matching the link name */ + ret = sof_set_dai_config(sdev, size, link, config); + if (ret < 0) + dev_err(scomp->dev, "error: failed to save DAI config for SAI%d\n", + config->dai_index); + + return ret; } static int sof_link_esai_load(struct snd_soc_component *scomp, int index, -- cgit v1.2.3 From 5bd216c6a6b48d8ed0b3283bf7ba84fc3a566b25 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:29 -0600 Subject: ASoC: SOF: Intel: hda: add namespace for hda-codec functionality Define namespaces (one generic and one dedicated for i915) and include them in HDaudio top-level module. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 14 +++++++------- sound/soc/sof/intel/hda.c | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index d7855b1f8e2e..5514e6191ba4 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -76,8 +76,8 @@ void hda_codec_jack_check(struct snd_sof_dev *sdev) void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) {} void hda_codec_jack_check(struct snd_sof_dev *sdev) {} #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */ -EXPORT_SYMBOL(hda_codec_jack_wake_enable); -EXPORT_SYMBOL(hda_codec_jack_check); +EXPORT_SYMBOL_NS(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC); +EXPORT_SYMBOL_NS(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC); /* probe individual codec */ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, @@ -160,7 +160,7 @@ void hda_codec_probe_bus(struct snd_sof_dev *sdev, } } } -EXPORT_SYMBOL(hda_codec_probe_bus); +EXPORT_SYMBOL_NS(hda_codec_probe_bus, SND_SOC_SOF_HDA_AUDIO_CODEC); #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) || \ IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI) @@ -172,7 +172,7 @@ void hda_codec_i915_get(struct snd_sof_dev *sdev) dev_dbg(bus->dev, "Turning i915 HDAC power on\n"); snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); } -EXPORT_SYMBOL(hda_codec_i915_get); +EXPORT_SYMBOL_NS(hda_codec_i915_get, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); void hda_codec_i915_put(struct snd_sof_dev *sdev) { @@ -181,7 +181,7 @@ void hda_codec_i915_put(struct snd_sof_dev *sdev) dev_dbg(bus->dev, "Turning i915 HDAC power off\n"); snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); } -EXPORT_SYMBOL(hda_codec_i915_put); +EXPORT_SYMBOL_NS(hda_codec_i915_put, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); int hda_codec_i915_init(struct snd_sof_dev *sdev) { @@ -197,7 +197,7 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev) return 0; } -EXPORT_SYMBOL(hda_codec_i915_init); +EXPORT_SYMBOL_NS(hda_codec_i915_init, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); int hda_codec_i915_exit(struct snd_sof_dev *sdev) { @@ -210,7 +210,7 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev) return ret; } -EXPORT_SYMBOL(hda_codec_i915_exit); +EXPORT_SYMBOL_NS(hda_codec_i915_exit, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); #endif diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 3335e0076180..adb842ed6b26 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -795,3 +795,5 @@ void hda_machine_select(struct snd_sof_dev *sdev) } MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC_I915); -- cgit v1.2.3 From 0f501c7cde4086d15c396a95c59631b05dbc0351 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:30 -0600 Subject: ASoC: SOF: move arch_ops under ops The current structures are not well designed. We include Xtensa information from the ACPI and PCI levels, but at the Kconfig/module level everything Xtensa related is included at the sof/intel level. Move the arch_ops under ops so that Xtensa is hidden in the DSP ops, with a structure that follows the Kconfig/module partition. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 1 - sound/soc/sof/intel/apl.c | 2 ++ sound/soc/sof/intel/bdw.c | 2 ++ sound/soc/sof/intel/byt.c | 6 ++++++ sound/soc/sof/intel/cnl.c | 2 ++ sound/soc/sof/sof-acpi-dev.c | 4 ---- sound/soc/sof/sof-pci-dev.c | 10 ---------- sound/soc/sof/sof-priv.h | 4 +++- 8 files changed, 15 insertions(+), 16 deletions(-) (limited to 'sound/soc/sof') diff --git a/include/sound/sof.h b/include/sound/sof.h index 6ea74f1a9ec2..a0cbca021230 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -93,7 +93,6 @@ struct sof_dev_desc { const char *default_fw_filename; const struct snd_sof_dsp_ops *ops; - const struct sof_arch_ops *arch_ops; }; int sof_nocodec_setup(struct device *dev, diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 97831d2c9df6..2483b15699e7 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -111,6 +111,8 @@ const struct snd_sof_dsp_ops sof_apl_ops = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + + .arch_ops = &sof_xtensa_arch_ops, }; EXPORT_SYMBOL_NS(sof_apl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index f017089c7b2d..4d45b54a0f8b 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -632,6 +632,8 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, + + .arch_ops = &sof_xtensa_arch_ops, }; EXPORT_SYMBOL_NS(sof_bdw_ops, SND_SOC_SOF_BROADWELL); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 07634873deb6..08193882f91f 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -618,6 +618,8 @@ const struct snd_sof_dsp_ops sof_tng_ops = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, + + .arch_ops = &sof_xtensa_arch_ops, }; EXPORT_SYMBOL_NS(sof_tng_ops, SND_SOC_SOF_MERRIFIELD); @@ -792,6 +794,8 @@ const struct snd_sof_dsp_ops sof_byt_ops = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, + + .arch_ops = &sof_xtensa_arch_ops, }; EXPORT_SYMBOL_NS(sof_byt_ops, SND_SOC_SOF_BAYTRAIL); @@ -865,6 +869,8 @@ const struct snd_sof_dsp_ops sof_cht_ops = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH, + + .arch_ops = &sof_xtensa_arch_ops, }; EXPORT_SYMBOL_NS(sof_cht_ops, SND_SOC_SOF_BAYTRAIL); diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index b27088e67c7b..9e2d8afe0535 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -297,6 +297,8 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + + .arch_ops = &sof_xtensa_arch_ops, }; EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 9100d7c70bb2..1278aa95effa 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -48,7 +48,6 @@ static const struct sof_dev_desc sof_acpi_broadwell_desc = { .default_fw_filename = "sof-bdw.ri", .nocodec_tplg_filename = "sof-bdw-nocodec.tplg", .ops = &sof_bdw_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -67,7 +66,6 @@ static const struct sof_dev_desc sof_acpi_baytrailcr_desc = { .default_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt-nocodec.tplg", .ops = &sof_byt_ops, - .arch_ops = &sof_xtensa_arch_ops }; static const struct sof_dev_desc sof_acpi_baytrail_desc = { @@ -82,7 +80,6 @@ static const struct sof_dev_desc sof_acpi_baytrail_desc = { .default_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt-nocodec.tplg", .ops = &sof_byt_ops, - .arch_ops = &sof_xtensa_arch_ops }; static const struct sof_dev_desc sof_acpi_cherrytrail_desc = { @@ -97,7 +94,6 @@ static const struct sof_dev_desc sof_acpi_cherrytrail_desc = { .default_fw_filename = "sof-cht.ri", .nocodec_tplg_filename = "sof-cht-nocodec.tplg", .ops = &sof_cht_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 20638f666189..da7b17e5177b 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -50,7 +50,6 @@ static const struct sof_dev_desc bxt_desc = { .default_fw_filename = "sof-apl.ri", .nocodec_tplg_filename = "sof-apl-nocodec.tplg", .ops = &sof_apl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -68,7 +67,6 @@ static const struct sof_dev_desc glk_desc = { .default_fw_filename = "sof-glk.ri", .nocodec_tplg_filename = "sof-glk-nocodec.tplg", .ops = &sof_apl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -96,7 +94,6 @@ static const struct sof_dev_desc tng_desc = { .default_fw_filename = "sof-byt.ri", .nocodec_tplg_filename = "sof-byt.tplg", .ops = &sof_tng_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -114,7 +111,6 @@ static const struct sof_dev_desc cnl_desc = { .default_fw_filename = "sof-cnl.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -132,7 +128,6 @@ static const struct sof_dev_desc cfl_desc = { .default_fw_filename = "sof-cfl.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -152,7 +147,6 @@ static const struct sof_dev_desc cml_desc = { .default_fw_filename = "sof-cml.ri", .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -170,7 +164,6 @@ static const struct sof_dev_desc icl_desc = { .default_fw_filename = "sof-icl.ri", .nocodec_tplg_filename = "sof-icl-nocodec.tplg", .ops = &sof_cnl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -188,7 +181,6 @@ static const struct sof_dev_desc tgl_desc = { .default_fw_filename = "sof-tgl.ri", .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", .ops = &sof_cnl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -206,7 +198,6 @@ static const struct sof_dev_desc ehl_desc = { .default_fw_filename = "sof-ehl.ri", .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", .ops = &sof_cnl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif @@ -223,7 +214,6 @@ static const struct sof_dev_desc jsl_desc = { .default_tplg_path = "intel/sof-tplg", .nocodec_tplg_filename = "sof-jsl-nocodec.tplg", .ops = &sof_cnl_ops, - .arch_ops = &sof_xtensa_arch_ops }; #endif diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 3f1e1eb7c55f..bc2337cf1142 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -217,6 +217,8 @@ struct snd_sof_dsp_ops { /* ALSA HW info flags, will be stored in snd_pcm_runtime.hw.info */ u32 hw_info; + + const struct sof_arch_ops *arch_ops; }; /* DSP architecture specific callbacks for oops and stack dumps */ @@ -226,7 +228,7 @@ struct sof_arch_ops { u32 *stack, u32 stack_words); }; -#define sof_arch_ops(sdev) ((sdev)->pdata->desc->arch_ops) +#define sof_arch_ops(sdev) ((sdev)->pdata->desc->ops->arch_ops) /* DSP device HW descriptor mapping between bus ID and ops */ struct sof_ops_table { -- cgit v1.2.3 From 068ac0db8637d3c188010ab8b9cc136f98fcd3df Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Dec 2019 14:22:31 -0600 Subject: ASoC: SOF: Intel: add namespace for XTENSA Now that Xtensa stuff is only referenced in Intel stuff, define namespace and import it in Intel BYT/BDW/HDaudio modules Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191217202231.18259-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 1 + sound/soc/sof/intel/byt.c | 1 + sound/soc/sof/intel/hda.c | 1 + sound/soc/sof/xtensa/core.c | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 4d45b54a0f8b..6c23c5769330 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -645,3 +645,4 @@ EXPORT_SYMBOL_NS(bdw_chip_info, SND_SOC_SOF_BROADWELL); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); +MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 08193882f91f..f84391294f12 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -884,3 +884,4 @@ EXPORT_SYMBOL_NS(cht_chip_info, SND_SOC_SOF_BAYTRAIL); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); +MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index adb842ed6b26..d08462f481de 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -797,3 +797,4 @@ void hda_machine_select(struct snd_sof_dev *sdev) MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC); MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC_I915); +MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); diff --git a/sound/soc/sof/xtensa/core.c b/sound/soc/sof/xtensa/core.c index 46a4905a9dce..ea08651f0bb3 100644 --- a/sound/soc/sof/xtensa/core.c +++ b/sound/soc/sof/xtensa/core.c @@ -132,7 +132,7 @@ const struct sof_arch_ops sof_xtensa_arch_ops = { .dsp_oops = xtensa_dsp_oops, .dsp_stack = xtensa_stack, }; -EXPORT_SYMBOL(sof_xtensa_arch_ops); +EXPORT_SYMBOL_NS(sof_xtensa_arch_ops, SND_SOC_SOF_XTENSA); MODULE_DESCRIPTION("SOF Xtensa DSP support"); MODULE_LICENSE("Dual BSD/GPL"); -- cgit v1.2.3 From e68d6696575e1af3f92125e842f2853708f34589 Mon Sep 17 00:00:00 2001 From: Sathyanarayana Nujella Date: Fri, 20 Dec 2019 11:10:36 -0600 Subject: ASoC: SOF: Intel: hda: Add iDisp4 DAI TGL supports more than three iDisp DAI's. Add support for iDisp4 CPU DAI. Without this patch, we saw the below error on our TGL DUT: sof_rt5682 tgl_max98357a_rt5682: ASoC: CPU DAI iDisp4 Pin not registered Signed-off-by: Sathyanarayana Nujella Signed-off-by: Jairaj Arava Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191220171037.10689-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 2d9ac0035bd2..638812a41328 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -440,6 +440,10 @@ struct snd_soc_dai_driver skl_dai[] = { .name = "iDisp3 Pin", .ops = &hda_link_dai_ops, }, +{ + .name = "iDisp4 Pin", + .ops = &hda_link_dai_ops, +}, { .name = "Analog CPU DAI", .ops = &hda_link_dai_ops, -- cgit v1.2.3 From 49f261e273078a5dc0272296a833dc72571efd92 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 1 Jan 2020 18:49:46 +0100 Subject: ASoC: SOF: imx8: use resource_size Use resource_size rather than a verbose computation on the end and start fields. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) @@ struct resource ptr; @@ - (ptr.end - ptr.start + 1) + resource_size(&ptr) Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/1577900990-8588-7-git-send-email-Julia.Lawall@inria.fr Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index aef6ca167b9c..b2556f5e2871 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -294,8 +294,7 @@ static int imx8_probe(struct snd_sof_dev *sdev) } sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, - res.end - res.start + - 1); + resource_size(&res)); if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", base, size); -- cgit v1.2.3 From 46207ca24545540231ac8b4cf856baf1ca19e2fa Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Jan 2020 10:08:39 -0600 Subject: ASoC: SOF: pci: change the default firmware path when the community key is used Since ApolloLake, Intel platforms require signed firmware. On all Windows platforms the default is to require the Intel production key be used. But some platforms allow for a community key to be used, which allows developers to compile/build their own firmware. In the linux-firmware tree, the default intel/sof path is used for firmwares signed for the production key, and files signed with the community key are located in intel/sof/community. Since we don't have an API to query which key is used on what platforms, we have to rely on DMI-based quirks. Developers can bypass this mechanism by setting a kernel 'fw_path' module parameter. Additional dynamic debug traces are provided to help debug cases where the wrong file might be used. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200107160840.1524-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index da7b17e5177b..9993be36d105 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -9,6 +9,7 @@ // #include +#include #include #include #include @@ -36,6 +37,23 @@ MODULE_PARM_DESC(sof_pci_debug, "SOF PCI debug options (0x0 all off)"); #define SOF_PCI_DISABLE_PM_RUNTIME BIT(0) +static const struct dmi_system_id community_key_platforms[] = { + { + .ident = "Up Squared", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), + } + }, + { + .ident = "Google Chromebooks", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + } + }, + {}, +}; + #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) static const struct sof_dev_desc bxt_desc = { .machines = snd_soc_acpi_intel_bxt_machines, @@ -290,12 +308,34 @@ static int sof_pci_probe(struct pci_dev *pci, sof_pdata->dev = dev; sof_pdata->fw_filename = desc->default_fw_filename; + /* + * for platforms using the SOF community key, change the + * default path automatically to pick the right files from the + * linux-firmware tree. This can be overridden with the + * fw_path kernel parameter, e.g. for developers. + */ + /* alternate fw and tplg filenames ? */ - if (fw_path) + if (fw_path) { sof_pdata->fw_filename_prefix = fw_path; - else + + dev_dbg(dev, + "Module parameter used, changed fw path to %s\n", + sof_pdata->fw_filename_prefix); + + } else if (dmi_check_system(community_key_platforms)) { + sof_pdata->fw_filename_prefix = + devm_kasprintf(dev, GFP_KERNEL, "%s/%s", + sof_pdata->desc->default_fw_path, + "community"); + + dev_dbg(dev, + "Platform uses community key, changed fw path to %s\n", + sof_pdata->fw_filename_prefix); + } else { sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; + } if (tplg_path) sof_pdata->tplg_filename_prefix = tplg_path; -- cgit v1.2.3 From 490a625b01775857a9d00c623164e8aa0be762a2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Jan 2020 10:08:40 -0600 Subject: ASoC: SOF: loader: add dynamic debug trace We currently have no trace referring to the firmware path, add a trace to help debug cases where the wrong file might be used. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200107160840.1524-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 235be4fc0862..fc4ab51bacf4 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -487,6 +487,9 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); + } else { + dev_dbg(sdev->dev, "request_firmware %s successful\n", + fw_filename); } kfree(fw_filename); -- cgit v1.2.3 From cfe8191b1bbf2b41581b63eb97e56cd6bc3c34a1 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 10 Jan 2020 17:57:49 -0600 Subject: ASoC: SOF: fix PCM playback through ALSA OSS emulation Any app using ALSA OSS emulation on top of SOF will fail to error from OSS SNDCTL_DSP_SETFMT ioctl. Reported initially as an issue with xournalpp (application using PortAudio with an OSS backend), but applies more generally to other apps using OSS as well. Problem is caused by SOF PCM not supporting repeated calls to hw_params(), without matching calls to pcm_free(). This is however exactly what the ALSA OSS PCM code is doing when it is handling the OSS ioctls. The problem will lead to leaking of DSP resources and eventual failure of DSP PCM_PARAMS IPC. BugLink: https://github.com/thesofproject/linux/issues/1510 Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200110235751.3404-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 9bb6388742e1..314f3095c12f 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -92,7 +92,27 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) } EXPORT_SYMBOL(snd_sof_pcm_period_elapsed); -/* this may get called several times by oss emulation */ +static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, + struct snd_sof_dev *sdev, + struct snd_sof_pcm *spcm) +{ + struct sof_ipc_stream stream; + struct sof_ipc_reply reply; + int ret; + + stream.hdr.size = sizeof(stream); + stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; + stream.comp_id = spcm->stream[substream->stream].comp_id; + + /* send IPC to the DSP */ + ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, + sizeof(stream), &reply, sizeof(reply)); + if (!ret) + spcm->prepared[substream->stream] = false; + + return ret; +} + static int sof_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -113,6 +133,16 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, if (!spcm) return -EINVAL; + /* + * Handle repeated calls to hw_params() without free_pcm() in + * between. At least ALSA OSS emulation depends on this. + */ + if (spcm->prepared[substream->stream]) { + ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); + if (ret < 0) + return ret; + } + dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); @@ -201,27 +231,6 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, return ret; } -static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, - struct snd_sof_dev *sdev, - struct snd_sof_pcm *spcm) -{ - struct sof_ipc_stream stream; - struct sof_ipc_reply reply; - int ret; - - stream.hdr.size = sizeof(stream); - stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; - stream.comp_id = spcm->stream[substream->stream].comp_id; - - /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, - sizeof(stream), &reply, sizeof(reply)); - if (!ret) - spcm->prepared[substream->stream] = false; - - return ret; -} - static int sof_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { -- cgit v1.2.3 From 5732c0fc53eb45565c485a886d027c0b1f86d4c5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 10 Jan 2020 16:25:30 -0600 Subject: ASoC: SOF: Intel: reference SoundWire machine lists Use static tables to automatically select the relevant configurations. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200110222530.30303-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 9993be36d105..d855bc2b76ad 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -118,6 +118,7 @@ static const struct sof_dev_desc tng_desc = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) static const struct sof_dev_desc cnl_desc = { .machines = snd_soc_acpi_intel_cnl_machines, + .alt_machines = snd_soc_acpi_intel_cnl_sdw_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, @@ -135,6 +136,7 @@ static const struct sof_dev_desc cnl_desc = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) static const struct sof_dev_desc cfl_desc = { .machines = snd_soc_acpi_intel_cfl_machines, + .alt_machines = snd_soc_acpi_intel_cfl_sdw_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, @@ -154,6 +156,7 @@ static const struct sof_dev_desc cfl_desc = { static const struct sof_dev_desc cml_desc = { .machines = snd_soc_acpi_intel_cml_machines, + .alt_machines = snd_soc_acpi_intel_cml_sdw_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, @@ -171,6 +174,7 @@ static const struct sof_dev_desc cml_desc = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) static const struct sof_dev_desc icl_desc = { .machines = snd_soc_acpi_intel_icl_machines, + .alt_machines = snd_soc_acpi_intel_icl_sdw_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, @@ -188,6 +192,7 @@ static const struct sof_dev_desc icl_desc = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) static const struct sof_dev_desc tgl_desc = { .machines = snd_soc_acpi_intel_tgl_machines, + .alt_machines = snd_soc_acpi_intel_tgl_sdw_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, -- cgit v1.2.3 From d873997192ddcacb5333575502be2f91ea4b47b8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 13 Jan 2020 14:56:20 -0600 Subject: ASoC: SOF: Intel: hda-dai: fix compilation warning in pcm_prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix GCC warning with W=1, previous cleanup did not remove unnecessary variable. sound/soc/sof/intel/hda-dai.c: In function ‘hda_link_pcm_prepare’: sound/soc/sof/intel/hda-dai.c:265:31: warning: variable ‘hda_stream’ set but not used [-Wunused-but-set-variable] 265 | struct sof_intel_hda_stream *hda_stream; | ^~~~~~~~~~ Fixes: a3ebccb52efdf ("ASoC: SOF: Intel: hda: reset link DMA state in prepare") Cc: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200113205620.27285-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 313611dcb5e4..9c6e3f990ee3 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -262,14 +262,11 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream, { struct hdac_ext_stream *link_dev = snd_soc_dai_get_dma_data(dai, substream); - struct sof_intel_hda_stream *hda_stream; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); int stream = substream->stream; - hda_stream = hstream_to_sof_hda_stream(link_dev); - if (link_dev->link_prepared) return 0; -- cgit v1.2.3 From a6947c9d86bcfd61b758b5693eba58defe7fd2ae Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 13 Jan 2020 12:40:54 +0100 Subject: ASoC: SOF: Intel: hda: Fix SKL dai count With fourth pin added for iDisp for skl_dai, update SOF_SKL_DAI_NUM to account for the change. Without this, dais from the bottom of the list are skipped. In current state that's the case for 'Alt Analog CPU DAI'. Fixes: ac42b142cd76 ("ASoC: SOF: Intel: hda: Add iDisp4 DAI") Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200113114054.9716-1-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 18d7e72bf9b7..8981c00c4d94 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -345,7 +345,7 @@ /* Number of DAIs */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -#define SOF_SKL_NUM_DAIS 14 +#define SOF_SKL_NUM_DAIS 15 #else #define SOF_SKL_NUM_DAIS 8 #endif -- cgit v1.2.3