• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include "drv_hdmi_event.h"
20 
21 #define HDMI_EVENT_NOT_MACH_SLEEP 500
22 #define HDMI_EVENT_READ_SLEEP     100
23 #define HDMI_EVENT_DEINIT_SLEEP   200
24 
25 static hdmi_event_info g_event_info[HDMI_DEVICE_ID_BUTT];
26 
event_info_ptr_get(hdmi_device_id hdmi)27 static hdmi_event_info *event_info_ptr_get(hdmi_device_id hdmi)
28 {
29     if (hdmi < HDMI_DEVICE_ID_BUTT) {
30         return &g_event_info[hdmi];
31     }
32     return HI_NULL;
33 }
34 
event_type_counter(hdmi_event_pool * pool,hdmi_event event,hi_bool write)35 static hi_s32 event_type_counter(hdmi_event_pool *pool, hdmi_event event, hi_bool write)
36 {
37     switch (event) {
38         case HDMI_EVENT_HOTPLUG:
39             write ? pool->run_cnt.hpd_wr_cnt++ : pool->run_cnt.hpd_rd_cnt++;
40             break;
41         case HDMI_EVENT_HOTUNPLUG:
42             write ? pool->run_cnt.unhpd_wr_cnt++ : pool->run_cnt.unhpd_rd_cnt++;
43             break;
44         case HDMI_EVENT_EDID_FAIL:
45             write ? pool->run_cnt.edid_fail_wr_cnt++ : pool->run_cnt.edid_fail_rd_cnt++;
46             break;
47         case HDMI_EVENT_RSEN_CONNECT:
48             write ? pool->run_cnt.rsen_con_wr_cnt++ : pool->run_cnt.rsen_con_rd_cnt++;
49             break;
50         case HDMI_EVENT_RSEN_DISCONNECT:
51             write ? pool->run_cnt.rsen_dis_wr_cnt++ : pool->run_cnt.rsen_dis_rd_cnt++;
52             break;
53         default:
54             break;
55     }
56 
57     return HI_SUCCESS;
58 }
59 
event_mach_id(hdmi_event_info * evt_info,hi_u32 pool_id)60 static hi_u32 event_mach_id(hdmi_event_info *evt_info, hi_u32 pool_id)
61 {
62     hi_u32 i;
63     hdmi_event_pool *tmp_pool = HI_NULL;
64 
65     hdmi_mutex_lock(evt_info->event_mutex);
66     if (evt_info->total == 0) {
67         hdmi_warn("event pool list is empty\n");
68         hdmi_mutex_unlock(evt_info->event_mutex);
69         return HI_SUCCESS;
70     }
71 
72     /* find a match proc */
73     for (i = 0, tmp_pool = &evt_info->pool[0]; i < HDMI_EVENT_POOL_CNT; i++, tmp_pool++) {
74         if (tmp_pool->ctrl.pool_id == pool_id) {
75             break;
76         }
77     }
78     hdmi_mutex_unlock(evt_info->event_mutex);
79 
80     return i;
81 }
82 
drv_hdmi_event_init(hdmi_device_id hdmi_id)83 hi_s32 drv_hdmi_event_init(hdmi_device_id hdmi_id)
84 {
85     hdmi_event_info *evt_info = HI_NULL;
86 
87     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
88     evt_info = event_info_ptr_get(hdmi_id);
89     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
90 
91     if (evt_info->init != HI_TRUE) {
92         (hi_void)memset_s(evt_info, sizeof(hdmi_event_info), 0, sizeof(hdmi_event_info));
93         /* init */
94         osal_wait_init(&evt_info->wr_queue);
95         osal_sema_init(&evt_info->event_mutex, 1);
96         evt_info->total = 0;
97         evt_info->init = HI_TRUE;
98         evt_info->wakeup_all = HI_FALSE;
99     }
100 
101     return HI_SUCCESS;
102 }
103 
drv_hdmi_event_deinit(hdmi_device_id hdmi_id)104 hi_s32 drv_hdmi_event_deinit(hdmi_device_id hdmi_id)
105 {
106     hdmi_event_info *evt_info = HI_NULL;
107 
108     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
109     evt_info = event_info_ptr_get(hdmi_id);
110     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
111     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
112 
113     /* wake up all process which is waiting for event */
114     hdmi_mutex_lock(evt_info->event_mutex);
115     evt_info->wakeup_all = HI_TRUE;
116     hdmi_mutex_unlock(evt_info->event_mutex);
117 
118     osal_wakeup(&evt_info->wr_queue);
119     osal_msleep(HDMI_EVENT_DEINIT_SLEEP);
120 
121     hdmi_mutex_lock(evt_info->event_mutex);
122     (hi_void)memset_s(evt_info->pool, sizeof(evt_info->pool), 0, sizeof(evt_info->pool));
123     evt_info->total = 0;
124     evt_info->init = HI_FALSE;
125     hdmi_mutex_unlock(evt_info->event_mutex);
126     osal_sema_destroy(&evt_info->event_mutex);
127     osal_wait_destroy(&evt_info->wr_queue);
128 
129     return HI_SUCCESS;
130 }
131 
drv_hdmi_event_pool_malloc(hdmi_device_id hdmi_id,hi_u32 * pool_id)132 hi_s32 drv_hdmi_event_pool_malloc(hdmi_device_id hdmi_id, hi_u32 *pool_id)
133 {
134     hi_u32 i;
135     hi_u32 cur_gid;
136     hdmi_event_pool *tmp_pool = HI_NULL;
137     hdmi_event_info *evt_info = HI_NULL;
138 
139     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
140     evt_info = event_info_ptr_get(hdmi_id);
141     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
142     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
143 
144     cur_gid = (hi_u32)hdmi_get_current_id();
145     /* malloc a new pool element & init */
146     hdmi_mutex_lock(evt_info->event_mutex);
147 
148     /* check ID exist */
149     for (i = 0, tmp_pool = &evt_info->pool[0]; i < HDMI_EVENT_POOL_CNT; i++, tmp_pool++) {
150         if (tmp_pool->ctrl.pool_id == cur_gid) {
151             hdmi_warn("proc ID=%u  exist!\n", cur_gid);
152             hdmi_mutex_unlock(evt_info->event_mutex);
153             return HDMI_EVENT_ID_EXIST;
154         }
155     }
156 
157     for (i = 0, tmp_pool = &evt_info->pool[0]; i < HDMI_EVENT_POOL_CNT; i++, tmp_pool++) {
158         if (!tmp_pool->ctrl.pool_id) {
159             break;
160         }
161     }
162 
163     if (i >= HDMI_EVENT_POOL_CNT) {
164         hdmi_warn("proc ID=%u no event sercer,pool max cnt = %u!\n", cur_gid, i);
165         hdmi_mutex_unlock(evt_info->event_mutex);
166         return HI_FAILURE;
167     }
168 
169     (hi_void)memset_s(&tmp_pool->ctrl, sizeof(tmp_pool->ctrl), 0, sizeof(hdmi_event_run_ctrl));
170     (hi_void)memset_s(&tmp_pool->run_cnt, sizeof(tmp_pool->run_cnt), 0, sizeof(hdmi_event_run_cnt));
171     tmp_pool->ctrl.pool_id = cur_gid;
172     if (pool_id != HI_NULL) {
173         *pool_id = tmp_pool->ctrl.pool_id;
174     }
175     tmp_pool->ctrl.wakeup_flag = HI_FALSE;
176     for (i = 0; i < HDMI_EVENT_POOL_SIZE; i++) {
177         tmp_pool->ctrl.event_pool[i] = HDMI_EVENT_BUTT;
178     }
179     evt_info->total++;
180     hdmi_mutex_unlock(evt_info->event_mutex);
181 
182     return HI_SUCCESS;
183 }
184 
drv_hdmi_event_pool_free(hdmi_device_id hdmi_id,hi_u32 pool_id)185 hi_s32 drv_hdmi_event_pool_free(hdmi_device_id hdmi_id, hi_u32 pool_id)
186 {
187     hi_u32 i;
188     hdmi_event_pool *tmp_pool = HI_NULL;
189     hdmi_event_info *evt_info = HI_NULL;
190 
191     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
192     evt_info = event_info_ptr_get(hdmi_id);
193     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
194     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
195 
196     hdmi_mutex_lock(evt_info->event_mutex);
197     /* find a match ID and free it */
198     for (i = 0, tmp_pool = &evt_info->pool[0]; i < HDMI_EVENT_POOL_CNT; i++, tmp_pool++) {
199         if (tmp_pool->ctrl.pool_id == pool_id) {
200             evt_info->total--;
201             tmp_pool->ctrl.wakeup_flag = HI_TRUE;
202             osal_wakeup(&evt_info->wr_queue);
203             tmp_pool->ctrl.pool_id = 0;
204             hdmi_info("delete proc(%u) node\n", pool_id);
205             break;
206         }
207     }
208     hdmi_mutex_unlock(evt_info->event_mutex);
209 
210     /* can't find a match ID */
211     if (i >= HDMI_EVENT_POOL_CNT) {
212         hdmi_err("proc id(%u) free fail\n", pool_id);
213         return HI_FAILURE;
214     }
215 
216     return HI_SUCCESS;
217 }
218 
drv_hdmi_event_pool_write(hdmi_device_id hdmi_id,hdmi_event event)219 hi_s32 drv_hdmi_event_pool_write(hdmi_device_id hdmi_id, hdmi_event event)
220 {
221     hi_u32 i;
222     hdmi_event_pool *tmp_pool = HI_NULL;
223     hdmi_event_info *evt_info = HI_NULL;
224 
225     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
226     evt_info = event_info_ptr_get(hdmi_id);
227     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
228     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
229 
230     if ((event < HDMI_EVENT_HOTPLUG) || (event > HDMI_EVENT_HDCP_USERSETTING)) {
231         hdmi_warn("the event(0x%x) invalid ,we don't write!\n", event);
232         return HI_FAILURE;
233     }
234 
235     hdmi_mutex_lock(evt_info->event_mutex);
236     if (evt_info->total == 0) {
237         hdmi_warn("event pool is empty\n");
238         hdmi_mutex_unlock(evt_info->event_mutex);
239         return HI_SUCCESS;
240     }
241 
242     /* write event into all event pool in the list */
243     for (i = 0, tmp_pool = &evt_info->pool[0]; i < HDMI_EVENT_POOL_CNT; i++, tmp_pool++) {
244         if (tmp_pool->ctrl.pool_id) {
245             /* the event pool is overflow */
246             if ((tmp_pool->ctrl.event_pool[tmp_pool->ctrl.write_ptr] >= HDMI_EVENT_HOTPLUG) &&
247                 (tmp_pool->ctrl.event_pool[tmp_pool->ctrl.write_ptr] <= HDMI_EVENT_HDCP_USERSETTING)) {
248                 tmp_pool->run_cnt.err_wd_cnt++;
249                 tmp_pool->ctrl.readable_cnt--;
250                 tmp_pool->ctrl.read_ptr = (tmp_pool->ctrl.write_ptr + 1) % HDMI_EVENT_POOL_SIZE;
251                 hdmi_warn("the event pool of proc(%u) is overflow\n", tmp_pool->ctrl.pool_id);
252             }
253             tmp_pool->ctrl.event_pool[tmp_pool->ctrl.write_ptr++] = event;
254             tmp_pool->ctrl.write_ptr %= HDMI_EVENT_POOL_SIZE;
255             event_type_counter(tmp_pool, event, HI_TRUE);
256             tmp_pool->ctrl.readable_cnt++;
257             osal_wakeup(&evt_info->wr_queue);
258             hdmi_info("the event(0x%x) is writed into event pool of proc(%u) success\n",
259                       event, tmp_pool->ctrl.pool_id);
260         }
261     }
262     hdmi_mutex_unlock(evt_info->event_mutex);
263 
264     return HI_SUCCESS;
265 }
266 
drv_hdmi_event_callback(const hi_void * param)267 hi_s32 drv_hdmi_event_callback(const hi_void *param)
268 {
269     const hdmi_event_wait_callback *tmp = HI_NULL;
270     hi_s32 result;
271 
272     tmp = (const hdmi_event_wait_callback *)param;
273     result =
274         (tmp->evt_info->wakeup_all || tmp->tmp_pool->ctrl.wakeup_flag || (tmp->tmp_pool->ctrl.readable_cnt > 0));
275 
276     return result;
277 }
278 
drv_hdmi_event_pool_read(hdmi_device_id hdmi_id,hi_u32 pool_id,hdmi_event * event)279 hi_s32 drv_hdmi_event_pool_read(hdmi_device_id hdmi_id, hi_u32 pool_id, hdmi_event *event)
280 {
281     hi_u32 i;
282     hi_s32 ret;
283     hdmi_event_pool         *tmp_pool = HI_NULL;
284     hdmi_event_info         *evt_info = HI_NULL;
285     hdmi_event_wait_callback callback = {0};
286 
287     evt_info = event_info_ptr_get(hdmi_id);
288     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
289     hdmi_if_null_warn_return(event, HI_FAILURE);
290     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
291 
292     *event = HDMI_EVENT_BUTT;
293     i = event_mach_id(evt_info, pool_id);
294     if (i >= HDMI_EVENT_POOL_CNT) {
295         hdmi_err("the proc(%u) is not find\n", pool_id);
296         osal_msleep(HDMI_EVENT_NOT_MACH_SLEEP);
297         return HI_FAILURE;
298     }
299     tmp_pool = &evt_info->pool[i];
300     callback.evt_info = evt_info;
301     callback.tmp_pool = tmp_pool;
302     ret = osal_wait_event_timeout_interruptible(&(evt_info->wr_queue), drv_hdmi_event_callback,
303                                                 (hi_void *)&callback, HDMI_EVENT_READ_SLEEP);
304     if (ret <= 0) {
305         return HI_SUCCESS;
306     }
307 
308     hdmi_mutex_lock(evt_info->event_mutex);
309     if (tmp_pool->ctrl.readable_cnt == 0) {
310         hdmi_mutex_unlock(evt_info->event_mutex);
311         return HI_SUCCESS;
312     } else {
313         *event = tmp_pool->ctrl.event_pool[tmp_pool->ctrl.read_ptr];
314         tmp_pool->ctrl.event_pool[tmp_pool->ctrl.read_ptr] = HDMI_EVENT_BUTT;
315         tmp_pool->ctrl.read_ptr = (tmp_pool->ctrl.read_ptr + 1) % HDMI_EVENT_POOL_SIZE;
316         tmp_pool->ctrl.wakeup_flag = HI_FALSE;
317         if ((*event >= HDMI_EVENT_HOTPLUG) && (*event <= HDMI_EVENT_HDCP_USERSETTING)) {
318             tmp_pool->ctrl.readable_cnt--;
319             event_type_counter(tmp_pool, *event, HI_FALSE);
320             ret = HI_SUCCESS;
321             hdmi_info("the proc(%u) poll event(0x%x) success\n", tmp_pool->ctrl.pool_id, *event);
322         } else {
323             tmp_pool->run_cnt.err_rd_cnt++;
324             ret = HI_FAILURE;
325         }
326     }
327     hdmi_mutex_unlock(evt_info->event_mutex);
328 
329     return ret;
330 }
331 
drv_hdmi_event_pool_status_get(hdmi_device_id hdmi_id,hi_u32 pool_num,hdmi_event_run_ctrl * ctrl,hdmi_event_run_cnt * cnt)332 hi_s32 drv_hdmi_event_pool_status_get(hdmi_device_id hdmi_id, hi_u32 pool_num,
333                                       hdmi_event_run_ctrl *ctrl, hdmi_event_run_cnt *cnt)
334 {
335     errno_t ret;
336     hi_u32 i;
337     hi_u32 j = 0;
338     hdmi_event_pool *tmp_pool = HI_NULL;
339     hdmi_event_info *evt_info = HI_NULL;
340 
341     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
342     evt_info = event_info_ptr_get(hdmi_id);
343     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
344     hdmi_if_null_warn_return(ctrl, HI_FAILURE);
345     hdmi_if_null_warn_return(cnt, HI_FAILURE);
346     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
347 
348     (hi_void)memset_s(ctrl, sizeof(hdmi_event_run_ctrl), 0, sizeof(hdmi_event_run_ctrl));
349     (hi_void)memset_s(cnt, sizeof(hdmi_event_run_cnt), 0, sizeof(hdmi_event_run_cnt));
350 
351     hdmi_mutex_lock(evt_info->event_mutex);
352     if ((pool_num > evt_info->total) || (pool_num == 0)) {
353         hdmi_warn("the input pool num(%u) is wrong,event pool range is [1~%u]\n", pool_num, evt_info->total);
354         hdmi_mutex_unlock(evt_info->event_mutex);
355         return HI_FAILURE;
356     }
357 
358     if (evt_info->total == 0) {
359         hdmi_warn("event pool is empty\n");
360         hdmi_mutex_unlock(evt_info->event_mutex);
361         return HI_SUCCESS;
362     }
363 
364     /* find a match ID and copy status */
365     for (i = 0, tmp_pool = &evt_info->pool[0]; i < HDMI_EVENT_POOL_CNT; i++, tmp_pool++) {
366         if (tmp_pool->ctrl.pool_id) {
367             j++;
368             if (j == pool_num) {
369                 ret = memcpy_s(ctrl, sizeof(*ctrl), &tmp_pool->ctrl, sizeof(hdmi_event_run_ctrl));
370                 hdmi_unlock_unequal_eok_return(ret, evt_info->event_mutex, HI_ERR_HDMI_INVALID_PARA);
371                 ret = memcpy_s(cnt, sizeof(*cnt), &tmp_pool->run_cnt, sizeof(hdmi_event_run_cnt));
372                 hdmi_unlock_unequal_eok_return(ret, evt_info->event_mutex, HI_ERR_HDMI_INVALID_PARA);
373                 break;
374             }
375         }
376     }
377     hdmi_mutex_unlock(evt_info->event_mutex);
378 
379     return HI_SUCCESS;
380 }
381 
drv_hdmi_event_pool_total_get(hdmi_device_id hdmi_id,hi_u32 * total)382 hi_s32 drv_hdmi_event_pool_total_get(hdmi_device_id hdmi_id, hi_u32 *total)
383 {
384     hdmi_event_info *evt_info = HI_NULL;
385 
386     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
387     evt_info = event_info_ptr_get(hdmi_id);
388     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
389     hdmi_if_null_warn_return(total, HI_FAILURE);
390     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
391 
392     hdmi_mutex_lock(evt_info->event_mutex);
393     *total = evt_info->total;
394     hdmi_mutex_unlock(evt_info->event_mutex);
395 
396     return HI_SUCCESS;
397 }
398 
drv_hdmi_event_pool_id_get(hdmi_device_id hdmi_id,hi_u32 * thread_id)399 hi_s32 drv_hdmi_event_pool_id_get(hdmi_device_id hdmi_id, hi_u32 *thread_id)
400 {
401     hdmi_event_info *evt_info = HI_NULL;
402 
403     hdmi_check_max_return(hdmi_id, HDMI_DEVICE_ID_BUTT - 1, HI_FAILURE);
404     evt_info = event_info_ptr_get(hdmi_id);
405     hdmi_if_null_warn_return(evt_info, HI_FAILURE);
406     hdmi_if_null_warn_return(thread_id, HI_FAILURE);
407     hdmi_if_false_warn_return(evt_info->init, HI_FAILURE);
408 
409     hdmi_mutex_lock(evt_info->event_mutex);
410     *thread_id = evt_info->pool[0].ctrl.pool_id;
411     hdmi_mutex_unlock(evt_info->event_mutex);
412 
413     return HI_SUCCESS;
414 }
415 
416