1671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru/*
2671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * Copyright (C) 2012 The Android Open Source Project
3671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru *
4671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License");
5671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * you may not use this file except in compliance with the License.
6671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * You may obtain a copy of the License at
7671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru *
8671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
9671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru *
10671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
11671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
12671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * See the License for the specific language governing permissions and
14671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * limitations under the License.
15671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru */
16671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
17671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#define LOG_TAG "lights"
18671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#define LOGE ALOGE
19671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
20671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <cutils/log.h>
21671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
22671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <stdint.h>
23671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <string.h>
24671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <unistd.h>
25671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <errno.h>
26671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <fcntl.h>
27671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
28671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <sys/ioctl.h>
29671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <sys/types.h>
30671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
31671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <hardware/lights.h>
32671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru#include <hardware/hardware.h>
33671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
34671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustatic pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
35671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
36671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustatic int write_int(char const *path, int value)
37671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru{
38671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int fd;
39671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	static int already_warned = -1;
40671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	fd = open(path, O_RDWR);
41671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	if (fd >= 0) {
42671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		char buffer[20];
43671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int bytes = sprintf(buffer, "%d\n", value);
44671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int amt = write(fd, buffer, bytes);
45671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		close(fd);
46671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		return amt == -1 ? -errno : 0;
47671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	} else {
48671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		if (already_warned == -1) {
49671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru			LOGE("write_int failed to open %s\n", path);
50671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru			already_warned = 1;
51671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		}
52671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		return -errno;
53671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	}
54671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru}
55671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
56671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustatic int rgb_to_brightness(struct light_state_t const *state)
57671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru{
58671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int color = state->color & 0x00ffffff;
59671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	return ((77 * ((color >> 16) & 0x00ff))
60671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		+ (150 * ((color >> 8) & 0x00ff)) +
61671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		(29 * (color & 0x00ff))) >> 8;
62671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru}
63671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
64671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustatic int set_light_backlight(struct light_device_t *dev,
65671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru			       struct light_state_t const *state)
66671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru{
67671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int err = 0;
68671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int brightness = rgb_to_brightness(state);
69671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	//+++ power save
70671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int range_num = 1;
71671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int old_brightness_range_indexs[] = {160,255};
72671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int new_brightness_range_indexs[] = {160,182};
73671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int old_brightness = brightness;
74671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int i=0;
75671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int old_brightness_in_range = -1;// 0:1~10 , 1:10~102 , 2:102~255
76671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	for(i=0;i<range_num;i++){
77671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int t_range_min = old_brightness_range_indexs[i];
78671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int t_range_max = old_brightness_range_indexs[i+1];
79671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		if( brightness>=t_range_min && brightness<=t_range_max){
80671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru			old_brightness_in_range = i;
81671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru			break;
82671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		}
83671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	}
84671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	if(old_brightness_in_range>=0){
85671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int old_br_min = old_brightness_range_indexs[old_brightness_in_range];
86671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int olb_br_max = old_brightness_range_indexs[old_brightness_in_range+1];
87671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int new_br_min = new_brightness_range_indexs[old_brightness_in_range];
88671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int new_br_max = new_brightness_range_indexs[old_brightness_in_range+1];
89671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		int new_brightness = new_br_min +
90671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru				(new_br_max-new_br_min)*(old_brightness-old_br_min)/(olb_br_max-old_br_min);
91671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		brightness = new_brightness;
92671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	}
93671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	//---
94671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	pthread_mutex_lock(&g_lock);
95671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	err = write_int("/sys/class/backlight/pwm-backlight/brightness",
96671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru			brightness);
97671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	pthread_mutex_unlock(&g_lock);
98671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
99671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	return err;
100671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru}
101671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
102671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru/** Close the lights device */
103671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustatic int close_lights(struct light_device_t *dev)
104671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru{
105671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	if (dev)
106671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		free(dev);
107671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	return 0;
108671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru}
109671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
110671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru/** Open a new instance of a lights device using name */
111671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustatic int open_lights(const struct hw_module_t *module, char const *name,
112671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		       struct hw_device_t **device)
113671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru{
114671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	pthread_t lighting_poll_thread;
115671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
116671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	int (*set_light) (struct light_device_t *dev,
117671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru			  struct light_state_t const *state);
118671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
119671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
120671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		set_light = set_light_backlight;
121671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	else
122671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru		return -EINVAL;
123671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
124671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	pthread_mutex_init(&g_lock, NULL);
125671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
126671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	struct light_device_t *dev = malloc(sizeof(struct light_device_t));
127671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	memset(dev, 0, sizeof(*dev));
128671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
129671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	dev->common.tag = HARDWARE_DEVICE_TAG;
130671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	dev->common.version = 0;
131671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	dev->common.module = (struct hw_module_t *)module;
132671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	dev->common.close = (int (*)(struct hw_device_t *))close_lights;
133671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	dev->set_light = set_light;
134671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
135671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	*device = (struct hw_device_t *)dev;
136671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
137671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	return 0;
138671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru}
139671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
140671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustatic struct hw_module_methods_t lights_methods =
141671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru{
142671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.open =  open_lights,
143671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru};
144671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru
145671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru/*
146671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru * The backlight Module
147671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru */
148671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Querustruct hw_module_t HAL_MODULE_INFO_SYM =
149671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru{
150671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.tag = HARDWARE_MODULE_TAG,
151671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.version_major = 1,
152671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.version_minor = 0,
153671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.id = LIGHTS_HARDWARE_MODULE_ID,
154671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.name = "NVIDIA Kai lights module",
155671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.author = "NVIDIA",
156671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru	.methods = &lights_methods,
157671476b0aa1b2b8a3d0bd0b1adb800a759030d13Jean-Baptiste Queru};
158