Replace function name to get variable pointer
[platform/core/system/deviced.git] / plugins / mobile / display / device-interface.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd.
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
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdbool.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <limits.h>
29 #include <math.h>
30 #include <assert.h>
31 #include <errno.h>
32 #include <dlfcn.h>
33
34 #include "ambient-mode.h"
35 #include "core/log.h"
36 #include "core/devices.h"
37 #include "core/common.h"
38 #include "core/device-notifier.h"
39 #include "util.h"
40 #include "device-interface.h"
41 #include "vconf.h"
42 #include "core.h"
43 #include "device-node.h"
44 #include "display/display-dpms.h"
45 #include "display/display.h"
46 #include "display/display-lock.h"
47 #include "power/boot.h"
48 #include "power/power-control.h"
49
50 #define TOUCH_ON        1
51 #define TOUCH_OFF       0
52
53 #define LCD_PHASED_MIN_BRIGHTNESS       1
54 #define LCD_PHASED_MAX_BRIGHTNESS       100
55 #define LCD_PHASED_CHANGE_STEP          5
56 #define LCD_PHASED_DELAY                10000   /* microsecond */
57 #define DUMP_MODE_WAITING_TIME          600000  /* milisecond */
58
59 #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so"
60
61 #define GESTURE_STR                     "gesture"
62 #define POWERKEY_STR                    "powerkey"
63 #define EVENT_STR                       "event"
64 #define TOUCH_STR                       "touch"
65 #define TIMEOUT_STR                     "timeout"
66 #define PROXIMITY_STR                   "proximity"
67 #define PALM_STR                        "palm"
68 #define UNKNOWN_STR                     "unknown"
69
70 static struct _backlight_ops backlight_ops;
71 static bool custom_status;
72 static int custom_brightness;
73 static int force_brightness;
74 static int default_brightness;
75 static int dpms_running_state = DPMS_SETTING_DONE;
76 static struct display_device *display_dev;
77 static guint release_timer;
78 static struct display_config *display_conf;
79
80 inline struct _backlight_ops *get_var_backlight_ops(void)
81 {
82         return &backlight_ops;
83 }
84
85 struct display_device *display_dev_get(void)
86 {
87         return display_dev;
88 }
89
90 void dpms_set_running_state(int val)
91 {
92         dpms_running_state = val;
93 }
94
95 static int bl_onoff(int on, enum device_flags flags)
96 {
97         dpms_set_state(on);
98
99 #ifdef ENABLE_PM_LOG
100         if (on == DPMS_ON)
101                 pm_history_save(PM_LOG_LCD_ON_COMPLETE, get_pm_cur_state());
102         else if (on == DPMS_OFF || on == DPMS_FORCE_OFF)
103                 pm_history_save(PM_LOG_LCD_OFF_COMPLETE, get_pm_cur_state());
104         else
105                 pm_history_save(PM_LOG_LCD_CONTROL_FAIL, on);
106 #endif
107
108         return 0;
109 }
110
111 static int bl_brt(int brightness, int delay)
112 {
113         int ret = -1;
114
115         if (delay > 0)
116                 usleep(delay);
117
118         /* Update device brightness */
119         ret = backlight_ops.set_brightness(brightness);
120
121         _I("Set brightness(%d): %d", brightness, ret);
122
123         return ret;
124 }
125
126 static int get_lcd_power(void)
127 {
128         enum display_state val;
129         int ret;
130
131         if (!display_dev || !display_dev->get_state) {
132                 return dpms_get_state();
133         } else {
134                 ret = display_dev->get_state(&val);
135                 if (ret < 0)
136                         return ret;
137
138                 if (val == DISPLAY_ON && ambient_get_state())
139                         return DPMS_OFF;
140
141                 if (dpms_running_state != DPMS_SETTING_DONE)
142                         return dpms_running_state;
143
144                 switch (val) {
145                 case DISPLAY_ON:
146                         return DPMS_ON;
147                 case DISPLAY_STANDBY:
148                         return DPMS_STANDBY;
149                 case DISPLAY_SUSPEND:
150                         return DPMS_SUSPEND;
151                 case DISPLAY_OFF:
152                         return DPMS_OFF;
153                 default:
154                         return -EINVAL;
155                 }
156         }
157 }
158
159 bool display_dimstay_check(void)
160 {
161         if (get_pm_status_flag() & DIM_FLAG)
162                 return true;
163
164         if ((get_pm_status_flag() & PWRSV_FLAG) && !(get_pm_status_flag() & BRTCH_FLAG))
165                 return true;
166
167         return false;
168 }
169
170 static void change_brightness(int start, int end, int step)
171 {
172         int diff, val;
173         int ret = -1;
174         int prev;
175
176         if (display_dimstay_check())
177                 return;
178
179         ret = backlight_ops.get_brightness(&prev);
180         if (ret < 0) {
181                 _E("Failed to get brightness: %d", ret);
182                 return;
183         }
184
185         if (prev == end)
186                 return;
187
188         if (get_pm_status_flag() & DIM_MASK)
189                 end = 0;
190
191         _I("start %d end %d step %d", start, end, step);
192
193         if (display_dev && display_dev->set_multi_brightness) {
194                 ret = display_dev->set_multi_brightness(end, step, LCD_PHASED_DELAY);
195                 if (ret < 0)
196                         _E("Failed to set_multi_brightness (%d)", ret);
197
198                 backlight_ops.set_brightness(end);
199
200                 return;
201         }
202
203         diff = end - start;
204
205         if (abs(diff) < step)
206                 val = (diff > 0 ? 1 : -1);
207         else
208                 val = (int)ceil((double)diff / step);
209
210         while (start != end) {
211                 if (val == 0) break;
212
213                 start += val;
214                 if ((val > 0 && start > end) ||
215                     (val < 0 && start < end))
216                         start = end;
217
218                 bl_brt(start, LCD_PHASED_DELAY);
219         }
220 }
221
222 static int backlight_on(enum device_flags flags)
223 {
224         int ret = -1;
225         static int cnt;
226
227         _I("[DPMS XLIB Backlight] LCD on %#x cnt:%d", flags, cnt);
228
229         cnt++;
230         ret = bl_onoff(DPMS_ON, flags);
231 #ifdef ENABLE_PM_LOG
232         pm_history_save(PM_LOG_LCD_ON, get_pm_cur_state());
233 #endif
234
235         return ret;
236 }
237
238 static int backlight_off(enum device_flags flags)
239 {
240         int ret = -1;
241         static int cnt, ambient_cnt;
242
243         if (flags & AMBIENT_MODE) {
244                 _I("[DPMS XLIB Backlight] LCD suspend %#x cnt:%d", flags, ambient_cnt);
245                 ambient_cnt++;
246
247                 return 0;
248         }
249
250         _I("[DPMS XLIB Backlight] LCD off %#x cnt:%d", flags, cnt);
251         cnt++;
252
253         if (flags & LCD_PHASED_TRANSIT_MODE)
254                 backlight_ops.transit_brt(default_brightness,
255                     LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
256
257         if (flags & FORCE_OFF_MODE)
258                 ret = bl_onoff(DPMS_FORCE_OFF, flags);
259         else
260                 ret = bl_onoff(DPMS_OFF, flags);
261
262 #ifdef ENABLE_PM_LOG
263         pm_history_save(PM_LOG_LCD_OFF, get_pm_cur_state());
264 #endif
265
266         return ret;
267 }
268
269 static int backlight_dim(void)
270 {
271         int ret;
272
273         ret = backlight_ops.set_brightness(PM_DIM_BRIGHTNESS);
274 #ifdef ENABLE_PM_LOG
275         if (!ret)
276                 pm_history_save(PM_LOG_LCD_DIM, get_pm_cur_state());
277         else
278                 pm_history_save(PM_LOG_LCD_DIM_FAIL, get_pm_cur_state());
279 #endif
280         return ret;
281 }
282
283 static int set_custom_status(bool on)
284 {
285         custom_status = on;
286         return 0;
287 }
288
289 static bool get_custom_status(void)
290 {
291         return custom_status;
292 }
293
294 static int save_custom_brightness(void)
295 {
296         int ret, brightness;
297
298         ret = backlight_ops.get_brightness(&brightness);
299
300         custom_brightness = brightness;
301
302         return ret;
303 }
304
305 static int custom_backlight_update(void)
306 {
307         int ret = 0;
308
309         if (custom_brightness < PM_MIN_BRIGHTNESS ||
310             custom_brightness > PM_MAX_BRIGHTNESS)
311                 return -EINVAL;
312
313         if (display_dimstay_check())
314                 ret = backlight_dim();
315         else {
316                 _I("custom brightness restored! %d", custom_brightness);
317                 ret = backlight_ops.set_brightness(custom_brightness);
318         }
319
320         return ret;
321 }
322
323 static int set_force_brightness(int level)
324 {
325         if (level < 0 ||  level > PM_MAX_BRIGHTNESS)
326                 return -EINVAL;
327
328         force_brightness = level;
329
330         return 0;
331 }
332
333 static int backlight_update(void)
334 {
335         int ret = 0;
336         int brt;
337
338         if (get_custom_status()) {
339                 _I("custom brightness mode! brt no updated");
340                 return 0;
341         }
342         if (display_dimstay_check())
343                 ret = backlight_dim();
344         else {
345                 brt = backlight_ops.get_default_brt();
346                 ret = backlight_ops.set_brightness(brt);
347         }
348         return ret;
349 }
350
351 static int backlight_standby(int force)
352 {
353         int ret = -1;
354
355         if ((get_lcd_power() == DPMS_ON) || force) {
356                 _I("LCD standby");
357                 ret = bl_onoff(DPMS_STANDBY, 0);
358         }
359
360         return ret;
361 }
362
363 static int set_default_brt(int level)
364 {
365         if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
366                 level = display_conf->pm_default_brightness;
367
368         default_brightness = level;
369
370         return 0;
371 }
372
373 static int get_default_brt(void)
374 {
375         return default_brightness;
376 }
377
378 static int get_max_brightness(void)
379 {
380         static int max = -1;
381         int ret;
382
383         if (max > 0)
384                 return max;
385
386         if (!display_dev) {
387                 _E("There is no display device.");
388                 return -ENOENT;
389         }
390
391         if (!display_dev->get_max_brightness) {
392                 max = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
393                 return max;
394         }
395
396         ret = display_dev->get_max_brightness(&max);
397         if (ret < 0) {
398                 _E("Failed to get max brightness: %d", ret);
399                 return ret;
400         }
401
402         return max;
403 }
404
405 static int set_brightness(int val)
406 {
407         int max;
408
409         if (!display_dev || !display_dev->set_brightness) {
410                 _E("There is no display device.");
411                 return -ENOENT;
412         }
413
414         max = get_max_brightness();
415         if (max < 0) {
416                 _E("Failed to get max brightness.");
417                 return max;
418         }
419
420         if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
421                 _I("brightness(%d), force brightness(%d)",
422                     val, force_brightness);
423                 val = force_brightness;
424         }
425
426         if (get_pm_status_flag() & DIM_MASK)
427                 val = 0;
428
429         /* Maximum Brightness to users is 100.
430          * Thus real brightness need to be calculated */
431         val = val * max / 100;
432
433         _I("set brightness %d (default:%d)", val, default_brightness);
434         device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
435
436         return display_dev->set_brightness(val);
437 }
438
439 static int get_brt_normalized(int brt_raw)
440 {
441         int quotient, remainder;
442         int max;
443
444         max = get_max_brightness();
445         if (max < 0) {
446                 _E("Failed to get max brightness.");
447                 return max;
448         }
449
450         /* Maximum Brightness to users is 100.
451          * Thus the brightness value need to be calculated using real brightness.
452          *    ex) Let's suppose that the maximum brightness of driver is 255.
453          *      case 1) When the user sets the brightness to 41,
454          *              real brightness is
455          *                 41 * 255 / 100 = 104.55 = 104 (rounded off)
456          *      case 2) When the user gets the brightness,
457          *              the driver returns the brightness 104.
458          *              Thus the brightness to users is
459          *                 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
460          */
461         quotient = brt_raw * 100 / max;
462         remainder = brt_raw * 100 % max;
463         if (remainder > 0)
464                 quotient++;
465
466         return quotient;
467 }
468
469 static int get_brightness(int *val)
470 {
471         int brt, ret;
472
473         if (!display_dev || !display_dev->get_brightness) {
474                 _E("There is no display device.");
475                 return -ENOENT;
476         }
477
478         ret = display_dev->get_brightness(&brt);
479         if (ret < 0) {
480                 _E("Failed to get brightness: %d", ret);
481                 return ret;
482         }
483
484         *val = get_brt_normalized(brt);
485         return 0;
486 }
487
488 static int get_brightness_by_light_sensor(float lmax, float lmin, float light, int *brt)
489 {
490         int brt_raw;
491         int ret;
492
493         if (!display_dev || !display_dev->get_auto_brightness)
494                 return -ENOTSUP;
495
496         ret = display_dev->get_auto_brightness(lmax, lmin, light, &brt_raw);
497         if (ret < 0) {
498                 _E("Failed to get brightness by light sensor: %d", ret);
499                 return ret;
500         }
501
502         *brt = get_brt_normalized(brt_raw);
503         return 0;
504 }
505
506 static int get_image_effect(enum display_image_effect *effect)
507 {
508         int ret;
509         enum display_image_effect val;
510
511         if (!display_dev || !display_dev->get_image_effect) {
512                 _E("There is no display device.");
513                 return -ENOENT;
514         }
515
516         ret = display_dev->get_image_effect(&val);
517         if (ret < 0) {
518                 _E("Failed to get image effect: %d", ret);
519                 return ret;
520         }
521
522         *effect = val;
523
524         return 0;
525 }
526
527 static int set_image_effect(enum display_image_effect effect)
528 {
529         int ret;
530
531         if (!display_dev || !display_dev->set_image_effect) {
532                 _E("There is no display device.");
533                 return -ENOENT;
534         }
535
536         ret = display_dev->set_image_effect(effect);
537         if (ret < 0) {
538                 _E("Failed to set image effect: %d", ret);
539                 return ret;
540         }
541
542         return 0;
543 }
544
545 static int get_panel_mode(enum display_panel_mode *mode)
546 {
547         int ret;
548         enum display_panel_mode val;
549
550         if (!display_dev || !display_dev->get_panel_mode) {
551                 _E("there is no display device");
552                 return -ENOENT;
553         }
554
555         ret = display_dev->get_panel_mode(&val);
556         if (ret < 0) {
557                 _E("failed to get panel mode(%d)", ret);
558                 return ret;
559         }
560
561         *mode = val;
562
563         return 0;
564 }
565
566 static int set_panel_mode(enum display_panel_mode mode)
567 {
568         int ret;
569
570         if (!display_dev || !display_dev->set_panel_mode) {
571                 _E("there is no display device");
572                 return -ENOENT;
573         }
574
575         ret = display_dev->set_panel_mode(mode);
576         if (ret < 0) {
577                 _E("failed to set panel mode(%d)", ret);
578                 return ret;
579         }
580
581         return 0;
582 }
583
584 static int get_frame_rate(int *rate)
585 {
586         if (!rate)
587                 return -EINVAL;
588
589         if (!display_dev || !display_dev->get_frame_rate)
590                 return -ENOTSUP;
591
592         return display_dev->get_frame_rate(rate);
593 }
594
595 static int set_frame_rate(int rate)
596 {
597         int ret;
598         static int fmin = -1, fmax = -1;
599
600         if (!display_dev ||
601                 !display_dev->set_frame_rate)
602                 return -ENOTSUP;
603
604         if (display_dev->get_min_frame_rate) {
605                 if (fmin < 0) {
606                         ret = display_dev->get_min_frame_rate(&fmin);
607                         if (ret < 0) {
608                                 _E("Failed to get min frate rate: %d", ret);
609                                 return ret;
610                         }
611                 }
612                 if (rate < fmin) {
613                         _E("Invalid rate(%d). (Valid rate: %d <= rate)", rate, fmin);
614                         return -EINVAL;
615                 }
616         }
617
618         if (display_dev->get_max_frame_rate) {
619                 if (fmax < 0) {
620                         ret = display_dev->get_max_frame_rate(&fmax);
621                         if (ret < 0) {
622                                 _E("Failed to get max frate rate: %d", ret);
623                                 return ret;
624                         }
625                 }
626                 if (rate > fmax) {
627                         _E("Invalid rate(%d). (Valid rate: rate <= %d)", rate, fmax);
628                         return -EINVAL;
629                 }
630         }
631
632         return display_dev->set_frame_rate(rate);
633 }
634
635 /* It was operated only AOD enter & leave */
636 static int backlight_transit_state(int state)
637 {
638         int brt, val;
639         int start, end;
640
641         backlight_ops.get_brightness(&brt);
642
643         if (state == DPMS_OFF) {
644                 start = brt;
645                 end = display_conf->aod_enter_level;
646
647                 /*
648                  * The value of backlight_ops.get_brightness is system brightness.
649                  * But when device is LBM, the value is not same with real brightness.
650                  * So it should be read exactly value for transit smooth effect
651                  */
652                 get_brightness(&val);
653
654                 if (val > display_conf->aod_enter_level)
655                         backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
656         } else {
657                 /* prevent transit effect when another effect is already executed */
658                 if (brt != display_conf->aod_enter_level) {
659                         _W("effect is already executed brt(%d) aod_level(%d)",
660                                         brt, display_conf->aod_enter_level);
661                         return 0;
662                 }
663
664                 start = display_conf->aod_enter_level;
665                 end = default_brightness;
666                 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
667         }
668
669         return 0;
670 }
671
672 static gboolean blink_cb(gpointer data)
673 {
674         static bool flag;
675
676         set_brightness(flag ? PM_MAX_BRIGHTNESS : PM_MIN_BRIGHTNESS);
677
678         flag = !flag;
679
680         return G_SOURCE_CONTINUE;
681 }
682
683 static void blink(int timeout)
684 {
685         static guint timer;
686
687         if (timer) {
688                 g_source_remove(timer);
689                 timer = 0;
690         }
691
692         if (timeout < 0) {
693                 _E("timeout value is invalid %d", timeout);
694                 return;
695         }
696
697         if (timeout == 0) {
698                 backlight_update();
699                 return;
700         }
701
702         timer = g_timeout_add(timeout, blink_cb, NULL);
703 }
704
705 static gboolean release_blink_cb(gpointer data)
706 {
707         blink(0);
708
709         release_timer = 0;
710         return G_SOURCE_REMOVE;
711 }
712
713 static void release_blink(void)
714 {
715         if (release_timer) {
716                 g_source_remove(release_timer);
717                 release_timer = 0;
718         }
719
720         release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL);
721 }
722
723 static void restore_brightness_func(void)
724 {
725         backlight_ops.set_brightness = set_brightness;
726         backlight_ops.get_brightness = get_brightness;
727         backlight_ops.transit_brt = change_brightness;
728 }
729
730 static struct _backlight_ops backlight_ops = {
731         .off = backlight_off,
732         .dim = backlight_dim,
733         .on = backlight_on,
734         .update = backlight_update,
735         .standby = backlight_standby,
736         .set_default_brt = set_default_brt,
737         .get_default_brt = get_default_brt,
738         .get_lcd_power = get_lcd_power,
739         .set_custom_status = set_custom_status,
740         .get_custom_status = get_custom_status,
741         .save_custom_brightness = save_custom_brightness,
742         .custom_update = custom_backlight_update,
743         .set_force_brightness = set_force_brightness,
744         .set_brightness = set_brightness,
745         .get_brightness = get_brightness,
746         .restore_brightness_func = restore_brightness_func,
747         .get_brightness_by_light_sensor = get_brightness_by_light_sensor,
748         .get_image_effect = get_image_effect,
749         .set_image_effect = set_image_effect,
750         .get_panel_mode = get_panel_mode,
751         .set_panel_mode = set_panel_mode,
752         .get_frame_rate = get_frame_rate,
753         .set_frame_rate = set_frame_rate,
754         .transit_state = backlight_transit_state,
755         .transit_brt = change_brightness,
756         .blink = blink,
757         .release_blink = release_blink,
758 };
759
760 int display_service_load(void)
761 {
762         struct hw_info *info;
763         int r;
764
765         if (display_dev)
766                 return 0;
767
768         r = hw_get_info(DISPLAY_HARDWARE_DEVICE_ID,
769                         (const struct hw_info **)&info);
770         if (r < 0) {
771                 _I("display shared library is not supported: %d", r);
772                 return 0;
773         }
774
775         if (!info->open) {
776                 _E("Failed to open display device: open(NULL).");
777                 return -EPERM;
778         }
779
780         r = info->open(info, NULL, (struct hw_common **)&display_dev);
781         if (r < 0) {
782                 _E("Failed to get display device structure: %d", r);
783                 return -EPERM;
784         }
785
786         _D("Display device structure load success.");
787         return 0;
788 }
789
790 int display_service_free(void)
791 {
792         struct hw_info *info;
793
794         if (!display_dev)
795                 return -ENOENT;
796
797         info = display_dev->common.info;
798
799         assert(info);
800
801         info->close((struct hw_common *)display_dev);
802         display_dev = NULL;
803
804         return 0;
805 }
806
807 static int booting_done(void *data)
808 {
809         static int done = false;
810
811         if (!data)
812                 return done;
813
814         done = *(int *)data;
815
816         return done;
817 }
818
819 int is_lcdon_blocked(void)
820 {
821         /* block lcdon until booting done in silent boot mode */
822         if (silent_boot && !booting_done(NULL))
823                 return LCDON_BLOCK_DURING_SILENT_BOOT;
824
825         return LCDON_BLOCK_NONE;
826 }
827
828 int init_sysfs(unsigned int flags)
829 {
830         register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
831         register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
832
833         return 0;
834 }
835
836 int exit_sysfs(void)
837 {
838         const struct device_ops *ops = NULL;
839
840         backlight_update();
841
842         exit_dpms();
843
844         ops = find_device("touchscreen");
845         if (!check_default(ops))
846                 ops->start(NORMAL_MODE);
847
848         ops = find_device("touchkey");
849         if (!check_default(ops))
850                 ops->start(NORMAL_MODE);
851
852         unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
853
854         return 0;
855 }
856
857 static void __CONSTRUCTOR__ initialize(void)
858 {
859         display_conf = get_var_display_config();
860         if (!display_conf)
861                 _E("Failed to get display configuration variable.");
862 }
863