Skip to content

Commit b3b7c89

Browse files
move stuff moved out of dai-zephyr.c
Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
1 parent d8abafa commit b3b7c89

3 files changed

Lines changed: 130 additions & 1 deletion

File tree

src/audio/dai-zephyr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ int dai_get_uaol_stream_id(struct dai *dai, int *uaol_link_id, int *uaol_stream_
298298
return 0;
299299
}
300300
#endif /* CONFIG_DAI_INTEL_UAOL */
301-
#endif // 0
302301

303302
static void process_uaol_feedback(struct comp_dev *dev, struct dai_data *dd)
304303
{
@@ -420,6 +419,7 @@ static int uaol_dma_buffer_copy_to(struct dai_data *dd, size_t bytes)
420419

421420
return ret;
422421
}
422+
#endif //0
423423

424424
/* this is called by DMA driver every time descriptor has completed */
425425
static enum sof_dma_cb_status

src/audio/uaol.c

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,124 @@ int dai_get_uaol_stream_id(struct dai *dai, int *uaol_link_id, int *uaol_stream_
106106

107107
return 0;
108108
}
109+
110+
void process_uaol_feedback(struct comp_dev *dev, struct dai_data *dd)
111+
{
112+
assert(dd && dd->uaol.fb_chan_idx >= 0 && dd->uaol.fb_dma_buf);
113+
///assert(dev->direction == SOF_IPC_STREAM_PLAYBACK);
114+
115+
struct dma_status stat = {0};
116+
int ret = sof_dma_get_status(dd->dma, dd->uaol.fb_chan_idx, &stat);
117+
if (ret) {
118+
comp_err(dev, "Failed to get UAOL feedback DMA status: %d", ret);
119+
return;
120+
}
121+
122+
if (stat.pending_length < 4) {
123+
/* TODO: That's a normal case, remove this comp_dbg() ??? */
124+
comp_dbg(dev, "Not enough data in UAOL feedback buffer: %d bytes", stat.pending_length);
125+
return;
126+
}
127+
128+
assert(dd->uaol.fb_dma_buf_size >= 4);
129+
if (stat.read_position < 0 || stat.read_position > dd->uaol.fb_dma_buf_size - 4) {
130+
comp_err(dev, "Invalid read position in UAOL feedback buffer: %d", stat.read_position);
131+
return;
132+
}
133+
134+
/* Use uncached pointer to read DMA buffer */
135+
assert(is_uncached(dd->uaol.fb_dma_buf));
136+
137+
/* NOTE: Not all DMA drivers populate stat.write_position. Intel ACE HDA does. */
138+
assert(stat.write_position & 3 == 0); /* 4-byte alignment check. */
139+
/* Read the last received 4 bytes (ignore older ones if any). */
140+
int last_4_bytes_pos = stat.write_position >= 4 ? (stat.write_position - 4) :
141+
(dd->uaol.fb_dma_buf_size - 4);
142+
uint32_t feedback_value = dd->uaol.fb_dma_buf[last_4_bytes_pos / 4];
143+
144+
ret = sof_dma_reload(dd->dma, dd->uaol.fb_chan_idx, stat.pending_length);
145+
if (ret < 0) {
146+
comp_err(dev, "Failed to reload UAOL feedback DMA: %d, pending_length: %d",
147+
ret, stat.pending_length);
148+
return;
149+
}
150+
151+
comp_dbg(dev, "UAOL feedback value: %u", feedback_value);
152+
153+
const struct device *uaol_zdev = get_uaol_zdevice(dd->uaol.link_id);
154+
int freq = uaol_interpret_feedback_value(uaol_zdev, dd->uaol.stream_id, feedback_value);
155+
156+
if (freq < 0) {
157+
comp_err(dev, "Bad unexpected feedback freq value: %d", freq);
158+
return;
159+
}
160+
161+
/* Let's limit the maximum drift to a reasonable value to prevent significant audio distortion
162+
* when, for some reason, the reported drift is quite big.
163+
*/
164+
#define MAX_UAOL_DRIFT_HZ 6
165+
166+
int drift = freq - dd->ipc_config.sampling_frequency;
167+
if (drift < -MAX_UAOL_DRIFT_HZ || drift > MAX_UAOL_DRIFT_HZ) {
168+
comp_warn(dev, "Too much/unreasonable UAOL feedback freq value: %d, drift: %d", freq, drift);
169+
return;
170+
}
171+
172+
dd->uaol.feedback_drift = drift;
173+
if (dd->uaol.feedback_drift > 0)
174+
dsrc_set_rate(&dd->uaol.dsrc, dd->ipc_config.sampling_frequency, freq);
175+
}
176+
177+
void adjust_uaol_rate(const struct dai_data *dd, bool increase)
178+
{
179+
const struct device *uaol_zdev = get_uaol_zdevice(dd->uaol.link_id);
180+
int ret = uaol_adjust_rate(uaol_zdev, dd->uaol.stream_id, increase);
181+
182+
if (ret != 0)
183+
comp_err(dd->dai_dev, "Failed to adjust UAOL rate: %d", ret);
184+
}
185+
186+
int uaol_dma_buffer_copy_to(struct dai_data *dd, size_t bytes)
187+
{
188+
int ret = 0;
189+
190+
assert(dd->uaol.feedback_drift != 0);
191+
192+
if (dd->uaol.feedback_drift > 0) {
193+
buffer_stream_invalidate(dd->local_buffer, bytes);
194+
195+
struct cir_buf_ptr in = { dd->local_buffer->stream.addr,
196+
dd->local_buffer->stream.end_addr, dd->local_buffer->stream.r_ptr };
197+
assert(dd->uaol.dsrc_buf);
198+
struct cir_buf_ptr out = { dd->uaol.dsrc_buf->stream.addr,
199+
dd->uaol.dsrc_buf->stream.end_addr, dd->uaol.dsrc_buf->stream.w_ptr };
200+
size_t frames = bytes / audio_stream_frame_bytes(&dd->local_buffer->stream);
201+
202+
size_t added_frames = dsrc_process(&dd->uaol.dsrc, &in, &out, frames);
203+
size_t added_bytes = added_frames * audio_stream_frame_bytes(&dd->local_buffer->stream);
204+
205+
comp_update_buffer_consume(dd->local_buffer, bytes);
206+
audio_stream_produce(&dd->uaol.dsrc_buf->stream, bytes + added_bytes);
207+
208+
if (added_frames)
209+
adjust_uaol_rate(dd, true);
210+
211+
size_t extra_bytes = added_frames * audio_stream_frame_bytes(&dd->dma_buffer->stream);
212+
ret = dma_buffer_copy_to(dd->uaol.dsrc_buf, dd->dma_buffer,
213+
dd->process, bytes + extra_bytes, dd->chmap);
214+
} else if (dd->uaol.feedback_drift < 0) {
215+
assert(dd->uaol.feedback_drift <= -1 && dd->uaol.feedback_drift >= -1000);
216+
dd->uaol.ms_since_last_adjustment++;
217+
if (-1000 / dd->uaol.feedback_drift >= dd->uaol.ms_since_last_adjustment) {
218+
dd->uaol.ms_since_last_adjustment = 0;
219+
adjust_uaol_rate(dd, false);
220+
}
221+
222+
ret = dma_buffer_copy_to(dd->local_buffer, dd->dma_buffer,
223+
dd->process, bytes, dd->chmap);
224+
} else {
225+
return -EINVAL;
226+
}
227+
228+
return ret;
229+
}

src/include/sof/audio/uaol.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,15 @@ const struct device *get_uaol_zdevice(int uaol_link_id);
2525
/************************************ moved from dai-zephyr.c **********************************/
2626

2727
struct dai;
28+
struct comp_dev;
29+
struct dai_data;
2830

2931
int dai_get_uaol_stream_id(struct dai *dai, int *uaol_link_id, int *uaol_stream_id);
3032

33+
void process_uaol_feedback(struct comp_dev *dev, struct dai_data *dd);
34+
35+
void adjust_uaol_rate(const struct dai_data *dd, bool increase);
36+
37+
int uaol_dma_buffer_copy_to(struct dai_data *dd, size_t bytes);
38+
3139
#endif /* __SOF_AUDIO_UAOL_H__ */

0 commit comments

Comments
 (0)