1 /*
2 * Copyright (c) 2020-2021 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 "power_state_token.h"
10 #include "hdf_device_desc.h"
11 #include "hdf_slist.h"
12 #include "osal_mem.h"
13 #include "hdf_power_state.h"
14
PowerStateTokenOnFirstAcquire(struct HdfSRef * sref)15 static void PowerStateTokenOnFirstAcquire(struct HdfSRef *sref)
16 {
17 struct PowerStateToken *stateToken = NULL;
18 if (sref == NULL) {
19 return;
20 }
21 stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF(
22 struct HdfSRef, sref, struct PowerStateToken, wakeRef);
23
24 if (stateToken->psmState == PSM_STATE_ACTIVE) {
25 return;
26 }
27
28 if (stateToken->psmState == PSM_STATE_INACTIVE || stateToken->psmState == PSM_STATE_IDLE) {
29 const struct IPowerEventListener *listener = stateToken->listener;
30 if ((listener != NULL) && (listener->Resume != NULL)) {
31 listener->Resume(stateToken->deviceObject);
32 }
33 }
34 stateToken->psmState = PSM_STATE_ACTIVE;
35 }
36
PowerStateTokenOnLastRelease(struct HdfSRef * sref)37 static void PowerStateTokenOnLastRelease(struct HdfSRef *sref)
38 {
39 struct PowerStateToken *stateToken = NULL;
40 const struct IPowerEventListener *listener = NULL;
41 if (sref == NULL) {
42 return;
43 }
44 stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF(
45 struct HdfSRef, sref, struct PowerStateToken, wakeRef);
46
47 if (stateToken->psmState != PSM_STATE_ACTIVE && stateToken->psmState != PSM_STATE_IDLE) {
48 return;
49 }
50
51 listener = stateToken->listener;
52 if ((listener != NULL) && (listener->Suspend != NULL)) {
53 listener->Suspend(stateToken->deviceObject);
54 }
55 stateToken->psmState = PSM_STATE_INACTIVE;
56 }
57
PowerStateChange(struct PowerStateToken * stateToken,uint32_t pEvent)58 int PowerStateChange(struct PowerStateToken *stateToken, uint32_t pEvent)
59 {
60 if (stateToken == NULL || stateToken->listener == NULL || stateToken->mode != HDF_POWER_SYS_CTRL) {
61 return HDF_SUCCESS;
62 }
63
64 switch (pEvent) {
65 case POWER_STATE_SUSPEND:
66 if (stateToken->listener->Suspend != NULL) {
67 return stateToken->listener->Suspend(stateToken->deviceObject);
68 }
69 break;
70 case POWER_STATE_RESUME:
71 if (stateToken->listener->Resume != NULL) {
72 return stateToken->listener->Resume(stateToken->deviceObject);
73 }
74 break;
75 case POWER_STATE_DOZE_SUSPEND:
76 if (stateToken->listener->DozeSuspend != NULL) {
77 return stateToken->listener->DozeSuspend(stateToken->deviceObject);
78 }
79 break;
80 case POWER_STATE_DOZE_RESUME:
81 if (stateToken->listener->DozeResume != NULL) {
82 return stateToken->listener->DozeResume(stateToken->deviceObject);
83 }
84 break;
85 default:
86 break;
87 }
88
89 return HDF_SUCCESS;
90 }
91
PowerStateTokenAcquireWakeLock(struct IPowerStateToken * token)92 static void PowerStateTokenAcquireWakeLock(struct IPowerStateToken *token)
93 {
94 struct HdfSRef *sref = NULL;
95 struct PowerStateToken *stateToken = (struct PowerStateToken *)token;
96 if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) {
97 return;
98 }
99 sref = (struct HdfSRef *)&stateToken->wakeRef;
100 if ((sref != NULL) && (sref->Acquire != NULL)) {
101 sref->Acquire(sref);
102 }
103 }
104
PowerStateTokenReleaseWakeLock(struct IPowerStateToken * token)105 static void PowerStateTokenReleaseWakeLock(struct IPowerStateToken *token)
106 {
107 struct HdfSRef *sref = NULL;
108 struct PowerStateToken *stateToken = (struct PowerStateToken *)token;
109 if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) {
110 return;
111 }
112 sref = (struct HdfSRef *)&stateToken->wakeRef;
113 if ((sref == NULL) || (sref->Release == NULL)) {
114 return;
115 }
116
117 /* Not allowed to decrease the ref count to negative */
118 if (HdfSRefCount(sref) == 0) {
119 PowerStateTokenOnLastRelease(sref);
120 } else {
121 sref->Release(sref);
122 }
123 }
124
PowerStateTokenConstruct(struct PowerStateToken * powerStateToken,struct HdfDeviceObject * deviceObject,const struct IPowerEventListener * listener)125 static int32_t PowerStateTokenConstruct(struct PowerStateToken *powerStateToken,
126 struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener)
127 {
128 struct IPowerStateToken *tokenIf = &powerStateToken->super;
129 struct IHdfSRefListener *srefListener = (struct IHdfSRefListener *)OsalMemCalloc(sizeof(struct IHdfSRefListener));
130 if (srefListener == NULL) {
131 return HDF_ERR_MALLOC_FAIL;
132 }
133
134 tokenIf->AcquireWakeLock = PowerStateTokenAcquireWakeLock;
135 tokenIf->ReleaseWakeLock = PowerStateTokenReleaseWakeLock;
136
137 srefListener->OnFirstAcquire = PowerStateTokenOnFirstAcquire;
138 srefListener->OnLastRelease = PowerStateTokenOnLastRelease;
139
140 powerStateToken->psmState = PSM_STATE_IDLE;
141 powerStateToken->listener = listener;
142 powerStateToken->deviceObject = deviceObject;
143 HdfSRefConstruct(&powerStateToken->wakeRef, srefListener);
144
145 return HDF_SUCCESS;
146 }
147
PowerStateTokenNewInstance(struct HdfDeviceObject * deviceObject,const struct IPowerEventListener * listener)148 struct PowerStateToken *PowerStateTokenNewInstance(
149 struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener)
150 {
151 struct PowerStateToken *stateToken =
152 (struct PowerStateToken *)OsalMemCalloc(sizeof(struct PowerStateToken));
153 if (stateToken == NULL) {
154 return NULL;
155 }
156
157 if (PowerStateTokenConstruct(stateToken, deviceObject, listener) != HDF_SUCCESS) {
158 OsalMemFree(stateToken);
159 return NULL;
160 }
161
162 return stateToken;
163 }
164
PowerStateTokenFreeInstance(struct PowerStateToken * stateToken)165 void PowerStateTokenFreeInstance(struct PowerStateToken *stateToken)
166 {
167 if (stateToken != NULL) {
168 if (stateToken->wakeRef.listener != NULL) {
169 OsalMemFree(stateToken->wakeRef.listener);
170 stateToken->wakeRef.listener = NULL;
171 }
172 OsalMemFree(stateToken);
173 }
174 }
175