1 /*
2  * Copyright (c) 2022 Jiangsu Hoperun Software Co., Ltd.
3  *
4  * This file 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 <stdlib.h>
10 #include <stdio.h>
11 #include "device_resource_if.h"
12 #include "hdf_device_desc.h"
13 #include "pwm_core.h"
14 #include "hdf_log.h"
15 #include "wm_pwm.h"
16 
17 struct PwmResource {
18     uint32_t channel;
19     uint32_t freq;
20 };
21 
22 struct PwmDevice {
23     struct IDeviceIoService ioService;
24     pwm_init_param pwmCfg;
25     struct PwmConfig *cfg;
26     struct PwmResource resource;
27 };
28 
29 static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config);
30 
31 struct PwmMethod g_pwmmethod = {
32     .setConfig = PwmDevSetConfig,
33 };
34 
PwmDevSetConfig(struct PwmDev * pwm,struct PwmConfig * config)35 static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config)
36 {
37     struct PwmDevice *prvPwm = NULL;
38     pwm_init_param *pwmCfg = NULL;
39     uint32_t freq;
40 
41     if (pwm == NULL || config == NULL) {
42         HDF_LOGE("%s\r\n", __FUNCTION__);
43         return HDF_FAILURE;
44     }
45 
46     prvPwm = (struct PwmDevice *)PwmGetPriv(pwm);
47     if (prvPwm == NULL) {
48         return HDF_FAILURE;
49     }
50     pwmCfg = &prvPwm->pwmCfg;
51     pwmCfg->period = config->period;
52     pwmCfg->duty = config->duty;
53     pwmCfg->pnum = config->number;
54     pwmCfg->channel = prvPwm->resource.channel;
55     freq = prvPwm->resource.freq;
56 
57     if (config->status == PWM_ENABLE_STATUS) {
58         tls_pwm_init(pwmCfg->channel, freq, pwmCfg->duty, pwmCfg->pnum);
59     }
60 
61     return HDF_SUCCESS;
62 }
63 
GetPwmDeviceResource(struct PwmDevice * device,const struct DeviceResourceNode * resourceNode)64 static uint32_t GetPwmDeviceResource(
65     struct PwmDevice *device, const struct DeviceResourceNode *resourceNode)
66 {
67     struct DeviceResourceIface *dri = NULL;
68     struct PwmResource *resource = NULL;
69     if (device == NULL || resourceNode == NULL) {
70         HDF_LOGE("resource or device is NULL\r\n");
71         return HDF_ERR_INVALID_PARAM;
72     }
73 
74     resource = &device->resource;
75     if (resource == NULL) {
76         HDF_LOGE("resource is NULL\r\n");
77         return HDF_ERR_INVALID_OBJECT;
78     }
79 
80     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
81     if (dri == NULL || dri->GetUint32 == NULL) {
82         HDF_LOGE("DeviceResourceIface is invalid\r\n");
83         return HDF_ERR_INVALID_PARAM;
84     }
85 
86     if (dri->GetUint32(resourceNode, "channel", &resource->channel, 0) != HDF_SUCCESS) {
87         HDF_LOGE("read channel fail\r\n");
88         return HDF_FAILURE;
89     }
90 
91     if (dri->GetUint32(resourceNode, "freq", &resource->freq, 0) != HDF_SUCCESS) {
92         HDF_LOGE("read freq fail\r\n");
93         return HDF_FAILURE;
94     }
95 
96     return HDF_SUCCESS;
97 }
98 
AttachPwmDevice(struct PwmDev * host,const struct HdfDeviceObject * device)99 static int32_t AttachPwmDevice(struct PwmDev *host, const struct HdfDeviceObject *device)
100 {
101     int32_t ret;
102     struct PwmDevice *pwmDevice = NULL;
103     if (device == NULL || device->property == NULL || host == NULL) {
104         HDF_LOGE("%s: param is NULL\r\n", __func__);
105         return HDF_ERR_INVALID_PARAM;
106     }
107 
108     pwmDevice = (struct PwmDevice *)OsalMemAlloc(sizeof(struct PwmDevice));
109     if (pwmDevice == NULL) {
110         HDF_LOGE("%s: OsalMemAlloc pwmDevice error\r\n", __func__);
111         return HDF_ERR_MALLOC_FAIL;
112     }
113 
114     ret = GetPwmDeviceResource(pwmDevice, device->property);
115     if (ret != HDF_SUCCESS) {
116         (void)OsalMemFree(pwmDevice);
117         return HDF_FAILURE;
118     }
119 
120     host->priv = pwmDevice;
121 
122     return HDF_SUCCESS;
123 }
124 
PwmDriverBind(struct HdfDeviceObject * device)125 static int32_t PwmDriverBind(struct HdfDeviceObject *device)
126 {
127     static struct PwmDev devService;
128 
129     if (device == NULL) {
130         HDF_LOGE("hdfDevice object is null!\r\n");
131         return HDF_FAILURE;
132     }
133 
134     device->service = &devService.service;
135     devService.device = device;
136     HDF_LOGI("Enter %s\r\n", __func__);
137 
138     return HDF_SUCCESS;
139 }
140 
PwmDriverInit(struct HdfDeviceObject * device)141 static int32_t PwmDriverInit(struct HdfDeviceObject *device)
142 {
143     int32_t ret;
144     struct PwmDev *host = NULL;
145 
146     if (device == NULL) {
147         HDF_LOGE("%s: device is NULL\r\n", __func__);
148         return HDF_ERR_INVALID_OBJECT;
149     }
150 
151     HDF_LOGI("Enter %s:\r\n", __func__);
152 
153     host = (struct PwmDev *)OsalMemAlloc(sizeof(struct PwmDev));
154     if (host == NULL) {
155         HDF_LOGE("%s: host is NULL\r\n", __func__);
156         return HDF_ERR_MALLOC_FAIL;
157     }
158 
159     ret = AttachPwmDevice(host, device);
160     if (ret != HDF_SUCCESS) {
161         OsalMemFree(host);
162         HDF_LOGE("%s:attach error\r\n", __func__);
163         return HDF_DEV_ERR_ATTACHDEV_FAIL;
164     }
165 
166     host->method = &g_pwmmethod;
167     ret = PwmDeviceAdd(device, host);
168     if (ret != HDF_SUCCESS) {
169         PwmDeviceRemove(device, host);
170         OsalMemFree(host->device);
171         OsalMemFree(host);
172         return HDF_DEV_ERR_NO_DEVICE;
173     }
174 
175     HDF_LOGI("PwmDriverInit success!\r\n");
176     return HDF_SUCCESS;
177 }
178 
PwmDriverRelease(struct HdfDeviceObject * device)179 static void PwmDriverRelease(struct HdfDeviceObject *device)
180 {
181     struct PwmDev *host = NULL;
182 
183     if (device == NULL || device->service == NULL) {
184         HDF_LOGE("device is null\r\n");
185         return;
186     }
187 
188     host = (struct PwmDev *)device->service;
189     if (host->device != NULL) {
190         host->method = NULL;
191         OsalMemFree(host->device);
192         OsalMemFree(host);
193         host->device = NULL;
194         host = NULL;
195     }
196 
197     device->service = NULL;
198     HDF_LOGI("PwmDriverRelease finish!!\r\n");
199     return;
200 }
201 
202 /* HdfDriverEntry definitions */
203 struct HdfDriverEntry g_pwmDriverEntry = {
204     .moduleVersion = 1,
205     .moduleName = "WM_PWM_MODULE_HDF",
206     .Bind = PwmDriverBind,
207     .Init = PwmDriverInit,
208     .Release = PwmDriverRelease,
209 };
210 
211 // Initialize HdfDriverEntry
212 HDF_INIT(g_pwmDriverEntry);
213