History

ASoC: Intel: avs: PCI driver implementation

HD-Audio bus is a PCI device. Add all functions necessary to probe such device along with its removal sequence. Behaviour implemented for all standard operations is similar to existing solutions: sound/pci/hda and sound/soc/intel/skylake.

Cezary Rojewski committed 4 years ago

Commit 1affc441 parent beed9836 files · +499 −4Browse files

Unified · Split

6 files
  1. include/sound/intel-dsp-config.h +2 −1
  2. sound/soc/intel/Kconfig +1 −0
  3. sound/soc/intel/avs/avs.h +1 −0
  4. sound/soc/intel/avs/core.c +494 −0
  5. sound/soc/intel/avs/dsp.c +0 −3
  6. sound/soc/intel/avs/registers.h +1 −0
include/sound/intel-dsp-config.h+2−1
@@ -15,7 +15,8 @@ enum { · 14 unmodified lines
1515 SND_INTEL_DSP_DRIVER_LEGACY,
1616 SND_INTEL_DSP_DRIVER_SST,
1717 SND_INTEL_DSP_DRIVER_SOF,
18− SND_INTEL_DSP_DRIVER_LAST = SND_INTEL_DSP_DRIVER_SOF
18+ SND_INTEL_DSP_DRIVER_AVS,
19+ SND_INTEL_DSP_DRIVER_LAST = SND_INTEL_DSP_DRIVER_AVS
1920 };
2021
2122 #if IS_ENABLED(CONFIG_SND_INTEL_DSP_CONFIG)
sound/soc/intel/Kconfig+1−0
@@ -216,6 +216,7 @@ config SND_SOC_INTEL_AVS · 215 unmodified lines
216216 depends on COMMON_CLK
217217 select SND_SOC_ACPI if ACPI
218218 select SND_SOC_TOPOLOGY
219+ select SND_HDA
219220 select SND_HDA_EXT_CORE
220221 select SND_HDA_DSP_LOADER
221222 select SND_INTEL_DSP_CONFIG
sound/soc/intel/avs/avs.h+1−0
@@ -126,6 +126,7 @@ struct avs_dev { · 125 unmodified lines
126126 char **lib_names;
127127
128128 struct completion fw_ready;
129+ struct work_struct probe_work;
129130
130131 struct nhlt_acpi_table *nhlt;
131132 struct list_head comp_list;
sound/soc/intel/avs/core.c+494−0
@@ -14,9 +14,17 @@ · 13 unmodified lines
1414 // foundation of this driver
1515 //
1616
17+#include <linux/module.h>
1718 #include <linux/pci.h>
19+#include <sound/hda_codec.h>
20+#include <sound/hda_i915.h>
21+#include <sound/hda_register.h>
1822 #include <sound/hdaudio.h>
23+#include <sound/hdaudio_ext.h>
24+#include <sound/intel-dsp-config.h>
25+#include <sound/intel-nhlt.h>
1926 #include "avs.h"
27+#include "cldma.h"
2028
2129 static void
2230 avs_hda_update_config_dword(struct hdac_bus *bus, u32 reg, u32 mask, u32 value)
@@ -59,3 +67,489 @@ void avs_hda_l1sen_enable(struct avs_dev *adev, bool enable) · 36 unmodified lines
5967 value = enable ? AZX_VS_EM2_L1SEN : 0;
6068 snd_hdac_chip_updatel(&adev->base.core, VS_EM2, AZX_VS_EM2_L1SEN, value);
6169 }
70+
71+static int avs_hdac_bus_init_streams(struct hdac_bus *bus)
72+{
73+ unsigned int cp_streams, pb_streams;
74+ unsigned int gcap;
75+
76+ gcap = snd_hdac_chip_readw(bus, GCAP);
77+ cp_streams = (gcap >> 8) & 0x0F;
78+ pb_streams = (gcap >> 12) & 0x0F;
79+ bus->num_streams = cp_streams + pb_streams;
80+
81+ snd_hdac_ext_stream_init_all(bus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE);
82+ snd_hdac_ext_stream_init_all(bus, cp_streams, pb_streams, SNDRV_PCM_STREAM_PLAYBACK);
83+
84+ return snd_hdac_bus_alloc_stream_pages(bus);
85+}
86+
87+static bool avs_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset)
88+{
89+ struct hdac_ext_link *hlink;
90+ bool ret;
91+
92+ avs_hdac_clock_gating_enable(bus, false);
93+ ret = snd_hdac_bus_init_chip(bus, full_reset);
94+
95+ /* Reset stream-to-link mapping */
96+ list_for_each_entry(hlink, &bus->hlink_list, list)
97+ writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
98+
99+ avs_hdac_clock_gating_enable(bus, true);
100+
101+ /* Set DUM bit to address incorrect position reporting for capture
102+ * streams. In order to do so, CTRL needs to be out of reset state
103+ */
104+ snd_hdac_chip_updatel(bus, VS_EM2, AZX_VS_EM2_DUM, AZX_VS_EM2_DUM);
105+
106+ return ret;
107+}
108+
109+static int probe_codec(struct hdac_bus *bus, int addr)
110+{
111+ struct hda_codec *codec;
112+ unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
113+ (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
114+ unsigned int res = -1;
115+ int ret;
116+
117+ mutex_lock(&bus->cmd_mutex);
118+ snd_hdac_bus_send_cmd(bus, cmd);
119+ snd_hdac_bus_get_response(bus, addr, &res);
120+ mutex_unlock(&bus->cmd_mutex);
121+ if (res == -1)
122+ return -EIO;
123+
124+ dev_dbg(bus->dev, "codec #%d probed OK: 0x%x\n", addr, res);
125+
126+ codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "hdaudioB%dD%d", bus->idx, addr);
127+ if (IS_ERR(codec)) {
128+ dev_err(bus->dev, "init codec failed: %ld\n", PTR_ERR(codec));
129+ return PTR_ERR(codec);
130+ }
131+ /*
132+ * Allow avs_core suspend by forcing suspended state on all
133+ * of its codec child devices. Component interested in
134+ * dealing with hda codecs directly takes pm responsibilities
135+ */
136+ pm_runtime_set_suspended(hda_codec_dev(codec));
137+
138+ /* configure effectively creates new ASoC component */
139+ ret = snd_hda_codec_configure(codec);
140+ if (ret < 0) {
141+ dev_err(bus->dev, "failed to config codec %d\n", ret);
142+ return ret;
143+ }
144+
145+ return 0;
146+}
147+
148+static void avs_hdac_bus_probe_codecs(struct hdac_bus *bus)
149+{
150+ int c;
151+
152+ /* First try to probe all given codec slots */
153+ for (c = 0; c < HDA_MAX_CODECS; c++) {
154+ if (!(bus->codec_mask & BIT(c)))
155+ continue;
156+
157+ if (!probe_codec(bus, c))
158+ /* success, continue probing */
159+ continue;
160+
161+ /*
162+ * Some BIOSen give you wrong codec addresses
163+ * that don't exist
164+ */
165+ dev_warn(bus->dev, "Codec #%d probe error; disabling it...\n", c);
166+ bus->codec_mask &= ~BIT(c);
167+ /*
168+ * More badly, accessing to a non-existing
169+ * codec often screws up the controller bus,
170+ * and disturbs the further communications.
171+ * Thus if an error occurs during probing,
172+ * better to reset the controller bus to get
173+ * back to the sanity state.
174+ */
175+ snd_hdac_bus_stop_chip(bus);
176+ avs_hdac_bus_init_chip(bus, true);
177+ }
178+}
179+
180+static void avs_hda_probe_work(struct work_struct *work)
181+{
182+ struct avs_dev *adev = container_of(work, struct avs_dev, probe_work);
183+ struct hdac_bus *bus = &adev->base.core;
184+ struct hdac_ext_link *hlink;
185+ int ret;
186+
187+ pm_runtime_set_active(bus->dev); /* clear runtime_error flag */
188+
189+ ret = snd_hdac_i915_init(bus);
190+ if (ret < 0)
191+ dev_info(bus->dev, "i915 init unsuccessful: %d\n", ret);
192+
193+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
194+ avs_hdac_bus_init_chip(bus, true);
195+ avs_hdac_bus_probe_codecs(bus);
196+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
197+
198+ /* with all codecs probed, links can be powered down */
199+ list_for_each_entry(hlink, &bus->hlink_list, list)
200+ snd_hdac_ext_bus_link_put(bus, hlink);
201+
202+ snd_hdac_ext_bus_ppcap_enable(bus, true);
203+ snd_hdac_ext_bus_ppcap_int_enable(bus, true);
204+
205+ ret = avs_dsp_first_boot_firmware(adev);
206+ if (ret < 0)
207+ return;
208+
209+ adev->nhlt = intel_nhlt_init(adev->dev);
210+ if (!adev->nhlt)
211+ dev_info(bus->dev, "platform has no NHLT\n");
212+
213+ avs_register_all_boards(adev);
214+
215+ /* configure PM */
216+ pm_runtime_set_autosuspend_delay(bus->dev, 2000);
217+ pm_runtime_use_autosuspend(bus->dev);
218+ pm_runtime_mark_last_busy(bus->dev);
219+ pm_runtime_put_autosuspend(bus->dev);
220+ pm_runtime_allow(bus->dev);
221+}
222+
223+static void hdac_stream_update_pos(struct hdac_stream *stream, u64 buffer_size)
224+{
225+ u64 prev_pos, pos, num_bytes;
226+
227+ div64_u64_rem(stream->curr_pos, buffer_size, &prev_pos);
228+ pos = snd_hdac_stream_get_pos_posbuf(stream);
229+
230+ if (pos < prev_pos)
231+ num_bytes = (buffer_size - prev_pos) + pos;
232+ else
233+ num_bytes = pos - prev_pos;
234+
235+ stream->curr_pos += num_bytes;
236+}
237+
238+/* called from IRQ */
239+static void hdac_update_stream(struct hdac_bus *bus, struct hdac_stream *stream)
240+{
241+ if (stream->substream) {
242+ snd_pcm_period_elapsed(stream->substream);
243+ } else if (stream->cstream) {
244+ u64 buffer_size = stream->cstream->runtime->buffer_size;
245+
246+ hdac_stream_update_pos(stream, buffer_size);
247+ snd_compr_fragment_elapsed(stream->cstream);
248+ }
249+}
250+
251+static irqreturn_t hdac_bus_irq_handler(int irq, void *context)
252+{
253+ struct hdac_bus *bus = context;
254+ u32 mask, int_enable;
255+ u32 status;
256+ int ret = IRQ_NONE;
257+
258+ if (!pm_runtime_active(bus->dev))
259+ return ret;
260+
261+ spin_lock(&bus->reg_lock);
262+
263+ status = snd_hdac_chip_readl(bus, INTSTS);
264+ if (status == 0 || status == UINT_MAX) {
265+ spin_unlock(&bus->reg_lock);
266+ return ret;
267+ }
268+
269+ /* clear rirb int */
270+ status = snd_hdac_chip_readb(bus, RIRBSTS);
271+ if (status & RIRB_INT_MASK) {
272+ if (status & RIRB_INT_RESPONSE)
273+ snd_hdac_bus_update_rirb(bus);
274+ snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
275+ }
276+
277+ mask = (0x1 << bus->num_streams) - 1;
278+
279+ status = snd_hdac_chip_readl(bus, INTSTS);
280+ status &= mask;
281+ if (status) {
282+ /* Disable stream interrupts; Re-enable in bottom half */
283+ int_enable = snd_hdac_chip_readl(bus, INTCTL);
284+ snd_hdac_chip_writel(bus, INTCTL, (int_enable & (~mask)));
285+ ret = IRQ_WAKE_THREAD;
286+ } else {
287+ ret = IRQ_HANDLED;
288+ }
289+
290+ spin_unlock(&bus->reg_lock);
291+ return ret;
292+}
293+
294+static irqreturn_t hdac_bus_irq_thread(int irq, void *context)
295+{
296+ struct hdac_bus *bus = context;
297+ u32 status;
298+ u32 int_enable;
299+ u32 mask;
300+ unsigned long flags;
301+
302+ status = snd_hdac_chip_readl(bus, INTSTS);
303+
304+ snd_hdac_bus_handle_stream_irq(bus, status, hdac_update_stream);
305+
306+ /* Re-enable stream interrupts */
307+ mask = (0x1 << bus->num_streams) - 1;
308+ spin_lock_irqsave(&bus->reg_lock, flags);
309+ int_enable = snd_hdac_chip_readl(bus, INTCTL);
310+ snd_hdac_chip_writel(bus, INTCTL, (int_enable | mask));
311+ spin_unlock_irqrestore(&bus->reg_lock, flags);
312+
313+ return IRQ_HANDLED;
314+}
315+
316+static int avs_hdac_acquire_irq(struct avs_dev *adev)
317+{
318+ struct hdac_bus *bus = &adev->base.core;
319+ struct pci_dev *pci = to_pci_dev(bus->dev);
320+ int ret;
321+
322+ /* request one and check that we only got one interrupt */
323+ ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
324+ if (ret != 1) {
325+ dev_err(adev->dev, "Failed to allocate IRQ vector: %d\n", ret);
326+ return ret;
327+ }
328+
329+ ret = pci_request_irq(pci, 0, hdac_bus_irq_handler, hdac_bus_irq_thread, bus,
330+ KBUILD_MODNAME);
331+ if (ret < 0) {
332+ dev_err(adev->dev, "Failed to request stream IRQ handler: %d\n", ret);
333+ goto free_vector;
334+ }
335+
336+ ret = pci_request_irq(pci, 0, avs_dsp_irq_handler, avs_dsp_irq_thread, adev,
337+ KBUILD_MODNAME);
338+ if (ret < 0) {
339+ dev_err(adev->dev, "Failed to request IPC IRQ handler: %d\n", ret);
340+ goto free_stream_irq;
341+ }
342+
343+ return 0;
344+
345+free_stream_irq:
346+ pci_free_irq(pci, 0, bus);
347+free_vector:
348+ pci_free_irq_vectors(pci);
349+ return ret;
350+}
351+
352+static int avs_bus_init(struct avs_dev *adev, struct pci_dev *pci, const struct pci_device_id *id)
353+{
354+ struct hda_bus *bus = &adev->base;
355+ struct avs_ipc *ipc;
356+ struct device *dev = &pci->dev;
357+ int ret;
358+
359+ ret = snd_hdac_ext_bus_init(&bus->core, dev, NULL, NULL);
360+ if (ret < 0)
361+ return ret;
362+
363+ bus->core.use_posbuf = 1;
364+ bus->core.bdl_pos_adj = 0;
365+ bus->core.sync_write = 1;
366+ bus->pci = pci;
367+ bus->mixer_assigned = -1;
368+ mutex_init(&bus->prepare_mutex);
369+
370+ ipc = devm_kzalloc(dev, sizeof(*ipc), GFP_KERNEL);
371+ if (!ipc)
372+ return -ENOMEM;
373+ ret = avs_ipc_init(ipc, dev);
374+ if (ret < 0)
375+ return ret;
376+
377+ adev->dev = dev;
378+ adev->spec = (const struct avs_spec *)id->driver_data;
379+ adev->ipc = ipc;
380+ adev->hw_cfg.dsp_cores = hweight_long(AVS_MAIN_CORE_MASK);
381+ INIT_WORK(&adev->probe_work, avs_hda_probe_work);
382+ INIT_LIST_HEAD(&adev->comp_list);
383+ INIT_LIST_HEAD(&adev->path_list);
384+ INIT_LIST_HEAD(&adev->fw_list);
385+ init_completion(&adev->fw_ready);
386+ spin_lock_init(&adev->path_list_lock);
387+ mutex_init(&adev->modres_mutex);
388+ mutex_init(&adev->comp_list_mutex);
389+ mutex_init(&adev->path_mutex);
390+
391+ return 0;
392+}
393+
394+static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
395+{
396+ struct hdac_bus *bus;
397+ struct avs_dev *adev;
398+ struct device *dev = &pci->dev;
399+ int ret;
400+
401+ ret = snd_intel_dsp_driver_probe(pci);
402+ if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_AVS)
403+ return -ENODEV;
404+
405+ ret = pcim_enable_device(pci);
406+ if (ret < 0)
407+ return ret;
408+
409+ adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL);
410+ if (!adev)
411+ return -ENOMEM;
412+ ret = avs_bus_init(adev, pci, id);
413+ if (ret < 0) {
414+ dev_err(dev, "failed to init avs bus: %d\n", ret);
415+ return ret;
416+ }
417+
418+ ret = pci_request_regions(pci, "AVS HDAudio");
419+ if (ret < 0)
420+ return ret;
421+
422+ bus = &adev->base.core;
423+ bus->addr = pci_resource_start(pci, 0);
424+ bus->remap_addr = pci_ioremap_bar(pci, 0);
425+ if (!bus->remap_addr) {
426+ dev_err(bus->dev, "ioremap error\n");
427+ ret = -ENXIO;
428+ goto err_remap_bar0;
429+ }
430+
431+ adev->dsp_ba = pci_ioremap_bar(pci, 4);
432+ if (!adev->dsp_ba) {
433+ dev_err(bus->dev, "ioremap error\n");
434+ ret = -ENXIO;
435+ goto err_remap_bar4;
436+ }
437+
438+ snd_hdac_bus_parse_capabilities(bus);
439+ if (bus->mlcap)
440+ snd_hdac_ext_bus_get_ml_capabilities(bus);
441+
442+ if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
443+ dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
444+ } else {
445+ dma_set_mask(dev, DMA_BIT_MASK(32));
446+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
447+ }
448+
449+ ret = avs_hdac_bus_init_streams(bus);
450+ if (ret < 0) {
451+ dev_err(dev, "failed to init streams: %d\n", ret);
452+ goto err_init_streams;
453+ }
454+
455+ ret = avs_hdac_acquire_irq(adev);
456+ if (ret < 0) {
457+ dev_err(bus->dev, "failed to acquire irq: %d\n", ret);
458+ goto err_acquire_irq;
459+ }
460+
461+ pci_set_master(pci);
462+ pci_set_drvdata(pci, bus);
463+ device_disable_async_suspend(dev);
464+
465+ schedule_work(&adev->probe_work);
466+
467+ return 0;
468+
469+err_acquire_irq:
470+ snd_hdac_bus_free_stream_pages(bus);
471+ snd_hdac_stream_free_all(bus);
472+err_init_streams:
473+ iounmap(adev->dsp_ba);
474+err_remap_bar4:
475+ iounmap(bus->remap_addr);
476+err_remap_bar0:
477+ pci_release_regions(pci);
478+ return ret;
479+}
480+
481+static void avs_pci_remove(struct pci_dev *pci)
482+{
483+ struct hdac_device *hdev, *save;
484+ struct hdac_bus *bus = pci_get_drvdata(pci);
485+ struct avs_dev *adev = hdac_to_avs(bus);
486+
487+ cancel_work_sync(&adev->probe_work);
488+ avs_ipc_block(adev->ipc);
489+
490+ avs_unregister_all_boards(adev);
491+
492+ if (adev->nhlt)
493+ intel_nhlt_free(adev->nhlt);
494+
495+ if (avs_platattr_test(adev, CLDMA))
496+ hda_cldma_free(&code_loader);
497+
498+ snd_hdac_stop_streams_and_chip(bus);
499+ avs_dsp_op(adev, int_control, false);
500+ snd_hdac_ext_bus_ppcap_int_enable(bus, false);
501+
502+ /* it is safe to remove all codecs from the system now */
503+ list_for_each_entry_safe(hdev, save, &bus->codec_list, list)
504+ snd_hda_codec_unregister(hdac_to_hda_codec(hdev));
505+
506+ snd_hdac_bus_free_stream_pages(bus);
507+ snd_hdac_stream_free_all(bus);
508+ /* reverse ml_capabilities */
509+ snd_hdac_link_free_all(bus);
510+ snd_hdac_ext_bus_exit(bus);
511+
512+ avs_dsp_core_disable(adev, GENMASK(adev->hw_cfg.dsp_cores - 1, 0));
513+ snd_hdac_ext_bus_ppcap_enable(bus, false);
514+
515+ /* snd_hdac_stop_streams_and_chip does that already? */
516+ snd_hdac_bus_stop_chip(bus);
517+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
518+ if (bus->audio_component)
519+ snd_hdac_i915_exit(bus);
520+
521+ avs_module_info_free(adev);
522+ pci_free_irq(pci, 0, adev);
523+ pci_free_irq(pci, 0, bus);
524+ pci_free_irq_vectors(pci);
525+ iounmap(bus->remap_addr);
526+ iounmap(adev->dsp_ba);
527+ pci_release_regions(pci);
528+
529+ /* Firmware is not needed anymore */
530+ avs_release_firmwares(adev);
531+
532+ /* pm_runtime_forbid() can rpm_resume() which we do not want */
533+ pm_runtime_disable(&pci->dev);
534+ pm_runtime_forbid(&pci->dev);
535+ pm_runtime_enable(&pci->dev);
536+ pm_runtime_get_noresume(&pci->dev);
537+}
538+
539+static const struct pci_device_id avs_ids[] = {
540+ { 0 }
541+};
542+MODULE_DEVICE_TABLE(pci, avs_ids);
543+
544+static struct pci_driver avs_pci_driver = {
545+ .name = KBUILD_MODNAME,
546+ .id_table = avs_ids,
547+ .probe = avs_pci_probe,
548+ .remove = avs_pci_remove,
549+};
550+module_pci_driver(avs_pci_driver);
551+
552+MODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>");
553+MODULE_AUTHOR("Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>");
554+MODULE_DESCRIPTION("Intel cAVS sound driver");
555+MODULE_LICENSE("GPL");
sound/soc/intel/avs/dsp.c+0−3
@@ -6,7 +6,6 @@ · 5 unmodified lines
66 // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
77 //
88
9−#include <linux/module.h>
109 #include <sound/hdaudio_ext.h>
1110 #include "avs.h"
1211 #include "registers.h"
@@ -322,5 +321,3 @@ int avs_dsp_delete_pipeline(struct avs_dev *adev, u8 instance_id) · 309 unmodified lines
322321 ida_free(&adev->ppl_ida, instance_id);
323322 return ret;
324323 }
325−
326−MODULE_LICENSE("GPL");
sound/soc/intel/avs/registers.h+1−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #define AZX_PGCTL_LSRMD_MASK BIT(4)
1515 #define AZX_CGCTL_MISCBDCGE_MASK BIT(6)
1616 #define AZX_VS_EM2_L1SEN BIT(13)
17+#define AZX_VS_EM2_DUM BIT(23)
1718
1819 /* Intel HD Audio General DSP Registers */
1920 #define AVS_ADSP_GEN_BASE 0x0

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t