1 /*
2 * Copyright (c) 2022 Huawei Device 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/device.h>
10 #include <linux/err.h>
11 #include <linux/errno.h>
12 #include <linux/extcon-provider.h>
13 #include <linux/iio/consumer.h>
14 #include <linux/input.h>
15 #include <linux/interrupt.h>
16 #include <linux/irq.h>
17 #include <linux/platform_device.h>
18 #include "analog_headset.h"
19 #include "analog_headset_base.h"
20 #include "hdf_workqueue.h"
21 #include "osal_time.h"
22 #include "osal_mem.h"
23 #include "securec.h"
24 #include "gpio_if.h"
25 #include "osal_irq.h"
26
27 #define HDF_LOG_TAG analog_headset_adc
28 #define HOOK_ADC_SAMPLE_TIME 100
29
30 #define HOOK_LEVEL_HIGH 410 // 1V*1024/2.5
31 #define HOOK_LEVEL_LOW 204 // 0.5V*1024/2.5
32 #define HOOK_DEFAULT_VAL 1024
33
34 #define HEADSET_IN 1
35 #define HEADSET_OUT 0
36 #define HOOK_DOWN 1
37 #define HOOK_UP 0
38
39 #define HEADSET_TIMER 1
40 #define HOOK_TIMER 2
41
42 #define WAIT 2
43 #define BUSY 1
44 #define IDLE 0
45
46 /* headset private data */
47 struct HeadsetPriv {
48 struct input_dev *inDev;
49 struct HeadsetPdata *pdata;
50 uint32_t hsStatus : 1;
51 uint32_t hookStatus : 1;
52 struct iio_channel *chan;
53 /* headset interrupt working will not check hook key */
54 uint32_t hsIrqWorking;
55 int32_t curHsStatus;
56 HdfWorkQueue workQueue;
57 HdfWork hDelayedWork[HS_HOOK_COUNT];
58 struct extcon_dev *edev;
59 unsigned char *keycodes;
60 HdfWork hHookWork;
61 /* ms */
62 uint32_t hookTime;
63 bool isMic;
64 };
65
66 static struct HeadsetPriv *g_hsInfo = NULL;
67
ExtconSetStateSync(struct HeadsetPriv * hs,unsigned int id,bool state)68 static int ExtconSetStateSync(struct HeadsetPriv *hs, unsigned int id, bool state)
69 {
70 if (hs == NULL) {
71 AUDIO_DEVICE_LOG_ERR("hs is NULL!");
72 return -EINVAL;
73 }
74
75 extcon_set_state_sync(hs->edev, id, state);
76 SetStateSync(id, state);
77 AUDIO_DEVICE_LOG_DEBUG("id = %u, state = %s.", id, state ? "in" : "out");
78
79 return 0;
80 }
81
InputReportKeySync(struct HeadsetPriv * hs,unsigned int code,int value)82 static void InputReportKeySync(struct HeadsetPriv *hs, unsigned int code, int value)
83 {
84 if (hs == NULL) {
85 AUDIO_DEVICE_LOG_ERR("hs is NULL!");
86 return;
87 }
88
89 input_report_key(hs->inDev, code, value);
90 input_sync(hs->inDev);
91 SetStateSync(code, value);
92 AUDIO_DEVICE_LOG_DEBUG("code = %u, value = %s.", code, value ? "in" : "out");
93 }
94
InitHeadsetPriv(struct HeadsetPriv * hs,struct HeadsetPdata * pdata)95 static void InitHeadsetPriv(struct HeadsetPriv *hs, struct HeadsetPdata *pdata)
96 {
97 if ((hs == NULL) || (pdata == NULL)) {
98 AUDIO_DEVICE_LOG_ERR("hs or pdata is NULL!");
99 return;
100 }
101
102 hs->pdata = pdata;
103 hs->hsStatus = HEADSET_OUT;
104 hs->hsIrqWorking = IDLE;
105 hs->hookStatus = HOOK_UP;
106 hs->hookTime = HOOK_ADC_SAMPLE_TIME;
107 hs->curHsStatus = BIT_HEADSET_NULL;
108 hs->isMic = false;
109 AUDIO_DEVICE_LOG_DEBUG("isMic = %s.", hs->isMic ? "true" : "false");
110 hs->chan = pdata->chan;
111 }
112
CheckState(struct HeadsetPriv * hs,bool * beChange)113 static int32_t CheckState(struct HeadsetPriv *hs, bool *beChange)
114 {
115 struct HeadsetPdata *pdata = NULL;
116 static uint32_t oldStatus = 0;
117 int32_t i;
118 int32_t ret;
119 int16_t level = 0;
120
121 if ((hs == NULL) || (hs->pdata == NULL) || (beChange == NULL)) {
122 AUDIO_DEVICE_LOG_ERR("hs, pdata or beChange is NULL.");
123 return HDF_ERR_INVALID_PARAM;
124 }
125
126 pdata = hs->pdata;
127 OsalMSleep(IRQ_CONFIRM_MS150);
128 for (i = 0; i < GET_GPIO_REPEAT_TIMES; i++) {
129 ret = GpioRead(pdata->hsGpio, &level);
130 if (ret < 0) {
131 AUDIO_DEVICE_LOG_ERR("get pin level again, pin=%u, i=%d.", pdata->hsGpio, i);
132 OsalMSleep(IRQ_CONFIRM_MS1);
133 continue;
134 }
135 break;
136 }
137 if ((level < 0) || (ret < 0)) {
138 AUDIO_DEVICE_LOG_ERR("get pin level err.");
139 return HDF_FAILURE;
140 }
141
142 oldStatus = hs->hsStatus;
143 switch (pdata->hsInsertType) {
144 case HEADSET_IN_HIGH:
145 hs->hsStatus = (level > 0) ? HEADSET_IN : HEADSET_OUT;
146 break;
147 case HEADSET_IN_LOW:
148 hs->hsStatus = (level == 0) ? HEADSET_IN : HEADSET_OUT;
149 break;
150 default:
151 AUDIO_DEVICE_LOG_ERR("[hsInsertType] error.");
152 break;
153 }
154 if (oldStatus == hs->hsStatus) {
155 *beChange = false;
156 return HDF_SUCCESS;
157 }
158
159 *beChange = true;
160 AUDIO_DEVICE_LOG_DEBUG("(headset in is %s)headset status is %s.",
161 pdata->hsInsertType ? "high" : "low", hs->hsStatus ? "in" : "out");
162
163 return HDF_SUCCESS;
164 }
165
ReportCurrentState(struct HeadsetPriv * hs)166 static int32_t ReportCurrentState(struct HeadsetPriv *hs)
167 {
168 struct HeadsetPdata *pdata = NULL;
169
170 if ((hs == NULL) || (hs->pdata == NULL)) {
171 AUDIO_DEVICE_LOG_ERR("hs or pdata is NULL.");
172 return HDF_ERR_INVALID_PARAM;
173 }
174
175 pdata = hs->pdata;
176 if (hs->hsStatus == HEADSET_IN) {
177 if (pdata->chan != NULL) {
178 /* detect hook key */
179 (void)HdfAddDelayedWork(&hs->workQueue, &hs->hDelayedWork[HOOK], DELAY_WORK_MS200);
180 } else {
181 hs->isMic = false;
182 AUDIO_DEVICE_LOG_DEBUG("isMic = %s.", hs->isMic ? "true" : "false");
183 hs->curHsStatus = BIT_HEADSET_NO_MIC;
184 (void)ExtconSetStateSync(hs, KEY_JACK_HEADPHONE, true);
185 AUDIO_DEVICE_LOG_DEBUG("notice headset status = %d(0: NULL, 1: HEADSET, 2: HEADPHONE).", hs->curHsStatus);
186 }
187 } else {
188 hs->curHsStatus = BIT_HEADSET_NULL;
189 HdfCancelDelayedWorkSync(&hs->hHookWork);
190 if (hs->isMic) {
191 if (hs->hookStatus == HOOK_DOWN) {
192 hs->hookStatus = HOOK_UP;
193 InputReportKeySync(hs, HOOK_KEY_CODE, hs->hookStatus);
194 }
195 hs->isMic = false;
196 AUDIO_DEVICE_LOG_DEBUG("isMic = %s.", hs->isMic ? "true" : "false");
197 }
198
199 // Need judge the type, it is not always microphone.
200 (void)ExtconSetStateSync(hs, KEY_JACK_HEADSET, false);
201 AUDIO_DEVICE_LOG_DEBUG("notice headset status = %d(0: NULL, 1: HEADSET, 2:HEADPHONE).", hs->curHsStatus);
202 }
203
204 return HDF_SUCCESS;
205 }
206
HeadsetInterrupt(uint16_t gpio,void * data)207 static int32_t HeadsetInterrupt(uint16_t gpio, void * data)
208 {
209 int32_t ret;
210 struct HeadsetPriv *hs = g_hsInfo;
211 bool beChange = false;
212
213 (void)data;
214 if (hs == NULL) {
215 AUDIO_DEVICE_LOG_ERR("hs is NULL.");
216 return -EINVAL;
217 }
218
219 GpioDisableIrq(hs->pdata->hsGpio);
220 if ((hs->hsIrqWorking == BUSY) ||
221 (hs->hsIrqWorking == WAIT)) {
222 AUDIO_DEVICE_LOG_DEBUG("hsIrqWorking is BUSY or WAIT.");
223 return IRQ_HANDLED;
224 }
225
226 hs->hsIrqWorking = BUSY;
227 ret = CheckState(hs, &beChange);
228 if (ret != HDF_SUCCESS) {
229 AUDIO_DEVICE_LOG_DEBUG("[CheckState] failed.");
230 hs->hsIrqWorking = IDLE;
231 GpioEnableIrq(hs->pdata->hsGpio);
232 return IRQ_HANDLED;
233 }
234 if (!beChange) {
235 hs->hsIrqWorking = IDLE;
236 GpioEnableIrq(hs->pdata->hsGpio);
237 return IRQ_HANDLED;
238 }
239
240 (void)ReportCurrentState(hs);
241 hs->hsIrqWorking = IDLE;
242 GpioEnableIrq(hs->pdata->hsGpio);
243 return IRQ_HANDLED;
244 }
245
246 #ifdef TEST_FOR_CHANGE_IRQTYPE /* not actived. */
HeadsetChangeIrqtype(int type,unsigned int irqType)247 static int32_t HeadsetChangeIrqtype(int type, unsigned int irqType)
248 {
249 int32_t ret;
250
251 free_irq(g_hsInfo->irq[type], NULL);
252
253 AUDIO_DEVICE_LOG_DEBUG("type is %s irqtype is %s.", type ? "hook" : "headset",
254 (irqType == IRQF_TRIGGER_RISING) ? "RISING" : "FALLING");
255 AUDIO_DEVICE_LOG_DEBUG("type is %s irqtype is %s.",
256 type ? "hook" : "headset", (irqType == IRQF_TRIGGER_LOW) ? "LOW" : "HIGH");
257 switch (type) {
258 case HEADSET:
259 ret = request_threaded_irq(g_hsInfo->irq[type], NULL, HeadsetInterrupt, irqType, "headset_input", NULL);
260 if (ret < 0) {
261 AUDIO_DEVICE_LOG_DEBUG("HeadsetChangeIrqtype: request irq failed.");
262 }
263 break;
264 default:
265 ret = -EINVAL;
266 break;
267 }
268 return ret;
269 }
270 #endif
271
HookOnceWork(void * arg)272 static void HookOnceWork(void *arg)
273 {
274 int32_t ret;
275 int32_t val;
276 uint32_t type;
277 struct HeadsetPriv *hs = (struct HeadsetPriv *)arg;
278
279 if (hs == NULL) {
280 AUDIO_DEVICE_LOG_ERR("hs is NULL.");
281 return;
282 }
283 ret = iio_read_channel_raw(hs->chan, &val);
284 if (ret < 0) {
285 AUDIO_DEVICE_LOG_ERR("read HookOnceWork adc channel() error: %d.", ret);
286 } else {
287 AUDIO_DEVICE_LOG_DEBUG("HookOnceWork read adc value: %d.", val);
288 }
289
290 if (val >= 0 && val < HOOK_LEVEL_LOW) {
291 hs->isMic = false;
292 } else if (val >= HOOK_LEVEL_HIGH) {
293 hs->isMic = true;
294 (void)HdfAddDelayedWork(&hs->workQueue, &hs->hHookWork, DELAY_WORK_MS100);
295 } else {
296 ; // do nothing.
297 }
298 AUDIO_DEVICE_LOG_DEBUG("isMic = %s.", g_hsInfo->isMic ? "true" : "false");
299 hs->curHsStatus = hs->isMic ? BIT_HEADSET : BIT_HEADSET_NO_MIC;
300
301 if (hs->curHsStatus != BIT_HEADSET_NULL) {
302 type = (hs->isMic) ? KEY_JACK_HEADSET : KEY_JACK_HEADPHONE;
303 (void)ExtconSetStateSync(hs, type, true);
304 }
305 AUDIO_DEVICE_LOG_DEBUG("notice headset status = %d(0: NULL, 1: HEADSET, 2:HEADPHONE).", hs->curHsStatus);
306 }
307
CheckInsertType(struct HeadsetPdata * pdata)308 static int32_t CheckInsertType(struct HeadsetPdata *pdata)
309 {
310 int32_t i;
311 int32_t ret;
312 int16_t level = 0;
313
314 for (i = 0; i < GET_GPIO_REPEAT_TIMES; i++) {
315 ret = GpioRead(pdata->hsGpio, &level);
316 if (ret < 0) {
317 AUDIO_DEVICE_LOG_ERR("get pin level again, pin=%u, i=%d.", pdata->hsGpio, i);
318 OsalMSleep(IRQ_CONFIRM_MS1);
319 continue;
320 }
321 break;
322 }
323
324 if ((level < 0) || (ret < 0)) {
325 AUDIO_DEVICE_LOG_ERR("get pin level err.");
326 return HDF_FAILURE;
327 }
328
329 switch (pdata->hsInsertType) {
330 case HEADSET_IN_HIGH:
331 ret = (level > 0) ? HEADSET_IN : HEADSET_OUT;
332 break;
333 case HEADSET_IN_LOW:
334 ret = (level == 0) ? HEADSET_IN : HEADSET_OUT;
335 break;
336 default:
337 ret = HDF_FAILURE;
338 AUDIO_DEVICE_LOG_ERR("[hsInsertType] error.");
339 break;
340 }
341
342 return ret;
343 }
344
HookWorkCallback(void * arg)345 static void HookWorkCallback(void * arg)
346 {
347 int32_t ret;
348 int32_t val;
349 struct HeadsetPriv *hs = (struct HeadsetPriv *)arg;
350 static uint32_t oldStatus = HOOK_UP;
351 static int32_t oldVal = -1; // Invalid initial value
352
353 if ((hs == NULL) || (hs->pdata == NULL)) {
354 AUDIO_DEVICE_LOG_ERR("hs or hs->pdata is NULL.");
355 return;
356 }
357
358 ret = iio_read_channel_raw(hs->chan, &val);
359 if (ret < 0) {
360 AUDIO_DEVICE_LOG_ERR("read hook adc channel() error: %d.", ret);
361 return;
362 }
363
364 ret = CheckInsertType(hs->pdata);
365 if ((hs->hsStatus == HEADSET_OUT) || (hs->hsIrqWorking == BUSY) || (hs->hsIrqWorking == WAIT) ||
366 (ret != HEADSET_IN)) {
367 AUDIO_DEVICE_LOG_DEBUG("Headset is out or waiting for headset is in or out, after same time check HOOK key.");
368 return;
369 }
370 oldStatus = hs->hookStatus;
371 if (val < HOOK_LEVEL_LOW && val >= 0) {
372 hs->hookStatus = HOOK_DOWN;
373 } else if (val > HOOK_LEVEL_HIGH && val < HOOK_DEFAULT_VAL) {
374 hs->hookStatus = HOOK_UP;
375 } else {
376 ; // do nothing.
377 }
378 if (oldVal != val) {
379 AUDIO_DEVICE_LOG_DEBUG("HOOK status is %s , adc value = %d, hookTime = %u.",
380 hs->hookStatus ? "down" : "up", val, hs->hookTime);
381 oldVal = val;
382 }
383 if (oldStatus == hs->hookStatus) {
384 (void)HdfAddDelayedWork(&hs->workQueue, &hs->hHookWork, DELAY_WORK_MS100);
385 return;
386 }
387
388 ret = CheckInsertType(hs->pdata);
389 if ((hs->hsStatus == HEADSET_OUT) || (hs->hsIrqWorking == BUSY) || (hs->hsIrqWorking == WAIT) ||
390 (ret != HEADSET_IN)) {
391 AUDIO_DEVICE_LOG_DEBUG("headset is out, HOOK status must discard.");
392 return;
393 }
394 InputReportKeySync(hs, HOOK_KEY_CODE, hs->hookStatus);
395 (void)HdfAddDelayedWork(&hs->workQueue, &hs->hHookWork, DELAY_WORK_MS100);
396 }
397
AnalogHskeyOpen(struct input_dev * dev)398 static int AnalogHskeyOpen(struct input_dev *dev)
399 {
400 (void)dev;
401 return 0;
402 }
403
AnalogHskeyClose(struct input_dev * dev)404 static void AnalogHskeyClose(struct input_dev *dev)
405 {
406 (void)dev;
407 }
408
409 static const unsigned int g_hsCable[] = {
410 KEY_JACK_HEADSET,
411 KEY_JACK_HEADPHONE,
412 EXTCON_NONE,
413 };
414
InitWorkData(struct HeadsetPriv * hs)415 static int32_t InitWorkData(struct HeadsetPriv *hs)
416 {
417 struct HeadsetPdata *pdata = NULL;
418 if ((hs == NULL) || (hs->pdata == NULL)) {
419 AUDIO_DEVICE_LOG_ERR("hs or pdata is NULL.");
420 return HDF_ERR_INVALID_PARAM;
421 }
422 pdata = hs->pdata;
423 if (HdfWorkQueueInit(&hs->workQueue, HDF_HEADSET_WORK_QUEUE_NAME) != HDF_SUCCESS) {
424 AUDIO_DEVICE_LOG_ERR("Init work queue failed");
425 return HDF_FAILURE;
426 }
427 HdfDelayedWorkInit(&hs->hDelayedWork[HOOK], HookOnceWork, hs);
428 if (pdata->chan != NULL) { // this is always true.
429 HdfDelayedWorkInit(&hs->hHookWork, HookWorkCallback, hs);
430 }
431
432 return HDF_SUCCESS;
433 }
434
CreateAndRegisterInputDevice(struct platform_device * pdev,struct HeadsetPriv * hs)435 static int32_t CreateAndRegisterInputDevice(struct platform_device *pdev, struct HeadsetPriv *hs)
436 {
437 int32_t ret;
438
439 AUDIO_DEVICE_LOG_INFO("enter.");
440 if ((hs == NULL) || (pdev == NULL)) {
441 AUDIO_DEVICE_LOG_ERR("hs or pdev is NULL.");
442 return -EINVAL;
443 }
444
445 hs->inDev = devm_input_allocate_device(&pdev->dev);
446 if (hs->inDev == NULL) {
447 AUDIO_DEVICE_LOG_ERR("failed to allocate input device.");
448 ret = -ENOMEM;
449 return ret;
450 }
451
452 hs->inDev->name = pdev->name;
453 hs->inDev->open = AnalogHskeyOpen;
454 hs->inDev->close = AnalogHskeyClose;
455 hs->inDev->dev.parent = &pdev->dev;
456
457 hs->inDev->id.vendor = INPUT_DEVID_VENDOR;
458 hs->inDev->id.product = INPUT_DEVID_PRODUCT;
459 hs->inDev->id.version = INPUT_DEVID_VERSION;
460 // register the input device
461 ret = input_register_device(hs->inDev);
462 if (ret) {
463 AUDIO_DEVICE_LOG_ERR("failed to register input device.");
464 return ret;
465 }
466 input_set_capability(hs->inDev, EV_KEY, HOOK_KEY_CODE);
467 AUDIO_DEVICE_LOG_INFO("%s: done.");
468
469 return ret;
470 }
471
SetHeadsetIrqEnable(struct device * dev,struct HeadsetPriv * hs)472 static int32_t SetHeadsetIrqEnable(struct device *dev, struct HeadsetPriv *hs)
473 {
474 int32_t ret;
475 struct HeadsetPdata *pdata = NULL;
476 uint32_t irqType;
477 uint32_t irq;
478
479 if ((hs == NULL) || (hs->pdata == NULL) || (dev == NULL)) {
480 AUDIO_DEVICE_LOG_ERR("hs, pdata or dev is NULL.");
481 return HDF_ERR_INVALID_PARAM;
482 }
483
484 pdata = hs->pdata;
485 if (pdata->hsGpio) {
486 irqType = GPIO_IRQ_TRIGGER_RISING | GPIO_IRQ_TRIGGER_FALLING | GPIO_IRQ_USING_THREAD;
487 ret = GpioSetIrq(pdata->hsGpio, irqType, HeadsetInterrupt, NULL);
488 if (ret != HDF_SUCCESS) {
489 AUDIO_DEVICE_LOG_ERR("failed headset adc probe ret=%d.", ret);
490 return ret;
491 }
492
493 ret = GpioEnableIrq(pdata->hsGpio);
494 if (ret != HDF_SUCCESS) {
495 AUDIO_DEVICE_LOG_ERR("enable irq fail! ret:%d\n", ret);
496 (void)GpioUnsetIrq(pdata->hsGpio, NULL);
497 return ret;
498 }
499
500 if (pdata->hsWakeup) {
501 irq = gpio_to_irq(pdata->hsGpio);
502 enable_irq_wake(irq);
503 }
504 } else {
505 AUDIO_DEVICE_LOG_ERR("failed init headset,please full hook_io_init function in board.");
506 ret = -EEXIST;
507 return ret;
508 }
509
510 return 0;
511 }
512
AnalogHeadsetAdcInit(struct platform_device * pdev,struct HeadsetPdata * pdata)513 int32_t AnalogHeadsetAdcInit(struct platform_device *pdev, struct HeadsetPdata *pdata)
514 {
515 int32_t ret;
516 struct HeadsetPriv *hs;
517
518 AUDIO_DEVICE_LOG_INFO("%s: enter.");
519 hs = (struct HeadsetPriv *)OsalMemCalloc(sizeof(*hs));
520 if (hs == NULL) {
521 AUDIO_DEVICE_LOG_ERR("failed to allocate driver data.");
522 return HDF_ERR_MALLOC_FAIL;
523 }
524 g_hsInfo = hs;
525 InitHeadsetPriv(hs, pdata);
526 hs->edev = devm_extcon_dev_allocate(&pdev->dev, g_hsCable);
527 if (IS_ERR(hs->edev)) {
528 AUDIO_DEVICE_LOG_ERR("failed to allocate extcon device.");
529 return-ENOMEM;
530 }
531 ret = devm_extcon_dev_register(&pdev->dev, hs->edev);
532 if (ret < 0) {
533 AUDIO_DEVICE_LOG_ERR("extcon_dev_register() failed: %d.", ret);
534 return ret;
535 }
536 ret = InitWorkData(hs);
537 if (ret != HDF_SUCCESS) {
538 AUDIO_DEVICE_LOG_ERR("[InitWorkData] failed");
539 return ret;
540 }
541 // Create and register the input driver
542 ret = CreateAndRegisterInputDevice(pdev, hs);
543 if (ret != 0) {
544 AUDIO_DEVICE_LOG_ERR("[CreateAndRegisterInputDevice] failed");
545 return ret;
546 }
547 ret = CreateAndRegisterHdfInputDevice((void *)hs, pdata->device);
548 if (ret != 0) {
549 AUDIO_DEVICE_LOG_DEBUG("[CreateAndRegisterHdfInputDevice] failed");
550 }
551 ret = SetHeadsetIrqEnable(&pdev->dev, hs);
552 if (ret != 0) {
553 AUDIO_DEVICE_LOG_ERR("[SetHeadsetIrqEnable] failed");
554 return ret;
555 }
556 AUDIO_DEVICE_LOG_INFO("%s: success.");
557 return ret;
558 }
559
AnalogHeadsetAdcSuspend(struct platform_device * pdev,pm_message_t state)560 int AnalogHeadsetAdcSuspend(struct platform_device *pdev, pm_message_t state)
561 {
562 AUDIO_DEVICE_LOG_DEBUG("%d enter.");
563 (void)pdev;
564 (void)state;
565
566 return 0;
567 }
568
AnalogHeadsetAdcResume(struct platform_device * pdev)569 int AnalogHeadsetAdcResume(struct platform_device *pdev)
570 {
571 AUDIO_DEVICE_LOG_DEBUG("%d enter.");
572 (void)pdev;
573
574 return 0;
575 }
576
AnalogHeadsetAdcRelease(struct HeadsetPdata * pdata)577 void AnalogHeadsetAdcRelease(struct HeadsetPdata *pdata)
578 {
579 struct HeadsetPriv *hs = g_hsInfo;
580 if (hs == NULL) {
581 AUDIO_DEVICE_LOG_ERR("hs is NULL.");
582 return;
583 }
584 (void)pdata;
585 HdfWorkDestroy(&hs->hDelayedWork[HOOK]);
586 HdfCancelDelayedWorkSync(&hs->hHookWork);
587 HdfWorkDestroy(&hs->hHookWork);
588 HdfWorkQueueDestroy(&hs->workQueue);
589 DestroyHdfInputDevice();
590 OsalMemFree(hs);
591 g_hsInfo = NULL;
592 }