1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019 Intel Corporation. All rights reserved.
4  *
5  * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com>
6  */
7 
8 #ifndef __SOF_AUDIO_KPB_H__
9 #define __SOF_AUDIO_KPB_H__
10 
11 #include <sof/trace/trace.h>
12 #include <user/trace.h>
13 #include <stdint.h>
14 
15 struct comp_buffer;
16 
17 /* KPB internal defines */
18 
19 #ifdef CONFIG_TIGERLAKE
20 #define KPB_MAX_BUFF_TIME 3000 /**< time of buffering in miliseconds */
21 #define HOST_WAKEUP_TIME 1000 /* aprox. time of host DMA wakup from suspend [ms] */
22 #else
23 /** Due to memory constraints on non-TGL platforms, the buffers are smaller. */
24 #define KPB_MAX_BUFF_TIME 2100 /**< time of buffering in miliseconds */
25 #define HOST_WAKEUP_TIME 0 /* aprox. time of host DMA wakup from suspend [ms] */
26 #endif
27 
28 #define KPB_MAX_DRAINING_REQ (KPB_MAX_BUFF_TIME - HOST_WAKEUP_TIME)
29 #define KPB_MAX_SUPPORTED_CHANNELS 2 /**< number of supported channels */
30 /**< number of samples taken each milisecond */
31 #define	KPB_SAMPLES_PER_MS (KPB_SAMPLNG_FREQUENCY / 1000)
32 #define	KPB_SAMPLNG_FREQUENCY 16000 /**< supported sampling frequency in Hz */
33 #define KPB_NUM_OF_CHANNELS 2
34 #define KPB_SAMPLE_CONTAINER_SIZE(sw) ((sw == 16) ? 16 : 32)
35 #define KPB_MAX_BUFFER_SIZE(sw) ((KPB_SAMPLNG_FREQUENCY / 1000) * \
36 	(KPB_SAMPLE_CONTAINER_SIZE(sw) / 8) * KPB_MAX_BUFF_TIME * \
37 	KPB_NUM_OF_CHANNELS)
38 #define KPB_MAX_NO_OF_CLIENTS 2
39 #define KPB_NO_OF_HISTORY_BUFFERS 2 /**< no of internal buffers */
40 #define KPB_ALLOCATION_STEP 0x100
41 #define KPB_NO_OF_MEM_POOLS 3
42 #define KPB_BYTES_TO_FRAMES(bytes, sample_width) \
43 	(bytes / ((KPB_SAMPLE_CONTAINER_SIZE(sample_width) / 8) * \
44 	KPB_NUM_OF_CHANNELS))
45 /**< Defines how much faster draining is in comparison to pipeline copy. */
46 #define KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE 2
47 /**< Host buffer shall be at least two times bigger than history buffer. */
48 #define HOST_BUFFER_MIN_SIZE(hb) (hb * 2)
49 
50 /** All states below as well as relations between them are documented in
51  * the sof-dosc in [kpbm-state-diagram]
52  * Therefore any addition of new states or modification of existing ones
53  * should have a corresponding update in the sof-docs.
54  * [kpbm-state-diagram]:
55 https://thesofproject.github.io/latest/developer_guides/firmware/kd_integration/kd-integration.html#kpbm-state-diagram
56 "Keyphrase buffer manager state diagram"
57  */
58 enum kpb_state {
59 	KPB_STATE_DISABLED = 0,
60 	KPB_STATE_RESET_FINISHING,
61 	KPB_STATE_CREATED,
62 	KPB_STATE_PREPARING,
63 	KPB_STATE_RUN,
64 	KPB_STATE_BUFFERING,
65 	KPB_STATE_INIT_DRAINING,
66 	KPB_STATE_DRAINING,
67 	KPB_STATE_HOST_COPY,
68 	KPB_STATE_RESETTING,
69 };
70 
71 enum kpb_event {
72 	KPB_EVENT_REGISTER_CLIENT = 0,
73 	KPB_EVENT_UPDATE_PARAMS,
74 	KPB_EVENT_BEGIN_DRAINING,
75 	KPB_EVENT_STOP_DRAINING,
76 	KPB_EVENT_UNREGISTER_CLIENT,
77 };
78 
79 struct kpb_event_data {
80 	enum kpb_event event_id;
81 	struct kpb_client *client_data;
82 };
83 
84 enum kpb_client_state {
85 	KPB_CLIENT_UNREGISTERED = 0,
86 	KPB_CLIENT_BUFFERING,
87 	KPB_CLIENT_DRAINNING,
88 	KPB_CLIENT_DRAINNING_OD, /**< draining on demand */
89 };
90 
91 struct kpb_client {
92 	uint8_t id; /**< id associated with output sink */
93 	uint32_t drain_req; /**< normalized value of buffered bytes */
94 	enum kpb_client_state state; /**< current state of a client */
95 	void *r_ptr; /**< current read position */
96 	struct comp_buffer *sink; /**< client's sink */
97 };
98 
99 enum buffer_state {
100 	KPB_BUFFER_FREE = 0,
101 	KPB_BUFFER_FULL,
102 	KPB_BUFFER_OFF,
103 };
104 
105 enum kpb_id {
106 	KPB_LP = 0,
107 	KPB_HP,
108 };
109 
110 struct history_buffer {
111 	enum buffer_state state; /**< state of the buffer */
112 	void *start_addr; /**< buffer start address */
113 	void *end_addr; /**< buffer end address */
114 	void *w_ptr; /**< buffer write pointer */
115 	void *r_ptr; /**< buffer read pointer */
116 	struct history_buffer *next; /**< next history buffer */
117 	struct history_buffer *prev; /**< next history buffer */
118 };
119 
120 /* Draining task data */
121 struct draining_data {
122 	struct comp_buffer *sink;
123 	struct history_buffer *hb;
124 	size_t drain_req;
125 	uint8_t is_draining_active;
126 	size_t sample_width;
127 	size_t buffered_while_draining;
128 	size_t drain_interval;
129 	size_t pb_limit; /**< Period bytes limit */
130 	struct comp_dev *dev;
131 	bool sync_mode_on;
132 	enum comp_copy_type copy_type;
133 };
134 
135 struct history_data {
136 	size_t buffer_size; /**< size of internal history buffer */
137 	size_t buffered; /**< amount of buffered data */
138 	size_t free; /** spce we can use to write new data */
139 	struct history_buffer *c_hb; /**< current buffer used for writing */
140 };
141 
142 #ifdef UNIT_TEST
143 void sys_comp_kpb_init(void);
144 #endif
145 
146 #endif /* __SOF_AUDIO_KPB_H__ */
147