Commit | Line | Data |
---|---|---|
e149ca29 | 1 | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ |
d1d95fcb LG |
2 | /* |
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | |
4 | * redistributing this file, you may do so under either license. | |
5 | * | |
6 | * Copyright(c) 2018 Intel Corporation. All rights reserved. | |
7 | * | |
8 | * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> | |
9 | */ | |
10 | ||
11 | #ifndef __SOUND_SOC_SOF_IO_H | |
12 | #define __SOUND_SOC_SOF_IO_H | |
13 | ||
14 | #include <linux/device.h> | |
15 | #include <linux/interrupt.h> | |
16 | #include <linux/kernel.h> | |
17 | #include <linux/types.h> | |
18 | #include <sound/pcm.h> | |
19 | #include "sof-priv.h" | |
20 | ||
21 | #define sof_ops(sdev) \ | |
22 | ((sdev)->pdata->desc->ops) | |
23 | ||
37e809d5 | 24 | static inline int sof_ops_init(struct snd_sof_dev *sdev) |
856601e5 PLB |
25 | { |
26 | if (sdev->pdata->desc->ops_init) | |
37e809d5 PLB |
27 | return sdev->pdata->desc->ops_init(sdev); |
28 | ||
29 | return 0; | |
856601e5 PLB |
30 | } |
31 | ||
bc433fd7 RS |
32 | static inline void sof_ops_free(struct snd_sof_dev *sdev) |
33 | { | |
34 | if (sdev->pdata->desc->ops_free) | |
35 | sdev->pdata->desc->ops_free(sdev); | |
36 | } | |
37 | ||
d1d95fcb LG |
38 | /* Mandatory operations are verified during probing */ |
39 | ||
40 | /* init */ | |
17baaa1f PLB |
41 | static inline int snd_sof_probe_early(struct snd_sof_dev *sdev) |
42 | { | |
43 | if (sof_ops(sdev)->probe_early) | |
44 | return sof_ops(sdev)->probe_early(sdev); | |
45 | ||
46 | return 0; | |
47 | } | |
48 | ||
d1d95fcb LG |
49 | static inline int snd_sof_probe(struct snd_sof_dev *sdev) |
50 | { | |
51 | return sof_ops(sdev)->probe(sdev); | |
52 | } | |
53 | ||
e4d09de3 | 54 | static inline void snd_sof_remove(struct snd_sof_dev *sdev) |
d1d95fcb LG |
55 | { |
56 | if (sof_ops(sdev)->remove) | |
e4d09de3 | 57 | sof_ops(sdev)->remove(sdev); |
d1d95fcb LG |
58 | } |
59 | ||
264aeb99 | 60 | static inline void snd_sof_remove_late(struct snd_sof_dev *sdev) |
17baaa1f PLB |
61 | { |
62 | if (sof_ops(sdev)->remove_late) | |
264aeb99 | 63 | sof_ops(sdev)->remove_late(sdev); |
17baaa1f PLB |
64 | } |
65 | ||
7edb3051 KJ |
66 | static inline int snd_sof_shutdown(struct snd_sof_dev *sdev) |
67 | { | |
68 | if (sof_ops(sdev)->shutdown) | |
69 | return sof_ops(sdev)->shutdown(sdev); | |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
d1d95fcb LG |
74 | /* control */ |
75 | ||
76 | /* | |
77 | * snd_sof_dsp_run returns the core mask of the cores that are available | |
78 | * after successful fw boot | |
79 | */ | |
80 | static inline int snd_sof_dsp_run(struct snd_sof_dev *sdev) | |
81 | { | |
82 | return sof_ops(sdev)->run(sdev); | |
83 | } | |
84 | ||
a70eb708 | 85 | static inline int snd_sof_dsp_stall(struct snd_sof_dev *sdev, unsigned int core_mask) |
d1d95fcb LG |
86 | { |
87 | if (sof_ops(sdev)->stall) | |
a70eb708 | 88 | return sof_ops(sdev)->stall(sdev, core_mask); |
d1d95fcb LG |
89 | |
90 | return 0; | |
91 | } | |
92 | ||
93 | static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev) | |
94 | { | |
95 | if (sof_ops(sdev)->reset) | |
96 | return sof_ops(sdev)->reset(sdev); | |
97 | ||
98 | return 0; | |
99 | } | |
100 | ||
9ea80748 | 101 | /* dsp core get/put */ |
c414d5df RS |
102 | static inline int snd_sof_dsp_core_get(struct snd_sof_dev *sdev, int core) |
103 | { | |
104 | if (core > sdev->num_cores - 1) { | |
105 | dev_err(sdev->dev, "invalid core id: %d for num_cores: %d\n", core, | |
106 | sdev->num_cores); | |
107 | return -EINVAL; | |
108 | } | |
109 | ||
110 | if (sof_ops(sdev)->core_get) { | |
111 | int ret; | |
112 | ||
113 | /* if current ref_count is > 0, increment it and return */ | |
114 | if (sdev->dsp_core_ref_count[core] > 0) { | |
115 | sdev->dsp_core_ref_count[core]++; | |
116 | return 0; | |
117 | } | |
118 | ||
119 | /* power up the core */ | |
120 | ret = sof_ops(sdev)->core_get(sdev, core); | |
121 | if (ret < 0) | |
122 | return ret; | |
123 | ||
124 | /* increment ref_count */ | |
125 | sdev->dsp_core_ref_count[core]++; | |
126 | ||
127 | /* and update enabled_cores_mask */ | |
128 | sdev->enabled_cores_mask |= BIT(core); | |
129 | ||
130 | dev_dbg(sdev->dev, "Core %d powered up\n", core); | |
131 | } | |
132 | ||
133 | return 0; | |
134 | } | |
135 | ||
136 | static inline int snd_sof_dsp_core_put(struct snd_sof_dev *sdev, int core) | |
137 | { | |
138 | if (core > sdev->num_cores - 1) { | |
139 | dev_err(sdev->dev, "invalid core id: %d for num_cores: %d\n", core, | |
140 | sdev->num_cores); | |
141 | return -EINVAL; | |
142 | } | |
143 | ||
144 | if (sof_ops(sdev)->core_put) { | |
145 | int ret; | |
146 | ||
147 | /* decrement ref_count and return if it is > 0 */ | |
148 | if (--(sdev->dsp_core_ref_count[core]) > 0) | |
149 | return 0; | |
150 | ||
151 | /* power down the core */ | |
152 | ret = sof_ops(sdev)->core_put(sdev, core); | |
153 | if (ret < 0) | |
154 | return ret; | |
155 | ||
156 | /* and update enabled_cores_mask */ | |
157 | sdev->enabled_cores_mask &= ~BIT(core); | |
158 | ||
159 | dev_dbg(sdev->dev, "Core %d powered down\n", core); | |
160 | } | |
161 | ||
162 | return 0; | |
163 | } | |
164 | ||
d1d95fcb LG |
165 | /* pre/post fw load */ |
166 | static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev) | |
167 | { | |
168 | if (sof_ops(sdev)->pre_fw_run) | |
169 | return sof_ops(sdev)->pre_fw_run(sdev); | |
170 | ||
171 | return 0; | |
172 | } | |
173 | ||
174 | static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev) | |
175 | { | |
176 | if (sof_ops(sdev)->post_fw_run) | |
177 | return sof_ops(sdev)->post_fw_run(sdev); | |
178 | ||
179 | return 0; | |
180 | } | |
181 | ||
e984f3ef FO |
182 | /* parse platform specific extended manifest */ |
183 | static inline int snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev *sdev, | |
184 | const struct sof_ext_man_elem_header *hdr) | |
185 | { | |
186 | if (sof_ops(sdev)->parse_platform_ext_manifest) | |
187 | return sof_ops(sdev)->parse_platform_ext_manifest(sdev, hdr); | |
188 | ||
189 | return 0; | |
190 | } | |
191 | ||
ce8234a6 DB |
192 | /* misc */ |
193 | ||
194 | /** | |
195 | * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index | |
196 | * | |
197 | * @sdev: sof device | |
198 | * @type: section type as described by snd_sof_fw_blk_type | |
199 | * | |
200 | * Returns the corresponding BAR index (a positive integer) or -EINVAL | |
201 | * in case there is no mapping | |
202 | */ | |
203 | static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type) | |
204 | { | |
205 | if (sof_ops(sdev)->get_bar_index) | |
206 | return sof_ops(sdev)->get_bar_index(sdev, type); | |
207 | ||
208 | return sdev->mmio_bar; | |
209 | } | |
210 | ||
bb9c93f5 DB |
211 | static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev) |
212 | { | |
213 | if (sof_ops(sdev)->get_mailbox_offset) | |
214 | return sof_ops(sdev)->get_mailbox_offset(sdev); | |
215 | ||
216 | dev_err(sdev->dev, "error: %s not defined\n", __func__); | |
353bc992 | 217 | return -EOPNOTSUPP; |
bb9c93f5 DB |
218 | } |
219 | ||
e17422cd DB |
220 | static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev, |
221 | u32 id) | |
222 | { | |
223 | if (sof_ops(sdev)->get_window_offset) | |
224 | return sof_ops(sdev)->get_window_offset(sdev, id); | |
225 | ||
226 | dev_err(sdev->dev, "error: %s not defined\n", __func__); | |
353bc992 | 227 | return -EOPNOTSUPP; |
e17422cd | 228 | } |
d1d95fcb LG |
229 | /* power management */ |
230 | static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) | |
231 | { | |
232 | if (sof_ops(sdev)->resume) | |
233 | return sof_ops(sdev)->resume(sdev); | |
234 | ||
235 | return 0; | |
236 | } | |
237 | ||
61e285ca RS |
238 | static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev, |
239 | u32 target_state) | |
d1d95fcb LG |
240 | { |
241 | if (sof_ops(sdev)->suspend) | |
61e285ca | 242 | return sof_ops(sdev)->suspend(sdev, target_state); |
d1d95fcb LG |
243 | |
244 | return 0; | |
245 | } | |
246 | ||
247 | static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev) | |
248 | { | |
249 | if (sof_ops(sdev)->runtime_resume) | |
250 | return sof_ops(sdev)->runtime_resume(sdev); | |
251 | ||
252 | return 0; | |
253 | } | |
254 | ||
1c38c922 | 255 | static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev) |
d1d95fcb LG |
256 | { |
257 | if (sof_ops(sdev)->runtime_suspend) | |
1c38c922 | 258 | return sof_ops(sdev)->runtime_suspend(sdev); |
d1d95fcb LG |
259 | |
260 | return 0; | |
261 | } | |
262 | ||
62fde977 KV |
263 | static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev) |
264 | { | |
265 | if (sof_ops(sdev)->runtime_idle) | |
266 | return sof_ops(sdev)->runtime_idle(sdev); | |
267 | ||
268 | return 0; | |
269 | } | |
270 | ||
7077a07a | 271 | static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev) |
ed3baacd RS |
272 | { |
273 | if (sof_ops(sdev)->set_hw_params_upon_resume) | |
7077a07a RS |
274 | return sof_ops(sdev)->set_hw_params_upon_resume(sdev); |
275 | return 0; | |
ed3baacd RS |
276 | } |
277 | ||
d1d95fcb LG |
278 | static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq) |
279 | { | |
280 | if (sof_ops(sdev)->set_clk) | |
281 | return sof_ops(sdev)->set_clk(sdev, freq); | |
282 | ||
283 | return 0; | |
284 | } | |
285 | ||
61e285ca RS |
286 | static inline int |
287 | snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev, | |
288 | const struct sof_dsp_power_state *target_state) | |
e8f112d8 | 289 | { |
8b66d7c5 KJ |
290 | int ret = 0; |
291 | ||
292 | mutex_lock(&sdev->power_state_access); | |
293 | ||
e8f112d8 | 294 | if (sof_ops(sdev)->set_power_state) |
8b66d7c5 | 295 | ret = sof_ops(sdev)->set_power_state(sdev, target_state); |
e8f112d8 | 296 | |
8b66d7c5 KJ |
297 | mutex_unlock(&sdev->power_state_access); |
298 | ||
299 | return ret; | |
e8f112d8 KJ |
300 | } |
301 | ||
d1d95fcb | 302 | /* debug */ |
2f148430 | 303 | void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, const char *msg, u32 flags); |
5e4a27fd | 304 | |
07e833b4 PU |
305 | static inline int snd_sof_debugfs_add_region_item(struct snd_sof_dev *sdev, |
306 | enum snd_sof_fw_blk_type blk_type, u32 offset, size_t size, | |
307 | const char *name, enum sof_debugfs_access_type access_type) | |
308 | { | |
309 | if (sof_ops(sdev) && sof_ops(sdev)->debugfs_add_region_item) | |
310 | return sof_ops(sdev)->debugfs_add_region_item(sdev, blk_type, offset, | |
311 | size, name, access_type); | |
312 | ||
313 | return 0; | |
314 | } | |
315 | ||
d1d95fcb | 316 | /* register IO */ |
f8fbf0dc | 317 | static inline void snd_sof_dsp_write8(struct snd_sof_dev *sdev, u32 bar, |
74fe0c4d PLB |
318 | u32 offset, u8 value) |
319 | { | |
f8fbf0dc PLB |
320 | if (sof_ops(sdev)->write8) |
321 | sof_ops(sdev)->write8(sdev, sdev->bar[bar] + offset, value); | |
74fe0c4d PLB |
322 | else |
323 | writeb(value, sdev->bar[bar] + offset); | |
324 | } | |
325 | ||
d1d95fcb LG |
326 | static inline void snd_sof_dsp_write(struct snd_sof_dev *sdev, u32 bar, |
327 | u32 offset, u32 value) | |
328 | { | |
01278cb6 | 329 | if (sof_ops(sdev)->write) |
d1d95fcb | 330 | sof_ops(sdev)->write(sdev, sdev->bar[bar] + offset, value); |
01278cb6 PLB |
331 | else |
332 | writel(value, sdev->bar[bar] + offset); | |
d1d95fcb LG |
333 | } |
334 | ||
335 | static inline void snd_sof_dsp_write64(struct snd_sof_dev *sdev, u32 bar, | |
336 | u32 offset, u64 value) | |
337 | { | |
01278cb6 | 338 | if (sof_ops(sdev)->write64) |
d1d95fcb | 339 | sof_ops(sdev)->write64(sdev, sdev->bar[bar] + offset, value); |
01278cb6 PLB |
340 | else |
341 | writeq(value, sdev->bar[bar] + offset); | |
d1d95fcb LG |
342 | } |
343 | ||
f8fbf0dc | 344 | static inline u8 snd_sof_dsp_read8(struct snd_sof_dev *sdev, u32 bar, |
74fe0c4d PLB |
345 | u32 offset) |
346 | { | |
f8fbf0dc PLB |
347 | if (sof_ops(sdev)->read8) |
348 | return sof_ops(sdev)->read8(sdev, sdev->bar[bar] + offset); | |
74fe0c4d PLB |
349 | else |
350 | return readb(sdev->bar[bar] + offset); | |
351 | } | |
352 | ||
d1d95fcb LG |
353 | static inline u32 snd_sof_dsp_read(struct snd_sof_dev *sdev, u32 bar, |
354 | u32 offset) | |
355 | { | |
356 | if (sof_ops(sdev)->read) | |
357 | return sof_ops(sdev)->read(sdev, sdev->bar[bar] + offset); | |
01278cb6 PLB |
358 | else |
359 | return readl(sdev->bar[bar] + offset); | |
d1d95fcb LG |
360 | } |
361 | ||
362 | static inline u64 snd_sof_dsp_read64(struct snd_sof_dev *sdev, u32 bar, | |
363 | u32 offset) | |
364 | { | |
365 | if (sof_ops(sdev)->read64) | |
366 | return sof_ops(sdev)->read64(sdev, sdev->bar[bar] + offset); | |
01278cb6 PLB |
367 | else |
368 | return readq(sdev->bar[bar] + offset); | |
d1d95fcb LG |
369 | } |
370 | ||
f8fbf0dc | 371 | static inline void snd_sof_dsp_update8(struct snd_sof_dev *sdev, u32 bar, |
5afc7eef | 372 | u32 offset, u8 mask, u8 value) |
c28a36b0 PLB |
373 | { |
374 | u8 reg; | |
375 | ||
f8fbf0dc | 376 | reg = snd_sof_dsp_read8(sdev, bar, offset); |
c28a36b0 PLB |
377 | reg &= ~mask; |
378 | reg |= value; | |
f8fbf0dc | 379 | snd_sof_dsp_write8(sdev, bar, offset, reg); |
c28a36b0 PLB |
380 | } |
381 | ||
d1d95fcb | 382 | /* block IO */ |
4624bb2f PU |
383 | static inline int snd_sof_dsp_block_read(struct snd_sof_dev *sdev, |
384 | enum snd_sof_fw_blk_type blk_type, | |
385 | u32 offset, void *dest, size_t bytes) | |
d1d95fcb | 386 | { |
4624bb2f | 387 | return sof_ops(sdev)->block_read(sdev, blk_type, offset, dest, bytes); |
d1d95fcb LG |
388 | } |
389 | ||
4624bb2f PU |
390 | static inline int snd_sof_dsp_block_write(struct snd_sof_dev *sdev, |
391 | enum snd_sof_fw_blk_type blk_type, | |
392 | u32 offset, void *src, size_t bytes) | |
d1d95fcb | 393 | { |
4624bb2f | 394 | return sof_ops(sdev)->block_write(sdev, blk_type, offset, src, bytes); |
d1d95fcb LG |
395 | } |
396 | ||
f71f59dd DB |
397 | /* mailbox IO */ |
398 | static inline void snd_sof_dsp_mailbox_read(struct snd_sof_dev *sdev, | |
399 | u32 offset, void *dest, size_t bytes) | |
400 | { | |
401 | if (sof_ops(sdev)->mailbox_read) | |
402 | sof_ops(sdev)->mailbox_read(sdev, offset, dest, bytes); | |
403 | } | |
404 | ||
405 | static inline void snd_sof_dsp_mailbox_write(struct snd_sof_dev *sdev, | |
406 | u32 offset, void *src, size_t bytes) | |
407 | { | |
408 | if (sof_ops(sdev)->mailbox_write) | |
409 | sof_ops(sdev)->mailbox_write(sdev, offset, src, bytes); | |
410 | } | |
411 | ||
d1d95fcb LG |
412 | /* ipc */ |
413 | static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev, | |
414 | struct snd_sof_ipc_msg *msg) | |
415 | { | |
416 | return sof_ops(sdev)->send_msg(sdev, msg); | |
417 | } | |
418 | ||
d1d95fcb LG |
419 | /* host PCM ops */ |
420 | static inline int | |
421 | snd_sof_pcm_platform_open(struct snd_sof_dev *sdev, | |
422 | struct snd_pcm_substream *substream) | |
423 | { | |
424 | if (sof_ops(sdev) && sof_ops(sdev)->pcm_open) | |
425 | return sof_ops(sdev)->pcm_open(sdev, substream); | |
426 | ||
427 | return 0; | |
428 | } | |
429 | ||
430 | /* disconnect pcm substream to a host stream */ | |
431 | static inline int | |
432 | snd_sof_pcm_platform_close(struct snd_sof_dev *sdev, | |
433 | struct snd_pcm_substream *substream) | |
434 | { | |
435 | if (sof_ops(sdev) && sof_ops(sdev)->pcm_close) | |
436 | return sof_ops(sdev)->pcm_close(sdev, substream); | |
437 | ||
438 | return 0; | |
439 | } | |
440 | ||
441 | /* host stream hw params */ | |
442 | static inline int | |
443 | snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev, | |
444 | struct snd_pcm_substream *substream, | |
445 | struct snd_pcm_hw_params *params, | |
31f60a0c | 446 | struct snd_sof_platform_stream_params *platform_params) |
d1d95fcb LG |
447 | { |
448 | if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params) | |
31f60a0c PU |
449 | return sof_ops(sdev)->pcm_hw_params(sdev, substream, params, |
450 | platform_params); | |
d1d95fcb LG |
451 | |
452 | return 0; | |
453 | } | |
454 | ||
93146bc2 RS |
455 | /* host stream hw free */ |
456 | static inline int | |
457 | snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev, | |
458 | struct snd_pcm_substream *substream) | |
459 | { | |
460 | if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free) | |
461 | return sof_ops(sdev)->pcm_hw_free(sdev, substream); | |
462 | ||
463 | return 0; | |
464 | } | |
465 | ||
d1d95fcb LG |
466 | /* host stream trigger */ |
467 | static inline int | |
468 | snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev, | |
469 | struct snd_pcm_substream *substream, int cmd) | |
470 | { | |
471 | if (sof_ops(sdev) && sof_ops(sdev)->pcm_trigger) | |
472 | return sof_ops(sdev)->pcm_trigger(sdev, substream, cmd); | |
473 | ||
474 | return 0; | |
475 | } | |
476 | ||
96ec1741 PU |
477 | /* Firmware loading */ |
478 | static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev) | |
479 | { | |
480 | dev_dbg(sdev->dev, "loading firmware\n"); | |
481 | ||
482 | return sof_ops(sdev)->load_firmware(sdev); | |
483 | } | |
484 | ||
d1d95fcb | 485 | /* host DSP message data */ |
6a0ba071 | 486 | static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev, |
1b905942 | 487 | struct snd_sof_pcm_stream *sps, |
6a0ba071 | 488 | void *p, size_t sz) |
d1d95fcb | 489 | { |
1b905942 | 490 | return sof_ops(sdev)->ipc_msg_data(sdev, sps, p, sz); |
d1d95fcb | 491 | } |
757ce810 PU |
492 | /* host side configuration of the stream's data offset in stream mailbox area */ |
493 | static inline int | |
494 | snd_sof_set_stream_data_offset(struct snd_sof_dev *sdev, | |
249f186d | 495 | struct snd_sof_pcm_stream *sps, |
757ce810 PU |
496 | size_t posn_offset) |
497 | { | |
498 | if (sof_ops(sdev) && sof_ops(sdev)->set_stream_data_offset) | |
249f186d | 499 | return sof_ops(sdev)->set_stream_data_offset(sdev, sps, |
757ce810 PU |
500 | posn_offset); |
501 | ||
502 | return 0; | |
503 | } | |
504 | ||
d1d95fcb LG |
505 | /* host stream pointer */ |
506 | static inline snd_pcm_uframes_t | |
507 | snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev, | |
508 | struct snd_pcm_substream *substream) | |
509 | { | |
510 | if (sof_ops(sdev) && sof_ops(sdev)->pcm_pointer) | |
511 | return sof_ops(sdev)->pcm_pointer(sdev, substream); | |
512 | ||
513 | return 0; | |
514 | } | |
515 | ||
4a39ea3f RS |
516 | /* pcm ack */ |
517 | static inline int snd_sof_pcm_platform_ack(struct snd_sof_dev *sdev, | |
518 | struct snd_pcm_substream *substream) | |
519 | { | |
520 | if (sof_ops(sdev) && sof_ops(sdev)->pcm_ack) | |
521 | return sof_ops(sdev)->pcm_ack(sdev, substream); | |
522 | ||
523 | return 0; | |
524 | } | |
525 | ||
7f956297 RW |
526 | static inline u64 snd_sof_pcm_get_stream_position(struct snd_sof_dev *sdev, |
527 | struct snd_soc_component *component, | |
528 | struct snd_pcm_substream *substream) | |
529 | { | |
530 | if (sof_ops(sdev) && sof_ops(sdev)->get_stream_position) | |
531 | return sof_ops(sdev)->get_stream_position(sdev, component, substream); | |
532 | ||
533 | return 0; | |
534 | } | |
535 | ||
285880a2 DB |
536 | /* machine driver */ |
537 | static inline int | |
538 | snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata) | |
539 | { | |
540 | if (sof_ops(sdev) && sof_ops(sdev)->machine_register) | |
541 | return sof_ops(sdev)->machine_register(sdev, pdata); | |
542 | ||
543 | return 0; | |
544 | } | |
545 | ||
546 | static inline void | |
547 | snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) | |
548 | { | |
549 | if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister) | |
550 | sof_ops(sdev)->machine_unregister(sdev, pdata); | |
551 | } | |
552 | ||
cb515f10 | 553 | static inline struct snd_soc_acpi_mach * |
285880a2 DB |
554 | snd_sof_machine_select(struct snd_sof_dev *sdev) |
555 | { | |
556 | if (sof_ops(sdev) && sof_ops(sdev)->machine_select) | |
cb515f10 GL |
557 | return sof_ops(sdev)->machine_select(sdev); |
558 | ||
559 | return NULL; | |
285880a2 DB |
560 | } |
561 | ||
562 | static inline void | |
cb515f10 | 563 | snd_sof_set_mach_params(struct snd_soc_acpi_mach *mach, |
17e9d6b0 | 564 | struct snd_sof_dev *sdev) |
285880a2 | 565 | { |
285880a2 | 566 | if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params) |
17e9d6b0 | 567 | sof_ops(sdev)->set_mach_params(mach, sdev); |
285880a2 DB |
568 | } |
569 | ||
d1d95fcb LG |
570 | /** |
571 | * snd_sof_dsp_register_poll_timeout - Periodically poll an address | |
572 | * until a condition is met or a timeout occurs | |
573 | * @op: accessor function (takes @addr as its only argument) | |
574 | * @addr: Address to poll | |
575 | * @val: Variable to read the value into | |
576 | * @cond: Break condition (usually involving @val) | |
577 | * @sleep_us: Maximum time to sleep between reads in us (0 | |
578 | * tight-loops). Should be less than ~20ms since usleep_range | |
458f69ef | 579 | * is used (see Documentation/timers/timers-howto.rst). |
d1d95fcb LG |
580 | * @timeout_us: Timeout in us, 0 means never timeout |
581 | * | |
582 | * Returns 0 on success and -ETIMEDOUT upon a timeout. In either | |
583 | * case, the last read value at @addr is stored in @val. Must not | |
584 | * be called from atomic context if sleep_us or timeout_us are used. | |
585 | * | |
586 | * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. | |
587 | */ | |
588 | #define snd_sof_dsp_read_poll_timeout(sdev, bar, offset, val, cond, sleep_us, timeout_us) \ | |
589 | ({ \ | |
590 | u64 __timeout_us = (timeout_us); \ | |
591 | unsigned long __sleep_us = (sleep_us); \ | |
592 | ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ | |
593 | might_sleep_if((__sleep_us) != 0); \ | |
594 | for (;;) { \ | |
595 | (val) = snd_sof_dsp_read(sdev, bar, offset); \ | |
596 | if (cond) { \ | |
597 | dev_dbg(sdev->dev, \ | |
3b2e93ed KJ |
598 | "FW Poll Status: reg[%#x]=%#x successful\n", \ |
599 | (offset), (val)); \ | |
d1d95fcb LG |
600 | break; \ |
601 | } \ | |
602 | if (__timeout_us && \ | |
603 | ktime_compare(ktime_get(), __timeout) > 0) { \ | |
604 | (val) = snd_sof_dsp_read(sdev, bar, offset); \ | |
605 | dev_dbg(sdev->dev, \ | |
3b2e93ed KJ |
606 | "FW Poll Status: reg[%#x]=%#x timedout\n", \ |
607 | (offset), (val)); \ | |
d1d95fcb LG |
608 | break; \ |
609 | } \ | |
610 | if (__sleep_us) \ | |
611 | usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ | |
612 | } \ | |
613 | (cond) ? 0 : -ETIMEDOUT; \ | |
614 | }) | |
615 | ||
616 | /* This is for registers bits with attribute RWC */ | |
617 | bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset, | |
618 | u32 mask, u32 value); | |
619 | ||
620 | bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar, | |
621 | u32 offset, u32 mask, u32 value); | |
622 | ||
623 | bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar, | |
624 | u32 offset, u64 mask, u64 value); | |
625 | ||
626 | bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset, | |
627 | u32 mask, u32 value); | |
628 | ||
629 | bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar, | |
630 | u32 offset, u64 mask, u64 value); | |
631 | ||
632 | void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar, | |
633 | u32 offset, u32 mask, u32 value); | |
634 | ||
635 | int snd_sof_dsp_register_poll(struct snd_sof_dev *sdev, u32 bar, u32 offset, | |
636 | u32 mask, u32 target, u32 timeout_ms, | |
637 | u32 interval_us); | |
638 | ||
b2b10aa7 | 639 | void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset, bool non_recoverable); |
d1d95fcb | 640 | #endif |