• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Unionman Technology Co., Ltd.
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 
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/dma-mapping.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/notifier.h>
17 #include <linux/of.h>
18 #include <linux/of_dma.h>
19 #include <linux/of_device.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 #include <linux/stat.h>
23 #include <linux/string.h>
24 #include <linux/sysfs.h>
25 #include <linux/suspend.h>
26 #include "sound/memalloc.h"
27 
28 #include "axg_snd_card.h"
29 
30 #include "audio_platform_base.h"
31 #include "osal_io.h"
32 #include "osal_uaccess.h"
33 #include "audio_driver_log.h"
34 #include "a311d_dma_ops.h"
35 
36 #define HDF_LOG_TAG a311d_dma_ops
37 
38 static struct axg_fifo *g_fifoDev[2]; // [0]: capture, [1]: playback
39 
A311DAudioDmaDeviceInit(const struct AudioCard * card,const struct PlatformDevice * platform)40 int32_t A311DAudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform)
41 {
42     struct PlatformData *data = NULL;
43 
44     if (meson_axg_snd_card_init()) {
45         AUDIO_DRIVER_LOG_ERR("axg_snd_card_init() failed.");
46         return HDF_FAILURE;
47     }
48 
49     g_fifoDev[AUDIO_CAPTURE_STREAM] = meson_axg_default_fifo_get(1);
50     g_fifoDev[AUDIO_RENDER_STREAM] = meson_axg_default_fifo_get(0);
51 
52     if (!g_fifoDev[AUDIO_CAPTURE_STREAM] || !g_fifoDev[AUDIO_RENDER_STREAM]) {
53         AUDIO_DRIVER_LOG_ERR("meson_axg_fifo_get failed.");
54         return HDF_FAILURE;
55     }
56 
57     data = PlatformDataFromCard(card);
58     if (data == NULL) {
59         AUDIO_DRIVER_LOG_ERR("PlatformDataFromCard failed.");
60         return HDF_FAILURE;
61     }
62 
63     if (data->platformInitFlag == true) {
64         AUDIO_DRIVER_LOG_INFO("platform already inited.");
65         return HDF_SUCCESS;
66     }
67 
68     data->platformInitFlag = true;
69 
70     AUDIO_DRIVER_LOG_DEBUG("success.");
71     return HDF_SUCCESS;
72 }
73 
A311DAudioDmaBufAlloc(struct PlatformData * data,const enum AudioStreamType streamType)74 int32_t A311DAudioDmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType)
75 {
76     uint32_t cirBufMax;
77     struct axg_fifo *fifo;
78 
79     AUDIO_DRIVER_LOG_DEBUG("streamType = %d", streamType);
80 
81     if (data == NULL) {
82         AUDIO_DRIVER_LOG_ERR("data is null");
83         return HDF_FAILURE;
84     }
85 
86     fifo = g_fifoDev[streamType];
87     cirBufMax = (streamType == AUDIO_CAPTURE_STREAM) ? data->captureBufInfo.cirBufMax : data->renderBufInfo.cirBufMax;
88 
89     AUDIO_DRIVER_LOG_DEBUG("streamType = %d, cirBufMax = %u", streamType, cirBufMax);
90 
91     if (cirBufMax > fifo->dma_area) {
92         AUDIO_DRIVER_LOG_ERR("requested buffer size(%u) is larger than dma_area(%u).",
93                              cirBufMax, fifo->dma_area);
94         return HDF_FAILURE;
95     }
96 
97     if (streamType == AUDIO_CAPTURE_STREAM) {
98         data->captureBufInfo.virtAddr = (uint32_t *)fifo->dma_vaddr;
99         data->captureBufInfo.phyAddr = fifo->dma_addr;
100     } else {
101         data->renderBufInfo.virtAddr = (uint32_t *)fifo->dma_vaddr;
102         data->renderBufInfo.phyAddr = fifo->dma_addr;
103     }
104 
105     AUDIO_DRIVER_LOG_DEBUG("success.");
106 
107     return HDF_SUCCESS;
108 }
109 
A311DAudioDmaBufFree(struct PlatformData * data,const enum AudioStreamType streamType)110 int32_t A311DAudioDmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType)
111 {
112     (void)data;
113     AUDIO_DRIVER_LOG_DEBUG("success");
114     return HDF_SUCCESS;
115 }
116 
A311DAudioDmaRequestChannel(const struct PlatformData * data,const enum AudioStreamType streamType)117 int32_t A311DAudioDmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
118 {
119     (void)data;
120     AUDIO_DRIVER_LOG_DEBUG("sucess");
121     return HDF_SUCCESS;
122 }
123 
A311DAudioDmaConfigChannel(const struct PlatformData * data,const enum AudioStreamType streamType)124 int32_t A311DAudioDmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
125 {
126     uint32_t period, cir_buf_size;
127     struct axg_fifo *fifo;
128 
129     AUDIO_DRIVER_LOG_DEBUG("streamType = %d", streamType);
130 
131     fifo = g_fifoDev[streamType];
132 
133     if (streamType == AUDIO_RENDER_STREAM) {
134         period = data->renderBufInfo.periodSize;
135         cir_buf_size = data->renderBufInfo.cirBufSize;
136     } else {
137         period = data->captureBufInfo.periodSize;
138         cir_buf_size = data->captureBufInfo.cirBufSize;
139     }
140 
141     meson_axg_fifo_pcm_hw_free(fifo);
142     if (meson_axg_fifo_pcm_hw_params(fifo, period, cir_buf_size)) {
143         AUDIO_DRIVER_LOG_ERR("meson_axg_fifo_pcm_hw_params(%u, %u) failed.\n",
144                              period, cir_buf_size);
145         return HDF_FAILURE;
146     }
147 
148     AUDIO_DRIVER_LOG_INFO("success. stream=%d, period=%u, cir_buf_size=%u",
149                           streamType, period, cir_buf_size);
150     return HDF_SUCCESS;
151 }
152 
BytesToFrames(uint32_t frameBytes,uint32_t size)153 static inline uint32_t BytesToFrames(uint32_t frameBytes, uint32_t size)
154 {
155     if (frameBytes == 0) {
156         AUDIO_DRIVER_LOG_ERR("input error. frameBits==0");
157         return 0;
158     }
159     return size / frameBytes;
160 }
161 
A311DAudioDmaPointer(struct PlatformData * data,const enum AudioStreamType streamType,uint32_t * pointer)162 int32_t A311DAudioDmaPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer)
163 {
164     uint32_t currentPointer;
165     uint32_t frameBytes;
166 
167     currentPointer = meson_axg_fifo_pcm_pointer(g_fifoDev[streamType]);
168 
169     frameBytes = (streamType == AUDIO_RENDER_STREAM) ? data->renderPcmInfo.frameSize : data->capturePcmInfo.frameSize;
170 
171     *pointer = BytesToFrames(frameBytes, currentPointer);
172 
173     return HDF_SUCCESS;
174 }
175 
A311DAudioDmaPrep(const struct PlatformData * data,const enum AudioStreamType streamType)176 int32_t A311DAudioDmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType)
177 {
178     (void)data;
179     AUDIO_DRIVER_LOG_DEBUG("sucess");
180     return HDF_SUCCESS;
181 }
182 
A311DAudioDmaSubmit(const struct PlatformData * data,const enum AudioStreamType streamType)183 int32_t A311DAudioDmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType)
184 {
185     int32_t ret;
186 
187     (void)data;
188     AUDIO_DRIVER_LOG_DEBUG("streamType = %d", streamType);
189 
190     ret = meson_axg_fifo_pcm_prepare(g_fifoDev[streamType]);
191 
192     AUDIO_DRIVER_LOG_DEBUG("ret: %d", ret);
193 
194     return ret;
195 }
196 
A311DAudioDmaPending(struct PlatformData * data,const enum AudioStreamType streamType)197 int32_t A311DAudioDmaPending(struct PlatformData *data, const enum AudioStreamType streamType)
198 {
199     int32_t ret;
200 
201     AUDIO_DRIVER_LOG_DEBUG("streamType = %d", streamType);
202 
203     ret = meson_axg_fifo_pcm_enable(g_fifoDev[streamType], true);
204 
205     AUDIO_DRIVER_LOG_DEBUG("ret: %d", ret);
206 
207     return ret;
208 }
209 
A311DAudioDmaPause(struct PlatformData * data,const enum AudioStreamType streamType)210 int32_t A311DAudioDmaPause(struct PlatformData *data, const enum AudioStreamType streamType)
211 {
212     int32_t ret;
213 
214     AUDIO_DRIVER_LOG_DEBUG("streamType = %d", streamType);
215 
216     ret = meson_axg_fifo_pcm_enable(g_fifoDev[streamType], false);
217 
218     AUDIO_DRIVER_LOG_DEBUG("success");
219     return ret;
220 }
221 
A311DAudioDmaResume(const struct PlatformData * data,const enum AudioStreamType streamType)222 int32_t A311DAudioDmaResume(const struct PlatformData *data, const enum AudioStreamType streamType)
223 {
224     int32_t ret;
225 
226     AUDIO_DRIVER_LOG_DEBUG("streamType = %d", streamType);
227 
228     ret = meson_axg_fifo_pcm_enable(g_fifoDev[streamType], true);
229 
230     AUDIO_DRIVER_LOG_DEBUG("ret: %d", ret);
231     return ret;
232 }
233