1 /*
2  * Copyright (c) 2017 comsuisse AG
3  * Copyright (c) 2021 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <zephyr/ztest.h>
10 #include <zephyr/drivers/i2s.h>
11 #include "i2s_api_test.h"
12 
13 /* The test cases here are copied from test_i2s_loopback.c and adapted for use
14  * on devices that cannot independently start and stop the RX and TX streams
15  * and require the use of the I2S_DIR_BOTH value for RX/TX transfers.
16  */
17 
18 /** @brief Short I2S transfer.
19  *
20  * - START trigger starts both the transmission and reception.
21  * - Sending / receiving a short sequence of data returns success.
22  * - DRAIN trigger empties the transmit queue and stops both streams.
23  */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_short)24 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_short)
25 {
26 	if (!dir_both_supported) {
27 		TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
28 		ztest_test_skip();
29 		return;
30 	}
31 
32 	int ret;
33 
34 	/* Prefill TX queue */
35 	ret = tx_block_write(dev_i2s, 0, 0);
36 	zassert_equal(ret, TC_PASS);
37 	TC_PRINT("%d->OK\n", 1);
38 
39 	ret = tx_block_write(dev_i2s, 1, 0);
40 	zassert_equal(ret, TC_PASS);
41 	TC_PRINT("%d->OK\n", 2);
42 
43 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
44 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
45 
46 	ret = rx_block_read(dev_i2s, 0);
47 	zassert_equal(ret, TC_PASS);
48 	TC_PRINT("%d<-OK\n", 1);
49 
50 	ret = tx_block_write(dev_i2s, 2, 0);
51 	zassert_equal(ret, TC_PASS);
52 	TC_PRINT("%d->OK\n", 3);
53 
54 	/* All data written, drain TX queue and stop both streams. */
55 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
56 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
57 
58 	ret = rx_block_read(dev_i2s, 1);
59 	zassert_equal(ret, TC_PASS);
60 	TC_PRINT("%d<-OK\n", 2);
61 
62 	ret = rx_block_read(dev_i2s, 2);
63 	zassert_equal(ret, TC_PASS);
64 	TC_PRINT("%d<-OK\n", 3);
65 
66 	/* TODO: Verify the interface is in READY state when i2s_state_get
67 	 * function is available.
68 	 */
69 }
70 
71 #define TEST_I2S_TRANSFER_LONG_REPEAT_COUNT  100
72 
73 /** @brief Long I2S transfer.
74  *
75  * - START trigger starts both the transmission and reception.
76  * - Sending / receiving a long sequence of data returns success.
77  * - DRAIN trigger empties the transmit queue and stops both streams.
78  */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_long)79 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_long)
80 {
81 	if (!dir_both_supported) {
82 		TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
83 		ztest_test_skip();
84 		return;
85 	}
86 
87 	int ret;
88 
89 	/* Prefill TX queue */
90 	ret = tx_block_write(dev_i2s, 0, 0);
91 	zassert_equal(ret, TC_PASS);
92 
93 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
94 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
95 
96 	for (int i = 0; i < TEST_I2S_TRANSFER_LONG_REPEAT_COUNT; i++) {
97 		ret = tx_block_write(dev_i2s, 0, 0);
98 		zassert_equal(ret, TC_PASS);
99 
100 		ret = rx_block_read(dev_i2s, 0);
101 		zassert_equal(ret, TC_PASS);
102 	}
103 
104 	/* All data written, all but one data block read, flush TX queue
105 	 * and stop both streams.
106 	 */
107 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
108 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
109 
110 	ret = rx_block_read(dev_i2s, 0);
111 	zassert_equal(ret, TC_PASS);
112 
113 	/* TODO: Verify the interface is in READY state when i2s_state_get
114 	 * function is available.
115 	 */
116 }
117 
118 /** @brief Re-start I2S transfer.
119  *
120  * - STOP trigger stops transfer / reception at the end of the current block,
121  *   consecutive START trigger restarts transfer / reception with the next data
122  *   block.
123  */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_restart)124 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_restart)
125 {
126 	if (!dir_both_supported) {
127 		TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
128 		ztest_test_skip();
129 		return;
130 	}
131 
132 	int ret;
133 
134 	/* Prefill TX queue */
135 	ret = tx_block_write(dev_i2s, 0, 0);
136 	zassert_equal(ret, TC_PASS);
137 	TC_PRINT("%d->OK\n", 1);
138 
139 	ret = tx_block_write(dev_i2s, 1, 0);
140 	zassert_equal(ret, TC_PASS);
141 	TC_PRINT("%d->OK\n", 2);
142 
143 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
144 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
145 
146 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_STOP);
147 	zassert_equal(ret, 0, "RX/TX STOP trigger failed");
148 
149 	ret = rx_block_read(dev_i2s, 0);
150 	zassert_equal(ret, TC_PASS);
151 	TC_PRINT("%d<-OK\n", 1);
152 
153 	TC_PRINT("Stop transmission\n");
154 
155 	/* Keep interface inactive */
156 	k_sleep(K_MSEC(1000));
157 
158 	TC_PRINT("Start transmission\n");
159 
160 	/* Prefill TX queue */
161 	ret = tx_block_write(dev_i2s, 2, 0);
162 	zassert_equal(ret, TC_PASS);
163 	TC_PRINT("%d->OK\n", 3);
164 
165 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
166 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
167 
168 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
169 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
170 
171 	ret = rx_block_read(dev_i2s, 1);
172 	zassert_equal(ret, TC_PASS);
173 	TC_PRINT("%d<-OK\n", 2);
174 
175 	ret = rx_block_read(dev_i2s, 2);
176 	zassert_equal(ret, TC_PASS);
177 	TC_PRINT("%d<-OK\n", 3);
178 }
179 
180 /** @brief RX buffer overrun.
181  *
182  * - In case of RX buffer overrun it is possible to read out RX data blocks
183  *   that are stored in the RX queue.
184  * - Reading from an empty RX queue when the RX buffer overrun occurred results
185  *   in an error.
186  * - Sending PREPARE trigger after the RX buffer overrun occurred changes
187  *   the interface state to READY.
188  */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_rx_overrun)189 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_rx_overrun)
190 {
191 	if (!dir_both_supported) {
192 		TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
193 		ztest_test_skip();
194 		return;
195 	}
196 
197 	size_t rx_size;
198 	int ret;
199 	char rx_buf[BLOCK_SIZE];
200 
201 	/* Prefill TX queue */
202 	ret = tx_block_write(dev_i2s, 0, 0);
203 	zassert_equal(ret, TC_PASS);
204 
205 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
206 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
207 
208 	for (int i = 0; i < NUM_RX_BLOCKS; i++) {
209 		ret = tx_block_write(dev_i2s, 0, 0);
210 		zassert_equal(ret, TC_PASS);
211 	}
212 
213 	/* All data written, flush TX queue and stop the transmission */
214 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
215 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
216 
217 	/* Wait for transmission to finish */
218 	k_sleep(K_MSEC(200));
219 
220 	/* Read one data block, expect success even if RX queue is already in
221 	 * the error state.
222 	 */
223 	ret = rx_block_read(dev_i2s, 0);
224 	zassert_equal(ret, TC_PASS);
225 
226 	/* Attempt to read more data blocks than are available in the RX queue */
227 	for (int i = 0; i < NUM_RX_BLOCKS; i++) {
228 		ret = i2s_buf_read(dev_i2s, rx_buf, &rx_size);
229 		if (ret != 0) {
230 			break;
231 		}
232 	}
233 	zassert_equal(ret, -EIO, "RX overrun error not detected");
234 
235 	ret = i2s_trigger(dev_i2s, I2S_DIR_RX, I2S_TRIGGER_PREPARE);
236 	zassert_equal(ret, 0, "RX PREPARE trigger failed");
237 
238 	/* Transmit and receive one more data block */
239 	ret = tx_block_write(dev_i2s, 0, 0);
240 	zassert_equal(ret, TC_PASS);
241 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
242 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
243 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
244 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
245 	ret = rx_block_read(dev_i2s, 0);
246 	zassert_equal(ret, TC_PASS);
247 
248 	k_sleep(K_MSEC(200));
249 }
250 
251 /** @brief TX buffer underrun.
252  *
253  * - An attempt to write to the TX queue when TX buffer underrun has occurred
254  *   results in an error.
255  * - Sending PREPARE trigger after the TX buffer underrun occurred changes
256  *   the interface state to READY.
257  */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_tx_underrun)258 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_tx_underrun)
259 {
260 	if (!dir_both_supported) {
261 		TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
262 		ztest_test_skip();
263 		return;
264 	}
265 
266 	int ret;
267 
268 	/* Prefill TX queue */
269 	ret = tx_block_write(dev_i2s, 0, 0);
270 	zassert_equal(ret, TC_PASS);
271 
272 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
273 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
274 
275 	ret = rx_block_read(dev_i2s, 0);
276 	zassert_equal(ret, TC_PASS);
277 
278 	k_sleep(K_MSEC(200));
279 
280 	/* Write one more TX data block, expect an error */
281 	ret = tx_block_write(dev_i2s, 2, -EIO);
282 	zassert_equal(ret, TC_PASS);
283 
284 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
285 	zassert_equal(ret, 0, "RX/TX PREPARE trigger failed");
286 
287 	k_sleep(K_MSEC(200));
288 
289 	/* Transmit and receive two more data blocks */
290 	ret = tx_block_write(dev_i2s, 1, 0);
291 	zassert_equal(ret, TC_PASS);
292 	ret = tx_block_write(dev_i2s, 1, 0);
293 	zassert_equal(ret, TC_PASS);
294 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
295 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
296 	ret = rx_block_read(dev_i2s, 1);
297 	zassert_equal(ret, TC_PASS);
298 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
299 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
300 	ret = rx_block_read(dev_i2s, 1);
301 	zassert_equal(ret, TC_PASS);
302 
303 	k_sleep(K_MSEC(200));
304 }
305