Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
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
24/* Mandatory operations are verified during probing */
25
26/* init */
27static inline int snd_sof_probe(struct snd_sof_dev *sdev)
28{
29 return sof_ops(sdev)->probe(sdev);
30}
31
32static inline int snd_sof_remove(struct snd_sof_dev *sdev)
33{
34 if (sof_ops(sdev)->remove)
35 return sof_ops(sdev)->remove(sdev);
36
37 return 0;
38}
39
40static inline int snd_sof_shutdown(struct snd_sof_dev *sdev)
41{
42 if (sof_ops(sdev)->shutdown)
43 return sof_ops(sdev)->shutdown(sdev);
44
45 return 0;
46}
47
48/* control */
49
50/*
51 * snd_sof_dsp_run returns the core mask of the cores that are available
52 * after successful fw boot
53 */
54static inline int snd_sof_dsp_run(struct snd_sof_dev *sdev)
55{
56 return sof_ops(sdev)->run(sdev);
57}
58
59static inline int snd_sof_dsp_stall(struct snd_sof_dev *sdev, unsigned int core_mask)
60{
61 if (sof_ops(sdev)->stall)
62 return sof_ops(sdev)->stall(sdev, core_mask);
63
64 return 0;
65}
66
67static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
68{
69 if (sof_ops(sdev)->reset)
70 return sof_ops(sdev)->reset(sdev);
71
72 return 0;
73}
74
75/* dsp core power up/power down */
76static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev,
77 unsigned int core_mask)
78{
79 int ret = 0;
80
81 core_mask &= ~sdev->enabled_cores_mask;
82 if (sof_ops(sdev)->core_power_up && core_mask) {
83 ret = sof_ops(sdev)->core_power_up(sdev, core_mask);
84 if (!ret)
85 sdev->enabled_cores_mask |= core_mask;
86 }
87
88 return ret;
89}
90
91static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev,
92 unsigned int core_mask)
93{
94 int ret = 0;
95
96 core_mask &= sdev->enabled_cores_mask;
97 if (sof_ops(sdev)->core_power_down && core_mask) {
98 ret = sof_ops(sdev)->core_power_down(sdev, core_mask);
99 if (!ret)
100 sdev->enabled_cores_mask &= ~core_mask;
101 }
102
103 return ret;
104}
105
106/* pre/post fw load */
107static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev)
108{
109 if (sof_ops(sdev)->pre_fw_run)
110 return sof_ops(sdev)->pre_fw_run(sdev);
111
112 return 0;
113}
114
115static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev)
116{
117 if (sof_ops(sdev)->post_fw_run)
118 return sof_ops(sdev)->post_fw_run(sdev);
119
120 return 0;
121}
122
123/* parse platform specific extended manifest */
124static inline int snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev *sdev,
125 const struct sof_ext_man_elem_header *hdr)
126{
127 if (sof_ops(sdev)->parse_platform_ext_manifest)
128 return sof_ops(sdev)->parse_platform_ext_manifest(sdev, hdr);
129
130 return 0;
131}
132
133/* misc */
134
135/**
136 * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index
137 *
138 * @sdev: sof device
139 * @type: section type as described by snd_sof_fw_blk_type
140 *
141 * Returns the corresponding BAR index (a positive integer) or -EINVAL
142 * in case there is no mapping
143 */
144static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
145{
146 if (sof_ops(sdev)->get_bar_index)
147 return sof_ops(sdev)->get_bar_index(sdev, type);
148
149 return sdev->mmio_bar;
150}
151
152static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev)
153{
154 if (sof_ops(sdev)->get_mailbox_offset)
155 return sof_ops(sdev)->get_mailbox_offset(sdev);
156
157 dev_err(sdev->dev, "error: %s not defined\n", __func__);
158 return -ENOTSUPP;
159}
160
161static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev,
162 u32 id)
163{
164 if (sof_ops(sdev)->get_window_offset)
165 return sof_ops(sdev)->get_window_offset(sdev, id);
166
167 dev_err(sdev->dev, "error: %s not defined\n", __func__);
168 return -ENOTSUPP;
169}
170/* power management */
171static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev)
172{
173 if (sof_ops(sdev)->resume)
174 return sof_ops(sdev)->resume(sdev);
175
176 return 0;
177}
178
179static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev,
180 u32 target_state)
181{
182 if (sof_ops(sdev)->suspend)
183 return sof_ops(sdev)->suspend(sdev, target_state);
184
185 return 0;
186}
187
188static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev)
189{
190 if (sof_ops(sdev)->runtime_resume)
191 return sof_ops(sdev)->runtime_resume(sdev);
192
193 return 0;
194}
195
196static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev)
197{
198 if (sof_ops(sdev)->runtime_suspend)
199 return sof_ops(sdev)->runtime_suspend(sdev);
200
201 return 0;
202}
203
204static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev)
205{
206 if (sof_ops(sdev)->runtime_idle)
207 return sof_ops(sdev)->runtime_idle(sdev);
208
209 return 0;
210}
211
212static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
213{
214 if (sof_ops(sdev)->set_hw_params_upon_resume)
215 return sof_ops(sdev)->set_hw_params_upon_resume(sdev);
216 return 0;
217}
218
219static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
220{
221 if (sof_ops(sdev)->set_clk)
222 return sof_ops(sdev)->set_clk(sdev, freq);
223
224 return 0;
225}
226
227static inline int
228snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
229 const struct sof_dsp_power_state *target_state)
230{
231 int ret = 0;
232
233 mutex_lock(&sdev->power_state_access);
234
235 if (sof_ops(sdev)->set_power_state)
236 ret = sof_ops(sdev)->set_power_state(sdev, target_state);
237
238 mutex_unlock(&sdev->power_state_access);
239
240 return ret;
241}
242
243/* debug */
244void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, u32 flags);
245
246static inline int snd_sof_debugfs_add_region_item(struct snd_sof_dev *sdev,
247 enum snd_sof_fw_blk_type blk_type, u32 offset, size_t size,
248 const char *name, enum sof_debugfs_access_type access_type)
249{
250 if (sof_ops(sdev) && sof_ops(sdev)->debugfs_add_region_item)
251 return sof_ops(sdev)->debugfs_add_region_item(sdev, blk_type, offset,
252 size, name, access_type);
253
254 return 0;
255}
256
257/* register IO */
258static inline void snd_sof_dsp_write(struct snd_sof_dev *sdev, u32 bar,
259 u32 offset, u32 value)
260{
261 if (sof_ops(sdev)->write) {
262 sof_ops(sdev)->write(sdev, sdev->bar[bar] + offset, value);
263 return;
264 }
265
266 dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
267}
268
269static inline void snd_sof_dsp_write64(struct snd_sof_dev *sdev, u32 bar,
270 u32 offset, u64 value)
271{
272 if (sof_ops(sdev)->write64) {
273 sof_ops(sdev)->write64(sdev, sdev->bar[bar] + offset, value);
274 return;
275 }
276
277 dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
278}
279
280static inline u32 snd_sof_dsp_read(struct snd_sof_dev *sdev, u32 bar,
281 u32 offset)
282{
283 if (sof_ops(sdev)->read)
284 return sof_ops(sdev)->read(sdev, sdev->bar[bar] + offset);
285
286 dev_err(sdev->dev, "error: %s not defined\n", __func__);
287 return -ENOTSUPP;
288}
289
290static inline u64 snd_sof_dsp_read64(struct snd_sof_dev *sdev, u32 bar,
291 u32 offset)
292{
293 if (sof_ops(sdev)->read64)
294 return sof_ops(sdev)->read64(sdev, sdev->bar[bar] + offset);
295
296 dev_err(sdev->dev, "error: %s not defined\n", __func__);
297 return -ENOTSUPP;
298}
299
300/* block IO */
301static inline int snd_sof_dsp_block_read(struct snd_sof_dev *sdev,
302 enum snd_sof_fw_blk_type blk_type,
303 u32 offset, void *dest, size_t bytes)
304{
305 return sof_ops(sdev)->block_read(sdev, blk_type, offset, dest, bytes);
306}
307
308static inline int snd_sof_dsp_block_write(struct snd_sof_dev *sdev,
309 enum snd_sof_fw_blk_type blk_type,
310 u32 offset, void *src, size_t bytes)
311{
312 return sof_ops(sdev)->block_write(sdev, blk_type, offset, src, bytes);
313}
314
315/* mailbox IO */
316static inline void snd_sof_dsp_mailbox_read(struct snd_sof_dev *sdev,
317 u32 offset, void *dest, size_t bytes)
318{
319 if (sof_ops(sdev)->mailbox_read)
320 sof_ops(sdev)->mailbox_read(sdev, offset, dest, bytes);
321}
322
323static inline void snd_sof_dsp_mailbox_write(struct snd_sof_dev *sdev,
324 u32 offset, void *src, size_t bytes)
325{
326 if (sof_ops(sdev)->mailbox_write)
327 sof_ops(sdev)->mailbox_write(sdev, offset, src, bytes);
328}
329
330/* ipc */
331static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev,
332 struct snd_sof_ipc_msg *msg)
333{
334 return sof_ops(sdev)->send_msg(sdev, msg);
335}
336
337/* host DMA trace */
338static inline int snd_sof_dma_trace_init(struct snd_sof_dev *sdev,
339 u32 *stream_tag)
340{
341 if (sof_ops(sdev)->trace_init)
342 return sof_ops(sdev)->trace_init(sdev, stream_tag);
343
344 return 0;
345}
346
347static inline int snd_sof_dma_trace_release(struct snd_sof_dev *sdev)
348{
349 if (sof_ops(sdev)->trace_release)
350 return sof_ops(sdev)->trace_release(sdev);
351
352 return 0;
353}
354
355static inline int snd_sof_dma_trace_trigger(struct snd_sof_dev *sdev, int cmd)
356{
357 if (sof_ops(sdev)->trace_trigger)
358 return sof_ops(sdev)->trace_trigger(sdev, cmd);
359
360 return 0;
361}
362
363/* host PCM ops */
364static inline int
365snd_sof_pcm_platform_open(struct snd_sof_dev *sdev,
366 struct snd_pcm_substream *substream)
367{
368 if (sof_ops(sdev) && sof_ops(sdev)->pcm_open)
369 return sof_ops(sdev)->pcm_open(sdev, substream);
370
371 return 0;
372}
373
374/* disconnect pcm substream to a host stream */
375static inline int
376snd_sof_pcm_platform_close(struct snd_sof_dev *sdev,
377 struct snd_pcm_substream *substream)
378{
379 if (sof_ops(sdev) && sof_ops(sdev)->pcm_close)
380 return sof_ops(sdev)->pcm_close(sdev, substream);
381
382 return 0;
383}
384
385/* host stream hw params */
386static inline int
387snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
388 struct snd_pcm_substream *substream,
389 struct snd_pcm_hw_params *params,
390 struct sof_ipc_stream_params *ipc_params)
391{
392 if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params)
393 return sof_ops(sdev)->pcm_hw_params(sdev, substream,
394 params, ipc_params);
395
396 return 0;
397}
398
399/* host stream hw free */
400static inline int
401snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
402 struct snd_pcm_substream *substream)
403{
404 if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
405 return sof_ops(sdev)->pcm_hw_free(sdev, substream);
406
407 return 0;
408}
409
410/* host stream trigger */
411static inline int
412snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
413 struct snd_pcm_substream *substream, int cmd)
414{
415 if (sof_ops(sdev) && sof_ops(sdev)->pcm_trigger)
416 return sof_ops(sdev)->pcm_trigger(sdev, substream, cmd);
417
418 return 0;
419}
420
421/* Firmware loading */
422static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev)
423{
424 dev_dbg(sdev->dev, "loading firmware\n");
425
426 return sof_ops(sdev)->load_firmware(sdev);
427}
428
429/* host DSP message data */
430static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
431 struct snd_pcm_substream *substream,
432 void *p, size_t sz)
433{
434 return sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
435}
436
437/* host configure DSP HW parameters */
438static inline int
439snd_sof_ipc_pcm_params(struct snd_sof_dev *sdev,
440 struct snd_pcm_substream *substream,
441 const struct sof_ipc_pcm_params_reply *reply)
442{
443 return sof_ops(sdev)->ipc_pcm_params(sdev, substream, reply);
444}
445
446/* host stream pointer */
447static inline snd_pcm_uframes_t
448snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
449 struct snd_pcm_substream *substream)
450{
451 if (sof_ops(sdev) && sof_ops(sdev)->pcm_pointer)
452 return sof_ops(sdev)->pcm_pointer(sdev, substream);
453
454 return 0;
455}
456
457#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
458static inline int
459snd_sof_probe_compr_assign(struct snd_sof_dev *sdev,
460 struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
461{
462 return sof_ops(sdev)->probe_assign(sdev, cstream, dai);
463}
464
465static inline int
466snd_sof_probe_compr_free(struct snd_sof_dev *sdev,
467 struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
468{
469 return sof_ops(sdev)->probe_free(sdev, cstream, dai);
470}
471
472static inline int
473snd_sof_probe_compr_set_params(struct snd_sof_dev *sdev,
474 struct snd_compr_stream *cstream,
475 struct snd_compr_params *params, struct snd_soc_dai *dai)
476{
477 return sof_ops(sdev)->probe_set_params(sdev, cstream, params, dai);
478}
479
480static inline int
481snd_sof_probe_compr_trigger(struct snd_sof_dev *sdev,
482 struct snd_compr_stream *cstream, int cmd,
483 struct snd_soc_dai *dai)
484{
485 return sof_ops(sdev)->probe_trigger(sdev, cstream, cmd, dai);
486}
487
488static inline int
489snd_sof_probe_compr_pointer(struct snd_sof_dev *sdev,
490 struct snd_compr_stream *cstream,
491 struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai)
492{
493 if (sof_ops(sdev) && sof_ops(sdev)->probe_pointer)
494 return sof_ops(sdev)->probe_pointer(sdev, cstream, tstamp, dai);
495
496 return 0;
497}
498#endif
499
500/* machine driver */
501static inline int
502snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
503{
504 if (sof_ops(sdev) && sof_ops(sdev)->machine_register)
505 return sof_ops(sdev)->machine_register(sdev, pdata);
506
507 return 0;
508}
509
510static inline void
511snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata)
512{
513 if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister)
514 sof_ops(sdev)->machine_unregister(sdev, pdata);
515}
516
517static inline void
518snd_sof_machine_select(struct snd_sof_dev *sdev)
519{
520 if (sof_ops(sdev) && sof_ops(sdev)->machine_select)
521 sof_ops(sdev)->machine_select(sdev);
522}
523
524static inline void
525snd_sof_set_mach_params(const struct snd_soc_acpi_mach *mach,
526 struct snd_sof_dev *sdev)
527{
528 if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params)
529 sof_ops(sdev)->set_mach_params(mach, sdev);
530}
531
532/**
533 * snd_sof_dsp_register_poll_timeout - Periodically poll an address
534 * until a condition is met or a timeout occurs
535 * @op: accessor function (takes @addr as its only argument)
536 * @addr: Address to poll
537 * @val: Variable to read the value into
538 * @cond: Break condition (usually involving @val)
539 * @sleep_us: Maximum time to sleep between reads in us (0
540 * tight-loops). Should be less than ~20ms since usleep_range
541 * is used (see Documentation/timers/timers-howto.rst).
542 * @timeout_us: Timeout in us, 0 means never timeout
543 *
544 * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
545 * case, the last read value at @addr is stored in @val. Must not
546 * be called from atomic context if sleep_us or timeout_us are used.
547 *
548 * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
549 */
550#define snd_sof_dsp_read_poll_timeout(sdev, bar, offset, val, cond, sleep_us, timeout_us) \
551({ \
552 u64 __timeout_us = (timeout_us); \
553 unsigned long __sleep_us = (sleep_us); \
554 ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
555 might_sleep_if((__sleep_us) != 0); \
556 for (;;) { \
557 (val) = snd_sof_dsp_read(sdev, bar, offset); \
558 if (cond) { \
559 dev_dbg(sdev->dev, \
560 "FW Poll Status: reg[%#x]=%#x successful\n", \
561 (offset), (val)); \
562 break; \
563 } \
564 if (__timeout_us && \
565 ktime_compare(ktime_get(), __timeout) > 0) { \
566 (val) = snd_sof_dsp_read(sdev, bar, offset); \
567 dev_dbg(sdev->dev, \
568 "FW Poll Status: reg[%#x]=%#x timedout\n", \
569 (offset), (val)); \
570 break; \
571 } \
572 if (__sleep_us) \
573 usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
574 } \
575 (cond) ? 0 : -ETIMEDOUT; \
576})
577
578/* This is for registers bits with attribute RWC */
579bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,
580 u32 mask, u32 value);
581
582bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,
583 u32 offset, u32 mask, u32 value);
584
585bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,
586 u32 offset, u64 mask, u64 value);
587
588bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,
589 u32 mask, u32 value);
590
591bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar,
592 u32 offset, u64 mask, u64 value);
593
594void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,
595 u32 offset, u32 mask, u32 value);
596
597int snd_sof_dsp_register_poll(struct snd_sof_dev *sdev, u32 bar, u32 offset,
598 u32 mask, u32 target, u32 timeout_ms,
599 u32 interval_us);
600
601void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset);
602#endif