add new driver for all sensors
This commit is contained in:
parent
2543880c8e
commit
20f9121ccf
32 changed files with 5045 additions and 27 deletions
|
|
@ -90,12 +90,34 @@ struct gsensor_platform_data {
|
|||
void (*exit_platform_hw)(void);
|
||||
};
|
||||
|
||||
|
||||
struct akm8975_platform_data {
|
||||
short m_layout[4][3][3];
|
||||
char project_name[64];
|
||||
int gpio_DRDY;
|
||||
};
|
||||
|
||||
struct sensor_platform_data {
|
||||
int type;
|
||||
int irq;
|
||||
int power_pin;
|
||||
int reset_pin;
|
||||
int irq_enable; //if irq_enable=1 then use irq else use polling
|
||||
int poll_delay_ms; //polling
|
||||
int x_min; //filter
|
||||
int y_min;
|
||||
int z_min;
|
||||
unsigned char address;
|
||||
signed char orientation[9];
|
||||
short m_layout[4][3][3];
|
||||
char project_name[64];
|
||||
int (*init_platform_hw)(void);
|
||||
void (*exit_platform_hw)(void);
|
||||
int (*power_on)(void);
|
||||
int (*power_off)(void);
|
||||
};
|
||||
|
||||
|
||||
struct goodix_platform_data {
|
||||
int model ;
|
||||
int rest_pin;
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ source "drivers/input/jogball/Kconfig"
|
|||
|
||||
source "drivers/input/lightsensor/Kconfig"
|
||||
|
||||
source "drivers/input/sensors/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -28,5 +28,7 @@ obj-$(CONFIG_INPUT_JOGBALL) += jogball/
|
|||
obj-$(CONFIG_LIGHT_SENSOR_DEVICE) += lightsensor/
|
||||
obj-$(CONFIG_MAG_SENSORS) += magnetometer/
|
||||
|
||||
obj-$(CONFIG_SENSOR_DEVICE) += sensors/
|
||||
|
||||
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
|
||||
obj-$(CONFIG_INPUT_KEYRESET) += keyreset.o
|
||||
|
|
|
|||
19
drivers/input/sensors/Kconfig
Executable file
19
drivers/input/sensors/Kconfig
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# all sensors drivers configuration
|
||||
#
|
||||
|
||||
comment "handle all sensors"
|
||||
|
||||
menuconfig SENSOR_DEVICE
|
||||
tristate "handle gsensor,compass,gyroscope,lsensor psensor etc"
|
||||
|
||||
if SENSOR_DEVICE
|
||||
|
||||
source "drivers/input/sensors/accel/Kconfig"
|
||||
source "drivers/input/sensors/compass/Kconfig"
|
||||
source "drivers/input/sensors/gyro/Kconfig"
|
||||
source "drivers/input/sensors/lsensor/Kconfig"
|
||||
source "drivers/input/sensors/psensor/Kconfig"
|
||||
source "drivers/input/sensors/temperature/Kconfig"
|
||||
|
||||
endif
|
||||
10
drivers/input/sensors/Makefile
Executable file
10
drivers/input/sensors/Makefile
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
# sensor drivers
|
||||
obj-$(CONFIG_GSENSOR_DEVICE) += accel/
|
||||
obj-$(CONFIG_COMPASS_DEVICE) += compass/
|
||||
obj-$(CONFIG_GYROSCOPE_DEVICE) += gyro/
|
||||
obj-$(CONFIG_LIGHT_DEVICE) += lsensor/
|
||||
obj-$(CONFIG_PROXIMITY_DEVICE) += psensor/
|
||||
|
||||
|
||||
obj-$(CONFIG_SENSOR_DEVICE) += sensor-i2c.o
|
||||
obj-$(CONFIG_SENSOR_DEVICE) += sensor-dev.o
|
||||
36
drivers/input/sensors/accel/Kconfig
Executable file
36
drivers/input/sensors/accel/Kconfig
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# gsensor drivers configuration
|
||||
#
|
||||
|
||||
menuconfig GSENSOR_DEVICE
|
||||
bool "g_sensor device support"
|
||||
help
|
||||
Enable this to be able to choose the drivers for controlling the
|
||||
g_sensor on some platforms, for example on PDAs.
|
||||
|
||||
if GSENSOR_DEVICE
|
||||
config GS_MMA8452
|
||||
bool "gsensor mma8452"
|
||||
help
|
||||
To have support for your specific gsesnor you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config GS_KXTIK
|
||||
bool "gsensor kxtik"
|
||||
help
|
||||
To have support for your specific gsesnor you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config GS_LIS3DH
|
||||
bool "gsensor lis3dh"
|
||||
help
|
||||
To have support for your specific gsesnor you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config GS_BMA023
|
||||
bool "gsensor bma023"
|
||||
help
|
||||
To have support for your specific gsesnor you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
endif
|
||||
|
||||
3
drivers/input/sensors/accel/Makefile
Executable file
3
drivers/input/sensors/accel/Makefile
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
obj-$(CONFIG_GS_KXTIK) += kxtik.o
|
||||
obj-$(CONFIG_GS_MMA8452) += mma8452.o
|
||||
270
drivers/input/sensors/accel/kxtik.c
Executable file
270
drivers/input/sensors/accel/kxtik.c
Executable file
|
|
@ -0,0 +1,270 @@
|
|||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/kxtik.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_ACCEL
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
status = KXTIK_ENABLE; //kxtik
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~KXTIK_ENABLE; //kxtik
|
||||
sensor->ops->ctrl_data &= status;
|
||||
}
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
result = sensor_write_reg(client, KXTIK_DATA_CTRL_REG, KXTIK_ODR400F);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(sensor->pdata->irq_enable) //open interrupt
|
||||
{
|
||||
result = sensor_write_reg(client, KXTIK_INT_CTRL_REG1, 0x34);//enable int,active high,need read INT_REL
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
sensor->ops->ctrl_data = (KXTIK_RES_12BIT | KXTIK_G_2G);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
|
||||
{
|
||||
s64 result;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
//int precision = sensor->ops->precision;
|
||||
switch (sensor->devid) {
|
||||
case KXTIK_DEVID:
|
||||
result = (((int)high_byte << 8) | ((int)low_byte ))>>4;
|
||||
if (result < KXTIK_BOUNDARY)
|
||||
result = result* KXTIK_GRAVITY_STEP;
|
||||
else
|
||||
result = ~( ((~result & (0x7fff>>(16-KXTIK_PRECISION)) ) + 1)
|
||||
* KXTIK_GRAVITY_STEP) + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "%s: devid wasn't set correctly\n",__func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
/* Report acceleration sensor information */
|
||||
input_report_abs(sensor->input_dev, ABS_X, axis->x);
|
||||
input_report_abs(sensor->input_dev, ABS_Y, axis->y);
|
||||
input_report_abs(sensor->input_dev, ABS_Z, axis->z);
|
||||
input_sync(sensor->input_dev);
|
||||
DBG("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GSENSOR_MIN 10
|
||||
static int sensor_report_value(struct i2c_client *client, unsigned char *buffer, int length)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_platform_data *pdata = sensor->pdata;
|
||||
int ret = 0;
|
||||
int x,y,z;
|
||||
struct sensor_axis axis;
|
||||
char buffer[6] = {0};
|
||||
|
||||
if(sensor->ops->read_len < 6) //sensor->ops->read_len = 6
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, 6);
|
||||
|
||||
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
|
||||
do {
|
||||
*buffer = sensor->ops->read_reg;
|
||||
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} while (0);
|
||||
|
||||
//this gsensor need 6 bytes buffer
|
||||
x = sensor_convert_data(sensor->client, buffer[1], buffer[0]); //buffer[1]:high bit
|
||||
y = sensor_convert_data(sensor->client, buffer[3], buffer[2]);
|
||||
z = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
|
||||
|
||||
axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
|
||||
axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;
|
||||
axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
|
||||
|
||||
DBG( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
|
||||
|
||||
//Report event only while value is changed to save some power
|
||||
if((abs(sensor->axis.x - axis.x) > GSENSOR_MIN) || (abs(sensor->axis.y - axis.y) > GSENSOR_MIN) || (abs(sensor->axis.z - axis.z) > GSENSOR_MIN))
|
||||
{
|
||||
gsensor_report_value(client, &axis);
|
||||
|
||||
/* »¥³âµØ»º´æÊý¾Ý. */
|
||||
mutex_lock(&(sensor->data_mutex) );
|
||||
sensor->axis = axis;
|
||||
mutex_unlock(&(sensor->data_mutex) );
|
||||
}
|
||||
|
||||
if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
|
||||
{
|
||||
|
||||
ret= sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
if(ret)
|
||||
{
|
||||
printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct sensor_operate gsensor_ops = {
|
||||
.name = "kxtik",
|
||||
.type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct
|
||||
.id_i2c = ACCEL_ID_KXTIK, //i2c id number
|
||||
.read_reg = KXTIK_XOUT_L, //read data
|
||||
.read_len = 6, //data length
|
||||
.id_reg = KXTIK_WHO_AM_I, //read device id from this register
|
||||
.id_data = KXTIK_DEVID, //device id
|
||||
.precision = KXTIK_PRECISION, //12 bits
|
||||
.ctrl_reg = KXTIK_CTRL_REG1, //enable or disable
|
||||
.int_status_reg = KXTIK_INT_REL, //intterupt status register
|
||||
.range = {-KXTIK_RANGE,KXTIK_RANGE}, //range
|
||||
.trig = IRQF_TRIGGER_LOW|IRQF_ONESHOT,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *gsensor_get_ops(void)
|
||||
{
|
||||
return &gsensor_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gsensor_get_ops);
|
||||
|
||||
static int __init gsensor_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = gsensor_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, gsensor_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gsensor_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = gsensor_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, gsensor_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(gsensor_init);
|
||||
module_exit(gsensor_exit);
|
||||
|
||||
|
||||
308
drivers/input/sensors/accel/mma8452.c
Executable file
308
drivers/input/sensors/accel/mma8452.c
Executable file
|
|
@ -0,0 +1,308 @@
|
|||
/* drivers/input/sensors/access/mma8452.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/mma8452.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_ACCEL
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
|
||||
#define MMA8451_DEVID 0x1a
|
||||
#define MMA8452_DEVID 0x2a
|
||||
#define MMA8453_DEVID 0x3a
|
||||
|
||||
#define MMA8452_ENABLE 1
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
status = MMA8452_ENABLE; //mma8452
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~MMA8452_ENABLE; //mma8452
|
||||
sensor->ops->ctrl_data &= status;
|
||||
}
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
int tmp;
|
||||
int ret = 0;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
ret = sensor->ops->active(client,0,0);
|
||||
if(ret)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
/* disable FIFO FMODE = 0*/
|
||||
ret = sensor_write_reg(client,MMA8452_REG_F_SETUP,0);
|
||||
DBG("%s: MMA8452_REG_F_SETUP:%x\n",__func__, sensor_read_reg(client,MMA8452_REG_F_SETUP));
|
||||
|
||||
/* set full scale range to 2g */
|
||||
ret = sensor_write_reg(client,MMA8452_REG_XYZ_DATA_CFG,0);
|
||||
DBG("%s: MMA8452_REG_XYZ_DATA_CFG:%x\n",__func__, sensor_read_reg(client,MMA8452_REG_XYZ_DATA_CFG));
|
||||
|
||||
/* set bus 8bit/14bit(FREAD = 1,FMODE = 0) ,data rate*/
|
||||
tmp = (MMA8452_RATE_12P5<< MMA8452_RATE_SHIFT) | FREAD_MASK;
|
||||
ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG1,tmp);
|
||||
|
||||
sensor->ops->ctrl_data = tmp;
|
||||
|
||||
DBG("mma8452 MMA8452_REG_CTRL_REG1:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG1));
|
||||
|
||||
DBG("mma8452 MMA8452_REG_SYSMOD:%x\n",sensor_read_reg(client,MMA8452_REG_SYSMOD));
|
||||
|
||||
ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG3,5);
|
||||
DBG("mma8452 MMA8452_REG_CTRL_REG3:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG3));
|
||||
|
||||
ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG4,1);
|
||||
DBG("mma8452 MMA8452_REG_CTRL_REG4:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG4));
|
||||
|
||||
ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG5,1);
|
||||
DBG("mma8452 MMA8452_REG_CTRL_REG5:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG5));
|
||||
|
||||
DBG("mma8452 MMA8452_REG_SYSMOD:%x\n",sensor_read_reg(client,MMA8452_REG_SYSMOD));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
|
||||
{
|
||||
s64 result;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
//int precision = sensor->ops->precision;
|
||||
switch (sensor->devid) {
|
||||
case MMA8451_DEVID:
|
||||
swap(high_byte,low_byte);
|
||||
result = ((int)high_byte << (MMA8451_PRECISION-8))
|
||||
| ((int)low_byte >> (16-MMA8451_PRECISION));
|
||||
if (result < MMA8451_BOUNDARY)
|
||||
result = result* MMA8451_GRAVITY_STEP;
|
||||
else
|
||||
result = ~( ((~result & (0x7fff>>(16-MMA8451_PRECISION)) ) + 1)
|
||||
* MMA8451_GRAVITY_STEP) + 1;
|
||||
break;
|
||||
|
||||
case MMA8452_DEVID:
|
||||
swap(high_byte,low_byte);
|
||||
result = ((int)high_byte << (MMA8452_PRECISION-8))
|
||||
| ((int)low_byte >> (16-MMA8452_PRECISION));
|
||||
if (result < MMA8452_BOUNDARY)
|
||||
result = result* MMA8452_GRAVITY_STEP;
|
||||
else
|
||||
result = ~( ((~result & (0x7fff>>(16-MMA8452_PRECISION)) ) + 1)
|
||||
* MMA8452_GRAVITY_STEP) + 1;
|
||||
break;
|
||||
|
||||
case MMA8453_DEVID:
|
||||
swap(high_byte,low_byte);
|
||||
result = ((int)high_byte << (MMA8453_PRECISION-8))
|
||||
| ((int)low_byte >> (16-MMA8453_PRECISION));
|
||||
if (result < MMA8453_BOUNDARY)
|
||||
result = result* MMA8453_GRAVITY_STEP;
|
||||
else
|
||||
result = ~( ((~result & (0x7fff>>(16-MMA8453_PRECISION)) ) + 1)
|
||||
* MMA8453_GRAVITY_STEP) + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "%s: devid wasn't set correctly\n",__func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
/* Report acceleration sensor information */
|
||||
input_report_abs(sensor->input_dev, ABS_X, axis->x);
|
||||
input_report_abs(sensor->input_dev, ABS_Y, axis->y);
|
||||
input_report_abs(sensor->input_dev, ABS_Z, axis->z);
|
||||
input_sync(sensor->input_dev);
|
||||
DBG("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GSENSOR_MIN 10
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_platform_data *pdata = sensor->pdata;
|
||||
int ret = 0;
|
||||
int x,y,z;
|
||||
struct sensor_axis axis;
|
||||
char buffer[6] = {0};
|
||||
|
||||
if(sensor->ops->read_len < 6) //sensor->ops->read_len = 6
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, 6);
|
||||
|
||||
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
|
||||
do {
|
||||
*buffer = sensor->ops->read_reg;
|
||||
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} while (0);
|
||||
|
||||
|
||||
//this gsensor need 6 bytes buffer
|
||||
x = sensor_convert_data(sensor->client, buffer[1], buffer[0]); //buffer[1]:high bit
|
||||
y = sensor_convert_data(sensor->client, buffer[3], buffer[2]);
|
||||
z = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
|
||||
|
||||
axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
|
||||
axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;
|
||||
axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
|
||||
|
||||
DBG( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
|
||||
|
||||
//Report event only while value is changed to save some power
|
||||
if((abs(sensor->axis.x - axis.x) > GSENSOR_MIN) || (abs(sensor->axis.y - axis.y) > GSENSOR_MIN) || (abs(sensor->axis.z - axis.z) > GSENSOR_MIN))
|
||||
{
|
||||
gsensor_report_value(client, &axis);
|
||||
|
||||
/* »¥³âµØ»º´æÊý¾Ý. */
|
||||
mutex_lock(&(sensor->data_mutex) );
|
||||
sensor->axis = axis;
|
||||
mutex_unlock(&(sensor->data_mutex) );
|
||||
}
|
||||
|
||||
if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
|
||||
{
|
||||
|
||||
ret= sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
if(ret)
|
||||
{
|
||||
printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gsensor_ops = {
|
||||
.name = "mma8452",
|
||||
.type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct
|
||||
.id_i2c = ACCEL_ID_MMA845X, //i2c id number
|
||||
.read_reg = MMA8452_REG_X_OUT_MSB, //read data
|
||||
.read_len = 6, //data length
|
||||
.id_reg = MMA8452_REG_WHO_AM_I, //read device id from this register
|
||||
.id_data = MMA8452_DEVID, //device id
|
||||
.precision = MMA8452_PRECISION, //12 bit
|
||||
.ctrl_reg = MMA8452_REG_CTRL_REG1, //enable or disable
|
||||
.int_status_reg = MMA8452_REG_INTSRC, //intterupt status register
|
||||
.range = {-MMA845X_RANGE,MMA845X_RANGE}, //range
|
||||
.trig = IRQF_TRIGGER_LOW|IRQF_ONESHOT,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *gsensor_get_ops(void)
|
||||
{
|
||||
return &gsensor_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gsensor_get_ops);
|
||||
|
||||
static int __init gsensor_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = gsensor_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, gsensor_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gsensor_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = gsensor_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, gsensor_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(gsensor_init);
|
||||
module_exit(gsensor_exit);
|
||||
|
||||
|
||||
|
||||
37
drivers/input/sensors/compass/Kconfig
Executable file
37
drivers/input/sensors/compass/Kconfig
Executable file
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Magnetometer drivers configuration
|
||||
#
|
||||
|
||||
menuconfig COMPASS_DEVICE
|
||||
bool "Magnetometer sensors"
|
||||
help
|
||||
Say Y here, and a list of Magnetometer sensors drivers will be displayed.
|
||||
Everything that didn't fit into the other categories is here. This option
|
||||
doesn't affect the kernel.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
if COMPASS_DEVICE
|
||||
|
||||
config COMPASS_AK8975
|
||||
tristate "Asahi Kasei AK8975 3-Axis Magnetometer"
|
||||
depends on I2C
|
||||
help
|
||||
Say yes here to build support for Asahi Kasei AK8975 3-Axis
|
||||
Magnetometer.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called ak8975.
|
||||
|
||||
config COMPASS_MMC328X
|
||||
tristate "Mmc328x 3-Axis Magnetometer"
|
||||
depends on I2C
|
||||
help
|
||||
Say yes here to build support for mmc3280 3-Axis
|
||||
Magnetometer.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called mmc3280.
|
||||
|
||||
endif
|
||||
|
||||
6
drivers/input/sensors/compass/Makefile
Executable file
6
drivers/input/sensors/compass/Makefile
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Makefile for industrial I/O Magnetometer sensors
|
||||
#
|
||||
obj-$(CONFIG_COMPASS_AK8975) := ak8975.o
|
||||
obj-$(CONFIG_COMPASS_AK8973) := ak8973.o
|
||||
obj-$(CONFIG_COMPASS_MMC328X) := mmc328x.o
|
||||
753
drivers/input/sensors/compass/ak8975.c
Executable file
753
drivers/input/sensors/compass/ak8975.c
Executable file
|
|
@ -0,0 +1,753 @@
|
|||
/* drivers/input/sensors/access/akm8975.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/akm8975.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#define SENSOR_DATA_SIZE 8
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_COMPASS
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define AK8975_DEVICE_ID 0x48
|
||||
static struct i2c_client *this_client;
|
||||
|
||||
static atomic_t m_flag;
|
||||
static atomic_t a_flag;
|
||||
static atomic_t mv_flag;
|
||||
static atomic_t open_flag;
|
||||
static short akmd_delay = 100;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(open_wq);
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
status = AK8975_MODE_SNG_MEASURE;
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~AK8975_MODE_SNG_MEASURE;
|
||||
sensor->ops->ctrl_data &= status;
|
||||
}
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
|
||||
this_client = client;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
sensor->ops->ctrl_data = 0;
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
char buffer[8] = {0};
|
||||
unsigned char *stat;
|
||||
unsigned char *stat2;
|
||||
int ret = 0;
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
int i;
|
||||
#endif
|
||||
if(sensor->ops->read_len < 8) //sensor->ops->read_len = 8
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, 8);
|
||||
|
||||
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
|
||||
do {
|
||||
*buffer = sensor->ops->read_reg;
|
||||
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} while (0);
|
||||
|
||||
stat = &buffer[0];
|
||||
stat2 = &buffer[7];
|
||||
|
||||
/*
|
||||
* ST : data ready -
|
||||
* Measurement has been completed and data is ready to be read.
|
||||
*/
|
||||
if ((*stat & 0x01) != 0x01) {
|
||||
DBG(KERN_ERR "%s:ST is not set\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ST2 : data error -
|
||||
* occurs when data read is started outside of a readable period;
|
||||
* data read would not be correct.
|
||||
* Valid in continuous measurement mode only.
|
||||
* In single measurement mode this error should not occour but we
|
||||
* stil account for it and return an error, since the data would be
|
||||
* corrupted.
|
||||
* DERR bit is self-clearing when ST2 register is read.
|
||||
*/
|
||||
if (*stat2 & 0x04)
|
||||
{
|
||||
DBG(KERN_ERR "%s:compass data error\n",__func__);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* ST2 : overflow -
|
||||
* the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
|
||||
* This is likely to happen in presence of an external magnetic
|
||||
* disturbance; it indicates, the sensor data is incorrect and should
|
||||
* be ignored.
|
||||
* An error is returned.
|
||||
* HOFL bit clears when a new measurement starts.
|
||||
*/
|
||||
if (*stat2 & 0x08)
|
||||
{
|
||||
DBG(KERN_ERR "%s:compass data overflow\n",__func__);
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* »¥³âµØ»º´æÊý¾Ý. */
|
||||
mutex_lock(&sensor->data_mutex);
|
||||
memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);
|
||||
mutex_unlock(&sensor->data_mutex);
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
DBG("%s:",__func__);
|
||||
for(i=0; i<sensor->ops->read_len; i++)
|
||||
DBG("%d,",buffer[i]);
|
||||
DBG("\n");
|
||||
#endif
|
||||
|
||||
if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
|
||||
{
|
||||
|
||||
ret= sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
if(ret)
|
||||
{
|
||||
printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void compass_set_YPR(short *rbuf)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(this_client);
|
||||
|
||||
/* Report magnetic sensor information */
|
||||
if (atomic_read(&m_flag)) {
|
||||
input_report_abs(sensor->input_dev, ABS_RX, rbuf[0]);
|
||||
input_report_abs(sensor->input_dev, ABS_RY, rbuf[1]);
|
||||
input_report_abs(sensor->input_dev, ABS_RZ, rbuf[2]);
|
||||
input_report_abs(sensor->input_dev, ABS_RUDDER, rbuf[4]);
|
||||
DBG("%s:m_flag:x=%d,y=%d,z=%d,RUDDER=%d\n",__func__,rbuf[0], rbuf[1], rbuf[2], rbuf[4]);
|
||||
}
|
||||
|
||||
/* Report acceleration sensor information */
|
||||
if (atomic_read(&a_flag)) {
|
||||
input_report_abs(sensor->input_dev, ABS_X, rbuf[6]);
|
||||
input_report_abs(sensor->input_dev, ABS_Y, rbuf[7]);
|
||||
input_report_abs(sensor->input_dev, ABS_Z, rbuf[8]);
|
||||
input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[5]);
|
||||
|
||||
DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[6], rbuf[7], rbuf[8], rbuf[5]);
|
||||
}
|
||||
|
||||
/* Report magnetic vector information */
|
||||
if (atomic_read(&mv_flag)) {
|
||||
input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[9]);
|
||||
input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[10]);
|
||||
input_report_abs(sensor->input_dev, ABS_BRAKE, rbuf[11]);
|
||||
|
||||
DBG("%s:mv_flag:x=%d,y=%d,BRAKE=%d\n",__func__,rbuf[9], rbuf[10], rbuf[11]);
|
||||
}
|
||||
|
||||
input_sync(sensor->input_dev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int compass_aot_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(this_client);
|
||||
#endif
|
||||
int result = 0;
|
||||
int flag = 0;
|
||||
flag = atomic_read(&open_flag);
|
||||
if(!flag)
|
||||
{
|
||||
atomic_set(&open_flag, 1);
|
||||
wake_up(&open_wq);
|
||||
}
|
||||
|
||||
DBG("%s\n", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int compass_aot_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(this_client);
|
||||
#endif
|
||||
//struct i2c_client *client = this_client;
|
||||
int result = 0;
|
||||
int flag = 0;
|
||||
flag = atomic_read(&open_flag);
|
||||
if(flag)
|
||||
{
|
||||
atomic_set(&open_flag, 0);
|
||||
wake_up(&open_wq);
|
||||
}
|
||||
|
||||
DBG("%s\n", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* ioctl - I/O control */
|
||||
static long compass_aot_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(this_client);
|
||||
#endif
|
||||
void __user *argp = (void __user *)arg;
|
||||
int result = 0;
|
||||
short flag;
|
||||
|
||||
switch (cmd) {
|
||||
case ECS_IOCTL_APP_SET_MFLAG:
|
||||
case ECS_IOCTL_APP_SET_AFLAG:
|
||||
case ECS_IOCTL_APP_SET_MVFLAG:
|
||||
if (copy_from_user(&flag, argp, sizeof(flag))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
if (flag < 0 || flag > 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case ECS_IOCTL_APP_SET_DELAY:
|
||||
if (copy_from_user(&flag, argp, sizeof(flag))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ECS_IOCTL_APP_SET_MFLAG:
|
||||
atomic_set(&m_flag, flag);
|
||||
DBG("%s:ECS_IOCTL_APP_SET_MFLAG,flag=%d\n", __func__,flag);
|
||||
break;
|
||||
case ECS_IOCTL_APP_GET_MFLAG:
|
||||
flag = atomic_read(&m_flag);
|
||||
DBG("%s:ECS_IOCTL_APP_GET_MFLAG,flag=%d\n", __func__,flag);
|
||||
break;
|
||||
case ECS_IOCTL_APP_SET_AFLAG:
|
||||
atomic_set(&a_flag, flag);
|
||||
DBG("%s:ECS_IOCTL_APP_SET_AFLAG,flag=%d\n", __func__,flag);
|
||||
break;
|
||||
case ECS_IOCTL_APP_GET_AFLAG:
|
||||
flag = atomic_read(&a_flag);
|
||||
DBG("%s:ECS_IOCTL_APP_GET_AFLAG,flag=%d\n", __func__,flag);
|
||||
break;
|
||||
case ECS_IOCTL_APP_SET_MVFLAG:
|
||||
atomic_set(&mv_flag, flag);
|
||||
DBG("%s:ECS_IOCTL_APP_SET_MVFLAG,flag=%d\n", __func__,flag);
|
||||
break;
|
||||
case ECS_IOCTL_APP_GET_MVFLAG:
|
||||
flag = atomic_read(&mv_flag);
|
||||
DBG("%s:ECS_IOCTL_APP_GET_MVFLAG,flag=%d\n", __func__,flag);
|
||||
break;
|
||||
case ECS_IOCTL_APP_SET_DELAY:
|
||||
akmd_delay = flag;
|
||||
break;
|
||||
case ECS_IOCTL_APP_GET_DELAY:
|
||||
flag = akmd_delay;
|
||||
break;
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ECS_IOCTL_APP_GET_MFLAG:
|
||||
case ECS_IOCTL_APP_GET_AFLAG:
|
||||
case ECS_IOCTL_APP_GET_MVFLAG:
|
||||
case ECS_IOCTL_APP_GET_DELAY:
|
||||
if (copy_to_user(argp, &flag, sizeof(flag))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int compass_dev_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(this_client);
|
||||
#endif
|
||||
int result = 0;
|
||||
DBG("%s\n",__func__);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int compass_dev_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(this_client);
|
||||
#endif
|
||||
int result = 0;
|
||||
DBG("%s\n",__func__);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int compass_akm_set_mode(struct i2c_client *client, char mode)
|
||||
{
|
||||
struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
|
||||
int result = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case AK8975_MODE_SNG_MEASURE:
|
||||
case AK8975_MODE_SELF_TEST:
|
||||
case AK8975_MODE_FUSE_ACCESS:
|
||||
if(sensor->status_cur == SENSOR_OFF)
|
||||
{
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
//DBG("%s:enable irq=%d\n",__func__,client->irq);
|
||||
//enable_irq(client->irq);
|
||||
}
|
||||
else
|
||||
{
|
||||
schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_ON;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AK8975_MODE_POWERDOWN:
|
||||
if(sensor->status_cur == SENSOR_ON)
|
||||
{
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
//DBG("%s:disable irq=%d\n",__func__,client->irq);
|
||||
//disable_irq_nosync(client->irq);//disable irq
|
||||
}
|
||||
else
|
||||
cancel_delayed_work_sync(&sensor->delaywork);
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case AK8975_MODE_SNG_MEASURE:
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SNG_MEASURE);
|
||||
if(result)
|
||||
printk("%s:i2c error,mode=%d\n",__func__,mode);
|
||||
break;
|
||||
case AK8975_MODE_SELF_TEST:
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SELF_TEST);
|
||||
if(result)
|
||||
printk("%s:i2c error,mode=%d\n",__func__,mode);
|
||||
break;
|
||||
case AK8975_MODE_FUSE_ACCESS:
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_FUSE_ACCESS);
|
||||
if(result)
|
||||
printk("%s:i2c error,mode=%d\n",__func__,mode);
|
||||
break;
|
||||
case AK8975_MODE_POWERDOWN:
|
||||
/* Set powerdown mode */
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_POWERDOWN);
|
||||
if(result)
|
||||
printk("%s:i2c error,mode=%d\n",__func__,mode);
|
||||
udelay(100);
|
||||
break;
|
||||
default:
|
||||
printk("%s: Unknown mode(%d)", __func__, mode);
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
DBG("%s:mode=%d\n",__func__,mode);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int compass_akm_get_openstatus(void)
|
||||
{
|
||||
wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
|
||||
return atomic_read(&open_flag);
|
||||
}
|
||||
|
||||
static int compass_akm_get_closestatus(void)
|
||||
{
|
||||
wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0));
|
||||
return atomic_read(&open_flag);
|
||||
}
|
||||
|
||||
|
||||
/* ioctl - I/O control */
|
||||
static long compass_dev_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
|
||||
struct i2c_client *client = this_client;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int result = 0;
|
||||
struct akm8975_platform_data compass;
|
||||
|
||||
/* NOTE: In this function the size of "char" should be 1-byte. */
|
||||
char compass_data[SENSOR_DATA_SIZE];/* for GETDATA */
|
||||
char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */
|
||||
char mode; /* for SET_MODE*/
|
||||
short value[12]; /* for SET_YPR */
|
||||
short delay; /* for GET_DELAY */
|
||||
int status; /* for OPEN/CLOSE_STATUS */
|
||||
int ret = -1; /* Return value. */
|
||||
|
||||
switch (cmd) {
|
||||
case ECS_IOCTL_WRITE:
|
||||
case ECS_IOCTL_READ:
|
||||
if (argp == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case ECS_IOCTL_SET_MODE:
|
||||
if (argp == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (copy_from_user(&mode, argp, sizeof(mode))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case ECS_IOCTL_SET_YPR:
|
||||
if (argp == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (copy_from_user(&value, argp, sizeof(value))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ECS_IOCTL_WRITE:
|
||||
DBG("%s:ECS_IOCTL_WRITE start\n",__func__);
|
||||
mutex_lock(&sensor->operation_mutex);
|
||||
if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
printk("%s:fait to tx data\n",__func__);
|
||||
return ret;
|
||||
}
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
break;
|
||||
case ECS_IOCTL_READ:
|
||||
DBG("%s:ECS_IOCTL_READ start\n",__func__);
|
||||
mutex_lock(&sensor->operation_mutex);
|
||||
if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
printk("%s:data is error\n",__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
printk("%s:fait to rx data\n",__func__);
|
||||
return ret;
|
||||
}
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
break;
|
||||
case ECS_IOCTL_SET_MODE:
|
||||
DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__);
|
||||
mutex_lock(&sensor->operation_mutex);
|
||||
ret = compass_akm_set_mode(client, mode);
|
||||
if (ret < 0) {
|
||||
printk("%s:fait to set mode\n",__func__);
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
return ret;
|
||||
}
|
||||
mutex_unlock(&sensor->operation_mutex);
|
||||
break;
|
||||
case ECS_IOCTL_GETDATA:
|
||||
DBG("%s:ECS_IOCTL_GETDATA start\n",__func__);
|
||||
mutex_lock(&sensor->data_mutex);
|
||||
memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer
|
||||
mutex_unlock(&sensor->data_mutex);
|
||||
break;
|
||||
case ECS_IOCTL_SET_YPR:
|
||||
DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__);
|
||||
mutex_lock(&sensor->data_mutex);
|
||||
compass_set_YPR(value);
|
||||
mutex_unlock(&sensor->data_mutex);
|
||||
break;
|
||||
case ECS_IOCTL_GET_OPEN_STATUS:
|
||||
status = compass_akm_get_openstatus();
|
||||
DBG("%s:openstatus=%d\n",__func__,status);
|
||||
break;
|
||||
case ECS_IOCTL_GET_CLOSE_STATUS:
|
||||
status = compass_akm_get_closestatus();
|
||||
DBG("%s:closestatus=%d\n",__func__,status);
|
||||
break;
|
||||
case ECS_IOCTL_GET_DELAY:
|
||||
delay = akmd_delay;
|
||||
break;
|
||||
case ECS_IOCTL_GET_PLATFORM_DATA:
|
||||
DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__);
|
||||
memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout));
|
||||
memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name));
|
||||
ret = copy_to_user(argp, &compass, sizeof(compass));
|
||||
if(ret < 0)
|
||||
{
|
||||
printk("%s:error,ret=%d\n",__FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ECS_IOCTL_READ:
|
||||
if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case ECS_IOCTL_GETDATA:
|
||||
if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case ECS_IOCTL_GET_OPEN_STATUS:
|
||||
case ECS_IOCTL_GET_CLOSE_STATUS:
|
||||
if (copy_to_user(argp, &status, sizeof(status))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case ECS_IOCTL_GET_DELAY:
|
||||
if (copy_to_user(argp, &delay, sizeof(delay))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static struct file_operations compass_aot_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = compass_aot_ioctl,
|
||||
.open = compass_aot_open,
|
||||
.release = compass_aot_release,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct miscdevice compass_aot_device =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "akm8975_aot",
|
||||
.fops = &compass_aot_fops,
|
||||
};
|
||||
|
||||
|
||||
static struct file_operations compass_dev_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = compass_dev_open,
|
||||
.release = compass_dev_release,
|
||||
.unlocked_ioctl = compass_dev_ioctl,
|
||||
};
|
||||
|
||||
|
||||
static struct miscdevice compass_dev_device =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "akm8975_dev",
|
||||
.fops = &compass_dev_fops,
|
||||
};
|
||||
|
||||
struct sensor_operate akm8975_ops = {
|
||||
.name = "akm8975",
|
||||
.type = SENSOR_TYPE_COMPASS, //it is important
|
||||
.id_i2c = COMPASS_ID_AK8975,
|
||||
.read_reg = AK8975_REG_ST1, //read data
|
||||
.read_len = SENSOR_DATA_SIZE, //data length
|
||||
.id_reg = AK8975_REG_WIA, //read id
|
||||
.id_data = AK8975_DEVICE_ID,
|
||||
.precision = 8, //12 bits
|
||||
.ctrl_reg = AK8975_REG_CNTL, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //not exist
|
||||
.range = {-0xffff,0xffff},
|
||||
.trig = IRQF_TRIGGER_RISING, //if LEVEL interrupt then IRQF_ONESHOT
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
.misc_dev = &compass_dev_device, //private misc support
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *compass_get_ops(void)
|
||||
{
|
||||
return &akm8975_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(compass_get_ops);
|
||||
|
||||
|
||||
static int __init compass_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = compass_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, compass_get_ops);
|
||||
|
||||
result = misc_register(&compass_aot_device);
|
||||
if (result < 0) {
|
||||
printk("%s:fail to register misc device %s\n", __func__, compass_aot_device.name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* As default, report all information */
|
||||
atomic_set(&m_flag, 1);
|
||||
atomic_set(&a_flag, 1);
|
||||
atomic_set(&mv_flag, 1);
|
||||
atomic_set(&open_flag, 0);
|
||||
init_waitqueue_head(&open_wq);
|
||||
|
||||
printk("%s\n",__func__);
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit compass_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = compass_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, compass_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(compass_init);
|
||||
module_exit(compass_exit);
|
||||
|
||||
|
||||
19
drivers/input/sensors/gyro/Kconfig
Executable file
19
drivers/input/sensors/gyro/Kconfig
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# gyroscope drivers configuration
|
||||
#
|
||||
|
||||
menuconfig GYROSCOPE_DEVICE
|
||||
bool "gyroscope device support"
|
||||
default n
|
||||
|
||||
if GYROSCOPE_DEVICE
|
||||
|
||||
config GYRO_L3G4200D
|
||||
bool "gyroscope l3g4200d"
|
||||
default n
|
||||
|
||||
config GYRO_K3G
|
||||
bool "gyroscope k3g"
|
||||
default n
|
||||
|
||||
endif
|
||||
4
drivers/input/sensors/gyro/Makefile
Executable file
4
drivers/input/sensors/gyro/Makefile
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
# gyroscope drivers
|
||||
|
||||
obj-$(CONFIG_GYRO_SENSOR_K3G) += k3g.o
|
||||
obj-$(CONFIG_GYRO_L3G4200D) += l3g4200d.o
|
||||
267
drivers/input/sensors/gyro/l3g4200d.c
Executable file
267
drivers/input/sensors/gyro/l3g4200d.c
Executable file
|
|
@ -0,0 +1,267 @@
|
|||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/l3g4200d.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_GYROSCOPE
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
#define L3G4200D_ENABLE 0x08
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
status = L3G4200D_ENABLE; //l3g4200d
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~L3G4200D_ENABLE; //l3g4200d
|
||||
sensor->ops->ctrl_data &= status;
|
||||
}
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
unsigned char buf[5];
|
||||
unsigned char data = 0;
|
||||
int i = 0;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
buf[0] = 0x07; //27
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x20; //0x00
|
||||
buf[4] = 0x00;
|
||||
for(i=0; i<5; i++)
|
||||
{
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg+i, buf[i]);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
if (result >= 0)
|
||||
data = result & 0x000F;
|
||||
|
||||
sensor->ops->ctrl_data = data + ODR100_BW12_5;
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int gyro_report_value(struct i2c_client *client, struct sensor_axis *axis)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
/* Report GYRO information */
|
||||
input_report_rel(sensor->input_dev, ABS_RX, axis->x);
|
||||
input_report_rel(sensor->input_dev, ABS_RY, axis->y);
|
||||
input_report_rel(sensor->input_dev, ABS_RZ, axis->z);
|
||||
input_sync(sensor->input_dev);
|
||||
DBG("gyro x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_platform_data *pdata = sensor->pdata;
|
||||
int ret = 0;
|
||||
int x = 0, y = 0, z = 0;
|
||||
struct sensor_axis axis;
|
||||
char buffer[6] = {0};
|
||||
int i = 0;
|
||||
|
||||
if(sensor->ops->read_len < 6) //sensor->ops->read_len = 6
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, 6);
|
||||
#if 0
|
||||
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
|
||||
do {
|
||||
buffer[0] = sensor->ops->read_reg;
|
||||
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} while (0);
|
||||
#else
|
||||
|
||||
for(i=0; i<6; i++)
|
||||
{
|
||||
//buffer[i] = sensor->ops->read_reg + i;
|
||||
buffer[i] = sensor_read_reg(client, sensor->ops->read_reg + i);
|
||||
}
|
||||
#endif
|
||||
x = (short) (((buffer[1]) << 8) | buffer[0]);
|
||||
y = (short) (((buffer[3]) << 8) | buffer[2]);
|
||||
z = (short) (((buffer[5]) << 8) | buffer[4]);
|
||||
|
||||
DBG("%s: x=%d y=%d z=%d \n",__func__, x,y,z);
|
||||
if(pdata && pdata->orientation)
|
||||
{
|
||||
axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
|
||||
axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;
|
||||
axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
|
||||
}
|
||||
else
|
||||
{
|
||||
axis.x = x;
|
||||
axis.y = y;
|
||||
axis.z = z;
|
||||
}
|
||||
|
||||
//filter gyro data
|
||||
if((abs(axis.x) > pdata->x_min)||(abs(axis.y) > pdata->y_min)||(abs(axis.z) > pdata->z_min))
|
||||
{
|
||||
gyro_report_value(client, &axis);
|
||||
|
||||
/* »¥³âµØ»º´æÊý¾Ý. */
|
||||
mutex_lock(&(sensor->data_mutex) );
|
||||
sensor->axis = axis;
|
||||
mutex_unlock(&(sensor->data_mutex) );
|
||||
}
|
||||
|
||||
if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
|
||||
{
|
||||
|
||||
ret= sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
if(ret)
|
||||
{
|
||||
printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gyro_ops = {
|
||||
.name = "l3g4200d",
|
||||
.type = SENSOR_TYPE_GYROSCOPE,//sensor type and it should be correct
|
||||
.id_i2c = GYRO_ID_L3G4200D, //i2c id number
|
||||
.read_reg = GYRO_DATA_REG, //read data
|
||||
.read_len = 6, //data length
|
||||
.id_reg = GYRO_WHO_AM_I, //read device id from this register
|
||||
.id_data = GYRO_DEVID_L3G4200D, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = GYRO_CTRL_REG1, //enable or disable
|
||||
.int_status_reg = GYRO_INT_SRC, //intterupt status register,if no exist then -1
|
||||
.range = {-32768,32768}, //range
|
||||
.trig = IRQF_TRIGGER_LOW|IRQF_ONESHOT,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *gyro_get_ops(void)
|
||||
{
|
||||
return &gyro_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gyro_get_ops);
|
||||
|
||||
static int __init gyro_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = gyro_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, gyro_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gyro_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = gyro_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, gyro_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(gyro_init);
|
||||
module_exit(gyro_exit);
|
||||
|
||||
|
||||
22
drivers/input/sensors/lsensor/Kconfig
Executable file
22
drivers/input/sensors/lsensor/Kconfig
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# light and position sensor drivers configuration
|
||||
#
|
||||
|
||||
menuconfig LIGHT_DEVICE
|
||||
bool "light sensor device support"
|
||||
default n
|
||||
|
||||
if LIGHT_DEVICE
|
||||
config LS_CM3217
|
||||
bool "light sensor cm3217"
|
||||
default n
|
||||
|
||||
config LS_AL3006
|
||||
bool "light sensor al3006"
|
||||
default n
|
||||
|
||||
config LS_STK3171
|
||||
bool "light sensor stk3171"
|
||||
default n
|
||||
endif
|
||||
|
||||
5
drivers/input/sensors/lsensor/Makefile
Executable file
5
drivers/input/sensors/lsensor/Makefile
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
# gsensor drivers
|
||||
|
||||
obj-$(CONFIG_LS_CM3217) += cm3217.o
|
||||
obj-$(CONFIG_LS_AL3006) += ls_al3006.o
|
||||
obj-$(CONFIG_LS_STK3171) += ls_stk3171.o
|
||||
238
drivers/input/sensors/lsensor/cm3217.c
Executable file
238
drivers/input/sensors/lsensor/cm3217.c
Executable file
|
|
@ -0,0 +1,238 @@
|
|||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
#define CM3217_ADDR_COM1 0x10
|
||||
#define CM3217_ADDR_COM2 0x11
|
||||
#define CM3217_ADDR_DATA_MSB 0x10
|
||||
#define CM3217_ADDR_DATA_LSB 0x11
|
||||
|
||||
#define CM3217_COM1_VALUE 0xA7 // (GAIN1:GAIN0)=10, (IT_T1:IT_TO)=01,WMD=1,SD=1,
|
||||
#define CM3217_COM2_VALUE 0xA0 //100ms
|
||||
|
||||
#define CM3217_CLOSE 0x01
|
||||
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->client->addr = sensor->ops->ctrl_reg;
|
||||
sensor->ops->ctrl_data = sensor_read_reg_normal(client);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(!enable)
|
||||
{
|
||||
status = CM3217_CLOSE; //cm3217
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~CM3217_CLOSE; //cm3217
|
||||
sensor->ops->ctrl_data &= status;
|
||||
}
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg_normal(client, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
sensor->client->addr = sensor->ops->ctrl_reg;
|
||||
sensor->ops->ctrl_data = CM3217_COM1_VALUE;
|
||||
result = sensor_write_reg_normal(client, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->client->addr = CM3217_ADDR_COM2;
|
||||
result = sensor_write_reg_normal(client, CM3217_COM2_VALUE);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void light_report_value(struct input_dev *input, int data)
|
||||
{
|
||||
unsigned char index = 0;
|
||||
if(data <= 10){
|
||||
index = 0;goto report;
|
||||
}
|
||||
else if(data <= 160){
|
||||
index = 1;goto report;
|
||||
}
|
||||
else if(data <= 225){
|
||||
index = 2;goto report;
|
||||
}
|
||||
else if(data <= 320){
|
||||
index = 3;goto report;
|
||||
}
|
||||
else if(data <= 640){
|
||||
index = 4;goto report;
|
||||
}
|
||||
else if(data <= 1280){
|
||||
index = 5;goto report;
|
||||
}
|
||||
else if(data <= 2600){
|
||||
index = 6;goto report;
|
||||
}
|
||||
else{
|
||||
index = 7;goto report;
|
||||
}
|
||||
|
||||
report:
|
||||
DBG("cm3217 report data=%d,index = %d\n",data,index);
|
||||
input_report_abs(input, ABS_MISC, index);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
char msb = 0, lsb = 0;
|
||||
|
||||
sensor->client->addr = CM3217_ADDR_DATA_LSB;
|
||||
sensor_rx_data_normal(sensor->client, &lsb, 1);
|
||||
sensor->client->addr = CM3217_ADDR_DATA_MSB;
|
||||
sensor_rx_data_normal(sensor->client, &msb, 1);
|
||||
result = ((msb << 8) | lsb) & 0xffff;
|
||||
|
||||
DBG("%s:result=%d\n",__func__,result);
|
||||
light_report_value(sensor->input_dev, result);
|
||||
|
||||
if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
|
||||
{
|
||||
|
||||
result= sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate light_ops = {
|
||||
.name = "cm3217",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_CM3217, //i2c id number
|
||||
.read_reg = CM3217_ADDR_DATA_LSB, //read data
|
||||
.read_len = 2, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = CM3217_ADDR_COM1, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.trig = SENSOR_UNKNOW_DATA,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(light_get_ops);
|
||||
|
||||
static int __init light_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, light_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, light_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(light_init);
|
||||
module_exit(light_exit);
|
||||
|
||||
|
||||
299
drivers/input/sensors/lsensor/ls_al3006.c
Executable file
299
drivers/input/sensors/lsensor/ls_al3006.c
Executable file
|
|
@ -0,0 +1,299 @@
|
|||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
#define CONFIG_REG (0x00)
|
||||
#define TIM_CTL_REG (0x01)
|
||||
#define ALS_CTL_REG (0x02)
|
||||
#define INT_STATUS_REG (0x03)
|
||||
#define PS_CTL_REG (0x04)
|
||||
#define PS_ALS_DATA_REG (0x05)
|
||||
#define ALS_WINDOWS_REG (0x08)
|
||||
|
||||
//enable bit[ 0-1], in register CONFIG_REG
|
||||
#define ONLY_ALS_EN (0x00)
|
||||
#define ONLY_PROX_EN (0x01)
|
||||
#define ALL_PROX_ALS_EN (0x02)
|
||||
#define ALL_IDLE (0x03)
|
||||
|
||||
#define POWER_MODE_MASK (0x0C)
|
||||
#define POWER_UP_MODE (0x00)
|
||||
#define POWER_DOWN_MODE (0x08)
|
||||
#define POWER_RESET_MODE (0x0C)
|
||||
|
||||
static int sensor_power_updown(struct i2c_client *client, int on)
|
||||
{
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
int i = 0;
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
if(!on)
|
||||
{
|
||||
result = sensor_write_reg(client, CONFIG_REG, POWER_DOWN_MODE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = sensor_read_reg(client, CONFIG_REG);
|
||||
value &= ~POWER_MODE_MASK;
|
||||
value |= POWER_UP_MODE;
|
||||
result = sensor_write_reg(client, CONFIG_REG, value);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!result)
|
||||
break;
|
||||
}
|
||||
|
||||
if(i>1)
|
||||
printk("%s:set %d times",__func__,i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
if( (sensor->ops->ctrl_data & 0x03) == ONLY_PROX_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_PROX_ALS_EN;
|
||||
}
|
||||
else if((value & 0x03) == ALL_IDLE )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_ALS_EN;
|
||||
}
|
||||
|
||||
sensor_power_updown(client, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (sensor->ops->ctrl_data & 0x03) == ONLY_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_IDLE;
|
||||
}
|
||||
else if((sensor->ops->ctrl_data & 0x03) == ALL_PROX_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_PROX_EN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sensor->ops->ctrl_data = value;
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
|
||||
|
||||
sensor_power_updown(client, 0);
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
value = 0x41;//The ADC effective resolution = 9; Low lux threshold level = 1;
|
||||
//value = 0x69; //The ADC effective resolution = 17; Low lux threshold level = 9;
|
||||
result = sensor_write_reg(client, ALS_CTL_REG, value);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
//value = 0x04;//0x01-0x0f; 17%->93.5% if value = 0x04,then Compensate Loss 52%
|
||||
value = 0x02;//0x01-0x0f; 17%->93.5% if value = 0x02,then Compensate Loss 31%
|
||||
result = sensor_write_reg(client, ALS_WINDOWS_REG, value);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int light_report_value(struct input_dev *input, int data)
|
||||
{
|
||||
unsigned char index = 0;
|
||||
if(data <= 0){
|
||||
index = 0;goto report;
|
||||
}
|
||||
else if(data <= 2){
|
||||
index = 1;goto report;
|
||||
}
|
||||
else if(data <= 4){
|
||||
index = 2;goto report;
|
||||
}
|
||||
else if(data <= 8){
|
||||
index = 3;goto report;
|
||||
}
|
||||
else if(data <= 14){
|
||||
index = 4;goto report;
|
||||
}
|
||||
else if(data <= 20){
|
||||
index = 5;goto report;
|
||||
}
|
||||
else if(data <= 26){
|
||||
index = 6;goto report;
|
||||
}
|
||||
else{
|
||||
index = 7;goto report;
|
||||
}
|
||||
|
||||
report:
|
||||
input_report_abs(input, ABS_MISC, index);
|
||||
input_sync(input);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
char index = 0;
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->read_reg);
|
||||
index = light_report_value(sensor->input_dev, value&0x3f); // bit0-5 is ls data;
|
||||
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_ops = {
|
||||
.name = "ls_al3006",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_AL3006, //i2c id number
|
||||
.read_reg = PS_ALS_DATA_REG, //read data
|
||||
.read_len = 1, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = CONFIG_REG, //enable or disable
|
||||
.int_status_reg = INT_STATUS_REG, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(light_get_ops);
|
||||
|
||||
static int __init light_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, light_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, light_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(light_init);
|
||||
module_exit(light_exit);
|
||||
|
||||
|
||||
301
drivers/input/sensors/lsensor/ls_stk3171.c
Executable file
301
drivers/input/sensors/lsensor/ls_stk3171.c
Executable file
|
|
@ -0,0 +1,301 @@
|
|||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
#define ALS_CMD 0x01
|
||||
#define ALS_DT1 0x02
|
||||
#define ALS_DT2 0X03
|
||||
#define ALS_THDH1 0X04
|
||||
#define ALS_THDH2 0X05
|
||||
#define ALS_THDL1 0X06
|
||||
#define ALS_THDL2 0X07
|
||||
#define STA_TUS 0X08
|
||||
#define PS_CMD 0X09
|
||||
#define PS_DT 0X0A
|
||||
#define PS_THDH 0X0B
|
||||
#define PS_THDL 0X0C
|
||||
#define SW_RESET 0X80
|
||||
|
||||
//ALS_CMD
|
||||
#define ALS_SD_ENABLE (0<<0)
|
||||
#define ALS_SD_DISABLE (1<<0)
|
||||
#define ALS_INT_DISABLE (0<<1)
|
||||
#define ALS_INT_ENABLE (1<<1)
|
||||
#define ALS_1T_100MS (0<<2)
|
||||
#define ALS_2T_200MS (1<<2)
|
||||
#define ALS_4T_400MS (2<<2)
|
||||
#define ALS_8T_800MS (3<<2)
|
||||
#define ALS_RANGE_57671 (0<<5)
|
||||
#define ALS_RANGE_28836 (1<<5)
|
||||
|
||||
//PS_CMD
|
||||
#define PS_SD_ENABLE (0<<0)
|
||||
#define PS_SD_DISABLE (1<<0)
|
||||
#define PS_INT_DISABLE (0<<1)
|
||||
#define PS_INT_ENABLE (1<<1)
|
||||
#define PS_10T_2MS (0<<2)
|
||||
#define PS_15T_3MS (1<<2)
|
||||
#define PS_20T_4MS (2<<2)
|
||||
#define PS_25T_5MS (3<<2)
|
||||
#define PS_CUR_100MA (0<<3)
|
||||
#define PS_CUR_200MA (1<<3)
|
||||
#define PS_SLP_10MS (0<<4)
|
||||
#define PS_SLP_30MS (1<<4)
|
||||
#define PS_SLP_90MS (2<<4)
|
||||
#define PS_SLP_270MS (3<<4)
|
||||
#define TRIG_PS_OR_LS (0<<5)
|
||||
#define TRIG_PS_AND_LS (1<<5)
|
||||
|
||||
//STA_TUS
|
||||
#define STA_PS_INT (1<<4)
|
||||
#define STA_ALS_INT (1<<3)
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(!enable)
|
||||
{
|
||||
status = ALS_SD_DISABLE;
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~ALS_SD_DISABLE;
|
||||
sensor->ops->ctrl_data &= status;
|
||||
}
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
result = sensor_write_reg(client, SW_RESET, 0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
sensor->ops->ctrl_data |= (ALS_1T_100MS | ALS_RANGE_28836);
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
sensor->ops->ctrl_data |= ALS_INT_ENABLE;
|
||||
else
|
||||
sensor->ops->ctrl_data &= ~ALS_INT_ENABLE;
|
||||
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int light_report_value(struct input_dev *input, int data)
|
||||
{
|
||||
unsigned char index = 0;
|
||||
if(data <= 10){
|
||||
index = 0;goto report;
|
||||
}
|
||||
else if(data <= 1600){
|
||||
index = 1;goto report;
|
||||
}
|
||||
else if(data <= 2250){
|
||||
index = 2;goto report;
|
||||
}
|
||||
else if(data <= 3200){
|
||||
index = 3;goto report;
|
||||
}
|
||||
else if(data <= 6400){
|
||||
index = 4;goto report;
|
||||
}
|
||||
else if(data <= 12800){
|
||||
index = 5;goto report;
|
||||
}
|
||||
else if(data <= 26000){
|
||||
index = 6;goto report;
|
||||
}
|
||||
else{
|
||||
index = 7;goto report;
|
||||
}
|
||||
|
||||
report:
|
||||
input_report_abs(input, ABS_MISC, index);
|
||||
input_sync(input);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int value = 0;
|
||||
char buffer[2] = {0};
|
||||
char index = 0;
|
||||
|
||||
if(sensor->ops->read_len < 2) //sensor->ops->read_len = 2
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, 2);
|
||||
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
value = (short) (((buffer[1]) << 8) | buffer[0]);
|
||||
|
||||
index = light_report_value(sensor->input_dev, value);
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
if(value & STA_ALS_INT)
|
||||
{
|
||||
value &= ~STA_ALS_INT;
|
||||
result = sensor_write_reg(client, sensor->ops->int_status_reg,value); //clear int
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_ops = {
|
||||
.name = "ls_stk3171",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_STK3171, //i2c id number
|
||||
.read_reg = ALS_DT1, //read data
|
||||
.read_len = 2, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 16, //8 bits
|
||||
.ctrl_reg = ALS_CMD, //enable or disable
|
||||
.int_status_reg = STA_TUS, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(light_get_ops);
|
||||
|
||||
static int __init light_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, light_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, light_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(light_init);
|
||||
module_exit(light_exit);
|
||||
|
||||
|
||||
20
drivers/input/sensors/psensor/Kconfig
Executable file
20
drivers/input/sensors/psensor/Kconfig
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# light and position sensor drivers configuration
|
||||
#
|
||||
|
||||
menuconfig PROXIMITY_DEVICE
|
||||
bool "proximity sensor device support"
|
||||
default n
|
||||
|
||||
if PROXIMITY_DEVICE
|
||||
|
||||
config PS_AL3006
|
||||
bool "psensor al3006"
|
||||
default n
|
||||
|
||||
config PS_STK3171
|
||||
bool "psensor stk3171"
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
4
drivers/input/sensors/psensor/Makefile
Executable file
4
drivers/input/sensors/psensor/Makefile
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
# gsensor drivers
|
||||
|
||||
obj-$(CONFIG_PS_AL3006) += ps_al3006.o
|
||||
obj-$(CONFIG_PS_STK3171) += ps_stk3171.o
|
||||
260
drivers/input/sensors/psensor/ps_al3006.c
Executable file
260
drivers/input/sensors/psensor/ps_al3006.c
Executable file
|
|
@ -0,0 +1,260 @@
|
|||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_PROXIMITY
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
#define CONFIG_REG (0x00)
|
||||
#define TIM_CTL_REG (0x01)
|
||||
#define ALS_CTL_REG (0x02)
|
||||
#define INT_STATUS_REG (0x03)
|
||||
#define PS_CTL_REG (0x04)
|
||||
#define PS_ALS_DATA_REG (0x05)
|
||||
#define ALS_WINDOWS_REG (0x08)
|
||||
|
||||
//enable bit[ 0-1], in register CONFIG_REG
|
||||
#define ONLY_ALS_EN (0x00)
|
||||
#define ONLY_PROX_EN (0x01)
|
||||
#define ALL_PROX_ALS_EN (0x02)
|
||||
#define ALL_IDLE (0x03)
|
||||
|
||||
#define POWER_MODE_MASK (0x0C)
|
||||
#define POWER_UP_MODE (0x00)
|
||||
#define POWER_DOWN_MODE (0x08)
|
||||
#define POWER_RESET_MODE (0x0C)
|
||||
|
||||
static int sensor_power_updown(struct i2c_client *client, int on)
|
||||
{
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
int i = 0;
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
if(!on)
|
||||
{
|
||||
result = sensor_write_reg(client, CONFIG_REG, POWER_DOWN_MODE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = sensor_read_reg(client, CONFIG_REG);
|
||||
value &= ~POWER_MODE_MASK;
|
||||
value |= POWER_UP_MODE;
|
||||
result = sensor_write_reg(client, CONFIG_REG, value);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!result)
|
||||
break;
|
||||
}
|
||||
|
||||
if(i>1)
|
||||
printk("%s:set %d times",__func__,i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
if( (sensor->ops->ctrl_data & 0x03) == ONLY_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_PROX_ALS_EN;
|
||||
}
|
||||
else if((value & 0x03) == ALL_IDLE )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_PROX_EN;
|
||||
}
|
||||
|
||||
sensor_power_updown(client, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (sensor->ops->ctrl_data & 0x03) == ONLY_PROX_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_IDLE;
|
||||
}
|
||||
else if((sensor->ops->ctrl_data & 0x03) == ALL_PROX_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_ALS_EN;
|
||||
}
|
||||
}
|
||||
|
||||
sensor->ops->ctrl_data = value;
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
|
||||
sensor_power_updown(client, 0);
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
value = 0x41;//The ADC effective resolution = 9; Low lux threshold level = 1;
|
||||
//value = 0x69; //The ADC effective resolution = 17; Low lux threshold level = 9;
|
||||
result = sensor_write_reg(client, ALS_CTL_REG, value);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
//value = 0x04;//0x01-0x0f; 17%->93.5% if value = 0x04,then Compensate Loss 52%
|
||||
value = 0x02;//0x01-0x0f; 17%->93.5% if value = 0x02,then Compensate Loss 31%
|
||||
result = sensor_write_reg(client, ALS_WINDOWS_REG, value);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
char value = 0;
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->read_reg);
|
||||
input_report_abs(sensor->input_dev, ABS_DISTANCE, (value>>7)?0:1);
|
||||
input_sync(sensor->input_dev);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,(value>>7)?0:1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate proximity_ops = {
|
||||
.name = "ps_al3006",
|
||||
.type = SENSOR_TYPE_PROXIMITY,//sensor type and it should be correct
|
||||
.id_i2c = PROXIMITY_ID_AL3006, //i2c id number
|
||||
.read_reg = PS_ALS_DATA_REG, //read data
|
||||
.read_len = 1, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = CONFIG_REG, //enable or disable
|
||||
.int_status_reg = INT_STATUS_REG, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(proximity_get_ops);
|
||||
|
||||
static int __init proximity_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = proximity_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, proximity_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = proximity_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, proximity_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(proximity_init);
|
||||
module_exit(proximity_exit);
|
||||
|
||||
|
||||
265
drivers/input/sensors/psensor/ps_stk3171.c
Executable file
265
drivers/input/sensors/psensor/ps_stk3171.c
Executable file
|
|
@ -0,0 +1,265 @@
|
|||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_PROXIMITY
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
#define ALS_CMD 0x01
|
||||
#define ALS_DT1 0x02
|
||||
#define ALS_DT2 0X03
|
||||
#define ALS_THDH1 0X04
|
||||
#define ALS_THDH2 0X05
|
||||
#define ALS_THDL1 0X06
|
||||
#define ALS_THDL2 0X07
|
||||
#define STA_TUS 0X08
|
||||
#define PS_CMD 0X09
|
||||
#define PS_DT 0X0A
|
||||
#define PS_THDH 0X0B
|
||||
#define PS_THDL 0X0C
|
||||
#define SW_RESET 0X80
|
||||
|
||||
//ALS_CMD
|
||||
#define ALS_SD_ENABLE (0<<0)
|
||||
#define ALS_SD_DISABLE (1<<0)
|
||||
#define ALS_INT_DISABLE (0<<1)
|
||||
#define ALS_INT_ENABLE (1<<1)
|
||||
#define ALS_1T_100MS (0<<2)
|
||||
#define ALS_2T_200MS (1<<2)
|
||||
#define ALS_4T_400MS (2<<2)
|
||||
#define ALS_8T_800MS (3<<2)
|
||||
#define ALS_RANGE_57671 (0<<5)
|
||||
#define ALS_RANGE_28836 (1<<5)
|
||||
|
||||
//PS_CMD
|
||||
#define PS_SD_ENABLE (0<<0)
|
||||
#define PS_SD_DISABLE (1<<0)
|
||||
#define PS_INT_DISABLE (0<<1)
|
||||
#define PS_INT_ENABLE (1<<1)
|
||||
#define PS_10T_2MS (0<<2)
|
||||
#define PS_15T_3MS (1<<2)
|
||||
#define PS_20T_4MS (2<<2)
|
||||
#define PS_25T_5MS (3<<2)
|
||||
#define PS_CUR_100MA (0<<3)
|
||||
#define PS_CUR_200MA (1<<3)
|
||||
#define PS_SLP_10MS (0<<4)
|
||||
#define PS_SLP_30MS (1<<4)
|
||||
#define PS_SLP_90MS (2<<4)
|
||||
#define PS_SLP_270MS (3<<4)
|
||||
#define TRIG_PS_OR_LS (0<<5)
|
||||
#define TRIG_PS_AND_LS (1<<5)
|
||||
|
||||
//STA_TUS
|
||||
#define STA_PS_INT (1<<4)
|
||||
#define STA_ALS_INT (1<<3)
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(!enable)
|
||||
{
|
||||
status = PS_SD_DISABLE;
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~PS_SD_DISABLE;
|
||||
sensor->ops->ctrl_data &= status;
|
||||
}
|
||||
|
||||
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
result = sensor_write_reg(client, SW_RESET, 0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
sensor->ops->ctrl_data |= (PS_15T_3MS| PS_SLP_90MS | TRIG_PS_OR_LS);
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
sensor->ops->ctrl_data |= PS_INT_ENABLE;
|
||||
else
|
||||
sensor->ops->ctrl_data &= ~PS_INT_ENABLE;
|
||||
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int value = 0;
|
||||
char buffer[1] = {0};
|
||||
|
||||
if(sensor->ops->read_len < 1) //sensor->ops->read_len = 1
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, 1);
|
||||
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
value = buffer[0];
|
||||
|
||||
input_report_abs(sensor->input_dev, ABS_DISTANCE, value?0:1);
|
||||
input_sync(sensor->input_dev);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,value?0:1);
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
if(value & STA_PS_INT)
|
||||
{
|
||||
value &= ~STA_PS_INT;
|
||||
result = sensor_write_reg(client, sensor->ops->int_status_reg,value); //clear int
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate proximity_ops = {
|
||||
.name = "ps_stk3171",
|
||||
.type = SENSOR_TYPE_PROXIMITY, //sensor type and it should be correct
|
||||
.id_i2c = PROXIMITY_ID_STK3171, //i2c id number
|
||||
.read_reg = PS_DT, //read data
|
||||
.read_len = 1, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = PS_CMD, //enable or disable
|
||||
.int_status_reg = STA_TUS, //intterupt status register
|
||||
.range = {0,1}, //range
|
||||
.trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_ops;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(proximity_get_ops);
|
||||
|
||||
static int __init proximity_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = proximity_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, proximity_get_ops);
|
||||
printk("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = proximity_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, proximity_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(proximity_init);
|
||||
module_exit(proximity_exit);
|
||||
|
||||
|
||||
1327
drivers/input/sensors/sensor-dev.c
Executable file
1327
drivers/input/sensors/sensor-dev.c
Executable file
File diff suppressed because it is too large
Load diff
234
drivers/input/sensors/sensor-i2c.c
Executable file
234
drivers/input/sensors/sensor-i2c.c
Executable file
|
|
@ -0,0 +1,234 @@
|
|||
/* drivers/input/sensors/sensor-i2c.c - sensor i2c handle
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#define SENSOR_I2C_RATE 200*1000
|
||||
|
||||
#if 0
|
||||
#define SENSOR_DEBUG_TYPE SENSOR_TYPE_COMPASS
|
||||
#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
static int sensor_i2c_write(struct i2c_adapter *i2c_adap,
|
||||
unsigned char address,
|
||||
unsigned int len, unsigned char const *data)
|
||||
{
|
||||
struct i2c_msg msgs[1];
|
||||
int res;
|
||||
|
||||
if (!data || !i2c_adap) {
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msgs[0].addr = address;
|
||||
msgs[0].flags = 0; /* write */
|
||||
msgs[0].buf = (unsigned char *)data;
|
||||
msgs[0].len = len;
|
||||
msgs[0].scl_rate = SENSOR_I2C_RATE;
|
||||
|
||||
res = i2c_transfer(i2c_adap, msgs, 1);
|
||||
if (res == 1)
|
||||
return 0;
|
||||
else if(res == 0)
|
||||
return -EBUSY;
|
||||
else
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
static int senosr_i2c_read(struct i2c_adapter *i2c_adap,
|
||||
unsigned char address, unsigned char reg,
|
||||
unsigned int len, unsigned char *data)
|
||||
{
|
||||
struct i2c_msg msgs[2];
|
||||
int res;
|
||||
|
||||
if (!data || !i2c_adap) {
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msgs[0].addr = address;
|
||||
msgs[0].flags = 0; /* write */
|
||||
msgs[0].buf = ®
|
||||
msgs[0].len = 1;
|
||||
msgs[0].scl_rate = SENSOR_I2C_RATE;
|
||||
|
||||
msgs[1].addr = address;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
msgs[1].buf = data;
|
||||
msgs[1].len = len;
|
||||
msgs[1].scl_rate = SENSOR_I2C_RATE;
|
||||
|
||||
res = i2c_transfer(i2c_adap, msgs, 2);
|
||||
if (res == 2)
|
||||
return 0;
|
||||
else if(res == 0)
|
||||
return -EBUSY;
|
||||
else
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int sensor_rx_data(struct i2c_client *client, char *rxData, int length)
|
||||
{
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
int i = 0;
|
||||
#endif
|
||||
int ret = 0;
|
||||
char reg = rxData[0];
|
||||
ret = senosr_i2c_read(client->adapter, client->addr, reg, length, rxData);
|
||||
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
DBG("addr=0x%x,len=%d,rxdata:",reg,length);
|
||||
for(i=0; i<length; i++)
|
||||
DBG("0x%x,",rxData[i]);
|
||||
DBG("\n");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_rx_data);
|
||||
|
||||
int sensor_tx_data(struct i2c_client *client, char *txData, int length)
|
||||
{
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
int i = 0;
|
||||
#endif
|
||||
int ret = 0;
|
||||
#ifdef SENSOR_DEBUG_TYPE
|
||||
DBG("addr=0x%x,len=%d,txdata:",txData[0],length);
|
||||
for(i=1; i<length; i++)
|
||||
DBG("0x%x,",txData[i]);
|
||||
DBG("\n");
|
||||
#endif
|
||||
ret = sensor_i2c_write(client->adapter, client->addr, length, txData);
|
||||
return ret;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_tx_data);
|
||||
|
||||
int sensor_write_reg(struct i2c_client *client, int addr, int value)
|
||||
{
|
||||
char buffer[2];
|
||||
int ret = 0;
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
|
||||
mutex_lock(&sensor->i2c_mutex);
|
||||
buffer[0] = addr;
|
||||
buffer[1] = value;
|
||||
ret = sensor_tx_data(client, &buffer[0], 2);
|
||||
mutex_unlock(&sensor->i2c_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_write_reg);
|
||||
|
||||
int sensor_read_reg(struct i2c_client *client, int addr)
|
||||
{
|
||||
char tmp[1] = {0};
|
||||
int ret = 0;
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
|
||||
mutex_lock(&sensor->i2c_mutex);
|
||||
tmp[0] = addr;
|
||||
ret = sensor_rx_data(client, tmp, 1);
|
||||
mutex_unlock(&sensor->i2c_mutex);
|
||||
|
||||
return tmp[0];
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sensor_read_reg);
|
||||
|
||||
|
||||
int sensor_tx_data_normal(struct i2c_client *client, char *buf, int num)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = i2c_master_normal_send(client, buf, num, SENSOR_I2C_RATE);
|
||||
|
||||
return (ret == num) ? 0 : ret;
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_tx_data_normal);
|
||||
|
||||
|
||||
int sensor_rx_data_normal(struct i2c_client *client, char *buf, int num)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = i2c_master_normal_recv(client, buf, num, SENSOR_I2C_RATE);
|
||||
|
||||
return (ret == num) ? 0 : ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sensor_rx_data_normal);
|
||||
|
||||
|
||||
int sensor_write_reg_normal(struct i2c_client *client, char value)
|
||||
{
|
||||
char buffer[2];
|
||||
int ret = 0;
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
|
||||
mutex_lock(&sensor->i2c_mutex);
|
||||
buffer[0] = value;
|
||||
ret = sensor_tx_data_normal(client, &buffer[0], 1);
|
||||
mutex_unlock(&sensor->i2c_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_write_reg_normal);
|
||||
|
||||
int sensor_read_reg_normal(struct i2c_client *client)
|
||||
{
|
||||
char tmp[0];
|
||||
int ret = 0;
|
||||
struct sensor_private_data* sensor =
|
||||
(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
|
||||
mutex_lock(&sensor->i2c_mutex);
|
||||
ret = sensor_rx_data_normal(client, tmp, 1);
|
||||
mutex_unlock(&sensor->i2c_mutex);
|
||||
|
||||
return tmp[0];
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sensor_read_reg_normal);
|
||||
|
||||
|
||||
0
drivers/input/sensors/temperature/Kconfig
Executable file
0
drivers/input/sensors/temperature/Kconfig
Executable file
0
drivers/input/sensors/temperature/Makefile
Executable file
0
drivers/input/sensors/temperature/Makefile
Executable file
48
include/linux/akm8975.h
Normal file → Executable file
48
include/linux/akm8975.h
Normal file → Executable file
|
|
@ -6,17 +6,21 @@
|
|||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define AKM8975_I2C_NAME "ak8975"
|
||||
|
||||
/*! \name AK8975 operation mode
|
||||
\anchor AK8975_Mode
|
||||
Defines an operation mode of the AK8975.*/
|
||||
/*! @{*/
|
||||
#define AK8975_MODE_SNG_MEASURE 0x01
|
||||
#define AK8975_MODE_SELF_TEST 0x08
|
||||
#define AK8975_MODE_FUSE_ACCESS 0x0F
|
||||
#define AK8975_MODE_POWER_DOWN 0x00
|
||||
#define AK8975_MODE_SNG_MEASURE 0x01
|
||||
#define AK8975_MODE_SELF_TEST 0x08
|
||||
#define AK8975_MODE_FUSE_ACCESS 0x0F
|
||||
#define AK8975_MODE_POWERDOWN 0x00
|
||||
/*! @}*/
|
||||
|
||||
#define RBUFF_SIZE 8 /* Rx buffer size */
|
||||
#define SENSOR_DATA_SIZE 8 /* Rx buffer size, i.e from ST1 to ST2 */
|
||||
#define RWBUF_SIZE 16 /* Read/Write buffer size.*/
|
||||
|
||||
|
||||
/*! \name AK8975 register address
|
||||
\anchor AK8975_REG
|
||||
|
|
@ -52,36 +56,34 @@ Defines a read-only address of the fuse ROM of the AK8975.*/
|
|||
#define AKMIO 0xA1
|
||||
|
||||
/* IOCTLs for AKM library */
|
||||
#define ECS_IOCTL_WRITE _IOW(AKMIO, 0x02, char[5])
|
||||
#define ECS_IOCTL_READ _IOWR(AKMIO, 0x03, char[5])
|
||||
#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x08, char[RBUFF_SIZE])
|
||||
#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x0C, short[12])
|
||||
#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x0D, int)
|
||||
#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x0E, int)
|
||||
#define ECS_IOCTL_WRITE _IOW(AKMIO, 0x01, char*)
|
||||
#define ECS_IOCTL_READ _IOWR(AKMIO, 0x02, char*)
|
||||
#define ECS_IOCTL_RESET _IO(AKMIO, 0x03) /* NOT used in AK8975 */
|
||||
#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x04, short)
|
||||
#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x05, char[SENSOR_DATA_SIZE])
|
||||
#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x06, short[12])
|
||||
#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x07, int)
|
||||
#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x08, int)
|
||||
#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, short)
|
||||
#define ECS_IOCTL_GET_PROJECT_NAME _IOR(AKMIO, 0x0D, char[64])
|
||||
#define ECS_IOCTL_GET_MATRIX _IOR(AKMIO, 0x0E, short [4][3][3])
|
||||
#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(AKMIO, 0x0E, struct akm8975_platform_data)
|
||||
|
||||
|
||||
/* IOCTLs for APPs */
|
||||
#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short)
|
||||
#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short)
|
||||
#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short)
|
||||
#define ECS_IOCTL_APP_SET_AFLAG _IOW(AKMIO, 0x13, short)
|
||||
#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short)
|
||||
#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short)/* NOT use */
|
||||
#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short)/* NOT use */
|
||||
#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17) /* NOT use */
|
||||
#define ECS_IOCTL_APP_SET_DELAY _IOW(AKMIO, 0x18, short)
|
||||
#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY
|
||||
/* Set raw magnetic vector flag */
|
||||
#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short)
|
||||
/* Get raw magnetic vector flag */
|
||||
#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short)
|
||||
#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short)
|
||||
|
||||
|
||||
struct akm8975_platform_data {
|
||||
int intr;
|
||||
|
||||
int (*init)(void);
|
||||
void (*exit)(void);
|
||||
int (*power_on)(void);
|
||||
int (*power_off)(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
77
include/linux/kxtik.h
Executable file
77
include/linux/kxtik.h
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
#define KXTIK_DEVID 0x05 //chip id
|
||||
#define KXTIK_RANGE 2000000
|
||||
|
||||
#define KXTIK_XOUT_HPF_L (0x00) /* 0000 0000 */
|
||||
#define KXTIK_XOUT_HPF_H (0x01) /* 0000 0001 */
|
||||
#define KXTIK_YOUT_HPF_L (0x02) /* 0000 0010 */
|
||||
#define KXTIK_YOUT_HPF_H (0x03) /* 0000 0011 */
|
||||
#define KXTIK_ZOUT_HPF_L (0x04) /* 0001 0100 */
|
||||
#define KXTIK_ZOUT_HPF_H (0x05) /* 0001 0101 */
|
||||
#define KXTIK_XOUT_L (0x06) /* 0000 0110 */
|
||||
#define KXTIK_XOUT_H (0x07) /* 0000 0111 */
|
||||
#define KXTIK_YOUT_L (0x08) /* 0000 1000 */
|
||||
#define KXTIK_YOUT_H (0x09) /* 0000 1001 */
|
||||
#define KXTIK_ZOUT_L (0x0A) /* 0001 1010 */
|
||||
#define KXTIK_ZOUT_H (0x0B) /* 0001 1011 */
|
||||
#define KXTIK_ST_RESP (0x0C) /* 0000 1100 */
|
||||
#define KXTIK_WHO_AM_I (0x0F) /* 0000 1111 */
|
||||
#define KXTIK_TILT_POS_CUR (0x10) /* 0001 0000 */
|
||||
#define KXTIK_TILT_POS_PRE (0x11) /* 0001 0001 */
|
||||
#define KXTIK_INT_SRC_REG1 (0x15) /* 0001 0101 */
|
||||
#define KXTIK_INT_SRC_REG2 (0x16) /* 0001 0110 */
|
||||
#define KXTIK_STATUS_REG (0x18) /* 0001 1000 */
|
||||
#define KXTIK_INT_REL (0x1A) /* 0001 1010 */
|
||||
#define KXTIK_CTRL_REG1 (0x1B) /* 0001 1011 */
|
||||
#define KXTIK_CTRL_REG2 (0x1C) /* 0001 1100 */
|
||||
#define KXTIK_CTRL_REG3 (0x1D) /* 0001 1101 */
|
||||
#define KXTIK_INT_CTRL_REG1 (0x1E) /* 0001 1110 */
|
||||
#define KXTIK_INT_CTRL_REG2 (0x1F) /* 0001 1111 */
|
||||
#define KXTIK_INT_CTRL_REG3 (0x20) /* 0010 0000 */
|
||||
#define KXTIK_DATA_CTRL_REG (0x21) /* 0010 0001 */
|
||||
#define KXTIK_TILT_TIMER (0x28) /* 0010 1000 */
|
||||
#define KXTIK_WUF_TIMER (0x29) /* 0010 1001 */
|
||||
#define KXTIK_TDT_TIMER (0x2B) /* 0010 1011 */
|
||||
#define KXTIK_TDT_H_THRESH (0x2C) /* 0010 1100 */
|
||||
#define KXTIK_TDT_L_THRESH (0x2D) /* 0010 1101 */
|
||||
#define KXTIK_TDT_TAP_TIMER (0x2E) /* 0010 1110 */
|
||||
#define KXTIK_TDT_TOTAL_TIMER (0x2F) /* 0010 1111 */
|
||||
#define KXTIK_TDT_LATENCY_TIMER (0x30) /* 0011 0000 */
|
||||
#define KXTIK_TDT_WINDOW_TIMER (0x31) /* 0011 0001 */
|
||||
#define KXTIK_WUF_THRESH (0x5A) /* 0101 1010 */
|
||||
#define KXTIK_TILT_ANGLE (0x5C) /* 0101 1100 */
|
||||
#define KXTIK_HYST_SET (0x5F) /* 0101 1111 */
|
||||
|
||||
/* CONTROL REGISTER 1 BITS */
|
||||
#define KXTIK_DISABLE 0x7F
|
||||
#define KXTIK_ENABLE (1 << 7)
|
||||
/* INPUT_ABS CONSTANTS */
|
||||
#define FUZZ 3
|
||||
#define FLAT 3
|
||||
/* RESUME STATE INDICES */
|
||||
#define RES_DATA_CTRL 0
|
||||
#define RES_CTRL_REG1 1
|
||||
#define RES_INT_CTRL1 2
|
||||
#define RESUME_ENTRIES 3
|
||||
|
||||
/* CTRL_REG1: set resolution, g-range, data ready enable */
|
||||
/* Output resolution: 8-bit valid or 12-bit valid */
|
||||
#define KXTIK_RES_8BIT 0
|
||||
#define KXTIK_RES_12BIT (1 << 6)
|
||||
/* Output g-range: +/-2g, 4g, or 8g */
|
||||
#define KXTIK_G_2G 0
|
||||
#define KXTIK_G_4G (1 << 3)
|
||||
#define KXTIK_G_8G (1 << 4)
|
||||
|
||||
/* DATA_CTRL_REG: controls the output data rate of the part */
|
||||
#define KXTIK_ODR12_5F 0
|
||||
#define KXTIK_ODR25F 1
|
||||
#define KXTIK_ODR50F 2
|
||||
#define KXTIK_ODR100F 3
|
||||
#define KXTIK_ODR200F 4
|
||||
#define KXTIK_ODR400F 5
|
||||
#define KXTIK_ODR800F 6
|
||||
|
||||
/* kxtik */
|
||||
#define KXTIK_PRECISION 12
|
||||
#define KXTIK_BOUNDARY (0x1 << (KXTIK_PRECISION - 1))
|
||||
#define KXTIK_GRAVITY_STEP KXTIK_RANGE / KXTIK_BOUNDARY
|
||||
|
|
@ -54,12 +54,25 @@
|
|||
#define L3G4200D_FS_500DPS 0x10
|
||||
#define L3G4200D_FS_2000DPS 0x30
|
||||
|
||||
#define PM_OFF 0x00
|
||||
#define PM_NORMAL 0x08
|
||||
#define ENABLE_ALL_AXES 0x07
|
||||
#define PM_OFF 0x00
|
||||
#define PM_NORMAL 0x08
|
||||
#define ENABLE_ALL_AXES 0x07
|
||||
|
||||
/* l3g4200d gyroscope registers */
|
||||
#define GYRO_WHO_AM_I 0x0F
|
||||
#define GYRO_CTRL_REG1 0x20 /* power control reg */
|
||||
#define GYRO_CTRL_REG2 0x21 /* power control reg */
|
||||
#define GYRO_CTRL_REG3 0x22 /* power control reg */
|
||||
#define GYRO_CTRL_REG4 0x23 /* interrupt control reg */
|
||||
#define GYRO_CTRL_REG5 0x24 /* interrupt control reg */
|
||||
#define GYRO_DATA_REG 0x28
|
||||
#define GYRO_INT_SRC 0x31
|
||||
|
||||
|
||||
|
||||
|
||||
/*status*/
|
||||
#define L3G4200D_SUSPEND 2
|
||||
#define L3G4200D_SUSPEND 2
|
||||
#define L3G4200D_OPEN 1
|
||||
#define L3G4200D_CLOSE 0
|
||||
|
||||
|
|
|
|||
194
include/linux/sensor-dev.h
Executable file
194
include/linux/sensor-dev.h
Executable file
|
|
@ -0,0 +1,194 @@
|
|||
/* include/linux/sensor-dev.h - sensor header file
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define SENSOR_ON 1
|
||||
#define SENSOR_OFF 0
|
||||
#define SENSOR_UNKNOW_DATA -1
|
||||
|
||||
enum sensor_type {
|
||||
SENSOR_TYPE_NULL,
|
||||
SENSOR_TYPE_ACCEL,
|
||||
SENSOR_TYPE_COMPASS,
|
||||
SENSOR_TYPE_GYROSCOPE,
|
||||
SENSOR_TYPE_LIGHT,
|
||||
SENSOR_TYPE_PROXIMITY,
|
||||
SENSOR_TYPE_TEMPERATURE,
|
||||
//SENSOR_TYPE_PRESSURE,
|
||||
SENSOR_NUM_TYPES
|
||||
};
|
||||
|
||||
enum sensor_id {
|
||||
ID_INVALID = 0,
|
||||
|
||||
ACCEL_ID_ALL,
|
||||
ACCEL_ID_LIS331,
|
||||
ACCEL_ID_LSM303DLX,
|
||||
ACCEL_ID_LIS3DH,
|
||||
ACCEL_ID_KXSD9,
|
||||
ACCEL_ID_KXTF9,
|
||||
ACCEL_ID_KXTIK,
|
||||
ACCEL_ID_BMA150,
|
||||
ACCEL_ID_BMA222,
|
||||
ACCEL_ID_BMA250,
|
||||
ACCEL_ID_ADXL34X,
|
||||
ACCEL_ID_MMA8450,
|
||||
ACCEL_ID_MMA845X,
|
||||
ACCEL_ID_MPU6050,
|
||||
|
||||
COMPASS_ID_ALL,
|
||||
COMPASS_ID_AK8975,
|
||||
COMPASS_ID_AK8972,
|
||||
COMPASS_ID_AMI30X,
|
||||
COMPASS_ID_AMI306,
|
||||
COMPASS_ID_YAS529,
|
||||
COMPASS_ID_YAS530,
|
||||
COMPASS_ID_HMC5883,
|
||||
COMPASS_ID_LSM303DLH,
|
||||
COMPASS_ID_LSM303DLM,
|
||||
COMPASS_ID_MMC314X,
|
||||
COMPASS_ID_HSCDTD002B,
|
||||
COMPASS_ID_HSCDTD004A,
|
||||
|
||||
GYRO_ID_ALL,
|
||||
GYRO_ID_L3G4200D,
|
||||
GYRO_ID_K3G,
|
||||
|
||||
LIGHT_ID_ALL,
|
||||
LIGHT_ID_CM3217,
|
||||
LIGHT_ID_AL3006,
|
||||
LIGHT_ID_STK3171,
|
||||
|
||||
PROXIMITY_ID_ALL,
|
||||
PROXIMITY_ID_AL3006,
|
||||
PROXIMITY_ID_STK3171,
|
||||
TEMPERATURE_ID_ALL,
|
||||
|
||||
PRESSURE_ID_ALL,
|
||||
PRESSURE_ID_BMA085,
|
||||
};
|
||||
|
||||
|
||||
struct sensor_axis {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
struct sensor_operate {
|
||||
char *name;
|
||||
int type;
|
||||
int id_i2c;
|
||||
int range[2];
|
||||
int read_reg;
|
||||
int read_len;
|
||||
int id_reg;
|
||||
int id_data;
|
||||
int precision;
|
||||
int ctrl_reg;
|
||||
int ctrl_data;
|
||||
int int_ctrl_reg;
|
||||
int int_status_reg;
|
||||
int trig; //intterupt trigger
|
||||
int (*active)(struct i2c_client *client, int enable, int rate);
|
||||
int (*init)(struct i2c_client *client);
|
||||
int (*report)(struct i2c_client *client);
|
||||
int (*suspend)(struct i2c_client *client);
|
||||
int (*resume)(struct i2c_client *client);
|
||||
struct miscdevice *misc_dev;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* Platform data for the sensor */
|
||||
struct sensor_private_data {
|
||||
int type;
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
struct work_struct work;
|
||||
struct delayed_work delaywork; /*report second event*/
|
||||
struct sensor_axis axis;
|
||||
char sensor_data[40]; //max support40 bytes data
|
||||
atomic_t data_ready;
|
||||
wait_queue_head_t data_ready_wq;
|
||||
struct mutex data_mutex;
|
||||
struct mutex operation_mutex;
|
||||
struct mutex sensor_mutex;
|
||||
struct mutex i2c_mutex;
|
||||
int status_cur;
|
||||
int start_count;
|
||||
int devid;
|
||||
struct i2c_device_id *i2c_id;
|
||||
struct sensor_platform_data *pdata;
|
||||
struct sensor_operate *ops;
|
||||
struct file_operations fops;
|
||||
struct miscdevice miscdev;
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
struct early_suspend early_suspend;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
extern int sensor_register_slave(int type,struct i2c_client *client,
|
||||
struct sensor_platform_data *slave_pdata,
|
||||
struct sensor_operate *(*get_sensor_ops)(void));
|
||||
|
||||
|
||||
extern int sensor_unregister_slave(int type,struct i2c_client *client,
|
||||
struct sensor_platform_data *slave_pdata,
|
||||
struct sensor_operate *(*get_sensor_ops)(void));
|
||||
|
||||
|
||||
#define GSENSOR_IO 0xA1
|
||||
#define GBUFF_SIZE 12 /* Rx buffer size */
|
||||
|
||||
/* IOCTLs for MMA8452 library */
|
||||
#define GSENSOR_IOCTL_INIT _IO(GSENSOR_IO, 0x01)
|
||||
#define GSENSOR_IOCTL_RESET _IO(GSENSOR_IO, 0x04)
|
||||
#define GSENSOR_IOCTL_CLOSE _IO(GSENSOR_IO, 0x02)
|
||||
#define GSENSOR_IOCTL_START _IO(GSENSOR_IO, 0x03)
|
||||
#define GSENSOR_IOCTL_GETDATA _IOR(GSENSOR_IO, 0x08, char[GBUFF_SIZE+1])
|
||||
/* IOCTLs for APPs */
|
||||
#define GSENSOR_IOCTL_APP_SET_RATE _IOW(GSENSOR_IO, 0x10, char)
|
||||
|
||||
|
||||
#define LIGHTSENSOR_IOCTL_MAGIC 'l'
|
||||
#define LIGHTSENSOR_IOCTL_GET_ENABLED _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *)
|
||||
#define LIGHTSENSOR_IOCTL_ENABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *)
|
||||
#define LIGHTSENSOR_IOCTL_DISABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 3, int *)
|
||||
|
||||
#define PSENSOR_IOCTL_MAGIC 'c'
|
||||
#define PSENSOR_IOCTL_GET_ENABLED _IOR(PSENSOR_IOCTL_MAGIC, 1, int *)
|
||||
#define PSENSOR_IOCTL_ENABLE _IOW(PSENSOR_IOCTL_MAGIC, 2, int *)
|
||||
#define PSENSOR_IOCTL_DISABLE _IOW(PSENSOR_IOCTL_MAGIC, 3, int *)
|
||||
|
||||
|
||||
|
||||
|
||||
extern int sensor_rx_data(struct i2c_client *client, char *rxData, int length);
|
||||
extern int sensor_tx_data(struct i2c_client *client, char *txData, int length);
|
||||
extern int sensor_write_reg(struct i2c_client *client, int addr, int value);
|
||||
extern int sensor_read_reg(struct i2c_client *client, int addr);
|
||||
extern int sensor_tx_data_normal(struct i2c_client *client, char *buf, int num);
|
||||
extern int sensor_rx_data_normal(struct i2c_client *client, char *buf, int num);
|
||||
extern int sensor_write_reg_normal(struct i2c_client *client, char value);
|
||||
extern int sensor_read_reg_normal(struct i2c_client *client);
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue