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