1 /*
2 * Copyright (C) 2021–2022 Beijing OSWare Technology Co., Ltd
3 * This file contains confidential and proprietary information of
4 * OSWare Technology Co., Ltd
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "audio_core.h"
20 #include "audio_driver_log.h"
21 #include "imx8mm_platform.h"
22 #include "imx8mm_common.h"
23 #include "osal_mem.h"
24 #include "imx8mm_platform_ops.h"
25
26 #define HDF_LOG_TAG imx8mm_platform_adapter
27
28 #define PLATFORM_FIND_SUCCESS 2
29 #define PLATFORM_FIND_NEXT 0
30
31 static int32_t AudioPlatformDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform);
32 static int32_t PlatformDmaPrvDataInit(struct PlatformData *data, struct HdfDeviceObject *device);
33
34 struct AudioDmaOps g_platform_device_ops = {
35 .DmaBufAlloc = Imx8mmDmaBufAlloc,
36 .DmaBufFree = Imx8mmDmaBufFree,
37 .DmaRequestChannel = Imx8mmDmaRequestChannel,
38 .DmaConfigChannel = Imx8mmDmaConfigChannel,
39 .DmaPrep = Imx8mmDmaPrep,
40 .DmaSubmit = Imx8mmDmaSubmit,
41 .DmaPending = Imx8mmDmaPending,
42 .DmaPause = Imx8mmDmaPause,
43 .DmaResume = Imx8mmDmaResume,
44 .DmaPointer = Imx8mmDmaPointer,
45 };
46
47 struct PlatformData g_platform_data = {
48 .PlatformInit = AudioPlatformDeviceInit,
49 .ops = &g_platform_device_ops,
50 .platformInitFlag = false,
51 };
52
53 /* HdfDriverEntry implementations */
PlatformDriverBind(struct HdfDeviceObject * device)54 static int32_t PlatformDriverBind(struct HdfDeviceObject *device)
55 {
56 struct PlatformHost *platformHost = NULL;
57 AUDIO_DRIVER_LOG_DEBUG("entry!");
58
59 if (device == NULL) {
60 AUDIO_DRIVER_LOG_ERR("input para is NULL.");
61 return HDF_FAILURE;
62 }
63
64 platformHost = (struct PlatformHost *)OsalMemCalloc(sizeof(*platformHost));
65 if (platformHost == NULL) {
66 AUDIO_DRIVER_LOG_ERR("malloc host fail!");
67 return HDF_FAILURE;
68 }
69
70 platformHost->device = device;
71 device->service = &platformHost->service;
72
73 AUDIO_DRIVER_LOG_DEBUG("success!");
74 return HDF_SUCCESS;
75 }
76
PlatformGetServiceName(const struct HdfDeviceObject * device)77 static int32_t PlatformGetServiceName(const struct HdfDeviceObject *device)
78 {
79 const struct DeviceResourceNode *node = NULL;
80 struct DeviceResourceIface *drsOps = NULL;
81 int32_t ret;
82
83 if (device == NULL) {
84 AUDIO_DRIVER_LOG_ERR("para is NULL.");
85 return HDF_FAILURE;
86 }
87
88 node = device->property;
89 if (node == NULL) {
90 AUDIO_DRIVER_LOG_ERR("node is NULL.");
91 return HDF_FAILURE;
92 }
93
94 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
95 if (drsOps == NULL || drsOps->GetString == NULL) {
96 AUDIO_DRIVER_LOG_ERR("get drsops object instance fail!");
97 return HDF_FAILURE;
98 }
99
100 ret = drsOps->GetString(node, "serviceName", &g_platform_data.drvPlatformName, 0);
101 if (ret != HDF_SUCCESS) {
102 AUDIO_DRIVER_LOG_ERR("read serviceName fail!");
103 return ret;
104 }
105
106 return HDF_SUCCESS;
107 }
108
PlatformDriverInit(struct HdfDeviceObject * device)109 static int32_t PlatformDriverInit(struct HdfDeviceObject *device)
110 {
111 int32_t ret;
112
113 AUDIO_DRIVER_LOG_DEBUG("entry.\n");
114 struct PlatformHost *platformHost = NULL;
115
116 if (device == NULL) {
117 AUDIO_DRIVER_LOG_ERR("device is NULL.");
118 return HDF_ERR_INVALID_OBJECT;
119 }
120
121 ret = PlatformGetServiceName(device);
122 if (ret != HDF_SUCCESS) {
123 AUDIO_DRIVER_LOG_ERR("get service name fail.");
124 return ret;
125 }
126
127 ret = AudioSocRegisterPlatform(device, (struct PlatformData *)(&g_platform_data));
128 if (ret != HDF_SUCCESS) {
129 AUDIO_DRIVER_LOG_ERR("register dai fail.");
130 return ret;
131 }
132
133 platformHost = (struct PlatformHost *)device->service;
134 if (platformHost != NULL) {
135 OsalMutexInit(&g_platform_data.renderBufInfo.buffMutex);
136 OsalMutexInit(&g_platform_data.captureBufInfo.buffMutex);
137 }
138
139 ret = PlatformDmaPrvDataInit(&g_platform_data, device);
140 if (ret != HDF_SUCCESS) {
141 AUDIO_DRIVER_LOG_ERR("platform soc init fail");
142 return ret;
143 }
144
145 AUDIO_DRIVER_LOG_INFO("success.\n");
146 return HDF_SUCCESS;
147 }
148
PlatformDriverRelease(struct HdfDeviceObject * device)149 static void PlatformDriverRelease(struct HdfDeviceObject *device)
150 {
151 struct PlatformHost *platformHost = NULL;
152
153 if (device == NULL) {
154 AUDIO_DRIVER_LOG_ERR("device is NULL");
155 return;
156 }
157
158 platformHost = (struct PlatformHost *)device->service;
159 if (platformHost == NULL) {
160 AUDIO_DRIVER_LOG_ERR("platformHost is NULL");
161 return;
162 }
163
164 OsalMutexDestroy(&g_platform_data.renderBufInfo.buffMutex);
165 OsalMutexDestroy(&g_platform_data.captureBufInfo.buffMutex);
166 OsalMemFree(platformHost);
167 }
168
AudioPlatformDeviceInit(const struct AudioCard * card,const struct PlatformDevice * platform)169 static int32_t AudioPlatformDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform)
170 {
171 AUDIO_DRIVER_LOG_ERR("ENTRY");
172 if (card == NULL || platform == NULL || platform->devData == NULL) {
173 AUDIO_DRIVER_LOG_ERR("platform is NULL.");
174 return HDF_FAILURE;
175 }
176 if (platform->devData->platformInitFlag == true) {
177 AUDIO_DRIVER_LOG_DEBUG("platform init complete!");
178 return HDF_SUCCESS;
179 }
180 platform->devData->platformInitFlag = true;
181
182 SaiDaiProbe(platform->devData);
183
184 return HDF_SUCCESS;
185 }
186
PlatformGetInfoFromHcs(struct PrivPlatformData * ppd,const struct DeviceResourceNode * node)187 static int32_t PlatformGetInfoFromHcs(struct PrivPlatformData *ppd,
188 const struct DeviceResourceNode *node)
189 {
190 struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
191 if (ppd == NULL || node == NULL || iface == NULL || iface->GetString == NULL) {
192 AUDIO_DRIVER_LOG_ERR("face is invalid");
193 return HDF_FAILURE;
194 }
195
196 if (iface->GetString(node, "sai_name", &ppd->sai_name, NULL) != HDF_SUCCESS) {
197 AUDIO_DRIVER_LOG_ERR("read sai_name fail");
198 return HDF_FAILURE;
199 }
200
201 AUDIO_DRIVER_LOG_ERR("sai name = %s", ppd->sai_name);
202
203 return HDF_SUCCESS;
204 }
205
PlatformFindDeviceFromBus(struct device * dev,void * para)206 static int32_t PlatformFindDeviceFromBus(struct device *dev, void *para)
207 {
208 struct platform_device *pdev = NULL;
209 struct PrivPlatformData *ppd = (struct PrivPlatformData*)para;
210
211 if (dev == NULL || para == NULL) {
212 AUDIO_DRIVER_LOG_ERR("invalid param");
213 return HDF_ERR_INVALID_PARAM;
214 }
215
216 pdev = to_platform_device(dev);
217 if (pdev->name == NULL) {
218 AUDIO_DRIVER_LOG_ERR("pdev name NULL");
219 return HDF_ERR_INVALID_PARAM;
220 }
221
222 if (!strstr(pdev->name, ppd->sai_name)) {
223 return PLATFORM_FIND_NEXT;
224 }
225 ppd->pdev = pdev;
226
227 return PLATFORM_FIND_SUCCESS;
228 }
229
PlatformDmaPrvDataInit(struct PlatformData * data,struct HdfDeviceObject * device)230 static int32_t PlatformDmaPrvDataInit(struct PlatformData *data, struct HdfDeviceObject *device)
231 {
232 int32_t ret;
233 struct PrivPlatformData *ppd = NULL;
234
235 if (device->property == NULL|| data == NULL) {
236 AUDIO_DRIVER_LOG_ERR("property is null");
237 return HDF_FAILURE;
238 }
239
240 ppd = (struct PrivPlatformData *)OsalMemCalloc(sizeof(struct PrivPlatformData));
241 if (ppd == NULL) {
242 AUDIO_DRIVER_LOG_ERR("OsalMemCalloc malloc error");
243 return HDF_ERR_MALLOC_FAIL;
244 }
245
246 ret = PlatformGetInfoFromHcs(ppd, device->property);
247 if (ret != HDF_SUCCESS) {
248 AUDIO_DRIVER_LOG_ERR("PlatformGetInfoFromHcs error");
249 OsalMemFree(ppd);
250 return HDF_FAILURE;
251 }
252
253 data->dmaPrv = ppd;
254
255 ret = bus_for_each_dev(&platform_bus_type, NULL, (void*)ppd, PlatformFindDeviceFromBus);
256 if (ret != PLATFORM_FIND_SUCCESS) {
257 AUDIO_DRIVER_LOG_ERR("platform find fail, ret is %d", ret);
258 return HDF_FAILURE;
259 }
260
261 AUDIO_DRIVER_LOG_ERR("sai_name = %s", ppd->pdev->name);
262
263 ret = SaiDriverInit(data);
264 AUDIO_DRIVER_LOG_ERR("RET = %d", ret);
265 ret = DmaInit(data);
266 AUDIO_DRIVER_LOG_ERR("RET = %d", ret);
267
268 return HDF_SUCCESS;
269 }
270
271 /* HdfDriverEntry definitions */
272 struct HdfDriverEntry g_platform_driver_entry = {
273 .moduleVersion = 1,
274 .moduleName = "SAI_IMX8",
275 .Bind = PlatformDriverBind,
276 .Init = PlatformDriverInit,
277 .Release = PlatformDriverRelease,
278 };
279 HDF_INIT(g_platform_driver_entry);
280