xref: /openbmc/linux/sound/soc/sof/intel/atom.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
147fad239SPierre-Louis Bossart // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
247fad239SPierre-Louis Bossart //
347fad239SPierre-Louis Bossart // This file is provided under a dual BSD/GPLv2 license.  When using or
447fad239SPierre-Louis Bossart // redistributing this file, you may do so under either license.
547fad239SPierre-Louis Bossart //
647fad239SPierre-Louis Bossart // Copyright(c) 2018-2021 Intel Corporation. All rights reserved.
747fad239SPierre-Louis Bossart //
847fad239SPierre-Louis Bossart // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
947fad239SPierre-Louis Bossart //
1047fad239SPierre-Louis Bossart 
1147fad239SPierre-Louis Bossart /*
1247fad239SPierre-Louis Bossart  * Hardware interface for audio DSP on Atom devices
1347fad239SPierre-Louis Bossart  */
1447fad239SPierre-Louis Bossart 
1547fad239SPierre-Louis Bossart #include <linux/module.h>
1647fad239SPierre-Louis Bossart #include <sound/sof.h>
1747fad239SPierre-Louis Bossart #include <sound/sof/xtensa.h>
1847fad239SPierre-Louis Bossart #include <sound/soc-acpi.h>
1947fad239SPierre-Louis Bossart #include <sound/soc-acpi-intel-match.h>
2047fad239SPierre-Louis Bossart #include <sound/intel-dsp-config.h>
2147fad239SPierre-Louis Bossart #include "../ops.h"
2247fad239SPierre-Louis Bossart #include "shim.h"
2347fad239SPierre-Louis Bossart #include "atom.h"
2447fad239SPierre-Louis Bossart #include "../sof-acpi-dev.h"
2547fad239SPierre-Louis Bossart #include "../sof-audio.h"
2647fad239SPierre-Louis Bossart #include "../../intel/common/soc-intel-quirks.h"
2747fad239SPierre-Louis Bossart 
2847fad239SPierre-Louis Bossart static void atom_host_done(struct snd_sof_dev *sdev);
2947fad239SPierre-Louis Bossart static void atom_dsp_done(struct snd_sof_dev *sdev);
3047fad239SPierre-Louis Bossart 
3147fad239SPierre-Louis Bossart /*
3247fad239SPierre-Louis Bossart  * Debug
3347fad239SPierre-Louis Bossart  */
3447fad239SPierre-Louis Bossart 
atom_get_registers(struct snd_sof_dev * sdev,struct sof_ipc_dsp_oops_xtensa * xoops,struct sof_ipc_panic_info * panic_info,u32 * stack,size_t stack_words)3547fad239SPierre-Louis Bossart static void atom_get_registers(struct snd_sof_dev *sdev,
3647fad239SPierre-Louis Bossart 			       struct sof_ipc_dsp_oops_xtensa *xoops,
3747fad239SPierre-Louis Bossart 			       struct sof_ipc_panic_info *panic_info,
3847fad239SPierre-Louis Bossart 			       u32 *stack, size_t stack_words)
3947fad239SPierre-Louis Bossart {
4047fad239SPierre-Louis Bossart 	u32 offset = sdev->dsp_oops_offset;
4147fad239SPierre-Louis Bossart 
4247fad239SPierre-Louis Bossart 	/* first read regsisters */
4347fad239SPierre-Louis Bossart 	sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
4447fad239SPierre-Louis Bossart 
4547fad239SPierre-Louis Bossart 	/* note: variable AR register array is not read */
4647fad239SPierre-Louis Bossart 
4747fad239SPierre-Louis Bossart 	/* then get panic info */
4847fad239SPierre-Louis Bossart 	if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
4947fad239SPierre-Louis Bossart 		dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
5047fad239SPierre-Louis Bossart 			xoops->arch_hdr.totalsize);
5147fad239SPierre-Louis Bossart 		return;
5247fad239SPierre-Louis Bossart 	}
5347fad239SPierre-Louis Bossart 	offset += xoops->arch_hdr.totalsize;
5447fad239SPierre-Louis Bossart 	sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
5547fad239SPierre-Louis Bossart 
5647fad239SPierre-Louis Bossart 	/* then get the stack */
5747fad239SPierre-Louis Bossart 	offset += sizeof(*panic_info);
5847fad239SPierre-Louis Bossart 	sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
5947fad239SPierre-Louis Bossart }
6047fad239SPierre-Louis Bossart 
atom_dump(struct snd_sof_dev * sdev,u32 flags)6147fad239SPierre-Louis Bossart void atom_dump(struct snd_sof_dev *sdev, u32 flags)
6247fad239SPierre-Louis Bossart {
6347fad239SPierre-Louis Bossart 	struct sof_ipc_dsp_oops_xtensa xoops;
6447fad239SPierre-Louis Bossart 	struct sof_ipc_panic_info panic_info;
6547fad239SPierre-Louis Bossart 	u32 stack[STACK_DUMP_SIZE];
6647fad239SPierre-Louis Bossart 	u64 status, panic, imrd, imrx;
6747fad239SPierre-Louis Bossart 
6847fad239SPierre-Louis Bossart 	/* now try generic SOF status messages */
6947fad239SPierre-Louis Bossart 	status = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCD);
7047fad239SPierre-Louis Bossart 	panic = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCX);
7147fad239SPierre-Louis Bossart 	atom_get_registers(sdev, &xoops, &panic_info, stack,
7247fad239SPierre-Louis Bossart 			   STACK_DUMP_SIZE);
734995ffceSPeter Ujfalusi 	sof_print_oops_and_stack(sdev, KERN_ERR, status, panic, &xoops,
744995ffceSPeter Ujfalusi 				 &panic_info, stack, STACK_DUMP_SIZE);
7547fad239SPierre-Louis Bossart 
7647fad239SPierre-Louis Bossart 	/* provide some context for firmware debug */
7747fad239SPierre-Louis Bossart 	imrx = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IMRX);
7847fad239SPierre-Louis Bossart 	imrd = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IMRD);
7947fad239SPierre-Louis Bossart 	dev_err(sdev->dev,
8047fad239SPierre-Louis Bossart 		"error: ipc host -> DSP: pending %s complete %s raw 0x%llx\n",
8147fad239SPierre-Louis Bossart 		(panic & SHIM_IPCX_BUSY) ? "yes" : "no",
8247fad239SPierre-Louis Bossart 		(panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
8347fad239SPierre-Louis Bossart 	dev_err(sdev->dev,
8447fad239SPierre-Louis Bossart 		"error: mask host: pending %s complete %s raw 0x%llx\n",
8547fad239SPierre-Louis Bossart 		(imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
8647fad239SPierre-Louis Bossart 		(imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
8747fad239SPierre-Louis Bossart 	dev_err(sdev->dev,
8847fad239SPierre-Louis Bossart 		"error: ipc DSP -> host: pending %s complete %s raw 0x%llx\n",
8947fad239SPierre-Louis Bossart 		(status & SHIM_IPCD_BUSY) ? "yes" : "no",
9047fad239SPierre-Louis Bossart 		(status & SHIM_IPCD_DONE) ? "yes" : "no", status);
9147fad239SPierre-Louis Bossart 	dev_err(sdev->dev,
9247fad239SPierre-Louis Bossart 		"error: mask DSP: pending %s complete %s raw 0x%llx\n",
9347fad239SPierre-Louis Bossart 		(imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
9447fad239SPierre-Louis Bossart 		(imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
9547fad239SPierre-Louis Bossart 
9647fad239SPierre-Louis Bossart }
9747fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_dump, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
9847fad239SPierre-Louis Bossart 
9947fad239SPierre-Louis Bossart /*
10047fad239SPierre-Louis Bossart  * IPC Doorbell IRQ handler and thread.
10147fad239SPierre-Louis Bossart  */
10247fad239SPierre-Louis Bossart 
atom_irq_handler(int irq,void * context)10347fad239SPierre-Louis Bossart irqreturn_t atom_irq_handler(int irq, void *context)
10447fad239SPierre-Louis Bossart {
10547fad239SPierre-Louis Bossart 	struct snd_sof_dev *sdev = context;
10647fad239SPierre-Louis Bossart 	u64 ipcx, ipcd;
10747fad239SPierre-Louis Bossart 	int ret = IRQ_NONE;
10847fad239SPierre-Louis Bossart 
10947fad239SPierre-Louis Bossart 	ipcx = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCX);
11047fad239SPierre-Louis Bossart 	ipcd = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCD);
11147fad239SPierre-Louis Bossart 
11247fad239SPierre-Louis Bossart 	if (ipcx & SHIM_BYT_IPCX_DONE) {
11347fad239SPierre-Louis Bossart 
11447fad239SPierre-Louis Bossart 		/* reply message from DSP, Mask Done interrupt first */
11547fad239SPierre-Louis Bossart 		snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR,
11647fad239SPierre-Louis Bossart 						   SHIM_IMRX,
11747fad239SPierre-Louis Bossart 						   SHIM_IMRX_DONE,
11847fad239SPierre-Louis Bossart 						   SHIM_IMRX_DONE);
11947fad239SPierre-Louis Bossart 		ret = IRQ_WAKE_THREAD;
12047fad239SPierre-Louis Bossart 	}
12147fad239SPierre-Louis Bossart 
12247fad239SPierre-Louis Bossart 	if (ipcd & SHIM_BYT_IPCD_BUSY) {
12347fad239SPierre-Louis Bossart 
12447fad239SPierre-Louis Bossart 		/* new message from DSP, Mask Busy interrupt first */
12547fad239SPierre-Louis Bossart 		snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR,
12647fad239SPierre-Louis Bossart 						   SHIM_IMRX,
12747fad239SPierre-Louis Bossart 						   SHIM_IMRX_BUSY,
12847fad239SPierre-Louis Bossart 						   SHIM_IMRX_BUSY);
12947fad239SPierre-Louis Bossart 		ret = IRQ_WAKE_THREAD;
13047fad239SPierre-Louis Bossart 	}
13147fad239SPierre-Louis Bossart 
13247fad239SPierre-Louis Bossart 	return ret;
13347fad239SPierre-Louis Bossart }
13447fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_irq_handler, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
13547fad239SPierre-Louis Bossart 
atom_irq_thread(int irq,void * context)13647fad239SPierre-Louis Bossart irqreturn_t atom_irq_thread(int irq, void *context)
13747fad239SPierre-Louis Bossart {
13847fad239SPierre-Louis Bossart 	struct snd_sof_dev *sdev = context;
13947fad239SPierre-Louis Bossart 	u64 ipcx, ipcd;
14047fad239SPierre-Louis Bossart 
14147fad239SPierre-Louis Bossart 	ipcx = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCX);
14247fad239SPierre-Louis Bossart 	ipcd = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCD);
14347fad239SPierre-Louis Bossart 
14447fad239SPierre-Louis Bossart 	/* reply message from DSP */
14547fad239SPierre-Louis Bossart 	if (ipcx & SHIM_BYT_IPCX_DONE) {
14647fad239SPierre-Louis Bossart 
14747fad239SPierre-Louis Bossart 		spin_lock_irq(&sdev->ipc_lock);
14847fad239SPierre-Louis Bossart 
14947fad239SPierre-Louis Bossart 		/*
15047fad239SPierre-Louis Bossart 		 * handle immediate reply from DSP core. If the msg is
15147fad239SPierre-Louis Bossart 		 * found, set done bit in cmd_done which is called at the
15247fad239SPierre-Louis Bossart 		 * end of message processing function, else set it here
15347fad239SPierre-Louis Bossart 		 * because the done bit can't be set in cmd_done function
15447fad239SPierre-Louis Bossart 		 * which is triggered by msg
15547fad239SPierre-Louis Bossart 		 */
1560bd2891bSPeter Ujfalusi 		snd_sof_ipc_process_reply(sdev, ipcx);
15747fad239SPierre-Louis Bossart 
15847fad239SPierre-Louis Bossart 		atom_dsp_done(sdev);
15947fad239SPierre-Louis Bossart 
16047fad239SPierre-Louis Bossart 		spin_unlock_irq(&sdev->ipc_lock);
16147fad239SPierre-Louis Bossart 	}
16247fad239SPierre-Louis Bossart 
16347fad239SPierre-Louis Bossart 	/* new message from DSP */
16447fad239SPierre-Louis Bossart 	if (ipcd & SHIM_BYT_IPCD_BUSY) {
16547fad239SPierre-Louis Bossart 
16647fad239SPierre-Louis Bossart 		/* Handle messages from DSP Core */
16747fad239SPierre-Louis Bossart 		if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
168b2b10aa7SPeter Ujfalusi 			snd_sof_dsp_panic(sdev, PANIC_OFFSET(ipcd) + MBOX_OFFSET,
169b2b10aa7SPeter Ujfalusi 					  true);
17047fad239SPierre-Louis Bossart 		} else {
17147fad239SPierre-Louis Bossart 			snd_sof_ipc_msgs_rx(sdev);
17247fad239SPierre-Louis Bossart 		}
17347fad239SPierre-Louis Bossart 
17447fad239SPierre-Louis Bossart 		atom_host_done(sdev);
17547fad239SPierre-Louis Bossart 	}
17647fad239SPierre-Louis Bossart 
17747fad239SPierre-Louis Bossart 	return IRQ_HANDLED;
17847fad239SPierre-Louis Bossart }
17947fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_irq_thread, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
18047fad239SPierre-Louis Bossart 
atom_send_msg(struct snd_sof_dev * sdev,struct snd_sof_ipc_msg * msg)18147fad239SPierre-Louis Bossart int atom_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
18247fad239SPierre-Louis Bossart {
18347fad239SPierre-Louis Bossart 	/* unmask and prepare to receive Done interrupt */
18447fad239SPierre-Louis Bossart 	snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IMRX,
18547fad239SPierre-Louis Bossart 					   SHIM_IMRX_DONE, 0);
18647fad239SPierre-Louis Bossart 
18747fad239SPierre-Louis Bossart 	/* send the message */
18847fad239SPierre-Louis Bossart 	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
18947fad239SPierre-Louis Bossart 			  msg->msg_size);
19047fad239SPierre-Louis Bossart 	snd_sof_dsp_write64(sdev, DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY);
19147fad239SPierre-Louis Bossart 
19247fad239SPierre-Louis Bossart 	return 0;
19347fad239SPierre-Louis Bossart }
19447fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_send_msg, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
19547fad239SPierre-Louis Bossart 
atom_get_mailbox_offset(struct snd_sof_dev * sdev)19647fad239SPierre-Louis Bossart int atom_get_mailbox_offset(struct snd_sof_dev *sdev)
19747fad239SPierre-Louis Bossart {
19847fad239SPierre-Louis Bossart 	return MBOX_OFFSET;
19947fad239SPierre-Louis Bossart }
20047fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_get_mailbox_offset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
20147fad239SPierre-Louis Bossart 
atom_get_window_offset(struct snd_sof_dev * sdev,u32 id)20247fad239SPierre-Louis Bossart int atom_get_window_offset(struct snd_sof_dev *sdev, u32 id)
20347fad239SPierre-Louis Bossart {
20447fad239SPierre-Louis Bossart 	return MBOX_OFFSET;
20547fad239SPierre-Louis Bossart }
20647fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_get_window_offset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
20747fad239SPierre-Louis Bossart 
atom_host_done(struct snd_sof_dev * sdev)20847fad239SPierre-Louis Bossart static void atom_host_done(struct snd_sof_dev *sdev)
20947fad239SPierre-Louis Bossart {
21047fad239SPierre-Louis Bossart 	/* clear BUSY bit and set DONE bit - accept new messages */
21147fad239SPierre-Louis Bossart 	snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IPCD,
21247fad239SPierre-Louis Bossart 					   SHIM_BYT_IPCD_BUSY |
21347fad239SPierre-Louis Bossart 					   SHIM_BYT_IPCD_DONE,
21447fad239SPierre-Louis Bossart 					   SHIM_BYT_IPCD_DONE);
21547fad239SPierre-Louis Bossart 
21647fad239SPierre-Louis Bossart 	/* unmask and prepare to receive next new message */
21747fad239SPierre-Louis Bossart 	snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IMRX,
21847fad239SPierre-Louis Bossart 					   SHIM_IMRX_BUSY, 0);
21947fad239SPierre-Louis Bossart }
22047fad239SPierre-Louis Bossart 
atom_dsp_done(struct snd_sof_dev * sdev)22147fad239SPierre-Louis Bossart static void atom_dsp_done(struct snd_sof_dev *sdev)
22247fad239SPierre-Louis Bossart {
22347fad239SPierre-Louis Bossart 	/* clear DONE bit - tell DSP we have completed */
22447fad239SPierre-Louis Bossart 	snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IPCX,
22547fad239SPierre-Louis Bossart 					   SHIM_BYT_IPCX_DONE, 0);
22647fad239SPierre-Louis Bossart }
22747fad239SPierre-Louis Bossart 
22847fad239SPierre-Louis Bossart /*
22947fad239SPierre-Louis Bossart  * DSP control.
23047fad239SPierre-Louis Bossart  */
23147fad239SPierre-Louis Bossart 
atom_run(struct snd_sof_dev * sdev)23247fad239SPierre-Louis Bossart int atom_run(struct snd_sof_dev *sdev)
23347fad239SPierre-Louis Bossart {
23447fad239SPierre-Louis Bossart 	int tries = 10;
23547fad239SPierre-Louis Bossart 
23647fad239SPierre-Louis Bossart 	/* release stall and wait to unstall */
23747fad239SPierre-Louis Bossart 	snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_CSR,
23847fad239SPierre-Louis Bossart 				  SHIM_BYT_CSR_STALL, 0x0);
23947fad239SPierre-Louis Bossart 	while (tries--) {
24047fad239SPierre-Louis Bossart 		if (!(snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_CSR) &
24147fad239SPierre-Louis Bossart 		      SHIM_BYT_CSR_PWAITMODE))
24247fad239SPierre-Louis Bossart 			break;
24347fad239SPierre-Louis Bossart 		msleep(100);
24447fad239SPierre-Louis Bossart 	}
245e131bc58SPeter Ujfalusi 	if (tries < 0)
24647fad239SPierre-Louis Bossart 		return -ENODEV;
24747fad239SPierre-Louis Bossart 
24847fad239SPierre-Louis Bossart 	/* return init core mask */
24947fad239SPierre-Louis Bossart 	return 1;
25047fad239SPierre-Louis Bossart }
25147fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_run, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
25247fad239SPierre-Louis Bossart 
atom_reset(struct snd_sof_dev * sdev)25347fad239SPierre-Louis Bossart int atom_reset(struct snd_sof_dev *sdev)
25447fad239SPierre-Louis Bossart {
25547fad239SPierre-Louis Bossart 	/* put DSP into reset, set reset vector and stall */
25647fad239SPierre-Louis Bossart 	snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_CSR,
25747fad239SPierre-Louis Bossart 				  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
25847fad239SPierre-Louis Bossart 				  SHIM_BYT_CSR_STALL,
25947fad239SPierre-Louis Bossart 				  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
26047fad239SPierre-Louis Bossart 				  SHIM_BYT_CSR_STALL);
26147fad239SPierre-Louis Bossart 
26247fad239SPierre-Louis Bossart 	usleep_range(10, 15);
26347fad239SPierre-Louis Bossart 
26447fad239SPierre-Louis Bossart 	/* take DSP out of reset and keep stalled for FW loading */
26547fad239SPierre-Louis Bossart 	snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_CSR,
26647fad239SPierre-Louis Bossart 				  SHIM_BYT_CSR_RST, 0);
26747fad239SPierre-Louis Bossart 
26847fad239SPierre-Louis Bossart 	return 0;
26947fad239SPierre-Louis Bossart }
27047fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_reset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
27147fad239SPierre-Louis Bossart 
fixup_tplg_name(struct snd_sof_dev * sdev,const char * sof_tplg_filename,const char * ssp_str)27247fad239SPierre-Louis Bossart static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
27347fad239SPierre-Louis Bossart 				   const char *sof_tplg_filename,
27447fad239SPierre-Louis Bossart 				   const char *ssp_str)
27547fad239SPierre-Louis Bossart {
27647fad239SPierre-Louis Bossart 	const char *tplg_filename = NULL;
277*27b196c1SPeter Ujfalusi 	const char *split_ext;
278*27b196c1SPeter Ujfalusi 	char *filename, *tmp;
27947fad239SPierre-Louis Bossart 
280*27b196c1SPeter Ujfalusi 	filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
28147fad239SPierre-Louis Bossart 	if (!filename)
28247fad239SPierre-Louis Bossart 		return NULL;
28347fad239SPierre-Louis Bossart 
28447fad239SPierre-Louis Bossart 	/* this assumes a .tplg extension */
285*27b196c1SPeter Ujfalusi 	tmp = filename;
286*27b196c1SPeter Ujfalusi 	split_ext = strsep(&tmp, ".");
287*27b196c1SPeter Ujfalusi 	if (split_ext)
28847fad239SPierre-Louis Bossart 		tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
28947fad239SPierre-Louis Bossart 					       "%s-%s.tplg",
29047fad239SPierre-Louis Bossart 					       split_ext, ssp_str);
291*27b196c1SPeter Ujfalusi 	kfree(filename);
292*27b196c1SPeter Ujfalusi 
29347fad239SPierre-Louis Bossart 	return tplg_filename;
29447fad239SPierre-Louis Bossart }
29547fad239SPierre-Louis Bossart 
atom_machine_select(struct snd_sof_dev * sdev)296cb515f10SGuennadi Liakhovetski struct snd_soc_acpi_mach *atom_machine_select(struct snd_sof_dev *sdev)
29747fad239SPierre-Louis Bossart {
29847fad239SPierre-Louis Bossart 	struct snd_sof_pdata *sof_pdata = sdev->pdata;
29947fad239SPierre-Louis Bossart 	const struct sof_dev_desc *desc = sof_pdata->desc;
30047fad239SPierre-Louis Bossart 	struct snd_soc_acpi_mach *mach;
30147fad239SPierre-Louis Bossart 	struct platform_device *pdev;
30247fad239SPierre-Louis Bossart 	const char *tplg_filename;
30347fad239SPierre-Louis Bossart 
30447fad239SPierre-Louis Bossart 	mach = snd_soc_acpi_find_machine(desc->machines);
30547fad239SPierre-Louis Bossart 	if (!mach) {
30647fad239SPierre-Louis Bossart 		dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
307cb515f10SGuennadi Liakhovetski 		return NULL;
30847fad239SPierre-Louis Bossart 	}
30947fad239SPierre-Louis Bossart 
31047fad239SPierre-Louis Bossart 	pdev = to_platform_device(sdev->dev);
31147fad239SPierre-Louis Bossart 	if (soc_intel_is_byt_cr(pdev)) {
31247fad239SPierre-Louis Bossart 		dev_dbg(sdev->dev,
31347fad239SPierre-Louis Bossart 			"BYT-CR detected, SSP0 used instead of SSP2\n");
31447fad239SPierre-Louis Bossart 
31547fad239SPierre-Louis Bossart 		tplg_filename = fixup_tplg_name(sdev,
31647fad239SPierre-Louis Bossart 						mach->sof_tplg_filename,
31747fad239SPierre-Louis Bossart 						"ssp0");
31847fad239SPierre-Louis Bossart 	} else {
31947fad239SPierre-Louis Bossart 		tplg_filename = mach->sof_tplg_filename;
32047fad239SPierre-Louis Bossart 	}
32147fad239SPierre-Louis Bossart 
32247fad239SPierre-Louis Bossart 	if (!tplg_filename) {
32347fad239SPierre-Louis Bossart 		dev_dbg(sdev->dev,
32447fad239SPierre-Louis Bossart 			"error: no topology filename\n");
325cb515f10SGuennadi Liakhovetski 		return NULL;
32647fad239SPierre-Louis Bossart 	}
32747fad239SPierre-Louis Bossart 
32847fad239SPierre-Louis Bossart 	sof_pdata->tplg_filename = tplg_filename;
32947fad239SPierre-Louis Bossart 	mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
330cb515f10SGuennadi Liakhovetski 
331cb515f10SGuennadi Liakhovetski 	return mach;
33247fad239SPierre-Louis Bossart }
33347fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_machine_select, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
33447fad239SPierre-Louis Bossart 
33547fad239SPierre-Louis Bossart /* Atom DAIs */
33647fad239SPierre-Louis Bossart struct snd_soc_dai_driver atom_dai[] = {
33747fad239SPierre-Louis Bossart {
33847fad239SPierre-Louis Bossart 	.name = "ssp0-port",
33947fad239SPierre-Louis Bossart 	.playback = {
34047fad239SPierre-Louis Bossart 		.channels_min = 1,
34147fad239SPierre-Louis Bossart 		.channels_max = 8,
34247fad239SPierre-Louis Bossart 	},
34347fad239SPierre-Louis Bossart 	.capture = {
34447fad239SPierre-Louis Bossart 		.channels_min = 1,
34547fad239SPierre-Louis Bossart 		.channels_max = 8,
34647fad239SPierre-Louis Bossart 	},
34747fad239SPierre-Louis Bossart },
34847fad239SPierre-Louis Bossart {
34947fad239SPierre-Louis Bossart 	.name = "ssp1-port",
35047fad239SPierre-Louis Bossart 	.playback = {
35147fad239SPierre-Louis Bossart 		.channels_min = 1,
35247fad239SPierre-Louis Bossart 		.channels_max = 8,
35347fad239SPierre-Louis Bossart 	},
35447fad239SPierre-Louis Bossart 	.capture = {
35547fad239SPierre-Louis Bossart 		.channels_min = 1,
35647fad239SPierre-Louis Bossart 		.channels_max = 8,
35747fad239SPierre-Louis Bossart 	},
35847fad239SPierre-Louis Bossart },
35947fad239SPierre-Louis Bossart {
36047fad239SPierre-Louis Bossart 	.name = "ssp2-port",
36147fad239SPierre-Louis Bossart 	.playback = {
36247fad239SPierre-Louis Bossart 		.channels_min = 1,
36347fad239SPierre-Louis Bossart 		.channels_max = 8,
36447fad239SPierre-Louis Bossart 	},
36547fad239SPierre-Louis Bossart 	.capture = {
36647fad239SPierre-Louis Bossart 		.channels_min = 1,
36747fad239SPierre-Louis Bossart 		.channels_max = 8,
36847fad239SPierre-Louis Bossart 	}
36947fad239SPierre-Louis Bossart },
37047fad239SPierre-Louis Bossart {
37147fad239SPierre-Louis Bossart 	.name = "ssp3-port",
37247fad239SPierre-Louis Bossart 	.playback = {
37347fad239SPierre-Louis Bossart 		.channels_min = 1,
37447fad239SPierre-Louis Bossart 		.channels_max = 8,
37547fad239SPierre-Louis Bossart 	},
37647fad239SPierre-Louis Bossart 	.capture = {
37747fad239SPierre-Louis Bossart 		.channels_min = 1,
37847fad239SPierre-Louis Bossart 		.channels_max = 8,
37947fad239SPierre-Louis Bossart 	},
38047fad239SPierre-Louis Bossart },
38147fad239SPierre-Louis Bossart {
38247fad239SPierre-Louis Bossart 	.name = "ssp4-port",
38347fad239SPierre-Louis Bossart 	.playback = {
38447fad239SPierre-Louis Bossart 		.channels_min = 1,
38547fad239SPierre-Louis Bossart 		.channels_max = 8,
38647fad239SPierre-Louis Bossart 	},
38747fad239SPierre-Louis Bossart 	.capture = {
38847fad239SPierre-Louis Bossart 		.channels_min = 1,
38947fad239SPierre-Louis Bossart 		.channels_max = 8,
39047fad239SPierre-Louis Bossart 	},
39147fad239SPierre-Louis Bossart },
39247fad239SPierre-Louis Bossart {
39347fad239SPierre-Louis Bossart 	.name = "ssp5-port",
39447fad239SPierre-Louis Bossart 	.playback = {
39547fad239SPierre-Louis Bossart 		.channels_min = 1,
39647fad239SPierre-Louis Bossart 		.channels_max = 8,
39747fad239SPierre-Louis Bossart 	},
39847fad239SPierre-Louis Bossart 	.capture = {
39947fad239SPierre-Louis Bossart 		.channels_min = 1,
40047fad239SPierre-Louis Bossart 		.channels_max = 8,
40147fad239SPierre-Louis Bossart 	},
40247fad239SPierre-Louis Bossart },
40347fad239SPierre-Louis Bossart };
40447fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_dai, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
40547fad239SPierre-Louis Bossart 
atom_set_mach_params(struct snd_soc_acpi_mach * mach,struct snd_sof_dev * sdev)406cb515f10SGuennadi Liakhovetski void atom_set_mach_params(struct snd_soc_acpi_mach *mach,
40747fad239SPierre-Louis Bossart 			  struct snd_sof_dev *sdev)
40847fad239SPierre-Louis Bossart {
40947fad239SPierre-Louis Bossart 	struct snd_sof_pdata *pdata = sdev->pdata;
41047fad239SPierre-Louis Bossart 	const struct sof_dev_desc *desc = pdata->desc;
41147fad239SPierre-Louis Bossart 	struct snd_soc_acpi_mach_params *mach_params;
41247fad239SPierre-Louis Bossart 
413cb515f10SGuennadi Liakhovetski 	mach_params = &mach->mach_params;
41447fad239SPierre-Louis Bossart 	mach_params->platform = dev_name(sdev->dev);
41547fad239SPierre-Louis Bossart 	mach_params->num_dai_drivers = desc->ops->num_drv;
41647fad239SPierre-Louis Bossart 	mach_params->dai_drivers = desc->ops->drv;
41747fad239SPierre-Louis Bossart }
41847fad239SPierre-Louis Bossart EXPORT_SYMBOL_NS(atom_set_mach_params, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
41947fad239SPierre-Louis Bossart 
42047fad239SPierre-Louis Bossart MODULE_LICENSE("Dual BSD/GPL");
421