1 /*
2 * Copyright (c) 2022 Institute of Software, CAS.
3 * Author : huangji@nj.iscas.ac.cn
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <linux/device.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 #include <linux/mfd/rk808.h>
22 #include "rk817_codec.h"
23 #include "rk809_codec_impl.h"
24 #include "audio_accessory_base.h"
25 #include "audio_codec_if.h"
26 #include "audio_codec_base.h"
27 #include "audio_driver_log.h"
28
29 #define HDF_LOG_TAG "rk809_codec_adapter"
30
31 struct CodecData g_rk809Data = {
32 .Init = Rk809DeviceInit,
33 .Read = RK809CodecReadReg,
34 .Write = Rk809CodecWriteReg,
35 };
36
37 struct AudioDaiOps g_rk809DaiDeviceOps = {
38 .Startup = Rk809DaiStartup,
39 .HwParams = Rk809DaiHwParams,
40 .Trigger = Rk809NormalTrigger,
41 };
42
43 struct DaiData g_rk809DaiData = {
44 .DaiInit = Rk809DaiDeviceInit,
45 .ops = &g_rk809DaiDeviceOps,
46 };
47
48 static struct Rk809ChipData *g_chip;
GetCodecDevice(void)49 struct Rk809ChipData* GetCodecDevice(void)
50 {
51 return g_chip;
52 }
53 /* HdfDriverEntry */
GetServiceName(const struct HdfDeviceObject * device)54 static int32_t GetServiceName(const struct HdfDeviceObject *device)
55 {
56 const struct DeviceResourceNode *node = NULL;
57 struct DeviceResourceIface *drsOps = NULL;
58 int32_t ret;
59
60 if (device == NULL) {
61 AUDIO_DEVICE_LOG_ERR("input HdfDeviceObject object is nullptr.");
62 return HDF_FAILURE;
63 }
64 node = device->property;
65 if (node == NULL) {
66 AUDIO_DEVICE_LOG_ERR("get drs node is nullptr.");
67 return HDF_FAILURE;
68 }
69 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
70 if (drsOps == NULL || drsOps->GetString == NULL) {
71 AUDIO_DEVICE_LOG_ERR("drsOps or drsOps getString is null!");
72 return HDF_FAILURE;
73 }
74 ret = drsOps->GetString(node, "serviceName", &g_chip->codec.drvCodecName, 0);
75 if (ret != HDF_SUCCESS) {
76 AUDIO_DEVICE_LOG_ERR("read serviceName failed.");
77 return ret;
78 }
79 return HDF_SUCCESS;
80 }
81
82 /* HdfDriverEntry implementations */
Rk809DriverBind(struct HdfDeviceObject * device)83 static int32_t Rk809DriverBind(struct HdfDeviceObject *device)
84 {
85 struct CodecHost *codecHost;
86 if (device == NULL) {
87 AUDIO_DRIVER_LOG_ERR("input para is NULL.");
88 return HDF_FAILURE;
89 }
90
91 codecHost = (struct CodecHost *)OsalMemCalloc(sizeof(*codecHost));
92 if (codecHost == NULL) {
93 AUDIO_DRIVER_LOG_ERR("malloc codecHost fail!");
94 return HDF_FAILURE;
95 }
96 codecHost->device = device;
97 device->service = &codecHost->service;
98
99 return HDF_SUCCESS;
100 }
101
102 static void RK809ChipRelease(void);
103
Rk809DriverInit(struct HdfDeviceObject * device)104 static int32_t Rk809DriverInit(struct HdfDeviceObject *device)
105 {
106 int32_t ret;
107 struct regmap_config codecRegmapCfg = getCodecRegmap();
108 struct platform_device *codeDev = GetCodecPlatformDevice();
109 struct rk808 *rk808;
110 if (!codeDev) {
111 AUDIO_DEVICE_LOG_ERR("codeDev not ready");
112 return HDF_FAILURE;
113 }
114 g_chip = devm_kzalloc(&codeDev->dev, sizeof(struct Rk809ChipData), GFP_KERNEL);
115 if (!g_chip) {
116 return HDF_ERR_MALLOC_FAIL;
117 }
118 g_chip->codec = g_rk809Data;
119 g_chip->dai = g_rk809DaiData;
120 platform_set_drvdata(codeDev, g_chip);
121 g_chip->pdev = codeDev;
122 rk808 = dev_get_drvdata(g_chip->pdev->dev.parent);
123 if (!rk808) {
124 RK809ChipRelease();
125 return HDF_FAILURE;
126 }
127 g_chip->regmap = devm_regmap_init_i2c(rk808->i2c, &codecRegmapCfg);
128 if (IS_ERR(g_chip->regmap)) {
129 AUDIO_DEVICE_LOG_ERR("failed to allocate regmap: %ld\n", PTR_ERR(g_chip->regmap));
130 RK809ChipRelease();
131 return ret;
132 }
133 ret = CodecGetConfigInfo(device, &(g_chip->codec));
134 if (ret != HDF_SUCCESS) {
135 RK809ChipRelease();
136 return ret;
137 }
138 if (CodecSetConfigInfo(&(g_chip->codec), &(g_chip->dai)) != HDF_SUCCESS) {
139 return HDF_FAILURE;
140 }
141 ret = GetServiceName(device);
142 if (ret != HDF_SUCCESS) {
143 RK809ChipRelease();
144 return ret;
145 }
146 ret = CodecGetDaiName(device, &(g_chip->dai.drvDaiName));
147 if (ret != HDF_SUCCESS) {
148 return HDF_FAILURE;
149 }
150 ret = AudioRegisterCodec(device, &(g_chip->codec), &(g_chip->dai));
151 if (ret != HDF_SUCCESS) {
152 RK809ChipRelease();
153 return ret;
154 }
155 return HDF_SUCCESS;
156 }
157
RK809ChipRelease(void)158 static void RK809ChipRelease(void)
159 {
160 if (g_chip) {
161 platform_set_drvdata(g_chip->pdev, NULL);
162 if (g_chip->regmap) {
163 regmap_exit(g_chip->regmap);
164 }
165 devm_kfree(&g_chip->pdev->dev, g_chip);
166 }
167 AUDIO_DEVICE_LOG_ERR("success!");
168 return;
169 }
170
RK809DriverRelease(struct HdfDeviceObject * device)171 static void RK809DriverRelease(struct HdfDeviceObject *device)
172 {
173 struct CodecHost *codecHost;
174 if (device == NULL) {
175 AUDIO_DRIVER_LOG_ERR("device is NULL");
176 return;
177 }
178
179 if (device->priv != NULL) {
180 OsalMemFree(device->priv);
181 }
182 codecHost = (struct CodecHost *)device->service;
183 if (codecHost == NULL) {
184 HDF_LOGE("CodecDriverRelease: codecHost is NULL");
185 return;
186 }
187 OsalMemFree(codecHost);
188 }
189
190 /* HdfDriverEntry definitions */
191 struct HdfDriverEntry g_Rk809DriverEntry = {
192 .moduleVersion = 1,
193 .moduleName = "CODEC_RK809",
194 .Bind = Rk809DriverBind,
195 .Init = Rk809DriverInit,
196 .Release = RK809DriverRelease,
197 };
198
199 HDF_INIT(g_Rk809DriverEntry);
200