1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2016 Intel Corporation. All rights reserved.
4  *
5  * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6  */
7 
8 #ifndef __SOF_LIB_NOTIFIER_H__
9 #define __SOF_LIB_NOTIFIER_H__
10 
11 #include <sof/bit.h>
12 #include <sof/list.h>
13 #include <sof/spinlock.h>
14 #include <sof/sof.h>
15 #include <stdint.h>
16 
17 /* notifier target core masks */
18 #define NOTIFIER_TARGET_CORE_MASK(x)	(1 << (x))
19 #define NOTIFIER_TARGET_CORE_LOCAL	NOTIFIER_TARGET_CORE_MASK(cpu_get_id())
20 #define NOTIFIER_TARGET_CORE_ALL_MASK	0xFFFFFFFF
21 
22 /** \brief Notifier flags. */
23 #define NOTIFIER_FLAG_AGGREGATE		BIT(0)
24 
25 enum notify_id {
26 	NOTIFIER_ID_CPU_FREQ = 0,		/* struct clock_notify_data * */
27 	NOTIFIER_ID_SSP_FREQ,			/* struct clock_notify_data * */
28 	NOTIFIER_ID_KPB_CLIENT_EVT,		/* struct kpb_event_data * */
29 	NOTIFIER_ID_DMA_DOMAIN_CHANGE,		/* struct dma_chan_data * */
30 	NOTIFIER_ID_BUFFER_PRODUCE,		/* struct buffer_cb_transact* */
31 	NOTIFIER_ID_BUFFER_CONSUME,		/* struct buffer_cb_transact* */
32 	NOTIFIER_ID_BUFFER_FREE,		/* struct buffer_cb_free* */
33 	NOTIFIER_ID_DMA_COPY,			/* struct dma_cb_data* */
34 	NOTIFIER_ID_LL_POST_RUN,		/* NULL */
35 	NOTIFIER_ID_DMA_IRQ,			/* struct dma_chan_data * */
36 	NOTIFIER_ID_DAI_TRIGGER,		/* struct dai_group * */
37 	NOTIFIER_ID_COUNT
38 };
39 
40 struct notify {
41 	struct list_item list[NOTIFIER_ID_COUNT]; /* list of callback handles */
42 	spinlock_t lock;	/* list lock */
43 };
44 
45 struct notify_data {
46 	const void *caller;
47 	enum notify_id type;
48 	uint32_t data_size;
49 	void *data;
50 };
51 
52 #ifdef CLK_SSP
53 #define NOTIFIER_CLK_CHANGE_ID(clk) \
54 	((clk) == CLK_SSP ? NOTIFIER_ID_SSP_FREQ : NOTIFIER_ID_CPU_FREQ)
55 #else
56 #define NOTIFIER_CLK_CHANGE_ID(clk) NOTIFIER_ID_CPU_FREQ
57 #endif
58 
59 struct notify **arch_notify_get(void);
60 
61 /** Register a callback to be run when event 'type' happens.
62  *
63  * The identifier for un-registration is the tuple (receiver_data,
64  * caller_id_filter, event_type), the callback argument is not part of
65  * it.
66  *
67  * caller_data argument from notifier_event()
68  *
69  * @param receiver_data private data passed to the callback.
70  * @param caller_id_filter optional, can be used to be notified only by
71  * some specific notifier_event() calls when not NULL.
72  * @param event_type list of callbacks to be added to
73  * @param callback callback function
74  * @param flags see NOTIFIER_FLAG_* above
75  */
76 int notifier_register(void *receiver_data, void *caller_id_filter, enum notify_id event_type,
77 		      void (*callback)(void *receiver_data, enum notify_id event_type,
78 				       void *caller_data),
79 		      uint32_t flags);
80 
81 /** Unregister all callbacks matching that arguments tuple. NULL acts
82  * as a wildcard.
83  */
84 void notifier_unregister(void *receiver_data_filter, void *caller_id_filter, enum notify_id type);
85 
86 /** Unregister callbacks matching the arguments for every notify_id.
87  *  A NULL parameter acts as a wildcard.
88  */
89 void notifier_unregister_all(void *receiver_data_filter, void *caller_id_filter);
90 
91 void notifier_notify_remote(void);
92 
93 /* data_size is required to manage cache coherency for notifications
94  * across cores.
95  */
96 void notifier_event(const void *caller_id, enum notify_id event_type, uint32_t core_mask,
97 		    void *caller_data, uint32_t data_size);
98 
99 void init_system_notify(struct sof *sof);
100 
101 void free_system_notify(void);
102 
notify_data_get(void)103 static inline struct notify_data *notify_data_get(void)
104 {
105 	return sof_get()->notify_data;
106 }
107 
108 #endif /* __SOF_LIB_NOTIFIER_H__ */
109