3874e8b3dc6d289a0706fe006c7b4071e88fe843
[platform/core/system/deviced.git] / src / display / display.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #include <fnmatch.h>
19 #include <signal.h>
20
21 #include <libsyscommon/list.h>
22 #include <libsyscommon/resource-manager.h>
23 #include <system/syscommon-plugin-deviced-power-interface.h>
24 #include <system/syscommon-plugin-deviced-common-interface.h>
25 #include <shared/devices.h>
26
27 #include "core/udev.h"
28 #include "shared/device-notifier.h"
29 #include "shared/log.h"
30 #include "power/power.h"
31 #include "power/power-suspend.h"
32 #include "device-interface.h"
33 #include "display.h"
34 #include "display-lock.h"
35 #include "display-plugin.h"
36 #include "display-config.h"
37 #include "display-misc.h"
38 #include "display-ops.h"
39 #include "display-signal.h"
40 #include "display-state-transition.h"
41 #include "lock-detector.h"
42
43 #define DELAYED_INIT_WATING_TIME        60000   /* 1 minute */
44
45 static const struct device_ops *display_plugin_device_ops;
46 static unsigned int pm_status_flag;
47 static enum display_init_direction_e g_display_init_direction;
48 static bool g_display_hal_backend_available = false;
49 static GList *display_dependent_device_ops;
50 static enum device_ops_status display_ops_status = DEVICE_OPS_STATUS_UNINIT;
51
52 extern void init_save_userlock(void);
53
54 inline unsigned int get_pm_status_flag(void)
55 {
56         return pm_status_flag;
57 }
58
59 inline void set_pm_status_flag(unsigned int status_flag)
60 {
61         pm_status_flag |= status_flag;
62 }
63
64 inline void clear_pm_status_flag(unsigned int status_flag)
65 {
66         pm_status_flag &= ~status_flag;
67 }
68
69 inline enum display_init_direction_e get_display_init_direction(void)
70 {
71         return g_display_init_direction;
72 }
73
74 inline void set_display_init_direction(enum display_init_direction_e display_init_direction)
75 {
76         g_display_init_direction = display_init_direction;
77 }
78
79 void lcd_direct_control(enum dpms_state dpms_state, int flags)
80 {
81         const struct device_ops *ops = NULL;
82         GList *l = NULL;
83
84         switch (dpms_state) {
85         case DPMS_ON:
86                 SYS_G_LIST_FOREACH(display_dependent_device_ops, l, ops)
87                         ops->start(flags);
88                 break;
89         case DPMS_OFF:
90                 SYS_G_LIST_FOREACH(display_dependent_device_ops, l, ops)
91                         ops->stop(flags);
92                 break;
93         default:
94                 _E("state is wrong value %d", dpms_state);
95                 break;
96         }
97 }
98
99 bool display_is_hal_backend_available(void)
100 {
101         return g_display_hal_backend_available;
102 }
103
104 void display_start_dependent_device(unsigned long flags)
105 {
106         const struct device_ops *ops = NULL;
107         GList *l;
108
109         SYS_G_LIST_FOREACH(display_dependent_device_ops, l, ops)
110                 ops->start(flags);
111 }
112
113 void display_stop_dependent_device(unsigned long flags)
114 {
115         const struct device_ops *ops = NULL;
116         GList *l;
117
118         SYS_G_LIST_FOREACH(display_dependent_device_ops, l, ops)
119                 ops->stop(flags);
120 }
121
122 void display_register_dependent_device(const struct device_ops *ops)
123 {
124         SYS_G_LIST_APPEND(display_dependent_device_ops, ops);
125 }
126
127 void display_unregister_dependent_device(void)
128 {
129         GList *l = NULL;
130         GList *l_next = NULL;;
131         const struct device_ops *ops = NULL;
132
133         SYS_G_LIST_FOREACH_SAFE(display_dependent_device_ops, l, l_next, ops)
134                 SYS_G_LIST_REMOVE_LIST(display_dependent_device_ops, l);
135 }
136
137 /* FIXME: display_dimstay_check function should be changed to plugin api call.
138  *        Only the wearable profile had the first condition only, checking DIM_FLAG. */
139 bool display_dimstay_check(void)
140 {
141         if (pm_status_flag & DIM_FLAG)
142                 return true;
143
144         if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG))
145                 return true;
146
147         return false;
148 }
149
150 int display_initialize_display_state_timeout_from_setting(void)
151 {
152         int i;
153         int val = 0;
154         const char* state_name = NULL;
155         enum deviced_display_state state = DEVICED_DISPLAY_STATE_START;
156
157         for (i = 0; i < DEVICED_DISPLAY_STATE_END; i++) {
158                 display_plugin_state_get_state_by_state_index(i, &state);
159                 switch (state) {
160                 case DEVICED_DISPLAY_STATE_ON:
161                         get_run_timeout(&val);
162                         break;
163                 case DEVICED_DISPLAY_STATE_DIM:
164                         get_dim_timeout(&val);
165                         break;
166                 case DEVICED_DISPLAY_STATE_OFF:
167                         display_plugin_config_get_lcdoff_timeout(&val);
168                         break;
169                 default:
170                         /* This state doesn't need to set time out. */
171                         val = 0;
172                         break;
173                 }
174                 if (val > 0) {
175                         display_plugin_state_set_timeout(i, val);
176                 }
177
178                 display_plugin_state_get_name(i, &state_name);
179                 _I("State(%s) timeout(%d) ms", state_name, val);
180         }
181
182         return 0;
183 }
184
185 /** FIXME: display_ops_status getter/setter will be removed after plugin-core separation
186            This work should be proceeded in the display core
187 */
188 bool display_is_display_ops_started_status(void)
189 {
190         return (display_ops_status == DEVICE_OPS_STATUS_START);
191 }
192
193 void display_set_display_ops_status(enum device_ops_status dev_ops_status)
194 {
195         display_ops_status = dev_ops_status;
196 }
197
198 int display_get_display_ops_status(enum device_ops_status *dev_ops_status)
199 {
200         if (!dev_ops_status)
201                 return -EINVAL;
202
203         *dev_ops_status = display_ops_status;
204         return 0;
205 }
206
207 void display_set_power_save_mode_flag(int onoff)
208 {
209         int ret;
210         enum deviced_display_state current;
211
212         if (display_plugin_set_power_save_mode_flag(onoff) == 0)
213                 return;
214
215         if (onoff)
216                 set_pm_status_flag(PWRSV_FLAG);
217         else
218                 clear_pm_status_flag(PWRSV_FLAG);
219
220         ret = display_state_get_current(&current);
221         if (ret < 0)
222                 return;
223
224         if (current == DEVICED_DISPLAY_STATE_ON)
225                 display_backlight_update_by_default_brightness();
226 }
227
228 static int power_resume_from_echomem_callback(void *data)
229 {
230         int ret;
231         enum deviced_display_state current;
232
233         ret = display_state_get_current(&current);
234         if (ret < 0)
235                 return ret;
236
237         display_plugin_set_system_wakeup_flag(true);
238         if (check_wakeup_src() == EVENT_DEVICE)
239                 /* system waked up by devices */
240                 display_state_transition_do_state_transition(current, EVENT_DEVICE);
241         else
242                 /* system waked up by user input */
243                 display_state_transition_do_state_transition(current, EVENT_INPUT);
244
245         return 0;
246 }
247
248 static int poweroff_triggered_callback(void *udata)
249 {
250         int val = (int)(intptr_t) udata;
251
252         switch (val) {
253         case VCONFKEY_SYSMAN_POWER_OFF_NONE:
254                 clear_pm_status_flag(PWROFF_FLAG);
255                 break;
256         case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
257         case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
258                 set_pm_status_flag(PWROFF_FLAG);
259                 break;
260         }
261
262         return 0;
263 }
264
265 static gboolean delayed_dpms_init_done(gpointer data)
266 {
267         int timeout = 0;
268         bool timeout_enable = false;
269         int lcdoff_timeout = 0;
270         int ret;
271         enum deviced_display_state current;
272
273         if (!display_panel_init_dpms())
274                 return G_SOURCE_CONTINUE;
275
276         ret = display_state_get_current(&current);
277         if (ret < 0)
278                 return G_SOURCE_REMOVE;
279
280         switch (current) {
281         case DEVICED_DISPLAY_STATE_ON:
282         case DEVICED_DISPLAY_STATE_DIM:
283                 display_panel_lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
284                 display_plugin_config_get_timeout_enable(&timeout_enable);
285                 if (timeout_enable) {
286                         display_plugin_state_get_timeout(DEVICED_DISPLAY_STATE_ON, &timeout);
287                         /* check minimun lcd on time */
288                         if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
289                                 timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
290                         display_state_transition_reset_state_transition_timeout(timeout);
291                 }
292                 break;
293         case DEVICED_DISPLAY_STATE_OFF:
294                 display_panel_lcd_off_procedure(LCD_OFF_BY_EVENT);
295                 display_plugin_config_get_lcdoff_timeout(&lcdoff_timeout);
296                 display_state_transition_reset_state_transition_timeout(lcdoff_timeout);
297                 break;
298         default:
299                 break;
300         }
301
302         return G_SOURCE_REMOVE;
303 }
304
305 void display_add_timer_for_waiting_dpms_init(void)
306 {
307         guint id = g_timeout_add(500/* milliseconds */, delayed_dpms_init_done, NULL);
308         if (id == 0)
309                 _E("Failed to add display_panel_init_dpms timeout.");
310 }
311
312 void display_set_initial_brightness(void)
313 {
314         int ret = -1;
315         int brightness = 0;
316         int default_brightness = 0;
317
318         ret = get_setting_brightness(&brightness);
319         if (ret != 0 || (brightness < PM_MIN_BRIGHTNESS || brightness > PM_MAX_BRIGHTNESS)) {
320                 _I("Failed to read vconf value for brightness.");
321                 display_plugin_config_get_pm_default_brightness(&default_brightness);
322                 if (brightness < PM_MIN_BRIGHTNESS || brightness > PM_MAX_BRIGHTNESS) {
323                         ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, default_brightness);
324                         if (ret < 0)
325                                 _E("Failed to set vconf value for lcd brightness: %d", vconf_get_ext_errno());
326                 }
327                 brightness = default_brightness;
328         }
329         _I("Set brightness(%d) from setting app.", brightness);
330         display_backlight_set_default_brightness(brightness);
331         display_backlight_set_brightness(brightness);
332 }
333
334 /* FIXME: This function should be moved to battery module after battery plguin/module refactoring */
335 void display_set_initial_battery_flag(void)
336 {
337         int ret = -1;
338         int battery_state = 0;
339
340         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &battery_state);
341         if (ret < 0) {
342                 battery_state = VCONFKEY_SYSMAN_BAT_NORMAL;
343                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
344         }
345
346         if (display_misc_is_low_battery_state(battery_state)) {
347                 if (!(get_pm_status_flag() & CHRGR_FLAG)) {
348                         display_set_power_save_mode_flag(true);
349                         set_pm_status_flag(LOWBT_FLAG);
350                 }
351         }
352 }
353
354 void display_set_initial_lockscreen_status(void)
355 {
356         int ret = -1;
357         int lock_state = 0;
358         int lock_screen_timeout = 0;
359
360         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
361         if (ret < 0) {
362                 lock_state = -1;
363                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
364         }
365         set_lock_screen_state(lock_state);
366         display_state_transition_get_lock_screen_timeout(&lock_screen_timeout);
367         if (lock_state == VCONFKEY_IDLE_LOCK) {
368                 display_plugin_state_set_timeout(DEVICED_DISPLAY_STATE_ON, lock_screen_timeout);
369                 _I("LCD NORMAL timeout(%d ms) is set for lock screen.", lock_screen_timeout);
370         }
371 }
372
373 /** FIXME: below uevent functions usage and role are unclear, during refactoring
374    these can be removed.
375 */
376 static void esd_action(void)
377 {
378         const struct device_ops *touchscreen_ops = NULL;
379
380         _I("ESD on");
381
382         touchscreen_ops = find_device("touchscreen");
383
384         if (!check_default(touchscreen_ops))
385                 touchscreen_ops->stop(NORMAL_MODE);
386         display_panel_set_panel_state_by_off_state(NORMAL_MODE);
387         display_panel_set_panel_state_by_on_state(NORMAL_MODE);
388         if (!check_default(touchscreen_ops))
389                 touchscreen_ops->start(NORMAL_MODE);
390 }
391
392 static void lcd_uevent_changed(struct udev_device *dev)
393 {
394         const char *devpath;
395         const char *action;
396
397         devpath = udev_device_get_devpath(dev);
398         if (!devpath)
399                 return;
400
401         if (!fnmatch(LCD_ESD_PATH, devpath, 0)) {
402                 action = udev_device_get_action(dev);
403                 if (!strcmp(action, UDEV_CHANGE))
404                         esd_action();
405         }
406 }
407
408 static const struct uevent_handler lcd_uevent_ops = {
409         .subsystem      = LCD_EVENT_SUBSYSTEM,
410         .uevent_func    = lcd_uevent_changed,
411         .data           = NULL,
412 };
413
414 static gboolean handle_sighup(gpointer data)
415 {
416         int signo = (int)(intptr_t) data;
417         _I("received sig hub %d", signo);
418         pm_save_logdump();
419
420         return G_SOURCE_REMOVE;
421 }
422
423 static int delayed_init_done(void *data)
424 {
425         static bool done = false;
426
427         if (!data)
428                 return done;
429
430         done = *(int*)data;
431         if (!done)
432                 return done;
433
434         _I("Booting done, release booting lock.");
435         display_lock_request_unlock_with_option(DEVICED_EVENT_MISC_BOOTING, LCD_NORMAL, PM_SLEEP_MARGIN);
436         display_lock_request_unlock_with_option(DEVICED_EVENT_MISC_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
437
438         return done;
439 }
440
441 static void init_lcd_operation(void)
442 {
443         const struct device_ops *ops = NULL;
444
445         ops = find_device("display");
446         if (!check_default(ops))
447                 display_register_dependent_device(ops);
448
449         ops = find_device("touchkey");
450         if (!check_default(ops))
451                 display_register_dependent_device(ops);
452
453         ops = find_device("touchscreen");
454         if (!check_default(ops))
455                 display_register_dependent_device(ops);
456 }
457
458 static void load_display_hal_backend(void)
459 {
460         int ret;
461
462         if (g_display_hal_backend_available)
463                 return;
464
465         ret = hal_device_display_get_backend();
466         if (ret < 0) {
467                 _W("There is no HAL for display.");
468                 g_display_hal_backend_available = false;
469         }
470
471         g_display_hal_backend_available = true;
472         _W("Display device structure load success.");
473 }
474
475 static int unload_display_hal_backend(void)
476 {
477         g_display_hal_backend_available = false;
478         return hal_device_display_put_backend();
479 }
480
481 static int display_probe(void *data)
482 {
483         int ret = 0;
484
485         display_plugin_device_ops = find_device("display-plugin");
486         if (!display_plugin_device_ops || !display_plugin_device_ops->probe)
487                 return 0;
488
489         ret = display_plugin_device_ops->probe(&g_display_plugin);
490         if (ret < 0)
491                 return ret;
492
493         /**
494          * load display hal backend
495          * if there is no display shared library,
496          * deviced does not provide any method and function of display.
497          */
498         load_display_hal_backend();
499         return 0;
500 }
501
502 static int input_init_handler(void)
503 {
504         if (!g_display_plugin.config->input_support)
505                 remove_device_by_devname("input");
506
507         return 0;
508 }
509
510 static void display_init(void *data)
511 {
512         bool timeout_enable = false;
513         int lcd_always_on = 0;
514         int timeout = 0;
515         int ret = 0;
516         unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS);
517         enum deviced_display_state current;
518
519         if (!display_plugin_device_ops || !display_plugin_device_ops->init)
520                 return;
521
522         g_unix_signal_add(SIGHUP, handle_sighup, (gpointer) SIGHUP);
523         /* FIMXE: display config load should be put here*/
524         display_plugin_device_ops->init(data);
525
526         register_kernel_uevent_control(&lcd_uevent_ops);
527
528         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
529         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
530         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
531         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
532         display_signal_register_display_brightness_notifier();
533         display_misc_register_battery_health_notifier();
534         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
535         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback);
536
537         init_save_userlock();
538
539         ret = init_setting(NULL);
540         if (ret != 0)
541                 _W("Failed to init: setting init error");
542
543         display_plugin_config_get_timeout_enable(&timeout_enable);
544         if (timeout_enable)
545                 display_initialize_display_state_timeout_from_setting();
546
547         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
548
549         _I("input init");
550         ret = input_init_handler();
551         pm_lock_detector_init();
552         if (ret != 0)
553                 _W("Failed to init: input devices poll init error");
554
555         _I("Dbus init.");
556         ret = init_pm_dbus();
557         if (ret != 0)
558                 _W("Failed to init: dbus initialization error");
559
560         display_ops_init(NULL);
561 #ifdef ENABLE_PM_LOG
562                 pm_history_init();
563 #endif
564         init_lcd_operation();
565         display_set_initial_brightness();
566         display_set_initial_battery_flag();
567         display_set_initial_lockscreen_status();
568
569         /* In smd test, TSP should be turned off if display panel is not existed. */
570         if (display_panel_get_dpms_cached_state() == -ENOENT) {
571                 _I("Display panel is not existed.");
572                 lcd_direct_control(DPMS_OFF, NORMAL_MODE);
573                 display_unregister_dependent_device();
574         }
575
576         /* wm_ready needs to be checked
577                 * since display manager can be launched later than deviced.
578                 * In the case, display cannot be turned on at the first booting */
579         // wm_ready = check_wm_ready();
580         if (display_panel_init_dpms()) {
581                 if (display_plugin_is_lcd_on_blocked() != LCDON_BLOCK_NONE) {
582                         display_panel_lcd_off_procedure(LCD_OFF_BY_EVENT);
583                 } else {
584                         display_panel_lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
585                 }
586         } else {
587                 display_add_timer_for_waiting_dpms_init();
588         }
589
590         display_plugin_config_get_lcd_always_on(&lcd_always_on);
591         if (lcd_always_on) {
592                 _I("LCD always on.");
593                 display_state_transition_set_transition_table_display_state(DEVICED_DISPLAY_STATE_ON, DEVICED_DISPLAY_STATE_ON, EVENT_TIMEOUT);
594         }
595
596         if (flags & WITHOUT_STARTNOTI) {        /* start without noti */
597                 _I("Start Power managing without noti");
598                 syscommon_resman_set_resource_attr_uint64_4(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_POWER),
599                         DEVICED_POWER_ATTR_SET_UINT64_4_CURRENT_STATE,
600                         DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL,
601                         HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN, 0);
602
603                 /*
604                         * Lock lcd off until booting is done.
605                         * deviced guarantees all booting script is executing.
606                         * Last script of booting unlocks this suspend blocking state.
607                         */
608                 display_lock_request_lock_with_option(DEVICED_EVENT_MISC_BOOTING, LCD_OFF,
609                                         STAY_CUR_STATE, DELAYED_INIT_WATING_TIME);
610
611                 /* Initial display state right after the booting done */
612                 if (display_plugin_is_lcd_on_blocked())
613                         set_pm_cur_state(DEVICED_DISPLAY_STATE_OFF);
614                 else
615                         set_pm_cur_state(DEVICED_DISPLAY_STATE_ON);
616
617                 ret = display_state_get_current(&current);
618                 if (ret == 0) {
619                         ret = vconf_set_int(VCONFKEY_PM_STATE, current);
620                         if (ret < 0)
621                                 _E("Failed to set vconf value for pm cur state: %d", vconf_get_ext_errno());
622                 }
623
624                 display_set_display_ops_status(DEVICE_OPS_STATUS_START);
625                 if (timeout_enable) {
626                         display_plugin_state_get_timeout(DEVICED_DISPLAY_STATE_ON, &timeout);
627                         /* check minimun lcd on time */
628                         if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT)) {
629                                 timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
630                         }
631                         display_lock_request_lock_with_option(DEVICED_EVENT_MISC_BOOTING, LCD_NORMAL,
632                                                 STAY_CUR_STATE, timeout);
633                 }
634         }
635
636         set_display_init_direction(g_display_plugin.config->display_init_direction);
637 }
638
639 static void display_exit(void *data)
640 {
641         const struct device_ops *ops = NULL;
642
643         if (!display_plugin_device_ops || !display_plugin_device_ops->exit)
644                 return;
645
646         display_plugin_device_ops->exit(data);
647
648         display_set_display_ops_status(DEVICE_OPS_STATUS_STOP);
649
650         /* Set current state to DEVICED_DISPLAY_STATE_ON */
651         set_pm_cur_state(DEVICED_DISPLAY_STATE_ON);
652         set_setting_pmstate(DEVICED_DISPLAY_STATE_ON);
653         /* timeout is not needed */
654         display_state_transition_reset_state_transition_timeout(TIMEOUT_NONE);
655
656         unregister_kernel_uevent_control(&lcd_uevent_ops);
657
658         display_ops_exit(NULL);
659
660         exit_setting();
661
662         display_backlight_update_by_default_brightness();
663
664         display_panel_exit_dpms();
665
666         ops = find_device("touchscreen");
667         if (!check_default(ops))
668                 ops->start(NORMAL_MODE);
669
670         ops = find_device("touchkey");
671         if (!check_default(ops))
672                 ops->start(NORMAL_MODE);
673
674         syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
675         syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
676         syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
677         syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
678         syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
679         display_misc_unregister_battery_health_notifier();
680         display_signal_unregister_display_brightness_notifier();
681         syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
682         syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback);
683
684         display_unregister_dependent_device();
685         free_lock_info_list();
686
687         unload_display_hal_backend();
688 }
689
690 static int display_start(enum device_flags flags)
691 {
692         if (!display_plugin_device_ops || !display_plugin_device_ops->start)
693                 return 0;
694
695         return display_plugin_device_ops->start(flags);
696 }
697
698 static int display_stop(enum device_flags flags)
699 {
700         if (!display_plugin_device_ops || !display_plugin_device_ops->stop)
701                 return 0;
702
703         return display_plugin_device_ops->stop(flags);
704 }
705
706 static int display_status(void)
707 {
708         if (!display_plugin_device_ops || !display_plugin_device_ops->status)
709                 return 0;
710
711         return display_plugin_device_ops->status();
712 }
713
714 static const struct device_ops display_device_ops = {
715         .priority = DEVICE_PRIORITY_HIGH,
716         DECLARE_NAME_LEN("display"),
717         .probe    = display_probe,
718         .init     = display_init,
719         .exit     = display_exit,
720         .start    = display_start,
721         .stop     = display_stop,
722         .status   = display_status,
723 };
724
725 DEVICE_OPS_REGISTER(&display_device_ops)