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_states.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 #define TEST_I2S_STATE_RUNNING_NEG_REPEAT_COUNT  5
19 
20 /** @brief Verify all failure cases in RUNNING state.
21  *
22  * - Sending START, PREPARE trigger in RUNNING state returns failure.
23  */
ZTEST_USER(i2s_dir_both_states,test_i2s_dir_both_state_running_neg)24 ZTEST_USER(i2s_dir_both_states, test_i2s_dir_both_state_running_neg)
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 
38 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
39 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
40 
41 	for (int i = 0; i < TEST_I2S_STATE_RUNNING_NEG_REPEAT_COUNT; i++) {
42 		ret = tx_block_write(dev_i2s, 0, 0);
43 		zassert_equal(ret, TC_PASS);
44 
45 		ret = rx_block_read(dev_i2s, 0);
46 		zassert_equal(ret, TC_PASS);
47 
48 		/* Send invalid triggers, expect failure */
49 		ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
50 		zassert_equal(ret, -EIO);
51 		ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
52 		zassert_equal(ret, -EIO);
53 	}
54 
55 	/* All data written, drain TX queue and stop both streams. */
56 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
57 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
58 
59 	ret = rx_block_read(dev_i2s, 0);
60 	zassert_equal(ret, TC_PASS);
61 }
62 
63 /** @brief Verify all failure cases in STOPPING state.
64  *
65  * - Sending START, STOP, DRAIN, PREPARE trigger in STOPPING state returns
66  *   failure.
67  */
ZTEST_USER(i2s_dir_both_states,test_i2s_dir_both_state_stopping_neg)68 ZTEST_USER(i2s_dir_both_states, test_i2s_dir_both_state_stopping_neg)
69 {
70 	if (!dir_both_supported) {
71 		TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
72 		ztest_test_skip();
73 		return;
74 	}
75 
76 	int ret;
77 
78 	/* Prefill TX queue */
79 	ret = tx_block_write(dev_i2s, 0, 0);
80 	zassert_equal(ret, TC_PASS);
81 
82 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
83 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
84 
85 	ret = tx_block_write(dev_i2s, 0, 0);
86 	zassert_equal(ret, TC_PASS);
87 
88 	ret = rx_block_read(dev_i2s, 0);
89 	zassert_equal(ret, TC_PASS);
90 
91 	/* All data written, all but one data block read, flush TX queue and
92 	 * stop both streams.
93 	 */
94 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
95 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
96 
97 	/* Send invalid triggers, expect failure */
98 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
99 	zassert_equal(ret, -EIO);
100 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_STOP);
101 	zassert_equal(ret, -EIO);
102 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
103 	zassert_equal(ret, -EIO);
104 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
105 	zassert_equal(ret, -EIO);
106 
107 	ret = rx_block_read(dev_i2s, 0);
108 	zassert_equal(ret, TC_PASS);
109 
110 	/* This is incase the RX channel is stuck in STOPPING state.
111 	 * Clear out the state before running the next test.
112 	 */
113 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DROP);
114 	zassert_equal(ret, 0, "RX/TX DROP trigger failed");
115 }
116 
117 /** @brief Verify all failure cases in ERROR state.
118  *
119  * - Sending START, STOP, DRAIN trigger in ERROR state returns failure.
120  */
ZTEST_USER(i2s_dir_both_states,test_i2s_dir_both_state_error_neg)121 ZTEST_USER(i2s_dir_both_states, test_i2s_dir_both_state_error_neg)
122 {
123 	if (!dir_both_supported) {
124 		TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
125 		ztest_test_skip();
126 		return;
127 	}
128 
129 	size_t rx_size;
130 	int ret;
131 	char rx_buf[BLOCK_SIZE];
132 
133 	/* Prefill TX queue */
134 	ret = tx_block_write(dev_i2s, 0, 0);
135 	zassert_equal(ret, TC_PASS);
136 
137 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
138 	zassert_equal(ret, 0, "RX/TX START trigger failed\n");
139 
140 	for (int i = 0; i < NUM_RX_BLOCKS; i++) {
141 		ret = tx_block_write(dev_i2s, 0, 0);
142 		zassert_equal(ret, TC_PASS);
143 	}
144 
145 	/* Wait for transmission to finish */
146 	k_sleep(K_MSEC(200));
147 
148 	/* Read one data block, expect success even if RX queue is already in
149 	 * the error state.
150 	 */
151 	ret = rx_block_read(dev_i2s, 0);
152 	zassert_equal(ret, TC_PASS);
153 
154 	/* Attempt to read more data blocks than are available in the RX queue */
155 	for (int i = 0; i < NUM_RX_BLOCKS; i++) {
156 		ret = i2s_buf_read(dev_i2s, rx_buf, &rx_size);
157 		if (ret != 0) {
158 			break;
159 		}
160 	}
161 	zassert_equal(ret, -EIO, "RX overrun error not detected");
162 
163 	/* Write one more TX data block, expect an error */
164 	ret = tx_block_write(dev_i2s, 2, -EIO);
165 	zassert_equal(ret, TC_PASS);
166 
167 	/* Send invalid triggers, expect failure */
168 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
169 	zassert_equal(ret, -EIO);
170 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_STOP);
171 	zassert_equal(ret, -EIO);
172 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
173 	zassert_equal(ret, -EIO);
174 
175 	/* Recover from ERROR state */
176 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
177 	zassert_equal(ret, 0, "RX/TX PREPARE trigger failed");
178 
179 	/* Transmit and receive one more data block */
180 	ret = tx_block_write(dev_i2s, 0, 0);
181 	zassert_equal(ret, TC_PASS);
182 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
183 	zassert_equal(ret, 0, "RX/TX START trigger failed");
184 	ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
185 	zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
186 	ret = rx_block_read(dev_i2s, 0);
187 	zassert_equal(ret, TC_PASS);
188 
189 	k_sleep(K_MSEC(200));
190 }
191