2 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 #include <linux/module.h>
20 #include <linux/types.h>
21 #include <linux/init.h>
22 #include <linux/device.h>
24 #include <linux/err.h>
25 #ifdef CONFIG_ADSP_FACTORY
26 #include <linux/kernel.h>
29 #ifdef CONFIG_SLEEP_MONITOR
30 #include <linux/power/sleep_monitor.h>
31 #include "sensors_core.h"
34 struct class *sensors_class;
35 struct class *sensors_event_class;
36 static struct device *symlink_dev;
37 static atomic_t sensor_count;
51 * definitions of placement of sensors
52 * P0 - P3: view from top of device
53 * P4 - P7: view from bottom of device
56 * Y of device aligned with Y of OS (i.e: Android)
66 * Y of device aligned with Y of OS (i.e.: Android)
67 * rotated by 90 degrees clockwise
77 * Y of device aligned with Y of OS (i.e.: Android)
78 * rotated by 180 degrees clockwise
89 * Y of device aligned with Y of OS (i.e.: Android)
90 * rotated by 270 degrees clockwise
101 #define MAX_AXIS_REMAP_TAB_SZ 8 /* P0~P7 */
103 static const struct axis_remap axis_table[MAX_AXIS_REMAP_TAB_SZ] = {
104 /* src_x src_y src_z sign_x sign_y sign_z */
105 { 0, 1, 2, 1, 1, 1 }, /* P0 */
106 { 1, 0, 2, 1, -1, 1 }, /* P1 */
107 { 0, 1, 2, -1, -1, 1 }, /* P2 */
108 { 1, 0, 2, -1, 1, 1 }, /* P3 */
109 { 0, 1, 2, -1, 1, -1 }, /* P4 */
110 { 1, 0, 2, -1, -1, -1 }, /* P5 */
111 { 0, 1, 2, 1, -1, -1 }, /* P6 */
112 { 1, 0, 2, 1, 1, -1 }, /* P7 */
115 void remap_sensor_data(s16 *val, u32 idx)
119 if (idx < MAX_AXIS_REMAP_TAB_SZ) {
120 tmp[0] = val[axis_table[idx].src_x] * axis_table[idx].sign_x;
121 tmp[1] = val[axis_table[idx].src_y] * axis_table[idx].sign_y;
122 tmp[2] = val[axis_table[idx].src_z] * axis_table[idx].sign_z;
124 memcpy(val, &tmp, sizeof(tmp));
128 void remap_sensor_data_32(int *val, u32 idx)
132 if (idx < MAX_AXIS_REMAP_TAB_SZ) {
133 tmp[0] = val[axis_table[idx].src_x] * axis_table[idx].sign_x;
134 tmp[1] = val[axis_table[idx].src_y] * axis_table[idx].sign_y;
135 tmp[2] = val[axis_table[idx].src_z] * axis_table[idx].sign_z;
137 memcpy(val, &tmp, sizeof(tmp));
141 int sensors_create_symlink(struct kobject *target, const char *name)
145 if (symlink_dev == NULL) {
146 pr_err("%s, symlink_dev is NULL!!!\n", __func__);
150 err = sysfs_create_link(&symlink_dev->kobj, target, name);
152 pr_err("%s, %s failed!(%d)\n", __func__, name, err);
159 void sensors_remove_symlink(struct kobject *target, const char *name)
161 if (symlink_dev == NULL)
162 pr_err("%s, symlink_dev is NULL!!!\n", __func__);
164 sysfs_delete_link(&symlink_dev->kobj, target, name);
167 static void set_sensor_attr(struct device *dev,
168 struct device_attribute *attributes[])
172 for (i = 0; attributes[i] != NULL; i++)
173 if ((device_create_file(dev, attributes[i])) < 0)
174 pr_err("[SENSOR CORE] fail device_create_file"\
175 "(dev, attributes[%d])\n", i);
178 int sensors_register(struct device *dev, void *drvdata,
179 struct device_attribute *attributes[], char *name)
183 if (sensors_class == NULL) {
184 sensors_class = class_create(THIS_MODULE, "sensors");
185 if (IS_ERR(sensors_class))
186 return PTR_ERR(sensors_class);
189 dev = device_create(sensors_class, NULL, 0, drvdata, "%s", name);
192 pr_err("[SENSORS CORE] device_create failed![%d]\n", ret);
196 set_sensor_attr(dev, attributes);
197 atomic_inc(&sensor_count);
202 void sensors_unregister(struct device *dev,
203 struct device_attribute *attributes[])
207 for (i = 0; attributes[i] != NULL; i++)
208 device_remove_file(dev, attributes[i]);
210 #ifdef CONFIG_SLEEP_MONITOR
211 u8 sensors_enable_mask = 0;
212 void sensors_set_enable_mask(int enable, int offset_bit) {
214 sensors_enable_mask = sensors_enable_mask | (enable << offset_bit);
216 sensors_enable_mask = sensors_enable_mask & (~(0x01 << offset_bit));
218 pr_info("%s: enabled sensors mask = 0x%x", __func__, sensors_enable_mask);
221 static int sensors_get_sleep_monitor_cb(void *priv, unsigned int *raw_val, int check_level, int caller_type)
223 int ret = DEVICE_POWER_OFF;
224 * raw_val = sensors_enable_mask;
226 switch (check_level) {
228 case SLEEP_MONITOR_CHECK_SOFT:
229 case SLEEP_MONITOR_CHECK_HARD:
231 if (*raw_val == DEVICE_POWER_OFF_MASK)
232 ret = DEVICE_POWER_OFF;
233 else if (*raw_val == DEVICE_ON_ACTIVE2_MASK)
234 ret = DEVICE_ON_ACTIVE2;
236 ret = DEVICE_ON_ACTIVE2;
242 static struct sleep_monitor_ops sensors_sleep_monitor_ops = {
243 .read_cb_func = sensors_get_sleep_monitor_cb,
247 void destroy_sensor_class(void)
249 #ifdef CONFIG_ADSP_FACTORY
251 class_destroy(sensors_class);
252 sensors_class = NULL;
255 if (sensors_event_class) {
256 device_destroy(sensors_event_class, symlink_dev->devt);
257 class_destroy(sensors_event_class);
259 sensors_event_class = NULL;
263 #ifdef CONFIG_ADSP_FACTORY
265 extern struct class *get_adsp_sensor_class(void);
268 static int __init sensors_class_init(void)
270 pr_info("[SENSORS CORE] sensors_class_init\n");
272 #ifdef CONFIG_ADSP_FACTORY
273 sensors_class = get_adsp_sensor_class();
275 sensors_class = class_create(THIS_MODULE, "sensors");
276 if (IS_ERR(sensors_class)) {
277 pr_err("%s, create sensors_class is failed.(err=%ld)\n",
278 __func__, IS_ERR(sensors_class));
279 return PTR_ERR(sensors_class);
282 /* For symbolic link */
283 sensors_event_class = class_create(THIS_MODULE, "sensor_event");
284 if (IS_ERR(sensors_event_class)) {
285 pr_err("%s, create sensors_class is failed.(err=%ld)\n",
286 __func__, IS_ERR(sensors_event_class));
287 class_destroy(sensors_class);
288 return PTR_ERR(sensors_event_class);
291 symlink_dev = device_create(sensors_event_class, NULL, 0, NULL,
293 if (IS_ERR(symlink_dev)) {
294 pr_err("[SENSORS CORE] symlink_dev create failed![%ld]\n",
295 IS_ERR(symlink_dev));
297 class_destroy(sensors_class);
298 class_destroy(sensors_event_class);
299 return PTR_ERR(symlink_dev);
302 atomic_set(&sensor_count, 0);
303 sensors_class->dev_uevent = NULL;
305 #ifdef CONFIG_SLEEP_MONITOR
306 sleep_monitor_register_ops(NULL, &sensors_sleep_monitor_ops, SLEEP_MONITOR_SENSOR);
311 static void __exit sensors_class_exit(void)
313 if (sensors_class || sensors_event_class) {
314 class_destroy(sensors_class);
315 sensors_class = NULL;
316 class_destroy(sensors_event_class);
317 sensors_event_class = NULL;
319 #ifdef CONFIG_SLEEP_MONITOR
320 sleep_monitor_unregister_ops(SLEEP_MONITOR_SENSOR);
324 subsys_initcall(sensors_class_init);
325 module_exit(sensors_class_exit);
327 MODULE_DESCRIPTION("Universal sensors core class");
328 MODULE_AUTHOR("Samsung Electronics");
329 MODULE_LICENSE("GPL");