pci-tng.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2018-2021 Intel Corporation. All rights reserved.
  7. //
  8. // Author: Liam Girdwood <[email protected]>
  9. //
  10. #include <linux/module.h>
  11. #include <linux/pci.h>
  12. #include <sound/soc-acpi.h>
  13. #include <sound/soc-acpi-intel-match.h>
  14. #include <sound/sof.h>
  15. #include "../ops.h"
  16. #include "atom.h"
  17. #include "../sof-pci-dev.h"
  18. #include "../sof-audio.h"
  19. /* platform specific devices */
  20. #include "shim.h"
  21. static struct snd_soc_acpi_mach sof_tng_machines[] = {
  22. {
  23. .id = "INT343A",
  24. .drv_name = "edison",
  25. .sof_tplg_filename = "sof-byt.tplg",
  26. },
  27. {}
  28. };
  29. static const struct snd_sof_debugfs_map tng_debugfs[] = {
  30. {"dmac0", DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
  31. SOF_DEBUGFS_ACCESS_ALWAYS},
  32. {"dmac1", DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
  33. SOF_DEBUGFS_ACCESS_ALWAYS},
  34. {"ssp0", DSP_BAR, SSP0_OFFSET, SSP_SIZE,
  35. SOF_DEBUGFS_ACCESS_ALWAYS},
  36. {"ssp1", DSP_BAR, SSP1_OFFSET, SSP_SIZE,
  37. SOF_DEBUGFS_ACCESS_ALWAYS},
  38. {"ssp2", DSP_BAR, SSP2_OFFSET, SSP_SIZE,
  39. SOF_DEBUGFS_ACCESS_ALWAYS},
  40. {"iram", DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
  41. SOF_DEBUGFS_ACCESS_D0_ONLY},
  42. {"dram", DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
  43. SOF_DEBUGFS_ACCESS_D0_ONLY},
  44. {"shim", DSP_BAR, SHIM_OFFSET, SHIM_SIZE_BYT,
  45. SOF_DEBUGFS_ACCESS_ALWAYS},
  46. };
  47. static int tangier_pci_probe(struct snd_sof_dev *sdev)
  48. {
  49. struct snd_sof_pdata *pdata = sdev->pdata;
  50. const struct sof_dev_desc *desc = pdata->desc;
  51. struct pci_dev *pci = to_pci_dev(sdev->dev);
  52. const struct sof_intel_dsp_desc *chip;
  53. u32 base, size;
  54. int ret;
  55. chip = get_chip_info(sdev->pdata);
  56. if (!chip) {
  57. dev_err(sdev->dev, "error: no such device supported\n");
  58. return -EIO;
  59. }
  60. sdev->num_cores = chip->cores_num;
  61. /* DSP DMA can only access low 31 bits of host memory */
  62. ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
  63. if (ret < 0) {
  64. dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
  65. return ret;
  66. }
  67. /* LPE base */
  68. base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
  69. size = PCI_BAR_SIZE;
  70. dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
  71. sdev->bar[DSP_BAR] = devm_ioremap(sdev->dev, base, size);
  72. if (!sdev->bar[DSP_BAR]) {
  73. dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
  74. base, size);
  75. return -ENODEV;
  76. }
  77. dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[DSP_BAR]);
  78. /* IMR base - optional */
  79. if (desc->resindex_imr_base == -1)
  80. goto irq;
  81. base = pci_resource_start(pci, desc->resindex_imr_base);
  82. size = pci_resource_len(pci, desc->resindex_imr_base);
  83. /* some BIOSes don't map IMR */
  84. if (base == 0x55aa55aa || base == 0x0) {
  85. dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
  86. goto irq;
  87. }
  88. dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
  89. sdev->bar[IMR_BAR] = devm_ioremap(sdev->dev, base, size);
  90. if (!sdev->bar[IMR_BAR]) {
  91. dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
  92. base, size);
  93. return -ENODEV;
  94. }
  95. dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[IMR_BAR]);
  96. irq:
  97. /* register our IRQ */
  98. sdev->ipc_irq = pci->irq;
  99. dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
  100. ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
  101. atom_irq_handler, atom_irq_thread,
  102. 0, "AudioDSP", sdev);
  103. if (ret < 0) {
  104. dev_err(sdev->dev, "error: failed to register IRQ %d\n",
  105. sdev->ipc_irq);
  106. return ret;
  107. }
  108. /* enable BUSY and disable DONE Interrupt by default */
  109. snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_IMRX,
  110. SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
  111. SHIM_IMRX_DONE);
  112. /* set default mailbox offset for FW ready message */
  113. sdev->dsp_box.offset = MBOX_OFFSET;
  114. return ret;
  115. }
  116. struct snd_sof_dsp_ops sof_tng_ops = {
  117. /* device init */
  118. .probe = tangier_pci_probe,
  119. /* DSP core boot / reset */
  120. .run = atom_run,
  121. .reset = atom_reset,
  122. /* Register IO */
  123. .write = sof_io_write,
  124. .read = sof_io_read,
  125. .write64 = sof_io_write64,
  126. .read64 = sof_io_read64,
  127. /* Block IO */
  128. .block_read = sof_block_read,
  129. .block_write = sof_block_write,
  130. /* Mailbox IO */
  131. .mailbox_read = sof_mailbox_read,
  132. .mailbox_write = sof_mailbox_write,
  133. /* doorbell */
  134. .irq_handler = atom_irq_handler,
  135. .irq_thread = atom_irq_thread,
  136. /* ipc */
  137. .send_msg = atom_send_msg,
  138. .get_mailbox_offset = atom_get_mailbox_offset,
  139. .get_window_offset = atom_get_window_offset,
  140. .ipc_msg_data = sof_ipc_msg_data,
  141. .set_stream_data_offset = sof_set_stream_data_offset,
  142. /* machine driver */
  143. .machine_select = atom_machine_select,
  144. .machine_register = sof_machine_register,
  145. .machine_unregister = sof_machine_unregister,
  146. .set_mach_params = atom_set_mach_params,
  147. /* debug */
  148. .debug_map = tng_debugfs,
  149. .debug_map_count = ARRAY_SIZE(tng_debugfs),
  150. .dbg_dump = atom_dump,
  151. .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
  152. /* stream callbacks */
  153. .pcm_open = sof_stream_pcm_open,
  154. .pcm_close = sof_stream_pcm_close,
  155. /*Firmware loading */
  156. .load_firmware = snd_sof_load_firmware_memcpy,
  157. /* DAI drivers */
  158. .drv = atom_dai,
  159. .num_drv = 3, /* we have only 3 SSPs on byt*/
  160. /* ALSA HW info flags */
  161. .hw_info = SNDRV_PCM_INFO_MMAP |
  162. SNDRV_PCM_INFO_MMAP_VALID |
  163. SNDRV_PCM_INFO_INTERLEAVED |
  164. SNDRV_PCM_INFO_PAUSE |
  165. SNDRV_PCM_INFO_BATCH,
  166. .dsp_arch_ops = &sof_xtensa_arch_ops,
  167. };
  168. const struct sof_intel_dsp_desc tng_chip_info = {
  169. .cores_num = 1,
  170. .host_managed_cores_mask = 1,
  171. .hw_ip_version = SOF_INTEL_TANGIER,
  172. };
  173. static const struct sof_dev_desc tng_desc = {
  174. .machines = sof_tng_machines,
  175. .resindex_lpe_base = 3, /* IRAM, but subtract IRAM offset */
  176. .resindex_pcicfg_base = -1,
  177. .resindex_imr_base = 0,
  178. .irqindex_host_ipc = -1,
  179. .chip_info = &tng_chip_info,
  180. .ipc_supported_mask = BIT(SOF_IPC),
  181. .ipc_default = SOF_IPC,
  182. .default_fw_path = {
  183. [SOF_IPC] = "intel/sof",
  184. },
  185. .default_tplg_path = {
  186. [SOF_IPC] = "intel/sof-tplg",
  187. },
  188. .default_fw_filename = {
  189. [SOF_IPC] = "sof-byt.ri",
  190. },
  191. .nocodec_tplg_filename = "sof-byt.tplg",
  192. .ops = &sof_tng_ops,
  193. };
  194. /* PCI IDs */
  195. static const struct pci_device_id sof_pci_ids[] = {
  196. { PCI_DEVICE(0x8086, 0x119a),
  197. .driver_data = (unsigned long)&tng_desc},
  198. { 0, }
  199. };
  200. MODULE_DEVICE_TABLE(pci, sof_pci_ids);
  201. /* pci_driver definition */
  202. static struct pci_driver snd_sof_pci_intel_tng_driver = {
  203. .name = "sof-audio-pci-intel-tng",
  204. .id_table = sof_pci_ids,
  205. .probe = sof_pci_probe,
  206. .remove = sof_pci_remove,
  207. .shutdown = sof_pci_shutdown,
  208. .driver = {
  209. .pm = &sof_pci_pm,
  210. },
  211. };
  212. module_pci_driver(snd_sof_pci_intel_tng_driver);
  213. MODULE_LICENSE("Dual BSD/GPL");
  214. MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
  215. MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
  216. MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
  217. MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_ATOM_HIFI_EP);