1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
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.
6 // Copyright(c) 2018 Intel Corporation
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
12 * Hardware interface for audio DSP on Baytrail, Braswell and Cherrytrail.
15 #include <linux/module.h>
16 #include <sound/sof.h>
17 #include <sound/sof/xtensa.h>
18 #include <sound/soc-acpi.h>
19 #include <sound/soc-acpi-intel-match.h>
20 #include <sound/intel-dsp-config.h>
24 #include "../sof-acpi-dev.h"
25 #include "../sof-audio.h"
26 #include "../../intel/common/soc-intel-quirks.h"
28 static const struct snd_sof_debugfs_map byt_debugfs
[] = {
29 {"dmac0", DSP_BAR
, DMAC0_OFFSET
, DMAC_SIZE
,
30 SOF_DEBUGFS_ACCESS_ALWAYS
},
31 {"dmac1", DSP_BAR
, DMAC1_OFFSET
, DMAC_SIZE
,
32 SOF_DEBUGFS_ACCESS_ALWAYS
},
33 {"ssp0", DSP_BAR
, SSP0_OFFSET
, SSP_SIZE
,
34 SOF_DEBUGFS_ACCESS_ALWAYS
},
35 {"ssp1", DSP_BAR
, SSP1_OFFSET
, SSP_SIZE
,
36 SOF_DEBUGFS_ACCESS_ALWAYS
},
37 {"ssp2", DSP_BAR
, SSP2_OFFSET
, SSP_SIZE
,
38 SOF_DEBUGFS_ACCESS_ALWAYS
},
39 {"iram", DSP_BAR
, IRAM_OFFSET
, IRAM_SIZE
,
40 SOF_DEBUGFS_ACCESS_D0_ONLY
},
41 {"dram", DSP_BAR
, DRAM_OFFSET
, DRAM_SIZE
,
42 SOF_DEBUGFS_ACCESS_D0_ONLY
},
43 {"shim", DSP_BAR
, SHIM_OFFSET
, SHIM_SIZE_BYT
,
44 SOF_DEBUGFS_ACCESS_ALWAYS
},
47 static const struct snd_sof_debugfs_map cht_debugfs
[] = {
48 {"dmac0", DSP_BAR
, DMAC0_OFFSET
, DMAC_SIZE
,
49 SOF_DEBUGFS_ACCESS_ALWAYS
},
50 {"dmac1", DSP_BAR
, DMAC1_OFFSET
, DMAC_SIZE
,
51 SOF_DEBUGFS_ACCESS_ALWAYS
},
52 {"dmac2", DSP_BAR
, DMAC2_OFFSET
, DMAC_SIZE
,
53 SOF_DEBUGFS_ACCESS_ALWAYS
},
54 {"ssp0", DSP_BAR
, SSP0_OFFSET
, SSP_SIZE
,
55 SOF_DEBUGFS_ACCESS_ALWAYS
},
56 {"ssp1", DSP_BAR
, SSP1_OFFSET
, SSP_SIZE
,
57 SOF_DEBUGFS_ACCESS_ALWAYS
},
58 {"ssp2", DSP_BAR
, SSP2_OFFSET
, SSP_SIZE
,
59 SOF_DEBUGFS_ACCESS_ALWAYS
},
60 {"ssp3", DSP_BAR
, SSP3_OFFSET
, SSP_SIZE
,
61 SOF_DEBUGFS_ACCESS_ALWAYS
},
62 {"ssp4", DSP_BAR
, SSP4_OFFSET
, SSP_SIZE
,
63 SOF_DEBUGFS_ACCESS_ALWAYS
},
64 {"ssp5", DSP_BAR
, SSP5_OFFSET
, SSP_SIZE
,
65 SOF_DEBUGFS_ACCESS_ALWAYS
},
66 {"iram", DSP_BAR
, IRAM_OFFSET
, IRAM_SIZE
,
67 SOF_DEBUGFS_ACCESS_D0_ONLY
},
68 {"dram", DSP_BAR
, DRAM_OFFSET
, DRAM_SIZE
,
69 SOF_DEBUGFS_ACCESS_D0_ONLY
},
70 {"shim", DSP_BAR
, SHIM_OFFSET
, SHIM_SIZE_CHT
,
71 SOF_DEBUGFS_ACCESS_ALWAYS
},
74 static void byt_reset_dsp_disable_int(struct snd_sof_dev
*sdev
)
76 /* Disable Interrupt from both sides */
77 snd_sof_dsp_update_bits64(sdev
, DSP_BAR
, SHIM_IMRX
, 0x3, 0x3);
78 snd_sof_dsp_update_bits64(sdev
, DSP_BAR
, SHIM_IMRD
, 0x3, 0x3);
80 /* Put DSP into reset, set reset vector */
81 snd_sof_dsp_update_bits64(sdev
, DSP_BAR
, SHIM_CSR
,
82 SHIM_BYT_CSR_RST
| SHIM_BYT_CSR_VECTOR_SEL
,
83 SHIM_BYT_CSR_RST
| SHIM_BYT_CSR_VECTOR_SEL
);
86 static int byt_suspend(struct snd_sof_dev
*sdev
, u32 target_state
)
88 byt_reset_dsp_disable_int(sdev
);
93 static int byt_resume(struct snd_sof_dev
*sdev
)
95 /* enable BUSY and disable DONE Interrupt by default */
96 snd_sof_dsp_update_bits64(sdev
, DSP_BAR
, SHIM_IMRX
,
97 SHIM_IMRX_BUSY
| SHIM_IMRX_DONE
,
103 static void byt_remove(struct snd_sof_dev
*sdev
)
105 byt_reset_dsp_disable_int(sdev
);
108 static int byt_acpi_probe(struct snd_sof_dev
*sdev
)
110 struct snd_sof_pdata
*pdata
= sdev
->pdata
;
111 const struct sof_dev_desc
*desc
= pdata
->desc
;
112 struct platform_device
*pdev
=
113 container_of(sdev
->dev
, struct platform_device
, dev
);
114 const struct sof_intel_dsp_desc
*chip
;
115 struct resource
*mmio
;
119 chip
= get_chip_info(sdev
->pdata
);
121 dev_err(sdev
->dev
, "error: no such device supported\n");
125 sdev
->num_cores
= chip
->cores_num
;
127 /* DSP DMA can only access low 31 bits of host memory */
128 ret
= dma_coerce_mask_and_coherent(sdev
->dev
, DMA_BIT_MASK(31));
130 dev_err(sdev
->dev
, "error: failed to set DMA mask %d\n", ret
);
135 mmio
= platform_get_resource(pdev
, IORESOURCE_MEM
,
136 desc
->resindex_lpe_base
);
139 size
= resource_size(mmio
);
141 dev_err(sdev
->dev
, "error: failed to get LPE base at idx %d\n",
142 desc
->resindex_lpe_base
);
146 dev_dbg(sdev
->dev
, "LPE PHY base at 0x%x size 0x%x", base
, size
);
147 sdev
->bar
[DSP_BAR
] = devm_ioremap(sdev
->dev
, base
, size
);
148 if (!sdev
->bar
[DSP_BAR
]) {
149 dev_err(sdev
->dev
, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
153 dev_dbg(sdev
->dev
, "LPE VADDR %p\n", sdev
->bar
[DSP_BAR
]);
155 /* TODO: add offsets */
156 sdev
->mmio_bar
= DSP_BAR
;
157 sdev
->mailbox_bar
= DSP_BAR
;
159 /* IMR base - optional */
160 if (desc
->resindex_imr_base
== -1)
163 mmio
= platform_get_resource(pdev
, IORESOURCE_MEM
,
164 desc
->resindex_imr_base
);
167 size
= resource_size(mmio
);
169 dev_err(sdev
->dev
, "error: failed to get IMR base at idx %d\n",
170 desc
->resindex_imr_base
);
174 /* some BIOSes don't map IMR */
175 if (base
== 0x55aa55aa || base
== 0x0) {
176 dev_info(sdev
->dev
, "IMR not set by BIOS. Ignoring\n");
180 dev_dbg(sdev
->dev
, "IMR base at 0x%x size 0x%x", base
, size
);
181 sdev
->bar
[IMR_BAR
] = devm_ioremap(sdev
->dev
, base
, size
);
182 if (!sdev
->bar
[IMR_BAR
]) {
183 dev_err(sdev
->dev
, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
187 dev_dbg(sdev
->dev
, "IMR VADDR %p\n", sdev
->bar
[IMR_BAR
]);
190 /* register our IRQ */
191 sdev
->ipc_irq
= platform_get_irq(pdev
, desc
->irqindex_host_ipc
);
192 if (sdev
->ipc_irq
< 0)
193 return sdev
->ipc_irq
;
195 dev_dbg(sdev
->dev
, "using IRQ %d\n", sdev
->ipc_irq
);
196 ret
= devm_request_threaded_irq(sdev
->dev
, sdev
->ipc_irq
,
197 atom_irq_handler
, atom_irq_thread
,
198 IRQF_SHARED
, "AudioDSP", sdev
);
200 dev_err(sdev
->dev
, "error: failed to register IRQ %d\n",
205 /* enable BUSY and disable DONE Interrupt by default */
206 snd_sof_dsp_update_bits64(sdev
, DSP_BAR
, SHIM_IMRX
,
207 SHIM_IMRX_BUSY
| SHIM_IMRX_DONE
,
210 /* set default mailbox offset for FW ready message */
211 sdev
->dsp_box
.offset
= MBOX_OFFSET
;
217 static const struct snd_sof_dsp_ops sof_byt_ops
= {
219 .probe
= byt_acpi_probe
,
220 .remove
= byt_remove
,
222 /* DSP core boot / reset */
226 /* Register IO uses direct mmio */
229 .block_read
= sof_block_read
,
230 .block_write
= sof_block_write
,
233 .mailbox_read
= sof_mailbox_read
,
234 .mailbox_write
= sof_mailbox_write
,
237 .irq_handler
= atom_irq_handler
,
238 .irq_thread
= atom_irq_thread
,
241 .send_msg
= atom_send_msg
,
242 .get_mailbox_offset
= atom_get_mailbox_offset
,
243 .get_window_offset
= atom_get_window_offset
,
245 .ipc_msg_data
= sof_ipc_msg_data
,
246 .set_stream_data_offset
= sof_set_stream_data_offset
,
249 .machine_select
= atom_machine_select
,
250 .machine_register
= sof_machine_register
,
251 .machine_unregister
= sof_machine_unregister
,
252 .set_mach_params
= atom_set_mach_params
,
255 .debug_map
= byt_debugfs
,
256 .debug_map_count
= ARRAY_SIZE(byt_debugfs
),
257 .dbg_dump
= atom_dump
,
258 .debugfs_add_region_item
= snd_sof_debugfs_add_region_item_iomem
,
260 /* stream callbacks */
261 .pcm_open
= sof_stream_pcm_open
,
262 .pcm_close
= sof_stream_pcm_close
,
264 /*Firmware loading */
265 .load_firmware
= snd_sof_load_firmware_memcpy
,
268 .suspend
= byt_suspend
,
269 .resume
= byt_resume
,
273 .num_drv
= 3, /* we have only 3 SSPs on byt*/
275 /* ALSA HW info flags */
276 .hw_info
= SNDRV_PCM_INFO_MMAP
|
277 SNDRV_PCM_INFO_MMAP_VALID
|
278 SNDRV_PCM_INFO_INTERLEAVED
|
279 SNDRV_PCM_INFO_PAUSE
|
280 SNDRV_PCM_INFO_BATCH
,
282 .dsp_arch_ops
= &sof_xtensa_arch_ops
,
285 static const struct sof_intel_dsp_desc byt_chip_info
= {
287 .host_managed_cores_mask
= 1,
288 .hw_ip_version
= SOF_INTEL_BAYTRAIL
,
291 /* cherrytrail and braswell ops */
292 static const struct snd_sof_dsp_ops sof_cht_ops
= {
294 .probe
= byt_acpi_probe
,
295 .remove
= byt_remove
,
297 /* DSP core boot / reset */
301 /* Register IO uses direct mmio */
304 .block_read
= sof_block_read
,
305 .block_write
= sof_block_write
,
308 .mailbox_read
= sof_mailbox_read
,
309 .mailbox_write
= sof_mailbox_write
,
312 .irq_handler
= atom_irq_handler
,
313 .irq_thread
= atom_irq_thread
,
316 .send_msg
= atom_send_msg
,
317 .get_mailbox_offset
= atom_get_mailbox_offset
,
318 .get_window_offset
= atom_get_window_offset
,
320 .ipc_msg_data
= sof_ipc_msg_data
,
321 .set_stream_data_offset
= sof_set_stream_data_offset
,
324 .machine_select
= atom_machine_select
,
325 .machine_register
= sof_machine_register
,
326 .machine_unregister
= sof_machine_unregister
,
327 .set_mach_params
= atom_set_mach_params
,
330 .debug_map
= cht_debugfs
,
331 .debug_map_count
= ARRAY_SIZE(cht_debugfs
),
332 .dbg_dump
= atom_dump
,
333 .debugfs_add_region_item
= snd_sof_debugfs_add_region_item_iomem
,
335 /* stream callbacks */
336 .pcm_open
= sof_stream_pcm_open
,
337 .pcm_close
= sof_stream_pcm_close
,
339 /*Firmware loading */
340 .load_firmware
= snd_sof_load_firmware_memcpy
,
343 .suspend
= byt_suspend
,
344 .resume
= byt_resume
,
348 /* all 6 SSPs may be available for cherrytrail */
351 /* ALSA HW info flags */
352 .hw_info
= SNDRV_PCM_INFO_MMAP
|
353 SNDRV_PCM_INFO_MMAP_VALID
|
354 SNDRV_PCM_INFO_INTERLEAVED
|
355 SNDRV_PCM_INFO_PAUSE
|
356 SNDRV_PCM_INFO_BATCH
,
358 .dsp_arch_ops
= &sof_xtensa_arch_ops
,
361 static const struct sof_intel_dsp_desc cht_chip_info
= {
363 .host_managed_cores_mask
= 1,
364 .hw_ip_version
= SOF_INTEL_BAYTRAIL
,
367 /* BYTCR uses different IRQ index */
368 static const struct sof_dev_desc sof_acpi_baytrailcr_desc
= {
369 .machines
= snd_soc_acpi_intel_baytrail_machines
,
370 .resindex_lpe_base
= 0,
371 .resindex_pcicfg_base
= 1,
372 .resindex_imr_base
= 2,
373 .irqindex_host_ipc
= 0,
374 .chip_info
= &byt_chip_info
,
375 .ipc_supported_mask
= BIT(SOF_IPC_TYPE_3
),
376 .ipc_default
= SOF_IPC_TYPE_3
,
378 [SOF_IPC_TYPE_3
] = "intel/sof",
380 .default_tplg_path
= {
381 [SOF_IPC_TYPE_3
] = "intel/sof-tplg",
383 .default_fw_filename
= {
384 [SOF_IPC_TYPE_3
] = "sof-byt.ri",
386 .nocodec_tplg_filename
= "sof-byt-nocodec.tplg",
390 static const struct sof_dev_desc sof_acpi_baytrail_desc
= {
391 .machines
= snd_soc_acpi_intel_baytrail_machines
,
392 .resindex_lpe_base
= 0,
393 .resindex_pcicfg_base
= 1,
394 .resindex_imr_base
= 2,
395 .irqindex_host_ipc
= 5,
396 .chip_info
= &byt_chip_info
,
397 .ipc_supported_mask
= BIT(SOF_IPC_TYPE_3
),
398 .ipc_default
= SOF_IPC_TYPE_3
,
400 [SOF_IPC_TYPE_3
] = "intel/sof",
402 .default_tplg_path
= {
403 [SOF_IPC_TYPE_3
] = "intel/sof-tplg",
405 .default_fw_filename
= {
406 [SOF_IPC_TYPE_3
] = "sof-byt.ri",
408 .nocodec_tplg_filename
= "sof-byt-nocodec.tplg",
412 static const struct sof_dev_desc sof_acpi_cherrytrail_desc
= {
413 .machines
= snd_soc_acpi_intel_cherrytrail_machines
,
414 .resindex_lpe_base
= 0,
415 .resindex_pcicfg_base
= 1,
416 .resindex_imr_base
= 2,
417 .irqindex_host_ipc
= 5,
418 .chip_info
= &cht_chip_info
,
419 .ipc_supported_mask
= BIT(SOF_IPC_TYPE_3
),
420 .ipc_default
= SOF_IPC_TYPE_3
,
422 [SOF_IPC_TYPE_3
] = "intel/sof",
424 .default_tplg_path
= {
425 [SOF_IPC_TYPE_3
] = "intel/sof-tplg",
427 .default_fw_filename
= {
428 [SOF_IPC_TYPE_3
] = "sof-cht.ri",
430 .nocodec_tplg_filename
= "sof-cht-nocodec.tplg",
434 static const struct acpi_device_id sof_baytrail_match
[] = {
435 { "80860F28", (unsigned long)&sof_acpi_baytrail_desc
},
436 { "808622A8", (unsigned long)&sof_acpi_cherrytrail_desc
},
439 MODULE_DEVICE_TABLE(acpi
, sof_baytrail_match
);
441 static int sof_baytrail_probe(struct platform_device
*pdev
)
443 struct device
*dev
= &pdev
->dev
;
444 const struct sof_dev_desc
*desc
;
445 const struct acpi_device_id
*id
;
448 id
= acpi_match_device(dev
->driver
->acpi_match_table
, dev
);
452 ret
= snd_intel_acpi_dsp_driver_probe(dev
, id
->id
);
453 if (ret
!= SND_INTEL_DSP_DRIVER_ANY
&& ret
!= SND_INTEL_DSP_DRIVER_SOF
) {
454 dev_dbg(dev
, "SOF ACPI driver not selected, aborting probe\n");
458 desc
= (const struct sof_dev_desc
*)id
->driver_data
;
459 if (desc
== &sof_acpi_baytrail_desc
&& soc_intel_is_byt_cr(pdev
))
460 desc
= &sof_acpi_baytrailcr_desc
;
462 return sof_acpi_probe(pdev
, desc
);
465 /* acpi_driver definition */
466 static struct platform_driver snd_sof_acpi_intel_byt_driver
= {
467 .probe
= sof_baytrail_probe
,
468 .remove
= sof_acpi_remove
,
470 .name
= "sof-audio-acpi-intel-byt",
472 .acpi_match_table
= sof_baytrail_match
,
475 module_platform_driver(snd_sof_acpi_intel_byt_driver
);
477 MODULE_LICENSE("Dual BSD/GPL");
478 MODULE_DESCRIPTION("SOF support for Baytrail/Cherrytrail");
479 MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HIFI_EP_IPC");
480 MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
481 MODULE_IMPORT_NS("SND_SOC_SOF_ACPI_DEV");
482 MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_ATOM_HIFI_EP");