1 /*
2 * Copyright (c) 2019-2020, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <stdint.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdbool.h>
37
38 #ifndef DebugP_ASSERT_ENABLED
39 #define DebugP_ASSERT_ENABLED 0
40 #endif
41 #ifndef DebugP_LOG_ENABLED
42 #define DebugP_LOG_ENABLED 0
43 #endif
44
45 #include <ti/drivers/dpl/DebugP.h>
46 #include <ti/drivers/dpl/HwiP.h>
47
48 #include <ti/drivers/i2s/I2SCC32XX.h>
49 #include <ti/drivers/Power.h>
50 #include <ti/drivers/power/PowerCC32XX.h>
51 #include <ti/drivers/dma/UDMACC32XX.h>
52 #include <ti/drivers/utils/List.h>
53
54 #include <ti/devices/cc32xx/inc/hw_memmap.h>
55 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
56 #include <ti/devices/cc32xx/inc/hw_ints.h>
57 #include <ti/devices/cc32xx/inc/hw_mcasp.h>
58 #include <ti/devices/cc32xx/inc/hw_apps_config.h>
59 #include <ti/devices/cc32xx/inc/hw_types.h>
60 #include <ti/devices/cc32xx/driverlib/rom.h>
61 #include <ti/devices/cc32xx/driverlib/rom_map.h>
62 #include <ti/devices/cc32xx/driverlib/interrupt.h>
63 #include <ti/devices/cc32xx/driverlib/i2s.h>
64 #include <ti/devices/cc32xx/driverlib/prcm.h>
65 #include <ti/devices/cc32xx/driverlib/udma.h>
66
67 #define PinConfigPinMode(config) (((config) >> 8) & 0xF)
68 #define PinConfigPin(config) (((config) >> 0) & 0x3F)
69 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
70 #define PAD_RESET_STATE 0xC61
71 #define I2S_NB_CHANNELS_MAX 8U
72 #define BYTE_LENGTH 8U /* Length in bits of a byte*/
73 #define UDMA_MAX_TRANSFERLENGTH 1023 /* This is the maximum transfer length for uDMA in MODE BASIC. Transfers lengths must be inferior or equal to this value. */
74 #define HWRESOLUTION 4U /* All the settings are expressed in half-bytes (4 bits) */
75 #define PRCMI2SCLOCKFREQMIN 234377 /* Minimum Frequency (in Hz) possible with only one divider */
76 #define HCLKDIVMAX 0xFFF /* Max division of ulHClkDiv (ulHClkDiv is a 12-bit clock divider) */
77
78 #define DATA_SHIFT_NONE 0x00 /* Value to use for RXFMT.RDATDLY and TXFMT.XDATDLY if no data shift is expected */
79 #define DATA_SHIFT_1 0x01 /* Value to use for RXFMT.RDATDLY and TXFMT.XDATDLY if data are expected to shift by one - Value to use for true I2S format */
80 #define DATA_SHIFT_2 0x02 /* Value to use for RXFMT.RDATDLY and TXFMT.XDATDLY if data are expected to shift by two */
81
82 #define MCASP_RXFMCTL_FRWID_DEFAULT 0x10 /* This value is the default value to use for RXFMCTL.FRWID */
83 #define MCASP_TXFMCTL_FXWID_DEFAULT 0x10 /* This value is the default value to use for TXFMCTL.FXWID */
84 #define MCASP_RXFMCTL_RMOD_DEFAULT 0x100 /* This value is the default value to use for RXFMCTL.RMOD */
85 #define MCASP_TXFMCTL_XMOD_DEFAULT 0x100 /* This value is the default value to use for TXFMCTL.XMOD */
86 #define MCASP_AHCLKRCTL_HCLKRM_DEFAULT 0x8000 /* This value is the default value to use for AHCLKRCTL.HCLKRM */
87 #define MCASP_AHCLKXCTL_HCLKXM_DEFAULT 0x8000 /* This value is the default value to use for AHCLKXCTL.HCLKXM */
88
89 /*
90 * This lookup table is used to configure the DMA channels for the appropriate
91 * (8bit, 16bit or 32bit) transfer sizes.
92 * Table for an I2S DMA RX channel.
93 */
94 static const uint32_t dmaRxConfig[] = {
95 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8,
96 UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16,
97 UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32,
98 };
99
100 /*
101 * This lookup table is used to configure the DMA channels for the appropriate
102 * (8bit, 16bit or 32bit) transfer sizes.
103 * Table for an I2S DMA TX channel.
104 */
105 static const uint32_t dmaTxConfig[] = {
106 UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE,
107 UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE,
108 UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_NONE,
109 };
110
111 /*
112 * This lookup table is used to configure the DMA channels for the appropriate
113 * (8bit, 16bit or 32bit) transfer sizes.
114 * Table works for an both RX and TX I2S DMA channels.
115 */
116 #define UDMA_ARBLENGTH_DEFAULT 4
117 static const uint32_t dmaArbConfig [] = {
118 UDMA_ARB_1,
119 UDMA_ARB_2,
120 UDMA_ARB_4,
121 UDMA_ARB_8,
122 UDMA_ARB_16,
123 UDMA_ARB_32,
124 UDMA_ARB_64,
125 UDMA_ARB_128,
126 };
127
128 /* Forward declarations */
129 static bool initObject(I2S_Handle handle, I2S_Params *params);
130 static void initIO(I2S_Handle handle);
131 static void initDMA(I2S_Handle handle);
132 static void initHw(I2S_Handle handle);
133 static int postNotify(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg);
134
135 static void resetPin(unsigned long pinI2S);
136 static void openPin(unsigned long pinI2S);
137 static void restorePinpads(I2SCC32XX_HWAttrs const *hwAttrs);
138
139 static void configSCK(I2S_Handle handle);
140 static void configWS(I2S_Handle handle);
141 static void configSerialFormat(I2S_Handle handle);
142 static uint8_t getNumberOfChannels(const uint8_t channelsList);
143
144 static void I2S_hwiIntFxn(uintptr_t arg);
145 static void updateDataReadDMA(uintptr_t arg);
146 static void updateDataWriteDMA(uintptr_t arg);
147 static void updateDataReadCPU(uintptr_t arg);
148 static void updateDataWriteCPU(uintptr_t arg);
149 static void handleDMATransaction(I2S_Handle handle, I2S_Transaction *transaction, uint32_t transLength, I2SCC32XX_Interface *interface);
150 static void handleCPUTransaction(I2S_Handle handle, I2S_Transaction **ptrTransaction, I2SCC32XX_Interface *interface);
151
152 /* Extern globals */
153 extern const I2S_Config I2S_config[];
154 extern const uint_least8_t I2S_count;
155
156 /* Static globals */
157 static bool isInitialized = (bool)false;
158
159 /*
160 * ======== I2S_init ========
161 */
I2S_init(void)162 void I2S_init(void) {
163 uint_least8_t i;
164
165 if (!isInitialized) {
166 /* Init each instances' driver */
167 for (i = 0; i < I2S_count; i++) {
168 I2S_Handle handle = (I2S_Handle)&(I2S_config[i]);
169 I2SCC32XX_Object *object = (I2SCC32XX_Object *)handle->object;
170 object->isOpen = (bool)false;
171 }
172 /* Init as well UDMA */
173 UDMACC32XX_init();
174 isInitialized = (bool)true;
175 }
176 }
177
178 /*
179 * ======== I2S_open ========
180 */
I2S_open(uint_least8_t index,I2S_Params * params)181 I2S_Handle I2S_open(uint_least8_t index, I2S_Params *params) {
182 I2S_Handle handle;
183 I2SCC32XX_Object *object;
184 I2SCC32XX_HWAttrs const *hwAttrs;
185
186 handle = (I2S_Handle)&(I2S_config[index]);
187 object = handle->object;
188
189 /* Get the pointer to the object and hwAttrs */
190 hwAttrs = handle->hwAttrs;
191
192 DebugP_assert(index < I2S_count);
193
194 /* Check if module is initialized. */
195 if (!isInitialized || object->isOpen) {
196 handle = NULL;
197 }
198 /* Initialization of the I2S-object and verification of the parameters. */
199 else if (!initObject(handle, params)) {
200 /* The parameters provided are not correct. */
201 handle = NULL;
202 }
203 /* Set Power, set HW and register interrupts */
204 else {
205 /* Register HW interrupt */
206 HwiP_Params hwiParams;
207 HwiP_clearInterrupt(INT_I2S);
208 HwiP_Params_init(&hwiParams);
209 hwiParams.arg = (uintptr_t)handle;
210 hwiParams.priority = hwAttrs->intPriority;
211 object->hwi = HwiP_create(INT_I2S, (HwiP_Fxn)I2S_hwiIntFxn, &hwiParams);
212
213 if (object->hwi == NULL) {
214 /* HwiP creation failed */
215 handle = NULL;
216 restorePinpads(hwAttrs);
217 }
218 else {
219 object->isOpen = (bool)true;
220
221 /* Set Power */
222 Power_setDependency(PowerCC32XX_PERIPH_I2S);
223 MAP_PRCMPeripheralReset(PRCM_I2S);
224
225 /* Set DMA */
226 initDMA(handle);
227
228 /* Set HardWare */
229 initHw(handle);
230
231 Power_registerNotify(&(object->notifyObj), PowerCC32XX_AWAKE_LPDS, postNotify, (uint32_t)handle);
232
233 MAP_I2SIntDisable(I2S_BASE, 0xFFFFFFFF);
234
235 uintptr_t key = HwiP_disable();
236 /* Keep activatedFlags to be modified from somewhere else */
237 object->activatedFlag = 0;
238 HwiP_restore(key);
239 }
240 }
241
242 return handle;
243 }
244
245 /*
246 * ======== I2S_close ========
247 */
I2S_close(I2S_Handle handle)248 void I2S_close(I2S_Handle handle)
249 {
250 /* Get the pointer to the object and hwAttrs */
251 I2SCC32XX_Object *object = handle->object;
252 I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
253
254 /* Disable interrupts. */
255 MAP_I2SIntDisable(I2S_BASE, 0xFFFFFFFF);
256
257 uintptr_t key = HwiP_disable();
258 /* Keep activatedFlags to be modified from somewhere else */
259 object->activatedFlag = 0;
260 HwiP_restore(key);
261
262 /* Close the uDMA */
263 if(object->dmaHandle != NULL) {
264 UDMACC32XX_close(object->dmaHandle);
265 object->dmaHandle = NULL;
266 }
267
268 /* Delete the I2S HWI */
269 if(object->hwi != NULL) {
270 HwiP_delete(object->hwi);
271 object->hwi = NULL;
272 }
273
274 Power_unregisterNotify(&(object->notifyObj));
275 /* Release power dependency - i.e. potentially power down serial domain. */
276 Power_releaseDependency(PowerCC32XX_PERIPH_I2S);
277
278 /* Restore pin pads to their reset states */
279 restorePinpads(hwAttrs);
280
281 /* Mark the module as available */
282 object->isOpen = (bool)false;
283 }
284
285 /*
286 * ======== I2S_setReadQueueHead ========
287 */
I2S_setReadQueueHead(I2S_Handle handle,I2S_Transaction * transaction)288 void I2S_setReadQueueHead(I2S_Handle handle, I2S_Transaction *transaction){
289
290 DebugP_assert(transaction != 0x0);
291
292 I2SCC32XX_Object *object = handle->object;
293 I2SCC32XX_Interface *interface = &object->read;
294
295 interface->activeTransfer = transaction;
296 }
297
298 /*
299 * ======== I2S_setWriteQueueHead ========
300 */
I2S_setWriteQueueHead(I2S_Handle handle,I2S_Transaction * transaction)301 void I2S_setWriteQueueHead(I2S_Handle handle, I2S_Transaction *transaction){
302
303 DebugP_assert(transaction != 0x0);
304
305 I2SCC32XX_Object *object = handle->object;
306 I2SCC32XX_Interface *interface = &object->write;
307
308 interface->activeTransfer = transaction;
309 }
310
311 /*
312 * ======== I2S_startClocks ========
313 */
I2S_startClocks(I2S_Handle handle)314 void I2S_startClocks(I2S_Handle handle) {
315
316 I2SCC32XX_Object *object = handle->object;
317
318 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
319
320 uint8_t mode = ((object->noOfInputs != 0)? 1:0) << 1 |
321 ((object->noOfOutputs != 0)? 1:0) << 0;
322
323 MAP_I2SIntEnable(I2S_BASE, I2S_INT_RSYNCERR | I2S_INT_XSYNCERR);
324
325 uintptr_t key = HwiP_disable();
326 /* Keep activatedFlags to be modified from somewhere else */
327 object->activatedFlag |= I2S_STS_RSYNCERR | I2S_STS_XSYNCERR;
328 HwiP_restore(key);
329
330 MAP_I2SEnable(I2S_BASE, (unsigned long)mode);
331 }
332
333 /*
334 * ======== I2S_stopClocks ========
335 */
I2S_stopClocks(I2S_Handle handle)336 void I2S_stopClocks(I2S_Handle handle) {
337
338 I2SCC32XX_Object *object = handle->object;
339
340 /* Wait for the transfers to be properly terminated */
341 while(object->isLastReadTransfer || object->isLastWriteTransfer);
342
343 MAP_I2SIntDisable(I2S_BASE, I2S_INT_RSYNCERR | I2S_INT_XSYNCERR);
344
345 uintptr_t key = HwiP_disable();
346 /* Keep activatedFlags to be modified from somewhere else */
347 object->activatedFlag &= ~(I2S_STS_RSYNCERR | I2S_STS_XSYNCERR);
348 HwiP_restore(key);
349
350 MAP_I2SDisable(I2S_BASE);
351 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
352 }
353
354 /*
355 * ======== I2S_startRead ========
356 */
I2S_startRead(I2S_Handle handle)357 void I2S_startRead(I2S_Handle handle) {
358
359 I2SCC32XX_Object *object = handle->object;
360 I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
361 I2SCC32XX_DataInterface *SD0;
362 I2SCC32XX_DataInterface *SD1;
363
364 /* Get the pointer to the SD0 and SD1 interfaces */
365 SD0 = &object->dataInterfaceSD0;
366 SD1 = &object->dataInterfaceSD1;
367
368 if(object->noOfInputs != 0) {
369
370 uintptr_t key = HwiP_disable();
371 if(object->isDMAUnused) {
372 /* Enable I2S_INT_RDATA | I2S_INT_ROVRN */
373 HWREG(I2S_BASE + MCASP_O_EVTCTLR) |= (((I2S_INT_RDATA | I2S_INT_ROVRN) >> 16) & 0xFF);
374 object->activatedFlag |= I2S_STS_ROVERN | I2S_STS_RDATA;
375 object->updateDataReadFxn((uintptr_t)handle);
376 }
377 else {
378 /* Turn on the DMA channel of the I2S Read interface */
379 MAP_uDMAChannelAttributeEnable(hwAttrs->rxChannelIndex,UDMA_ATTR_USEBURST);
380 MAP_uDMAChannelAssign(hwAttrs->rxChannelIndex);
381 object->updateDataReadFxn((uintptr_t)handle);
382 MAP_I2SRxFIFOEnable(I2S_BASE, object->udmaArbLength, object->noOfInputs);
383
384 /* Enable I2S_INT_RDMA | I2S_INT_ROVRN | I2S_INT_RLAST */
385 /* Note: we do not activate the I2S_STS_RDMAERR flag (uDMA's responsibility) */
386 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR ) |= (((I2S_INT_RDMA | I2S_INT_ROVRN | I2S_INT_RLAST) &0xC0000000) >> 20);
387 HWREG(I2S_BASE + MCASP_O_EVTCTLR) |= (((I2S_INT_RDMA | I2S_INT_ROVRN | I2S_INT_RLAST) >> 16) & 0xFF);
388 object->activatedFlag |= I2S_STS_RLAST | I2S_STS_ROVERN | I2S_STS_RDMA;
389 }
390 HwiP_restore(key);
391
392 if(SD0->interfaceConfig == I2S_SD0_INPUT) {
393 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_RX, I2S_INACT_LOW_LEVEL);
394 }
395 if(SD1->interfaceConfig == I2S_SD1_INPUT) {
396 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_RX, I2S_INACT_LOW_LEVEL);
397 }
398 }
399 }
400
401 /*
402 * ======== I2S_startWrite ========
403 */
I2S_startWrite(I2S_Handle handle)404 void I2S_startWrite(I2S_Handle handle) {
405
406 I2SCC32XX_Object *object = handle->object;
407 I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
408 I2SCC32XX_DataInterface *SD0;
409 I2SCC32XX_DataInterface *SD1;
410
411 /* Get the pointer to the SD0 and SD1 interfaces */
412 SD0 = &object->dataInterfaceSD0;
413 SD1 = &object->dataInterfaceSD1;
414
415 if(object->noOfOutputs != 0) {
416
417 uintptr_t key = HwiP_disable();
418 if(object->isDMAUnused) {
419 /* Enable I2S_INT_XDATA | I2S_INT_XUNDRN */
420 HWREG(I2S_BASE + MCASP_O_EVTCTLX) |= ((I2S_INT_XDATA | I2S_INT_XUNDRN) & 0xFF);
421 object->activatedFlag |= I2S_STS_XDATA | I2S_STS_XUNDRN;
422 object->updateDataWriteFxn((uintptr_t)handle);
423 }
424 else {
425 /* Turn on the DMA channel of the I2S Write interface */
426 MAP_uDMAChannelAttributeEnable(hwAttrs->txChannelIndex,UDMA_ATTR_USEBURST);
427 MAP_uDMAChannelAssign(hwAttrs->txChannelIndex);
428 object->updateDataWriteFxn((uintptr_t)handle);
429 MAP_I2STxFIFOEnable(I2S_BASE, object->udmaArbLength, object->noOfOutputs);
430
431 /* Enable I2S_INT_XDMA | I2S_INT_XLAST | I2S_INT_XUNDRN */
432 /* Note: we do not activate the I2S_STS_XDMAERR flag (uDMA's responsibility) */
433 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR ) |= (((I2S_INT_XDMA | I2S_INT_XLAST | I2S_INT_XUNDRN) &0xC0000000) >> 20);
434 HWREG(I2S_BASE + MCASP_O_EVTCTLX) |= ((I2S_INT_XDMA | I2S_INT_XLAST | I2S_INT_XUNDRN) & 0xFF);
435 object->activatedFlag |= I2S_STS_XLAST | I2S_STS_XUNDRN | I2S_STS_XDMA;
436 }
437 HwiP_restore(key);
438
439 if(SD0->interfaceConfig == I2S_SD0_OUTPUT) {
440 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_TX, I2S_INACT_LOW_LEVEL);
441 }
442 if(SD1->interfaceConfig == I2S_SD1_OUTPUT) {
443 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_TX, I2S_INACT_LOW_LEVEL);
444 }
445 }
446 }
447
448 /*
449 * ======== I2S_stopRead ========
450 */
I2S_stopRead(I2S_Handle handle)451 void I2S_stopRead(I2S_Handle handle) {
452
453 I2SCC32XX_Object *object = handle->object;
454 I2SCC32XX_DataInterface *SD0;
455 I2SCC32XX_DataInterface *SD1;
456
457 /* Get the pointer to the SD0 and SD1 interfaces*/
458 SD0 = &object->dataInterfaceSD0;
459 SD1 = &object->dataInterfaceSD1;
460
461 if(object->noOfInputs != 0) {
462
463 if(!object->isDMAUnused) {
464 /* To stop the Read interface, we must wait for the end of the current DMA transaction*/
465 object->isLastReadTransfer = (bool)true;
466 }
467 else {
468
469 MAP_I2SIntDisable(I2S_BASE, I2S_INT_RDMA | I2S_INT_ROVRN );
470
471 uintptr_t key = HwiP_disable();
472 /* Keep activatedFlag to be modified from somewhere else */
473 object->activatedFlag &= ~(I2S_STS_RDMA | I2S_STS_ROVERN);
474 HwiP_restore(key);
475
476 if(SD0->interfaceConfig == I2S_SD0_INPUT) {
477 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
478 }
479 if(SD1->interfaceConfig == I2S_SD1_INPUT) {
480 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
481 }
482 }
483 }
484 }
485
486 /*
487 * ======== I2S_stopWrite ========
488 */
I2S_stopWrite(I2S_Handle handle)489 void I2S_stopWrite(I2S_Handle handle) {
490
491 I2SCC32XX_Object *object = handle->object;
492 I2SCC32XX_DataInterface *SD0;
493 I2SCC32XX_DataInterface *SD1;
494
495 /* Get the pointer to the SD0 and SD1 interfaces*/
496 SD0 = &object->dataInterfaceSD0;
497 SD1 = &object->dataInterfaceSD1;
498
499 if(object->noOfOutputs != 0) {
500
501 if(!object->isDMAUnused) {
502 /* To stop the Write interface, we must wait for the end of the current DMA transaction*/
503 object->isLastWriteTransfer = (bool)true;
504 }
505 else {
506
507 MAP_I2SIntDisable(I2S_BASE, I2S_INT_XDMA | I2S_INT_XUNDRN);
508
509 uintptr_t key = HwiP_disable();
510 /* Keep activatedFlag to be modified from somewhere else */
511 object->activatedFlag &= ~(I2S_STS_XDMA | I2S_STS_XUNDRN);
512 HwiP_restore(key);
513
514 if(SD0->interfaceConfig == I2S_SD0_OUTPUT) {
515 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
516 }
517 if(SD1->interfaceConfig == I2S_SD1_OUTPUT) {
518 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
519 }
520 }
521 }
522 }
523
524 /*
525 * ======== initHw ========
526 * This functions initializes the I2S hardware module.
527 *
528 * @pre Function assumes that the I2S handle is pointing to a hardware
529 * module which has already been opened.
530 */
initHw(I2S_Handle handle)531 static void initHw(I2S_Handle handle) {
532
533 /* Configure IOs */
534 initIO(handle);
535 /* Configure SCK clock (including sampling edge) */
536 configSCK(handle);
537 /* Configure WS clock (including WS inversion) */
538 configWS(handle);
539 /* Configure serial format (data-length, DMA use, MSB/LSB first, data padding, channels activated) */
540 configSerialFormat(handle);
541 }
542
543 /*
544 * ======== I2S_hwiIntFxn ========
545 * Hwi function that processes I2S interrupts.
546 */
I2S_hwiIntFxn(uintptr_t arg)547 static void I2S_hwiIntFxn(uintptr_t arg) {
548
549 I2S_Handle handle = (I2S_Handle)arg;
550 I2SCC32XX_Object const *object = handle->object;
551 uint16_t errStatus = 0U;
552
553 /* Read and clear all the interrupt flags */
554 /* Note: in CPU mode, RDATA and XDATA flags must be cleared AFTER data update */
555 uint32_t rawInterruptStatus = (uint32_t)MAP_I2SIntStatus(I2S_BASE);
556 if(object->isDMAUnused) {
557 MAP_I2SIntClear(I2S_BASE, rawInterruptStatus & ~I2S_STS_RDATA & ~I2S_STS_XDATA);
558 }
559 else {
560 MAP_I2SIntClear(I2S_BASE, rawInterruptStatus);
561 }
562
563 /* Filter the interrupt-status to only consider the activated flags */
564 uint32_t interruptStatus = (rawInterruptStatus & object->activatedFlag);
565
566
567 /* Normal work */
568 if((interruptStatus & (uint32_t)(I2S_STS_RLAST | I2S_STS_RDATA | I2S_STS_RDMA)) != 0U)
569 {
570 object->updateDataReadFxn(arg);
571 }
572
573 if((interruptStatus & (uint32_t)(I2S_STS_XLAST | I2S_STS_XDATA | I2S_STS_XDMA)) != 0U)
574 {
575 object->updateDataWriteFxn(arg);
576 }
577
578 /* Read errors */
579 if((interruptStatus & (uint32_t)I2S_STS_ROVERN ) != 0U)
580 {
581 errStatus |= I2S_PTR_READ_ERROR;
582 }
583
584 if((interruptStatus & (uint32_t)I2S_STS_RSYNCERR) != 0U)
585 {
586 errStatus |= I2S_TIMEOUT_ERROR;
587 }
588
589 if((interruptStatus & (uint32_t)I2S_STS_RDMAERR ) != 0U)
590 {
591 errStatus |= I2S_BUS_ERROR;
592 }
593
594 /* Write errors */
595 if((interruptStatus & (uint32_t)I2S_STS_XUNDRN ) != 0U)
596 {
597 errStatus |= I2S_PTR_WRITE_ERROR;
598 }
599
600 if((interruptStatus & (uint32_t)I2S_STS_XSYNCERR) != 0U)
601 {
602 errStatus |= I2S_WS_ERROR;
603 }
604
605 if((interruptStatus & (uint32_t)I2S_STS_XDMAERR ) != 0U)
606 {
607 errStatus |= I2S_BUS_ERROR;
608 }
609
610 /* Triggering of the error-Callback (only one call, with potentially several status bits activated) */
611 if(errStatus != 0U) {
612 object->errorCallback(handle, errStatus, NULL);
613 }
614 }
615
616 /*
617 * ======== updateDataReadDMA ========
618 */
updateDataReadDMA(uintptr_t arg)619 static void updateDataReadDMA(uintptr_t arg) {
620 I2S_Handle handle = (I2S_Handle)arg;
621 I2SCC32XX_Object *object = handle->object;
622 I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
623
624 /* Wait for the mode to be changed to "stopped" */
625 if(MAP_uDMAChannelModeGet(hwAttrs->rxChannelIndex) == UDMA_MODE_STOP){
626
627 if(!object->isLastReadTransfer) {
628
629 I2S_Transaction *transaction = (I2S_Transaction *)object->read.activeTransfer;
630 if(transaction != NULL) {
631
632 uint32_t transLength = transaction->bufSize - transaction->bytesTransferred; /* transfer length expressed in bytes */
633 transLength = transLength / (object->memorySlotLength / BYTE_LENGTH); /* expressed in number of samples (number of atomic DMA transfers) */
634 transLength = (transLength > UDMA_MAX_TRANSFERLENGTH)? UDMA_MAX_TRANSFERLENGTH : transLength; /* the transfer length of the uDMA is limited */
635 transLength = transLength - (transLength % object->udmaArbLength); /* taking in consideration the limitation of the DMA (DMA copies each time UDMA_ARB_x samples) */
636
637 MAP_uDMAChannelControlSet(hwAttrs->rxChannelIndex,
638 object->read.udmaConfig);
639 MAP_uDMAChannelTransferSet(hwAttrs->rxChannelIndex,
640 UDMA_MODE_BASIC,
641 (void *)I2S_RX_DMA_PORT,
642 (void *)((uint32_t)transaction->bufPtr + transaction->bytesTransferred),
643 transLength);
644
645 MAP_uDMAChannelEnable(hwAttrs->rxChannelIndex);
646
647 transLength = transLength * (object->memorySlotLength / BYTE_LENGTH); /* handleDMATransaction() expects transLength in bytes (not in samples): re-convert transLength in bytes */
648 handleDMATransaction(handle, transaction, transLength, &object->read);
649 }
650 }
651 else {
652 I2SCC32XX_DataInterface *SD0;
653 I2SCC32XX_DataInterface *SD1;
654
655 /* Get the pointer to the SD0 and SD1 interfaces*/
656 SD0 = &object->dataInterfaceSD0;
657 SD1 = &object->dataInterfaceSD1;
658
659 MAP_I2SIntDisable(I2S_BASE, I2S_INT_RLAST | I2S_INT_RDMA | I2S_INT_ROVRN);
660 object->activatedFlag &= ~(I2S_STS_RLAST | I2S_STS_RDMA | I2S_STS_ROVERN);
661
662 MAP_I2SRxFIFODisable(I2S_BASE);
663
664 if(SD0->interfaceConfig == I2S_SD0_INPUT) {
665 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
666 }
667 if(SD1->interfaceConfig == I2S_SD1_INPUT) {
668 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
669 }
670
671 object->isLastReadTransfer = (bool)false;
672 }
673 }
674 }
675
676 /*
677 * ======== updateDataWriteDMA ========
678 */
updateDataWriteDMA(uintptr_t arg)679 static void updateDataWriteDMA(uintptr_t arg) {
680 I2S_Handle handle = (I2S_Handle)arg;
681 I2SCC32XX_Object *object = handle->object;
682 I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
683 I2SCC32XX_DataInterface *SD0;
684 I2SCC32XX_DataInterface *SD1;
685
686 /* Wait for the mode to be changed to "stopped" */
687 if(MAP_uDMAChannelModeGet(hwAttrs->txChannelIndex) == UDMA_MODE_STOP){
688
689 if(!object->isLastWriteTransfer) {
690 I2S_Transaction *transaction = (I2S_Transaction *)object->write.activeTransfer;
691 if(transaction != NULL) {
692
693 uint32_t transLength = transaction->bufSize - transaction->bytesTransferred; /* transfer length expressed in bits */
694 transLength = transLength / (object->memorySlotLength / BYTE_LENGTH); /* expressed in number of samples (number of atomic DMA transfers) */
695 transLength = (transLength > UDMA_MAX_TRANSFERLENGTH)? UDMA_MAX_TRANSFERLENGTH : transLength; /* the transfer length of the uDMA is limited */
696 transLength = transLength - (transLength % object->udmaArbLength); /* taking in consideration the limitation of the DMA (DMA copies each time UDMA_ARB_x samples) */
697
698 MAP_uDMAChannelControlSet(hwAttrs->txChannelIndex,
699 object->write.udmaConfig);
700 MAP_uDMAChannelTransferSet(hwAttrs->txChannelIndex,
701 UDMA_MODE_BASIC,
702 (void *)((uint32_t)transaction->bufPtr + transaction->bytesTransferred),
703 (void *)I2S_TX_DMA_PORT,
704 transLength);
705
706 MAP_uDMAChannelEnable(hwAttrs->txChannelIndex);
707
708 transLength = transLength * (object->memorySlotLength / BYTE_LENGTH); /* handleDMATransaction() expects transLength in bytes (not in samples): re-convert transLength in bytes */
709 handleDMATransaction(handle, transaction, transLength, &object->write);
710 }
711 }
712
713 else {
714
715 /* Get the pointer to the SD0 and SD1 interfaces*/
716 SD0 = &object->dataInterfaceSD0;
717 SD1 = &object->dataInterfaceSD1;
718
719 MAP_I2SIntDisable(I2S_BASE, I2S_INT_XDMA | I2S_INT_XUNDRN | I2S_INT_XLAST);
720 object->activatedFlag &= ~(I2S_STS_XDMA | I2S_STS_XUNDRN | I2S_STS_XLAST);
721
722 MAP_I2STxFIFODisable(I2S_BASE);
723
724 if(SD0->interfaceConfig == I2S_SD0_OUTPUT) {
725 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
726 }
727 if(SD1->interfaceConfig == I2S_SD1_OUTPUT) {
728 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
729 }
730
731 object->isLastWriteTransfer = (bool)false;
732 }
733 }
734 }
735
736 /*
737 * ======== handleDMATransaction ========
738 * This function avoid to duplicate the code dedicated to take care of the transactions in DMA mode.
739 * This function remove the transaction from the list and trigger the user callback.
740 *
741 */
handleDMATransaction(I2S_Handle handle,I2S_Transaction * transactionFinished,uint32_t transLength,I2SCC32XX_Interface * interface)742 static void handleDMATransaction(I2S_Handle handle,
743 I2S_Transaction *transactionFinished,
744 uint32_t transLength,
745 I2SCC32XX_Interface *interface){
746
747 I2SCC32XX_Object *object = handle->object;
748
749 /* Is the transaction finished? (i.e. all the element are sent or we cannot perform the next DMA) */
750 uint16_t dmaMinimumStep = object->udmaArbLength * object->memorySlotLength / BYTE_LENGTH;
751 if(((transactionFinished->bytesTransferred + transLength + dmaMinimumStep) > transactionFinished->bufSize)) {
752
753 /* This transaction is finished */
754 interface->activeTransfer = (I2S_Transaction*)List_next(&transactionFinished->queueElement);
755
756 transactionFinished->untransferredBytes = transactionFinished->bufSize - transLength;
757 transactionFinished->numberOfCompletions ++;
758 transactionFinished->bytesTransferred = 0;
759
760 if(interface->activeTransfer == NULL) {
761 interface->callback(handle, I2S_ALL_TRANSACTIONS_SUCCESS, transactionFinished);
762
763 /* If needed the interface must be stopped */
764 if(interface->activeTransfer != NULL){
765 /* Application called I2S_setXxxxQueueHead()
766 * -> new transfers can be executed next time */
767 }
768 else if((I2S_Transaction*)List_next(&transactionFinished->queueElement) != NULL){
769 /* Application queued transactions after the transaction finished
770 * -> activeTransfer must be modified and transfers can be executed next time */
771 interface->activeTransfer = (I2S_Transaction*)List_next(&transactionFinished->queueElement);
772 }
773 else {
774 /* Application did nothing, we need to stop the interface to avoid errors */
775 interface->stopInterface(handle);
776 }
777 }
778 else {
779 interface->callback(handle, I2S_TRANSACTION_SUCCESS, transactionFinished);
780 }
781 }
782 else{
783 transactionFinished->bytesTransferred += transLength;
784 }
785 }
786
787 /*
788 * ======== updateDataReadCPU ========
789 */
updateDataReadCPU(uintptr_t arg)790 static void updateDataReadCPU(uintptr_t arg) {
791 I2S_Handle handle = (I2S_Handle)arg;
792 I2SCC32XX_Object *object = handle->object;
793 I2SCC32XX_DataInterface *SD0;
794 I2SCC32XX_DataInterface *SD1;
795
796 /* Get the pointer to the SD0 and SD1 interfaces*/
797 SD0 = &object->dataInterfaceSD0;
798 SD1 = &object->dataInterfaceSD1;
799
800 I2S_Transaction *transaction = (I2S_Transaction *)object->read.activeTransfer;
801 if(transaction != NULL) {
802
803 bool dataKO = (bool)false;
804 uint32_t *ptrValue;
805 ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
806
807 while((!dataKO) && (transaction != NULL)) {
808
809 if((SD0->interfaceConfig == I2S_SD0_INPUT) && (transaction != NULL) && (!dataKO)) {
810
811 dataKO |= MAP_I2SDataGetNonBlocking(I2S_BASE, SD0->dataLine, (unsigned long*)ptrValue);
812
813 if(!dataKO) {
814
815 handleCPUTransaction(handle, &transaction, &object->read);
816
817 if(transaction != NULL){
818 ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
819 }
820 }
821 }
822
823 if((SD1->interfaceConfig == I2S_SD1_INPUT) && (transaction != NULL) && (!dataKO)) {
824
825 dataKO |= MAP_I2SDataGetNonBlocking(I2S_BASE, SD1->dataLine, (unsigned long*)ptrValue);
826
827 if(!dataKO) {
828
829 handleCPUTransaction(handle, &transaction, &object->read);
830
831 if(transaction != NULL){
832 ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
833 }
834 }
835 }
836 }
837 }
838
839 /* In CPU mode interrupt clearing must be done AFTER data update */
840 MAP_I2SIntClear(I2S_BASE,I2S_STS_RDATA);
841 }
842
843 /*
844 * ======== updateDataWriteCPU ========
845 */
updateDataWriteCPU(uintptr_t arg)846 static void updateDataWriteCPU(uintptr_t arg) {
847 I2S_Handle handle = (I2S_Handle)arg;
848 I2SCC32XX_Object *object = handle->object;
849 I2SCC32XX_DataInterface *SD0;
850 I2SCC32XX_DataInterface *SD1;
851
852 /* Get the pointer to the SD0 and SD1 interfaces*/
853 SD0 = &object->dataInterfaceSD0;
854 SD1 = &object->dataInterfaceSD1;
855
856 I2S_Transaction *transaction = (I2S_Transaction *)object->write.activeTransfer;
857 if(transaction != NULL) {
858
859 bool dataKO = (bool)false;
860 uint32_t Value;
861 uint32_t *ptrValue = &Value;
862 ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
863 Value = *ptrValue;
864
865 while((!dataKO) && (transaction != NULL)) {
866
867 if((SD0->interfaceConfig == I2S_SD0_OUTPUT) && (transaction != NULL) && (!dataKO)) {
868
869 dataKO |= MAP_I2SDataPutNonBlocking(I2S_BASE, SD0->dataLine, Value);
870
871 if(!dataKO) {
872
873 handleCPUTransaction(handle, &transaction, &object->write);
874
875 if(transaction != NULL){
876 ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
877 Value = *ptrValue;
878 }
879 }
880 }
881
882 if((SD1->interfaceConfig == I2S_SD1_OUTPUT) && (transaction != NULL) && (!dataKO)) {
883
884 dataKO |= MAP_I2SDataPutNonBlocking(I2S_BASE, SD1->dataLine, Value);
885
886 if(!dataKO) {
887
888 handleCPUTransaction(handle, &transaction, &object->write);
889
890 if(transaction != NULL){
891 ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
892 Value = *ptrValue;
893 }
894 }
895 }
896 }
897 }
898
899 /* In CPU mode interrupt clearing must be done AFTER data update */
900 MAP_I2SIntClear(I2S_BASE,I2S_STS_XDATA);
901 }
902
903 /*
904 * ======== handleCPUTransaction ========
905 * This function avoid to duplicate the code dedicated to take care of the transactions in CPU mode.
906 * If needed, this function remove the transaction from the list and trigger the user callback.
907 */
handleCPUTransaction(I2S_Handle handle,I2S_Transaction ** ptrTransaction,I2SCC32XX_Interface * interface)908 static void handleCPUTransaction(I2S_Handle handle,
909 I2S_Transaction **ptrTransaction,
910 I2SCC32XX_Interface *interface){
911
912 I2SCC32XX_Object const *object = handle->object;
913 I2S_Transaction *transaction = *ptrTransaction;
914
915 transaction->bytesTransferred += object->memorySlotLength / BYTE_LENGTH;
916
917 if(transaction->bytesTransferred >= transaction->bufSize){
918
919 /* We note the transaction as finished */
920 transaction->numberOfCompletions ++;
921 transaction->untransferredBytes = transaction->bufSize - transaction->bytesTransferred;
922 transaction->bytesTransferred = 0;
923
924 /* We now take in consideration the next transaction */
925 interface->activeTransfer = (I2S_Transaction*)List_next(&transaction->queueElement);
926 *ptrTransaction = (I2S_Transaction*)interface->activeTransfer; /* transaction pointer must be updated because
927 * it is potentially reused by the calling function */
928
929 I2S_Transaction *newTransaction = *ptrTransaction;
930 if(newTransaction == NULL){
931 /* It's too late for the user to queue new transactions: the hardware is already running out of data */
932 interface->stopInterface(handle);
933 }
934 else if(List_next(&newTransaction->queueElement) == NULL) {
935 interface->callback(handle, I2S_ALL_TRANSACTIONS_SUCCESS, transaction);
936 }
937 else {
938 interface->callback(handle, I2S_TRANSACTION_SUCCESS, transaction);
939 }
940 }
941 }
942
943 /*
944 * ======== initObject ========
945 */
initObject(I2S_Handle handle,I2S_Params * params)946 static bool initObject(I2S_Handle handle, I2S_Params *params) {
947
948 I2SCC32XX_Object *object = handle->object;
949 I2SCC32XX_DataInterface *SD0;
950 I2SCC32XX_DataInterface *SD1;
951
952 uint8_t indexDmaConfig = 0;
953 uint8_t indexDmaArbConfig = 0;
954
955 bool retVal = (bool)true;
956
957 /* Get the pointer to the SD0 and SD1 interfaces*/
958 SD0 = &object->dataInterfaceSD0;
959 SD1 = &object->dataInterfaceSD1;
960
961 object->moduleRole = params->moduleRole;
962 object->invertWS = params->invertWS;
963 object->samplingEdge = params->samplingEdge;
964 object->isMSBFirst = params->isMSBFirst;
965 object->samplingFrequency = params->samplingFrequency;
966 object->dataShift = (params->trueI2sFormat)? DATA_SHIFT_1 : DATA_SHIFT_NONE;
967 object->isLastReadTransfer = (bool)false;
968 object->isLastWriteTransfer = (bool)false;
969
970 DebugP_assert(params->memorySlotLength == I2S_MEMORY_LENGTH_8BITS ||
971 params->memorySlotLength == I2S_MEMORY_LENGTH_16BITS ||
972 params->memorySlotLength == I2S_MEMORY_LENGTH_24BITS ||
973 params->memorySlotLength == I2S_MEMORY_LENGTH_32BITS );
974
975 if(!params->isDMAUnused){
976 if(params->memorySlotLength <= I2S_MEMORY_LENGTH_8BITS){
977 indexDmaConfig = 0;
978 object->memorySlotLength = I2S_MEMORY_LENGTH_8BITS;
979 }
980 else if(params->memorySlotLength <= I2S_MEMORY_LENGTH_16BITS){
981 indexDmaConfig = 1;
982 object->memorySlotLength = I2S_MEMORY_LENGTH_16BITS;
983 }
984 else if(params->memorySlotLength <= I2S_MEMORY_LENGTH_32BITS){
985 indexDmaConfig = 2;
986 object->memorySlotLength = I2S_MEMORY_LENGTH_32BITS;
987 }
988 else {
989 retVal = (bool)false;
990 }
991 }
992 else {
993 indexDmaConfig = 0;
994 object->memorySlotLength = params->memorySlotLength;
995 }
996
997 /* Computation of the sampleMask and the sampleRotation (to achieve before and after word padding) */
998 if(params->beforeWordPadding + params->bitsPerWord + params->afterWordPadding <= 32) {
999 object->dataLength = params->beforeWordPadding + params->bitsPerWord + params->afterWordPadding;
1000
1001 /* This is the default setting. Data are right aligned. */
1002 object->sampleMask = 0xFFFFFFFF >> (32-object->memorySlotLength);
1003 object->sampleRotation = (object->dataLength / HWRESOLUTION) % BYTE_LENGTH;
1004
1005 /* Data truncation is made by masking the LSB of the samples. Data are still right aligned. */
1006 if(params->bitsPerWord < object->memorySlotLength) {
1007 object->sampleMask &= (0xFFFFFFFF << (object->memorySlotLength - params->bitsPerWord));
1008 object->sampleRotation += ((object->memorySlotLength - params->bitsPerWord) / HWRESOLUTION) % BYTE_LENGTH;
1009 }
1010
1011 /* Data padding is made by increasing the left rotation (i.e. decreasing right rotation) */
1012 if(params->bitsPerWord > object->memorySlotLength) {
1013 object->sampleRotation -= ((params->bitsPerWord - object->memorySlotLength) / HWRESOLUTION) % BYTE_LENGTH;
1014 }
1015
1016 /* After word padding is made by increasing the left rotation (i.e. decreasing right rotation) */
1017 if(params->afterWordPadding) {
1018 object->sampleRotation -= (params->afterWordPadding / HWRESOLUTION) % BYTE_LENGTH;
1019 }
1020 }
1021 else {
1022 retVal = (bool)false;
1023 }
1024
1025 object->isDMAUnused = params->isDMAUnused;
1026 if(object->isDMAUnused) {
1027 object->updateDataReadFxn = updateDataReadCPU;
1028 object->updateDataWriteFxn = updateDataWriteCPU;
1029 }
1030 else {
1031 object->updateDataReadFxn = updateDataReadDMA;
1032 object->updateDataWriteFxn = updateDataWriteDMA;
1033 }
1034
1035 SD0->interfaceConfig = params->SD0Use;
1036 SD0->channelsUsed = params->SD0Channels;
1037 SD0->numberOfChannelsUsed = getNumberOfChannels((uint8_t)SD0->channelsUsed);
1038 SD0->dataLine = I2S_DATA_LINE_0;
1039 SD1->interfaceConfig = params->SD1Use;
1040 SD1->channelsUsed = params->SD1Channels;
1041 SD1->numberOfChannelsUsed = getNumberOfChannels((uint8_t)SD1->channelsUsed);
1042 SD1->dataLine = I2S_DATA_LINE_1;
1043
1044 object->noOfInputs = ((SD0->interfaceConfig == I2S_SD0_INPUT)? 1: 0)
1045 + ((SD1->interfaceConfig == I2S_SD1_INPUT)? 1: 0);
1046 object->noOfOutputs = ((SD0->interfaceConfig == I2S_SD0_OUTPUT)? 1: 0)
1047 + ((SD1->interfaceConfig == I2S_SD1_OUTPUT)? 1: 0);
1048
1049 /* Here we are looking for the biggest possible uDMA arbitration length */
1050 if(params->fixedBufferLength == 0) {
1051 retVal = (bool)false;
1052 }
1053 else {
1054 if(params->fixedBufferLength != 1) {
1055 uint16_t const fixedBufferLength = (params->fixedBufferLength /(object->memorySlotLength/BYTE_LENGTH));
1056 int i;
1057
1058 /* The udmaArbLength minimum value is 2 (= 2^1)*/
1059 object->udmaArbLength = 2;
1060 /* The udmaArbLength maximum value is 16 (= 2^4)*/
1061 for(i=2; i<=4; i++) {
1062 if(fixedBufferLength % (1 << i) == 0) {
1063 object->udmaArbLength = 1 << i;
1064 }
1065 }
1066 }
1067 else {
1068 object->udmaArbLength = UDMA_ARBLENGTH_DEFAULT;
1069 }
1070 }
1071
1072 /* Authorized Arbitration values are limited to 2, 4, 8, 16 */
1073 DebugP_assert(object->udmaArbLength == 2 ||
1074 object->udmaArbLength == 4 ||
1075 object->udmaArbLength == 8 ||
1076 object->udmaArbLength == 16 );
1077
1078 int i;
1079 for(i=0; i<BYTE_LENGTH; i++) {
1080 if(object->udmaArbLength == (1 << i)) {
1081 indexDmaArbConfig = i;
1082 }
1083 }
1084
1085 object->read.udmaConfig = dmaRxConfig[indexDmaConfig] | dmaArbConfig[indexDmaArbConfig];
1086 object->read.stopInterface = I2S_stopRead;
1087 object->read.callback = params->readCallback;
1088 if((object->read.callback == NULL) && (object->noOfInputs != 0U)) {
1089 retVal = (bool)false;
1090 }
1091
1092 object->write.udmaConfig = dmaTxConfig[indexDmaConfig] | dmaArbConfig[indexDmaArbConfig];
1093 object->write.stopInterface = I2S_stopWrite;
1094 object->write.callback = params->writeCallback;
1095 if((object->write.callback == NULL) && (object->noOfOutputs != 0U)) {
1096 retVal = (bool)false;
1097 }
1098
1099 object->errorCallback = params->errorCallback;
1100 if(object->errorCallback == NULL) {
1101 retVal = (bool)false;
1102 }
1103
1104 object->read.activeTransfer = NULL;
1105 object->write.activeTransfer = NULL;
1106
1107 return retVal;
1108 }
1109
1110 /*
1111 * ======== initIO ========
1112 */
initIO(I2S_Handle handle)1113 static void initIO(I2S_Handle handle) {
1114
1115 I2SCC32XX_HWAttrs const *hwAttrs;
1116
1117 /* Get the pointer to the object and hwAttrs */
1118 hwAttrs = handle->hwAttrs;
1119
1120 DebugP_assert(hwAttrs->pinSD1 == I2SCC32XX_PIN_50_SD1 ||
1121 hwAttrs->pinSD1 == I2SCC32XX_PIN_60_SD1 ||
1122 hwAttrs->pinSD1 == I2SCC32XX_PIN_UNUSED);
1123
1124 DebugP_assert(hwAttrs->pinSD0 == I2SCC32XX_PIN_45_SD0 ||
1125 hwAttrs->pinSD0 == I2SCC32XX_PIN_50_SD0 ||
1126 hwAttrs->pinSD0 == I2SCC32XX_PIN_52_SD0 ||
1127 hwAttrs->pinSD0 == I2SCC32XX_PIN_64_SD0 ||
1128 hwAttrs->pinSD0 == I2SCC32XX_PIN_UNUSED);
1129
1130 DebugP_assert(hwAttrs->pinSCK == I2SCC32XX_PIN_03_SCK ||
1131 hwAttrs->pinSCK == I2SCC32XX_PIN_52_SCK ||
1132 hwAttrs->pinSCK == I2SCC32XX_PIN_53_SCK ||
1133 hwAttrs->pinSCK == I2SCC32XX_PIN_UNUSED);
1134
1135 DebugP_assert(hwAttrs->pinWS == I2SCC32XX_PIN_02_WS ||
1136 hwAttrs->pinWS == I2SCC32XX_PIN_15_WS ||
1137 hwAttrs->pinWS == I2SCC32XX_PIN_17_WS ||
1138 hwAttrs->pinWS == I2SCC32XX_PIN_21_WS ||
1139 hwAttrs->pinWS == I2SCC32XX_PIN_45_WS ||
1140 hwAttrs->pinWS == I2SCC32XX_PIN_53_WS ||
1141 hwAttrs->pinWS == I2SCC32XX_PIN_63_WS);
1142
1143 DebugP_assert(hwAttrs->pinSD1 == I2SCC32XX_PIN_62_SCKX ||
1144 hwAttrs->pinSD1 == I2SCC32XX_PIN_UNUSED);
1145
1146 openPin(hwAttrs->pinSD1);
1147 openPin(hwAttrs->pinSD0);
1148 openPin(hwAttrs->pinSCK);
1149 openPin(hwAttrs->pinSCKX);
1150 openPin(hwAttrs->pinWS);
1151 }
1152
1153 /*
1154 * ======== openPin ========
1155 */
openPin(unsigned long pinI2S)1156 static void openPin(unsigned long pinI2S) {
1157
1158 if(pinI2S != I2SCC32XX_PIN_UNUSED) {
1159 MAP_PinTypeI2S((unsigned long)PinConfigPin(pinI2S),
1160 (unsigned long)PinConfigPinMode(pinI2S));
1161 }
1162 }
1163
1164 /*
1165 * ======== resetPin ========
1166 */
resetPin(unsigned long pinI2S)1167 static void resetPin(unsigned long pinI2S) {
1168
1169 if(pinI2S != I2SCC32XX_PIN_UNUSED) {
1170 uint32_t padRegister = (PinToPadGet((pinI2S) & 0x3f)<<2) + PAD_CONFIG_BASE;
1171 HWREG(padRegister) = PAD_RESET_STATE;
1172 }
1173 }
1174
1175 /*
1176 * ======== restorePinpads ========
1177 */
restorePinpads(I2SCC32XX_HWAttrs const * hwAttrs)1178 static void restorePinpads(I2SCC32XX_HWAttrs const *hwAttrs){
1179 resetPin(hwAttrs->pinSD1);
1180 resetPin(hwAttrs->pinSD0);
1181 resetPin(hwAttrs->pinSCK);
1182 resetPin(hwAttrs->pinSCKX);
1183 resetPin(hwAttrs->pinWS);
1184 }
1185
1186 /*
1187 * ======== initDMA ========
1188 */
initDMA(I2S_Handle handle)1189 static void initDMA(I2S_Handle handle) {
1190
1191 I2SCC32XX_Object *object;
1192 object = handle->object;
1193
1194 if(!object->isDMAUnused) {
1195
1196 object->dmaHandle = UDMACC32XX_open();
1197 }
1198 }
1199
1200 /*
1201 * ======== getNumberOfChannels ========
1202 */
getNumberOfChannels(const uint8_t channelsList)1203 static uint8_t getNumberOfChannels(const uint8_t channelsList) {
1204
1205 uint8_t i = 0;
1206 uint8_t nbChannelsUsed = 0;
1207 for(i=0; i<(I2S_NB_CHANNELS_MAX); i++) {
1208 if(((channelsList >> i) & 1U) == 1U) {
1209 nbChannelsUsed ++;
1210 }
1211 }
1212 return nbChannelsUsed;
1213 }
1214
1215 /*
1216 * ======== configSCK ========
1217 */
configSCK(I2S_Handle handle)1218 static void configSCK(I2S_Handle handle) {
1219
1220 I2SCC32XX_Object const *object;
1221
1222 /* Get the pointer to the object*/
1223 object = handle->object;
1224
1225 /* There are three freq dividers (one in the PRCM module, two in the I2S module).
1226 * Two of the three freq dividers are used to keep the possibility to activate
1227 * only the input (or only the output).
1228 * Smallest SCK frequency possible is 57 Hz. */
1229 unsigned long ulI2SClk = object->samplingFrequency * object->dataLength * 2;
1230 unsigned long ulBitClk = (ulI2SClk < PRCMI2SCLOCKFREQMIN)? PRCMI2SCLOCKFREQMIN : ulI2SClk;
1231 MAP_PRCMI2SClockFreqSet(ulBitClk);
1232
1233 /* Calculate remaining divider */
1234 unsigned long remainingDivider = ((ulBitClk + ulI2SClk/2) / ulI2SClk); /* We want to round the integer division: ROUND(a/b)=(a+b/2)/b */;
1235 unsigned long ulHClkDiv = (remainingDivider == 0)? 0 :(remainingDivider-1);
1236 ulHClkDiv = (ulHClkDiv > HCLKDIVMAX)? HCLKDIVMAX : ulHClkDiv;
1237 unsigned long ulClkDiv = 0; /* ulClkDiv is not activated */
1238
1239 HWREG(I2S_BASE + MCASP_O_AHCLKXCTL) = (MCASP_AHCLKXCTL_HCLKXM_DEFAULT|ulHClkDiv);
1240 if(object->noOfOutputs != 0) {
1241
1242 HWREG(I2S_BASE + MCASP_O_ACLKXCTL) = (((object->samplingEdge << 7) & MCASP_ACLKXCTL_CLKXP) |
1243 ((object->moduleRole << 5) & MCASP_ACLKXCTL_CLKXM) |
1244 ((ulClkDiv << 0) & MCASP_ACLKXCTL_CLKXDIV_M));
1245 }
1246
1247 HWREG(I2S_BASE + MCASP_O_AHCLKRCTL) = (MCASP_AHCLKRCTL_HCLKRM_DEFAULT|ulHClkDiv);
1248 if(object->noOfInputs != 0) {
1249
1250 HWREG(I2S_BASE + MCASP_O_ACLKRCTL) = (((object->samplingEdge << 7) & MCASP_ACLKRCTL_CLKRP) |
1251 ((object->moduleRole << 5) & MCASP_ACLKRCTL_CLKRM) |
1252 ((ulClkDiv << 0) & MCASP_ACLKRCTL_CLKRDIV_M));
1253 }
1254
1255 }
1256
1257 /*
1258 * ======== configWS ========
1259 */
configWS(I2S_Handle handle)1260 static void configWS(I2S_Handle handle) {
1261
1262 I2SCC32XX_Object const *object;
1263
1264 /* Get the pointer to the object*/
1265 object = handle->object;
1266
1267 if(object->noOfInputs != 0) {
1268 HWREG(I2S_BASE + MCASP_O_RXFMCTL) = ( MCASP_RXFMCTL_RMOD_DEFAULT |
1269 MCASP_RXFMCTL_FRWID_DEFAULT |
1270 ((object->moduleRole << 1) & MCASP_RXFMCTL_FSRM) |
1271 ((object->invertWS << 0) & MCASP_RXFMCTL_FSRP));
1272 }
1273
1274 /* Must be executed including in read-only mode */
1275 HWREG(I2S_BASE + MCASP_O_TXFMCTL) = ( MCASP_TXFMCTL_XMOD_DEFAULT |
1276 MCASP_TXFMCTL_FXWID_DEFAULT |
1277 ((object->moduleRole << 1) & MCASP_TXFMCTL_FSXM) |
1278 ((object->invertWS << 0) & MCASP_TXFMCTL_FSXP));
1279 }
1280
1281 /*
1282 * ======== configSerialFormat ========
1283 */
configSerialFormat(I2S_Handle handle)1284 static void configSerialFormat(I2S_Handle handle) {
1285
1286 I2SCC32XX_Object const *object;
1287 I2SCC32XX_DataInterface const *SD0;
1288 I2SCC32XX_DataInterface const *SD1;
1289
1290 uint8_t channelsToActivate;
1291
1292 /* Get the pointer to the SD0 and SD1 interfaces*/
1293 object = handle->object;
1294 SD0 = &object->dataInterfaceSD0;
1295 SD1 = &object->dataInterfaceSD1;
1296
1297 /* Expected values (intermediate values are also possible):
1298 * dataLength = 8 >> dataLengthCC32XX = 0x3
1299 * dataLength = 16 >> dataLengthCC32XX = 0x7
1300 * dataLength = 24 >> dataLengthCC32XX = 0xB
1301 * dataLength = 32 >> dataLengthCC32XX = 0xF
1302 * */
1303 uint8_t dataLengthCC32XX = 1;
1304 int i;
1305 for(i=HWRESOLUTION;i<=32;i+=HWRESOLUTION){
1306 if(object->dataLength > i) {
1307 dataLengthCC32XX += HWRESOLUTION/2;
1308 }
1309 }
1310
1311 if(object->noOfInputs != 0) {
1312
1313 channelsToActivate = ((SD0->interfaceConfig == I2S_SD0_INPUT)? SD0->channelsUsed: 0x00) |
1314 ((SD1->interfaceConfig == I2S_SD1_INPUT)? SD1->channelsUsed: 0x00);
1315 HWREG(I2S_BASE + MCASP_O_RXFMT) = (((object->dataShift << MCASP_RXFMT_RDATDLY_S) & MCASP_RXFMT_RDATDLY_M)|
1316 ((object->isMSBFirst << 15 ) & MCASP_RXFMT_RRVRS ) |
1317 ((dataLengthCC32XX << MCASP_RXFMT_RSSZ_S ) & MCASP_RXFMT_RSSZ_M) |
1318 ((object->isDMAUnused << 3 ) & MCASP_RXFMT_RBUSEL) |
1319 ((object->sampleRotation << MCASP_RXFMT_RROT_S ) & MCASP_RXFMT_RROT_M));
1320 HWREG(I2S_BASE + MCASP_O_RXMASK) = object->sampleMask;
1321 HWREG(I2S_BASE + MCASP_O_RXTDM) = channelsToActivate;
1322 }
1323
1324 /* Must be executed including in read-only mode */
1325 channelsToActivate = ((SD0->interfaceConfig == I2S_SD0_OUTPUT)? SD0->channelsUsed: 0x00) |
1326 ((SD1->interfaceConfig == I2S_SD1_OUTPUT)? SD1->channelsUsed: 0x00);
1327 HWREG(I2S_BASE + MCASP_O_TXFMT) = (((object->dataShift << MCASP_TXFMT_XDATDLY_S) & MCASP_TXFMT_XDATDLY_M)|
1328 ((object->isMSBFirst << 15 ) & MCASP_TXFMT_XRVRS ) |
1329 ((dataLengthCC32XX << MCASP_TXFMT_XSSZ_S ) & MCASP_TXFMT_XSSZ_M) |
1330 ((object->isDMAUnused << 3 ) & MCASP_TXFMT_XBUSEL) |
1331 ((object->sampleRotation << MCASP_TXFMT_XROT_S ) & MCASP_TXFMT_XROT_M));
1332 HWREG(I2S_BASE + MCASP_O_TXMASK) = object->sampleMask;
1333 HWREG(I2S_BASE + MCASP_O_TXTDM) = channelsToActivate;
1334 }
1335
1336 /*
1337 * ======== postNotify ========
1338 * This functions is called to notify the I2S driver of an ongoing transition
1339 * out of LPDS mode.
1340 * clientArg should be pointing to a hardware module which has already
1341 * been opened.
1342 */
postNotify(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)1343 static int postNotify(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg) {
1344
1345 /* Reconfigure the hardware when returning from LPDS */
1346 initHw((I2S_Handle)clientArg);
1347
1348 return (Power_NOTIFYDONE);
1349 }
1350