|
10 | 10 | #include <rtos/panic.h> |
11 | 11 | #include <rtos/alloc.h> |
12 | 12 | #include <ipc/stream.h> |
| 13 | +#include <sof/audio/module_adapter/module/generic.h> |
| 14 | +#include <module/ipc4/base-config.h> |
| 15 | +#include <sof/audio/component.h> |
| 16 | +#include <module/module/base.h> |
13 | 17 | #include <sof/audio/audio_buffer.h> |
14 | 18 | #include <sof/audio/sink_api.h> |
15 | 19 | #include <sof/audio/source_api.h> |
@@ -182,12 +186,74 @@ int audio_buffer_source_set_alignment_constants(struct sof_source *source, |
182 | 186 | return 0; |
183 | 187 | } |
184 | 188 |
|
185 | | -/** |
186 | | - * this is stub, always return Last Feeding Time - 0, meaning "NOW" |
187 | | - */ |
188 | 189 | uint32_t audio_buffer_sink_get_lft(struct sof_sink *sink) |
189 | 190 | { |
190 | | - return 0; |
| 191 | + struct sof_audio_buffer *buffer = sof_audio_buffer_from_sink(sink); |
| 192 | + /* get number of ms in the buffer */ |
| 193 | + size_t bytes_per_sec = sink_get_frame_bytes(&buffer->_sink_api) * |
| 194 | + sink_get_rate(&buffer->_sink_api); |
| 195 | + size_t bytes_per_ms = bytes_per_sec / 1000; |
| 196 | + |
| 197 | + /* round up for frequencies like 44100 */ |
| 198 | + if (bytes_per_ms * 1000 != bytes_per_sec) |
| 199 | + bytes_per_ms++; |
| 200 | + uint32_t us_in_buffer = |
| 201 | + 1000 * source_get_data_available(&buffer->_source_api) / bytes_per_ms; |
| 202 | + |
| 203 | + return us_in_buffer; |
| 204 | + |
| 205 | + /* |
| 206 | + * TODO, Currently there's no DP to DP connection |
| 207 | + * >>> the code below is never accessible and won't work because of cache incoherence <<< |
| 208 | + * |
| 209 | + * to make DP to DP connection possible: |
| 210 | + * |
| 211 | + * 1) module data must be ALWAYS located in non cached memory alias, allowing |
| 212 | + * cross core access to params like period (needed below) and calling |
| 213 | + * module_get_deadline for the next module, regardless of cores the modules are |
| 214 | + * running on |
| 215 | + * 2) comp_buffer must be removed from all pipeline code, replaced with a generic abstract |
| 216 | + * class audio_buffer - allowing using comp_buffer and ring_buffer without current |
| 217 | + * "hybrid buffer" solution |
| 218 | + */ |
| 219 | + |
| 220 | + /* a module bound to source API - taking data from source - is data destination */ |
| 221 | + struct processing_module *data_consumer_mod = source_get_bound_module(&buffer->_source_api); |
| 222 | + /* a module bound to sink API - sending data to sink - is data source */ |
| 223 | + struct processing_module *data_producer_mod = sink_get_bound_module(&buffer->_sink_api); |
| 224 | + |
| 225 | + /* if no module connected to source - no data consumer, LFT is infinite. |
| 226 | + * use MAXINT / 2 to avoid any overflows in further calculations. |
| 227 | + * Zephyr cannot get deadline for a thread longer than MAXINT CPU cycles, much less |
| 228 | + * than the value in microseconds returned here |
| 229 | + */ |
| 230 | + if (!data_consumer_mod) |
| 231 | + return UINT_MAX / 2; |
| 232 | + |
| 233 | + /* in case there's no data producer (should never happen), LFT is NOW */ |
| 234 | + if (!data_producer_mod) |
| 235 | + return 0; |
| 236 | + |
| 237 | + /* if data receiver is LL module, the LFT is NOW + number of ms in buffer */ |
| 238 | + if (data_consumer_mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) |
| 239 | + return us_in_buffer; |
| 240 | + |
| 241 | + /* destination is DP. calculate correction of deadline if period of data provider module is |
| 242 | + * shorter than consumer module |
| 243 | + */ |
| 244 | + int32_t deadline_correction = 0; |
| 245 | + |
| 246 | + if (data_consumer_mod->dev->period < data_producer_mod->dev->period) { |
| 247 | + deadline_correction = (data_consumer_mod->dev->period - us_in_buffer) / |
| 248 | + data_producer_mod->dev->period; |
| 249 | + if (deadline_correction < 0) |
| 250 | + deadline_correction = 0; |
| 251 | + else |
| 252 | + deadline_correction = |
| 253 | + module_get_LPT(data_producer_mod) * deadline_correction; |
| 254 | + } |
| 255 | + |
| 256 | + return us_in_buffer + module_get_deadline(data_producer_mod) - deadline_correction; |
191 | 257 | } |
192 | 258 |
|
193 | 259 | void audio_buffer_init(struct sof_audio_buffer *buffer, uint32_t buffer_type, bool is_shared, |
|
0 commit comments