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