File Index
Files and directories
Sign in
FILE

lnl.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/sof/intel/lnl.c C
  1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2//
  3// Copyright(c) 2023 Intel Corporation
  4
  5/*
  6 * Hardware interface for audio DSP on LunarLake.
  7 */
  8
  9#include <linux/debugfs.h>
 10#include <linux/firmware.h>
 11#include <sound/hda_register.h>
 12#include <sound/sof/ipc4/header.h>
 13#include <trace/events/sof_intel.h>
 14#include "../ipc4-priv.h"
 15#include "../ops.h"
 16#include "hda.h"
 17#include "hda-ipc.h"
 18#include "../sof-audio.h"
 19#include "mtl.h"
 20#include "lnl.h"
 21#include <sound/hda-mlink.h>
 22
 23/* this helps allows the DSP to setup DMIC/SSP */
 24static int hdac_bus_offload_dmic_ssp(struct hdac_bus *bus, bool enable)
 25{
 26	int ret;
 27
 28	ret = hdac_bus_eml_enable_offload(bus, true,
 29					  AZX_REG_ML_LEPTR_ID_INTEL_SSP, enable);
 30	if (ret < 0)
 31		return ret;
 32
 33	ret = hdac_bus_eml_enable_offload(bus, true,
 34					  AZX_REG_ML_LEPTR_ID_INTEL_DMIC, enable);
 35	if (ret < 0)
 36		return ret;
 37
 38	return 0;
 39}
 40
 41static int lnl_hda_dsp_probe(struct snd_sof_dev *sdev)
 42{
 43	int ret;
 44
 45	ret = hda_dsp_probe(sdev);
 46	if (ret < 0)
 47		return ret;
 48
 49	return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
 50}
 51
 52static void lnl_hda_dsp_remove(struct snd_sof_dev *sdev)
 53{
 54	int ret;
 55
 56	ret = hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), false);
 57	if (ret < 0)
 58		dev_warn(sdev->dev,
 59			 "Failed to disable offload for DMIC/SSP: %d\n", ret);
 60
 61	hda_dsp_remove(sdev);
 62}
 63
 64static int lnl_hda_dsp_resume(struct snd_sof_dev *sdev)
 65{
 66	int ret;
 67
 68	ret = hda_dsp_resume(sdev);
 69	if (ret < 0)
 70		return ret;
 71
 72	return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
 73}
 74
 75static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
 76{
 77	int ret;
 78
 79	ret = hda_dsp_runtime_resume(sdev);
 80	if (ret < 0)
 81		return ret;
 82
 83	return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
 84}
 85
 86static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev)
 87{
 88	if (sdev->first_boot) {
 89		struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
 90
 91		/* Check if IMR boot is usable */
 92		if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) {
 93			hda->imrboot_supported = true;
 94			debugfs_create_bool("skip_imr_boot",
 95					    0644, sdev->debugfs_root,
 96					    &hda->skip_imr_boot);
 97		}
 98	}
 99
100	return 0;
101}
102
103int sof_lnl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops)
104{
105	int ret;
106
107	ret = sof_mtl_set_ops(sdev, dsp_ops);
108	if (ret)
109		return ret;
110
111	/* probe/remove */
112	if (!sdev->dspless_mode_selected) {
113		dsp_ops->probe = lnl_hda_dsp_probe;
114		dsp_ops->remove = lnl_hda_dsp_remove;
115	}
116
117	/* post fw run */
118	dsp_ops->post_fw_run = lnl_dsp_post_fw_run;
119
120	/* PM */
121	if (!sdev->dspless_mode_selected) {
122		dsp_ops->resume = lnl_hda_dsp_resume;
123		dsp_ops->runtime_resume = lnl_hda_dsp_runtime_resume;
124	}
125
126	return 0;
127}
128EXPORT_SYMBOL_NS(sof_lnl_set_ops, "SND_SOC_SOF_INTEL_LNL");
129
130/* Check if an SDW IRQ occurred */
131bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
132{
133	struct hdac_bus *bus = sof_to_bus(sdev);
134
135	return hdac_bus_eml_check_interrupt(bus, true,  AZX_REG_ML_LEPTR_ID_SDW);
136}
137EXPORT_SYMBOL_NS(lnl_dsp_check_sdw_irq, "SND_SOC_SOF_INTEL_LNL");
138
139int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
140{
141	mtl_disable_ipc_interrupts(sdev);
142	return mtl_enable_interrupts(sdev, false);
143}
144EXPORT_SYMBOL_NS(lnl_dsp_disable_interrupts, "SND_SOC_SOF_INTEL_LNL");
145
146bool lnl_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
147{
148	struct hdac_bus *bus = sof_to_bus(sdev);
149	u16 wake_sts;
150
151	/*
152	 * we need to use the global HDaudio WAKEEN/STS to be able to
153	 * detect wakes in low-power modes. The link-specific information
154	 * is handled in the process_wakeen() helper, this helper only
155	 * detects a SoundWire wake without identifying the link.
156	 */
157	wake_sts = snd_hdac_chip_readw(bus, STATESTS);
158
159	/* filter out the range of SDIs that can be set for SoundWire */
160	return wake_sts & GENMASK(SDW_MAX_DEVICES, SDW_INTEL_DEV_NUM_IDA_MIN);
161}
162EXPORT_SYMBOL_NS(lnl_sdw_check_wakeen_irq, "SND_SOC_SOF_INTEL_LNL");
163
164const struct sof_intel_dsp_desc lnl_chip_info = {
165	.cores_num = 5,
166	.init_core_mask = BIT(0),
167	.host_managed_cores_mask = BIT(0),
168	.ipc_req = MTL_DSP_REG_HFIPCXIDR,
169	.ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
170	.ipc_ack = MTL_DSP_REG_HFIPCXIDA,
171	.ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
172	.ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
173	.rom_status_reg = LNL_DSP_REG_HFDSC,
174	.rom_init_timeout = 300,
175	.ssp_count = MTL_SSP_COUNT,
176	.d0i3_offset = MTL_HDA_VS_D0I3C,
177	.read_sdw_lcount =  hda_sdw_check_lcount_ext,
178	.check_sdw_irq = lnl_dsp_check_sdw_irq,
179	.check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq,
180	.sdw_process_wakeen = hda_sdw_process_wakeen_common,
181	.check_ipc_irq = mtl_dsp_check_ipc_irq,
182	.cl_init = mtl_dsp_cl_init,
183	.power_down_dsp = mtl_power_down_dsp,
184	.disable_interrupts = lnl_dsp_disable_interrupts,
185	.hw_ip_version = SOF_INTEL_ACE_2_0,
186	.platform = "lnl",
187};
188
189MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL");
190MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
~/ Read-only file preview.