xref: /openbmc/linux/sound/soc/sof/intel/cnl.c (revision c24b1b7279398c9140a8130b4c20db0c06d5dfc4)
127302052SLiam Girdwood // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
227302052SLiam Girdwood //
327302052SLiam Girdwood // This file is provided under a dual BSD/GPLv2 license.  When using or
427302052SLiam Girdwood // redistributing this file, you may do so under either license.
527302052SLiam Girdwood //
627302052SLiam Girdwood // Copyright(c) 2018 Intel Corporation. All rights reserved.
727302052SLiam Girdwood //
827302052SLiam Girdwood // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
927302052SLiam Girdwood //	    Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1027302052SLiam Girdwood //	    Rander Wang <rander.wang@intel.com>
1127302052SLiam Girdwood //          Keyon Jie <yang.jie@linux.intel.com>
1227302052SLiam Girdwood //
1327302052SLiam Girdwood 
1427302052SLiam Girdwood /*
1527302052SLiam Girdwood  * Hardware interface for audio DSP on Cannonlake.
1627302052SLiam Girdwood  */
1727302052SLiam Girdwood 
1827302052SLiam Girdwood #include "../ops.h"
1927302052SLiam Girdwood #include "hda.h"
2027302052SLiam Girdwood 
2127302052SLiam Girdwood static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
2227302052SLiam Girdwood 	{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
2327302052SLiam Girdwood 	{"pp", HDA_DSP_PP_BAR,  0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
2427302052SLiam Girdwood 	{"dsp", HDA_DSP_BAR,  0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
2527302052SLiam Girdwood };
2627302052SLiam Girdwood 
2727302052SLiam Girdwood static void cnl_ipc_host_done(struct snd_sof_dev *sdev);
2827302052SLiam Girdwood static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev);
2927302052SLiam Girdwood 
3027302052SLiam Girdwood static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
3127302052SLiam Girdwood {
3227302052SLiam Girdwood 	struct snd_sof_dev *sdev = context;
3327302052SLiam Girdwood 	u32 hipci;
3427302052SLiam Girdwood 	u32 hipcctl;
3527302052SLiam Girdwood 	u32 hipcida;
3627302052SLiam Girdwood 	u32 hipctdr;
3727302052SLiam Girdwood 	u32 hipctdd;
3827302052SLiam Girdwood 	u32 msg;
3927302052SLiam Girdwood 	u32 msg_ext;
4027302052SLiam Girdwood 	irqreturn_t ret = IRQ_NONE;
4127302052SLiam Girdwood 
4227302052SLiam Girdwood 	hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
4327302052SLiam Girdwood 	hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL);
4427302052SLiam Girdwood 	hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
45*c24b1b72SPierre-Louis Bossart 	hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD);
46*c24b1b72SPierre-Louis Bossart 	hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR);
4727302052SLiam Girdwood 
4827302052SLiam Girdwood 	/* reenable IPC interrupt */
4927302052SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
5027302052SLiam Girdwood 				HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC);
5127302052SLiam Girdwood 
5227302052SLiam Girdwood 	/* reply message from DSP */
5327302052SLiam Girdwood 	if (hipcida & CNL_DSP_REG_HIPCIDA_DONE &&
5427302052SLiam Girdwood 	    hipcctl & CNL_DSP_REG_HIPCCTL_DONE) {
5527302052SLiam Girdwood 		msg_ext = hipci & CNL_DSP_REG_HIPCIDR_MSG_MASK;
5627302052SLiam Girdwood 		msg = hipcida & CNL_DSP_REG_HIPCIDA_MSG_MASK;
5727302052SLiam Girdwood 
5827302052SLiam Girdwood 		dev_vdbg(sdev->dev,
5927302052SLiam Girdwood 			 "ipc: firmware response, msg:0x%x, msg_ext:0x%x\n",
6027302052SLiam Girdwood 			 msg, msg_ext);
6127302052SLiam Girdwood 
6227302052SLiam Girdwood 		/* mask Done interrupt */
6327302052SLiam Girdwood 		snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
6427302052SLiam Girdwood 					CNL_DSP_REG_HIPCCTL,
6527302052SLiam Girdwood 					CNL_DSP_REG_HIPCCTL_DONE, 0);
6627302052SLiam Girdwood 
671183e9a6SGuennadi Liakhovetski 		spin_lock_irq(&sdev->ipc_lock);
681183e9a6SGuennadi Liakhovetski 
6927302052SLiam Girdwood 		/* handle immediate reply from DSP core */
7027302052SLiam Girdwood 		hda_dsp_ipc_get_reply(sdev);
7127302052SLiam Girdwood 		snd_sof_ipc_reply(sdev, msg);
7227302052SLiam Girdwood 
7327302052SLiam Girdwood 		if (sdev->code_loading)	{
7427302052SLiam Girdwood 			sdev->code_loading = 0;
7527302052SLiam Girdwood 			wake_up(&sdev->waitq);
7627302052SLiam Girdwood 		}
7727302052SLiam Girdwood 
7827302052SLiam Girdwood 		cnl_ipc_dsp_done(sdev);
7927302052SLiam Girdwood 
801183e9a6SGuennadi Liakhovetski 		spin_unlock_irq(&sdev->ipc_lock);
811183e9a6SGuennadi Liakhovetski 
8227302052SLiam Girdwood 		ret = IRQ_HANDLED;
8327302052SLiam Girdwood 	}
8427302052SLiam Girdwood 
8527302052SLiam Girdwood 	/* new message from DSP */
8627302052SLiam Girdwood 	if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
8727302052SLiam Girdwood 		msg = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
8827302052SLiam Girdwood 		msg_ext = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
8927302052SLiam Girdwood 
9027302052SLiam Girdwood 		dev_vdbg(sdev->dev,
9127302052SLiam Girdwood 			 "ipc: firmware initiated, msg:0x%x, msg_ext:0x%x\n",
9227302052SLiam Girdwood 			 msg, msg_ext);
9327302052SLiam Girdwood 
9427302052SLiam Girdwood 		/* handle messages from DSP */
9527302052SLiam Girdwood 		if ((hipctdr & SOF_IPC_PANIC_MAGIC_MASK) ==
9627302052SLiam Girdwood 		   SOF_IPC_PANIC_MAGIC) {
9727302052SLiam Girdwood 			snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext));
9827302052SLiam Girdwood 		} else {
9927302052SLiam Girdwood 			snd_sof_ipc_msgs_rx(sdev);
10027302052SLiam Girdwood 		}
10127302052SLiam Girdwood 
10227302052SLiam Girdwood 		/*
10327302052SLiam Girdwood 		 * clear busy interrupt to tell dsp controller this
10427302052SLiam Girdwood 		 * interrupt has been accepted, not trigger it again
10527302052SLiam Girdwood 		 */
10627302052SLiam Girdwood 		snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
10727302052SLiam Girdwood 					       CNL_DSP_REG_HIPCTDR,
10827302052SLiam Girdwood 					       CNL_DSP_REG_HIPCTDR_BUSY,
10927302052SLiam Girdwood 					       CNL_DSP_REG_HIPCTDR_BUSY);
11027302052SLiam Girdwood 
11127302052SLiam Girdwood 		cnl_ipc_host_done(sdev);
11227302052SLiam Girdwood 
11327302052SLiam Girdwood 		ret = IRQ_HANDLED;
11427302052SLiam Girdwood 	}
11527302052SLiam Girdwood 
11627302052SLiam Girdwood 	return ret;
11727302052SLiam Girdwood }
11827302052SLiam Girdwood 
11927302052SLiam Girdwood static void cnl_ipc_host_done(struct snd_sof_dev *sdev)
12027302052SLiam Girdwood {
12127302052SLiam Girdwood 	/*
12227302052SLiam Girdwood 	 * set done bit to ack dsp the msg has been
12327302052SLiam Girdwood 	 * processed and send reply msg to dsp
12427302052SLiam Girdwood 	 */
12527302052SLiam Girdwood 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
12627302052SLiam Girdwood 				       CNL_DSP_REG_HIPCTDA,
12727302052SLiam Girdwood 				       CNL_DSP_REG_HIPCTDA_DONE,
12827302052SLiam Girdwood 				       CNL_DSP_REG_HIPCTDA_DONE);
12927302052SLiam Girdwood }
13027302052SLiam Girdwood 
13127302052SLiam Girdwood static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev)
13227302052SLiam Girdwood {
13327302052SLiam Girdwood 	/*
13427302052SLiam Girdwood 	 * set DONE bit - tell DSP we have received the reply msg
13527302052SLiam Girdwood 	 * from DSP, and processed it, don't send more reply to host
13627302052SLiam Girdwood 	 */
13727302052SLiam Girdwood 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
13827302052SLiam Girdwood 				       CNL_DSP_REG_HIPCIDA,
13927302052SLiam Girdwood 				       CNL_DSP_REG_HIPCIDA_DONE,
14027302052SLiam Girdwood 				       CNL_DSP_REG_HIPCIDA_DONE);
14127302052SLiam Girdwood 
14227302052SLiam Girdwood 	/* unmask Done interrupt */
14327302052SLiam Girdwood 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
14427302052SLiam Girdwood 				CNL_DSP_REG_HIPCCTL,
14527302052SLiam Girdwood 				CNL_DSP_REG_HIPCCTL_DONE,
14627302052SLiam Girdwood 				CNL_DSP_REG_HIPCCTL_DONE);
14727302052SLiam Girdwood }
14827302052SLiam Girdwood 
14927302052SLiam Girdwood static int cnl_ipc_send_msg(struct snd_sof_dev *sdev,
15027302052SLiam Girdwood 			    struct snd_sof_ipc_msg *msg)
15127302052SLiam Girdwood {
15227302052SLiam Girdwood 	/* send the message */
15327302052SLiam Girdwood 	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
15427302052SLiam Girdwood 			  msg->msg_size);
15527302052SLiam Girdwood 	snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
1566fbbc18eSDaniel Baluta 			  CNL_DSP_REG_HIPCIDR_BUSY);
15727302052SLiam Girdwood 
15827302052SLiam Girdwood 	return 0;
15927302052SLiam Girdwood }
16027302052SLiam Girdwood 
161dc20e5f3SPan Xiuli static void cnl_ipc_dump(struct snd_sof_dev *sdev)
162dc20e5f3SPan Xiuli {
163dc20e5f3SPan Xiuli 	u32 hipcctl;
164dc20e5f3SPan Xiuli 	u32 hipcida;
165dc20e5f3SPan Xiuli 	u32 hipctdr;
166dc20e5f3SPan Xiuli 
167dc20e5f3SPan Xiuli 	/* read IPC status */
168dc20e5f3SPan Xiuli 	hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
169dc20e5f3SPan Xiuli 	hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL);
170dc20e5f3SPan Xiuli 	hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
171dc20e5f3SPan Xiuli 
172dc20e5f3SPan Xiuli 	/* dump the IPC regs */
173dc20e5f3SPan Xiuli 	/* TODO: parse the raw msg */
174dc20e5f3SPan Xiuli 	dev_err(sdev->dev,
175dc20e5f3SPan Xiuli 		"error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
176dc20e5f3SPan Xiuli 		hipcida, hipctdr, hipcctl);
177dc20e5f3SPan Xiuli }
178dc20e5f3SPan Xiuli 
17927302052SLiam Girdwood /* cannonlake ops */
18027302052SLiam Girdwood const struct snd_sof_dsp_ops sof_cnl_ops = {
18127302052SLiam Girdwood 	/* probe and remove */
18227302052SLiam Girdwood 	.probe		= hda_dsp_probe,
18327302052SLiam Girdwood 	.remove		= hda_dsp_remove,
18427302052SLiam Girdwood 
18527302052SLiam Girdwood 	/* Register IO */
18627302052SLiam Girdwood 	.write		= sof_io_write,
18727302052SLiam Girdwood 	.read		= sof_io_read,
18827302052SLiam Girdwood 	.write64	= sof_io_write64,
18927302052SLiam Girdwood 	.read64		= sof_io_read64,
19027302052SLiam Girdwood 
19127302052SLiam Girdwood 	/* Block IO */
19227302052SLiam Girdwood 	.block_read	= sof_block_read,
19327302052SLiam Girdwood 	.block_write	= sof_block_write,
19427302052SLiam Girdwood 
19527302052SLiam Girdwood 	/* doorbell */
19627302052SLiam Girdwood 	.irq_handler	= hda_dsp_ipc_irq_handler,
19727302052SLiam Girdwood 	.irq_thread	= cnl_ipc_irq_thread,
19827302052SLiam Girdwood 
19927302052SLiam Girdwood 	/* ipc */
20027302052SLiam Girdwood 	.send_msg	= cnl_ipc_send_msg,
20127302052SLiam Girdwood 	.fw_ready	= hda_dsp_ipc_fw_ready,
20227302052SLiam Girdwood 
20327302052SLiam Girdwood 	.ipc_msg_data	= hda_ipc_msg_data,
20427302052SLiam Girdwood 	.ipc_pcm_params	= hda_ipc_pcm_params,
20527302052SLiam Girdwood 
20627302052SLiam Girdwood 	/* debug */
20727302052SLiam Girdwood 	.debug_map	= cnl_dsp_debugfs,
20827302052SLiam Girdwood 	.debug_map_count	= ARRAY_SIZE(cnl_dsp_debugfs),
20927302052SLiam Girdwood 	.dbg_dump	= hda_dsp_dump,
210dc20e5f3SPan Xiuli 	.ipc_dump	= cnl_ipc_dump,
21127302052SLiam Girdwood 
21227302052SLiam Girdwood 	/* stream callbacks */
21327302052SLiam Girdwood 	.pcm_open	= hda_dsp_pcm_open,
21427302052SLiam Girdwood 	.pcm_close	= hda_dsp_pcm_close,
21527302052SLiam Girdwood 	.pcm_hw_params	= hda_dsp_pcm_hw_params,
21627302052SLiam Girdwood 	.pcm_trigger	= hda_dsp_pcm_trigger,
217acd1c188SKeyon Jie 	.pcm_pointer	= hda_dsp_pcm_pointer,
21827302052SLiam Girdwood 
21927302052SLiam Girdwood 	/* firmware loading */
22027302052SLiam Girdwood 	.load_firmware = snd_sof_load_firmware_raw,
22127302052SLiam Girdwood 
22227302052SLiam Girdwood 	/* pre/post fw run */
22327302052SLiam Girdwood 	.pre_fw_run = hda_dsp_pre_fw_run,
22427302052SLiam Girdwood 	.post_fw_run = hda_dsp_post_fw_run,
22527302052SLiam Girdwood 
22627302052SLiam Girdwood 	/* dsp core power up/down */
22727302052SLiam Girdwood 	.core_power_up = hda_dsp_enable_core,
22827302052SLiam Girdwood 	.core_power_down = hda_dsp_core_reset_power_down,
22927302052SLiam Girdwood 
23027302052SLiam Girdwood 	/* firmware run */
23127302052SLiam Girdwood 	.run = hda_dsp_cl_boot_firmware,
23227302052SLiam Girdwood 
23327302052SLiam Girdwood 	/* trace callback */
23427302052SLiam Girdwood 	.trace_init = hda_dsp_trace_init,
23527302052SLiam Girdwood 	.trace_release = hda_dsp_trace_release,
23627302052SLiam Girdwood 	.trace_trigger = hda_dsp_trace_trigger,
23727302052SLiam Girdwood 
23827302052SLiam Girdwood 	/* DAI drivers */
23927302052SLiam Girdwood 	.drv		= skl_dai,
24027302052SLiam Girdwood 	.num_drv	= SOF_SKL_NUM_DAIS,
24127302052SLiam Girdwood 
24227302052SLiam Girdwood 	/* PM */
24327302052SLiam Girdwood 	.suspend		= hda_dsp_suspend,
24427302052SLiam Girdwood 	.resume			= hda_dsp_resume,
24527302052SLiam Girdwood 	.runtime_suspend	= hda_dsp_runtime_suspend,
24627302052SLiam Girdwood 	.runtime_resume		= hda_dsp_runtime_resume,
247ed3baacdSRanjani Sridharan 	.set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume,
24827302052SLiam Girdwood };
24927302052SLiam Girdwood EXPORT_SYMBOL(sof_cnl_ops);
25027302052SLiam Girdwood 
25127302052SLiam Girdwood const struct sof_intel_dsp_desc cnl_chip_info = {
25227302052SLiam Girdwood 	/* Cannonlake */
25327302052SLiam Girdwood 	.cores_num = 4,
25427302052SLiam Girdwood 	.init_core_mask = 1,
25527302052SLiam Girdwood 	.cores_mask = HDA_DSP_CORE_MASK(0) |
25627302052SLiam Girdwood 				HDA_DSP_CORE_MASK(1) |
25727302052SLiam Girdwood 				HDA_DSP_CORE_MASK(2) |
25827302052SLiam Girdwood 				HDA_DSP_CORE_MASK(3),
25927302052SLiam Girdwood 	.ipc_req = CNL_DSP_REG_HIPCIDR,
26027302052SLiam Girdwood 	.ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
26127302052SLiam Girdwood 	.ipc_ack = CNL_DSP_REG_HIPCIDA,
26227302052SLiam Girdwood 	.ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
26327302052SLiam Girdwood 	.ipc_ctl = CNL_DSP_REG_HIPCCTL,
26427302052SLiam Girdwood 	.rom_init_timeout	= 300,
265b095fe47SZhu Yingjiang 	.ssp_count = CNL_SSP_COUNT,
266b095fe47SZhu Yingjiang 	.ssp_base_offset = CNL_SSP_BASE_OFFSET,
26727302052SLiam Girdwood };
26827302052SLiam Girdwood EXPORT_SYMBOL(cnl_chip_info);
269630be964SZhu Yingjiang 
270630be964SZhu Yingjiang const struct sof_intel_dsp_desc icl_chip_info = {
271630be964SZhu Yingjiang 	/* Icelake */
272630be964SZhu Yingjiang 	.cores_num = 4,
273630be964SZhu Yingjiang 	.init_core_mask = 1,
274630be964SZhu Yingjiang 	.cores_mask = HDA_DSP_CORE_MASK(0) |
275630be964SZhu Yingjiang 				HDA_DSP_CORE_MASK(1) |
276630be964SZhu Yingjiang 				HDA_DSP_CORE_MASK(2) |
277630be964SZhu Yingjiang 				HDA_DSP_CORE_MASK(3),
278630be964SZhu Yingjiang 	.ipc_req = CNL_DSP_REG_HIPCIDR,
279630be964SZhu Yingjiang 	.ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
280630be964SZhu Yingjiang 	.ipc_ack = CNL_DSP_REG_HIPCIDA,
281630be964SZhu Yingjiang 	.ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
282630be964SZhu Yingjiang 	.ipc_ctl = CNL_DSP_REG_HIPCCTL,
283630be964SZhu Yingjiang 	.rom_init_timeout	= 300,
284630be964SZhu Yingjiang 	.ssp_count = ICL_SSP_COUNT,
285630be964SZhu Yingjiang 	.ssp_base_offset = CNL_SSP_BASE_OFFSET,
286630be964SZhu Yingjiang };
287630be964SZhu Yingjiang EXPORT_SYMBOL(icl_chip_info);
288