1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stddef.h>
24 #include <stdint.h>
25 #include "mxc_device.h"
26 #include "mxc_assert.h"
27 #include "mxc_lock.h"
28 #include "mxc_sys.h"
29 #include "mxc_delay.h"
30 #include "dma.h"
31 #include "i2s_reva.h"
32 #include "i2s.h"
33 
34 /* ***** Definitions ***** */
35 #define DATALENGTH_EIGHT (8)
36 #define DATALENGTH_SIXTEEN (16)
37 #define DATALENGTH_TWENTY (20)
38 #define DATALENGTH_TWENTYFOUR (24)
39 #define DATALENGTH_THIRTYTWO (32)
40 
41 // #define USE_LEGACY_I2S_DMA_CFG
42 
43 typedef struct {
44     int rxCnt;
45     int txCnt;
46     bool async;
47 } mxc_i2s_reva_txn_t;
48 
49 /* ****** Globals ****** */
50 static mxc_i2s_req_t *request;
51 static void (*dma_cb)(int, int) = NULL;
52 static void (*async_cb)(int) = NULL;
53 
54 static mxc_i2s_req_t txn_req;
55 static mxc_i2s_reva_txn_t txn_state;
56 static uint32_t txn_lock = 0;
57 
configure_data_sizes(mxc_i2s_reva_regs_t * i2s,uint8_t bits_word,uint8_t smp_sz,uint8_t wsize)58 static void configure_data_sizes(mxc_i2s_reva_regs_t *i2s, uint8_t bits_word, uint8_t smp_sz,
59                                  uint8_t wsize)
60 {
61     if (bits_word > 0) {
62         MXC_SETFIELD(i2s->ctrl1ch0, MXC_F_I2S_REVA_CTRL1CH0_BITS_WORD,
63                      (bits_word - 1) << MXC_F_I2S_REVA_CTRL1CH0_BITS_WORD_POS); // Subtract 1
64     } else {
65         MXC_SETFIELD(i2s->ctrl1ch0, MXC_F_I2S_REVA_CTRL1CH0_BITS_WORD,
66                      0); // Clear to 0
67     }
68 
69     //Set sample length if defined:
70     //The SMP_SIZE is equal to bitsWord when sampleSize == 0 or sampleSize > bitsWord
71     if (smp_sz > 0) {
72         MXC_SETFIELD(i2s->ctrl1ch0, MXC_F_I2S_REVA_CTRL1CH0_SMP_SIZE,
73                      (smp_sz - 1) << MXC_F_I2S_REVA_CTRL1CH0_SMP_SIZE_POS); // Subtract 1
74     } else {
75         MXC_SETFIELD(i2s->ctrl1ch0, MXC_F_I2S_REVA_CTRL1CH0_SMP_SIZE,
76                      0); // Clear to 0
77     }
78 
79     //Set datasize to load in FIFO
80     MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_WSIZE,
81                  wsize << MXC_F_I2S_REVA_CTRL0CH0_WSIZE_POS);
82 }
83 
84 /* ****** Functions ****** */
MXC_I2S_RevA_Init(mxc_i2s_reva_regs_t * i2s,mxc_i2s_req_t * req)85 int MXC_I2S_RevA_Init(mxc_i2s_reva_regs_t *i2s, mxc_i2s_req_t *req)
86 {
87     if (((req->txData == NULL) || (req->rawData == NULL)) && (req->rxData == NULL)) {
88         return E_NULL_PTR;
89     }
90 
91     if (req->length == 0) {
92         return E_BAD_PARAM;
93     }
94 
95     request = req;
96 
97     if (req->stereoMode) {
98         i2s->ctrl0ch0 |= (req->stereoMode << MXC_F_I2S_REVA_CTRL0CH0_STEREO_POS);
99     }
100 
101     //Set RX Threshold 2 (default)
102     i2s->ctrl0ch0 |= (2 << MXC_F_I2S_REVA_CTRL0CH0_RX_THD_VAL_POS);
103 
104     //Set justify
105     MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_ALIGN,
106                  (req->justify) << MXC_F_I2S_REVA_CTRL0CH0_ALIGN_POS);
107 
108     if (MXC_I2S_ConfigData((mxc_i2s_req_t *)req) != E_NO_ERROR) {
109         return E_BAD_PARAM;
110     }
111 
112     MXC_I2S_SetFrequency(req->channelMode, req->clkdiv);
113 
114     return E_NO_ERROR;
115 }
116 
MXC_I2S_RevA_Shutdown(mxc_i2s_reva_regs_t * i2s)117 int MXC_I2S_RevA_Shutdown(mxc_i2s_reva_regs_t *i2s)
118 {
119     MXC_I2S_DisableInt(0xFF);
120 
121     //Disable I2S TX and RX channel
122     MXC_I2S_TXDisable();
123     MXC_I2S_RXDisable();
124 
125     MXC_I2S_Flush();
126 
127     //Clear all the registers. Not cleared on reset
128     i2s->ctrl0ch0 = 0x00;
129     i2s->dmach0 = 0x00;
130     i2s->ctrl1ch0 = 0x00;
131 
132     i2s->ctrl0ch0 |= MXC_F_I2S_REVA_CTRL0CH0_RST; //Reset channel
133 
134     return E_NO_ERROR;
135 }
136 
MXC_I2S_RevA_ConfigData(mxc_i2s_reva_regs_t * i2s,mxc_i2s_req_t * req)137 int MXC_I2S_RevA_ConfigData(mxc_i2s_reva_regs_t *i2s, mxc_i2s_req_t *req)
138 {
139     uint32_t dataMask;
140 
141     //Data pointers
142     uint8_t *txdata_8 = (uint8_t *)req->txData;
143     uint16_t *txdata_16 = (uint16_t *)req->txData;
144     uint32_t *txdata_32 = (uint32_t *)req->txData;
145     uint8_t *rawdata_8 = (uint8_t *)req->rawData;
146     uint16_t *rawdata_16 = (uint16_t *)req->rawData;
147     uint32_t *rawdata_32 = (uint32_t *)req->rawData;
148 
149     if ((req->txData == NULL) && (req->rxData == NULL)) {
150         return E_NULL_PTR;
151     }
152 
153     if (req->length == 0) {
154         return E_BAD_PARAM;
155     }
156 
157     // Clear configuration bits
158     i2s->ctrl0ch0 &= ~MXC_F_I2S_REVA_CTRL0CH0_WSIZE;
159     i2s->ctrl1ch0 &= ~MXC_F_I2S_REVA_CTRL1CH0_BITS_WORD;
160     i2s->ctrl1ch0 &= ~MXC_F_I2S_REVA_CTRL1CH0_SMP_SIZE;
161 
162     configure_data_sizes(i2s, req->bitsWord, req->sampleSize, req->wordSize);
163 
164     MXC_SETFIELD(i2s->ctrl1ch0, MXC_F_I2S_REVA_CTRL1CH0_ADJUST,
165                  (req->adjust) << MXC_F_I2S_REVA_CTRL1CH0_ADJUST_POS);
166 
167     if (req->bitsWord <= DATALENGTH_EIGHT) {
168         dataMask = 0x000000ff;
169 
170         if ((req->rawData != NULL) && (req->txData != NULL)) {
171             for (uint32_t i = 0; i < req->length; i++) {
172                 *txdata_8++ = *rawdata_8++ & dataMask;
173             }
174         }
175     } else if (req->bitsWord <= DATALENGTH_SIXTEEN) {
176         dataMask = 0x0000ffff;
177 
178         if ((req->rawData != NULL) && (req->txData != NULL)) {
179             for (uint32_t i = 0; i < req->length; i++) {
180                 *txdata_16++ = *rawdata_16++ & dataMask;
181             }
182         }
183     } else if (req->bitsWord <= DATALENGTH_TWENTY) {
184         dataMask = 0x00fffff;
185 
186         if ((req->rawData != NULL) && (req->txData != NULL)) {
187             for (uint32_t i = 0; i < req->length; i++) {
188                 *txdata_32++ = (*rawdata_32++ & dataMask) << 12;
189             }
190         }
191     } else if (req->bitsWord <= DATALENGTH_TWENTYFOUR) {
192         dataMask = 0x00ffffff;
193 
194         if ((req->rawData != NULL) && (req->txData != NULL)) {
195             for (uint32_t i = 0; i < req->length; i++) {
196                 *txdata_32++ = (*rawdata_32++ & dataMask) << 8;
197             }
198         }
199     } else if (req->bitsWord <= DATALENGTH_THIRTYTWO) {
200         dataMask = 0xffffffff;
201 
202         if ((req->rawData != NULL) && (req->txData != NULL)) {
203             for (uint32_t i = 0; i < req->length; i++) {
204                 *txdata_32++ = *rawdata_32++ & dataMask;
205             }
206         }
207     }
208 
209     return E_NO_ERROR;
210 }
211 
MXC_I2S_RevA_TXEnable(mxc_i2s_reva_regs_t * i2s)212 void MXC_I2S_RevA_TXEnable(mxc_i2s_reva_regs_t *i2s)
213 {
214     MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_TX_EN,
215                  1 << MXC_F_I2S_REVA_CTRL0CH0_TX_EN_POS);
216 }
217 
MXC_I2S_RevA_TXDisable(mxc_i2s_reva_regs_t * i2s)218 void MXC_I2S_RevA_TXDisable(mxc_i2s_reva_regs_t *i2s)
219 {
220     MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_TX_EN,
221                  0 << MXC_F_I2S_REVA_CTRL0CH0_TX_EN_POS);
222 }
223 
MXC_I2S_RevA_RXEnable(mxc_i2s_reva_regs_t * i2s)224 void MXC_I2S_RevA_RXEnable(mxc_i2s_reva_regs_t *i2s)
225 {
226     MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_RX_EN,
227                  1 << MXC_F_I2S_REVA_CTRL0CH0_RX_EN_POS);
228 }
229 
MXC_I2S_RevA_RXDisable(mxc_i2s_reva_regs_t * i2s)230 void MXC_I2S_RevA_RXDisable(mxc_i2s_reva_regs_t *i2s)
231 {
232     MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_RX_EN,
233                  0 << MXC_F_I2S_REVA_CTRL0CH0_RX_EN_POS);
234 }
235 
MXC_I2S_RevA_SetRXThreshold(mxc_i2s_reva_regs_t * i2s,uint8_t threshold)236 int MXC_I2S_RevA_SetRXThreshold(mxc_i2s_reva_regs_t *i2s, uint8_t threshold)
237 {
238     if ((threshold == 0) || (threshold > 8)) {
239         return E_NOT_SUPPORTED;
240     }
241 
242     i2s->ctrl0ch0 |= (threshold << MXC_F_I2S_REVA_CTRL0CH0_RX_THD_VAL_POS);
243 
244     return E_NO_ERROR;
245 }
246 
MXC_I2S_RevA_SetFrequency(mxc_i2s_reva_regs_t * i2s,mxc_i2s_ch_mode_t mode,uint16_t clkdiv)247 int MXC_I2S_RevA_SetFrequency(mxc_i2s_reva_regs_t *i2s, mxc_i2s_ch_mode_t mode, uint16_t clkdiv)
248 {
249     i2s->ctrl1ch0 &= ~MXC_F_I2S_REVA_CTRL1CH0_EN;
250 
251     MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_CH_MODE,
252                  (mode) << MXC_F_I2S_REVA_CTRL0CH0_CH_MODE_POS);
253 
254     i2s->ctrl1ch0 |= ((uint32_t)clkdiv) << MXC_F_I2S_REVA_CTRL1CH0_CLKDIV_POS;
255 
256     i2s->ctrl1ch0 |= MXC_F_I2S_REVA_CTRL1CH0_EN;
257 
258     return E_NO_ERROR;
259 }
260 
MXC_I2S_RevA_SetSampleRate(mxc_i2s_reva_regs_t * i2s,uint32_t smpl_rate,mxc_i2s_wsize_t smpl_sz,uint32_t src_clk)261 int MXC_I2S_RevA_SetSampleRate(mxc_i2s_reva_regs_t *i2s, uint32_t smpl_rate,
262                                mxc_i2s_wsize_t smpl_sz, uint32_t src_clk)
263 {
264     int clk_div;
265 
266     clk_div = MXC_I2S_RevA_CalculateClockDiv(i2s, smpl_rate, smpl_sz, src_clk);
267     if (clk_div < 0) {
268         return clk_div;
269     }
270 
271     i2s->ctrl1ch0 &= ~MXC_F_I2S_REVA_CTRL1CH0_EN;
272     i2s->ctrl1ch0 |= ((uint32_t)clk_div) << MXC_F_I2S_REVA_CTRL1CH0_CLKDIV_POS;
273     i2s->ctrl1ch0 |= MXC_F_I2S_REVA_CTRL1CH0_EN;
274 
275     return MXC_I2S_RevA_GetSampleRate(i2s, src_clk);
276 }
277 
MXC_I2S_RevA_GetSampleRate(mxc_i2s_reva_regs_t * i2s,uint32_t src_clk)278 int MXC_I2S_RevA_GetSampleRate(mxc_i2s_reva_regs_t *i2s, uint32_t src_clk)
279 {
280     uint16_t word_sz, clk_div;
281     uint32_t bclk;
282 
283     word_sz = (i2s->ctrl0ch0 & MXC_F_I2S_REVA_CTRL0CH0_WSIZE) >> MXC_F_I2S_REVA_CTRL0CH0_WSIZE_POS;
284     clk_div = (i2s->ctrl1ch0 & MXC_F_I2S_REVA_CTRL1CH0_CLKDIV) >>
285               MXC_F_I2S_REVA_CTRL1CH0_CLKDIV_POS; // Get clock divider value
286 
287     switch (word_sz) { // Get word size
288     case MXC_I2S_WSIZE_BYTE:
289         word_sz = 8;
290         break;
291     case MXC_I2S_WSIZE_HALFWORD:
292         word_sz = 16;
293         break;
294     case MXC_I2S_WSIZE_WORD:
295     default:
296         word_sz = 32;
297         break;
298     }
299 
300     bclk = (src_clk / (clk_div + 1)) >>
301            1; // bclk_frequency = src_clk_frequency / (clk_divider + 1) / 2
302     return (bclk / word_sz) >>
303            1; // return sample rate (sample_rate = bclk_frequency / word_size / 2)
304 }
305 
MXC_I2S_RevA_CalculateClockDiv(mxc_i2s_reva_regs_t * i2s,uint32_t smpl_rate,mxc_i2s_wsize_t word_sz,uint32_t src_clk)306 int MXC_I2S_RevA_CalculateClockDiv(mxc_i2s_reva_regs_t *i2s, uint32_t smpl_rate,
307                                    mxc_i2s_wsize_t word_sz, uint32_t src_clk)
308 {
309     uint32_t bclk = 0;
310     uint32_t word_size = 0;
311 
312     switch (word_sz) { // Get word size
313     case MXC_I2S_WSIZE_BYTE:
314         word_size = 8;
315         break;
316     case MXC_I2S_WSIZE_HALFWORD:
317         word_size = 16;
318         break;
319     case MXC_I2S_WSIZE_WORD:
320         word_size = 32;
321         break;
322     default:
323         return E_BAD_PARAM;
324     }
325 
326     bclk = smpl_rate * word_size * 2; // bclk_frequency = sample_rate * word_size * 2
327 
328     if (bclk > src_clk) {
329         return E_INVALID;
330     }
331 
332     return (src_clk / (bclk * 2)) - 1; // clk_divider = src_clk_frequency / (bclk_frequency * 2) - 1
333 }
334 
MXC_I2S_RevA_Flush(mxc_i2s_reva_regs_t * i2s)335 void MXC_I2S_RevA_Flush(mxc_i2s_reva_regs_t *i2s)
336 {
337     i2s->ctrl0ch0 |= MXC_F_I2S_REVA_CTRL0CH0_FLUSH;
338 
339     while (i2s->ctrl0ch0 & MXC_F_I2S_REVA_CTRL0CH0_FLUSH) {}
340 }
341 
write_tx_fifo(void * tx,mxc_i2s_wsize_t wordSize,int smpl_cnt)342 static uint32_t write_tx_fifo(void *tx, mxc_i2s_wsize_t wordSize, int smpl_cnt)
343 {
344     uint32_t write_val = 0;
345 
346     if (wordSize == MXC_I2S_WSIZE_BYTE) {
347         uint8_t *tx8 = (uint8_t *)tx;
348         for (int i = 0; i < 4; i++) {
349             write_val |= (tx8[smpl_cnt++] << (i * 8));
350         }
351     } else if (wordSize == MXC_I2S_WSIZE_HALFWORD) {
352         uint16_t *tx16 = (uint16_t *)tx;
353         for (int i = 0; i < 2; i++) {
354             write_val |= (tx16[smpl_cnt++] << (i * 16));
355         }
356     } else if (wordSize == MXC_I2S_WSIZE_WORD) {
357         uint32_t *tx32 = (uint32_t *)tx;
358         write_val = tx32[smpl_cnt];
359     }
360 
361     return write_val;
362 }
363 
MXC_I2S_RevA_FillTXFIFO(mxc_i2s_reva_regs_t * i2s,void * txData,mxc_i2s_wsize_t wordSize,int len,int smpl_cnt)364 int MXC_I2S_RevA_FillTXFIFO(mxc_i2s_reva_regs_t *i2s, void *txData, mxc_i2s_wsize_t wordSize,
365                             int len, int smpl_cnt)
366 {
367     int num_smpl = 0x4 >> wordSize; // Number of samples per FIFO write
368     int sent = 0; // Total number of samples transmitted
369     uint32_t fifo_write, fifo_avail; // Value to write to I2S TX FIFO
370 
371     if (txData == NULL) { // Check for bad parameters
372         return E_NULL_PTR;
373     } else if (wordSize > MXC_I2S_WSIZE_WORD) {
374         return E_BAD_PARAM;
375     } else if (len == 0) {
376         return E_NO_ERROR;
377     }
378 
379     len -= len % num_smpl; // TEST
380     fifo_avail =
381         8 - ((i2s->dmach0 & MXC_F_I2S_REVA_DMACH0_TX_LVL) >> MXC_F_I2S_REVA_DMACH0_TX_LVL_POS);
382     fifo_avail *= num_smpl;
383     while (sent < len && sent < fifo_avail) {
384         fifo_write = write_tx_fifo(txData, wordSize, sent + smpl_cnt);
385         sent += num_smpl;
386 
387         i2s->fifoch0 = fifo_write;
388     }
389 
390     return sent;
391 }
392 
read_rx_fifo(mxc_i2s_reva_regs_t * i2s,void * rxData,mxc_i2s_wsize_t wordSize,int cnt)393 static void read_rx_fifo(mxc_i2s_reva_regs_t *i2s, void *rxData, mxc_i2s_wsize_t wordSize, int cnt)
394 {
395     uint32_t fifo_val = i2s->fifoch0;
396 
397     if (wordSize == MXC_I2S_WSIZE_BYTE) {
398         uint8_t *rx8 = (uint8_t *)rxData;
399         for (int i = 0; i < 4; i++) {
400             rx8[cnt++] = fifo_val & 0xFF;
401             fifo_val = fifo_val >> 8;
402         }
403     } else if (wordSize == MXC_I2S_WSIZE_HALFWORD) {
404         uint16_t *rx16 = (uint16_t *)rxData;
405         for (int i = 0; i < 2; i++) {
406             rx16[cnt++] = fifo_val & 0xFFFF;
407             fifo_val = fifo_val >> 16;
408         }
409     } else if (wordSize == MXC_I2S_WSIZE_WORD) {
410         uint32_t *rx32 = (uint32_t *)rxData;
411         rx32[cnt] = fifo_val;
412     }
413 }
414 
MXC_I2S_RevA_ReadRXFIFO(mxc_i2s_reva_regs_t * i2s,void * rxData,mxc_i2s_wsize_t wordSize,int len,int smpl_cnt)415 int MXC_I2S_RevA_ReadRXFIFO(mxc_i2s_reva_regs_t *i2s, void *rxData, mxc_i2s_wsize_t wordSize,
416                             int len, int smpl_cnt)
417 {
418     int received = 0;
419     int num_smpl = 0x4 >> wordSize;
420     uint32_t fifo_avail;
421 
422     if (rxData == NULL) { // Check for bad parameters
423         return E_NULL_PTR;
424     } else if (wordSize > MXC_I2S_WSIZE_WORD) {
425         return E_BAD_PARAM;
426     } else if (len == 0) {
427         return E_NO_ERROR;
428     }
429 
430     len -= len % num_smpl;
431     fifo_avail = (i2s->dmach0 & MXC_F_I2S_REVA_DMACH0_RX_LVL) >> MXC_F_I2S_REVA_DMACH0_RX_LVL_POS;
432     while (received < len && fifo_avail) {
433         read_rx_fifo(i2s, rxData, wordSize, received + smpl_cnt);
434         received += num_smpl;
435         fifo_avail = (i2s->dmach0 & MXC_F_I2S_REVA_DMACH0_RX_LVL) >>
436                      MXC_F_I2S_REVA_DMACH0_RX_LVL_POS;
437     }
438 
439     return received;
440 }
441 
MXC_I2S_RevA_EnableInt(mxc_i2s_reva_regs_t * i2s,uint32_t flags)442 void MXC_I2S_RevA_EnableInt(mxc_i2s_reva_regs_t *i2s, uint32_t flags)
443 {
444     i2s->inten |= flags;
445 }
446 
MXC_I2S_RevA_DisableInt(mxc_i2s_reva_regs_t * i2s,uint32_t flags)447 void MXC_I2S_RevA_DisableInt(mxc_i2s_reva_regs_t *i2s, uint32_t flags)
448 {
449     i2s->inten &= ~flags;
450 }
451 
MXC_I2S_RevA_GetFlags(mxc_i2s_reva_regs_t * i2s)452 int MXC_I2S_RevA_GetFlags(mxc_i2s_reva_regs_t *i2s)
453 {
454     return (i2s->intfl & 0xF);
455 }
456 
MXC_I2S_RevA_ClearFlags(mxc_i2s_reva_regs_t * i2s,uint32_t flags)457 void MXC_I2S_RevA_ClearFlags(mxc_i2s_reva_regs_t *i2s, uint32_t flags)
458 {
459     i2s->intfl |= flags;
460 }
461 
MXC_I2S_RevA_Transaction(mxc_i2s_reva_regs_t * i2s,mxc_i2s_req_t * i2s_req)462 int MXC_I2S_RevA_Transaction(mxc_i2s_reva_regs_t *i2s, mxc_i2s_req_t *i2s_req)
463 {
464     int err;
465 
466     if (i2s_req->rawData != NULL && i2s_req->txData == NULL) {
467         return E_INVALID;
468     } else if (i2s_req->length == 0) {
469         return E_INVALID;
470     } else if (MXC_GetLock(&txn_lock, 1) != E_NO_ERROR) {
471         return E_BUSY;
472     }
473 
474     i2s->ctrl1ch0 &= ~MXC_F_I2S_REVA_CTRL1CH0_EN; // Disable I2S while it's being configured
475 
476     txn_req = *i2s_req; // Initialize transaction request state variables
477     txn_state.rxCnt = txn_req.length;
478     txn_state.txCnt = txn_req.length;
479     txn_state.async = false;
480 
481     MXC_I2S_Flush();
482 
483     if (txn_req.rawData != NULL &&
484         txn_req.txData != NULL) { // Set up transmit if transmit parameters valid
485         txn_state.txCnt = 0;
486 
487         err = MXC_I2S_ConfigData(&txn_req);
488         if (err) {
489             MXC_FreeLock(&txn_lock);
490             return err;
491         }
492 
493         err = MXC_I2S_FillTXFIFO(txn_req.txData, txn_req.wordSize, txn_req.length,
494                                  txn_state.txCnt); // Initialize TX FIFO
495         if (err < E_NO_ERROR) {
496             MXC_FreeLock(&txn_lock);
497             return err;
498         }
499         txn_state.txCnt = err;
500 
501         MXC_I2S_TXEnable(); // Enable I2S transmit (Do this before Fill FIFO?)
502     }
503 
504     if (txn_req.rxData != NULL) { // Setup I2S receive if receive parameters valid
505         txn_state.rxCnt = 0;
506 
507         MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_RX_THD_VAL,
508                      (6 << MXC_F_I2S_REVA_CTRL0CH0_RX_THD_VAL_POS)); // Set RX threshold
509 
510         MXC_I2S_RXEnable(); // Enable I2S Receive
511     }
512 
513     i2s->ctrl1ch0 |= MXC_F_I2S_REVA_CTRL1CH0_EN; // Enable I2S RX/TX
514 
515     while (MXC_GetLock(&txn_lock, 1) != E_NO_ERROR) {
516         MXC_I2S_RevA_Handler(i2s);
517     }
518 
519     MXC_FreeLock(&txn_lock);
520 
521     return E_NO_ERROR;
522 }
523 
MXC_I2S_RevA_TransactionAsync(mxc_i2s_reva_regs_t * i2s,mxc_i2s_req_t * i2s_req)524 int MXC_I2S_RevA_TransactionAsync(mxc_i2s_reva_regs_t *i2s, mxc_i2s_req_t *i2s_req)
525 {
526     int err;
527     uint32_t int_en = 0;
528 
529     if (i2s_req->rawData != NULL && i2s_req->txData == NULL) {
530         return E_INVALID;
531     } else if (i2s_req->length == 0) {
532         return E_INVALID;
533     } else if (MXC_GetLock(&txn_lock, 1) != E_NO_ERROR) {
534         return E_BUSY;
535     }
536 
537     i2s->ctrl1ch0 &= ~MXC_F_I2S_REVA_CTRL1CH0_EN; // Disable I2S while it's being configured
538 
539     txn_req = *i2s_req; // Initialize transacion request state variables
540     txn_state.rxCnt = txn_req.length;
541     txn_state.txCnt = txn_req.length;
542     txn_state.async = true;
543 
544     MXC_I2S_Flush();
545 
546     if (txn_req.rawData != NULL &&
547         txn_req.txData != NULL) { // Set up transmit if transmit parameters valid
548         txn_state.txCnt = 0;
549 
550         err = MXC_I2S_ConfigData(&txn_req);
551         if (err) {
552             MXC_FreeLock(&txn_lock);
553             return err;
554         }
555 
556         int_en |= MXC_F_I2S_REVA_INTFL_TX_OB_CH0; // Enable TX one entry remaining interrupt
557 
558         err = MXC_I2S_FillTXFIFO(txn_req.txData, txn_req.wordSize, txn_req.length,
559                                  txn_state.txCnt); // Initialize TX FIFO
560         if (err < E_NO_ERROR) {
561             MXC_FreeLock(&txn_lock);
562             return err;
563         }
564         txn_state.txCnt = err;
565 
566         MXC_I2S_TXEnable(); // Enable I2S transmit (Do this before Fill FIFO?)
567     }
568 
569     if (txn_req.rxData != NULL) { // Setup I2S receive if receive parameters valid
570         txn_state.rxCnt = 0;
571 
572         int_en |= MXC_F_I2S_REVA_INTEN_RX_THD_CH0; // Enable RX threshold interrupt
573         MXC_SETFIELD(i2s->ctrl0ch0, MXC_F_I2S_REVA_CTRL0CH0_RX_THD_VAL,
574                      (6 << MXC_F_I2S_REVA_CTRL0CH0_RX_THD_VAL_POS)); // Set RX threshold
575 
576         MXC_I2S_RXEnable(); // Enable I2S Receive
577     }
578 
579     MXC_I2S_DisableInt(0xF); // Configure interrupts
580     MXC_I2S_ClearFlags(0xF);
581     MXC_I2S_EnableInt(int_en);
582 
583     i2s->ctrl1ch0 |= MXC_F_I2S_REVA_CTRL1CH0_EN; // Enable I2S RX/TX
584 
585     return E_NO_ERROR;
586 }
587 
MXC_I2S_RevA_TXDMAConfig(mxc_i2s_reva_regs_t * i2s,void * src_addr,int len)588 int MXC_I2S_RevA_TXDMAConfig(mxc_i2s_reva_regs_t *i2s, void *src_addr, int len)
589 {
590     int channel;
591     mxc_dma_config_t config;
592     mxc_dma_adv_config_t advConfig;
593     mxc_dma_srcdst_t srcdst;
594 
595     MXC_DMA_Init();
596 
597     i2s->dmach0 |= (2 << MXC_F_I2S_REVA_DMACH0_DMA_TX_THD_VAL_POS); //TX DMA Threshold
598 
599     channel = MXC_DMA_AcquireChannel();
600     if (channel < E_NO_ERROR) {
601         return channel;
602     }
603 
604     config.reqsel = MXC_DMA_REQUEST_I2STX;
605 
606     config.ch = channel;
607 
608     switch (request->wordSize) {
609     case MXC_I2S_WSIZE_WORD:
610         config.srcwd = MXC_DMA_WIDTH_WORD;
611         config.dstwd = MXC_DMA_WIDTH_WORD;
612         advConfig.burst_size = 4;
613         break;
614 
615     case MXC_I2S_WSIZE_HALFWORD:
616         config.srcwd = MXC_DMA_WIDTH_HALFWORD;
617         config.dstwd = MXC_DMA_WIDTH_WORD;
618         advConfig.burst_size = 2;
619         break;
620 
621     case MXC_I2S_WSIZE_BYTE:
622         config.srcwd = MXC_DMA_WIDTH_BYTE;
623         config.dstwd = MXC_DMA_WIDTH_WORD;
624         advConfig.burst_size = 1;
625         break;
626 
627     default:
628         config.srcwd = MXC_DMA_WIDTH_BYTE;
629         config.dstwd = MXC_DMA_WIDTH_WORD;
630         advConfig.burst_size = 1;
631         break;
632     }
633 
634 #ifndef USE_LEGACY_I2S_DMA_CFG
635     advConfig.burst_size = 4;
636 #endif
637 
638     config.srcinc_en = 1;
639     config.dstinc_en = 0;
640 
641     advConfig.ch = channel;
642     advConfig.prio = MXC_DMA_PRIO_HIGH; // 0
643     advConfig.reqwait_en = 0;
644     advConfig.tosel = MXC_DMA_TIMEOUT_4_CLK; // 0
645     advConfig.pssel = MXC_DMA_PRESCALE_DISABLE; // 0
646 
647     srcdst.ch = channel;
648     srcdst.source = src_addr;
649     srcdst.len = len;
650 
651     MXC_DMA_ConfigChannel(config, srcdst);
652     MXC_DMA_AdvConfigChannel(advConfig);
653     MXC_DMA_SetCallback(channel, dma_cb);
654 
655     MXC_I2S_TXEnable(); //Enable I2S TX
656     i2s->dmach0 |= MXC_F_I2S_REVA_DMACH0_DMA_TX_EN; //Enable I2S DMA
657 
658     MXC_DMA_EnableInt(channel);
659     MXC_DMA_Start(channel);
660     MXC_DMA->ch[channel].ctrl |= MXC_F_DMA_CTRL_CTZ_IE;
661 
662     return channel;
663 }
664 
MXC_I2S_RevA_RXDMAConfig(mxc_i2s_reva_regs_t * i2s,void * dest_addr,int len)665 int MXC_I2S_RevA_RXDMAConfig(mxc_i2s_reva_regs_t *i2s, void *dest_addr, int len)
666 {
667     int channel;
668     mxc_dma_config_t config;
669     mxc_dma_adv_config_t advConfig;
670     mxc_dma_srcdst_t srcdst;
671 
672     MXC_DMA_Init();
673 
674     i2s->dmach0 |= (6 << MXC_F_I2S_REVA_DMACH0_DMA_RX_THD_VAL_POS); //RX DMA Threshold
675 
676     channel = MXC_DMA_AcquireChannel();
677     if (channel < E_NO_ERROR) {
678         return channel;
679     }
680 
681     config.reqsel = MXC_DMA_REQUEST_I2SRX;
682 
683     config.ch = channel;
684 
685     switch (request->wordSize) {
686     case MXC_I2S_WSIZE_WORD:
687         config.srcwd = MXC_DMA_WIDTH_WORD;
688         config.dstwd = MXC_DMA_WIDTH_WORD;
689         advConfig.burst_size = 4;
690         break;
691 
692     case MXC_I2S_WSIZE_HALFWORD:
693         config.srcwd = MXC_DMA_WIDTH_WORD;
694         config.dstwd = MXC_DMA_WIDTH_HALFWORD;
695         advConfig.burst_size = 2;
696         break;
697 
698     case MXC_I2S_WSIZE_BYTE:
699         config.srcwd = MXC_DMA_WIDTH_WORD;
700         config.dstwd = MXC_DMA_WIDTH_BYTE;
701         advConfig.burst_size = 1;
702         break;
703 
704     default:
705         config.srcwd = MXC_DMA_WIDTH_WORD;
706         config.dstwd = MXC_DMA_WIDTH_BYTE;
707         advConfig.burst_size = 1;
708         break;
709     }
710 
711 #ifndef USE_LEGACY_I2S_DMA_CFG
712     advConfig.burst_size = 4;
713 #endif
714 
715     config.srcinc_en = 0;
716     config.dstinc_en = 1;
717 
718     advConfig.ch = channel;
719     advConfig.prio = MXC_DMA_PRIO_HIGH; // 0
720     advConfig.reqwait_en = 0;
721     advConfig.tosel = MXC_DMA_TIMEOUT_4_CLK; // 0
722     advConfig.pssel = MXC_DMA_PRESCALE_DISABLE; // 0
723 
724     srcdst.ch = channel;
725     srcdst.dest = dest_addr;
726     srcdst.len = len;
727 
728     MXC_DMA_ConfigChannel(config, srcdst);
729     MXC_DMA_AdvConfigChannel(advConfig);
730     MXC_DMA_SetCallback(channel, dma_cb);
731 
732     MXC_I2S_RXEnable(); //Enable I2S RX
733     i2s->dmach0 |= MXC_F_I2S_REVA_DMACH0_DMA_RX_EN; //Enable I2S DMA
734 
735     MXC_DMA_EnableInt(channel);
736     MXC_DMA_Start(channel);
737     MXC_DMA->ch[channel].ctrl |= MXC_F_DMA_CTRL_CTZ_IE;
738 
739     return channel;
740 }
741 
MXC_I2S_RevA_Handler(mxc_i2s_reva_regs_t * i2s)742 void MXC_I2S_RevA_Handler(mxc_i2s_reva_regs_t *i2s)
743 {
744     uint32_t flags = MXC_I2S_GetFlags();
745 
746     if (txn_state.txCnt == txn_req.length && txn_state.rxCnt == txn_req.length) {
747         MXC_I2S_DisableInt(MXC_F_I2S_REVA_INTEN_TX_OB_CH0 | MXC_F_I2S_REVA_INTEN_RX_THD_CH0);
748         MXC_I2S_ClearFlags(MXC_F_I2S_REVA_INTFL_TX_OB_CH0 | MXC_F_I2S_REVA_INTFL_RX_THD_CH0);
749 
750         while (i2s->dmach0 & MXC_F_I2S_REVA_DMACH0_TX_LVL) {}
751 
752         MXC_I2S_TXDisable();
753         MXC_I2S_RXDisable();
754 
755         if (async_cb != NULL && txn_state.async) {
756             async_cb(E_NO_ERROR);
757         }
758 
759         MXC_FreeLock(&txn_lock);
760     } else if (txn_req.txData != NULL && (flags & MXC_F_I2S_REVA_INTFL_TX_OB_CH0)) {
761         MXC_I2S_ClearFlags(MXC_F_I2S_REVA_INTFL_TX_OB_CH0);
762 
763         if (txn_state.txCnt < txn_req.length) {
764             txn_state.txCnt += MXC_I2S_FillTXFIFO(txn_req.txData, txn_req.wordSize,
765                                                   (txn_req.length - txn_state.txCnt),
766                                                   txn_state.txCnt);
767         }
768     } else if (txn_req.rxData != NULL && (flags & MXC_F_I2S_REVA_INTFL_RX_THD_CH0)) {
769         MXC_I2S_ClearFlags(MXC_F_I2S_REVA_INTFL_RX_THD_CH0);
770 
771         if (txn_state.rxCnt < txn_req.length) {
772             txn_state.rxCnt += MXC_I2S_ReadRXFIFO(txn_req.rxData, txn_req.wordSize,
773                                                   (txn_req.length - txn_state.rxCnt),
774                                                   txn_state.rxCnt);
775         }
776     }
777 }
778 
MXC_I2S_RevA_RegisterDMACallback(void (* callback)(int,int))779 void MXC_I2S_RevA_RegisterDMACallback(void (*callback)(int, int))
780 {
781     dma_cb = callback;
782 }
783 
MXC_I2S_RevA_RegisterAsyncCallback(void (* callback)(int))784 void MXC_I2S_RevA_RegisterAsyncCallback(void (*callback)(int))
785 {
786     async_cb = callback;
787 }
788