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