brintos

brintos / linux-shallow public Read only

0
0
Text · 18.5 KiB · 322ff11 Raw
701 lines · c
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 or4// redistributing this file, you may do so under either license.5//6// Copyright(c) 2018 Intel Corporation7//8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>9//10 11/*12 * Hardware interface for audio DSP on Broadwell13 */14 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>21#include "../ops.h"22#include "shim.h"23#include "../sof-acpi-dev.h"24#include "../sof-audio.h"25 26/* BARs */27#define BDW_DSP_BAR 028#define BDW_PCI_BAR 129 30/*31 * Debug32 */33 34/* DSP memories for BDW */35#define IRAM_OFFSET     0xA000036#define BDW_IRAM_SIZE       (10 * 32 * 1024)37#define DRAM_OFFSET     0x0000038#define BDW_DRAM_SIZE       (20 * 32 * 1024)39#define SHIM_OFFSET     0xFB00040#define SHIM_SIZE       0x10041#define MBOX_OFFSET     0x9E00042#define MBOX_SIZE       0x100043#define MBOX_DUMP_SIZE 0x3044#define EXCEPT_OFFSET	0x80045#define EXCEPT_MAX_HDR_SIZE	0x40046 47/* DSP peripherals */48#define DMAC0_OFFSET    0xFE00049#define DMAC1_OFFSET    0xFF00050#define DMAC_SIZE       0x42051#define SSP0_OFFSET     0xFC00052#define SSP1_OFFSET     0xFD00053#define SSP_SIZE	0x10054 55#define BDW_STACK_DUMP_SIZE	3256 57#define BDW_PANIC_OFFSET(x)	((x) & 0xFFFF)58 59static const struct snd_sof_debugfs_map bdw_debugfs[] = {60	{"dmac0", BDW_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,61	 SOF_DEBUGFS_ACCESS_ALWAYS},62	{"dmac1", BDW_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,63	 SOF_DEBUGFS_ACCESS_ALWAYS},64	{"ssp0", BDW_DSP_BAR, SSP0_OFFSET, SSP_SIZE,65	 SOF_DEBUGFS_ACCESS_ALWAYS},66	{"ssp1", BDW_DSP_BAR, SSP1_OFFSET, SSP_SIZE,67	 SOF_DEBUGFS_ACCESS_ALWAYS},68	{"iram", BDW_DSP_BAR, IRAM_OFFSET, BDW_IRAM_SIZE,69	 SOF_DEBUGFS_ACCESS_D0_ONLY},70	{"dram", BDW_DSP_BAR, DRAM_OFFSET, BDW_DRAM_SIZE,71	 SOF_DEBUGFS_ACCESS_D0_ONLY},72	{"shim", BDW_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,73	 SOF_DEBUGFS_ACCESS_ALWAYS},74};75 76static void bdw_host_done(struct snd_sof_dev *sdev);77static void bdw_dsp_done(struct snd_sof_dev *sdev);78 79/*80 * DSP Control.81 */82 83static int bdw_run(struct snd_sof_dev *sdev)84{85	/* set opportunistic mode on engine 0,1 for all channels */86	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,87				SHIM_HMDC_HDDA_E0_ALLCH |88				SHIM_HMDC_HDDA_E1_ALLCH, 0);89 90	/* set DSP to RUN */91	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,92					 SHIM_CSR_STALL, 0x0);93 94	/* return init core mask */95	return 1;96}97 98static int bdw_reset(struct snd_sof_dev *sdev)99{100	/* put DSP into reset and stall */101	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,102					 SHIM_CSR_RST | SHIM_CSR_STALL,103					 SHIM_CSR_RST | SHIM_CSR_STALL);104 105	/* keep in reset for 10ms */106	mdelay(10);107 108	/* take DSP out of reset and keep stalled for FW loading */109	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,110					 SHIM_CSR_RST | SHIM_CSR_STALL,111					 SHIM_CSR_STALL);112 113	return 0;114}115 116static int bdw_set_dsp_D0(struct snd_sof_dev *sdev)117{118	int tries = 10;119	u32 reg;120 121	/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */122	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,123					 PCI_VDRTCL2_DCLCGE |124					 PCI_VDRTCL2_DTCGE, 0);125 126	/* Disable D3PG (VDRTCTL0.D3PGD = 1) */127	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,128					 PCI_VDRTCL0_D3PGD, PCI_VDRTCL0_D3PGD);129 130	/* Set D0 state */131	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_PMCS,132					 PCI_PMCS_PS_MASK, 0);133 134	/* check that ADSP shim is enabled */135	while (tries--) {136		reg = readl(sdev->bar[BDW_PCI_BAR] + PCI_PMCS)137			& PCI_PMCS_PS_MASK;138		if (reg == 0)139			goto finish;140 141		msleep(20);142	}143 144	return -ENODEV;145 146finish:147	/*148	 * select SSP1 19.2MHz base clock, SSP clock 0,149	 * turn off Low Power Clock150	 */151	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,152					 SHIM_CSR_S1IOCS | SHIM_CSR_SBCS1 |153					 SHIM_CSR_LPCS, 0x0);154 155	/* stall DSP core, set clk to 192/96Mhz */156	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,157					 SHIM_CSR, SHIM_CSR_STALL |158					 SHIM_CSR_DCS_MASK,159					 SHIM_CSR_STALL |160					 SHIM_CSR_DCS(4));161 162	/* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */163	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CLKCTL,164					 SHIM_CLKCTL_MASK |165					 SHIM_CLKCTL_DCPLCG |166					 SHIM_CLKCTL_SCOE0,167					 SHIM_CLKCTL_MASK |168					 SHIM_CLKCTL_DCPLCG |169					 SHIM_CLKCTL_SCOE0);170 171	/* Stall and reset core, set CSR */172	bdw_reset(sdev);173 174	/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */175	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,176					 PCI_VDRTCL2_DCLCGE |177					 PCI_VDRTCL2_DTCGE,178					 PCI_VDRTCL2_DCLCGE |179					 PCI_VDRTCL2_DTCGE);180 181	usleep_range(50, 55);182 183	/* switch on audio PLL */184	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,185					 PCI_VDRTCL2_APLLSE_MASK, 0);186 187	/*188	 * set default power gating control, enable power gating control for189	 * all blocks. that is, can't be accessed, please enable each block190	 * before accessing.191	 */192	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,193					 0xfffffffC, 0x0);194 195	/* disable DMA finish function for SSP0 & SSP1 */196	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,  SHIM_CSR2,197					 SHIM_CSR2_SDFD_SSP1,198					 SHIM_CSR2_SDFD_SSP1);199 200	/* set on-demond mode on engine 0,1 for all channels */201	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,202				SHIM_HMDC_HDDA_E0_ALLCH |203				SHIM_HMDC_HDDA_E1_ALLCH,204				SHIM_HMDC_HDDA_E0_ALLCH |205				SHIM_HMDC_HDDA_E1_ALLCH);206 207	/* Enable Interrupt from both sides */208	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRX,209				(SHIM_IMRX_BUSY | SHIM_IMRX_DONE), 0x0);210	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRD,211				(SHIM_IMRD_DONE | SHIM_IMRD_BUSY |212				SHIM_IMRD_SSP0 | SHIM_IMRD_DMAC), 0x0);213 214	/* clear IPC registers */215	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, 0x0);216	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCD, 0x0);217	snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0x80, 0x6);218	snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0xe0, 0x300a);219 220	return 0;221}222 223static void bdw_get_registers(struct snd_sof_dev *sdev,224			      struct sof_ipc_dsp_oops_xtensa *xoops,225			      struct sof_ipc_panic_info *panic_info,226			      u32 *stack, size_t stack_words)227{228	u32 offset = sdev->dsp_oops_offset;229 230	/* first read registers */231	sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));232 233	/* note: variable AR register array is not read */234 235	/* then get panic info */236	if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {237		dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",238			xoops->arch_hdr.totalsize);239		return;240	}241	offset += xoops->arch_hdr.totalsize;242	sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));243 244	/* then get the stack */245	offset += sizeof(*panic_info);246	sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));247}248 249static void bdw_dump(struct snd_sof_dev *sdev, u32 flags)250{251	struct sof_ipc_dsp_oops_xtensa xoops;252	struct sof_ipc_panic_info panic_info;253	u32 stack[BDW_STACK_DUMP_SIZE];254	u32 status, panic, imrx, imrd;255 256	/* now try generic SOF status messages */257	status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);258	panic = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);259	bdw_get_registers(sdev, &xoops, &panic_info, stack,260			  BDW_STACK_DUMP_SIZE);261	sof_print_oops_and_stack(sdev, KERN_ERR, status, panic, &xoops,262				 &panic_info, stack, BDW_STACK_DUMP_SIZE);263 264	/* provide some context for firmware debug */265	imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX);266	imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD);267	dev_err(sdev->dev,268		"error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",269		(panic & SHIM_IPCX_BUSY) ? "yes" : "no",270		(panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);271	dev_err(sdev->dev,272		"error: mask host: pending %s complete %s raw 0x%8.8x\n",273		(imrx & SHIM_IMRX_BUSY) ? "yes" : "no",274		(imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);275	dev_err(sdev->dev,276		"error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",277		(status & SHIM_IPCD_BUSY) ? "yes" : "no",278		(status & SHIM_IPCD_DONE) ? "yes" : "no", status);279	dev_err(sdev->dev,280		"error: mask DSP: pending %s complete %s raw 0x%8.8x\n",281		(imrd & SHIM_IMRD_BUSY) ? "yes" : "no",282		(imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);283}284 285/*286 * IPC Doorbell IRQ handler and thread.287 */288 289static irqreturn_t bdw_irq_handler(int irq, void *context)290{291	struct snd_sof_dev *sdev = context;292	u32 isr;293	int ret = IRQ_NONE;294 295	/* Interrupt arrived, check src */296	isr = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_ISRX);297	if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))298		ret = IRQ_WAKE_THREAD;299 300	return ret;301}302 303static irqreturn_t bdw_irq_thread(int irq, void *context)304{305	struct snd_sof_dev *sdev = context;306	u32 ipcx, ipcd, imrx;307 308	imrx = snd_sof_dsp_read64(sdev, BDW_DSP_BAR, SHIM_IMRX);309	ipcx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);310 311	/* reply message from DSP */312	if (ipcx & SHIM_IPCX_DONE &&313	    !(imrx & SHIM_IMRX_DONE)) {314		/* Mask Done interrupt before return */315		snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,316						 SHIM_IMRX, SHIM_IMRX_DONE,317						 SHIM_IMRX_DONE);318 319		spin_lock_irq(&sdev->ipc_lock);320 321		/*322		 * handle immediate reply from DSP core. If the msg is323		 * found, set done bit in cmd_done which is called at the324		 * end of message processing function, else set it here325		 * because the done bit can't be set in cmd_done function326		 * which is triggered by msg327		 */328		snd_sof_ipc_process_reply(sdev, ipcx);329 330		bdw_dsp_done(sdev);331 332		spin_unlock_irq(&sdev->ipc_lock);333	}334 335	ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);336 337	/* new message from DSP */338	if (ipcd & SHIM_IPCD_BUSY &&339	    !(imrx & SHIM_IMRX_BUSY)) {340		/* Mask Busy interrupt before return */341		snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,342						 SHIM_IMRX, SHIM_IMRX_BUSY,343						 SHIM_IMRX_BUSY);344 345		/* Handle messages from DSP Core */346		if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {347			snd_sof_dsp_panic(sdev, BDW_PANIC_OFFSET(ipcx) + MBOX_OFFSET,348					  true);349		} else {350			snd_sof_ipc_msgs_rx(sdev);351		}352 353		bdw_host_done(sdev);354	}355 356	return IRQ_HANDLED;357}358 359/*360 * IPC Mailbox IO361 */362 363static int bdw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)364{365	/* send the message */366	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,367			  msg->msg_size);368	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, SHIM_IPCX_BUSY);369 370	return 0;371}372 373static int bdw_get_mailbox_offset(struct snd_sof_dev *sdev)374{375	return MBOX_OFFSET;376}377 378static int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id)379{380	return MBOX_OFFSET;381}382 383static void bdw_host_done(struct snd_sof_dev *sdev)384{385	/* clear BUSY bit and set DONE bit - accept new messages */386	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD,387					 SHIM_IPCD_BUSY | SHIM_IPCD_DONE,388					 SHIM_IPCD_DONE);389 390	/* unmask busy interrupt */391	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,392					 SHIM_IMRX_BUSY, 0);393}394 395static void bdw_dsp_done(struct snd_sof_dev *sdev)396{397	/* clear DONE bit - tell DSP we have completed */398	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX,399					 SHIM_IPCX_DONE, 0);400 401	/* unmask Done interrupt */402	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,403					 SHIM_IMRX_DONE, 0);404}405 406/*407 * Probe and remove.408 */409static int bdw_probe(struct snd_sof_dev *sdev)410{411	struct snd_sof_pdata *pdata = sdev->pdata;412	const struct sof_dev_desc *desc = pdata->desc;413	struct platform_device *pdev =414		container_of(sdev->dev, struct platform_device, dev);415	const struct sof_intel_dsp_desc *chip;416	struct resource *mmio;417	u32 base, size;418	int ret;419 420	chip = get_chip_info(sdev->pdata);421	if (!chip) {422		dev_err(sdev->dev, "error: no such device supported\n");423		return -EIO;424	}425 426	sdev->num_cores = chip->cores_num;427 428	/* LPE base */429	mmio = platform_get_resource(pdev, IORESOURCE_MEM,430				     desc->resindex_lpe_base);431	if (mmio) {432		base = mmio->start;433		size = resource_size(mmio);434	} else {435		dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",436			desc->resindex_lpe_base);437		return -EINVAL;438	}439 440	dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);441	sdev->bar[BDW_DSP_BAR] = devm_ioremap(sdev->dev, base, size);442	if (!sdev->bar[BDW_DSP_BAR]) {443		dev_err(sdev->dev,444			"error: failed to ioremap LPE base 0x%x size 0x%x\n",445			base, size);446		return -ENODEV;447	}448	dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BDW_DSP_BAR]);449 450	/* TODO: add offsets */451	sdev->mmio_bar = BDW_DSP_BAR;452	sdev->mailbox_bar = BDW_DSP_BAR;453	sdev->dsp_oops_offset = MBOX_OFFSET;454 455	/* PCI base */456	mmio = platform_get_resource(pdev, IORESOURCE_MEM,457				     desc->resindex_pcicfg_base);458	if (mmio) {459		base = mmio->start;460		size = resource_size(mmio);461	} else {462		dev_err(sdev->dev, "error: failed to get PCI base at idx %d\n",463			desc->resindex_pcicfg_base);464		return -ENODEV;465	}466 467	dev_dbg(sdev->dev, "PCI base at 0x%x size 0x%x", base, size);468	sdev->bar[BDW_PCI_BAR] = devm_ioremap(sdev->dev, base, size);469	if (!sdev->bar[BDW_PCI_BAR]) {470		dev_err(sdev->dev,471			"error: failed to ioremap PCI base 0x%x size 0x%x\n",472			base, size);473		return -ENODEV;474	}475	dev_dbg(sdev->dev, "PCI VADDR %p\n", sdev->bar[BDW_PCI_BAR]);476 477	/* register our IRQ */478	sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);479	if (sdev->ipc_irq < 0)480		return sdev->ipc_irq;481 482	dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);483	ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,484					bdw_irq_handler, bdw_irq_thread,485					IRQF_SHARED, "AudioDSP", sdev);486	if (ret < 0) {487		dev_err(sdev->dev, "error: failed to register IRQ %d\n",488			sdev->ipc_irq);489		return ret;490	}491 492	/* enable the DSP SHIM */493	ret = bdw_set_dsp_D0(sdev);494	if (ret < 0) {495		dev_err(sdev->dev, "error: failed to set DSP D0\n");496		return ret;497	}498 499	/* DSP DMA can only access low 31 bits of host memory */500	ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));501	if (ret < 0) {502		dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);503		return ret;504	}505 506	/* set default mailbox offset for FW ready message */507	sdev->dsp_box.offset = MBOX_OFFSET;508 509	return ret;510}511 512static struct snd_soc_acpi_mach *bdw_machine_select(struct snd_sof_dev *sdev)513{514	struct snd_sof_pdata *sof_pdata = sdev->pdata;515	const struct sof_dev_desc *desc = sof_pdata->desc;516	struct snd_soc_acpi_mach *mach;517 518	mach = snd_soc_acpi_find_machine(desc->machines);519	if (!mach) {520		dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");521		return NULL;522	}523 524	sof_pdata->tplg_filename = mach->sof_tplg_filename;525	mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;526 527	return mach;528}529 530static void bdw_set_mach_params(struct snd_soc_acpi_mach *mach,531				struct snd_sof_dev *sdev)532{533	struct snd_sof_pdata *pdata = sdev->pdata;534	const struct sof_dev_desc *desc = pdata->desc;535	struct snd_soc_acpi_mach_params *mach_params;536 537	mach_params = &mach->mach_params;538	mach_params->platform = dev_name(sdev->dev);539	mach_params->num_dai_drivers = desc->ops->num_drv;540	mach_params->dai_drivers = desc->ops->drv;541}542 543/* Broadwell DAIs */544static struct snd_soc_dai_driver bdw_dai[] = {545{546	.name = "ssp0-port",547	.playback = {548		.channels_min = 1,549		.channels_max = 8,550	},551	.capture = {552		.channels_min = 1,553		.channels_max = 8,554	},555},556{557	.name = "ssp1-port",558	.playback = {559		.channels_min = 1,560		.channels_max = 8,561	},562	.capture = {563		.channels_min = 1,564		.channels_max = 8,565	},566},567};568 569/* broadwell ops */570static const struct snd_sof_dsp_ops sof_bdw_ops = {571	/*Device init */572	.probe          = bdw_probe,573 574	/* DSP Core Control */575	.run            = bdw_run,576	.reset          = bdw_reset,577 578	/* Register IO uses direct mmio */579 580	/* Block IO */581	.block_read	= sof_block_read,582	.block_write	= sof_block_write,583 584	/* Mailbox IO */585	.mailbox_read	= sof_mailbox_read,586	.mailbox_write	= sof_mailbox_write,587 588	/* ipc */589	.send_msg	= bdw_send_msg,590	.get_mailbox_offset = bdw_get_mailbox_offset,591	.get_window_offset = bdw_get_window_offset,592 593	.ipc_msg_data	= sof_ipc_msg_data,594	.set_stream_data_offset = sof_set_stream_data_offset,595 596	/* machine driver */597	.machine_select = bdw_machine_select,598	.machine_register = sof_machine_register,599	.machine_unregister = sof_machine_unregister,600	.set_mach_params = bdw_set_mach_params,601 602	/* debug */603	.debug_map  = bdw_debugfs,604	.debug_map_count    = ARRAY_SIZE(bdw_debugfs),605	.dbg_dump   = bdw_dump,606	.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,607 608	/* stream callbacks */609	.pcm_open	= sof_stream_pcm_open,610	.pcm_close	= sof_stream_pcm_close,611 612	/*Firmware loading */613	.load_firmware	= snd_sof_load_firmware_memcpy,614 615	/* DAI drivers */616	.drv = bdw_dai,617	.num_drv = ARRAY_SIZE(bdw_dai),618 619	/* ALSA HW info flags */620	.hw_info =	SNDRV_PCM_INFO_MMAP |621			SNDRV_PCM_INFO_MMAP_VALID |622			SNDRV_PCM_INFO_INTERLEAVED |623			SNDRV_PCM_INFO_PAUSE |624			SNDRV_PCM_INFO_BATCH,625 626	.dsp_arch_ops = &sof_xtensa_arch_ops,627};628 629static const struct sof_intel_dsp_desc bdw_chip_info = {630	.cores_num = 1,631	.host_managed_cores_mask = 1,632	.hw_ip_version = SOF_INTEL_BROADWELL,633};634 635static const struct sof_dev_desc sof_acpi_broadwell_desc = {636	.machines = snd_soc_acpi_intel_broadwell_machines,637	.resindex_lpe_base = 0,638	.resindex_pcicfg_base = 1,639	.resindex_imr_base = -1,640	.irqindex_host_ipc = 0,641	.chip_info = &bdw_chip_info,642	.ipc_supported_mask = BIT(SOF_IPC_TYPE_3),643	.ipc_default = SOF_IPC_TYPE_3,644	.default_fw_path = {645		[SOF_IPC_TYPE_3] = "intel/sof",646	},647	.default_tplg_path = {648		[SOF_IPC_TYPE_3] = "intel/sof-tplg",649	},650	.default_fw_filename = {651		[SOF_IPC_TYPE_3] = "sof-bdw.ri",652	},653	.nocodec_tplg_filename = "sof-bdw-nocodec.tplg",654	.ops = &sof_bdw_ops,655};656 657static const struct acpi_device_id sof_broadwell_match[] = {658	{ "INT3438", (unsigned long)&sof_acpi_broadwell_desc },659	{ }660};661MODULE_DEVICE_TABLE(acpi, sof_broadwell_match);662 663static int sof_broadwell_probe(struct platform_device *pdev)664{665	struct device *dev = &pdev->dev;666	const struct acpi_device_id *id;667	const struct sof_dev_desc *desc;668	int ret;669 670	id = acpi_match_device(dev->driver->acpi_match_table, dev);671	if (!id)672		return -ENODEV;673 674	ret = snd_intel_acpi_dsp_driver_probe(dev, id->id);675	if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SOF) {676		dev_dbg(dev, "SOF ACPI driver not selected, aborting probe\n");677		return -ENODEV;678	}679 680	desc = (const struct sof_dev_desc *)id->driver_data;681	return sof_acpi_probe(pdev, desc);682}683 684/* acpi_driver definition */685static struct platform_driver snd_sof_acpi_intel_bdw_driver = {686	.probe = sof_broadwell_probe,687	.remove = sof_acpi_remove,688	.driver = {689		.name = "sof-audio-acpi-intel-bdw",690		.pm = &sof_acpi_pm,691		.acpi_match_table = sof_broadwell_match,692	},693};694module_platform_driver(snd_sof_acpi_intel_bdw_driver);695 696MODULE_LICENSE("Dual BSD/GPL");697MODULE_DESCRIPTION("SOF support for Broadwell platforms");698MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);699MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);700MODULE_IMPORT_NS(SND_SOC_SOF_ACPI_DEV);701