Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/intel/catpt/messages.c
51977 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
//
3
// Copyright(c) 2020 Intel Corporation
4
//
5
// Author: Cezary Rojewski <[email protected]>
6
//
7
8
#include <linux/slab.h>
9
#include "core.h"
10
#include "messages.h"
11
#include "registers.h"
12
13
int catpt_ipc_get_fw_version(struct catpt_dev *cdev,
14
struct catpt_fw_version *version)
15
{
16
union catpt_global_msg msg = CATPT_GLOBAL_MSG(GET_FW_VERSION);
17
struct catpt_ipc_msg request = {{0}}, reply;
18
19
request.header = msg.val;
20
reply.size = sizeof(*version);
21
reply.data = version;
22
23
return catpt_dsp_send_msg(cdev, request, &reply, "get fw version");
24
}
25
26
struct catpt_alloc_stream_input {
27
enum catpt_path_id path_id:8;
28
enum catpt_stream_type stream_type:8;
29
enum catpt_format_id format_id:8;
30
u8 reserved;
31
struct catpt_audio_format input_format;
32
struct catpt_ring_info ring_info;
33
u8 num_entries;
34
/* flex array with entries here */
35
struct catpt_memory_info persistent_mem;
36
struct catpt_memory_info scratch_mem;
37
u32 num_notifications; /* obsolete */
38
} __packed;
39
40
int catpt_ipc_alloc_stream(struct catpt_dev *cdev,
41
enum catpt_path_id path_id,
42
enum catpt_stream_type type,
43
struct catpt_audio_format *afmt,
44
struct catpt_ring_info *rinfo,
45
u8 num_modules,
46
struct catpt_module_entry *modules,
47
struct resource *persistent,
48
struct resource *scratch,
49
struct catpt_stream_info *sinfo)
50
{
51
union catpt_global_msg msg = CATPT_GLOBAL_MSG(ALLOCATE_STREAM);
52
struct catpt_alloc_stream_input input;
53
struct catpt_ipc_msg request, reply;
54
size_t size, arrsz;
55
u8 *payload;
56
off_t off;
57
int ret;
58
59
off = offsetof(struct catpt_alloc_stream_input, persistent_mem);
60
arrsz = sizeof(*modules) * num_modules;
61
size = sizeof(input) + arrsz;
62
63
payload = kzalloc(size, GFP_KERNEL);
64
if (!payload)
65
return -ENOMEM;
66
67
memset(&input, 0, sizeof(input));
68
input.path_id = path_id;
69
input.stream_type = type;
70
input.format_id = CATPT_FORMAT_PCM;
71
input.input_format = *afmt;
72
input.ring_info = *rinfo;
73
input.num_entries = num_modules;
74
input.persistent_mem.offset = catpt_to_dsp_offset(persistent->start);
75
input.persistent_mem.size = resource_size(persistent);
76
if (scratch) {
77
input.scratch_mem.offset = catpt_to_dsp_offset(scratch->start);
78
input.scratch_mem.size = resource_size(scratch);
79
}
80
81
/* re-arrange the input: account for flex array 'entries' */
82
memcpy(payload, &input, sizeof(input));
83
memmove(payload + off + arrsz, payload + off, sizeof(input) - off);
84
memcpy(payload + off, modules, arrsz);
85
86
request.header = msg.val;
87
request.size = size;
88
request.data = payload;
89
reply.size = sizeof(*sinfo);
90
reply.data = sinfo;
91
92
ret = catpt_dsp_send_msg(cdev, request, &reply, "alloc stream");
93
kfree(payload);
94
return ret;
95
}
96
97
int catpt_ipc_free_stream(struct catpt_dev *cdev, u8 stream_hw_id)
98
{
99
union catpt_global_msg msg = CATPT_GLOBAL_MSG(FREE_STREAM);
100
struct catpt_ipc_msg request;
101
102
request.header = msg.val;
103
request.size = sizeof(stream_hw_id);
104
request.data = &stream_hw_id;
105
106
return catpt_dsp_send_msg(cdev, request, NULL, "free stream");
107
}
108
109
int catpt_ipc_set_device_format(struct catpt_dev *cdev,
110
struct catpt_ssp_device_format *devfmt)
111
{
112
union catpt_global_msg msg = CATPT_GLOBAL_MSG(SET_DEVICE_FORMATS);
113
struct catpt_ipc_msg request;
114
115
request.header = msg.val;
116
request.size = sizeof(*devfmt);
117
request.data = devfmt;
118
119
return catpt_dsp_send_msg(cdev, request, NULL, "set device format");
120
}
121
122
int catpt_ipc_enter_dxstate(struct catpt_dev *cdev, enum catpt_dx_state state,
123
struct catpt_dx_context *context)
124
{
125
union catpt_global_msg msg = CATPT_GLOBAL_MSG(ENTER_DX_STATE);
126
struct catpt_ipc_msg request, reply;
127
128
request.header = msg.val;
129
request.size = sizeof(state);
130
request.data = &state;
131
reply.size = sizeof(*context);
132
reply.data = context;
133
134
return catpt_dsp_send_msg(cdev, request, &reply, "enter dx state");
135
}
136
137
int catpt_ipc_get_mixer_stream_info(struct catpt_dev *cdev,
138
struct catpt_mixer_stream_info *info)
139
{
140
union catpt_global_msg msg = CATPT_GLOBAL_MSG(GET_MIXER_STREAM_INFO);
141
struct catpt_ipc_msg request = {{0}}, reply;
142
143
request.header = msg.val;
144
reply.size = sizeof(*info);
145
reply.data = info;
146
147
return catpt_dsp_send_msg(cdev, request, &reply, "get mixer info");
148
}
149
150
int catpt_ipc_reset_stream(struct catpt_dev *cdev, u8 stream_hw_id)
151
{
152
union catpt_stream_msg msg = CATPT_STREAM_MSG(RESET_STREAM);
153
struct catpt_ipc_msg request = {{0}};
154
155
msg.stream_hw_id = stream_hw_id;
156
request.header = msg.val;
157
158
return catpt_dsp_send_msg(cdev, request, NULL, "reset stream");
159
}
160
161
int catpt_ipc_pause_stream(struct catpt_dev *cdev, u8 stream_hw_id)
162
{
163
union catpt_stream_msg msg = CATPT_STREAM_MSG(PAUSE_STREAM);
164
struct catpt_ipc_msg request = {{0}};
165
166
msg.stream_hw_id = stream_hw_id;
167
request.header = msg.val;
168
169
return catpt_dsp_send_msg(cdev, request, NULL, "pause stream");
170
}
171
172
int catpt_ipc_resume_stream(struct catpt_dev *cdev, u8 stream_hw_id)
173
{
174
union catpt_stream_msg msg = CATPT_STREAM_MSG(RESUME_STREAM);
175
struct catpt_ipc_msg request = {{0}};
176
177
msg.stream_hw_id = stream_hw_id;
178
request.header = msg.val;
179
180
return catpt_dsp_send_msg(cdev, request, NULL, "resume stream");
181
}
182
183
struct catpt_set_volume_input {
184
u32 channel;
185
u32 target_volume;
186
u64 curve_duration;
187
u32 curve_type;
188
} __packed;
189
190
int catpt_ipc_set_volume(struct catpt_dev *cdev, u8 stream_hw_id,
191
u32 channel, u32 volume,
192
u32 curve_duration,
193
enum catpt_audio_curve_type curve_type)
194
{
195
union catpt_stream_msg msg = CATPT_STAGE_MSG(SET_VOLUME);
196
struct catpt_ipc_msg request;
197
struct catpt_set_volume_input input;
198
199
msg.stream_hw_id = stream_hw_id;
200
input.channel = channel;
201
input.target_volume = volume;
202
input.curve_duration = curve_duration;
203
input.curve_type = curve_type;
204
205
request.header = msg.val;
206
request.size = sizeof(input);
207
request.data = &input;
208
209
return catpt_dsp_send_msg(cdev, request, NULL, "set stream volume");
210
}
211
212
struct catpt_set_write_pos_input {
213
u32 new_write_pos;
214
bool end_of_buffer;
215
bool low_latency;
216
} __packed;
217
218
int catpt_ipc_set_write_pos(struct catpt_dev *cdev, u8 stream_hw_id,
219
u32 pos, bool eob, bool ll)
220
{
221
union catpt_stream_msg msg = CATPT_STAGE_MSG(SET_WRITE_POSITION);
222
struct catpt_ipc_msg request;
223
struct catpt_set_write_pos_input input;
224
225
msg.stream_hw_id = stream_hw_id;
226
input.new_write_pos = pos;
227
input.end_of_buffer = eob;
228
input.low_latency = ll;
229
230
request.header = msg.val;
231
request.size = sizeof(input);
232
request.data = &input;
233
234
return catpt_dsp_send_msg(cdev, request, NULL, "set stream write pos");
235
}
236
237
int catpt_ipc_mute_loopback(struct catpt_dev *cdev, u8 stream_hw_id, bool mute)
238
{
239
union catpt_stream_msg msg = CATPT_STAGE_MSG(MUTE_LOOPBACK);
240
struct catpt_ipc_msg request;
241
242
msg.stream_hw_id = stream_hw_id;
243
request.header = msg.val;
244
request.size = sizeof(mute);
245
request.data = &mute;
246
247
return catpt_dsp_send_msg(cdev, request, NULL, "mute loopback");
248
}
249
250