Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/intel/avs/icl.c
26583 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
//
3
// Copyright(c) 2021-2024 Intel Corporation
4
//
5
// Authors: Cezary Rojewski <[email protected]>
6
// Amadeusz Slawinski <[email protected]>
7
//
8
9
#include <linux/slab.h>
10
#include <sound/hdaudio.h>
11
#include <sound/hdaudio_ext.h>
12
#include "avs.h"
13
#include "messages.h"
14
15
#define ICL_VS_LTRP_GB_ICCMAX 95
16
17
#ifdef CONFIG_DEBUG_FS
18
int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
19
u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
20
{
21
struct avs_icl_log_state_info *info;
22
u32 size, num_libs = adev->fw_cfg.max_libs_count;
23
int i, ret;
24
25
if (fls_long(resource_mask) > num_libs)
26
return -EINVAL;
27
size = struct_size(info, logs_priorities_mask, num_libs);
28
info = kzalloc(size, GFP_KERNEL);
29
if (!info)
30
return -ENOMEM;
31
32
info->aging_timer_period = aging_period;
33
info->fifo_full_timer_period = fifo_full_period;
34
info->enable = enable;
35
if (enable)
36
for_each_set_bit(i, &resource_mask, num_libs)
37
info->logs_priorities_mask[i] = *priorities++;
38
39
ret = avs_ipc_set_enable_logs(adev, (u8 *)info, size);
40
kfree(info);
41
if (ret)
42
return AVS_IPC_RET(ret);
43
44
return 0;
45
}
46
#endif
47
48
union avs_icl_memwnd2_slot_type {
49
u32 val;
50
struct {
51
u32 resource_id:8;
52
u32 type:24;
53
};
54
} __packed;
55
static_assert(sizeof(union avs_icl_memwnd2_slot_type) == 4);
56
57
struct avs_icl_memwnd2_desc {
58
u32 resource_id;
59
union avs_icl_memwnd2_slot_type slot_id;
60
u32 vma;
61
} __packed;
62
static_assert(sizeof(struct avs_icl_memwnd2_desc) == 12);
63
64
#define AVS_ICL_MEMWND2_SLOTS_COUNT 15
65
66
struct avs_icl_memwnd2 {
67
union {
68
struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT];
69
u8 rsvd[SZ_4K];
70
};
71
u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][SZ_4K];
72
} __packed;
73
static_assert(sizeof(struct avs_icl_memwnd2) == 65536);
74
75
#define AVS_ICL_SLOT_UNUSED \
76
((union avs_icl_memwnd2_slot_type) { 0x00000000U })
77
#define AVS_ICL_SLOT_CRITICAL_LOG \
78
((union avs_icl_memwnd2_slot_type) { 0x54524300U })
79
#define AVS_ICL_SLOT_DEBUG_LOG \
80
((union avs_icl_memwnd2_slot_type) { 0x474f4c00U })
81
#define AVS_ICL_SLOT_GDB_STUB \
82
((union avs_icl_memwnd2_slot_type) { 0x42444700U })
83
#define AVS_ICL_SLOT_BROKEN \
84
((union avs_icl_memwnd2_slot_type) { 0x44414544U })
85
86
static int avs_icl_slot_offset(struct avs_dev *adev, union avs_icl_memwnd2_slot_type slot_type)
87
{
88
struct avs_icl_memwnd2_desc desc[AVS_ICL_MEMWND2_SLOTS_COUNT];
89
int i;
90
91
memcpy_fromio(&desc, avs_sram_addr(adev, AVS_DEBUG_WINDOW), sizeof(desc));
92
93
for (i = 0; i < AVS_ICL_MEMWND2_SLOTS_COUNT; i++)
94
if (desc[i].slot_id.val == slot_type.val)
95
return offsetof(struct avs_icl_memwnd2, slot_array) + i * SZ_4K;
96
return -ENXIO;
97
}
98
99
int avs_icl_log_buffer_offset(struct avs_dev *adev, u32 core)
100
{
101
union avs_icl_memwnd2_slot_type slot_type = AVS_ICL_SLOT_DEBUG_LOG;
102
int ret;
103
104
slot_type.resource_id = core;
105
ret = avs_icl_slot_offset(adev, slot_type);
106
if (ret < 0)
107
dev_dbg(adev->dev, "No slot offset found for: %x\n",
108
slot_type.val);
109
110
return ret;
111
}
112
113
bool avs_icl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake)
114
{
115
/* Full-power when starting DMA engines. */
116
if (tx->glb.set_ppl_state.state == AVS_PPL_STATE_RUNNING)
117
return true;
118
119
/* Payload-less IPCs do not take part in d0ix toggling. */
120
return tx->size;
121
}
122
123
int avs_icl_set_d0ix(struct avs_dev *adev, bool enable)
124
{
125
int ret;
126
127
ret = avs_ipc_set_d0ix(adev, enable, false);
128
return AVS_IPC_RET(ret);
129
}
130
131
int avs_icl_load_basefw(struct avs_dev *adev, struct firmware *fw)
132
{
133
struct hdac_bus *bus = &adev->base.core;
134
struct hdac_ext_stream *host_stream;
135
struct snd_pcm_substream substream;
136
struct snd_dma_buffer dmab;
137
unsigned int sd_fmt;
138
u8 ltrp_gb;
139
int ret;
140
141
/*
142
* ICCMAX:
143
*
144
* For ICL+ platforms, as per HW recommendation LTRP_GB is set to 95us
145
* during FW load. Its original value shall be restored once load completes.
146
*
147
* To avoid DMI/OPIO L1 entry during the load procedure, additional CAPTURE
148
* stream is allocated and set to run.
149
*/
150
151
memset(&substream, 0, sizeof(substream));
152
substream.stream = SNDRV_PCM_STREAM_CAPTURE;
153
154
host_stream = snd_hdac_ext_stream_assign(bus, &substream, HDAC_EXT_STREAM_TYPE_HOST);
155
if (!host_stream)
156
return -EBUSY;
157
158
ltrp_gb = snd_hdac_chip_readb(bus, VS_LTRP) & AZX_REG_VS_LTRP_GB_MASK;
159
/* Carries no real data, use default format. */
160
sd_fmt = snd_hdac_stream_format(1, 32, 48000);
161
162
ret = snd_hdac_dsp_prepare(hdac_stream(host_stream), sd_fmt, fw->size, &dmab);
163
if (ret < 0)
164
goto release_stream;
165
166
snd_hdac_chip_updateb(bus, VS_LTRP, AZX_REG_VS_LTRP_GB_MASK, ICL_VS_LTRP_GB_ICCMAX);
167
168
spin_lock(&bus->reg_lock);
169
snd_hdac_stream_start(hdac_stream(host_stream));
170
spin_unlock(&bus->reg_lock);
171
172
ret = avs_hda_load_basefw(adev, fw);
173
174
spin_lock(&bus->reg_lock);
175
snd_hdac_stream_stop(hdac_stream(host_stream));
176
spin_unlock(&bus->reg_lock);
177
178
snd_hdac_dsp_cleanup(hdac_stream(host_stream), &dmab);
179
180
release_stream:
181
snd_hdac_ext_stream_release(host_stream, HDAC_EXT_STREAM_TYPE_HOST);
182
snd_hdac_chip_updateb(bus, VS_LTRP, AZX_REG_VS_LTRP_GB_MASK, ltrp_gb);
183
184
return ret;
185
}
186
187
const struct avs_dsp_ops avs_icl_dsp_ops = {
188
.power = avs_dsp_core_power,
189
.reset = avs_dsp_core_reset,
190
.stall = avs_dsp_core_stall,
191
.dsp_interrupt = avs_cnl_dsp_interrupt,
192
.int_control = avs_dsp_interrupt_control,
193
.load_basefw = avs_icl_load_basefw,
194
.load_lib = avs_hda_load_library,
195
.transfer_mods = avs_hda_transfer_modules,
196
.log_buffer_offset = avs_icl_log_buffer_offset,
197
.log_buffer_status = avs_apl_log_buffer_status,
198
.coredump = avs_apl_coredump,
199
.d0ix_toggle = avs_icl_d0ix_toggle,
200
.set_d0ix = avs_icl_set_d0ix,
201
AVS_SET_ENABLE_LOGS_OP(icl)
202
};
203
204