1+ /*
2+ * Copyright (c) 2006-2018, RT-Thread Development Team
3+ *
4+ * SPDX-License-Identifier: Apache-2.0
5+ *
6+ * Change Logs:
7+ * Date Author Notes
8+ * 2019-11-17 LiWeiHao First implementation
9+ */
10+
11+ #include "drv_mic.h"
12+ #include "fsl_common.h"
13+ #include "fsl_iocon.h"
14+ #include "fsl_dmic.h"
15+ #include "fsl_dma.h"
16+ #include "fsl_dmic_dma.h"
17+
18+ struct mic_device
19+ {
20+ dma_handle_t dma_handle ;
21+ dmic_dma_handle_t dmic_dma_handle ;
22+ struct rt_audio_device audio ;
23+ struct rt_audio_configure config ;
24+ rt_uint8_t * rx_fifo ;
25+ };
26+
27+ #define DMAREQ_DMIC0 16U
28+ #define DMAREQ_DMIC1 17U
29+ #define DMAREQ_CHANNEL DMAREQ_DMIC0
30+ #define DMIC_CHANNEL kDMIC_Channel0
31+ #define DMIC_CHANNEL_ENABLE DMIC_CHANEN_EN_CH0(1)
32+ #define FIFO_DEPTH 15U
33+
34+ #define RX_DMA_FIFO_SIZE (2048)
35+
36+ struct mic_device mic_dev ;
37+
38+ void dmic_dma_transfer_callback (DMIC_Type * base ,
39+ dmic_dma_handle_t * handle ,
40+ status_t status ,
41+ void * userData )
42+ {
43+ struct mic_device * mic_dev = (struct mic_device * )userData ;
44+ rt_audio_rx_done (& mic_dev -> audio , & mic_dev -> rx_fifo [0 ], RX_DMA_FIFO_SIZE );
45+ dmic_transfer_t dmic_transfer ;
46+ dmic_transfer .data = (uint16_t * )& mic_dev -> rx_fifo [0 ];
47+ dmic_transfer .dataSize = RX_DMA_FIFO_SIZE / 2 ;
48+ DMIC_TransferReceiveDMA (DMIC0 , & mic_dev -> dmic_dma_handle , & dmic_transfer , kDMIC_Channel0 );
49+ }
50+
51+ rt_err_t mic_device_init (struct rt_audio_device * audio )
52+ {
53+ dmic_channel_config_t dmic_channel_cfg ;
54+
55+ CLOCK_EnableClock (kCLOCK_Iocon );
56+ CLOCK_EnableClock (kCLOCK_InputMux );
57+ CLOCK_EnableClock (kCLOCK_Gpio0 );
58+
59+ IOCON_PinMuxSet (IOCON , 1 , 16 , IOCON_FUNC1 | IOCON_DIGITAL_EN );
60+ IOCON_PinMuxSet (IOCON , 1 , 15 , IOCON_FUNC1 | IOCON_DIGITAL_EN );
61+
62+ CLOCK_AttachClk (kFRO12M_to_DMIC );
63+ CLOCK_SetClkDiv (kCLOCK_DivDmicClk , 14 , false);
64+
65+ dmic_channel_cfg .divhfclk = kDMIC_PdmDiv1 ;
66+ dmic_channel_cfg .osr = 25U ;
67+ dmic_channel_cfg .gainshft = 2U ;
68+ dmic_channel_cfg .preac2coef = kDMIC_CompValueZero ;
69+ dmic_channel_cfg .preac4coef = kDMIC_CompValueZero ;
70+ dmic_channel_cfg .dc_cut_level = kDMIC_DcCut155 ;
71+ dmic_channel_cfg .post_dc_gain_reduce = 1 ;
72+ dmic_channel_cfg .saturate16bit = 1U ;
73+ dmic_channel_cfg .sample_rate = kDMIC_PhyFullSpeed ;
74+ DMIC_Init (DMIC0 );
75+
76+ DMIC_ConfigIO (DMIC0 , kDMIC_PdmDual );
77+ DMIC_Use2fs (DMIC0 , true);
78+ DMIC_SetOperationMode (DMIC0 , kDMIC_OperationModeDma );
79+ DMIC_ConfigChannel (DMIC0 , DMIC_CHANNEL , kDMIC_Left , & dmic_channel_cfg );
80+
81+ DMIC_FifoChannel (DMIC0 , DMIC_CHANNEL , FIFO_DEPTH , true, true);
82+
83+ DMIC_EnableChannnel (DMIC0 , DMIC_CHANNEL_ENABLE );
84+
85+ DMA_EnableChannel (DMA0 , DMAREQ_CHANNEL );
86+
87+ /* Request dma channels from DMA manager. */
88+ DMA_CreateHandle (& mic_dev .dma_handle , DMA0 , DMAREQ_CHANNEL );
89+
90+ /* Create DMIC DMA handle. */
91+ DMIC_TransferCreateHandleDMA (DMIC0 ,
92+ & mic_dev .dmic_dma_handle ,
93+ dmic_dma_transfer_callback ,
94+ (void * )& mic_dev ,
95+ & mic_dev .dma_handle );
96+ return RT_EOK ;
97+ }
98+
99+ rt_err_t mic_device_start (struct rt_audio_device * audio , int stream )
100+ {
101+ struct mic_device * mic_dev = (struct mic_device * )audio -> parent .user_data ;
102+ if (stream == AUDIO_STREAM_RECORD )
103+ {
104+ dmic_transfer_t dmic_transfer ;
105+ dmic_transfer .data = (uint16_t * )& mic_dev -> rx_fifo [0 ];
106+ dmic_transfer .dataSize = RX_DMA_FIFO_SIZE / 2 ;
107+ DMIC_TransferReceiveDMA (DMIC0 , & mic_dev -> dmic_dma_handle , & dmic_transfer , kDMIC_Channel0 );
108+ }
109+ return RT_EOK ;
110+ }
111+
112+ rt_err_t mic_device_stop (struct rt_audio_device * audio , int stream )
113+ {
114+ struct mic_device * mic_dev = (struct mic_device * )audio -> parent .user_data ;
115+ if (stream == AUDIO_STREAM_RECORD )
116+ {
117+ DMIC_TransferAbortReceiveDMA (DMIC0 , & mic_dev -> dmic_dma_handle );
118+ }
119+ return RT_EOK ;
120+ }
121+
122+ rt_err_t mic_device_getcaps (struct rt_audio_device * audio , struct rt_audio_caps * caps )
123+ {
124+ return RT_EOK ;
125+ }
126+
127+ rt_err_t mic_device_configure (struct rt_audio_device * audio , struct rt_audio_caps * caps )
128+ {
129+ return RT_EOK ;
130+ }
131+
132+ static struct rt_audio_ops _mic_audio_ops =
133+ {
134+ .getcaps = mic_device_getcaps ,
135+ .configure = mic_device_configure ,
136+ .init = mic_device_init ,
137+ .start = mic_device_start ,
138+ .stop = mic_device_stop ,
139+ .transmit = RT_NULL ,
140+ .buffer_info = RT_NULL ,
141+ };
142+
143+ int rt_hw_mic_init (void )
144+ {
145+ struct rt_audio_device * audio = & mic_dev .audio ;
146+ /* mic default */
147+ mic_dev .rx_fifo = rt_calloc (1 , RX_DMA_FIFO_SIZE );
148+ if (mic_dev .rx_fifo == RT_NULL )
149+ {
150+ return - RT_ENOMEM ;
151+ }
152+
153+ mic_dev .config .channels = 1 ;
154+ mic_dev .config .samplerate = 16000 ;
155+ mic_dev .config .samplebits = 16 ;
156+
157+ /* register mic device */
158+ audio -> ops = & _mic_audio_ops ;
159+ rt_audio_register (audio , "mic0" , RT_DEVICE_FLAG_RDONLY , (void * )& mic_dev );
160+
161+ return RT_EOK ;
162+ }
163+ INIT_DEVICE_EXPORT (rt_hw_mic_init );
0 commit comments