164a63d99SRanjani Sridharan // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
264a63d99SRanjani Sridharan //
364a63d99SRanjani Sridharan // Copyright(c) 2023 Intel Corporation. All rights reserved.
464a63d99SRanjani Sridharan
564a63d99SRanjani Sridharan /*
664a63d99SRanjani Sridharan * Hardware interface for audio DSP on LunarLake.
764a63d99SRanjani Sridharan */
864a63d99SRanjani Sridharan
964a63d99SRanjani Sridharan #include <linux/firmware.h>
1064a63d99SRanjani Sridharan #include <sound/hda_register.h>
1164a63d99SRanjani Sridharan #include <sound/sof/ipc4/header.h>
1264a63d99SRanjani Sridharan #include <trace/events/sof_intel.h>
1364a63d99SRanjani Sridharan #include "../ipc4-priv.h"
1464a63d99SRanjani Sridharan #include "../ops.h"
1564a63d99SRanjani Sridharan #include "hda.h"
1664a63d99SRanjani Sridharan #include "hda-ipc.h"
1764a63d99SRanjani Sridharan #include "../sof-audio.h"
1864a63d99SRanjani Sridharan #include "mtl.h"
19*6bdadbeeSPeter Ujfalusi #include "lnl.h"
2064a63d99SRanjani Sridharan #include <sound/hda-mlink.h>
2164a63d99SRanjani Sridharan
22c22d5327SPierre-Louis Bossart /* LunarLake ops */
23c22d5327SPierre-Louis Bossart struct snd_sof_dsp_ops sof_lnl_ops;
24c22d5327SPierre-Louis Bossart EXPORT_SYMBOL_NS(sof_lnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
25c22d5327SPierre-Louis Bossart
26c22d5327SPierre-Louis Bossart static const struct snd_sof_debugfs_map lnl_dsp_debugfs[] = {
27c22d5327SPierre-Louis Bossart {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
28c22d5327SPierre-Louis Bossart {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
29c22d5327SPierre-Louis Bossart {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
30c22d5327SPierre-Louis Bossart };
31c22d5327SPierre-Louis Bossart
32e78576c4SPierre-Louis Bossart /* this helps allows the DSP to setup DMIC/SSP */
hdac_bus_offload_dmic_ssp(struct hdac_bus * bus)33e78576c4SPierre-Louis Bossart static int hdac_bus_offload_dmic_ssp(struct hdac_bus *bus)
34e78576c4SPierre-Louis Bossart {
35e78576c4SPierre-Louis Bossart int ret;
36e78576c4SPierre-Louis Bossart
37e78576c4SPierre-Louis Bossart ret = hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_SSP, true);
38e78576c4SPierre-Louis Bossart if (ret < 0)
39e78576c4SPierre-Louis Bossart return ret;
40e78576c4SPierre-Louis Bossart
41e78576c4SPierre-Louis Bossart ret = hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_DMIC, true);
42e78576c4SPierre-Louis Bossart if (ret < 0)
43e78576c4SPierre-Louis Bossart return ret;
44e78576c4SPierre-Louis Bossart
45e78576c4SPierre-Louis Bossart return 0;
46e78576c4SPierre-Louis Bossart }
47e78576c4SPierre-Louis Bossart
lnl_hda_dsp_probe(struct snd_sof_dev * sdev)48e78576c4SPierre-Louis Bossart static int lnl_hda_dsp_probe(struct snd_sof_dev *sdev)
49e78576c4SPierre-Louis Bossart {
50e78576c4SPierre-Louis Bossart int ret;
51e78576c4SPierre-Louis Bossart
52e78576c4SPierre-Louis Bossart ret = hda_dsp_probe(sdev);
53e78576c4SPierre-Louis Bossart if (ret < 0)
54e78576c4SPierre-Louis Bossart return ret;
55e78576c4SPierre-Louis Bossart
56e78576c4SPierre-Louis Bossart return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev));
57e78576c4SPierre-Louis Bossart }
58e78576c4SPierre-Louis Bossart
lnl_hda_dsp_resume(struct snd_sof_dev * sdev)59e78576c4SPierre-Louis Bossart static int lnl_hda_dsp_resume(struct snd_sof_dev *sdev)
60e78576c4SPierre-Louis Bossart {
61e78576c4SPierre-Louis Bossart int ret;
62e78576c4SPierre-Louis Bossart
63e78576c4SPierre-Louis Bossart ret = hda_dsp_resume(sdev);
64e78576c4SPierre-Louis Bossart if (ret < 0)
65e78576c4SPierre-Louis Bossart return ret;
66e78576c4SPierre-Louis Bossart
67e78576c4SPierre-Louis Bossart return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev));
68e78576c4SPierre-Louis Bossart }
69e78576c4SPierre-Louis Bossart
lnl_hda_dsp_runtime_resume(struct snd_sof_dev * sdev)70e78576c4SPierre-Louis Bossart static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
71e78576c4SPierre-Louis Bossart {
72e78576c4SPierre-Louis Bossart int ret;
73e78576c4SPierre-Louis Bossart
74e78576c4SPierre-Louis Bossart ret = hda_dsp_runtime_resume(sdev);
75e78576c4SPierre-Louis Bossart if (ret < 0)
76e78576c4SPierre-Louis Bossart return ret;
77e78576c4SPierre-Louis Bossart
78e78576c4SPierre-Louis Bossart return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev));
79e78576c4SPierre-Louis Bossart }
80e78576c4SPierre-Louis Bossart
sof_lnl_ops_init(struct snd_sof_dev * sdev)81c22d5327SPierre-Louis Bossart int sof_lnl_ops_init(struct snd_sof_dev *sdev)
82c22d5327SPierre-Louis Bossart {
83c22d5327SPierre-Louis Bossart struct sof_ipc4_fw_data *ipc4_data;
84c22d5327SPierre-Louis Bossart
85c22d5327SPierre-Louis Bossart /* common defaults */
86c22d5327SPierre-Louis Bossart memcpy(&sof_lnl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
87c22d5327SPierre-Louis Bossart
88e78576c4SPierre-Louis Bossart /* probe */
89e78576c4SPierre-Louis Bossart sof_lnl_ops.probe = lnl_hda_dsp_probe;
90e78576c4SPierre-Louis Bossart
91c22d5327SPierre-Louis Bossart /* shutdown */
92c22d5327SPierre-Louis Bossart sof_lnl_ops.shutdown = hda_dsp_shutdown;
93c22d5327SPierre-Louis Bossart
94c22d5327SPierre-Louis Bossart /* doorbell */
95c22d5327SPierre-Louis Bossart sof_lnl_ops.irq_thread = mtl_ipc_irq_thread;
96c22d5327SPierre-Louis Bossart
97c22d5327SPierre-Louis Bossart /* ipc */
98c22d5327SPierre-Louis Bossart sof_lnl_ops.send_msg = mtl_ipc_send_msg;
99c22d5327SPierre-Louis Bossart sof_lnl_ops.get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset;
100c22d5327SPierre-Louis Bossart sof_lnl_ops.get_window_offset = mtl_dsp_ipc_get_window_offset;
101c22d5327SPierre-Louis Bossart
102c22d5327SPierre-Louis Bossart /* debug */
103c22d5327SPierre-Louis Bossart sof_lnl_ops.debug_map = lnl_dsp_debugfs;
104c22d5327SPierre-Louis Bossart sof_lnl_ops.debug_map_count = ARRAY_SIZE(lnl_dsp_debugfs);
105c22d5327SPierre-Louis Bossart sof_lnl_ops.dbg_dump = mtl_dsp_dump;
106c22d5327SPierre-Louis Bossart sof_lnl_ops.ipc_dump = mtl_ipc_dump;
107c22d5327SPierre-Louis Bossart
108c22d5327SPierre-Louis Bossart /* pre/post fw run */
109c22d5327SPierre-Louis Bossart sof_lnl_ops.pre_fw_run = mtl_dsp_pre_fw_run;
110c22d5327SPierre-Louis Bossart sof_lnl_ops.post_fw_run = mtl_dsp_post_fw_run;
111c22d5327SPierre-Louis Bossart
112c22d5327SPierre-Louis Bossart /* parse platform specific extended manifest */
113c22d5327SPierre-Louis Bossart sof_lnl_ops.parse_platform_ext_manifest = NULL;
114c22d5327SPierre-Louis Bossart
115c22d5327SPierre-Louis Bossart /* dsp core get/put */
116c22d5327SPierre-Louis Bossart /* TODO: add core_get and core_put */
117c22d5327SPierre-Louis Bossart
118e78576c4SPierre-Louis Bossart /* PM */
119e78576c4SPierre-Louis Bossart sof_lnl_ops.resume = lnl_hda_dsp_resume;
120e78576c4SPierre-Louis Bossart sof_lnl_ops.runtime_resume = lnl_hda_dsp_runtime_resume;
121e78576c4SPierre-Louis Bossart
122c22d5327SPierre-Louis Bossart sof_lnl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
123c22d5327SPierre-Louis Bossart
124c22d5327SPierre-Louis Bossart sdev->private = devm_kzalloc(sdev->dev, sizeof(struct sof_ipc4_fw_data), GFP_KERNEL);
125c22d5327SPierre-Louis Bossart if (!sdev->private)
126c22d5327SPierre-Louis Bossart return -ENOMEM;
127c22d5327SPierre-Louis Bossart
128c22d5327SPierre-Louis Bossart ipc4_data = sdev->private;
129c22d5327SPierre-Louis Bossart ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
130c22d5327SPierre-Louis Bossart
131c22d5327SPierre-Louis Bossart ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2;
132c22d5327SPierre-Louis Bossart
133c22d5327SPierre-Louis Bossart /* External library loading support */
134c22d5327SPierre-Louis Bossart ipc4_data->load_library = hda_dsp_ipc4_load_library;
135c22d5327SPierre-Louis Bossart
136c22d5327SPierre-Louis Bossart /* set DAI ops */
137c22d5327SPierre-Louis Bossart hda_set_dai_drv_ops(sdev, &sof_lnl_ops);
138c22d5327SPierre-Louis Bossart
139c22d5327SPierre-Louis Bossart sof_lnl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
140c22d5327SPierre-Louis Bossart
141c22d5327SPierre-Louis Bossart return 0;
142c22d5327SPierre-Louis Bossart };
143c22d5327SPierre-Louis Bossart EXPORT_SYMBOL_NS(sof_lnl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);
144c22d5327SPierre-Louis Bossart
14564a63d99SRanjani Sridharan /* Check if an SDW IRQ occurred */
lnl_dsp_check_sdw_irq(struct snd_sof_dev * sdev)14664a63d99SRanjani Sridharan static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
14764a63d99SRanjani Sridharan {
14864a63d99SRanjani Sridharan struct hdac_bus *bus = sof_to_bus(sdev);
14964a63d99SRanjani Sridharan
15064a63d99SRanjani Sridharan return hdac_bus_eml_check_interrupt(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
15164a63d99SRanjani Sridharan }
15264a63d99SRanjani Sridharan
lnl_enable_sdw_irq(struct snd_sof_dev * sdev,bool enable)15364a63d99SRanjani Sridharan static void lnl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
15464a63d99SRanjani Sridharan {
15564a63d99SRanjani Sridharan struct hdac_bus *bus = sof_to_bus(sdev);
15664a63d99SRanjani Sridharan
15764a63d99SRanjani Sridharan hdac_bus_eml_enable_interrupt(bus, true, AZX_REG_ML_LEPTR_ID_SDW, enable);
15864a63d99SRanjani Sridharan }
15964a63d99SRanjani Sridharan
lnl_dsp_disable_interrupts(struct snd_sof_dev * sdev)16064a63d99SRanjani Sridharan static int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
16164a63d99SRanjani Sridharan {
16264a63d99SRanjani Sridharan lnl_enable_sdw_irq(sdev, false);
16364a63d99SRanjani Sridharan mtl_disable_ipc_interrupts(sdev);
16464a63d99SRanjani Sridharan return mtl_enable_interrupts(sdev, false);
16564a63d99SRanjani Sridharan }
16664a63d99SRanjani Sridharan
16764a63d99SRanjani Sridharan const struct sof_intel_dsp_desc lnl_chip_info = {
16864a63d99SRanjani Sridharan .cores_num = 5,
16964a63d99SRanjani Sridharan .init_core_mask = BIT(0),
17064a63d99SRanjani Sridharan .host_managed_cores_mask = BIT(0),
17164a63d99SRanjani Sridharan .ipc_req = MTL_DSP_REG_HFIPCXIDR,
17264a63d99SRanjani Sridharan .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
17364a63d99SRanjani Sridharan .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
17464a63d99SRanjani Sridharan .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
17564a63d99SRanjani Sridharan .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
176*6bdadbeeSPeter Ujfalusi .rom_status_reg = LNL_DSP_REG_HFDSC,
17764a63d99SRanjani Sridharan .rom_init_timeout = 300,
17864a63d99SRanjani Sridharan .ssp_count = MTL_SSP_COUNT,
17964a63d99SRanjani Sridharan .d0i3_offset = MTL_HDA_VS_D0I3C,
18064a63d99SRanjani Sridharan .read_sdw_lcount = hda_sdw_check_lcount_ext,
18164a63d99SRanjani Sridharan .enable_sdw_irq = lnl_enable_sdw_irq,
18264a63d99SRanjani Sridharan .check_sdw_irq = lnl_dsp_check_sdw_irq,
18364a63d99SRanjani Sridharan .check_ipc_irq = mtl_dsp_check_ipc_irq,
18464a63d99SRanjani Sridharan .cl_init = mtl_dsp_cl_init,
18564a63d99SRanjani Sridharan .power_down_dsp = mtl_power_down_dsp,
18664a63d99SRanjani Sridharan .disable_interrupts = lnl_dsp_disable_interrupts,
18764a63d99SRanjani Sridharan .hw_ip_version = SOF_INTEL_ACE_2_0,
18864a63d99SRanjani Sridharan };
18964a63d99SRanjani Sridharan EXPORT_SYMBOL_NS(lnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
190