tizen 2.3 release
[framework/system/deviced.git] / src / display / auto-brightness.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 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 <stdbool.h>
21 #include <stdio.h>
22 #include <math.h>
23 #include <limits.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <vconf.h>
29 #include <sensor_internal.h>
30 #include <Ecore.h>
31
32 #include "util.h"
33 #include "core.h"
34 #include "display-ops.h"
35 #include "device-node.h"
36 #include "weaks.h"
37 #include "hbm.h"
38 #include "proc/proc-handler.h"
39 #include "core/device-notifier.h"
40 #include "core/config-parser.h"
41
42 #define DISP_FORCE_SHIFT        12
43 #define DISP_FORCE_CMD(prop, force)     (((force) << DISP_FORCE_SHIFT) | prop)
44
45 #define SAMPLING_INTERVAL       1       /* 1 sec */
46 #define MAX_SAMPLING_COUNT      3
47 #define MAX_FAULT               5
48 #define DEFAULT_AUTOMATIC_BRT   5
49 #define MAX_AUTOMATIC_COUNT     11
50 #define AUTOMATIC_DEVIDE_VAL    10
51 #define AUTOMATIC_DELAY_TIME    0.5     /* 0.5 sec */
52
53 #define RADIAN_VALUE            (57.2957)
54 #define ROTATION_90             90
55 #define WORKING_ANGLE_MIN       0
56 #define WORKING_ANGLE_MAX       20
57
58 #define ISVALID_AUTOMATIC_INDEX(index) (index >= 0 && index < MAX_AUTOMATIC_COUNT)
59 #define BOARD_CONF_FILE "/etc/deviced/display.conf"
60
61 #define ON_LUX          -1
62 #define OFF_LUX         -1
63 #define ON_COUNT        1
64 #define OFF_COUNT       1
65
66 struct lbm_config {
67         int on;
68         int off;
69         int on_count;
70         int off_count;
71 };
72
73 struct lbm_config lbm_conf = {
74         .on             = ON_LUX,
75         .off            = OFF_LUX,
76         .on_count       = ON_COUNT,
77         .off_count      = OFF_COUNT,
78 };
79
80 static int (*_default_action) (int);
81 static Ecore_Timer *alc_timeout_id = 0;
82 static Ecore_Timer *update_timeout;
83 static int light_handle = -1;
84 static int accel_handle = -1;
85 static int fault_count = 0;
86 static int automatic_brt = DEFAULT_AUTOMATIC_BRT;
87 static int min_brightness = PM_MIN_BRIGHTNESS;
88 static char *min_brightness_name = 0;
89 static int value_table[MAX_AUTOMATIC_COUNT];
90 static int lbm_state = -1;
91
92 static bool update_working_position(void)
93 {
94         sensor_data_t data;
95         int ret;
96         float x, y, z, pitch, realg;
97
98         if (!display_conf.accel_sensor_on)
99                 return false;
100
101         ret = sf_get_data(accel_handle, ACCELEROMETER_BASE_DATA_SET, &data);
102         if (ret < 0) {
103                 _E("Fail to get accelerometer data! %d", ret);
104                 return true;
105         }
106
107         x = data.values[0];
108         y = data.values[1];
109         z = data.values[2];
110
111         realg = (float)sqrt((x * x) + (y * y) + (z * z));
112         pitch = ROTATION_90 - abs((int) (asin(z / realg) * RADIAN_VALUE));
113
114         _D("accel data [%f, %f, %f] - %f", x, y, z, pitch);
115
116         if (pitch >= WORKING_ANGLE_MIN && pitch <= WORKING_ANGLE_MAX)
117                 return true;
118         return false;
119 }
120
121 static int get_siop_brightness(int value)
122 {
123         int cmd, ret, brt;
124
125         cmd = DISP_CMD(PROP_DISPLAY_MAX_BRIGHTNESS, DEFAULT_DISPLAY);
126         ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &brt);
127         if (ret >= 0 && value > brt)
128                 return brt;
129
130         return value;
131 }
132
133 static void alc_set_brightness(int setting, int value, int lux)
134 {
135         static int old;
136         int position, cmd, tmp_value = 0;
137
138         cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY);
139         if (device_get_property(DEVICE_TYPE_DISPLAY, cmd, &tmp_value) < 0) {
140                 _E("Fail to get display brightness!");
141                 return;
142         }
143
144         if (value < min_brightness)
145                 value = min_brightness;
146
147         if (cur_siop_level() != 0)
148                 value = get_siop_brightness(value);
149
150         if (tmp_value != value) {
151                 if (!setting && min_brightness == PM_MIN_BRIGHTNESS &&
152                     display_conf.accel_sensor_on == true) {
153                         position = update_working_position();
154                         if (!position && (old > lux)) {
155                                 _D("It's not working position, "
156                                     "LCD isn't getting dark!");
157                                 return;
158                         }
159                 }
160                 int diff, step;
161
162                 diff = value - tmp_value;
163                 if (abs(diff) < display_conf.brightness_change_step)
164                         step = (diff > 0 ? 1 : -1);
165                 else
166                         step = (int)ceil(diff /
167                             (float)display_conf.brightness_change_step);
168
169                 _D("%d", step);
170                 while (tmp_value != value) {
171                         if (step == 0) break;
172
173                         tmp_value += step;
174                         if ((step > 0 && tmp_value > value) ||
175                             (step < 0 && tmp_value < value))
176                                 tmp_value = value;
177
178                         backlight_ops.set_default_brt(tmp_value);
179                         backlight_ops.update();
180                 }
181                 _I("load light data:%d lux,auto brt %d,min brightness %d,"
182                     "brightness %d", lux, automatic_brt, min_brightness, value);
183                 old = lux;
184         }
185 }
186
187 static bool check_lbm(int lux, int setting)
188 {
189         static int on_count, off_count;
190
191         if (lux < 0)
192                 return false;
193
194         if (lbm_conf.on < 0 || lbm_conf.off < 0)
195                 return true;
196
197         if (lux <= lbm_conf.on && lbm_state != true) {
198                 off_count = 0;
199                 on_count++;
200                 if (on_count >= lbm_conf.on_count || setting) {
201                         on_count = 0;
202                         lbm_state = true;
203                         _D("LBM is on");
204                         return true;
205                 }
206         } else if (lux >= lbm_conf.off && lbm_state != false) {
207                 on_count = 0;
208                 off_count++;
209                 if (off_count >= lbm_conf.off_count || setting) {
210                         off_count = 0;
211                         lbm_state = false;
212                         _D("LBM is off");
213                         return true;
214                 }
215         } else if (lux > lbm_conf.on && lux < lbm_conf.off) {
216                 off_count = 0;
217                 on_count = 0;
218         }
219
220         if (setting)
221                 return true;
222
223         return false;
224 }
225
226 static bool check_brightness_changed(int value)
227 {
228         int i;
229         static int values[MAX_SAMPLING_COUNT], count = 0;
230
231         if (!get_hallic_open())
232                 return false;
233
234         if (count >= MAX_SAMPLING_COUNT || count < 0)
235                 count = 0;
236
237         values[count++] = value;
238
239         for (i = 0; i < MAX_SAMPLING_COUNT - 1; i++)
240                 if (values[i] != values[i+1])
241                         return false;
242         return true;
243 }
244
245 static bool check_hbm(int lux)
246 {
247         int ret, old_state, new_state;
248         static int on_count, off_count;
249
250         if (hbm_get_state == NULL)
251                 return false;
252
253         old_state = hbm_get_state();
254         if (old_state < 0) {
255                 _E("Failed to get HBM state!");
256                 return false;
257         }
258
259         if (old_state) {
260                 if (lux <= hbm_conf.off)
261                         off_count++;
262                 else
263                         off_count = 0;
264                 new_state = (off_count >= hbm_conf.off_count ? 0 : 1);
265         } else {
266                 if (lux >= hbm_conf.on)
267                         on_count++;
268                 else
269                         on_count = 0;
270                 new_state = (on_count >= hbm_conf.on_count ? 1 : 0);
271         }
272
273         if (old_state != new_state) {
274                 on_count = off_count = 0;
275                 _D("hbm is %s", (new_state ? "on" : "off"));
276                 ret = hbm_set_state(new_state);
277                 if (ret < 0)
278                         _E("Failed to set HBM state!");
279                 /*
280                  * Brightness is changed directly
281                  * when hbm state is changed from on to off
282                  */
283                 if (!new_state)
284                         display_info.update_auto_brightness(true);
285         }
286
287         return (new_state ? true : false);
288 }
289
290 static bool alc_update_brt(bool setting)
291 {
292         int value = 0;
293         int cal_value = 0;
294         int ret = -1;
295         int cmd;
296         sensor_data_t light_data;
297
298         ret = sf_get_data(light_handle, LIGHT_LUX_DATA_SET, &light_data);
299         if (ret < 0 || (int)light_data.values[0] < 0) {
300                 fault_count++;
301         } else {
302                 int force = (setting ? 1 : 0);
303                 cmd = DISP_FORCE_CMD(PROP_DISPLAY_BRIGHTNESS_BY_LUX, force);
304                 cmd = DISP_CMD(cmd, (int)light_data.values[0]);
305                 ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, value_table);
306
307                 value = (ISVALID_AUTOMATIC_INDEX(automatic_brt) ?
308                     value_table[automatic_brt] : value_table[DEFAULT_AUTOMATIC_BRT]);
309
310                 if (ret < 0 || value < PM_MIN_BRIGHTNESS ||
311                     value > PM_MAX_BRIGHTNESS) {
312                         _E("fail to load light data : %d lux, %d",
313                                 (int)light_data.values[0], value);
314                         fault_count++;
315                 } else {
316                         fault_count = 0;
317
318                         /* Check HBM (High Brightness Mode) */
319                         if (check_hbm((int)light_data.values[0]))
320                                 return EINA_TRUE;
321
322                         if (!check_lbm((int)light_data.values[0], setting))
323                                 return EINA_TRUE;
324
325                         if (display_conf.continuous_sampling &&
326                             !check_brightness_changed(value) && !setting)
327                                 return EINA_TRUE;
328
329                         alc_set_brightness(setting, value, (int)light_data.values[0]);
330                 }
331         }
332
333         if ((fault_count > MAX_FAULT) && !(pm_status_flag & PWROFF_FLAG)) {
334                 if (alc_timeout_id > 0)
335                         ecore_timer_del(alc_timeout_id);
336                 alc_timeout_id = NULL;
337                 vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
338                     SETTING_BRIGHTNESS_AUTOMATIC_OFF);
339                 _E("Fault counts is over %d, disable automatic brightness",
340                     MAX_FAULT);
341                 return EINA_FALSE;
342         }
343         return EINA_TRUE;
344 }
345
346 static bool alc_handler(void* data)
347 {
348         if (pm_cur_state != S_NORMAL || !get_hallic_open()){
349                 if (alc_timeout_id > 0)
350                         ecore_timer_del(alc_timeout_id);
351                 alc_timeout_id = NULL;
352                 return EINA_FALSE;
353         }
354
355         if (alc_update_brt(false) == EINA_FALSE)
356                 return EINA_FALSE;
357
358         if (alc_timeout_id != 0)
359                 return EINA_TRUE;
360
361         return EINA_FALSE;
362 }
363
364 static int alc_action(int timeout)
365 {
366         /* sampling timer add */
367         if (alc_timeout_id == 0 && !(pm_status_flag & PWRSV_FLAG)) {
368                 display_info.update_auto_brightness(true);
369
370                 alc_timeout_id =
371                     ecore_timer_add(display_conf.lightsensor_interval,
372                             (Ecore_Task_Cb)alc_handler, NULL);
373         }
374
375         if (_default_action != NULL)
376                 return _default_action(timeout);
377
378         /* unreachable code */
379         return -1;
380 }
381
382 static int connect_sfsvc(void)
383 {
384         int sf_state = -1;
385
386         _I("connect with sensor fw");
387         /* light sensor */
388         light_handle = sf_connect(LIGHT_SENSOR);
389         if (light_handle < 0) {
390                 _E("light sensor attach fail");
391                 goto error;
392         }
393         sf_state = sf_start(light_handle, 0);
394         if (sf_state < 0) {
395                 _E("light sensor attach fail");
396                 sf_disconnect(light_handle);
397                 light_handle = -1;
398                 goto error;
399         }
400         sf_change_sensor_option(light_handle, 1);
401
402         if (!display_conf.accel_sensor_on)
403                 goto success;
404
405         /* accelerometer sensor */
406         accel_handle = sf_connect(ACCELEROMETER_SENSOR);
407         if (accel_handle < 0) {
408                 _E("accelerometer sensor attach fail");
409                 goto error;
410         }
411         sf_state = sf_start(accel_handle, 0);
412         if (sf_state < 0) {
413                 _E("accelerometer sensor attach fail");
414                 sf_disconnect(accel_handle);
415                 accel_handle = -1;
416                 goto error;
417         }
418         sf_change_sensor_option(accel_handle, 1);
419
420 success:
421         fault_count = 0;
422         return 0;
423
424 error:
425         if (light_handle >= 0) {
426                 sf_stop(light_handle);
427                 sf_disconnect(light_handle);
428                 light_handle = -1;
429         }
430         if (display_conf.accel_sensor_on && accel_handle >= 0) {
431                 sf_stop(accel_handle);
432                 sf_disconnect(accel_handle);
433                 accel_handle = -1;
434         }
435         return -EIO;
436 }
437
438 static int disconnect_sfsvc(void)
439 {
440         _I("disconnect with sensor fw");
441         /* light sensor*/
442         if(light_handle >= 0) {
443                 sf_stop(light_handle);
444                 sf_disconnect(light_handle);
445                 light_handle = -1;
446         }
447         /* accelerometer sensor*/
448         if (display_conf.accel_sensor_on && accel_handle >= 0) {
449                 sf_stop(accel_handle);
450                 sf_disconnect(accel_handle);
451                 accel_handle = -1;
452         }
453
454         if (_default_action != NULL) {
455                 states[S_NORMAL].action = _default_action;
456                 _default_action = NULL;
457         }
458         if (alc_timeout_id > 0) {
459                 ecore_timer_del(alc_timeout_id);
460                 alc_timeout_id = NULL;
461         }
462
463         return 0;
464 }
465
466 static inline void set_brtch_state(void)
467 {
468         if (pm_status_flag & PWRSV_FLAG) {
469                 pm_status_flag |= BRTCH_FLAG;
470                 vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, true);
471                 _D("brightness changed in low battery,"
472                     "escape dim state (light)");
473         }
474 }
475
476 static int set_autobrightness_state(int status)
477 {
478         int ret = -1;
479         int brt = -1;
480         int default_brt = -1;
481         int max_brt = -1;
482
483         if (status == SETTING_BRIGHTNESS_AUTOMATIC_ON) {
484                 if(connect_sfsvc() < 0)
485                         return -1;
486
487                 /* escape dim state if it's in low battery.*/
488                 set_brtch_state();
489
490                 /* change alc action func */
491                 if (_default_action == NULL)
492                         _default_action = states[S_NORMAL].action;
493                 states[S_NORMAL].action = alc_action;
494
495                 display_info.update_auto_brightness(true);
496
497                 alc_timeout_id =
498                     ecore_timer_add(display_conf.lightsensor_interval,
499                             (Ecore_Task_Cb)alc_handler, NULL);
500         } else if (status == SETTING_BRIGHTNESS_AUTOMATIC_PAUSE) {
501                 _I("auto brightness paused!");
502                 disconnect_sfsvc();
503                 backlight_ops.hbm_off();
504                 lbm_state = 0;
505         } else {
506                 disconnect_sfsvc();
507                 backlight_ops.hbm_off();
508                 lbm_state = 0;
509                 /* escape dim state if it's in low battery.*/
510                 set_brtch_state();
511
512                 ret = get_setting_brightness(&default_brt);
513                 if (ret != 0 || (default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS)) {
514                         _I("fail to read vconf value for brightness");
515                         brt = PM_DEFAULT_BRIGHTNESS;
516                         if(default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS)
517                                 vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
518                         default_brt = brt;
519                 }
520
521                 backlight_ops.set_default_brt(default_brt);
522                 backlight_ops.update();
523         }
524
525         return 0;
526 }
527
528 static void set_alc_function(keynode_t *key_nodes, void *data)
529 {
530         int status, ret;
531
532         if (key_nodes == NULL) {
533                 _E("wrong parameter, key_nodes is null");
534                 return;
535         }
536
537         status = vconf_keynode_get_int(key_nodes);
538
539         switch (status) {
540         case SETTING_BRIGHTNESS_AUTOMATIC_OFF:
541         case SETTING_BRIGHTNESS_AUTOMATIC_ON:
542         case SETTING_BRIGHTNESS_AUTOMATIC_PAUSE:
543                 ret = set_autobrightness_state(status);
544                 _D("set auto brightness : %d", ret);
545                 break;
546         default:
547                 _E("invalid value! %d", status);
548         }
549 }
550
551 static bool check_sfsvc(void* data)
552 {
553         /* this function will return opposite value for re-callback in fail */
554         int vconf_auto;
555         int sf_state = 0;
556
557         _I("register sfsvc");
558
559         vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &vconf_auto);
560         if (vconf_auto == SETTING_BRIGHTNESS_AUTOMATIC_ON) {
561                 if(connect_sfsvc() < 0)
562                         return EINA_TRUE;
563
564                 /* change alc action func */
565                 if (_default_action == NULL)
566                         _default_action = states[S_NORMAL].action;
567                 states[S_NORMAL].action = alc_action;
568                 alc_timeout_id =
569                     ecore_timer_add(display_conf.lightsensor_interval,
570                             (Ecore_Task_Cb)alc_handler, NULL);
571                 if (alc_timeout_id > 0)
572                         return EINA_FALSE;
573                 disconnect_sfsvc();
574                 return EINA_TRUE;
575         }
576         _I("change vconf value before registering sfsvc");
577         return EINA_FALSE;
578 }
579
580 static void set_alc_automatic_brt(keynode_t *key_nodes, void *data)
581 {
582         if (key_nodes == NULL) {
583                 _E("wrong parameter, key_nodes is null");
584                 return;
585         }
586         automatic_brt = vconf_keynode_get_int(key_nodes) / AUTOMATIC_DEVIDE_VAL;
587         _D("automatic brt : %d", automatic_brt);
588
589         alc_update_brt(true);
590 }
591
592 static Eina_Bool update_handler(void* data)
593 {
594         int ret, on;
595
596         update_timeout = NULL;
597
598         if (pm_cur_state != S_NORMAL)
599                 return EINA_FALSE;
600
601         if (!get_hallic_open())
602                 return EINA_FALSE;
603
604         ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &on);
605         if (ret < 0 || on != SETTING_BRIGHTNESS_AUTOMATIC_ON)
606                 return EINA_FALSE;
607
608         _D("auto brightness is working!");
609         alc_update_brt(true);
610
611         return EINA_FALSE;
612 }
613
614 static void update_auto_brightness(bool update)
615 {
616         if (update_timeout) {
617                 ecore_timer_del(update_timeout);
618                 update_timeout = NULL;
619         }
620
621         if (update) {
622                 update_timeout = ecore_timer_add(AUTOMATIC_DELAY_TIME,
623                     update_handler, NULL);
624         }
625 }
626
627 static int prepare_lsensor(void *data)
628 {
629         int status, ret;
630         int sf_state = 0;
631         int brt = -1;
632
633         ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status);
634
635         if (ret == 0 && status == SETTING_BRIGHTNESS_AUTOMATIC_ON)
636                 set_autobrightness_state(status);
637
638         /* add auto_brt_setting change handler */
639         vconf_notify_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
640                                  set_alc_function, NULL);
641
642         vconf_get_int(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS, &brt);
643         if (brt < PM_MIN_BRIGHTNESS || brt > PM_MAX_BRIGHTNESS) {
644                 _E("Failed to get automatic brightness!");
645         } else {
646                 automatic_brt = brt / AUTOMATIC_DEVIDE_VAL;
647                 _I("automatic brt init success %d", automatic_brt);
648         }
649
650         vconf_notify_key_changed(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS,
651                                 set_alc_automatic_brt, NULL);
652
653         return 0;
654 }
655
656 static void update_brightness_direct(void)
657 {
658         int ret, status;
659
660         ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status);
661         if (ret == 0 && status == SETTING_BRIGHTNESS_AUTOMATIC_ON)
662                 alc_update_brt(true);
663 }
664
665 static int set_autobrightness_min(int val, char *name)
666 {
667         if (!name)
668                 return -EINVAL;
669
670         if (val < PM_MIN_BRIGHTNESS || val > PM_MAX_BRIGHTNESS)
671                 return -EINVAL;
672
673         min_brightness = val;
674
675         if (min_brightness_name) {
676                 free(min_brightness_name);
677                 min_brightness_name = 0;
678         }
679         min_brightness_name = strndup(name, strlen(name));
680
681         update_brightness_direct();
682
683         _I("auto brightness min value changed! (%d, %s)",
684             min_brightness, min_brightness_name);
685
686         return 0;
687 }
688
689 static int reset_autobrightness_min(char *name, enum watch_id id)
690 {
691         if (!name)
692                 return -EINVAL;
693
694         if (!min_brightness_name)
695                 return -EINVAL;
696
697         if (strcmp(name, min_brightness_name))
698                 return -EINVAL;
699
700         _I("change to default %d -> %d, %s", min_brightness,
701             PM_MIN_BRIGHTNESS, min_brightness_name);
702         min_brightness = PM_MIN_BRIGHTNESS;
703         if (min_brightness_name) {
704                 free(min_brightness_name);
705                 min_brightness_name = 0;
706         }
707
708         update_brightness_direct();
709
710         return 0;
711 }
712
713 static int lcd_changed_cb(void *data)
714 {
715         int lcd_state = (int)data;
716
717         if (lcd_state == S_LCDOFF && alc_timeout_id > 0) {
718                 ecore_timer_del(alc_timeout_id);
719                 alc_timeout_id = NULL;
720         }
721
722         return 0;
723 }
724
725 static int lbm_load_config(struct parse_result *result, void *user_data)
726 {
727         struct lbm_config *c = user_data;
728
729         _D("%s,%s,%s", result->section, result->name, result->value);
730
731         if (!c)
732                 return -EINVAL;
733
734         if (!MATCH(result->section, "LBM"))
735                 return 0;
736
737         if (MATCH(result->name, "on")) {
738                 SET_CONF(c->on, atoi(result->value));
739                 _D("on lux is %d", c->on);
740         } else if (MATCH(result->name, "off")) {
741                 SET_CONF(c->off, atoi(result->value));
742                 _D("off lux is %d", c->off);
743         } else if (MATCH(result->name, "on_count")) {
744                 SET_CONF(c->on_count, atoi(result->value));
745                 _D("on count is %d", c->on_count);
746         } else if (MATCH(result->name, "off_count")) {
747                 SET_CONF(c->off_count, atoi(result->value));
748                 _D("off count is %d", c->off_count);
749         }
750
751         return 0;
752 }
753
754 static void auto_brightness_init(void *data)
755 {
756         int ret;
757
758         display_info.update_auto_brightness = update_auto_brightness;
759         display_info.set_autobrightness_min = set_autobrightness_min;
760         display_info.reset_autobrightness_min = reset_autobrightness_min;
761
762         /* load configutation */
763         ret = config_parse(BOARD_CONF_FILE, lbm_load_config, &lbm_conf);
764         if (ret < 0)
765                 _W("Failed to load %s, %s Use default value!",
766                     BOARD_CONF_FILE, ret);
767
768         register_notifier(DEVICE_NOTIFIER_LCD, lcd_changed_cb);
769
770         prepare_lsensor(NULL);
771 }
772
773 static void auto_brightness_exit(void *data)
774 {
775         vconf_ignore_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
776             set_alc_function);
777
778         vconf_ignore_key_changed(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS,
779             set_alc_automatic_brt);
780
781         unregister_notifier(DEVICE_NOTIFIER_LCD, lcd_changed_cb);
782
783         set_autobrightness_state(SETTING_BRIGHTNESS_AUTOMATIC_OFF);
784 }
785
786 static const struct display_ops display_autobrightness_ops = {
787         .name     = "auto-brightness",
788         .init     = auto_brightness_init,
789         .exit     = auto_brightness_exit,
790 };
791
792 DISPLAY_OPS_REGISTER(&display_autobrightness_ops)
793