• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 HiHope Open Source Organization .
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 #include <sound/pcm_params.h>
9 #include <sound/dmaengine_pcm.h>
10 #include <linux/module.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/delay.h>
13 #include <linux/of_gpio.h>
14 #include <linux/of_device.h>
15 #include <linux/of_address.h>
16 #include <linux/clk.h>
17 #include <linux/clk/rockchip.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
20 #include <linux/reset.h>
21 #include <linux/spinlock.h>
22 
23 #include "audio_host.h"
24 #include "audio_control.h"
25 #include "audio_dai_if.h"
26 #include "audio_dai_base.h"
27 #include "audio_driver_log.h"
28 #include "audio_stream_dispatch.h"
29 #include "osal_io.h"
30 #include "rk3568_dai_linux.h"
31 #include "rk3568_audio_common.h"
32 #include "audio_platform_base.h"
33 #include "rk3568_dai_ops.h"
34 
35 #define HDF_LOG_TAG rk3568_dai_ops
36 
37 void *g_regDaiBase = NULL;
38 static const char *g_i2s1DtsTreePath = "/i2s@fe410000";
39 static struct platform_device *g_platformDev;
getPlatformDev(void)40 struct platform_device *getPlatformDev(void)
41 {
42     struct device_node *dmaOfNode;
43     dmaOfNode = of_find_node_by_path(g_i2s1DtsTreePath);
44     if (dmaOfNode == NULL) {
45         AUDIO_DEVICE_LOG_ERR("get device node failed.");
46     }
47     g_platformDev = of_find_device_by_node(dmaOfNode);
48     return g_platformDev;
49 }
Rk3568DeviceReadReg(unsigned long regBase,uint32_t reg,uint32_t * val)50 int32_t Rk3568DeviceReadReg(unsigned long regBase, uint32_t reg, uint32_t *val)
51 {
52     struct platform_device *platformdev = getPlatformDev();
53     struct rk3568_i2s_tdm_dev *i2sTdm;
54 
55     (void)regBase;
56     i2sTdm = dev_get_drvdata(&platformdev->dev);
57     if (regmap_read(i2sTdm->regmap, reg, val)) {
58         AUDIO_DEVICE_LOG_ERR("read register fail: [%04x]", reg);
59         return HDF_FAILURE;
60     }
61     AUDIO_DEVICE_LOG_DEBUG("success");
62     return HDF_SUCCESS;
63 }
64 
Rk3568DeviceWriteReg(unsigned long regBase,uint32_t reg,uint32_t value)65 int32_t Rk3568DeviceWriteReg(unsigned long regBase, uint32_t reg, uint32_t value)
66 {
67     struct platform_device *platformdev = getPlatformDev();
68     struct rk3568_i2s_tdm_dev *i2sTdm;
69     (void)regBase;
70     i2sTdm = dev_get_drvdata(&platformdev->dev);
71     if (regmap_write(i2sTdm->regmap, reg, value)) {
72         AUDIO_DEVICE_LOG_ERR("write register fail: [%04x] = %04x", reg, value);
73         return HDF_FAILURE;
74     }
75     AUDIO_DEVICE_LOG_DEBUG("success");
76     return HDF_SUCCESS;
77 }
78 
79 
Rk3568DaiDeviceInit(struct AudioCard * card,const struct DaiDevice * dai)80 int32_t Rk3568DaiDeviceInit(struct AudioCard *card, const struct DaiDevice *dai)
81 {
82     int32_t ret;
83     struct DaiData *data;
84 
85     if (dai == NULL || dai->device == NULL || dai->devDaiName == NULL) {
86         AUDIO_DEVICE_LOG_ERR("input para is NULL.");
87         return HDF_ERR_INVALID_PARAM;
88     }
89     if (dai == NULL || dai->devData == NULL) {
90         AUDIO_DEVICE_LOG_ERR("dai host is NULL.");
91         return HDF_FAILURE;
92     }
93     data = dai->devData;
94     if (DaiSetConfigInfo(data) != HDF_SUCCESS) {
95         AUDIO_DEVICE_LOG_ERR("set config info fail.");
96         return HDF_FAILURE;
97     }
98 
99     ret = AudioAddControls(card, data->controls, data->numControls);
100     if (ret != HDF_SUCCESS) {
101         AUDIO_DEVICE_LOG_ERR("add controls failed.");
102         return HDF_FAILURE;
103     }
104 
105     if (g_regDaiBase == NULL) {
106         g_regDaiBase = OsalIoRemap(data->regConfig->audioIdInfo.chipIdRegister,
107             data->regConfig->audioIdInfo.chipIdSize);
108         if (g_regDaiBase == NULL) {
109             AUDIO_DEVICE_LOG_ERR("OsalIoRemap fail.");
110             return HDF_FAILURE;
111         }
112     }
113     data->regVirtualAddr = (uintptr_t)g_regDaiBase;
114 
115     if (dai->devData->daiInitFlag == true) {
116         AUDIO_DRIVER_LOG_DEBUG("dai init complete!");
117         return HDF_SUCCESS;
118     }
119 
120     dai->devData->daiInitFlag = true;
121     AUDIO_DEVICE_LOG_DEBUG("success");
122     return HDF_SUCCESS;
123 }
124 
Rk3568DaiStartup(const struct AudioCard * card,const struct DaiDevice * dai)125 int32_t Rk3568DaiStartup(const struct AudioCard *card, const struct DaiDevice *dai)
126 {
127     (void)card;
128     (void)dai;
129     return HDF_SUCCESS;
130 }
131 
RK3568SetI2sFomartVal(const struct AudioPcmHwParams * param)132 int RK3568SetI2sFomartVal(const struct AudioPcmHwParams *param)
133 {
134     int32_t val;
135     switch (param->format) {
136         case AUDIO_FORMAT_PCM_8_BIT:
137             val |= I2S_TXCR_VDW(8); // 8-bit
138             break;
139         case AUDIO_FORMAT_PCM_16_BIT:
140             val |= I2S_TXCR_VDW(16); // 16-bit
141             break;
142         case AUDIO_FORMAT_PCM_24_BIT:
143             val |= I2S_TXCR_VDW(24); // 24-bit
144             break;
145         case AUDIO_FORMAT_PCM_32_BIT:
146             val |= I2S_TXCR_VDW(32); // 32-bit
147             break;
148         default:
149             return -1;
150     }
151     AUDIO_DEVICE_LOG_DEBUG("sucess");
152     return val;
153 }
154 
RK3568SetI2sChannels(struct rk3568_i2s_tdm_dev * i2sTdm,const struct AudioPcmHwParams * param)155 int32_t RK3568SetI2sChannels(struct rk3568_i2s_tdm_dev *i2sTdm, const struct AudioPcmHwParams *param)
156 {
157     unsigned int regFmt, fmt;
158     int32_t ret = 0;
159     AUDIO_DEVICE_LOG_DEBUG("entry");
160 
161     if (param->streamType == AUDIO_RENDER_STREAM) {
162         regFmt = I2S_TXCR;
163     } else {
164         regFmt = I2S_RXCR;
165     }
166 
167     regmap_read(i2sTdm->regmap, regFmt, &fmt);
168     fmt &= I2S_TXCR_TFS_MASK;
169     if (fmt == 0) { // I2S mode
170         switch (param->channels) {
171             case 8:               // channels is 8
172                 ret = I2S_CHN_8;
173                 break;
174             case 6:               // channels is 6
175                 ret = I2S_CHN_6;
176                 break;
177             case 4:               // channels is 4
178                 ret = I2S_CHN_4;
179                 break;
180             case 2:               // channels is 2
181                 ret = I2S_CHN_2;
182                 break;
183             default:
184                 ret = -EINVAL;
185                 break;
186         }
187     }
188     AUDIO_DEVICE_LOG_DEBUG("success");
189     return ret;
190 }
191 
ConfigInfoSetToReg(struct rk3568_i2s_tdm_dev * i2sTdm,const struct AudioPcmHwParams * param,unsigned int div_bclk,unsigned int div_lrck,int32_t fmt)192 int32_t ConfigInfoSetToReg(struct rk3568_i2s_tdm_dev *i2sTdm, const struct AudioPcmHwParams *param,
193     unsigned int div_bclk, unsigned int div_lrck, int32_t fmt)
194 {
195     AUDIO_DEVICE_LOG_DEBUG("entry");
196     regmap_update_bits(i2sTdm->regmap, I2S_CLKDIV,
197         I2S_CLKDIV_TXM_MASK | I2S_CLKDIV_RXM_MASK,
198         I2S_CLKDIV_TXM(div_bclk) | I2S_CLKDIV_RXM(div_bclk));
199     regmap_update_bits(i2sTdm->regmap, I2S_CKR,
200         I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK,
201         I2S_CKR_TSD(div_lrck) | I2S_CKR_RSD(div_lrck));
202 
203     if (param->streamType == AUDIO_RENDER_STREAM) {
204         regmap_update_bits(i2sTdm->regmap, I2S_TXCR,
205             I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
206             fmt);
207     } else {
208         regmap_update_bits(i2sTdm->regmap, I2S_RXCR,
209             I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK,
210             fmt);
211     }
212     AUDIO_DEVICE_LOG_DEBUG("success");
213     return HDF_SUCCESS;
214 }
215 
216 // i2s_tdm->mclk_tx_freq ? i2s_tdm->mclk_rx_freq ?
RK3568I2sTdmSetMclk(struct rk3568_i2s_tdm_dev * i2sTdm,struct clk ** mclk,const struct AudioPcmHwParams * param)217 int32_t RK3568I2sTdmSetMclk(struct rk3568_i2s_tdm_dev *i2sTdm, struct clk **mclk, const struct AudioPcmHwParams *param)
218 {
219     int32_t ret = 0;
220     unsigned int mclkRate, bclkRate, bclkDiv, lrclkDiv;
221     int32_t fmt = 0;
222     int32_t channels = 0;
223     AUDIO_DEVICE_LOG_DEBUG("entry");
224 
225     ret = clk_set_rate(i2sTdm->mclk_tx, i2sTdm->mclk_tx_freq);
226     if (ret) {
227         AUDIO_DEVICE_LOG_ERR(" clk_set_rate ret = %d", ret);
228         return ret;
229     }
230 
231     ret = clk_set_rate(i2sTdm->mclk_rx, i2sTdm->mclk_rx_freq);
232     if (ret) {
233         AUDIO_DEVICE_LOG_ERR(" clk_set_rate ret = %d", ret);
234         return ret;
235     }
236 
237     /* mclk_rx is also ok. */
238     mclkRate = clk_get_rate(i2sTdm->mclk_tx);
239     bclkRate = i2sTdm->bclk_fs * param->rate;
240     bclkDiv = DIV_ROUND_CLOSEST(mclkRate, bclkRate);
241     lrclkDiv = bclkRate / param->rate;
242     fmt = RK3568SetI2sFomartVal(param);
243     if (fmt < 0) {
244         AUDIO_DEVICE_LOG_ERR(" RK3568SetI2sFomartVal fmt = %d", fmt);
245         return HDF_FAILURE;
246     }
247     channels = RK3568SetI2sChannels(i2sTdm, param);
248     if (channels < 0) {
249         AUDIO_DEVICE_LOG_ERR(" RK3568SetI2sFomartVal channels = %d", channels);
250         return HDF_FAILURE;
251     }
252     fmt |= channels;
253     ret = ConfigInfoSetToReg(i2sTdm, param, bclkDiv, lrclkDiv, fmt);
254     if (ret != HDF_SUCCESS) {
255         AUDIO_DEVICE_LOG_ERR(" ConfigInfoSetToReg ret= %d", ret);
256         return HDF_FAILURE;
257     }
258 
259     AUDIO_DEVICE_LOG_DEBUG("success");
260     return HDF_SUCCESS;
261 }
RK3568I2sTdmSetSysClk(struct rk3568_i2s_tdm_dev * i2sTdm,const struct AudioPcmHwParams * param)262 int32_t RK3568I2sTdmSetSysClk(struct rk3568_i2s_tdm_dev *i2sTdm, const struct AudioPcmHwParams *param)
263 {
264     /* Put set mclk rate into rockchip_i2s_tdm_set_mclk() */
265     uint32_t sampleRate = param->rate;
266     uint32_t mclk_parent_freq = 0;
267     switch (sampleRate) {
268         case AUDIO_DEVICE_SAMPLE_RATE_8000:
269         case AUDIO_DEVICE_SAMPLE_RATE_16000:
270         case AUDIO_DEVICE_SAMPLE_RATE_24000:
271         case AUDIO_DEVICE_SAMPLE_RATE_32000:
272         case AUDIO_DEVICE_SAMPLE_RATE_48000:
273         case AUDIO_DEVICE_SAMPLE_RATE_64000:
274         case AUDIO_DEVICE_SAMPLE_RATE_96000:
275             mclk_parent_freq = i2sTdm->bclk_fs * AUDIO_DEVICE_SAMPLE_RATE_192000;
276             break;
277         case AUDIO_DEVICE_SAMPLE_RATE_11025:
278         case AUDIO_DEVICE_SAMPLE_RATE_22050:
279         case AUDIO_DEVICE_SAMPLE_RATE_44100:
280             mclk_parent_freq = i2sTdm->bclk_fs * AUDIO_DEVICE_SAMPLE_RATE_176400;
281             break;
282         default:
283             AUDIO_DEVICE_LOG_ERR("Invalid LRCK freq: %u Hz\n", sampleRate);
284             return HDF_FAILURE;
285     }
286     i2sTdm->mclk_tx_freq = mclk_parent_freq;
287     i2sTdm->mclk_rx_freq = mclk_parent_freq;
288 
289     return HDF_SUCCESS;
290 }
291 
Rk3568DaiHwParams(const struct AudioCard * card,const struct AudioPcmHwParams * param)292 int32_t Rk3568DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param)
293 {
294     int ret;
295     uint32_t bitWidth;
296     struct clk *mclk;
297     struct DaiData *data = DaiDataFromCard(card);
298     struct platform_device *platformdev = getPlatformDev();
299     struct rk3568_i2s_tdm_dev *i2sTdm;
300 
301     if (data == NULL) {
302         AUDIO_DEVICE_LOG_ERR("platformHost is nullptr.");
303         return HDF_FAILURE;
304     }
305     if (param == NULL || param->cardServiceName == NULL) {
306         AUDIO_DEVICE_LOG_ERR("input para is NULL.");
307         return HDF_ERR_INVALID_PARAM;
308     }
309     data->pcmInfo.channels = param->channels;
310 
311     if (AudioFramatToBitWidth(param->format, &bitWidth) != HDF_SUCCESS) {
312         AUDIO_DEVICE_LOG_ERR("AudioFramatToBitWidth error");
313         return HDF_FAILURE;
314     }
315     data->pcmInfo.bitWidth = bitWidth;
316     data->pcmInfo.rate = param->rate;
317     data->pcmInfo.streamType = param->streamType;
318 
319     i2sTdm = dev_get_drvdata(&platformdev->dev);
320     ret = RK3568I2sTdmSetSysClk(i2sTdm, param);
321     if (ret != HDF_SUCCESS) {
322         AUDIO_DEVICE_LOG_ERR("RK3568I2sTdmSetSysClk error");
323         return HDF_FAILURE;
324     }
325     ret = RK3568I2sTdmSetMclk(i2sTdm, &mclk, param);
326     if (ret != HDF_SUCCESS) {
327         AUDIO_DEVICE_LOG_ERR("RK3568I2sTdmSetMclk error");
328         return HDF_FAILURE;
329     }
330     AUDIO_DEVICE_LOG_DEBUG("success");
331     return HDF_SUCCESS;
332 }
GetTriggeredFlag(int cmd)333 static int GetTriggeredFlag(int cmd)
334 {
335     int32_t triggerFlag = false;
336     switch (cmd) {
337         case AUDIO_DRV_PCM_IOCTL_RENDER_START:
338         case AUDIO_DRV_PCM_IOCTL_RENDER_RESUME:
339         case AUDIO_DRV_PCM_IOCTL_CAPTURE_START:
340         case AUDIO_DRV_PCM_IOCTL_CAPTURE_RESUME:
341             triggerFlag = true;
342             break;
343 
344         case AUDIO_DRV_PCM_IOCTL_RENDER_STOP:
345         case AUDIO_DRV_PCM_IOCTL_CAPTURE_STOP:
346         case AUDIO_DRV_PCM_IOCTL_RENDER_PAUSE:
347         case AUDIO_DRV_PCM_IOCTL_CAPTURE_PAUSE:
348             triggerFlag = false;
349             break;
350 
351         default:
352             triggerFlag = false;
353     }
354     AUDIO_DEVICE_LOG_DEBUG("success");
355     return triggerFlag;
356 }
357 
358 
GetStreamType(int cmd)359 static int GetStreamType(int cmd)
360 {
361     enum AudioStreamType streamType = AUDIO_CAPTURE_STREAM;
362     switch (cmd) {
363         case AUDIO_DRV_PCM_IOCTL_RENDER_START:
364         case AUDIO_DRV_PCM_IOCTL_RENDER_RESUME:
365         case AUDIO_DRV_PCM_IOCTL_RENDER_STOP:
366         case AUDIO_DRV_PCM_IOCTL_RENDER_PAUSE:
367             streamType = AUDIO_RENDER_STREAM;
368             break;
369         case AUDIO_DRV_PCM_IOCTL_CAPTURE_START:
370         case AUDIO_DRV_PCM_IOCTL_CAPTURE_RESUME:
371         case AUDIO_DRV_PCM_IOCTL_CAPTURE_STOP:
372         case AUDIO_DRV_PCM_IOCTL_CAPTURE_PAUSE:
373             streamType = AUDIO_CAPTURE_STREAM;
374             break;
375 
376         default:
377             break;
378     }
379     AUDIO_DEVICE_LOG_DEBUG("success");
380     return streamType;
381 }
382 
Rk3568TxAndRxSetReg(struct rk3568_i2s_tdm_dev * i2sTdm,enum AudioStreamType streamType,int on)383 static void Rk3568TxAndRxSetReg(struct rk3568_i2s_tdm_dev *i2sTdm,
384     enum AudioStreamType streamType, int on)
385 {
386     unsigned int val = 0;
387     int retry = 10; // retry 10 times
388     if (on) {       // when start/resume
389         if (streamType == AUDIO_RENDER_STREAM) {
390             clk_prepare_enable(i2sTdm->mclk_tx);
391             regmap_update_bits(i2sTdm->regmap, I2S_DMACR,
392                 I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
393         } else {
394             clk_prepare_enable(i2sTdm->mclk_rx);
395             regmap_update_bits(i2sTdm->regmap, I2S_DMACR,
396                 I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
397             if (regmap_read(i2sTdm->regmap, I2S_DMACR, &val)) {
398                 AUDIO_DEVICE_LOG_ERR("read register fail: [%04x]", I2S_DMACR);
399                 return ;
400             }
401         }
402 
403         if (atomic_inc_return(&i2sTdm->refcount) == 1) {
404             regmap_update_bits(i2sTdm->regmap, I2S_XFER,
405                 I2S_XFER_TXS_START | I2S_XFER_RXS_START, I2S_XFER_TXS_START | I2S_XFER_RXS_START);
406             if (regmap_read(i2sTdm->regmap, I2S_XFER, &val)) {
407                 AUDIO_DEVICE_LOG_ERR("read register fail: [%04x]", I2S_XFER);
408                 return ;
409             }
410         }
411     } else {     // when stop/pause
412         if (streamType == AUDIO_RENDER_STREAM) {
413             clk_disable_unprepare(i2sTdm->mclk_tx);
414             regmap_update_bits(i2sTdm->regmap, I2S_DMACR,
415                 I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
416         } else {
417             clk_disable_unprepare(i2sTdm->mclk_rx);
418             regmap_update_bits(i2sTdm->regmap, I2S_DMACR,
419                 I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
420         }
421 
422         if (atomic_dec_and_test(&i2sTdm->refcount)) {
423             regmap_update_bits(i2sTdm->regmap, I2S_XFER,
424                 I2S_XFER_TXS_START | I2S_XFER_RXS_START, I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
425             udelay(150);
426             regmap_update_bits(i2sTdm->regmap, I2S_CLR,
427                 I2S_CLR_TXC | I2S_CLR_RXC, I2S_CLR_TXC | I2S_CLR_RXC);
428             regmap_read(i2sTdm->regmap, I2S_CLR, &val);
429             /* Should wait for clear operation to finish */
430             while (val && retry > 0) {
431                 regmap_read(i2sTdm->regmap, I2S_CLR, &val);
432                 retry--;
433             }
434         }
435     }
436 
437     AUDIO_DEVICE_LOG_DEBUG("success");
438     return;
439 }
440 
441 /* normal scene */
Rk3568NormalTrigger(const struct AudioCard * card,int cmd,const struct DaiDevice * device)442 int32_t Rk3568NormalTrigger(const struct AudioCard *card, int cmd, const struct DaiDevice *device)
443 {
444     struct platform_device *platformdev = getPlatformDev();
445     struct rk3568_i2s_tdm_dev *i2sTdm;
446     int32_t triggerFlag = GetTriggeredFlag(cmd);
447     enum AudioStreamType streamType = GetStreamType(cmd);
448 
449     i2sTdm = dev_get_drvdata(&platformdev->dev);
450     Rk3568TxAndRxSetReg(i2sTdm, streamType, triggerFlag);
451     AUDIO_DEVICE_LOG_DEBUG("success");
452     return HDF_SUCCESS;
453 }
454