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