1 /*
2  * Copyright (c) 2019, 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  *  @file       I2SCC32XX.h
34  *
35  *  @brief      I2S driver implementation for a CC32XX I2S controller
36  *
37  *  ============================================================================
38  */
39 #ifndef ti_drivers_i2s_I2SCC32XX__include
40 #define ti_drivers_i2s_I2SCC32XX__include
41 
42 #include <ti/drivers/I2S.h>
43 #include <ti/drivers/dma/UDMACC32XX.h>
44 #include <ti/drivers/dpl/SemaphoreP.h>
45 #include <ti/drivers/dpl/HwiP.h>
46 #include <ti/drivers/utils/List.h>
47 #include <ti/drivers/Power.h>
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 
54 /*
55  *  Macros defining possible I2S signal pin mux options
56  *
57  *  The bits in the pin mode macros are as follows:
58  *  The lower 8 bits of the macro refer to the pin, offset by 1, to match
59  *  driverlib pin defines.  For example, I2SCC32XX_PIN_02_WS & 0xff = 1,
60  *  which equals PIN_02 in driverlib pin.h.  By matching the PIN_xx defines in
61  *  driverlib pin.h, we can pass the pin directly to the driverlib functions.
62  *  The upper 8 bits of the macro correspond to the pin mux confg mode
63  *  value for the pin to operate in the I2S mode.  For example, pin 2 is
64  *  configured with mode 13 to operate as WS.
65  *
66  *  The macro I2SCC32XX_PIN_UNUSED allows the user to not activate one
67  *  of the signal.
68  */
69 /*! @cond HIDDEN_DEFINES */
70 #define I2SCC32XX_PIN_02_McAFSX  0x0d01 /*!< PIN 2 is used for McAFSX  */
71 #define I2SCC32XX_PIN_03_McACLK  0x0302 /*!< PIN 3 is used for McCLK   */
72 #define I2SCC32XX_PIN_15_McAFSX  0x070e /*!< PIN 15 is used for McAFSX */
73 #define I2SCC32XX_PIN_17_McAFSX  0x0610 /*!< PIN 17 is used for McAFSX */
74 #define I2SCC32XX_PIN_21_McAFSX  0x0214 /*!< PIN 21 is used for McAFSX */
75 #define I2SCC32XX_PIN_45_McAXR0  0x062c /*!< PIN 45 is used for McXR0  */
76 #define I2SCC32XX_PIN_45_McAFSX  0x0c2c /*!< PIN 45 is used for McAFSX */
77 #define I2SCC32XX_PIN_50_McAXR0  0x0431 /*!< PIN 50 is used for McXR0  */
78 #define I2SCC32XX_PIN_50_McAXR1  0x0631 /*!< PIN 50 is used for McXR1  */
79 #define I2SCC32XX_PIN_52_McACLK  0x0233 /*!< PIN 52 is used for McCLK  */
80 #define I2SCC32XX_PIN_52_McAXR0  0x0433 /*!< PIN 52 is used for McXR0  */
81 #define I2SCC32XX_PIN_53_McACLK  0x0234 /*!< PIN 53 is used for McCLK  */
82 #define I2SCC32XX_PIN_53_McAFSX  0x0334 /*!< PIN 53 is used for McAFSX */
83 #define I2SCC32XX_PIN_60_McAXR1  0x063b /*!< PIN 60 is used for McXR1  */
84 #define I2SCC32XX_PIN_62_McACLKX 0x0d3d /*!< PIN 62 is used for McCLKX */
85 #define I2SCC32XX_PIN_63_McAFSX  0x073e /*!< PIN 53 is used for McAFSX */
86 #define I2SCC32XX_PIN_64_McAXR0  0x073f /*!< PIN 64 is used for McXR0  */
87 #define I2SCC32XX_PIN_UNUSED     0xffff /*!< PIN non activated  */
88 
89 #define I2SCC32XX_PIN_50_SD1     I2SCC32XX_PIN_50_McAXR1   /*!< PIN 50 is used for SD1  */
90 #define I2SCC32XX_PIN_60_SD1     I2SCC32XX_PIN_60_McAXR1   /*!< PIN 60 is used for SD1  */
91 #define I2SCC32XX_PIN_52_SD0     I2SCC32XX_PIN_52_McAXR0   /*!< PIN 52 is used for SD0  */
92 #define I2SCC32XX_PIN_64_SD0     I2SCC32XX_PIN_64_McAXR0   /*!< PIN 64 is used for SD0  */
93 #define I2SCC32XX_PIN_45_SD0     I2SCC32XX_PIN_45_McAXR0   /*!< PIN 45 is used for SD0  */
94 #define I2SCC32XX_PIN_50_SD0     I2SCC32XX_PIN_50_McAXR0   /*!< PIN 50 is used for SD0  */
95 #define I2SCC32XX_PIN_03_SCK     I2SCC32XX_PIN_03_McACLK   /*!< PIN 03 is used for SCK  */
96 #define I2SCC32XX_PIN_52_SCK     I2SCC32XX_PIN_52_McACLK   /*!< PIN 52 is used for SCK  */
97 #define I2SCC32XX_PIN_53_SCK     I2SCC32XX_PIN_53_McACLK   /*!< PIN 53 is used for SCK  */
98 #define I2SCC32XX_PIN_62_SCKX    I2SCC32XX_PIN_62_McACLKX  /*!< PIN 62 is used for SCKX */
99 #define I2SCC32XX_PIN_02_WS      I2SCC32XX_PIN_02_McAFSX   /*!< PIN 02 is used for WS   */
100 #define I2SCC32XX_PIN_15_WS      I2SCC32XX_PIN_15_McAFSX   /*!< PIN 15 is used for WS   */
101 #define I2SCC32XX_PIN_17_WS      I2SCC32XX_PIN_17_McAFSX   /*!< PIN 17 is used for WS   */
102 #define I2SCC32XX_PIN_21_WS      I2SCC32XX_PIN_21_McAFSX   /*!< PIN 21 is used for WS   */
103 #define I2SCC32XX_PIN_45_WS      I2SCC32XX_PIN_45_McAFSX   /*!< PIN 45 is used for WS   */
104 #define I2SCC32XX_PIN_63_WS      I2SCC32XX_PIN_63_McAFSX   /*!< PIN 63 is used for WS   */
105 #define I2SCC32XX_PIN_53_WS      I2SCC32XX_PIN_53_McAFSX   /*!< PIN 53 is used for WS   */
106 
107 /*! @endcond*/
108 
109 /*!
110  *  @brief  I2S Hardware attributes
111  *
112  *  intPriority is the I2S peripheral's interrupt priority, as defined by the
113  *  TI-RTOS kernel. This value is passed unmodified to Hwi_create().
114  *
115  *  pinSD1 and pinSD0 define the SD0 and SD1 data pin mapping, respectively.
116  *  pinSCK, pinMCLK and pinWS define the SCK, MCLK and WS clock pin mapping, respectively.
117  *  All these pins are typically defined with a macro in a header file, which maps to an IOID.
118  *
119  *  rxChannelIndex and txChannelIndex are uDMA channels respectively used for the read and
120  *  the write interface.
121  *
122  *  A sample structure is shown below:
123  *  @code
124  *  const I2SCC32XX_HWAttrs i2sCC3220SHWAttrs[CC3220S_LAUNCHXL_I2SCOUNT] = {
125  *      {
126  *        .pinSD1           =  I2SCC32XX_PIN_50_SD1,
127  *        .pinSD0           =  I2SCC32XX_PIN_64_SD0,
128  *        .pinSCK           =  I2SCC32XX_PIN_53_SCK,
129  *        .pinSCKX          =  I2SCC32XX_PIN_UNUSED,
130  *        .pinWS            =  I2SCC32XX_PIN_63_WS,
131  *        .rxChannelIndex   =  UDMA_CH4_I2S_RX,
132  *        .txChannelIndex   =  UDMA_CH5_I2S_TX,
133  *        .intPriority      =  0x40,
134  *      }
135  *  };
136  *  @endcode
137  */
138 typedef struct {
139     uint32_t                        pinSD1;                  /*!< Pin used for SD1 signal.
140                                                                   Must be chosen between I2SCC32XX_PIN_50_SD1 and I2SCC32XX_PIN_60_SD1.
141                                                                   Signal can be deactivated using I2SCC32XX_PIN_UNUSED. */
142     uint32_t                        pinSD0;                  /*!< Pin used for SD0 signal.
143                                                                   Must be chosen between I2SCC32XX_PIN_45_SD0, I2SCC32XX_PIN_50_SD0, I2SCC32XX_PIN_52_SD0, and I2SCC32XX_PIN_64_SD0.
144                                                                   Signal can be deactivated using I2SCC32XX_PIN_UNUSED.*/
145     uint32_t                        pinSCK;                  /*!< Pin used for SCK signal.
146                                                                   Must be chosen between I2SCC32XX_PIN_03_SCK, I2SCC32XX_PIN_52_SCK, and I2SCC32XX_PIN_53_SCK.
147                                                                   Signal can be deactivated using I2SCC32XX_PIN_UNUSED.*/
148     uint32_t                        pinSCKX;                 /*!< Pin used for SCKX signal.
149                                                                   Must be I2SCC32XX_PIN_62_SCKX. */
150     uint32_t                        pinWS;                   /*!< Pin used for WS signal.
151                                                                   Must be chosen between I2SCC32XX_PIN_02_WS, I2SCC32XX_PIN_15_WS, I2SCC32XX_PIN_17_WS, I2SCC32XX_PIN_21_WS, I2SCC32XX_PIN_45_WS, I2SCC32XX_PIN_53_WS, and I2SCC32XX_PIN_63_WS.
152                                                                   This signal cannot be deactivated.*/
153     uint32_t                        rxChannelIndex;          /*!< uDMA channel index used for Rx.
154                                                                   Must be chosen between UDMA_CH4_I2S_RX and UDMA_CH18_I2S_RX. Does not need to be set if no using the DMA transfers. */
155     uint32_t                        txChannelIndex;          /*!< uDMA channel index used for Tx.
156                                                                   Must be chosen between UDMA_CH5_I2S_TX and UDMA_CH19_I2S_TX. Does not need to be set if no using the DMA transfers. */
157     uint32_t                        intPriority;             /*!< I2S Peripheral's interrupt priority */
158 }I2SCC32XX_HWAttrs;
159 
160 /*!
161  *  @cond NODOC
162  *  I2S data-interface
163  *
164  *  This struct defines how the physical I2S interface (SD0/SD1) behaves.
165  *  Do not modify.
166  */
167 typedef struct {
168     I2S_DataInterfaceUse            interfaceConfig;          /*!< IN / OUT / UNUSED */
169     I2S_ChannelConfig               channelsUsed;             /*!< List of the used channels. */
170     uint8_t                         numberOfChannelsUsed;     /*!< Number of channels used on SDx. */
171     uint8_t                         dataLine;                 /*!< DataLine used by SDx (I2S_DATA_LINE_0 or I2S_DATA_LINE_1) */
172 }I2SCC32XX_DataInterface;
173 /*! @endcond */
174 
175 /*!
176  *  @cond NODOC
177  *  I2S interface
178  *
179  *  This enum defines one of the interfaces (READ or WRITE) of the I2S module.
180  *  Do not modify.
181  */
182 typedef struct {
183     uint16_t                        delay;                    /*!< Number of WS cycles to wait before starting the first transfer. This value is mostly used when performing constant latency transfers. */
184     I2S_Transaction                *activeTransfer;           /*!< Pointer on the ongoing transfer */
185     I2S_Callback                    callback;                 /*!< Pointer to callback */
186     uint32_t                        udmaConfig;               /*!< Bit field. It's a OR of  UDMA_SIZE_xx, UDMA_CHCTL_SRCINC_xx, UDMA_DSTINC_xx, UDMA_ARB_xx. */
187     I2S_StopInterface               stopInterface;            /*!< Pointer on the function used to stop the interface */
188 }I2SCC32XX_Interface;
189 /*! @endcond */
190 
191 /*!
192  *  @brief      The definition of a function used by the I2S driver
193  *              to refresh the FIFO
194  *
195  *  @param      I2S_Handle  I2S_Handle
196  *
197  */
198 typedef void (*I2SCC32XX_FifoUpdate)(uintptr_t arg);
199 
200 /*!
201  *  @cond NODOC
202  *  I2S Object.  The application must not access any member variables
203  *  of this structure!
204  */
205 typedef struct {
206 
207     bool                            isOpen;                  /*!< To avoid multiple openings of the I2S. */
208     bool                            invertWS;                /*!< WS inversion.
209                                                                           false: The WS signal is not internally inverted.
210                                                                           true:  The WS signal is internally inverted. */
211     bool                            isMSBFirst;              /*!< Endianness of the samples transmitted.
212                                                                           false: Transmission are performed LSB first.
213                                                                           true:  Transmission are performed MSB first. */
214     bool                            isDMAUnused;             /*!< Selection between DMA transmissions and CPU transmissions.
215                                                                           false: Transmission are performed by DMA.
216                                                                           true:  Transmission are performed by CPU. */
217     volatile bool                   isLastReadTransfer;      /*!< This boolean indicates that no new DMA transfer must be started for the read interface.
218                                                                       The read interface will be stopped as soon as the current DMA transfer is finished.
219                                                                       This parameter is valid only in DMA mode. */
220     volatile bool                   isLastWriteTransfer;     /*!< This boolean indicates that no new DMA transfer must be started for the write interface.
221                                                                       The write interface will be stopped as soon as the current DMA transfer is finished.
222                                                                       This parameter is valid only in DMA mode. */
223     uint8_t                         dataShift;               /*!< When dataShift is set to 0, data are read/write on the data lines from the first SCK edge of the WS half-period.
224                                                                   By setting dataShift to a value different from zero, you can postpone the moment when data are read/write during the WS half-period.
225                                                                   For example, by setting dataShift to 1, data are read/write on the data lines from the second SCK period of the WS half-period. If no padding is activated, this corresponds to the I2S standard.
226                                                                   The only values possible for dataShift are DATA_SHIFT_NONE, DATA_SHIFT_1 and DATA_SHIFT_2 */
227     uint8_t                         memorySlotLength;        /*!< Select the size of the memory used.
228                                                                           I2S_MEMORY_LENGTH_8BITS  : Memory length is 8  bits.
229                                                                           I2S_MEMORY_LENGTH_16BITS : Memory length is 16 bits.
230                                                                           I2S_MEMORY_LENGTH_24BITS : Memory length is 24 bits.
231                                                                           I2S_MEMORY_LENGTH_32BITS : Memory length is 32 bits. */
232     uint8_t                         sampleRotation;          /*!< Right rotation of the samples: used to configure the padding before and after the word. */
233     uint8_t                         noOfInputs;              /*!< Number of I2S inputs (possible values are 0, 1 and 2) */
234     uint8_t                         noOfOutputs;             /*!< Number of I2S outputs (possible values are 0, 1 and 2) */
235     uint8_t                         udmaArbLength;           /*!< Number of uDMA transfers between two bus arbitration. By increasing this value, you increase the risk of incomplete I2S transfers. Possible values are 1, 2, 4(default), 8, 16, 32, 64 and 128. */
236     uint8_t                         dataLength;              /*!< Length (in bits) of the data transmitted. Must be between 8 and 32. */
237     I2S_Role                        moduleRole;              /*!< Select if the current device is a Slave or a Master.
238                                                                     I2S_SLAVE:  The device is a slave (clocks are generated externally).
239                                                                     I2S_MASTER: The device is a master (clocks are generated internally). */
240     I2S_SamplingEdge                samplingEdge;            /*!< Select edge sampling type.
241                                                                      I2S_SAMPLING_EDGE_FALLING: Sampling on falling edges.
242                                                                      I2S_SAMPLING_EDGE_RISING:  Sampling on raising edges. */
243     uint32_t                        samplingFrequency;       /*!< I2S sampling frequency configuration in samples/second. */
244     uint32_t                        sampleMask;              /*!< Mask applied to the samples: used to perform sample truncation and avoid transmission of unexpected data. */
245     uint32_t                        activatedFlag;           /*!< List of the activated flags. This field is required for CC32XX as we do not have a mechanism to only read the activated flags.  */
246     I2SCC32XX_DataInterface         dataInterfaceSD0;        /*!< Structure to describe the SD0 interface */
247     I2SCC32XX_DataInterface         dataInterfaceSD1;        /*!< Structure to describe the SD1 interface */
248     I2SCC32XX_Interface             read;                    /*!< Structure to describe the read (in) interface */
249     I2SCC32XX_Interface             write;                   /*!< Structure to describe the write (out) interface */
250     I2S_Callback                    errorCallback;           /*!< Pointer to error callback */
251     I2SCC32XX_FifoUpdate            updateDataReadFxn;       /*!< Pointer on the function used to update the FIFO */
252     I2SCC32XX_FifoUpdate            updateDataWriteFxn;      /*!< Pointer on the function used to update the FIFO */
253     HwiP_Handle                     hwi;                     /*!< Hwi object for interrupts */
254     UDMACC32XX_Handle               dmaHandle;               /*!< DMA object */
255     Power_NotifyObj                 notifyObj;               /*!< For notification of wake from LPDS */
256 } I2SCC32XX_Object;
257 /*! @endcond */
258 
259 #ifdef __cplusplus
260 }
261 #endif
262 
263 #endif /* ti_drivers_i2s_I2SCC32XX__include */
264