1 /* Copyright (c) 2022 Intel Corporation
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <zephyr/cache.h>
6 #include <zephyr/kernel.h>
7 #include <zephyr/ztest.h>
8 #include <intel_adsp_ipc.h>
9 #include <zephyr/devicetree.h>
10 #include "tests.h"
11 
12 #define HDA_HOST_IN_BASE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_in), reg, 0)
13 #define HDA_HOST_OUT_BASE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_out), reg, 0)
14 #define HDA_STREAM_COUNT DT_PROP(DT_NODELABEL(hda_host_out), dma_channels)
15 #define HDA_REGBLOCK_SIZE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_out), reg, 1)
16 #include <intel_adsp_hda.h>
17 
18 #define IPC_TIMEOUT K_MSEC(1500)
19 #define STREAM_ID 3U
20 #define HDA_BUF_SIZE 256
21 #define TRANSFER_COUNT 8
22 
23 #define ALIGNMENT DT_PROP(DT_NODELABEL(hda_host_in), dma_buf_addr_alignment)
24 static __aligned(ALIGNMENT) uint8_t hda_buf[HDA_BUF_SIZE];
25 
26 static volatile int msg_cnt;
27 static volatile int msg_res;
28 
ipc_message(const struct device * dev,void * arg,uint32_t data,uint32_t ext_data)29 static bool ipc_message(const struct device *dev, void *arg,
30 			uint32_t data, uint32_t ext_data)
31 {
32 	printk("HDA message received, data %u, ext_data %u\n", data, ext_data);
33 	msg_res = data;
34 	msg_cnt++;
35 	return true;
36 }
37 
38 /*
39  * Tests host input streams
40  *
41  * Note that the order of operations in this test are important and things potentially will not
42  * work in horrible and unexpected ways if not done as they are here.
43  */
ZTEST(intel_adsp_hda,test_hda_host_in_smoke)44 ZTEST(intel_adsp_hda, test_hda_host_in_smoke)
45 {
46 	int res;
47 	uint32_t last_msg_cnt;
48 
49 	printk("smoke testing hda with fifo buffer at address %p, size %d\n",
50 		hda_buf, HDA_BUF_SIZE);
51 
52 	intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_message, NULL);
53 
54 	printk("Using buffer of size %d at addr %p\n", HDA_BUF_SIZE, hda_buf);
55 
56 	/* setup a ramp in the buffer */
57 	for (uint32_t i = 0; i < HDA_BUF_SIZE; i++) {
58 		hda_buf[i] = i & 0xff;
59 	}
60 
61 #if (IS_ENABLED(CONFIG_KERNEL_COHERENCE))
62 	zassert_true(arch_mem_coherent(hda_buf), "Buffer is unexpectedly incoherent!");
63 #else
64 	/* The buffer is in the cached address range and must be flushed */
65 	zassert_false(arch_mem_coherent(hda_buf), "Buffer is unexpectedly coherent!");
66 	sys_cache_data_flush_range(hda_buf, HDA_BUF_SIZE);
67 #endif
68 
69 	intel_adsp_hda_init(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
70 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp init");
71 
72 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_RESET, STREAM_ID, IPC_TIMEOUT);
73 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
74 
75 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_CONFIG,
76 		    STREAM_ID | (HDA_BUF_SIZE << 8), IPC_TIMEOUT);
77 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host config");
78 
79 	res = intel_adsp_hda_set_buffer(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
80 				hda_buf, HDA_BUF_SIZE);
81 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp set_buffer");
82 	zassert_ok(res, "Expected set buffer to succeed");
83 
84 	intel_adsp_hda_enable(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID, true);
85 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp enable");
86 
87 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_START, STREAM_ID, IPC_TIMEOUT);
88 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host start");
89 
90 	for (uint32_t i = 0; i < TRANSFER_COUNT; i++) {
91 		intel_adsp_hda_host_commit(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
92 			HDA_BUF_SIZE);
93 		hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp inc_pos");
94 
95 		WAIT_FOR(intel_adsp_hda_wp_rp_eq(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID),
96 			10000, k_msleep(1));
97 		hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp wp == rp");
98 
99 		last_msg_cnt = msg_cnt;
100 		hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_VALIDATE, STREAM_ID,
101 			    IPC_TIMEOUT);
102 
103 		WAIT_FOR(msg_cnt > last_msg_cnt, 10000, k_msleep(1));
104 		zassert_true(msg_res == 1,
105 			     "Expected data validation to be true from Host");
106 	}
107 
108 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_RESET, STREAM_ID, IPC_TIMEOUT);
109 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
110 
111 	intel_adsp_hda_disable(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
112 	hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp disable");
113 }
114 
115 /*
116  * Tests host output streams
117  *
118  * Note that the order of operations in this test are important and things potentially will not
119  * work in horrible and unexpected ways if not done as they are here.
120  */
ZTEST(intel_adsp_hda,test_hda_host_out_smoke)121 ZTEST(intel_adsp_hda, test_hda_host_out_smoke)
122 {
123 	int res;
124 	bool is_ramp;
125 
126 	printk("smoke testing hda with fifo buffer at address %p, size %d\n",
127 		hda_buf, HDA_BUF_SIZE);
128 
129 	intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_message, NULL);
130 
131 	printk("Using buffer of size %d at addr %p\n", HDA_BUF_SIZE, hda_buf);
132 
133 	intel_adsp_hda_init(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
134 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp init");
135 
136 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_RESET, (STREAM_ID + 7), IPC_TIMEOUT);
137 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
138 
139 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_CONFIG,
140 		    (STREAM_ID + 7) | (HDA_BUF_SIZE << 8), IPC_TIMEOUT);
141 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host config");
142 
143 	res = intel_adsp_hda_set_buffer(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
144 		hda_buf, HDA_BUF_SIZE);
145 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp set buffer");
146 	zassert_ok(res, "Expected set buffer to succeed");
147 
148 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_START, (STREAM_ID + 7), IPC_TIMEOUT);
149 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host start");
150 
151 	intel_adsp_hda_enable(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID, true);
152 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp enable");
153 
154 	for (uint32_t i = 0; i < TRANSFER_COUNT; i++) {
155 		for (int j = 0; j < HDA_BUF_SIZE; j++) {
156 			hda_buf[j] = 0;
157 		}
158 
159 		hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_SEND,
160 			    (STREAM_ID + 7) | (HDA_BUF_SIZE << 8), IPC_TIMEOUT);
161 		hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host send");
162 
163 
164 		WAIT_FOR(intel_adsp_hda_buf_full(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID),
165 			10000, k_msleep(1));
166 		hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp wait for full");
167 
168 #if (IS_ENABLED(CONFIG_KERNEL_COHERENCE))
169 		zassert_true(arch_mem_coherent(hda_buf), "Buffer is unexpectedly incoherent!");
170 #else
171 		/* The buffer is in the cached address range and must be invalidated
172 		 * prior to reading.
173 		 */
174 		zassert_false(arch_mem_coherent(hda_buf), "Buffer is unexpectedly coherent!");
175 		sys_cache_data_invd_range(hda_buf, HDA_BUF_SIZE);
176 #endif
177 
178 		is_ramp = true;
179 		for (int j = 0; j < HDA_BUF_SIZE; j++) {
180 			/* printk("hda_buf[%d] = %d\n", j, hda_buf[j]); */ /* DEBUG HELPER */
181 			if (hda_buf[j] != j) {
182 				is_ramp = false;
183 			}
184 		}
185 		zassert_true(is_ramp, "Expected data to be a ramp");
186 
187 		intel_adsp_hda_host_commit(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
188 			HDA_BUF_SIZE);
189 		hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp inc pos");
190 
191 	}
192 
193 	hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_RESET, (STREAM_ID + 7),
194 		    IPC_TIMEOUT);
195 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
196 
197 	intel_adsp_hda_disable(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
198 	hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp disable");
199 }
200 
201 ZTEST_SUITE(intel_adsp_hda, NULL, NULL, NULL, NULL, NULL);
202