162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// This file is provided under a dual BSD/GPLv2 license.  When using or
462306a36Sopenharmony_ci// redistributing this file, you may do so under either license.
562306a36Sopenharmony_ci//
662306a36Sopenharmony_ci// Copyright(c) 2018 Intel Corporation. All rights reserved.
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
962306a36Sopenharmony_ci//
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * Hardware interface for audio DSP on Broadwell
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <sound/sof.h>
1762306a36Sopenharmony_ci#include <sound/sof/xtensa.h>
1862306a36Sopenharmony_ci#include <sound/soc-acpi.h>
1962306a36Sopenharmony_ci#include <sound/soc-acpi-intel-match.h>
2062306a36Sopenharmony_ci#include <sound/intel-dsp-config.h>
2162306a36Sopenharmony_ci#include "../ops.h"
2262306a36Sopenharmony_ci#include "shim.h"
2362306a36Sopenharmony_ci#include "../sof-acpi-dev.h"
2462306a36Sopenharmony_ci#include "../sof-audio.h"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* BARs */
2762306a36Sopenharmony_ci#define BDW_DSP_BAR 0
2862306a36Sopenharmony_ci#define BDW_PCI_BAR 1
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*
3162306a36Sopenharmony_ci * Debug
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* DSP memories for BDW */
3562306a36Sopenharmony_ci#define IRAM_OFFSET     0xA0000
3662306a36Sopenharmony_ci#define BDW_IRAM_SIZE       (10 * 32 * 1024)
3762306a36Sopenharmony_ci#define DRAM_OFFSET     0x00000
3862306a36Sopenharmony_ci#define BDW_DRAM_SIZE       (20 * 32 * 1024)
3962306a36Sopenharmony_ci#define SHIM_OFFSET     0xFB000
4062306a36Sopenharmony_ci#define SHIM_SIZE       0x100
4162306a36Sopenharmony_ci#define MBOX_OFFSET     0x9E000
4262306a36Sopenharmony_ci#define MBOX_SIZE       0x1000
4362306a36Sopenharmony_ci#define MBOX_DUMP_SIZE 0x30
4462306a36Sopenharmony_ci#define EXCEPT_OFFSET	0x800
4562306a36Sopenharmony_ci#define EXCEPT_MAX_HDR_SIZE	0x400
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* DSP peripherals */
4862306a36Sopenharmony_ci#define DMAC0_OFFSET    0xFE000
4962306a36Sopenharmony_ci#define DMAC1_OFFSET    0xFF000
5062306a36Sopenharmony_ci#define DMAC_SIZE       0x420
5162306a36Sopenharmony_ci#define SSP0_OFFSET     0xFC000
5262306a36Sopenharmony_ci#define SSP1_OFFSET     0xFD000
5362306a36Sopenharmony_ci#define SSP_SIZE	0x100
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define BDW_STACK_DUMP_SIZE	32
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define BDW_PANIC_OFFSET(x)	((x) & 0xFFFF)
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic const struct snd_sof_debugfs_map bdw_debugfs[] = {
6062306a36Sopenharmony_ci	{"dmac0", BDW_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
6162306a36Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
6262306a36Sopenharmony_ci	{"dmac1", BDW_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
6362306a36Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
6462306a36Sopenharmony_ci	{"ssp0", BDW_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
6562306a36Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
6662306a36Sopenharmony_ci	{"ssp1", BDW_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
6762306a36Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
6862306a36Sopenharmony_ci	{"iram", BDW_DSP_BAR, IRAM_OFFSET, BDW_IRAM_SIZE,
6962306a36Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_D0_ONLY},
7062306a36Sopenharmony_ci	{"dram", BDW_DSP_BAR, DRAM_OFFSET, BDW_DRAM_SIZE,
7162306a36Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_D0_ONLY},
7262306a36Sopenharmony_ci	{"shim", BDW_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
7362306a36Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic void bdw_host_done(struct snd_sof_dev *sdev);
7762306a36Sopenharmony_cistatic void bdw_dsp_done(struct snd_sof_dev *sdev);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/*
8062306a36Sopenharmony_ci * DSP Control.
8162306a36Sopenharmony_ci */
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic int bdw_run(struct snd_sof_dev *sdev)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	/* set opportunistic mode on engine 0,1 for all channels */
8662306a36Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
8762306a36Sopenharmony_ci				SHIM_HMDC_HDDA_E0_ALLCH |
8862306a36Sopenharmony_ci				SHIM_HMDC_HDDA_E1_ALLCH, 0);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/* set DSP to RUN */
9162306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
9262306a36Sopenharmony_ci					 SHIM_CSR_STALL, 0x0);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	/* return init core mask */
9562306a36Sopenharmony_ci	return 1;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic int bdw_reset(struct snd_sof_dev *sdev)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	/* put DSP into reset and stall */
10162306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
10262306a36Sopenharmony_ci					 SHIM_CSR_RST | SHIM_CSR_STALL,
10362306a36Sopenharmony_ci					 SHIM_CSR_RST | SHIM_CSR_STALL);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	/* keep in reset for 10ms */
10662306a36Sopenharmony_ci	mdelay(10);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	/* take DSP out of reset and keep stalled for FW loading */
10962306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
11062306a36Sopenharmony_ci					 SHIM_CSR_RST | SHIM_CSR_STALL,
11162306a36Sopenharmony_ci					 SHIM_CSR_STALL);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	return 0;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic int bdw_set_dsp_D0(struct snd_sof_dev *sdev)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	int tries = 10;
11962306a36Sopenharmony_ci	u32 reg;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
12262306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
12362306a36Sopenharmony_ci					 PCI_VDRTCL2_DCLCGE |
12462306a36Sopenharmony_ci					 PCI_VDRTCL2_DTCGE, 0);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* Disable D3PG (VDRTCTL0.D3PGD = 1) */
12762306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
12862306a36Sopenharmony_ci					 PCI_VDRTCL0_D3PGD, PCI_VDRTCL0_D3PGD);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	/* Set D0 state */
13162306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_PMCS,
13262306a36Sopenharmony_ci					 PCI_PMCS_PS_MASK, 0);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/* check that ADSP shim is enabled */
13562306a36Sopenharmony_ci	while (tries--) {
13662306a36Sopenharmony_ci		reg = readl(sdev->bar[BDW_PCI_BAR] + PCI_PMCS)
13762306a36Sopenharmony_ci			& PCI_PMCS_PS_MASK;
13862306a36Sopenharmony_ci		if (reg == 0)
13962306a36Sopenharmony_ci			goto finish;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci		msleep(20);
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	return -ENODEV;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cifinish:
14762306a36Sopenharmony_ci	/*
14862306a36Sopenharmony_ci	 * select SSP1 19.2MHz base clock, SSP clock 0,
14962306a36Sopenharmony_ci	 * turn off Low Power Clock
15062306a36Sopenharmony_ci	 */
15162306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
15262306a36Sopenharmony_ci					 SHIM_CSR_S1IOCS | SHIM_CSR_SBCS1 |
15362306a36Sopenharmony_ci					 SHIM_CSR_LPCS, 0x0);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* stall DSP core, set clk to 192/96Mhz */
15662306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
15762306a36Sopenharmony_ci					 SHIM_CSR, SHIM_CSR_STALL |
15862306a36Sopenharmony_ci					 SHIM_CSR_DCS_MASK,
15962306a36Sopenharmony_ci					 SHIM_CSR_STALL |
16062306a36Sopenharmony_ci					 SHIM_CSR_DCS(4));
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	/* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
16362306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CLKCTL,
16462306a36Sopenharmony_ci					 SHIM_CLKCTL_MASK |
16562306a36Sopenharmony_ci					 SHIM_CLKCTL_DCPLCG |
16662306a36Sopenharmony_ci					 SHIM_CLKCTL_SCOE0,
16762306a36Sopenharmony_ci					 SHIM_CLKCTL_MASK |
16862306a36Sopenharmony_ci					 SHIM_CLKCTL_DCPLCG |
16962306a36Sopenharmony_ci					 SHIM_CLKCTL_SCOE0);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	/* Stall and reset core, set CSR */
17262306a36Sopenharmony_ci	bdw_reset(sdev);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
17562306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
17662306a36Sopenharmony_ci					 PCI_VDRTCL2_DCLCGE |
17762306a36Sopenharmony_ci					 PCI_VDRTCL2_DTCGE,
17862306a36Sopenharmony_ci					 PCI_VDRTCL2_DCLCGE |
17962306a36Sopenharmony_ci					 PCI_VDRTCL2_DTCGE);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	usleep_range(50, 55);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	/* switch on audio PLL */
18462306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
18562306a36Sopenharmony_ci					 PCI_VDRTCL2_APLLSE_MASK, 0);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/*
18862306a36Sopenharmony_ci	 * set default power gating control, enable power gating control for
18962306a36Sopenharmony_ci	 * all blocks. that is, can't be accessed, please enable each block
19062306a36Sopenharmony_ci	 * before accessing.
19162306a36Sopenharmony_ci	 */
19262306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
19362306a36Sopenharmony_ci					 0xfffffffC, 0x0);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	/* disable DMA finish function for SSP0 & SSP1 */
19662306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,  SHIM_CSR2,
19762306a36Sopenharmony_ci					 SHIM_CSR2_SDFD_SSP1,
19862306a36Sopenharmony_ci					 SHIM_CSR2_SDFD_SSP1);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	/* set on-demond mode on engine 0,1 for all channels */
20162306a36Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
20262306a36Sopenharmony_ci				SHIM_HMDC_HDDA_E0_ALLCH |
20362306a36Sopenharmony_ci				SHIM_HMDC_HDDA_E1_ALLCH,
20462306a36Sopenharmony_ci				SHIM_HMDC_HDDA_E0_ALLCH |
20562306a36Sopenharmony_ci				SHIM_HMDC_HDDA_E1_ALLCH);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	/* Enable Interrupt from both sides */
20862306a36Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRX,
20962306a36Sopenharmony_ci				(SHIM_IMRX_BUSY | SHIM_IMRX_DONE), 0x0);
21062306a36Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRD,
21162306a36Sopenharmony_ci				(SHIM_IMRD_DONE | SHIM_IMRD_BUSY |
21262306a36Sopenharmony_ci				SHIM_IMRD_SSP0 | SHIM_IMRD_DMAC), 0x0);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	/* clear IPC registers */
21562306a36Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, 0x0);
21662306a36Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCD, 0x0);
21762306a36Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0x80, 0x6);
21862306a36Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0xe0, 0x300a);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	return 0;
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistatic void bdw_get_registers(struct snd_sof_dev *sdev,
22462306a36Sopenharmony_ci			      struct sof_ipc_dsp_oops_xtensa *xoops,
22562306a36Sopenharmony_ci			      struct sof_ipc_panic_info *panic_info,
22662306a36Sopenharmony_ci			      u32 *stack, size_t stack_words)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	u32 offset = sdev->dsp_oops_offset;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	/* first read registers */
23162306a36Sopenharmony_ci	sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	/* note: variable AR register array is not read */
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	/* then get panic info */
23662306a36Sopenharmony_ci	if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
23762306a36Sopenharmony_ci		dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
23862306a36Sopenharmony_ci			xoops->arch_hdr.totalsize);
23962306a36Sopenharmony_ci		return;
24062306a36Sopenharmony_ci	}
24162306a36Sopenharmony_ci	offset += xoops->arch_hdr.totalsize;
24262306a36Sopenharmony_ci	sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* then get the stack */
24562306a36Sopenharmony_ci	offset += sizeof(*panic_info);
24662306a36Sopenharmony_ci	sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic void bdw_dump(struct snd_sof_dev *sdev, u32 flags)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	struct sof_ipc_dsp_oops_xtensa xoops;
25262306a36Sopenharmony_ci	struct sof_ipc_panic_info panic_info;
25362306a36Sopenharmony_ci	u32 stack[BDW_STACK_DUMP_SIZE];
25462306a36Sopenharmony_ci	u32 status, panic, imrx, imrd;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	/* now try generic SOF status messages */
25762306a36Sopenharmony_ci	status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
25862306a36Sopenharmony_ci	panic = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
25962306a36Sopenharmony_ci	bdw_get_registers(sdev, &xoops, &panic_info, stack,
26062306a36Sopenharmony_ci			  BDW_STACK_DUMP_SIZE);
26162306a36Sopenharmony_ci	sof_print_oops_and_stack(sdev, KERN_ERR, status, panic, &xoops,
26262306a36Sopenharmony_ci				 &panic_info, stack, BDW_STACK_DUMP_SIZE);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	/* provide some context for firmware debug */
26562306a36Sopenharmony_ci	imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX);
26662306a36Sopenharmony_ci	imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD);
26762306a36Sopenharmony_ci	dev_err(sdev->dev,
26862306a36Sopenharmony_ci		"error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
26962306a36Sopenharmony_ci		(panic & SHIM_IPCX_BUSY) ? "yes" : "no",
27062306a36Sopenharmony_ci		(panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
27162306a36Sopenharmony_ci	dev_err(sdev->dev,
27262306a36Sopenharmony_ci		"error: mask host: pending %s complete %s raw 0x%8.8x\n",
27362306a36Sopenharmony_ci		(imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
27462306a36Sopenharmony_ci		(imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
27562306a36Sopenharmony_ci	dev_err(sdev->dev,
27662306a36Sopenharmony_ci		"error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
27762306a36Sopenharmony_ci		(status & SHIM_IPCD_BUSY) ? "yes" : "no",
27862306a36Sopenharmony_ci		(status & SHIM_IPCD_DONE) ? "yes" : "no", status);
27962306a36Sopenharmony_ci	dev_err(sdev->dev,
28062306a36Sopenharmony_ci		"error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
28162306a36Sopenharmony_ci		(imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
28262306a36Sopenharmony_ci		(imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci/*
28662306a36Sopenharmony_ci * IPC Doorbell IRQ handler and thread.
28762306a36Sopenharmony_ci */
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic irqreturn_t bdw_irq_handler(int irq, void *context)
29062306a36Sopenharmony_ci{
29162306a36Sopenharmony_ci	struct snd_sof_dev *sdev = context;
29262306a36Sopenharmony_ci	u32 isr;
29362306a36Sopenharmony_ci	int ret = IRQ_NONE;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	/* Interrupt arrived, check src */
29662306a36Sopenharmony_ci	isr = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_ISRX);
29762306a36Sopenharmony_ci	if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
29862306a36Sopenharmony_ci		ret = IRQ_WAKE_THREAD;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	return ret;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic irqreturn_t bdw_irq_thread(int irq, void *context)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	struct snd_sof_dev *sdev = context;
30662306a36Sopenharmony_ci	u32 ipcx, ipcd, imrx;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	imrx = snd_sof_dsp_read64(sdev, BDW_DSP_BAR, SHIM_IMRX);
30962306a36Sopenharmony_ci	ipcx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	/* reply message from DSP */
31262306a36Sopenharmony_ci	if (ipcx & SHIM_IPCX_DONE &&
31362306a36Sopenharmony_ci	    !(imrx & SHIM_IMRX_DONE)) {
31462306a36Sopenharmony_ci		/* Mask Done interrupt before return */
31562306a36Sopenharmony_ci		snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
31662306a36Sopenharmony_ci						 SHIM_IMRX, SHIM_IMRX_DONE,
31762306a36Sopenharmony_ci						 SHIM_IMRX_DONE);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		spin_lock_irq(&sdev->ipc_lock);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci		/*
32262306a36Sopenharmony_ci		 * handle immediate reply from DSP core. If the msg is
32362306a36Sopenharmony_ci		 * found, set done bit in cmd_done which is called at the
32462306a36Sopenharmony_ci		 * end of message processing function, else set it here
32562306a36Sopenharmony_ci		 * because the done bit can't be set in cmd_done function
32662306a36Sopenharmony_ci		 * which is triggered by msg
32762306a36Sopenharmony_ci		 */
32862306a36Sopenharmony_ci		snd_sof_ipc_process_reply(sdev, ipcx);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci		bdw_dsp_done(sdev);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci		spin_unlock_irq(&sdev->ipc_lock);
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	/* new message from DSP */
33862306a36Sopenharmony_ci	if (ipcd & SHIM_IPCD_BUSY &&
33962306a36Sopenharmony_ci	    !(imrx & SHIM_IMRX_BUSY)) {
34062306a36Sopenharmony_ci		/* Mask Busy interrupt before return */
34162306a36Sopenharmony_ci		snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
34262306a36Sopenharmony_ci						 SHIM_IMRX, SHIM_IMRX_BUSY,
34362306a36Sopenharmony_ci						 SHIM_IMRX_BUSY);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		/* Handle messages from DSP Core */
34662306a36Sopenharmony_ci		if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
34762306a36Sopenharmony_ci			snd_sof_dsp_panic(sdev, BDW_PANIC_OFFSET(ipcx) + MBOX_OFFSET,
34862306a36Sopenharmony_ci					  true);
34962306a36Sopenharmony_ci		} else {
35062306a36Sopenharmony_ci			snd_sof_ipc_msgs_rx(sdev);
35162306a36Sopenharmony_ci		}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci		bdw_host_done(sdev);
35462306a36Sopenharmony_ci	}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	return IRQ_HANDLED;
35762306a36Sopenharmony_ci}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci/*
36062306a36Sopenharmony_ci * IPC Mailbox IO
36162306a36Sopenharmony_ci */
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic int bdw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	/* send the message */
36662306a36Sopenharmony_ci	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
36762306a36Sopenharmony_ci			  msg->msg_size);
36862306a36Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, SHIM_IPCX_BUSY);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	return 0;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int bdw_get_mailbox_offset(struct snd_sof_dev *sdev)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	return MBOX_OFFSET;
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_cistatic int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id)
37962306a36Sopenharmony_ci{
38062306a36Sopenharmony_ci	return MBOX_OFFSET;
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_cistatic void bdw_host_done(struct snd_sof_dev *sdev)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	/* clear BUSY bit and set DONE bit - accept new messages */
38662306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD,
38762306a36Sopenharmony_ci					 SHIM_IPCD_BUSY | SHIM_IPCD_DONE,
38862306a36Sopenharmony_ci					 SHIM_IPCD_DONE);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	/* unmask busy interrupt */
39162306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
39262306a36Sopenharmony_ci					 SHIM_IMRX_BUSY, 0);
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cistatic void bdw_dsp_done(struct snd_sof_dev *sdev)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	/* clear DONE bit - tell DSP we have completed */
39862306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX,
39962306a36Sopenharmony_ci					 SHIM_IPCX_DONE, 0);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	/* unmask Done interrupt */
40262306a36Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
40362306a36Sopenharmony_ci					 SHIM_IMRX_DONE, 0);
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci/*
40762306a36Sopenharmony_ci * Probe and remove.
40862306a36Sopenharmony_ci */
40962306a36Sopenharmony_cistatic int bdw_probe(struct snd_sof_dev *sdev)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	struct snd_sof_pdata *pdata = sdev->pdata;
41262306a36Sopenharmony_ci	const struct sof_dev_desc *desc = pdata->desc;
41362306a36Sopenharmony_ci	struct platform_device *pdev =
41462306a36Sopenharmony_ci		container_of(sdev->dev, struct platform_device, dev);
41562306a36Sopenharmony_ci	const struct sof_intel_dsp_desc *chip;
41662306a36Sopenharmony_ci	struct resource *mmio;
41762306a36Sopenharmony_ci	u32 base, size;
41862306a36Sopenharmony_ci	int ret;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	chip = get_chip_info(sdev->pdata);
42162306a36Sopenharmony_ci	if (!chip) {
42262306a36Sopenharmony_ci		dev_err(sdev->dev, "error: no such device supported\n");
42362306a36Sopenharmony_ci		return -EIO;
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	sdev->num_cores = chip->cores_num;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	/* LPE base */
42962306a36Sopenharmony_ci	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
43062306a36Sopenharmony_ci				     desc->resindex_lpe_base);
43162306a36Sopenharmony_ci	if (mmio) {
43262306a36Sopenharmony_ci		base = mmio->start;
43362306a36Sopenharmony_ci		size = resource_size(mmio);
43462306a36Sopenharmony_ci	} else {
43562306a36Sopenharmony_ci		dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
43662306a36Sopenharmony_ci			desc->resindex_lpe_base);
43762306a36Sopenharmony_ci		return -EINVAL;
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
44162306a36Sopenharmony_ci	sdev->bar[BDW_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
44262306a36Sopenharmony_ci	if (!sdev->bar[BDW_DSP_BAR]) {
44362306a36Sopenharmony_ci		dev_err(sdev->dev,
44462306a36Sopenharmony_ci			"error: failed to ioremap LPE base 0x%x size 0x%x\n",
44562306a36Sopenharmony_ci			base, size);
44662306a36Sopenharmony_ci		return -ENODEV;
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci	dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BDW_DSP_BAR]);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	/* TODO: add offsets */
45162306a36Sopenharmony_ci	sdev->mmio_bar = BDW_DSP_BAR;
45262306a36Sopenharmony_ci	sdev->mailbox_bar = BDW_DSP_BAR;
45362306a36Sopenharmony_ci	sdev->dsp_oops_offset = MBOX_OFFSET;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* PCI base */
45662306a36Sopenharmony_ci	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
45762306a36Sopenharmony_ci				     desc->resindex_pcicfg_base);
45862306a36Sopenharmony_ci	if (mmio) {
45962306a36Sopenharmony_ci		base = mmio->start;
46062306a36Sopenharmony_ci		size = resource_size(mmio);
46162306a36Sopenharmony_ci	} else {
46262306a36Sopenharmony_ci		dev_err(sdev->dev, "error: failed to get PCI base at idx %d\n",
46362306a36Sopenharmony_ci			desc->resindex_pcicfg_base);
46462306a36Sopenharmony_ci		return -ENODEV;
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	dev_dbg(sdev->dev, "PCI base at 0x%x size 0x%x", base, size);
46862306a36Sopenharmony_ci	sdev->bar[BDW_PCI_BAR] = devm_ioremap(sdev->dev, base, size);
46962306a36Sopenharmony_ci	if (!sdev->bar[BDW_PCI_BAR]) {
47062306a36Sopenharmony_ci		dev_err(sdev->dev,
47162306a36Sopenharmony_ci			"error: failed to ioremap PCI base 0x%x size 0x%x\n",
47262306a36Sopenharmony_ci			base, size);
47362306a36Sopenharmony_ci		return -ENODEV;
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci	dev_dbg(sdev->dev, "PCI VADDR %p\n", sdev->bar[BDW_PCI_BAR]);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	/* register our IRQ */
47862306a36Sopenharmony_ci	sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
47962306a36Sopenharmony_ci	if (sdev->ipc_irq < 0)
48062306a36Sopenharmony_ci		return sdev->ipc_irq;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
48362306a36Sopenharmony_ci	ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
48462306a36Sopenharmony_ci					bdw_irq_handler, bdw_irq_thread,
48562306a36Sopenharmony_ci					IRQF_SHARED, "AudioDSP", sdev);
48662306a36Sopenharmony_ci	if (ret < 0) {
48762306a36Sopenharmony_ci		dev_err(sdev->dev, "error: failed to register IRQ %d\n",
48862306a36Sopenharmony_ci			sdev->ipc_irq);
48962306a36Sopenharmony_ci		return ret;
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	/* enable the DSP SHIM */
49362306a36Sopenharmony_ci	ret = bdw_set_dsp_D0(sdev);
49462306a36Sopenharmony_ci	if (ret < 0) {
49562306a36Sopenharmony_ci		dev_err(sdev->dev, "error: failed to set DSP D0\n");
49662306a36Sopenharmony_ci		return ret;
49762306a36Sopenharmony_ci	}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	/* DSP DMA can only access low 31 bits of host memory */
50062306a36Sopenharmony_ci	ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
50162306a36Sopenharmony_ci	if (ret < 0) {
50262306a36Sopenharmony_ci		dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
50362306a36Sopenharmony_ci		return ret;
50462306a36Sopenharmony_ci	}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	/* set default mailbox offset for FW ready message */
50762306a36Sopenharmony_ci	sdev->dsp_box.offset = MBOX_OFFSET;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	return ret;
51062306a36Sopenharmony_ci}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cistatic struct snd_soc_acpi_mach *bdw_machine_select(struct snd_sof_dev *sdev)
51362306a36Sopenharmony_ci{
51462306a36Sopenharmony_ci	struct snd_sof_pdata *sof_pdata = sdev->pdata;
51562306a36Sopenharmony_ci	const struct sof_dev_desc *desc = sof_pdata->desc;
51662306a36Sopenharmony_ci	struct snd_soc_acpi_mach *mach;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	mach = snd_soc_acpi_find_machine(desc->machines);
51962306a36Sopenharmony_ci	if (!mach) {
52062306a36Sopenharmony_ci		dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
52162306a36Sopenharmony_ci		return NULL;
52262306a36Sopenharmony_ci	}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	sof_pdata->tplg_filename = mach->sof_tplg_filename;
52562306a36Sopenharmony_ci	mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	return mach;
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_cistatic void bdw_set_mach_params(struct snd_soc_acpi_mach *mach,
53162306a36Sopenharmony_ci				struct snd_sof_dev *sdev)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	struct snd_sof_pdata *pdata = sdev->pdata;
53462306a36Sopenharmony_ci	const struct sof_dev_desc *desc = pdata->desc;
53562306a36Sopenharmony_ci	struct snd_soc_acpi_mach_params *mach_params;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	mach_params = &mach->mach_params;
53862306a36Sopenharmony_ci	mach_params->platform = dev_name(sdev->dev);
53962306a36Sopenharmony_ci	mach_params->num_dai_drivers = desc->ops->num_drv;
54062306a36Sopenharmony_ci	mach_params->dai_drivers = desc->ops->drv;
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci/* Broadwell DAIs */
54462306a36Sopenharmony_cistatic struct snd_soc_dai_driver bdw_dai[] = {
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	.name = "ssp0-port",
54762306a36Sopenharmony_ci	.playback = {
54862306a36Sopenharmony_ci		.channels_min = 1,
54962306a36Sopenharmony_ci		.channels_max = 8,
55062306a36Sopenharmony_ci	},
55162306a36Sopenharmony_ci	.capture = {
55262306a36Sopenharmony_ci		.channels_min = 1,
55362306a36Sopenharmony_ci		.channels_max = 8,
55462306a36Sopenharmony_ci	},
55562306a36Sopenharmony_ci},
55662306a36Sopenharmony_ci{
55762306a36Sopenharmony_ci	.name = "ssp1-port",
55862306a36Sopenharmony_ci	.playback = {
55962306a36Sopenharmony_ci		.channels_min = 1,
56062306a36Sopenharmony_ci		.channels_max = 8,
56162306a36Sopenharmony_ci	},
56262306a36Sopenharmony_ci	.capture = {
56362306a36Sopenharmony_ci		.channels_min = 1,
56462306a36Sopenharmony_ci		.channels_max = 8,
56562306a36Sopenharmony_ci	},
56662306a36Sopenharmony_ci},
56762306a36Sopenharmony_ci};
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci/* broadwell ops */
57062306a36Sopenharmony_cistatic struct snd_sof_dsp_ops sof_bdw_ops = {
57162306a36Sopenharmony_ci	/*Device init */
57262306a36Sopenharmony_ci	.probe          = bdw_probe,
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	/* DSP Core Control */
57562306a36Sopenharmony_ci	.run            = bdw_run,
57662306a36Sopenharmony_ci	.reset          = bdw_reset,
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	/* Register IO uses direct mmio */
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	/* Block IO */
58162306a36Sopenharmony_ci	.block_read	= sof_block_read,
58262306a36Sopenharmony_ci	.block_write	= sof_block_write,
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	/* Mailbox IO */
58562306a36Sopenharmony_ci	.mailbox_read	= sof_mailbox_read,
58662306a36Sopenharmony_ci	.mailbox_write	= sof_mailbox_write,
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	/* ipc */
58962306a36Sopenharmony_ci	.send_msg	= bdw_send_msg,
59062306a36Sopenharmony_ci	.get_mailbox_offset = bdw_get_mailbox_offset,
59162306a36Sopenharmony_ci	.get_window_offset = bdw_get_window_offset,
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	.ipc_msg_data	= sof_ipc_msg_data,
59462306a36Sopenharmony_ci	.set_stream_data_offset = sof_set_stream_data_offset,
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	/* machine driver */
59762306a36Sopenharmony_ci	.machine_select = bdw_machine_select,
59862306a36Sopenharmony_ci	.machine_register = sof_machine_register,
59962306a36Sopenharmony_ci	.machine_unregister = sof_machine_unregister,
60062306a36Sopenharmony_ci	.set_mach_params = bdw_set_mach_params,
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	/* debug */
60362306a36Sopenharmony_ci	.debug_map  = bdw_debugfs,
60462306a36Sopenharmony_ci	.debug_map_count    = ARRAY_SIZE(bdw_debugfs),
60562306a36Sopenharmony_ci	.dbg_dump   = bdw_dump,
60662306a36Sopenharmony_ci	.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	/* stream callbacks */
60962306a36Sopenharmony_ci	.pcm_open	= sof_stream_pcm_open,
61062306a36Sopenharmony_ci	.pcm_close	= sof_stream_pcm_close,
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	/*Firmware loading */
61362306a36Sopenharmony_ci	.load_firmware	= snd_sof_load_firmware_memcpy,
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	/* DAI drivers */
61662306a36Sopenharmony_ci	.drv = bdw_dai,
61762306a36Sopenharmony_ci	.num_drv = ARRAY_SIZE(bdw_dai),
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	/* ALSA HW info flags */
62062306a36Sopenharmony_ci	.hw_info =	SNDRV_PCM_INFO_MMAP |
62162306a36Sopenharmony_ci			SNDRV_PCM_INFO_MMAP_VALID |
62262306a36Sopenharmony_ci			SNDRV_PCM_INFO_INTERLEAVED |
62362306a36Sopenharmony_ci			SNDRV_PCM_INFO_PAUSE |
62462306a36Sopenharmony_ci			SNDRV_PCM_INFO_BATCH,
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	.dsp_arch_ops = &sof_xtensa_arch_ops,
62762306a36Sopenharmony_ci};
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_cistatic const struct sof_intel_dsp_desc bdw_chip_info = {
63062306a36Sopenharmony_ci	.cores_num = 1,
63162306a36Sopenharmony_ci	.host_managed_cores_mask = 1,
63262306a36Sopenharmony_ci	.hw_ip_version = SOF_INTEL_BROADWELL,
63362306a36Sopenharmony_ci};
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_cistatic const struct sof_dev_desc sof_acpi_broadwell_desc = {
63662306a36Sopenharmony_ci	.machines = snd_soc_acpi_intel_broadwell_machines,
63762306a36Sopenharmony_ci	.resindex_lpe_base = 0,
63862306a36Sopenharmony_ci	.resindex_pcicfg_base = 1,
63962306a36Sopenharmony_ci	.resindex_imr_base = -1,
64062306a36Sopenharmony_ci	.irqindex_host_ipc = 0,
64162306a36Sopenharmony_ci	.chip_info = &bdw_chip_info,
64262306a36Sopenharmony_ci	.ipc_supported_mask = BIT(SOF_IPC),
64362306a36Sopenharmony_ci	.ipc_default = SOF_IPC,
64462306a36Sopenharmony_ci	.default_fw_path = {
64562306a36Sopenharmony_ci		[SOF_IPC] = "intel/sof",
64662306a36Sopenharmony_ci	},
64762306a36Sopenharmony_ci	.default_tplg_path = {
64862306a36Sopenharmony_ci		[SOF_IPC] = "intel/sof-tplg",
64962306a36Sopenharmony_ci	},
65062306a36Sopenharmony_ci	.default_fw_filename = {
65162306a36Sopenharmony_ci		[SOF_IPC] = "sof-bdw.ri",
65262306a36Sopenharmony_ci	},
65362306a36Sopenharmony_ci	.nocodec_tplg_filename = "sof-bdw-nocodec.tplg",
65462306a36Sopenharmony_ci	.ops = &sof_bdw_ops,
65562306a36Sopenharmony_ci};
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_cistatic const struct acpi_device_id sof_broadwell_match[] = {
65862306a36Sopenharmony_ci	{ "INT3438", (unsigned long)&sof_acpi_broadwell_desc },
65962306a36Sopenharmony_ci	{ }
66062306a36Sopenharmony_ci};
66162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, sof_broadwell_match);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_cistatic int sof_broadwell_probe(struct platform_device *pdev)
66462306a36Sopenharmony_ci{
66562306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
66662306a36Sopenharmony_ci	const struct acpi_device_id *id;
66762306a36Sopenharmony_ci	const struct sof_dev_desc *desc;
66862306a36Sopenharmony_ci	int ret;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	id = acpi_match_device(dev->driver->acpi_match_table, dev);
67162306a36Sopenharmony_ci	if (!id)
67262306a36Sopenharmony_ci		return -ENODEV;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	ret = snd_intel_acpi_dsp_driver_probe(dev, id->id);
67562306a36Sopenharmony_ci	if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SOF) {
67662306a36Sopenharmony_ci		dev_dbg(dev, "SOF ACPI driver not selected, aborting probe\n");
67762306a36Sopenharmony_ci		return -ENODEV;
67862306a36Sopenharmony_ci	}
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	desc = (const struct sof_dev_desc *)id->driver_data;
68162306a36Sopenharmony_ci	return sof_acpi_probe(pdev, desc);
68262306a36Sopenharmony_ci}
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci/* acpi_driver definition */
68562306a36Sopenharmony_cistatic struct platform_driver snd_sof_acpi_intel_bdw_driver = {
68662306a36Sopenharmony_ci	.probe = sof_broadwell_probe,
68762306a36Sopenharmony_ci	.remove = sof_acpi_remove,
68862306a36Sopenharmony_ci	.driver = {
68962306a36Sopenharmony_ci		.name = "sof-audio-acpi-intel-bdw",
69062306a36Sopenharmony_ci		.pm = &sof_acpi_pm,
69162306a36Sopenharmony_ci		.acpi_match_table = sof_broadwell_match,
69262306a36Sopenharmony_ci	},
69362306a36Sopenharmony_ci};
69462306a36Sopenharmony_cimodule_platform_driver(snd_sof_acpi_intel_bdw_driver);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
69762306a36Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
69862306a36Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
69962306a36Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_ACPI_DEV);
700