mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
input: sensors: fromdos and remove trailing whitespace
Change-Id: I6799f2538f95953d1565ac805497161ce6043855 Signed-off-by: Huang, Tao <huangtao@rock-chips.com>
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
# sensor drivers
|
||||
obj-$(CONFIG_ANGLE_DEVICE) += angle/
|
||||
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_TEMPERATURE_DEVICE) += temperature/
|
||||
obj-$(CONFIG_PRESSURE_DEVICE) += pressure/
|
||||
obj-$(CONFIG_HALL_DEVICE) += hall/
|
||||
|
||||
|
||||
obj-$(CONFIG_SENSOR_DEVICE) += sensor-i2c.o
|
||||
obj-$(CONFIG_SENSOR_DEVICE) += sensor-dev.o
|
||||
# sensor drivers
|
||||
obj-$(CONFIG_ANGLE_DEVICE) += angle/
|
||||
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_TEMPERATURE_DEVICE) += temperature/
|
||||
obj-$(CONFIG_PRESSURE_DEVICE) += pressure/
|
||||
obj-$(CONFIG_HALL_DEVICE) += hall/
|
||||
|
||||
|
||||
obj-$(CONFIG_SENSOR_DEVICE) += sensor-i2c.o
|
||||
obj-$(CONFIG_SENSOR_DEVICE) += sensor-dev.o
|
||||
|
||||
@@ -1,483 +1,483 @@
|
||||
/* drivers/input/sensors/access/dmard10.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: guoyi <gy@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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
/* Default register settings */
|
||||
#define RBUFF_SIZE 12 /* Rx buffer size */
|
||||
|
||||
#define REG_ACTR 0x00
|
||||
#define REG_WDAL 0x01
|
||||
#define REG_TAPNS 0x0f
|
||||
#define REG_MISC2 0x1f
|
||||
#define REG_AFEM 0x0c
|
||||
#define REG_CKSEL 0x0d
|
||||
#define REG_INTC 0x0e
|
||||
#define REG_STADR 0x12
|
||||
#define REG_STAINT 0x1C
|
||||
#define REG_PD 0x21
|
||||
#define REG_TCGYZ 0x26
|
||||
#define REG_X_OUT 0x41
|
||||
|
||||
#define MODE_Off 0x00
|
||||
#define MODE_ResetAtOff 0x01
|
||||
#define MODE_Standby 0x02
|
||||
#define MODE_ResetAtStandby 0x03
|
||||
#define MODE_Active 0x06
|
||||
#define MODE_Trigger 0x0a
|
||||
#define MODE_ReadOTP 0x12
|
||||
#define MODE_WriteOTP 0x22
|
||||
#define MODE_WriteOTPBuf 0x42
|
||||
#define MODE_ResetDataPath 0x82
|
||||
|
||||
#define VALUE_STADR 0x55
|
||||
#define VALUE_STAINT 0xAA
|
||||
#define VALUE_AFEM_AFEN_Normal 0x8f// AFEN set 1 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
|
||||
#define VALUE_AFEM_Normal 0x0f// AFEN set 0 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
|
||||
#define VALUE_INTC 0x00// INTC[6:5]=b'00
|
||||
#define VALUE_INTC_Interrupt_En 0x20// INTC[6:5]=b'01 (Data ready interrupt enable, active high at INT0)
|
||||
#define VALUE_CKSEL_ODR_0_204 0x04// ODR[3:0]=b'0000 (0.78125Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_1_204 0x14// ODR[3:0]=b'0001 (1.5625Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_3_204 0x24// ODR[3:0]=b'0010 (3.125Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_6_204 0x34// ODR[3:0]=b'0011 (6.25Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_12_204 0x44// ODR[3:0]=b'0100 (12.5Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_25_204 0x54// ODR[3:0]=b'0101 (25Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_50_204 0x64// ODR[3:0]=b'0110 (50Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_100_204 0x74// ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
|
||||
#define VALUE_TAPNS_NoFilter 0x00 // TAP1/TAP2 NO FILTER
|
||||
#define VALUE_TAPNS_Ave_2 0x11 // TAP1/TAP2 Average 2
|
||||
#define VALUE_TAPNS_Ave_4 0x22 // TAP1/TAP2 Average 4
|
||||
#define VALUE_TAPNS_Ave_8 0x33 // TAP1/TAP2 Average 8
|
||||
#define VALUE_TAPNS_Ave_16 0x44 // TAP1/TAP2 Average 16
|
||||
#define VALUE_TAPNS_Ave_32 0x55 // TAP1/TAP2 Average 32
|
||||
#define VALUE_MISC2_OSCA_EN 0x08
|
||||
#define VALUE_PD_RST 0x52
|
||||
|
||||
|
||||
//#define DMARD10_REG_INTSU 0x47
|
||||
//#define DMARD10_REG_MODE 0x44
|
||||
//#define DMARD10_REG_SR 0x44
|
||||
|
||||
|
||||
#define DMARD10_REG_DS 0X49
|
||||
#define DMARD10_REG_ID 0X0F
|
||||
#define DMARD10_REG_IT 0X4D
|
||||
#define DMARD10_REG_INTSRC1_C 0X4A
|
||||
#define DMARD10_REG_INTSRC1_S 0X4B
|
||||
#define MMAIO 0xA1
|
||||
|
||||
// IOCTLs for DMARD10 library
|
||||
#define ECS_IOCTL_INIT _IO(MMAIO, 0x01)
|
||||
#define ECS_IOCTL_RESET _IO(MMAIO, 0x04)
|
||||
#define ECS_IOCTL_CLOSE _IO(MMAIO, 0x02)
|
||||
#define ECS_IOCTL_START _IO(MMAIO, 0x03)
|
||||
#define ECS_IOCTL_GETDATA _IOR(MMAIO, 0x08, char[RBUFF_SIZE+1])
|
||||
#define SENSOR_CALIBRATION _IOWR(MMAIO, 0x05 , int[SENSOR_DATA_SIZE])
|
||||
|
||||
// IOCTLs for APPs
|
||||
#define ECS_IOCTL_APP_SET_RATE _IOW(MMAIO, 0x10, char)
|
||||
|
||||
//rate
|
||||
#define DMARD10_RANGE 2000000
|
||||
|
||||
#define DMARD10_RATE_32 32
|
||||
/*
|
||||
#define DMARD10_RATE_64 64
|
||||
#define DMARD10_RATE_120 128
|
||||
#define DMARD10_RATE_MIN DMARD10_RATE_1
|
||||
#define DMARD10_RATE_MAX DMARD10_RATE_120
|
||||
*/
|
||||
/*status*/
|
||||
#define DMARD10_OPEN 1
|
||||
#define DMARD10_CLOSE 0
|
||||
#define DMARD10_NORMAL 2
|
||||
#define DMARD10_LOWPOWER 3
|
||||
|
||||
|
||||
|
||||
#define DMARD10_IIC_ADDR 0x18
|
||||
#define DMARD10_REG_LEN 11
|
||||
|
||||
|
||||
#define DMARD10_FATOR 15
|
||||
|
||||
|
||||
#define DMARD10_X_OUT 0x41
|
||||
#define SENSOR_DATA_SIZE 3
|
||||
#define DMARD10_SENSOR_RATE_1 0
|
||||
#define DMARD10_SENSOR_RATE_2 1
|
||||
#define DMARD10_SENSOR_RATE_3 2
|
||||
#define DMARD10_SENSOR_RATE_4 3
|
||||
|
||||
#define POWER_OR_RATE 1
|
||||
#define SW_RESET 1
|
||||
#define DMARD10_INTERRUPUT 1
|
||||
#define DMARD10_POWERDOWN 0
|
||||
#define DMARD10_POWERON 1
|
||||
|
||||
//g-senor layout configuration, choose one of the following configuration
|
||||
|
||||
#define AVG_NUM 16
|
||||
#define SENSOR_DATA_SIZE 3
|
||||
#define DEFAULT_SENSITIVITY 1024
|
||||
|
||||
|
||||
|
||||
#define DMARD10_ENABLE 1
|
||||
|
||||
#define DMARD10_REG_X_OUT 0x12
|
||||
#define DMARD10_REG_Y_OUT 0x1
|
||||
#define DMARD10_REG_Z_OUT 0x2
|
||||
#define DMARD10_REG_TILT 0x3
|
||||
#define DMARD10_REG_SRST 0x4
|
||||
#define DMARD10_REG_SPCNT 0x5
|
||||
#define DMARD10_REG_INTSU 0x6
|
||||
#define DMARD10_REG_MODE 0x7
|
||||
#define DMARD10_REG_SR 0x8
|
||||
#define DMARD10_REG_PDET 0x9
|
||||
#define DMARD10_REG_PD 0xa
|
||||
|
||||
#define DMARD10_RANGE 4000000
|
||||
#define DMARD10_PRECISION 10
|
||||
#define DMARD10_BOUNDARY (0x1 << (DMARD10_PRECISION - 1))
|
||||
#define DMARD10_GRAVITY_STEP (DMARD10_RANGE / DMARD10_BOUNDARY)
|
||||
|
||||
|
||||
struct sensor_axis_average {
|
||||
int x_average;
|
||||
int y_average;
|
||||
int z_average;
|
||||
int count;
|
||||
};
|
||||
|
||||
static struct sensor_axis_average axis_average;
|
||||
int gsensor_reset(struct i2c_client *client){
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
char buffer[7], buffer2[2];
|
||||
/* 1. check D10 , VALUE_STADR = 0x55 , VALUE_STAINT = 0xAA */
|
||||
buffer[0] = REG_STADR;
|
||||
buffer2[0] = REG_STAINT;
|
||||
|
||||
sensor_rx_data(client, buffer, 2);
|
||||
sensor_rx_data(client, buffer2, 2);
|
||||
|
||||
if( buffer[0] == VALUE_STADR || buffer2[0] == VALUE_STAINT){
|
||||
DBG(KERN_INFO " REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d\n", buffer[0], buffer2[0]);
|
||||
DBG(KERN_INFO " %s DMT_DEVICE_NAME registered I2C driver!\n",__FUNCTION__);
|
||||
}
|
||||
else{
|
||||
DBG(KERN_INFO " %s gsensor I2C err @@@ REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d \n", __func__, buffer[0], buffer2[0]);
|
||||
return -1;
|
||||
}
|
||||
/* 2. Powerdown reset */
|
||||
buffer[0] = REG_PD;
|
||||
buffer[1] = VALUE_PD_RST;
|
||||
sensor_tx_data(client, buffer, 2);
|
||||
/* 3. ACTR => Standby mode => Download OTP to parameter reg => Standby mode => Reset data path => Standby mode */
|
||||
buffer[0] = REG_ACTR;
|
||||
buffer[1] = MODE_Standby;
|
||||
buffer[2] = MODE_ReadOTP;
|
||||
buffer[3] = MODE_Standby;
|
||||
buffer[4] = MODE_ResetDataPath;
|
||||
buffer[5] = MODE_Standby;
|
||||
sensor_tx_data(client, buffer, 6);
|
||||
/* 4. OSCA_EN = 1 ,TSTO = b'000(INT1 = normal, TEST0 = normal) */
|
||||
buffer[0] = REG_MISC2;
|
||||
buffer[1] = VALUE_MISC2_OSCA_EN;
|
||||
sensor_tx_data(client, buffer, 2);
|
||||
/* 5. AFEN = 1(AFE will powerdown after ADC) */
|
||||
buffer[0] = REG_AFEM;
|
||||
buffer[1] = VALUE_AFEM_AFEN_Normal;
|
||||
buffer[2] = VALUE_CKSEL_ODR_100_204;
|
||||
buffer[3] = VALUE_INTC;
|
||||
buffer[4] = VALUE_TAPNS_Ave_2;
|
||||
buffer[5] = 0x00; // DLYC, no delay timing
|
||||
buffer[6] = 0x07; // INTD=1 (push-pull), INTA=1 (active high), AUTOT=1 (enable T)
|
||||
sensor_tx_data(client, buffer, 7);
|
||||
/* 6. write TCGYZ & TCGX */
|
||||
buffer[0] = REG_WDAL; // REG:0x01
|
||||
buffer[1] = 0x00; // set TC of Y,Z gain value
|
||||
buffer[2] = 0x00; // set TC of X gain value
|
||||
buffer[3] = 0x03; // Temperature coefficient of X,Y,Z gain
|
||||
sensor_tx_data(client, buffer, 4);
|
||||
|
||||
buffer[0] = REG_ACTR; // REG:0x00
|
||||
buffer[1] = MODE_Standby; // Standby
|
||||
buffer[2] = MODE_WriteOTPBuf; // WriteOTPBuf
|
||||
buffer[3] = MODE_Standby; // Standby
|
||||
|
||||
/* 7. Activation mode */
|
||||
buffer[0] = REG_ACTR;
|
||||
buffer[1] = MODE_Active;
|
||||
sensor_tx_data(client, buffer, 2);
|
||||
printk("\n dmard10 gsensor _reset SUCCESS!!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************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;
|
||||
gsensor_reset(client);
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
status = DMARD10_ENABLE; //dmard10
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~DMARD10_ENABLE; //dmard10
|
||||
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;
|
||||
|
||||
DBG("%s:DMARD10_REG_TILT=0x%x\n",__func__,sensor_read_reg(client, DMARD10_REG_TILT));
|
||||
|
||||
result = sensor_write_reg(client, DMARD10_REG_SR, (0x01<<5)| 0x02); //32 Samples/Second Active and Auto-Sleep Mode
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(sensor->pdata->irq_enable) //open interrupt
|
||||
{
|
||||
result = sensor_write_reg(client, DMARD10_REG_INTSU, 1<<4);//enable int,GINT=1
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
sensor->ops->ctrl_data = 1<<6; //Interrupt output INT is push-pull
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
memset(&axis_average, 0, sizeof(struct sensor_axis_average));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
|
||||
{
|
||||
s64 result;
|
||||
|
||||
|
||||
result = ((int)high_byte << 8)|((int)low_byte);
|
||||
|
||||
if (result < DMARD10_BOUNDARY){
|
||||
result = result* DMARD10_GRAVITY_STEP;
|
||||
}else{
|
||||
result = ~( ((~result & (0x7fff>>(16-DMARD10_PRECISION)) ) + 1)* DMARD10_GRAVITY_STEP) + 1;
|
||||
}
|
||||
|
||||
return 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 DMARD10_COUNT_AVERAGE 2
|
||||
#define GSENSOR_MIN 2
|
||||
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[8] = {0};
|
||||
char value = 0;
|
||||
|
||||
if(sensor->ops->read_len < 3) //sensor->ops->read_len = 3
|
||||
{
|
||||
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);
|
||||
|
||||
//this gsensor need 6 bytes buffer
|
||||
x = sensor_convert_data(sensor->client, buffer[3], buffer[2]); //buffer[1]:high bit
|
||||
y = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
|
||||
z = sensor_convert_data(sensor->client, buffer[7], buffer[6]);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
axis_average.x_average += axis.x;
|
||||
axis_average.y_average += axis.y;
|
||||
axis_average.z_average += axis.z;
|
||||
axis_average.count++;
|
||||
|
||||
if(axis_average.count >= DMARD10_COUNT_AVERAGE)
|
||||
{
|
||||
axis.x = axis_average.x_average / axis_average.count;
|
||||
axis.y = axis_average.y_average / axis_average.count;
|
||||
axis.z = axis_average.z_average / axis_average.count;
|
||||
|
||||
DBG( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
|
||||
|
||||
memset(&axis_average, 0, sizeof(struct sensor_axis_average));
|
||||
|
||||
//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);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gsensor_dmard10_ops = {
|
||||
.name = "gs_dmard10",
|
||||
.type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct
|
||||
.id_i2c = ACCEL_ID_DMARD10, //i2c id number
|
||||
.read_reg = DMARD10_REG_X_OUT, //read data
|
||||
.read_len = 8, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = DMARD10_PRECISION, //12 bit
|
||||
.ctrl_reg = DMARD10_REG_MODE, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {-DMARD10_RANGE,DMARD10_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
|
||||
static struct sensor_operate *gsensor_get_ops(void)
|
||||
{
|
||||
return &gsensor_dmard10_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gsensor_dmard10_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gsensor_dmard10_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_dmard10_init);
|
||||
module_exit(gsensor_dmard10_exit);
|
||||
|
||||
|
||||
|
||||
/* drivers/input/sensors/access/dmard10.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: guoyi <gy@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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
/* Default register settings */
|
||||
#define RBUFF_SIZE 12 /* Rx buffer size */
|
||||
|
||||
#define REG_ACTR 0x00
|
||||
#define REG_WDAL 0x01
|
||||
#define REG_TAPNS 0x0f
|
||||
#define REG_MISC2 0x1f
|
||||
#define REG_AFEM 0x0c
|
||||
#define REG_CKSEL 0x0d
|
||||
#define REG_INTC 0x0e
|
||||
#define REG_STADR 0x12
|
||||
#define REG_STAINT 0x1C
|
||||
#define REG_PD 0x21
|
||||
#define REG_TCGYZ 0x26
|
||||
#define REG_X_OUT 0x41
|
||||
|
||||
#define MODE_Off 0x00
|
||||
#define MODE_ResetAtOff 0x01
|
||||
#define MODE_Standby 0x02
|
||||
#define MODE_ResetAtStandby 0x03
|
||||
#define MODE_Active 0x06
|
||||
#define MODE_Trigger 0x0a
|
||||
#define MODE_ReadOTP 0x12
|
||||
#define MODE_WriteOTP 0x22
|
||||
#define MODE_WriteOTPBuf 0x42
|
||||
#define MODE_ResetDataPath 0x82
|
||||
|
||||
#define VALUE_STADR 0x55
|
||||
#define VALUE_STAINT 0xAA
|
||||
#define VALUE_AFEM_AFEN_Normal 0x8f// AFEN set 1 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
|
||||
#define VALUE_AFEM_Normal 0x0f// AFEN set 0 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
|
||||
#define VALUE_INTC 0x00// INTC[6:5]=b'00
|
||||
#define VALUE_INTC_Interrupt_En 0x20// INTC[6:5]=b'01 (Data ready interrupt enable, active high at INT0)
|
||||
#define VALUE_CKSEL_ODR_0_204 0x04// ODR[3:0]=b'0000 (0.78125Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_1_204 0x14// ODR[3:0]=b'0001 (1.5625Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_3_204 0x24// ODR[3:0]=b'0010 (3.125Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_6_204 0x34// ODR[3:0]=b'0011 (6.25Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_12_204 0x44// ODR[3:0]=b'0100 (12.5Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_25_204 0x54// ODR[3:0]=b'0101 (25Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_50_204 0x64// ODR[3:0]=b'0110 (50Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
#define VALUE_CKSEL_ODR_100_204 0x74// ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ)
|
||||
|
||||
#define VALUE_TAPNS_NoFilter 0x00 // TAP1/TAP2 NO FILTER
|
||||
#define VALUE_TAPNS_Ave_2 0x11 // TAP1/TAP2 Average 2
|
||||
#define VALUE_TAPNS_Ave_4 0x22 // TAP1/TAP2 Average 4
|
||||
#define VALUE_TAPNS_Ave_8 0x33 // TAP1/TAP2 Average 8
|
||||
#define VALUE_TAPNS_Ave_16 0x44 // TAP1/TAP2 Average 16
|
||||
#define VALUE_TAPNS_Ave_32 0x55 // TAP1/TAP2 Average 32
|
||||
#define VALUE_MISC2_OSCA_EN 0x08
|
||||
#define VALUE_PD_RST 0x52
|
||||
|
||||
|
||||
//#define DMARD10_REG_INTSU 0x47
|
||||
//#define DMARD10_REG_MODE 0x44
|
||||
//#define DMARD10_REG_SR 0x44
|
||||
|
||||
|
||||
#define DMARD10_REG_DS 0X49
|
||||
#define DMARD10_REG_ID 0X0F
|
||||
#define DMARD10_REG_IT 0X4D
|
||||
#define DMARD10_REG_INTSRC1_C 0X4A
|
||||
#define DMARD10_REG_INTSRC1_S 0X4B
|
||||
#define MMAIO 0xA1
|
||||
|
||||
// IOCTLs for DMARD10 library
|
||||
#define ECS_IOCTL_INIT _IO(MMAIO, 0x01)
|
||||
#define ECS_IOCTL_RESET _IO(MMAIO, 0x04)
|
||||
#define ECS_IOCTL_CLOSE _IO(MMAIO, 0x02)
|
||||
#define ECS_IOCTL_START _IO(MMAIO, 0x03)
|
||||
#define ECS_IOCTL_GETDATA _IOR(MMAIO, 0x08, char[RBUFF_SIZE+1])
|
||||
#define SENSOR_CALIBRATION _IOWR(MMAIO, 0x05 , int[SENSOR_DATA_SIZE])
|
||||
|
||||
// IOCTLs for APPs
|
||||
#define ECS_IOCTL_APP_SET_RATE _IOW(MMAIO, 0x10, char)
|
||||
|
||||
//rate
|
||||
#define DMARD10_RANGE 2000000
|
||||
|
||||
#define DMARD10_RATE_32 32
|
||||
/*
|
||||
#define DMARD10_RATE_64 64
|
||||
#define DMARD10_RATE_120 128
|
||||
#define DMARD10_RATE_MIN DMARD10_RATE_1
|
||||
#define DMARD10_RATE_MAX DMARD10_RATE_120
|
||||
*/
|
||||
/*status*/
|
||||
#define DMARD10_OPEN 1
|
||||
#define DMARD10_CLOSE 0
|
||||
#define DMARD10_NORMAL 2
|
||||
#define DMARD10_LOWPOWER 3
|
||||
|
||||
|
||||
|
||||
#define DMARD10_IIC_ADDR 0x18
|
||||
#define DMARD10_REG_LEN 11
|
||||
|
||||
|
||||
#define DMARD10_FATOR 15
|
||||
|
||||
|
||||
#define DMARD10_X_OUT 0x41
|
||||
#define SENSOR_DATA_SIZE 3
|
||||
#define DMARD10_SENSOR_RATE_1 0
|
||||
#define DMARD10_SENSOR_RATE_2 1
|
||||
#define DMARD10_SENSOR_RATE_3 2
|
||||
#define DMARD10_SENSOR_RATE_4 3
|
||||
|
||||
#define POWER_OR_RATE 1
|
||||
#define SW_RESET 1
|
||||
#define DMARD10_INTERRUPUT 1
|
||||
#define DMARD10_POWERDOWN 0
|
||||
#define DMARD10_POWERON 1
|
||||
|
||||
//g-senor layout configuration, choose one of the following configuration
|
||||
|
||||
#define AVG_NUM 16
|
||||
#define SENSOR_DATA_SIZE 3
|
||||
#define DEFAULT_SENSITIVITY 1024
|
||||
|
||||
|
||||
|
||||
#define DMARD10_ENABLE 1
|
||||
|
||||
#define DMARD10_REG_X_OUT 0x12
|
||||
#define DMARD10_REG_Y_OUT 0x1
|
||||
#define DMARD10_REG_Z_OUT 0x2
|
||||
#define DMARD10_REG_TILT 0x3
|
||||
#define DMARD10_REG_SRST 0x4
|
||||
#define DMARD10_REG_SPCNT 0x5
|
||||
#define DMARD10_REG_INTSU 0x6
|
||||
#define DMARD10_REG_MODE 0x7
|
||||
#define DMARD10_REG_SR 0x8
|
||||
#define DMARD10_REG_PDET 0x9
|
||||
#define DMARD10_REG_PD 0xa
|
||||
|
||||
#define DMARD10_RANGE 4000000
|
||||
#define DMARD10_PRECISION 10
|
||||
#define DMARD10_BOUNDARY (0x1 << (DMARD10_PRECISION - 1))
|
||||
#define DMARD10_GRAVITY_STEP (DMARD10_RANGE / DMARD10_BOUNDARY)
|
||||
|
||||
|
||||
struct sensor_axis_average {
|
||||
int x_average;
|
||||
int y_average;
|
||||
int z_average;
|
||||
int count;
|
||||
};
|
||||
|
||||
static struct sensor_axis_average axis_average;
|
||||
int gsensor_reset(struct i2c_client *client){
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
char buffer[7], buffer2[2];
|
||||
/* 1. check D10 , VALUE_STADR = 0x55 , VALUE_STAINT = 0xAA */
|
||||
buffer[0] = REG_STADR;
|
||||
buffer2[0] = REG_STAINT;
|
||||
|
||||
sensor_rx_data(client, buffer, 2);
|
||||
sensor_rx_data(client, buffer2, 2);
|
||||
|
||||
if( buffer[0] == VALUE_STADR || buffer2[0] == VALUE_STAINT){
|
||||
DBG(KERN_INFO " REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d\n", buffer[0], buffer2[0]);
|
||||
DBG(KERN_INFO " %s DMT_DEVICE_NAME registered I2C driver!\n",__FUNCTION__);
|
||||
}
|
||||
else{
|
||||
DBG(KERN_INFO " %s gsensor I2C err @@@ REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d \n", __func__, buffer[0], buffer2[0]);
|
||||
return -1;
|
||||
}
|
||||
/* 2. Powerdown reset */
|
||||
buffer[0] = REG_PD;
|
||||
buffer[1] = VALUE_PD_RST;
|
||||
sensor_tx_data(client, buffer, 2);
|
||||
/* 3. ACTR => Standby mode => Download OTP to parameter reg => Standby mode => Reset data path => Standby mode */
|
||||
buffer[0] = REG_ACTR;
|
||||
buffer[1] = MODE_Standby;
|
||||
buffer[2] = MODE_ReadOTP;
|
||||
buffer[3] = MODE_Standby;
|
||||
buffer[4] = MODE_ResetDataPath;
|
||||
buffer[5] = MODE_Standby;
|
||||
sensor_tx_data(client, buffer, 6);
|
||||
/* 4. OSCA_EN = 1 ,TSTO = b'000(INT1 = normal, TEST0 = normal) */
|
||||
buffer[0] = REG_MISC2;
|
||||
buffer[1] = VALUE_MISC2_OSCA_EN;
|
||||
sensor_tx_data(client, buffer, 2);
|
||||
/* 5. AFEN = 1(AFE will powerdown after ADC) */
|
||||
buffer[0] = REG_AFEM;
|
||||
buffer[1] = VALUE_AFEM_AFEN_Normal;
|
||||
buffer[2] = VALUE_CKSEL_ODR_100_204;
|
||||
buffer[3] = VALUE_INTC;
|
||||
buffer[4] = VALUE_TAPNS_Ave_2;
|
||||
buffer[5] = 0x00; // DLYC, no delay timing
|
||||
buffer[6] = 0x07; // INTD=1 (push-pull), INTA=1 (active high), AUTOT=1 (enable T)
|
||||
sensor_tx_data(client, buffer, 7);
|
||||
/* 6. write TCGYZ & TCGX */
|
||||
buffer[0] = REG_WDAL; // REG:0x01
|
||||
buffer[1] = 0x00; // set TC of Y,Z gain value
|
||||
buffer[2] = 0x00; // set TC of X gain value
|
||||
buffer[3] = 0x03; // Temperature coefficient of X,Y,Z gain
|
||||
sensor_tx_data(client, buffer, 4);
|
||||
|
||||
buffer[0] = REG_ACTR; // REG:0x00
|
||||
buffer[1] = MODE_Standby; // Standby
|
||||
buffer[2] = MODE_WriteOTPBuf; // WriteOTPBuf
|
||||
buffer[3] = MODE_Standby; // Standby
|
||||
|
||||
/* 7. Activation mode */
|
||||
buffer[0] = REG_ACTR;
|
||||
buffer[1] = MODE_Active;
|
||||
sensor_tx_data(client, buffer, 2);
|
||||
printk("\n dmard10 gsensor _reset SUCCESS!!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************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;
|
||||
gsensor_reset(client);
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
status = DMARD10_ENABLE; //dmard10
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~DMARD10_ENABLE; //dmard10
|
||||
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;
|
||||
|
||||
DBG("%s:DMARD10_REG_TILT=0x%x\n",__func__,sensor_read_reg(client, DMARD10_REG_TILT));
|
||||
|
||||
result = sensor_write_reg(client, DMARD10_REG_SR, (0x01<<5)| 0x02); //32 Samples/Second Active and Auto-Sleep Mode
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(sensor->pdata->irq_enable) //open interrupt
|
||||
{
|
||||
result = sensor_write_reg(client, DMARD10_REG_INTSU, 1<<4);//enable int,GINT=1
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
sensor->ops->ctrl_data = 1<<6; //Interrupt output INT is push-pull
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
memset(&axis_average, 0, sizeof(struct sensor_axis_average));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
|
||||
{
|
||||
s64 result;
|
||||
|
||||
|
||||
result = ((int)high_byte << 8)|((int)low_byte);
|
||||
|
||||
if (result < DMARD10_BOUNDARY){
|
||||
result = result* DMARD10_GRAVITY_STEP;
|
||||
}else{
|
||||
result = ~( ((~result & (0x7fff>>(16-DMARD10_PRECISION)) ) + 1)* DMARD10_GRAVITY_STEP) + 1;
|
||||
}
|
||||
|
||||
return 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 DMARD10_COUNT_AVERAGE 2
|
||||
#define GSENSOR_MIN 2
|
||||
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[8] = {0};
|
||||
char value = 0;
|
||||
|
||||
if(sensor->ops->read_len < 3) //sensor->ops->read_len = 3
|
||||
{
|
||||
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);
|
||||
|
||||
//this gsensor need 6 bytes buffer
|
||||
x = sensor_convert_data(sensor->client, buffer[3], buffer[2]); //buffer[1]:high bit
|
||||
y = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
|
||||
z = sensor_convert_data(sensor->client, buffer[7], buffer[6]);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
axis_average.x_average += axis.x;
|
||||
axis_average.y_average += axis.y;
|
||||
axis_average.z_average += axis.z;
|
||||
axis_average.count++;
|
||||
|
||||
if(axis_average.count >= DMARD10_COUNT_AVERAGE)
|
||||
{
|
||||
axis.x = axis_average.x_average / axis_average.count;
|
||||
axis.y = axis_average.y_average / axis_average.count;
|
||||
axis.z = axis_average.z_average / axis_average.count;
|
||||
|
||||
DBG( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
|
||||
|
||||
memset(&axis_average, 0, sizeof(struct sensor_axis_average));
|
||||
|
||||
//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);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gsensor_dmard10_ops = {
|
||||
.name = "gs_dmard10",
|
||||
.type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct
|
||||
.id_i2c = ACCEL_ID_DMARD10, //i2c id number
|
||||
.read_reg = DMARD10_REG_X_OUT, //read data
|
||||
.read_len = 8, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = DMARD10_PRECISION, //12 bit
|
||||
.ctrl_reg = DMARD10_REG_MODE, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {-DMARD10_RANGE,DMARD10_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
|
||||
static struct sensor_operate *gsensor_get_ops(void)
|
||||
{
|
||||
return &gsensor_dmard10_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gsensor_dmard10_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gsensor_dmard10_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_dmard10_init);
|
||||
module_exit(gsensor_dmard10_exit);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,366 +1,366 @@
|
||||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: Bruins <xwj@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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define LSM303D_WHO_AM_I (0x0F)
|
||||
|
||||
/* full scale setting - register & mask */
|
||||
#define LSM303D_CTRL_REG0 (0x1F)
|
||||
#define LSM303D_CTRL_REG1 (0x20)
|
||||
#define LSM303D_CTRL_REG2 (0x21)
|
||||
#define LSM303D_CTRL_REG3 (0x22)
|
||||
#define LSM303D_CTRL_REG4 (0x23)
|
||||
#define LSM303D_CTRL_REG5 (0x24)
|
||||
#define LSM303D_CTRL_REG6 (0x25)
|
||||
#define LSM303D_CTRL_REG7 (0x26)
|
||||
#define LSM303D_STATUS_REG (0x27)
|
||||
#define LSM303D_OUT_X_L (0x28)
|
||||
#define LSM303D_OUT_X_H (0x29)
|
||||
#define LSM303D_OUT_Y_L (0x2a)
|
||||
#define LSM303D_OUT_Y_H (0x2b)
|
||||
#define LSM303D_OUT_Z_L (0x2c)
|
||||
#define LSM303D_OUT_Z_H (0x2d)
|
||||
#define LSM303D_FIFO_CTRL_REG (0x2E)
|
||||
#define LSM303D_FIFO_SRC_REG (0X2F)
|
||||
|
||||
#define LSM303D_IG_CFG1 (0x30)
|
||||
#define LSM303D_IG_SRC1 (0x31)
|
||||
#define LSM303D_IG_THS1 (0x32)
|
||||
#define LSM303D_IG_DURATION1 (0x33)
|
||||
|
||||
#define LSM303D_IG_CFG2 (0x34)
|
||||
#define LSM303D_IG_SRC2 (0x35)
|
||||
#define LSM303D_IG_THS2 (0x36)
|
||||
#define LSM303D_IG_DURATION2 (0x37)
|
||||
|
||||
|
||||
#define LSM303D_DEVID (0x49) //chip id
|
||||
#define LSM303D_ACC_DISABLE (0x08)
|
||||
|
||||
#define LSM303D_RANGE 2000000
|
||||
|
||||
/* LSM303D */
|
||||
#define LSM303D_PRECISION 16
|
||||
#define LSM303D_BOUNDARY (0x1 << (LSM303D_PRECISION - 1))
|
||||
#define LSM303D_GRAVITY_STEP (LSM303D_RANGE / LSM303D_BOUNDARY)
|
||||
|
||||
#define ODR3P25 0x10 /* 3.25Hz output data rate */
|
||||
#define ODR6P25 0x20 /* 6.25Hz output data rate */
|
||||
#define ODR12P5 0x30 /* 12.5Hz output data rate */
|
||||
#define ODR25 0x40 /* 25Hz output data rate */
|
||||
#define ODR50 0x50 /* 50Hz output data rate */
|
||||
#define ODR100 0x60 /* 100Hz output data rate */
|
||||
#define ODR200 0x70 /* 200Hz output data rate */
|
||||
#define ODR400 0x80 /* 400Hz output data rate */
|
||||
#define ODR800 0x90 /* 800Hz output data rate */
|
||||
#define ODR1600 0xA0 /* 1600Hz output data rate */
|
||||
|
||||
|
||||
struct sensor_reg_data {
|
||||
char reg;
|
||||
char data;
|
||||
};
|
||||
|
||||
/****************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);
|
||||
|
||||
sensor->ops->ctrl_data |= ODR100; //100HZ,if 0 then power down
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(!enable)
|
||||
{
|
||||
status = LSM303D_ACC_DISABLE; //lis3dh
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~LSM303D_ACC_DISABLE; //lis3dh
|
||||
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;
|
||||
int i;
|
||||
|
||||
struct sensor_reg_data reg_data[] =
|
||||
{
|
||||
{LSM303D_CTRL_REG0,0x00},
|
||||
{LSM303D_CTRL_REG1,0x07},
|
||||
{LSM303D_CTRL_REG2,0x00},
|
||||
{LSM303D_CTRL_REG3,0x00},
|
||||
{LSM303D_CTRL_REG4,0x00},
|
||||
{LSM303D_CTRL_REG5,0x78}, //High resolution output mode:11,
|
||||
{LSM303D_CTRL_REG6,0x20},
|
||||
{LSM303D_CTRL_REG7,0x00},
|
||||
{LSM303D_FIFO_CTRL_REG,0x00},
|
||||
{LSM303D_IG_CFG1,0xFF}, //6 direction position recognition
|
||||
{LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold
|
||||
{LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f
|
||||
|
||||
/*
|
||||
{LSM303D_CTRL_REG7,0x00},
|
||||
{LSM303D_CTRL_REG4,0x08}, //High resolution output mode: 1, Normal mode
|
||||
{LSM303D_CTRL_REG6,0x40},
|
||||
|
||||
{LSM303D_FIFO_CTRL_REG,0x00}, //
|
||||
{LSM303D_IG_CFG1,0xFF}, //6 direction position recognition
|
||||
{LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold
|
||||
{LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f
|
||||
*/
|
||||
};
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
for(i=0;i<(sizeof(reg_data)/sizeof(struct sensor_reg_data));i++)
|
||||
{
|
||||
result = sensor_write_reg(client, reg_data[i].reg, reg_data[i].data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,i=%d,error\n",__func__,__LINE__,i);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
|
||||
result = sensor_write_reg(client, LSM303D_CTRL_REG3, 0x20);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
i = sensor_read_reg(client,LSM303D_CTRL_REG5);
|
||||
|
||||
result = sensor_write_reg(client, LSM303D_CTRL_REG5, (i|0x01));
|
||||
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);
|
||||
|
||||
switch (sensor->devid) {
|
||||
case LSM303D_DEVID:
|
||||
result = ((int)high_byte << 8) | (int)low_byte;
|
||||
if (result < LSM303D_BOUNDARY)
|
||||
result = result* LSM303D_GRAVITY_STEP;
|
||||
else
|
||||
result = ~( ((~result & (0x7fff>>(16-LSM303D_PRECISION)) ) + 1)
|
||||
* LSM303D_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};
|
||||
char value = 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);
|
||||
|
||||
value = sensor_read_reg(client, LSM303D_STATUS_REG);
|
||||
if((value & 0x0f) == 0)
|
||||
{
|
||||
printk("%s:line=%d,value=0x%x,data is not ready\n",__func__,__LINE__,value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
//printk( "%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);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct sensor_operate gsensor_lsm303d_ops = {
|
||||
.name = "lsm303d",
|
||||
.type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct
|
||||
.id_i2c = ACCEL_ID_LSM303D, //i2c id number
|
||||
.read_reg = (LSM303D_OUT_X_L | 0x80), //read data
|
||||
.read_len = 6, //data length
|
||||
.id_reg = LSM303D_WHO_AM_I, //read device id from this register
|
||||
.id_data = LSM303D_DEVID, //device id
|
||||
.precision = LSM303D_PRECISION, //16 bits
|
||||
.ctrl_reg = LSM303D_CTRL_REG1, //enable or disable
|
||||
.int_status_reg = LSM303D_IG_SRC1, //intterupt status register
|
||||
.range = {-LSM303D_RANGE,LSM303D_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
|
||||
static struct sensor_operate *gsensor_get_ops(void)
|
||||
{
|
||||
return &gsensor_lsm303d_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gsensor_lis3dh_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gsensor_lis3dh_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_lis3dh_init);
|
||||
module_exit(gsensor_lis3dh_exit);
|
||||
|
||||
|
||||
|
||||
|
||||
/* drivers/input/sensors/access/kxtik.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: Bruins <xwj@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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define LSM303D_WHO_AM_I (0x0F)
|
||||
|
||||
/* full scale setting - register & mask */
|
||||
#define LSM303D_CTRL_REG0 (0x1F)
|
||||
#define LSM303D_CTRL_REG1 (0x20)
|
||||
#define LSM303D_CTRL_REG2 (0x21)
|
||||
#define LSM303D_CTRL_REG3 (0x22)
|
||||
#define LSM303D_CTRL_REG4 (0x23)
|
||||
#define LSM303D_CTRL_REG5 (0x24)
|
||||
#define LSM303D_CTRL_REG6 (0x25)
|
||||
#define LSM303D_CTRL_REG7 (0x26)
|
||||
#define LSM303D_STATUS_REG (0x27)
|
||||
#define LSM303D_OUT_X_L (0x28)
|
||||
#define LSM303D_OUT_X_H (0x29)
|
||||
#define LSM303D_OUT_Y_L (0x2a)
|
||||
#define LSM303D_OUT_Y_H (0x2b)
|
||||
#define LSM303D_OUT_Z_L (0x2c)
|
||||
#define LSM303D_OUT_Z_H (0x2d)
|
||||
#define LSM303D_FIFO_CTRL_REG (0x2E)
|
||||
#define LSM303D_FIFO_SRC_REG (0X2F)
|
||||
|
||||
#define LSM303D_IG_CFG1 (0x30)
|
||||
#define LSM303D_IG_SRC1 (0x31)
|
||||
#define LSM303D_IG_THS1 (0x32)
|
||||
#define LSM303D_IG_DURATION1 (0x33)
|
||||
|
||||
#define LSM303D_IG_CFG2 (0x34)
|
||||
#define LSM303D_IG_SRC2 (0x35)
|
||||
#define LSM303D_IG_THS2 (0x36)
|
||||
#define LSM303D_IG_DURATION2 (0x37)
|
||||
|
||||
|
||||
#define LSM303D_DEVID (0x49) //chip id
|
||||
#define LSM303D_ACC_DISABLE (0x08)
|
||||
|
||||
#define LSM303D_RANGE 2000000
|
||||
|
||||
/* LSM303D */
|
||||
#define LSM303D_PRECISION 16
|
||||
#define LSM303D_BOUNDARY (0x1 << (LSM303D_PRECISION - 1))
|
||||
#define LSM303D_GRAVITY_STEP (LSM303D_RANGE / LSM303D_BOUNDARY)
|
||||
|
||||
#define ODR3P25 0x10 /* 3.25Hz output data rate */
|
||||
#define ODR6P25 0x20 /* 6.25Hz output data rate */
|
||||
#define ODR12P5 0x30 /* 12.5Hz output data rate */
|
||||
#define ODR25 0x40 /* 25Hz output data rate */
|
||||
#define ODR50 0x50 /* 50Hz output data rate */
|
||||
#define ODR100 0x60 /* 100Hz output data rate */
|
||||
#define ODR200 0x70 /* 200Hz output data rate */
|
||||
#define ODR400 0x80 /* 400Hz output data rate */
|
||||
#define ODR800 0x90 /* 800Hz output data rate */
|
||||
#define ODR1600 0xA0 /* 1600Hz output data rate */
|
||||
|
||||
|
||||
struct sensor_reg_data {
|
||||
char reg;
|
||||
char data;
|
||||
};
|
||||
|
||||
/****************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);
|
||||
|
||||
sensor->ops->ctrl_data |= ODR100; //100HZ,if 0 then power down
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(!enable)
|
||||
{
|
||||
status = LSM303D_ACC_DISABLE; //lis3dh
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~LSM303D_ACC_DISABLE; //lis3dh
|
||||
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;
|
||||
int i;
|
||||
|
||||
struct sensor_reg_data reg_data[] =
|
||||
{
|
||||
{LSM303D_CTRL_REG0,0x00},
|
||||
{LSM303D_CTRL_REG1,0x07},
|
||||
{LSM303D_CTRL_REG2,0x00},
|
||||
{LSM303D_CTRL_REG3,0x00},
|
||||
{LSM303D_CTRL_REG4,0x00},
|
||||
{LSM303D_CTRL_REG5,0x78}, //High resolution output mode:11,
|
||||
{LSM303D_CTRL_REG6,0x20},
|
||||
{LSM303D_CTRL_REG7,0x00},
|
||||
{LSM303D_FIFO_CTRL_REG,0x00},
|
||||
{LSM303D_IG_CFG1,0xFF}, //6 direction position recognition
|
||||
{LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold
|
||||
{LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f
|
||||
|
||||
/*
|
||||
{LSM303D_CTRL_REG7,0x00},
|
||||
{LSM303D_CTRL_REG4,0x08}, //High resolution output mode: 1, Normal mode
|
||||
{LSM303D_CTRL_REG6,0x40},
|
||||
|
||||
{LSM303D_FIFO_CTRL_REG,0x00}, //
|
||||
{LSM303D_IG_CFG1,0xFF}, //6 direction position recognition
|
||||
{LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold
|
||||
{LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f
|
||||
*/
|
||||
};
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
for(i=0;i<(sizeof(reg_data)/sizeof(struct sensor_reg_data));i++)
|
||||
{
|
||||
result = sensor_write_reg(client, reg_data[i].reg, reg_data[i].data);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,i=%d,error\n",__func__,__LINE__,i);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
|
||||
result = sensor_write_reg(client, LSM303D_CTRL_REG3, 0x20);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
i = sensor_read_reg(client,LSM303D_CTRL_REG5);
|
||||
|
||||
result = sensor_write_reg(client, LSM303D_CTRL_REG5, (i|0x01));
|
||||
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);
|
||||
|
||||
switch (sensor->devid) {
|
||||
case LSM303D_DEVID:
|
||||
result = ((int)high_byte << 8) | (int)low_byte;
|
||||
if (result < LSM303D_BOUNDARY)
|
||||
result = result* LSM303D_GRAVITY_STEP;
|
||||
else
|
||||
result = ~( ((~result & (0x7fff>>(16-LSM303D_PRECISION)) ) + 1)
|
||||
* LSM303D_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};
|
||||
char value = 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);
|
||||
|
||||
value = sensor_read_reg(client, LSM303D_STATUS_REG);
|
||||
if((value & 0x0f) == 0)
|
||||
{
|
||||
printk("%s:line=%d,value=0x%x,data is not ready\n",__func__,__LINE__,value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
//printk( "%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);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct sensor_operate gsensor_lsm303d_ops = {
|
||||
.name = "lsm303d",
|
||||
.type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct
|
||||
.id_i2c = ACCEL_ID_LSM303D, //i2c id number
|
||||
.read_reg = (LSM303D_OUT_X_L | 0x80), //read data
|
||||
.read_len = 6, //data length
|
||||
.id_reg = LSM303D_WHO_AM_I, //read device id from this register
|
||||
.id_data = LSM303D_DEVID, //device id
|
||||
.precision = LSM303D_PRECISION, //16 bits
|
||||
.ctrl_reg = LSM303D_CTRL_REG1, //enable or disable
|
||||
.int_status_reg = LSM303D_IG_SRC1, //intterupt status register
|
||||
.range = {-LSM303D_RANGE,LSM303D_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
|
||||
static struct sensor_operate *gsensor_get_ops(void)
|
||||
{
|
||||
return &gsensor_lsm303d_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gsensor_lis3dh_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gsensor_lis3dh_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_lis3dh_init);
|
||||
module_exit(gsensor_lis3dh_exit);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
obj-$(CONFIG_ANGLE_KXTIK) += angle_kxtik.o
|
||||
obj-$(CONFIG_ANGLE_LIS3DH) += angle_lis3dh.o
|
||||
obj-$(CONFIG_ANGLE_KXTIK) += angle_kxtik.o
|
||||
obj-$(CONFIG_ANGLE_LIS3DH) += angle_lis3dh.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,460 +1,460 @@
|
||||
/* drivers/input/sensors/gyro/Ewtsa.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: zhangaihui <zah@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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
/** This define controls compilation of the master device interface */
|
||||
/*#define EWTSA_MASTER_DEVICE*/
|
||||
/* configurable */
|
||||
#define GYRO_MOUNT_SWAP_XY 0 /* swap X, Y */
|
||||
#define GYRO_MOUNT_REVERSE_X 0 /* reverse X */
|
||||
#define GYRO_MOUNT_REVERSE_Y 0 /* reverse Y */
|
||||
#define GYRO_MOUNT_REVERSE_Z 0 /* reverse Z */
|
||||
|
||||
/* macro defines */
|
||||
/*#define CHIP_ID 0x68*/
|
||||
#define DEVICE_NAME "ewtsa"
|
||||
#define EWTSA_ON 1
|
||||
#define EWTSA_OFF 0
|
||||
#define SLEEP_PIN 14
|
||||
#define DRDY_PIN 12
|
||||
#define DIAG_PIN 11
|
||||
#define MAX_VALUE 32768
|
||||
|
||||
/* ewtsa_delay parameter */
|
||||
#define DELAY_THRES_MIN 1
|
||||
#define DELAY_THRES_1 4
|
||||
#define DELAY_THRES_2 9 /* msec x 90% */
|
||||
#define DELAY_THRES_3 18
|
||||
#define DELAY_THRES_4 45
|
||||
#define DELAY_THRES_5 90
|
||||
#define DELAY_THRES_6 128
|
||||
#define DELAY_THRES_MAX 255
|
||||
#define DELAY_DLPF_2 2
|
||||
#define DELAY_DLPF_3 3
|
||||
#define DELAY_DLPF_4 4
|
||||
#define DELAY_DLPF_5 5
|
||||
#define DELAY_DLPF_6 6
|
||||
#define DELAY_INTMIN_THRES 9
|
||||
|
||||
#define DATA_RATE_1 0x01
|
||||
|
||||
/* ewtsa_sleep parameter */
|
||||
#define SLEEP_OFF 0
|
||||
#define SLEEP_ON 1
|
||||
|
||||
/* event mode */
|
||||
#define EWTSA_POLLING_MODE 0
|
||||
#define EWTSA_INTERUPT_MODE 1
|
||||
|
||||
/* ewtsa register address */
|
||||
#define REG_SMPL 0x15
|
||||
#define REG_FS_DLPF 0x16
|
||||
#define REG_INT_CFG 0x17
|
||||
#define REG_INT_STATUS 0x1A
|
||||
#define REG_SELF_O_C 0x29
|
||||
#define REG_PWR_MGM 0x3E
|
||||
#define REG_MBURST_ALL 0xFF
|
||||
#define GYRO_DATA_REG 0x1D
|
||||
|
||||
/* ewtsa register param */
|
||||
#define SELF_O_C_ENABLE 0x00
|
||||
#define SELF_O_C_DISABLE 0x01
|
||||
#define SLEEP_CTRL_ACTIVATE 0x40
|
||||
#define SLEEP_CTRL_SLEEP 0x00
|
||||
#define INT_CFG_INT_ENABLE 0x01
|
||||
#define INT_CFG_INT_DISABLE 0x00
|
||||
|
||||
/* ewtsa interrupt control */
|
||||
#define EWSTA_INT_CLEAR 0x00
|
||||
#define EWSTA_INT_SKIP 0x01
|
||||
|
||||
/* wait time(ms)*/
|
||||
#define EWTSA_BOOST_TIME_0 500
|
||||
|
||||
/* sleep setting range */
|
||||
#define EWTSA_SLP_MIN 0
|
||||
#define EWTSA_SLP_MAX 1
|
||||
|
||||
/* delay setting range */
|
||||
#define EWTSA_DLY_MIN 1
|
||||
#define EWTSA_DLY_MAX 255
|
||||
|
||||
/* range setting range */
|
||||
#define EWTSA_RNG_MIN 0
|
||||
#define EWTSA_RNG_MAX 3
|
||||
|
||||
/* soc setting range */
|
||||
#define EWTSA_SOC_MIN 0
|
||||
#define EWTSA_SOC_MAX 1
|
||||
|
||||
/* event setting range */
|
||||
#define EWTSA_EVE_MIN 0
|
||||
#define EWTSA_EVE_MAX 1
|
||||
|
||||
/* init param */
|
||||
#define SLEEP_INIT_VAL (SLEEP_ON)
|
||||
#define DELAY_INIT_VAL 10
|
||||
#define RANGE_INIT_VAL 2 /*range 1000*/
|
||||
#define DLPF_INIT_VAL (DELAY_DLPF_2)
|
||||
#define CALIB_FUNC_INIT_VAL (EWTSA_ON)
|
||||
|
||||
/*config store counter num*/
|
||||
#define CONFIG_COUNTER_MIN (6+9)
|
||||
#define CONFIG_COUNTER_MAX (32+9)
|
||||
|
||||
/*command name */
|
||||
#define COMMAND_NAME_SOC 0
|
||||
#define COMMAND_NAME_DLY 1
|
||||
#define COMMAND_NAME_RNG 2
|
||||
#define COMMAND_NAME_EVE 3
|
||||
#define COMMAND_NAME_SLP 4
|
||||
#define COMMAND_NAME_NUM 5
|
||||
|
||||
#define EWTSA_delay DELAY_INIT_VAL
|
||||
#define EWTSA_range RANGE_INIT_VAL
|
||||
#define EWTSA_calib EWTSA_ON
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
static int i2c_read_byte(struct i2c_client *thisClient, unsigned char regAddr, char *pReadData)
|
||||
/* drivers/input/sensors/gyro/Ewtsa.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: zhangaihui <zah@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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
/** This define controls compilation of the master device interface */
|
||||
/*#define EWTSA_MASTER_DEVICE*/
|
||||
/* configurable */
|
||||
#define GYRO_MOUNT_SWAP_XY 0 /* swap X, Y */
|
||||
#define GYRO_MOUNT_REVERSE_X 0 /* reverse X */
|
||||
#define GYRO_MOUNT_REVERSE_Y 0 /* reverse Y */
|
||||
#define GYRO_MOUNT_REVERSE_Z 0 /* reverse Z */
|
||||
|
||||
/* macro defines */
|
||||
/*#define CHIP_ID 0x68*/
|
||||
#define DEVICE_NAME "ewtsa"
|
||||
#define EWTSA_ON 1
|
||||
#define EWTSA_OFF 0
|
||||
#define SLEEP_PIN 14
|
||||
#define DRDY_PIN 12
|
||||
#define DIAG_PIN 11
|
||||
#define MAX_VALUE 32768
|
||||
|
||||
/* ewtsa_delay parameter */
|
||||
#define DELAY_THRES_MIN 1
|
||||
#define DELAY_THRES_1 4
|
||||
#define DELAY_THRES_2 9 /* msec x 90% */
|
||||
#define DELAY_THRES_3 18
|
||||
#define DELAY_THRES_4 45
|
||||
#define DELAY_THRES_5 90
|
||||
#define DELAY_THRES_6 128
|
||||
#define DELAY_THRES_MAX 255
|
||||
#define DELAY_DLPF_2 2
|
||||
#define DELAY_DLPF_3 3
|
||||
#define DELAY_DLPF_4 4
|
||||
#define DELAY_DLPF_5 5
|
||||
#define DELAY_DLPF_6 6
|
||||
#define DELAY_INTMIN_THRES 9
|
||||
|
||||
#define DATA_RATE_1 0x01
|
||||
|
||||
/* ewtsa_sleep parameter */
|
||||
#define SLEEP_OFF 0
|
||||
#define SLEEP_ON 1
|
||||
|
||||
/* event mode */
|
||||
#define EWTSA_POLLING_MODE 0
|
||||
#define EWTSA_INTERUPT_MODE 1
|
||||
|
||||
/* ewtsa register address */
|
||||
#define REG_SMPL 0x15
|
||||
#define REG_FS_DLPF 0x16
|
||||
#define REG_INT_CFG 0x17
|
||||
#define REG_INT_STATUS 0x1A
|
||||
#define REG_SELF_O_C 0x29
|
||||
#define REG_PWR_MGM 0x3E
|
||||
#define REG_MBURST_ALL 0xFF
|
||||
#define GYRO_DATA_REG 0x1D
|
||||
|
||||
/* ewtsa register param */
|
||||
#define SELF_O_C_ENABLE 0x00
|
||||
#define SELF_O_C_DISABLE 0x01
|
||||
#define SLEEP_CTRL_ACTIVATE 0x40
|
||||
#define SLEEP_CTRL_SLEEP 0x00
|
||||
#define INT_CFG_INT_ENABLE 0x01
|
||||
#define INT_CFG_INT_DISABLE 0x00
|
||||
|
||||
/* ewtsa interrupt control */
|
||||
#define EWSTA_INT_CLEAR 0x00
|
||||
#define EWSTA_INT_SKIP 0x01
|
||||
|
||||
/* wait time(ms)*/
|
||||
#define EWTSA_BOOST_TIME_0 500
|
||||
|
||||
/* sleep setting range */
|
||||
#define EWTSA_SLP_MIN 0
|
||||
#define EWTSA_SLP_MAX 1
|
||||
|
||||
/* delay setting range */
|
||||
#define EWTSA_DLY_MIN 1
|
||||
#define EWTSA_DLY_MAX 255
|
||||
|
||||
/* range setting range */
|
||||
#define EWTSA_RNG_MIN 0
|
||||
#define EWTSA_RNG_MAX 3
|
||||
|
||||
/* soc setting range */
|
||||
#define EWTSA_SOC_MIN 0
|
||||
#define EWTSA_SOC_MAX 1
|
||||
|
||||
/* event setting range */
|
||||
#define EWTSA_EVE_MIN 0
|
||||
#define EWTSA_EVE_MAX 1
|
||||
|
||||
/* init param */
|
||||
#define SLEEP_INIT_VAL (SLEEP_ON)
|
||||
#define DELAY_INIT_VAL 10
|
||||
#define RANGE_INIT_VAL 2 /*range 1000*/
|
||||
#define DLPF_INIT_VAL (DELAY_DLPF_2)
|
||||
#define CALIB_FUNC_INIT_VAL (EWTSA_ON)
|
||||
|
||||
/*config store counter num*/
|
||||
#define CONFIG_COUNTER_MIN (6+9)
|
||||
#define CONFIG_COUNTER_MAX (32+9)
|
||||
|
||||
/*command name */
|
||||
#define COMMAND_NAME_SOC 0
|
||||
#define COMMAND_NAME_DLY 1
|
||||
#define COMMAND_NAME_RNG 2
|
||||
#define COMMAND_NAME_EVE 3
|
||||
#define COMMAND_NAME_SLP 4
|
||||
#define COMMAND_NAME_NUM 5
|
||||
|
||||
#define EWTSA_delay DELAY_INIT_VAL
|
||||
#define EWTSA_range RANGE_INIT_VAL
|
||||
#define EWTSA_calib EWTSA_ON
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
static int i2c_read_byte(struct i2c_client *thisClient, unsigned char regAddr, char *pReadData)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
||||
ret = i2c_master_send( thisClient, (char*)®Addr, 1);
|
||||
if(ret < 0)
|
||||
{
|
||||
printk("EWTSA send cAddress=0x%x error!\n", regAddr);
|
||||
printk("EWTSA send cAddress=0x%x error!\n", regAddr);
|
||||
return ret;
|
||||
}
|
||||
ret = i2c_master_recv( thisClient, (char*)pReadData, 1);
|
||||
if(ret < 0)
|
||||
{
|
||||
printk("EWTSAread *pReadData=0x%x error!\n", *pReadData);
|
||||
printk("EWTSAread *pReadData=0x%x error!\n", *pReadData);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
static int i2c_write_byte(struct i2c_client *thisClient, unsigned char regAddr, unsigned char writeData)
|
||||
}
|
||||
static int i2c_write_byte(struct i2c_client *thisClient, unsigned char regAddr, unsigned char writeData)
|
||||
{
|
||||
char write_data[2] = {0};
|
||||
int ret=0;
|
||||
|
||||
|
||||
write_data[0] = regAddr;
|
||||
write_data[1] = writeData;
|
||||
|
||||
|
||||
ret = i2c_master_send(thisClient, write_data, 2);
|
||||
if (ret < 0)
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = i2c_master_send(thisClient, write_data, 2);
|
||||
if (ret < 0)
|
||||
if (ret < 0)
|
||||
{
|
||||
printk("EWTSA send regAddr=0x%x error!\n", regAddr);
|
||||
printk("EWTSA send regAddr=0x%x error!\n", regAddr);
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ewtsa_system_restart(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static int ewtsa_system_restart(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
char reg;
|
||||
char smpl , dlpf;
|
||||
|
||||
err = i2c_write_byte(client, ( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_DISABLE);
|
||||
char reg;
|
||||
char smpl , dlpf;
|
||||
|
||||
err = i2c_write_byte(client, ( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_DISABLE);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
///Set SMPL register
|
||||
if (EWTSA_delay <= ( unsigned char)DELAY_THRES_2) {
|
||||
smpl = ( unsigned char)DELAY_INTMIN_THRES;
|
||||
if (EWTSA_delay <= ( unsigned char)DELAY_THRES_2) {
|
||||
smpl = ( unsigned char)DELAY_INTMIN_THRES;
|
||||
}else{
|
||||
smpl = ( unsigned char)(EWTSA_delay - ( unsigned char)1);
|
||||
}
|
||||
err = i2c_write_byte(client, ( unsigned char)REG_SMPL, ( unsigned char)smpl);
|
||||
smpl = ( unsigned char)(EWTSA_delay - ( unsigned char)1);
|
||||
}
|
||||
err = i2c_write_byte(client, ( unsigned char)REG_SMPL, ( unsigned char)smpl);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
///Set DLPF register
|
||||
if (EWTSA_delay >= ( unsigned char)DELAY_THRES_6){
|
||||
dlpf = ( unsigned char)DELAY_DLPF_6;
|
||||
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_5) {
|
||||
dlpf = ( unsigned char)DELAY_DLPF_5;
|
||||
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_4){
|
||||
dlpf = ( unsigned char)DELAY_DLPF_4;
|
||||
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_3) {
|
||||
dlpf = ( unsigned char)DELAY_DLPF_3;
|
||||
if (EWTSA_delay >= ( unsigned char)DELAY_THRES_6){
|
||||
dlpf = ( unsigned char)DELAY_DLPF_6;
|
||||
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_5) {
|
||||
dlpf = ( unsigned char)DELAY_DLPF_5;
|
||||
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_4){
|
||||
dlpf = ( unsigned char)DELAY_DLPF_4;
|
||||
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_3) {
|
||||
dlpf = ( unsigned char)DELAY_DLPF_3;
|
||||
}else{
|
||||
dlpf = ( unsigned char)DELAY_DLPF_2;
|
||||
dlpf = ( unsigned char)DELAY_DLPF_2;
|
||||
}
|
||||
|
||||
reg = ( unsigned char)(( unsigned char)(EWTSA_range << 3) | dlpf | ( unsigned char)0x80 ) ;
|
||||
|
||||
err = i2c_write_byte(client, REG_FS_DLPF, reg);
|
||||
reg = ( unsigned char)(( unsigned char)(EWTSA_range << 3) | dlpf | ( unsigned char)0x80 ) ;
|
||||
|
||||
err = i2c_write_byte(client, REG_FS_DLPF, reg);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (EWTSA_calib== EWTSA_ON) {
|
||||
printk("EWTSA_set_calibration() start \n");
|
||||
err = i2c_write_byte(client,( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_ENABLE);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
mdelay(500);
|
||||
printk("EWTSA_set_calibration() end \n");
|
||||
|
||||
if (EWTSA_calib== EWTSA_ON) {
|
||||
printk("EWTSA_set_calibration() start \n");
|
||||
err = i2c_write_byte(client,( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_ENABLE);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
mdelay(500);
|
||||
printk("EWTSA_set_calibration() end \n");
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ewtsa_disable(struct i2c_client *client)
|
||||
|
||||
static int ewtsa_disable(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_HIGH);
|
||||
|
||||
DBG("%s: end \n",__func__);
|
||||
|
||||
return 0;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_HIGH);
|
||||
|
||||
DBG("%s: end \n",__func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ewtsa_enable(struct i2c_client *client)
|
||||
|
||||
static int ewtsa_enable(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_LOW);
|
||||
err = i2c_write_byte(client, ( unsigned char)REG_PWR_MGM, ( unsigned char)SLEEP_CTRL_ACTIVATE);////0x44
|
||||
if (err < 0){
|
||||
//return err;
|
||||
err = ewtsa_system_restart(client);///restart; only when i2c error
|
||||
if (err < 0){
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = i2c_write_byte(client, ( unsigned char) REG_INT_CFG, ( unsigned char)INT_CFG_INT_ENABLE);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
DBG("%s: end \n",__func__);
|
||||
return 0;
|
||||
int err;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_LOW);
|
||||
err = i2c_write_byte(client, ( unsigned char)REG_PWR_MGM, ( unsigned char)SLEEP_CTRL_ACTIVATE);////0x44
|
||||
if (err < 0){
|
||||
//return err;
|
||||
err = ewtsa_system_restart(client);///restart; only when i2c error
|
||||
if (err < 0){
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = i2c_write_byte(client, ( unsigned char) REG_INT_CFG, ( unsigned char)INT_CFG_INT_ENABLE);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
DBG("%s: end \n",__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gyro_dev_reset(struct i2c_client *client)
|
||||
|
||||
void gyro_dev_reset(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
|
||||
DBG("%s\n",__func__);
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_HIGH);
|
||||
msleep(100);
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_LOW);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
DBG("%s\n",__func__);
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_HIGH);
|
||||
msleep(100);
|
||||
gpio_direction_output(sensor->pdata->standby_pin, GPIO_LOW);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
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 status = 0;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int status = 0;
|
||||
*/
|
||||
int result = 0;
|
||||
if(enable)
|
||||
{
|
||||
result=ewtsa_enable(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
result=ewtsa_disable(client);
|
||||
}
|
||||
|
||||
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;
|
||||
char pReadData=0;
|
||||
*/
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
gyro_dev_reset(client);
|
||||
ewtsa_system_restart(client);
|
||||
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;
|
||||
/* int value = 0; */
|
||||
|
||||
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++)
|
||||
if(enable)
|
||||
{
|
||||
i2c_read_byte(client, sensor->ops->read_reg + i,&buffer[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
x = (short) (((buffer[0]) << 8) | buffer[1]);
|
||||
y = (short) (((buffer[2]) << 8) | buffer[3]);
|
||||
z = (short) (((buffer[4]) << 8) | buffer[5]);
|
||||
result=ewtsa_enable(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
result=ewtsa_disable(client);
|
||||
}
|
||||
|
||||
//printk("%s: x=%d y=%d z=%d \n",__func__, x,y,z);
|
||||
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;
|
||||
char pReadData=0;
|
||||
*/
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
gyro_dev_reset(client);
|
||||
ewtsa_system_restart(client);
|
||||
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;
|
||||
/* int value = 0; */
|
||||
|
||||
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++)
|
||||
{
|
||||
i2c_read_byte(client, sensor->ops->read_reg + i,&buffer[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
x = (short) (((buffer[0]) << 8) | buffer[1]);
|
||||
y = (short) (((buffer[2]) << 8) | buffer[3]);
|
||||
z = (short) (((buffer[4]) << 8) | buffer[5]);
|
||||
|
||||
//printk("%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.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.x = x;
|
||||
axis.y = y;
|
||||
axis.z = z;
|
||||
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);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
mutex_lock(&(sensor->data_mutex) );
|
||||
sensor->axis = axis;
|
||||
mutex_unlock(&(sensor->data_mutex) );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gyro_ewtsa_ops = {
|
||||
.name = "ewtsa",
|
||||
.type = SENSOR_TYPE_GYROSCOPE,//sensor type and it should be correct
|
||||
.id_i2c = GYRO_ID_EWTSA, //i2c id number
|
||||
.read_reg = GYRO_DATA_REG, //read data
|
||||
.read_len = 6, //data length
|
||||
.id_reg = -1, //read device id from this register
|
||||
.id_data = -1, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = REG_PWR_MGM, //enable or disable
|
||||
.int_status_reg = REG_INT_STATUS, //intterupt status register,if no exist then -1
|
||||
.range = {-32768,32768}, //range
|
||||
.trig = IRQF_TRIGGER_HIGH|IRQF_ONESHOT,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
static struct sensor_operate *gyro_get_ops(void)
|
||||
{
|
||||
return &gyro_ewtsa_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gyro_ewtsa_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gyro_ewtsa_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_ewtsa_init);
|
||||
module_exit(gyro_ewtsa_exit);
|
||||
|
||||
|
||||
if((abs(axis.x) > pdata->x_min)||(abs(axis.y) > pdata->y_min)||(abs(axis.z) > pdata->z_min))
|
||||
{
|
||||
gyro_report_value(client, &axis);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
mutex_lock(&(sensor->data_mutex) );
|
||||
sensor->axis = axis;
|
||||
mutex_unlock(&(sensor->data_mutex) );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gyro_ewtsa_ops = {
|
||||
.name = "ewtsa",
|
||||
.type = SENSOR_TYPE_GYROSCOPE,//sensor type and it should be correct
|
||||
.id_i2c = GYRO_ID_EWTSA, //i2c id number
|
||||
.read_reg = GYRO_DATA_REG, //read data
|
||||
.read_len = 6, //data length
|
||||
.id_reg = -1, //read device id from this register
|
||||
.id_data = -1, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = REG_PWR_MGM, //enable or disable
|
||||
.int_status_reg = REG_INT_STATUS, //intterupt status register,if no exist then -1
|
||||
.range = {-32768,32768}, //range
|
||||
.trig = IRQF_TRIGGER_HIGH|IRQF_ONESHOT,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
static struct sensor_operate *gyro_get_ops(void)
|
||||
{
|
||||
return &gyro_ewtsa_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gyro_ewtsa_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gyro_ewtsa_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_ewtsa_init);
|
||||
module_exit(gyro_ewtsa_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,256 +1,256 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/l3g4200d.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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; //l3g20d
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~L3G4200D_ENABLE; //l3g20d
|
||||
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;
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/l3g4200d.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
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;
|
||||
int value = 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++)
|
||||
|
||||
#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)
|
||||
{
|
||||
//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]);
|
||||
status = L3G4200D_ENABLE; //l3g20d
|
||||
sensor->ops->ctrl_data |= status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ~L3G4200D_ENABLE; //l3g20d
|
||||
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;
|
||||
int value = 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.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.x = x;
|
||||
axis.y = y;
|
||||
axis.z = z;
|
||||
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);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct sensor_operate gyro_l3g20d_ops = {
|
||||
.name = "l3g20d",
|
||||
.type = SENSOR_TYPE_GYROSCOPE,//sensor type and it should be correct
|
||||
.id_i2c = GYRO_ID_L3G20D, //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_L3G20D, //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
|
||||
static struct sensor_operate *gyro_get_ops(void)
|
||||
{
|
||||
return &gyro_l3g20d_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gyro_l3g20d_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gyro_l3g20d_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_l3g20d_init);
|
||||
module_exit(gyro_l3g20d_exit);
|
||||
|
||||
|
||||
if((abs(axis.x) > pdata->x_min)||(abs(axis.y) > pdata->y_min)||(abs(axis.z) > pdata->z_min))
|
||||
{
|
||||
gyro_report_value(client, &axis);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct sensor_operate gyro_l3g20d_ops = {
|
||||
.name = "l3g20d",
|
||||
.type = SENSOR_TYPE_GYROSCOPE,//sensor type and it should be correct
|
||||
.id_i2c = GYRO_ID_L3G20D, //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_L3G20D, //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
|
||||
static struct sensor_operate *gyro_get_ops(void)
|
||||
{
|
||||
return &gyro_l3g20d_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gyro_l3g20d_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gyro_l3g20d_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_l3g20d_init);
|
||||
module_exit(gyro_l3g20d_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,256 +1,256 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/l3g4200d.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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;
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/l3g4200d.h>
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
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;
|
||||
int value = 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++)
|
||||
|
||||
#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)
|
||||
{
|
||||
//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]);
|
||||
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;
|
||||
int value = 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.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.x = x;
|
||||
axis.y = y;
|
||||
axis.z = z;
|
||||
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);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gyro_l3g4200d_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
|
||||
static struct sensor_operate *gyro_get_ops(void)
|
||||
{
|
||||
return &gyro_l3g4200d_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gyro_l3g4200d_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gyro_l3g4200d_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_l3g4200d_init);
|
||||
module_exit(gyro_l3g4200d_exit);
|
||||
|
||||
|
||||
if((abs(axis.x) > pdata->x_min)||(abs(axis.y) > pdata->y_min)||(abs(axis.z) > pdata->z_min))
|
||||
{
|
||||
gyro_report_value(client, &axis);
|
||||
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
|
||||
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
|
||||
{
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
DBG("%s:sensor int status :0x%x\n",__func__,value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate gyro_l3g4200d_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
|
||||
static struct sensor_operate *gyro_get_ops(void)
|
||||
{
|
||||
return &gyro_l3g4200d_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init gyro_l3g4200d_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit gyro_l3g4200d_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_l3g4200d_init);
|
||||
module_exit(gyro_l3g4200d_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,233 +1,233 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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 int 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:
|
||||
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 msb = 0, lsb = 0;
|
||||
int index = 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;
|
||||
|
||||
index = light_report_value(sensor->input_dev, result);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, result,index);
|
||||
|
||||
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_cm3217_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 = {100,65535}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_cm3217_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_cm3217_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_cm3217_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_cm3217_init);
|
||||
module_exit(light_cm3217_exit);
|
||||
|
||||
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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 int 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:
|
||||
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 msb = 0, lsb = 0;
|
||||
int index = 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;
|
||||
|
||||
index = light_report_value(sensor->input_dev, result);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, result,index);
|
||||
|
||||
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_cm3217_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 = {100,65535}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_cm3217_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_cm3217_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_cm3217_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_cm3217_init);
|
||||
module_exit(light_cm3217_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,240 +1,240 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define CM3232_CLOSE 0x01
|
||||
|
||||
|
||||
#define CM3232_ADDR_COM 0
|
||||
#define CM3232_ADDR_DATA 50
|
||||
|
||||
#define CM3232_DRV_NAME "cm3232"
|
||||
//command code
|
||||
#define COMMAND_CTRL 0
|
||||
#define COMMAND_ALS_DATA 50 //ALS: 15:8 MSB 8bits data
|
||||
//7:0 LSB 8bits data
|
||||
|
||||
//ctrl bit
|
||||
#define ALS_RESET(x) (((x)&1)<<6) //0 = Reset disable; 1 = Reset enable
|
||||
#define ALS_IT(x) (((x)&7)<<2) //ALS integration time setting
|
||||
#define HIGH_SENSITIVITY(x) (((x)&1)<<1) //0 = Normal mode; 1 = High sensitivity mode
|
||||
#define SHUT_DOWN(x) (((x)&1)<<0) //ALS shut down setting: 0 = ALS Power on ; 1 = ALS Shut down
|
||||
|
||||
#define ALS_IT100MS 0 //100ms
|
||||
#define ALS_IT200MS 1 //200ms
|
||||
#define ALS_IT400MS 2 //400ms
|
||||
#define ALS_IT800MS 3 //800ms
|
||||
#define ALS_IT1600MS 4 //1600ms
|
||||
#define ALS_IT3200MS 5 //3200ms
|
||||
|
||||
|
||||
/****************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(client, sensor->ops->ctrl_reg);
|
||||
//printk("%s: client addr = %#x\n\n", __func__, client->addr);
|
||||
//register setting according to chip datasheet
|
||||
if (enable) {
|
||||
sensor->ops->ctrl_data = ALS_RESET(1);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result) {
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(enable)
|
||||
{
|
||||
sensor->ops->ctrl_data = ALS_IT(ALS_IT200MS) | HIGH_SENSITIVITY(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->ops->ctrl_data = SHUT_DOWN(1);
|
||||
}
|
||||
|
||||
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;
|
||||
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 <= 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:
|
||||
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 msb = 0, lsb = 0;
|
||||
char data[2] = {0};
|
||||
unsigned short value = 0;
|
||||
int index = 0;
|
||||
|
||||
//sensor->client->addr = CM3232_ADDR_DATA;
|
||||
data[0] = CM3232_ADDR_DATA;
|
||||
sensor_rx_data(sensor->client, data, 2);
|
||||
value = (data[1] << 8) | data[0] ;
|
||||
|
||||
DBG("%s:result=%d\n",__func__,value);
|
||||
//printk("%s:result=%d\n",__func__,value);
|
||||
index = light_report_value(sensor->input_dev, value);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
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_cm3232_ops = {
|
||||
.name = "cm3232",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_CM3232, //i2c id number
|
||||
.read_reg = CM3232_ADDR_DATA, //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 = CM3232_ADDR_COM, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness = {10,255}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_cm3232_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_cm3232_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_cm3232_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_cm3232_init);
|
||||
module_exit(light_cm3232_exit);
|
||||
|
||||
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define CM3232_CLOSE 0x01
|
||||
|
||||
|
||||
#define CM3232_ADDR_COM 0
|
||||
#define CM3232_ADDR_DATA 50
|
||||
|
||||
#define CM3232_DRV_NAME "cm3232"
|
||||
//command code
|
||||
#define COMMAND_CTRL 0
|
||||
#define COMMAND_ALS_DATA 50 //ALS: 15:8 MSB 8bits data
|
||||
//7:0 LSB 8bits data
|
||||
|
||||
//ctrl bit
|
||||
#define ALS_RESET(x) (((x)&1)<<6) //0 = Reset disable; 1 = Reset enable
|
||||
#define ALS_IT(x) (((x)&7)<<2) //ALS integration time setting
|
||||
#define HIGH_SENSITIVITY(x) (((x)&1)<<1) //0 = Normal mode; 1 = High sensitivity mode
|
||||
#define SHUT_DOWN(x) (((x)&1)<<0) //ALS shut down setting: 0 = ALS Power on ; 1 = ALS Shut down
|
||||
|
||||
#define ALS_IT100MS 0 //100ms
|
||||
#define ALS_IT200MS 1 //200ms
|
||||
#define ALS_IT400MS 2 //400ms
|
||||
#define ALS_IT800MS 3 //800ms
|
||||
#define ALS_IT1600MS 4 //1600ms
|
||||
#define ALS_IT3200MS 5 //3200ms
|
||||
|
||||
|
||||
/****************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(client, sensor->ops->ctrl_reg);
|
||||
//printk("%s: client addr = %#x\n\n", __func__, client->addr);
|
||||
//register setting according to chip datasheet
|
||||
if (enable) {
|
||||
sensor->ops->ctrl_data = ALS_RESET(1);
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
|
||||
if(result) {
|
||||
printk("%s:fail to active sensor\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(enable)
|
||||
{
|
||||
sensor->ops->ctrl_data = ALS_IT(ALS_IT200MS) | HIGH_SENSITIVITY(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->ops->ctrl_data = SHUT_DOWN(1);
|
||||
}
|
||||
|
||||
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;
|
||||
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 <= 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:
|
||||
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 msb = 0, lsb = 0;
|
||||
char data[2] = {0};
|
||||
unsigned short value = 0;
|
||||
int index = 0;
|
||||
|
||||
//sensor->client->addr = CM3232_ADDR_DATA;
|
||||
data[0] = CM3232_ADDR_DATA;
|
||||
sensor_rx_data(sensor->client, data, 2);
|
||||
value = (data[1] << 8) | data[0] ;
|
||||
|
||||
DBG("%s:result=%d\n",__func__,value);
|
||||
//printk("%s:result=%d\n",__func__,value);
|
||||
index = light_report_value(sensor->input_dev, value);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
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_cm3232_ops = {
|
||||
.name = "cm3232",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_CM3232, //i2c id number
|
||||
.read_reg = CM3232_ADDR_DATA, //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 = CM3232_ADDR_COM, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness = {10,255}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_cm3232_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_cm3232_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_cm3232_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_cm3232_init);
|
||||
module_exit(light_cm3232_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,268 +1,268 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define ISL29023_REG_ADD_COMMAND1 0x00
|
||||
#define COMMMAND1_OPMODE_SHIFT 5
|
||||
#define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_POWER_DOWN (0 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_ALS_ONCE (1 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_IR_ONCE (2 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_ALS_CONTINUE (5 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_IR_CONTINUE (6 << COMMMAND1_OPMODE_SHIFT)
|
||||
|
||||
|
||||
#define ISL29023_REG_ADD_COMMANDII 0x01
|
||||
#define COMMANDII_RESOLUTION_SHIFT 2
|
||||
#define COMMANDII_RESOLUTION_65536 (0x0 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_4096 (0x1 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_256 (0x2 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_16 (0x3 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT)
|
||||
|
||||
#define COMMANDII_RANGE_SHIFT 0
|
||||
#define COMMANDII_RANGE_1000 (0x0 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_4000 (0x1 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_16000 (0x2 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_64000 (0x3 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
|
||||
|
||||
|
||||
#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
|
||||
|
||||
#define COMMANDII_SCHEME_SHIFT 7
|
||||
#define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT)
|
||||
|
||||
#define ISL29023_REG_ADD_DATA_LSB 0x02
|
||||
#define ISL29023_REG_ADD_DATA_MSB 0x03
|
||||
#define ISL29023_MAX_REGS ISL29023_REG_ADD_DATA_MSB
|
||||
|
||||
#define ISL29023_REG_LT_LSB 0x04
|
||||
#define ISL29023_REG_LT_MSB 0x05
|
||||
#define ISL29023_REG_HT_LSB 0x06
|
||||
#define ISL29023_REG_HT_MSB 0x07
|
||||
|
||||
|
||||
/****************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)
|
||||
{
|
||||
sensor->ops->ctrl_data &= 0x1f;
|
||||
sensor->ops->ctrl_data |= COMMMAND1_OPMODE_ALS_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->ops->ctrl_data &= 0x1f;
|
||||
//sensor->ops->ctrl_data |= COMMMAND1_OPMODE_POWER_DOWN;
|
||||
}
|
||||
|
||||
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__);
|
||||
|
||||
if(enable)
|
||||
sensor->ops->report(sensor->client);
|
||||
|
||||
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, ISL29023_REG_ADD_COMMANDII, COMMANDII_RANGE_4000 | COMMANDII_RESOLUTION_4096);
|
||||
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 <= 2){
|
||||
index = 0;goto report;
|
||||
}
|
||||
else if(data <= 3){
|
||||
index = 2;goto report;
|
||||
}
|
||||
else if(data <= 5){
|
||||
index = 3;goto report;
|
||||
}
|
||||
else if(data <= 8){
|
||||
index = 4;goto report;
|
||||
}
|
||||
else if(data <= 11){
|
||||
index = 5;goto report;
|
||||
}
|
||||
else if(data <= 14){
|
||||
index = 6;goto report;
|
||||
}
|
||||
else if(data <= 17){
|
||||
index = 7;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);
|
||||
|
||||
buffer[0] = sensor->ops->read_reg;
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
value = (buffer[1] << 8) | buffer[0];
|
||||
|
||||
|
||||
index = light_report_value(sensor->input_dev, value);
|
||||
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_isl29023_ops = {
|
||||
.name = "ls_isl29023",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_ISL29023, //i2c id number
|
||||
.read_reg = ISL29023_REG_ADD_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 = 16, //8 bits
|
||||
.ctrl_reg = ISL29023_REG_ADD_COMMAND1, //enable or disable
|
||||
.int_status_reg = ISL29023_REG_ADD_COMMAND1, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness ={10,255}, //brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_isl29023_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_isl29023_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_isl29023_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_isl29023_init);
|
||||
module_exit(light_isl29023_exit);
|
||||
|
||||
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define ISL29023_REG_ADD_COMMAND1 0x00
|
||||
#define COMMMAND1_OPMODE_SHIFT 5
|
||||
#define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_POWER_DOWN (0 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_ALS_ONCE (1 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_IR_ONCE (2 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_ALS_CONTINUE (5 << COMMMAND1_OPMODE_SHIFT)
|
||||
#define COMMMAND1_OPMODE_IR_CONTINUE (6 << COMMMAND1_OPMODE_SHIFT)
|
||||
|
||||
|
||||
#define ISL29023_REG_ADD_COMMANDII 0x01
|
||||
#define COMMANDII_RESOLUTION_SHIFT 2
|
||||
#define COMMANDII_RESOLUTION_65536 (0x0 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_4096 (0x1 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_256 (0x2 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_16 (0x3 << COMMANDII_RESOLUTION_SHIFT)
|
||||
#define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT)
|
||||
|
||||
#define COMMANDII_RANGE_SHIFT 0
|
||||
#define COMMANDII_RANGE_1000 (0x0 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_4000 (0x1 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_16000 (0x2 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_64000 (0x3 << COMMANDII_RANGE_SHIFT)
|
||||
#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
|
||||
|
||||
|
||||
#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
|
||||
|
||||
#define COMMANDII_SCHEME_SHIFT 7
|
||||
#define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT)
|
||||
|
||||
#define ISL29023_REG_ADD_DATA_LSB 0x02
|
||||
#define ISL29023_REG_ADD_DATA_MSB 0x03
|
||||
#define ISL29023_MAX_REGS ISL29023_REG_ADD_DATA_MSB
|
||||
|
||||
#define ISL29023_REG_LT_LSB 0x04
|
||||
#define ISL29023_REG_LT_MSB 0x05
|
||||
#define ISL29023_REG_HT_LSB 0x06
|
||||
#define ISL29023_REG_HT_MSB 0x07
|
||||
|
||||
|
||||
/****************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)
|
||||
{
|
||||
sensor->ops->ctrl_data &= 0x1f;
|
||||
sensor->ops->ctrl_data |= COMMMAND1_OPMODE_ALS_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->ops->ctrl_data &= 0x1f;
|
||||
//sensor->ops->ctrl_data |= COMMMAND1_OPMODE_POWER_DOWN;
|
||||
}
|
||||
|
||||
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__);
|
||||
|
||||
if(enable)
|
||||
sensor->ops->report(sensor->client);
|
||||
|
||||
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, ISL29023_REG_ADD_COMMANDII, COMMANDII_RANGE_4000 | COMMANDII_RESOLUTION_4096);
|
||||
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 <= 2){
|
||||
index = 0;goto report;
|
||||
}
|
||||
else if(data <= 3){
|
||||
index = 2;goto report;
|
||||
}
|
||||
else if(data <= 5){
|
||||
index = 3;goto report;
|
||||
}
|
||||
else if(data <= 8){
|
||||
index = 4;goto report;
|
||||
}
|
||||
else if(data <= 11){
|
||||
index = 5;goto report;
|
||||
}
|
||||
else if(data <= 14){
|
||||
index = 6;goto report;
|
||||
}
|
||||
else if(data <= 17){
|
||||
index = 7;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);
|
||||
|
||||
buffer[0] = sensor->ops->read_reg;
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
value = (buffer[1] << 8) | buffer[0];
|
||||
|
||||
|
||||
index = light_report_value(sensor->input_dev, value);
|
||||
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_isl29023_ops = {
|
||||
.name = "ls_isl29023",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_ISL29023, //i2c id number
|
||||
.read_reg = ISL29023_REG_ADD_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 = 16, //8 bits
|
||||
.ctrl_reg = ISL29023_REG_ADD_COMMAND1, //enable or disable
|
||||
.int_status_reg = ISL29023_REG_ADD_COMMAND1, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness ={10,255}, //brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_isl29023_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_isl29023_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_isl29023_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_isl29023_init);
|
||||
module_exit(light_isl29023_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,295 +1,295 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
value = sensor_read_reg(client, CONFIG_REG);
|
||||
value &= ~POWER_MODE_MASK;
|
||||
value |= POWER_DOWN_MODE;
|
||||
result = sensor_write_reg(client, CONFIG_REG, value);
|
||||
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;
|
||||
|
||||
if(enable)
|
||||
sensor_power_updown(client, 1);
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
if( (value & 0x03) == ONLY_PROX_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_PROX_ALS_EN;
|
||||
}
|
||||
else if((value & 0x03) == ALL_IDLE )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_ALS_EN;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (value & 0x03) == ONLY_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_IDLE;
|
||||
}
|
||||
else if((value & 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;
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
value = sensor_read_reg(client, CONFIG_REG);
|
||||
value &= ~POWER_MODE_MASK;
|
||||
value |= POWER_DOWN_MODE;
|
||||
result = sensor_write_reg(client, CONFIG_REG, value);
|
||||
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;
|
||||
|
||||
if(enable)
|
||||
sensor_power_updown(client, 1);
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
if( (value & 0x03) == ONLY_PROX_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_PROX_ALS_EN;
|
||||
}
|
||||
else if((value & 0x03) == ALL_IDLE )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_ALS_EN;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (value & 0x03) == ONLY_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_IDLE;
|
||||
}
|
||||
else if((value & 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;
|
||||
}
|
||||
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_al3006_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 = {100,65535}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_al3006_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_al3006_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_al3006_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_al3006_init);
|
||||
module_exit(light_al3006_exit);
|
||||
|
||||
|
||||
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_al3006_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 = {100,65535}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_al3006_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_al3006_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_al3006_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_al3006_init);
|
||||
module_exit(light_al3006_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
/* 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>
|
||||
|
||||
|
||||
/* 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>
|
||||
|
||||
|
||||
#define AP3212B_NUM_CACHABLE_REGS 23
|
||||
#define AP3216C_NUM_CACHABLE_REGS 26
|
||||
|
||||
#define AP3216C_NUM_CACHABLE_REGS 26
|
||||
|
||||
#define AP3212B_RAN_COMMAND 0x10
|
||||
#define AP3212B_RAN_MASK 0x30
|
||||
#define AP3212B_RAN_SHIFT (4)
|
||||
|
||||
#define AP3212B_MODE_COMMAND 0x00
|
||||
#define AP3212B_MODE_SHIFT (0)
|
||||
#define AP3212B_MODE_MASK 0x07
|
||||
|
||||
#define AP3212B_MODE_MASK 0x07
|
||||
|
||||
#define AP3212B_INT_COMMAND 0x01
|
||||
#define AP3212B_INT_SHIFT (0)
|
||||
#define AP3212B_INT_MASK 0x03
|
||||
#define AP3212B_INT_PMASK 0x02
|
||||
#define AP3212B_INT_AMASK 0x01
|
||||
|
||||
|
||||
#define AL3212_ADC_LSB 0x0c
|
||||
#define AL3212_ADC_MSB 0x0d
|
||||
|
||||
|
||||
#define AP3212B_ALS_LTHL 0x1a
|
||||
#define AP3212B_ALS_LTHL_SHIFT (0)
|
||||
#define AP3212B_ALS_LTHL_MASK 0xff
|
||||
@@ -68,9 +68,9 @@
|
||||
#define AP3212B_ALS_HTHH 0x1d
|
||||
#define AP3212B_ALS_HTHH_SHIFT (0)
|
||||
#define AP3212B_ALS_HTHH_MASK 0xff
|
||||
|
||||
static u16 ap321xx_threshole[8] = {28,444,625,888,1778,3555,7222,0xffff};
|
||||
|
||||
|
||||
static u16 ap321xx_threshole[8] = {28,444,625,888,1778,3555,7222,0xffff};
|
||||
|
||||
/*
|
||||
* register access helpers
|
||||
*/
|
||||
@@ -78,33 +78,33 @@ static u16 ap321xx_threshole[8] = {28,444,625,888,1778,3555,7222,0xffff};
|
||||
static int __ap321xx_read_reg(struct i2c_client *client,
|
||||
u32 reg, u8 mask, u8 shift)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, reg);
|
||||
return (val & mask) >> shift;
|
||||
u8 val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, reg);
|
||||
return (val & mask) >> shift;
|
||||
}
|
||||
|
||||
static int __ap321xx_write_reg(struct i2c_client *client,
|
||||
u32 reg, u8 mask, u8 shift, u8 val)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
u8 tmp;
|
||||
|
||||
tmp = i2c_smbus_read_byte_data(client, reg);
|
||||
|
||||
tmp = i2c_smbus_read_byte_data(client, reg);
|
||||
tmp &= ~mask;
|
||||
tmp |= val << shift;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, reg, tmp);
|
||||
|
||||
return ret;
|
||||
ret = i2c_smbus_write_byte_data(client, reg, tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* internally used functions
|
||||
*/
|
||||
*/
|
||||
/* range */
|
||||
static int ap321xx_set_range(struct i2c_client *client, int range)
|
||||
static int ap321xx_set_range(struct i2c_client *client, int range)
|
||||
{
|
||||
return __ap321xx_write_reg(client, AP3212B_RAN_COMMAND,
|
||||
AP3212B_RAN_MASK, AP3212B_RAN_SHIFT, range);;
|
||||
@@ -114,51 +114,51 @@ static int ap321xx_set_range(struct i2c_client *client, int range)
|
||||
/* mode */
|
||||
static int ap321xx_get_mode(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
ret = __ap321xx_read_reg(client, sensor->ops->ctrl_reg,
|
||||
ret = __ap321xx_read_reg(client, sensor->ops->ctrl_reg,
|
||||
AP3212B_MODE_MASK, AP3212B_MODE_SHIFT);
|
||||
return ret;
|
||||
}
|
||||
static int ap321xx_set_mode(struct i2c_client *client, int mode)
|
||||
static int ap321xx_set_mode(struct i2c_client *client, int mode)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int ret;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
ret = __ap321xx_write_reg(client, sensor->ops->ctrl_reg,
|
||||
ret = __ap321xx_write_reg(client, sensor->ops->ctrl_reg,
|
||||
AP3212B_MODE_MASK, AP3212B_MODE_SHIFT, mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int ap321xx_get_adc_value(struct i2c_client *client)
|
||||
{
|
||||
unsigned int lsb, msb, val;
|
||||
unsigned char index=0;
|
||||
unsigned char index=0;
|
||||
|
||||
lsb = i2c_smbus_read_byte_data(client, AL3212_ADC_LSB);
|
||||
lsb = i2c_smbus_read_byte_data(client, AL3212_ADC_LSB);
|
||||
if (lsb < 0) {
|
||||
return lsb;
|
||||
}
|
||||
|
||||
msb = i2c_smbus_read_byte_data(client, AL3212_ADC_MSB);
|
||||
msb = i2c_smbus_read_byte_data(client, AL3212_ADC_MSB);
|
||||
if (msb < 0)
|
||||
return msb;
|
||||
|
||||
val = msb << 8 | lsb;
|
||||
val = msb << 8 | lsb;
|
||||
for(index = 0; index < 7 && val > ap321xx_threshole[index];index++)
|
||||
;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/* ALS low threshold */
|
||||
}
|
||||
|
||||
/* ALS low threshold */
|
||||
static int ap321xx_set_althres(struct i2c_client *client, int val)
|
||||
{
|
||||
int lsb, msb, err;
|
||||
|
||||
|
||||
msb = val >> 8;
|
||||
lsb = val & AP3212B_ALS_LTHL_MASK;
|
||||
|
||||
@@ -173,14 +173,14 @@ static int ap321xx_set_althres(struct i2c_client *client, int val)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ALS high threshold */
|
||||
/* ALS high threshold */
|
||||
static int ap321xx_set_ahthres(struct i2c_client *client, int val)
|
||||
{
|
||||
int lsb, msb, err;
|
||||
|
||||
|
||||
msb = val >> 8;
|
||||
lsb = val & AP3212B_ALS_HTHL_MASK;
|
||||
|
||||
|
||||
err = __ap321xx_write_reg(client, AP3212B_ALS_HTHL,
|
||||
AP3212B_ALS_HTHL_MASK, AP3212B_ALS_HTHL_SHIFT, lsb);
|
||||
if (err)
|
||||
@@ -190,71 +190,71 @@ static int ap321xx_set_ahthres(struct i2c_client *client, int val)
|
||||
AP3212B_ALS_HTHH_MASK, AP3212B_ALS_HTHH_SHIFT, msb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int ap321xx_get_intstat(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg);
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg);
|
||||
val &= AP3212B_INT_MASK;
|
||||
|
||||
return val >> AP3212B_INT_SHIFT;
|
||||
}
|
||||
|
||||
static int ap321xx_product_detect(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static int ap321xx_product_detect(struct i2c_client *client)
|
||||
{
|
||||
int mid = i2c_smbus_read_byte_data(client, 0x03);
|
||||
int pid = i2c_smbus_read_byte_data(client, 0x04);
|
||||
int rid = i2c_smbus_read_byte_data(client, 0x05);
|
||||
|
||||
if ( mid == 0x01 && pid == 0x01 &&
|
||||
if ( mid == 0x01 && pid == 0x01 &&
|
||||
(rid == 0x03 || rid == 0x04) )
|
||||
{
|
||||
//printk("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid);
|
||||
}
|
||||
else if ( (mid == 0x01 && pid == 0x02 && rid == 0x00) ||
|
||||
//printk("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid);
|
||||
}
|
||||
else if ( (mid == 0x01 && pid == 0x02 && rid == 0x00) ||
|
||||
(mid == 0x02 && pid == 0x02 && rid == 0x01))
|
||||
{
|
||||
//printk("RevID [%d], ==> DA3212 v2.0 ...... AP3212C/AP3216C detected\n", rid);
|
||||
}
|
||||
//printk("RevID [%d], ==> DA3212 v2.0 ...... AP3212C/AP3216C detected\n", rid);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printk("MakeID[%d] ProductID[%d] RevID[%d] .... can't detect ... bad reversion!!!\n", mid, pid, rid);
|
||||
//printk("MakeID[%d] ProductID[%d] RevID[%d] .... can't detect ... bad reversion!!!\n", mid, pid, rid);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int ap321xx_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* set defaults */
|
||||
/* set defaults */
|
||||
ap321xx_set_range(client, 0);
|
||||
ap321xx_set_mode(client, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int ap321xx_lsensor_enable(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0,mode;
|
||||
|
||||
|
||||
mode = ap321xx_get_mode(client);
|
||||
if((mode & 0x01) == 0){
|
||||
mode |= 0x01;
|
||||
ret = ap321xx_set_mode(client,mode);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ap321xx_lsensor_disable(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0,mode;
|
||||
|
||||
|
||||
mode = ap321xx_get_mode(client);
|
||||
if(mode & 0x01){
|
||||
mode &= ~0x01;
|
||||
@@ -262,18 +262,18 @@ static int ap321xx_lsensor_disable(struct i2c_client *client)
|
||||
mode = 0;
|
||||
ret = ap321xx_set_mode(client,mode);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void ap321xx_change_ls_threshold(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int value;
|
||||
|
||||
value = ap321xx_get_adc_value(client);
|
||||
DBG("ALS lux index: %u\n", value);
|
||||
DBG("ALS lux index: %u\n", value);
|
||||
if(value > 0){
|
||||
ap321xx_set_althres(client,ap321xx_threshole[value-1]);
|
||||
ap321xx_set_ahthres(client,ap321xx_threshole[value]);
|
||||
@@ -282,128 +282,128 @@ static void ap321xx_change_ls_threshold(struct i2c_client *client)
|
||||
ap321xx_set_althres(client,0);
|
||||
ap321xx_set_ahthres(client,ap321xx_threshole[value]);
|
||||
}
|
||||
|
||||
input_report_abs(sensor->input_dev, ABS_MISC, value);
|
||||
input_sync(sensor->input_dev);
|
||||
}
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if (enable){
|
||||
result = ap321xx_lsensor_enable(client);
|
||||
if(!result){
|
||||
msleep(200);
|
||||
ap321xx_change_ls_threshold(client);
|
||||
}
|
||||
}
|
||||
else
|
||||
result = ap321xx_lsensor_disable(client);
|
||||
|
||||
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 = ap321xx_product_detect(client);
|
||||
if (result)
|
||||
{
|
||||
dev_err(&client->dev, "ret: %d, product version detect failed.\n",result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* initialize the AP3212B chip */
|
||||
result = ap321xx_init_client(client);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
int result = 0;
|
||||
u8 int_stat;
|
||||
|
||||
int_stat = ap321xx_get_intstat(client);
|
||||
// ALS int
|
||||
if (int_stat & AP3212B_INT_AMASK)
|
||||
{
|
||||
ap321xx_change_ls_threshold(client);
|
||||
|
||||
input_report_abs(sensor->input_dev, ABS_MISC, value);
|
||||
input_sync(sensor->input_dev);
|
||||
}
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if (enable){
|
||||
result = ap321xx_lsensor_enable(client);
|
||||
if(!result){
|
||||
msleep(200);
|
||||
ap321xx_change_ls_threshold(client);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_ap321xx_ops = {
|
||||
.name = "ls_ap321xx",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_AP321XX, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data //there are two regs, we fix them in code.
|
||||
.read_len = 1, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register //there are 3 regs, we fix them in code.
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 16, //8 bits
|
||||
.ctrl_reg = AP3212B_MODE_COMMAND, //enable or disable
|
||||
.int_status_reg = AP3212B_INT_COMMAND, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.trig = IRQF_TRIGGER_FALLING | 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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_ap321xx_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_ap321xx_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_ap321xx_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_ap321xx_init);
|
||||
module_exit(light_ap321xx_exit);
|
||||
|
||||
|
||||
else
|
||||
result = ap321xx_lsensor_disable(client);
|
||||
|
||||
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 = ap321xx_product_detect(client);
|
||||
if (result)
|
||||
{
|
||||
dev_err(&client->dev, "ret: %d, product version detect failed.\n",result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* initialize the AP3212B chip */
|
||||
result = ap321xx_init_client(client);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
int result = 0;
|
||||
u8 int_stat;
|
||||
|
||||
int_stat = ap321xx_get_intstat(client);
|
||||
// ALS int
|
||||
if (int_stat & AP3212B_INT_AMASK)
|
||||
{
|
||||
ap321xx_change_ls_threshold(client);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_ap321xx_ops = {
|
||||
.name = "ls_ap321xx",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_AP321XX, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data //there are two regs, we fix them in code.
|
||||
.read_len = 1, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register //there are 3 regs, we fix them in code.
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 16, //8 bits
|
||||
.ctrl_reg = AP3212B_MODE_COMMAND, //enable or disable
|
||||
.int_status_reg = AP3212B_INT_COMMAND, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.trig = IRQF_TRIGGER_FALLING | 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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_ap321xx_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_ap321xx_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_ap321xx_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_ap321xx_init);
|
||||
module_exit(light_ap321xx_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,314 +1,314 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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<<6)
|
||||
#define ALS_RANGE_28836 (1<<6)
|
||||
|
||||
//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<<4)
|
||||
#define PS_CUR_200MA (1<<4)
|
||||
#define PS_SLP_10MS (0<<5)
|
||||
#define PS_SLP_30MS (1<<5)
|
||||
#define PS_SLP_90MS (2<<5)
|
||||
#define PS_SLP_270MS (3<<5)
|
||||
#define TRIG_PS_OR_LS (0<<7)
|
||||
#define TRIG_PS_AND_LS (1<<7)
|
||||
|
||||
//STA_TUS
|
||||
#define STA_PS_INT (1<<5)
|
||||
#define STA_ALS_INT (1<<4)
|
||||
|
||||
|
||||
|
||||
/****************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__);
|
||||
|
||||
if(enable)
|
||||
sensor->ops->report(sensor->client);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
result = sensor_write_reg(client, ALS_THDH1, 0);//it is important,if not then als can not trig intterupt
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = sensor_write_reg(client, ALS_THDH2, 0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->ops->ctrl_data |= ALS_1T_100MS;
|
||||
|
||||
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 <= 100){
|
||||
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);
|
||||
|
||||
buffer[0] = sensor->ops->read_reg;
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
value = (buffer[0] << 8) | buffer[1];
|
||||
|
||||
|
||||
index = light_report_value(sensor->input_dev, value);
|
||||
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_stk3171_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 = {100,65535}, //range
|
||||
.brightness ={10,255}, //brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_stk3171_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_stk3171_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_stk3171_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_stk3171_init);
|
||||
module_exit(light_stk3171_exit);
|
||||
|
||||
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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<<6)
|
||||
#define ALS_RANGE_28836 (1<<6)
|
||||
|
||||
//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<<4)
|
||||
#define PS_CUR_200MA (1<<4)
|
||||
#define PS_SLP_10MS (0<<5)
|
||||
#define PS_SLP_30MS (1<<5)
|
||||
#define PS_SLP_90MS (2<<5)
|
||||
#define PS_SLP_270MS (3<<5)
|
||||
#define TRIG_PS_OR_LS (0<<7)
|
||||
#define TRIG_PS_AND_LS (1<<7)
|
||||
|
||||
//STA_TUS
|
||||
#define STA_PS_INT (1<<5)
|
||||
#define STA_ALS_INT (1<<4)
|
||||
|
||||
|
||||
|
||||
/****************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__);
|
||||
|
||||
if(enable)
|
||||
sensor->ops->report(sensor->client);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
result = sensor_write_reg(client, ALS_THDH1, 0);//it is important,if not then als can not trig intterupt
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = sensor_write_reg(client, ALS_THDH2, 0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->ops->ctrl_data |= ALS_1T_100MS;
|
||||
|
||||
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 <= 100){
|
||||
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);
|
||||
|
||||
buffer[0] = sensor->ops->read_reg;
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
value = (buffer[0] << 8) | buffer[1];
|
||||
|
||||
|
||||
index = light_report_value(sensor->input_dev, value);
|
||||
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate light_stk3171_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 = {100,65535}, //range
|
||||
.brightness ={10,255}, //brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_stk3171_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init light_stk3171_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit light_stk3171_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_stk3171_init);
|
||||
module_exit(light_stk3171_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,438 +1,438 @@
|
||||
#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>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
#define DRIVER_VERSION "1.0"
|
||||
|
||||
#define PWR_MODE_DOWN_MASK 0x80
|
||||
#define PWR_MODE_OPERATE_MASK 0x7F
|
||||
|
||||
|
||||
/*us5152 Slave Addr*/
|
||||
#define LIGHT_ADDR 0x72
|
||||
|
||||
/*Interrupt PIN for S3C6410*/
|
||||
#define IRQ_LIGHT_INT IRQ_EINT(6)
|
||||
|
||||
/*Register Set*/
|
||||
#define REGS_CR0 0x00
|
||||
#define REGS_CR1 0x01
|
||||
#define REGS_CR2 0x02
|
||||
#define REGS_CR3 0x03
|
||||
//ALS
|
||||
#define REGS_INT_LSB_TH_LO 0x04
|
||||
#define REGS_INT_MSB_TH_LO 0x05
|
||||
#define REGS_INT_LSB_TH_HI 0x06
|
||||
#define REGS_INT_MSB_TH_HI 0x07
|
||||
//ALS data
|
||||
#define REGS_LBS_SENSOR 0x0C
|
||||
#define REGS_MBS_SENSOR 0x0D
|
||||
|
||||
#define REGS_CR10 0x10
|
||||
#define REGS_CR11 0x11
|
||||
#define REGS_VERSION_ID 0x1F
|
||||
#define REGS_CHIP_ID 0xB2
|
||||
|
||||
/*ShutDown_EN*/
|
||||
#define CR0_OPERATION 0x0
|
||||
#define CR0_SHUTDOWN_EN 0x1
|
||||
|
||||
#define CR0_SHUTDOWN_SHIFT (7)
|
||||
#define CR0_SHUTDOWN_MASK (0x1 << CR0_SHUTDOWN_SHIFT)
|
||||
|
||||
/*OneShot_EN*/
|
||||
#define CR0_ONESHOT_EN 0x01
|
||||
|
||||
#define CR0_ONESHOT_SHIFT (6)
|
||||
#define CR0_ONESHOT_MASK (0x1 << CR0_ONESHOT_SHIFT)
|
||||
|
||||
/*Operation Mode*/
|
||||
#define CR0_OPMODE_ALSANDPS 0x0
|
||||
#define CR0_OPMODE_ALSONLY 0x1
|
||||
#define CR0_OPMODE_IRONLY 0x2
|
||||
|
||||
#define CR0_OPMODE_SHIFT (4)
|
||||
#define CR0_OPMODE_MASK (0x3 << CR0_OPMODE_SHIFT)
|
||||
|
||||
/*all int flag (PROX, INT_A, INT_P)*/
|
||||
#define CR0_ALL_INT_CLEAR 0x0
|
||||
|
||||
#define CR0_ALL_INT_SHIFT (1)
|
||||
#define CR0_ALL_INT_MASK (0x7 << CR0_ALL_INT_SHIFT)
|
||||
|
||||
|
||||
/*indicator of object proximity detection*/
|
||||
#define CR0_PROX_CLEAR 0x0
|
||||
|
||||
#define CR0_PROX_SHIFT (3)
|
||||
#define CR0_PROX_MASK (0x1 << CR0_PROX_SHIFT)
|
||||
|
||||
/*interrupt status of proximity sensor*/
|
||||
#define CR0_INTP_CLEAR 0x0
|
||||
|
||||
#define CR0_INTP_SHIFT (2)
|
||||
#define CR0_INTP_MASK (0x1 << CR0_INTP_SHIFT)
|
||||
|
||||
/*interrupt status of ambient sensor*/
|
||||
#define CR0_INTA_CLEAR 0x0
|
||||
|
||||
#define CR0_INTA_SHIFT (1)
|
||||
#define CR0_INTA_MASK (0x1 << CR0_INTA_SHIFT)
|
||||
|
||||
/*Word mode enable*/
|
||||
#define CR0_WORD_EN 0x1
|
||||
|
||||
#define CR0_WORD_SHIFT (0)
|
||||
#define CR0_WORD_MASK (0x1 << CR0_WORD_SHIFT)
|
||||
|
||||
|
||||
/*ALS fault queue depth for interrupt enent output*/
|
||||
#define CR1_ALS_FQ_1 0x0
|
||||
#define CR1_ALS_FQ_4 0x1
|
||||
#define CR1_ALS_FQ_8 0x2
|
||||
#define CR1_ALS_FQ_16 0x3
|
||||
#define CR1_ALS_FQ_24 0x4
|
||||
#define CR1_ALS_FQ_32 0x5
|
||||
#define CR1_ALS_FQ_48 0x6
|
||||
#define CR1_ALS_FQ_63 0x7
|
||||
|
||||
#define CR1_ALS_FQ_SHIFT (5)
|
||||
#define CR1_ALS_FQ_MASK (0x7 << CR1_ALS_FQ_SHIFT)
|
||||
|
||||
/*resolution for ALS*/
|
||||
#define CR1_ALS_RES_12BIT 0x0
|
||||
#define CR1_ALS_RES_14BIT 0x1
|
||||
#define CR1_ALS_RES_16BIT 0x2
|
||||
#define CR1_ALS_RES_16BIT_2 0x3
|
||||
|
||||
#define CR1_ALS_RES_SHIFT (3)
|
||||
#define CR1_ALS_RES_MASK (0x3 << CR1_ALS_RES_SHIFT)
|
||||
|
||||
/*sensing amplifier selection for ALS*/
|
||||
#define CR1_ALS_GAIN_X1 0x0
|
||||
#define CR1_ALS_GAIN_X2 0x1
|
||||
#define CR1_ALS_GAIN_X4 0x2
|
||||
#define CR1_ALS_GAIN_X8 0x3
|
||||
#define CR1_ALS_GAIN_X16 0x4
|
||||
#define CR1_ALS_GAIN_X32 0x5
|
||||
#define CR1_ALS_GAIN_X64 0x6
|
||||
#define CR1_ALS_GAIN_X128 0x7
|
||||
|
||||
#define CR1_ALS_GAIN_SHIFT (0)
|
||||
#define CR1_ALS_GAIN_MASK (0x7 << CR1_ALS_GAIN_SHIFT)
|
||||
|
||||
|
||||
/*PS fault queue depth for interrupt event output*/
|
||||
#define CR2_PS_FQ_1 0x0
|
||||
#define CR2_PS_FQ_4 0x1
|
||||
#define CR2_PS_FQ_8 0x2
|
||||
#define CR2_PS_FQ_15 0x3
|
||||
|
||||
#define CR2_PS_FQ_SHIFT (6)
|
||||
#define CR2_PS_FQ_MASK (0x3 << CR2_PS_FQ_SHIFT)
|
||||
|
||||
/*interrupt type setting */
|
||||
/*low active*/
|
||||
#define CR2_INT_LEVEL 0x0
|
||||
/*low pulse*/
|
||||
#define CR2_INT_PULSE 0x1
|
||||
|
||||
#define CR2_INT_SHIFT (5)
|
||||
#define CR2_INT_MASK (0x1 << CR2_INT_SHIFT)
|
||||
|
||||
/*resolution for PS*/
|
||||
#define CR2_PS_RES_12 0x0
|
||||
#define CR2_PS_RES_14 0x1
|
||||
#define CR2_PS_RES_16 0x2
|
||||
#define CR2_PS_RES_16_2 0x3
|
||||
|
||||
#define CR2_PS_RES_SHIFT (3)
|
||||
#define CR2_PS_RES_MASK (0x3 << CR2_PS_RES_SHIFT)
|
||||
|
||||
/*sensing amplifier selection for PS*/
|
||||
#define CR2_PS_GAIN_1 0x0
|
||||
#define CR2_PS_GAIN_2 0x1
|
||||
#define CR2_PS_GAIN_4 0x2
|
||||
#define CR2_PS_GAIN_8 0x3
|
||||
#define CR2_PS_GAIN_16 0x4
|
||||
#define CR2_PS_GAIN_32 0x5
|
||||
#define CR2_PS_GAIN_64 0x6
|
||||
#define CR2_PS_GAIN_128 0x7
|
||||
|
||||
#define CR2_PS_GAIN_SHIFT (0)
|
||||
#define CR2_PS_GAIN_MASK (0x7 << CR2_PS_GAIN_SHIFT)
|
||||
|
||||
/*wait-time slot selection*/
|
||||
#define CR3_WAIT_SEL_0 0x0
|
||||
#define CR3_WAIT_SEL_4 0x1
|
||||
#define CR3_WAIT_SEL_8 0x2
|
||||
#define CR3_WAIT_SEL_16 0x3
|
||||
|
||||
#define CR3_WAIT_SEL_SHIFT (6)
|
||||
#define CR3_WAIT_SEL_MASK (0x3 << CR3_WAIT_SEL_SHIFT)
|
||||
|
||||
/*IR-LED drive peak current setting*/
|
||||
#define CR3_LEDDR_12_5 0x0
|
||||
#define CR3_LEDDR_25 0x1
|
||||
#define CR3_LEDDR_50 0x2
|
||||
#define CR3_LEDDR_100 0x3
|
||||
|
||||
#define CR3_LEDDR_SHIFT (4)
|
||||
#define CR3_LEDDR_MASK (0x3 << CR3_LEDDR_SHIFT)
|
||||
|
||||
/*INT pin source selection*/
|
||||
#define CR3_INT_SEL_BATH 0x0
|
||||
#define CR3_INT_SEL_ALS 0x1
|
||||
#define CR3_INT_SEL_PS 0x2
|
||||
#define CR3_INT_SEL_PSAPP 0x3
|
||||
|
||||
#define CR3_INT_SEL_SHIFT (2)
|
||||
#define CR3_INT_SEL_MASK (0x3 << CR3_INT_SEL_SHIFT)
|
||||
|
||||
/*software reset for register and core*/
|
||||
#define CR3_SOFTRST_EN 0x1
|
||||
|
||||
#define CR3_SOFTRST_SHIFT (0)
|
||||
#define CR3_SOFTRST_MASK (0x1 << CR3_SOFTRST_SHIFT)
|
||||
|
||||
/*modulation frequency of LED driver*/
|
||||
#define CR10_FREQ_DIV2 0x0
|
||||
#define CR10_FREQ_DIV4 0x1
|
||||
#define CR10_FREQ_DIV8 0x2
|
||||
#define CR10_FREQ_DIV16 0x3
|
||||
|
||||
#define CR10_FREQ_SHIFT (1)
|
||||
#define CR10_FREQ_MASK (0x3 << CR10_FREQ_SHIFT)
|
||||
|
||||
/*50/60 Rejection enable*/
|
||||
#define CR10_REJ_5060_DIS 0x00
|
||||
#define CR10_REJ_5060_EN 0x01
|
||||
|
||||
#define CR10_REJ_5060_SHIFT (0)
|
||||
#define CR10_REJ_5060_MASK (0x1 << CR10_REJ_5060_SHIFT)
|
||||
|
||||
#define us5152_NUM_CACHABLE_REGS 0x12
|
||||
|
||||
|
||||
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;
|
||||
int i = 0;
|
||||
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
if(!enable)
|
||||
{
|
||||
value = sensor_read_reg(client, REGS_CR0);
|
||||
value |= PWR_MODE_DOWN_MASK; //ShutDown_EN=1
|
||||
result = sensor_write_reg(client, REGS_CR0, value);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = sensor_read_reg(client, REGS_CR0);
|
||||
value &= PWR_MODE_OPERATE_MASK ; //Operation_EN=0
|
||||
result = sensor_write_reg(client, REGS_CR0, value);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!result)
|
||||
break;
|
||||
}
|
||||
|
||||
if(i>1)
|
||||
printk("%s:set %d times",__func__,i);
|
||||
|
||||
|
||||
//TODO:? function to be added here
|
||||
|
||||
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;
|
||||
|
||||
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 = sensor_read_reg(client, REGS_CHIP_ID); //read chip ids
|
||||
printk("us5152 chip id is %x!\n", value);
|
||||
|
||||
value = 0x01;//word accessing
|
||||
|
||||
result = sensor_write_reg(client, REGS_CR0, value);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int us5152_value_report(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:
|
||||
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 index = 0;
|
||||
char buffer[2]= { 0 } ;
|
||||
int ret=0;
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg >= 0)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//value = sensor_read_reg(client, sensor->ops->read_reg); //TODO:? to be changed
|
||||
if(sensor->ops->read_len< 2) //12bit
|
||||
{
|
||||
printk("us5152 data read para num error ; len = %d\n ",sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
memset(buffer , 0 , 2);
|
||||
do
|
||||
{
|
||||
*buffer = sensor->ops->read_reg;
|
||||
ret=sensor_rx_data(client,buffer,sensor->ops->read_len);
|
||||
if(ret<0)
|
||||
return ret;
|
||||
}
|
||||
while(0);
|
||||
value=buffer[1];
|
||||
value =((value << 8) | buffer[0]) & 0xffff;
|
||||
index = us5152_value_report(sensor->input_dev, value); //now is 12bit
|
||||
|
||||
//printk("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
DBG("%s:%s result=%d,index=%d buffer[1]=0x%x , buffer[0]=0x%x \n",__func__,sensor->ops->name, value,index,buffer[1],buffer[0]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate light_us5152_ops = {
|
||||
.name = "ls_us5152",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_US5152, //i2c id number
|
||||
.read_reg = REGS_LBS_SENSOR, //read data
|
||||
.read_len = 2, //data length
|
||||
.id_reg = REGS_CHIP_ID, //read device id from this register
|
||||
.id_data = 0x26, //device id
|
||||
.precision = 12, //12 bits
|
||||
.ctrl_reg = REGS_CR0, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.brightness = {10,4095}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_us5152_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init us5152_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);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit us5152_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, light_get_ops);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Finley Huang finley_huang@upi-semi.com");
|
||||
MODULE_DESCRIPTION("us5152 ambient light sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRIVER_VERSION);
|
||||
|
||||
module_init(us5152_init);
|
||||
module_exit(us5152_exit);
|
||||
|
||||
#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>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
#define DRIVER_VERSION "1.0"
|
||||
|
||||
#define PWR_MODE_DOWN_MASK 0x80
|
||||
#define PWR_MODE_OPERATE_MASK 0x7F
|
||||
|
||||
|
||||
/*us5152 Slave Addr*/
|
||||
#define LIGHT_ADDR 0x72
|
||||
|
||||
/*Interrupt PIN for S3C6410*/
|
||||
#define IRQ_LIGHT_INT IRQ_EINT(6)
|
||||
|
||||
/*Register Set*/
|
||||
#define REGS_CR0 0x00
|
||||
#define REGS_CR1 0x01
|
||||
#define REGS_CR2 0x02
|
||||
#define REGS_CR3 0x03
|
||||
//ALS
|
||||
#define REGS_INT_LSB_TH_LO 0x04
|
||||
#define REGS_INT_MSB_TH_LO 0x05
|
||||
#define REGS_INT_LSB_TH_HI 0x06
|
||||
#define REGS_INT_MSB_TH_HI 0x07
|
||||
//ALS data
|
||||
#define REGS_LBS_SENSOR 0x0C
|
||||
#define REGS_MBS_SENSOR 0x0D
|
||||
|
||||
#define REGS_CR10 0x10
|
||||
#define REGS_CR11 0x11
|
||||
#define REGS_VERSION_ID 0x1F
|
||||
#define REGS_CHIP_ID 0xB2
|
||||
|
||||
/*ShutDown_EN*/
|
||||
#define CR0_OPERATION 0x0
|
||||
#define CR0_SHUTDOWN_EN 0x1
|
||||
|
||||
#define CR0_SHUTDOWN_SHIFT (7)
|
||||
#define CR0_SHUTDOWN_MASK (0x1 << CR0_SHUTDOWN_SHIFT)
|
||||
|
||||
/*OneShot_EN*/
|
||||
#define CR0_ONESHOT_EN 0x01
|
||||
|
||||
#define CR0_ONESHOT_SHIFT (6)
|
||||
#define CR0_ONESHOT_MASK (0x1 << CR0_ONESHOT_SHIFT)
|
||||
|
||||
/*Operation Mode*/
|
||||
#define CR0_OPMODE_ALSANDPS 0x0
|
||||
#define CR0_OPMODE_ALSONLY 0x1
|
||||
#define CR0_OPMODE_IRONLY 0x2
|
||||
|
||||
#define CR0_OPMODE_SHIFT (4)
|
||||
#define CR0_OPMODE_MASK (0x3 << CR0_OPMODE_SHIFT)
|
||||
|
||||
/*all int flag (PROX, INT_A, INT_P)*/
|
||||
#define CR0_ALL_INT_CLEAR 0x0
|
||||
|
||||
#define CR0_ALL_INT_SHIFT (1)
|
||||
#define CR0_ALL_INT_MASK (0x7 << CR0_ALL_INT_SHIFT)
|
||||
|
||||
|
||||
/*indicator of object proximity detection*/
|
||||
#define CR0_PROX_CLEAR 0x0
|
||||
|
||||
#define CR0_PROX_SHIFT (3)
|
||||
#define CR0_PROX_MASK (0x1 << CR0_PROX_SHIFT)
|
||||
|
||||
/*interrupt status of proximity sensor*/
|
||||
#define CR0_INTP_CLEAR 0x0
|
||||
|
||||
#define CR0_INTP_SHIFT (2)
|
||||
#define CR0_INTP_MASK (0x1 << CR0_INTP_SHIFT)
|
||||
|
||||
/*interrupt status of ambient sensor*/
|
||||
#define CR0_INTA_CLEAR 0x0
|
||||
|
||||
#define CR0_INTA_SHIFT (1)
|
||||
#define CR0_INTA_MASK (0x1 << CR0_INTA_SHIFT)
|
||||
|
||||
/*Word mode enable*/
|
||||
#define CR0_WORD_EN 0x1
|
||||
|
||||
#define CR0_WORD_SHIFT (0)
|
||||
#define CR0_WORD_MASK (0x1 << CR0_WORD_SHIFT)
|
||||
|
||||
|
||||
/*ALS fault queue depth for interrupt enent output*/
|
||||
#define CR1_ALS_FQ_1 0x0
|
||||
#define CR1_ALS_FQ_4 0x1
|
||||
#define CR1_ALS_FQ_8 0x2
|
||||
#define CR1_ALS_FQ_16 0x3
|
||||
#define CR1_ALS_FQ_24 0x4
|
||||
#define CR1_ALS_FQ_32 0x5
|
||||
#define CR1_ALS_FQ_48 0x6
|
||||
#define CR1_ALS_FQ_63 0x7
|
||||
|
||||
#define CR1_ALS_FQ_SHIFT (5)
|
||||
#define CR1_ALS_FQ_MASK (0x7 << CR1_ALS_FQ_SHIFT)
|
||||
|
||||
/*resolution for ALS*/
|
||||
#define CR1_ALS_RES_12BIT 0x0
|
||||
#define CR1_ALS_RES_14BIT 0x1
|
||||
#define CR1_ALS_RES_16BIT 0x2
|
||||
#define CR1_ALS_RES_16BIT_2 0x3
|
||||
|
||||
#define CR1_ALS_RES_SHIFT (3)
|
||||
#define CR1_ALS_RES_MASK (0x3 << CR1_ALS_RES_SHIFT)
|
||||
|
||||
/*sensing amplifier selection for ALS*/
|
||||
#define CR1_ALS_GAIN_X1 0x0
|
||||
#define CR1_ALS_GAIN_X2 0x1
|
||||
#define CR1_ALS_GAIN_X4 0x2
|
||||
#define CR1_ALS_GAIN_X8 0x3
|
||||
#define CR1_ALS_GAIN_X16 0x4
|
||||
#define CR1_ALS_GAIN_X32 0x5
|
||||
#define CR1_ALS_GAIN_X64 0x6
|
||||
#define CR1_ALS_GAIN_X128 0x7
|
||||
|
||||
#define CR1_ALS_GAIN_SHIFT (0)
|
||||
#define CR1_ALS_GAIN_MASK (0x7 << CR1_ALS_GAIN_SHIFT)
|
||||
|
||||
|
||||
/*PS fault queue depth for interrupt event output*/
|
||||
#define CR2_PS_FQ_1 0x0
|
||||
#define CR2_PS_FQ_4 0x1
|
||||
#define CR2_PS_FQ_8 0x2
|
||||
#define CR2_PS_FQ_15 0x3
|
||||
|
||||
#define CR2_PS_FQ_SHIFT (6)
|
||||
#define CR2_PS_FQ_MASK (0x3 << CR2_PS_FQ_SHIFT)
|
||||
|
||||
/*interrupt type setting */
|
||||
/*low active*/
|
||||
#define CR2_INT_LEVEL 0x0
|
||||
/*low pulse*/
|
||||
#define CR2_INT_PULSE 0x1
|
||||
|
||||
#define CR2_INT_SHIFT (5)
|
||||
#define CR2_INT_MASK (0x1 << CR2_INT_SHIFT)
|
||||
|
||||
/*resolution for PS*/
|
||||
#define CR2_PS_RES_12 0x0
|
||||
#define CR2_PS_RES_14 0x1
|
||||
#define CR2_PS_RES_16 0x2
|
||||
#define CR2_PS_RES_16_2 0x3
|
||||
|
||||
#define CR2_PS_RES_SHIFT (3)
|
||||
#define CR2_PS_RES_MASK (0x3 << CR2_PS_RES_SHIFT)
|
||||
|
||||
/*sensing amplifier selection for PS*/
|
||||
#define CR2_PS_GAIN_1 0x0
|
||||
#define CR2_PS_GAIN_2 0x1
|
||||
#define CR2_PS_GAIN_4 0x2
|
||||
#define CR2_PS_GAIN_8 0x3
|
||||
#define CR2_PS_GAIN_16 0x4
|
||||
#define CR2_PS_GAIN_32 0x5
|
||||
#define CR2_PS_GAIN_64 0x6
|
||||
#define CR2_PS_GAIN_128 0x7
|
||||
|
||||
#define CR2_PS_GAIN_SHIFT (0)
|
||||
#define CR2_PS_GAIN_MASK (0x7 << CR2_PS_GAIN_SHIFT)
|
||||
|
||||
/*wait-time slot selection*/
|
||||
#define CR3_WAIT_SEL_0 0x0
|
||||
#define CR3_WAIT_SEL_4 0x1
|
||||
#define CR3_WAIT_SEL_8 0x2
|
||||
#define CR3_WAIT_SEL_16 0x3
|
||||
|
||||
#define CR3_WAIT_SEL_SHIFT (6)
|
||||
#define CR3_WAIT_SEL_MASK (0x3 << CR3_WAIT_SEL_SHIFT)
|
||||
|
||||
/*IR-LED drive peak current setting*/
|
||||
#define CR3_LEDDR_12_5 0x0
|
||||
#define CR3_LEDDR_25 0x1
|
||||
#define CR3_LEDDR_50 0x2
|
||||
#define CR3_LEDDR_100 0x3
|
||||
|
||||
#define CR3_LEDDR_SHIFT (4)
|
||||
#define CR3_LEDDR_MASK (0x3 << CR3_LEDDR_SHIFT)
|
||||
|
||||
/*INT pin source selection*/
|
||||
#define CR3_INT_SEL_BATH 0x0
|
||||
#define CR3_INT_SEL_ALS 0x1
|
||||
#define CR3_INT_SEL_PS 0x2
|
||||
#define CR3_INT_SEL_PSAPP 0x3
|
||||
|
||||
#define CR3_INT_SEL_SHIFT (2)
|
||||
#define CR3_INT_SEL_MASK (0x3 << CR3_INT_SEL_SHIFT)
|
||||
|
||||
/*software reset for register and core*/
|
||||
#define CR3_SOFTRST_EN 0x1
|
||||
|
||||
#define CR3_SOFTRST_SHIFT (0)
|
||||
#define CR3_SOFTRST_MASK (0x1 << CR3_SOFTRST_SHIFT)
|
||||
|
||||
/*modulation frequency of LED driver*/
|
||||
#define CR10_FREQ_DIV2 0x0
|
||||
#define CR10_FREQ_DIV4 0x1
|
||||
#define CR10_FREQ_DIV8 0x2
|
||||
#define CR10_FREQ_DIV16 0x3
|
||||
|
||||
#define CR10_FREQ_SHIFT (1)
|
||||
#define CR10_FREQ_MASK (0x3 << CR10_FREQ_SHIFT)
|
||||
|
||||
/*50/60 Rejection enable*/
|
||||
#define CR10_REJ_5060_DIS 0x00
|
||||
#define CR10_REJ_5060_EN 0x01
|
||||
|
||||
#define CR10_REJ_5060_SHIFT (0)
|
||||
#define CR10_REJ_5060_MASK (0x1 << CR10_REJ_5060_SHIFT)
|
||||
|
||||
#define us5152_NUM_CACHABLE_REGS 0x12
|
||||
|
||||
|
||||
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;
|
||||
int i = 0;
|
||||
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
if(!enable)
|
||||
{
|
||||
value = sensor_read_reg(client, REGS_CR0);
|
||||
value |= PWR_MODE_DOWN_MASK; //ShutDown_EN=1
|
||||
result = sensor_write_reg(client, REGS_CR0, value);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = sensor_read_reg(client, REGS_CR0);
|
||||
value &= PWR_MODE_OPERATE_MASK ; //Operation_EN=0
|
||||
result = sensor_write_reg(client, REGS_CR0, value);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!result)
|
||||
break;
|
||||
}
|
||||
|
||||
if(i>1)
|
||||
printk("%s:set %d times",__func__,i);
|
||||
|
||||
|
||||
//TODO:? function to be added here
|
||||
|
||||
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;
|
||||
|
||||
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 = sensor_read_reg(client, REGS_CHIP_ID); //read chip ids
|
||||
printk("us5152 chip id is %x!\n", value);
|
||||
|
||||
value = 0x01;//word accessing
|
||||
|
||||
result = sensor_write_reg(client, REGS_CR0, value);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int us5152_value_report(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:
|
||||
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 index = 0;
|
||||
char buffer[2]= { 0 } ;
|
||||
int ret=0;
|
||||
|
||||
if(sensor->pdata->irq_enable)
|
||||
{
|
||||
if(sensor->ops->int_status_reg >= 0)
|
||||
{
|
||||
value = sensor_read_reg(client, sensor->ops->int_status_reg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//value = sensor_read_reg(client, sensor->ops->read_reg); //TODO:? to be changed
|
||||
if(sensor->ops->read_len< 2) //12bit
|
||||
{
|
||||
printk("us5152 data read para num error ; len = %d\n ",sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
memset(buffer , 0 , 2);
|
||||
do
|
||||
{
|
||||
*buffer = sensor->ops->read_reg;
|
||||
ret=sensor_rx_data(client,buffer,sensor->ops->read_len);
|
||||
if(ret<0)
|
||||
return ret;
|
||||
}
|
||||
while(0);
|
||||
value=buffer[1];
|
||||
value =((value << 8) | buffer[0]) & 0xffff;
|
||||
index = us5152_value_report(sensor->input_dev, value); //now is 12bit
|
||||
|
||||
//printk("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
|
||||
DBG("%s:%s result=%d,index=%d buffer[1]=0x%x , buffer[0]=0x%x \n",__func__,sensor->ops->name, value,index,buffer[1],buffer[0]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate light_us5152_ops = {
|
||||
.name = "ls_us5152",
|
||||
.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
|
||||
.id_i2c = LIGHT_ID_US5152, //i2c id number
|
||||
.read_reg = REGS_LBS_SENSOR, //read data
|
||||
.read_len = 2, //data length
|
||||
.id_reg = REGS_CHIP_ID, //read device id from this register
|
||||
.id_data = 0x26, //device id
|
||||
.precision = 12, //12 bits
|
||||
.ctrl_reg = REGS_CR0, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.brightness = {10,4095}, // brightness
|
||||
.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
|
||||
static struct sensor_operate *light_get_ops(void)
|
||||
{
|
||||
return &light_us5152_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init us5152_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);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit us5152_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = light_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, light_get_ops);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Finley Huang finley_huang@upi-semi.com");
|
||||
MODULE_DESCRIPTION("us5152 ambient light sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRIVER_VERSION);
|
||||
|
||||
module_init(us5152_init);
|
||||
module_exit(us5152_exit);
|
||||
|
||||
|
||||
@@ -1,292 +1,292 @@
|
||||
/* drivers/input/sensors/pressure/ms5607.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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define CMD_RESET 0x1E // ADC reset command
|
||||
#define CMD_ADC_READ 0x00 // ADC read command
|
||||
#define CMD_ADC_CONV 0x40 // ADC conversion command
|
||||
#define CMD_ADC_D1 0x00 // ADC D1 conversion
|
||||
#define CMD_ADC_D2 0x10 // ADC D2 conversion
|
||||
#define CMD_ADC_256 0x00 // ADC OSR=256
|
||||
#define CMD_ADC_512 0x02 // ADC OSR=512
|
||||
#define CMD_ADC_1024 0x04 // ADC OSR=1024
|
||||
#define CMD_ADC_2048 0x06 // ADC OSR=2048
|
||||
#define CMD_ADC_4096 0x08 // ADC OSR=4096
|
||||
#define CMD_PROM_RD 0xA0 // Prom read command
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int C[8] = {0};
|
||||
int g_ms5607_temp;
|
||||
int g_ms5607_pr_status;
|
||||
|
||||
#if defined(CONFIG_TMP_MS5607)
|
||||
extern int g_ms5607_temp_status;
|
||||
#else
|
||||
static int g_ms5607_temp_status = SENSOR_OFF;
|
||||
#endif
|
||||
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
char prom[16];
|
||||
|
||||
if((enable) && (g_ms5607_temp_status == SENSOR_OFF))
|
||||
{
|
||||
result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
if(result)
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
//Read PROM (128 bit of calibration words)
|
||||
memset(prom, 0, 16);
|
||||
prom[0]= CMD_PROM_RD;//CMD_PROM_RD;
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
prom[i*2]= CMD_PROM_RD + i*2;
|
||||
result = sensor_rx_data(client, &prom[i*2], 2);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
C[i] = prom[2*i] << 8 | prom[2*i + 1];
|
||||
//printk("prom[%d]=0x%x,prom[%d]=0x%x",2*i,prom[2*i],(2*i + 1),prom[2*i + 1]);
|
||||
//printk("\nC[%d]=%d,",i+1,C[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g_ms5607_pr_status = enable;
|
||||
|
||||
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;
|
||||
g_ms5607_pr_status = sensor->status_cur;
|
||||
|
||||
//Reset
|
||||
//result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
//if(result)
|
||||
//printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int pressure_report_value(struct input_dev *input, int data)
|
||||
{
|
||||
//get pressure, high and temperature from register data
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, data);
|
||||
input_sync(input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 buffer[3];
|
||||
char index = 0;
|
||||
unsigned int D1=0, D2=0;
|
||||
|
||||
int T2 = 0;
|
||||
long long OFF = 0; // offset at actual temperature
|
||||
long long SENS = 0; // sensitivity at actual temperature
|
||||
int dT = 0; // difference between actual and measured temperature
|
||||
long long OFF2 = 0;
|
||||
long long SENS2 = 0;
|
||||
int P = 0; // compensated pressure value
|
||||
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
if(sensor->ops->read_len < 3) //sensor->ops->read_len = 3
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//D1 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D1 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("\nD1=%d :buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D1,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
//D2 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D2 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("D2=%d:buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D2,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
dT = D2 - ((unsigned int)C[5] << 8);
|
||||
|
||||
g_ms5607_temp = (int)(2000 + ((long long)dT * C[6] >> 23));
|
||||
|
||||
OFF = ((unsigned long long)C[2] << 17) + (C[4] * (long long)dT >> 6);
|
||||
|
||||
SENS = ((long long)C[1] << 16) + (C[3] * (long long)dT >> 7);
|
||||
|
||||
/*calcualte 2nd order pressure and temperature (BP5607 2nd order algorithm)*/
|
||||
if (g_ms5607_temp < -4000 || g_ms5607_temp > 8500)
|
||||
{
|
||||
printk("%s:temperature is error\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_ms5607_temp < 2000)
|
||||
{
|
||||
int tmp;
|
||||
tmp = (g_ms5607_temp - 2000) * (g_ms5607_temp - 2000);
|
||||
|
||||
T2 = (int)((long long)(dT * dT) >> 31);
|
||||
OFF2 = (((long long)tmp * 61)*((long long)tmp * 61)) >> 4;
|
||||
SENS2 = (long long)((tmp*tmp) << 1);
|
||||
|
||||
if (g_ms5607_temp < -1500)
|
||||
{
|
||||
tmp = (g_ms5607_temp + 1500) * (g_ms5607_temp + 1500);
|
||||
OFF2 += 15 * tmp;
|
||||
SENS2 += 8 * tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T2=0;
|
||||
OFF2 = 0;
|
||||
SENS2 = 0;
|
||||
}
|
||||
|
||||
g_ms5607_temp -= T2;
|
||||
OFF -= OFF2;
|
||||
SENS -= SENS2;
|
||||
P = (int)((((D1 * SENS) >> 21) - OFF) >> 15);
|
||||
|
||||
index = pressure_report_value(sensor->input_dev, P);
|
||||
|
||||
DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate pressure_ms5607_ops = {
|
||||
.name = "pr_ms5607",
|
||||
.type = SENSOR_TYPE_PRESSURE, //sensor type and it should be correct
|
||||
.id_i2c = PRESSURE_ID_MS5607, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data
|
||||
.read_len = 3, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 24, //8 bits
|
||||
.ctrl_reg = SENSOR_UNKNOW_DATA, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness = {10,255}, //brightness
|
||||
.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
|
||||
static struct sensor_operate *pressure_get_ops(void)
|
||||
{
|
||||
return &pressure_ms5607_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init pressure_ms5607_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = pressure_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, pressure_get_ops);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit pressure_ms5607_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = pressure_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, pressure_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(pressure_ms5607_init);
|
||||
module_exit(pressure_ms5607_exit);
|
||||
|
||||
/* drivers/input/sensors/pressure/ms5607.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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define CMD_RESET 0x1E // ADC reset command
|
||||
#define CMD_ADC_READ 0x00 // ADC read command
|
||||
#define CMD_ADC_CONV 0x40 // ADC conversion command
|
||||
#define CMD_ADC_D1 0x00 // ADC D1 conversion
|
||||
#define CMD_ADC_D2 0x10 // ADC D2 conversion
|
||||
#define CMD_ADC_256 0x00 // ADC OSR=256
|
||||
#define CMD_ADC_512 0x02 // ADC OSR=512
|
||||
#define CMD_ADC_1024 0x04 // ADC OSR=1024
|
||||
#define CMD_ADC_2048 0x06 // ADC OSR=2048
|
||||
#define CMD_ADC_4096 0x08 // ADC OSR=4096
|
||||
#define CMD_PROM_RD 0xA0 // Prom read command
|
||||
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int C[8] = {0};
|
||||
int g_ms5607_temp;
|
||||
int g_ms5607_pr_status;
|
||||
|
||||
#if defined(CONFIG_TMP_MS5607)
|
||||
extern int g_ms5607_temp_status;
|
||||
#else
|
||||
static int g_ms5607_temp_status = SENSOR_OFF;
|
||||
#endif
|
||||
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
char prom[16];
|
||||
|
||||
if((enable) && (g_ms5607_temp_status == SENSOR_OFF))
|
||||
{
|
||||
result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
if(result)
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
//Read PROM (128 bit of calibration words)
|
||||
memset(prom, 0, 16);
|
||||
prom[0]= CMD_PROM_RD;//CMD_PROM_RD;
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
prom[i*2]= CMD_PROM_RD + i*2;
|
||||
result = sensor_rx_data(client, &prom[i*2], 2);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
C[i] = prom[2*i] << 8 | prom[2*i + 1];
|
||||
//printk("prom[%d]=0x%x,prom[%d]=0x%x",2*i,prom[2*i],(2*i + 1),prom[2*i + 1]);
|
||||
//printk("\nC[%d]=%d,",i+1,C[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g_ms5607_pr_status = enable;
|
||||
|
||||
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;
|
||||
g_ms5607_pr_status = sensor->status_cur;
|
||||
|
||||
//Reset
|
||||
//result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
//if(result)
|
||||
//printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int pressure_report_value(struct input_dev *input, int data)
|
||||
{
|
||||
//get pressure, high and temperature from register data
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, data);
|
||||
input_sync(input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 buffer[3];
|
||||
char index = 0;
|
||||
unsigned int D1=0, D2=0;
|
||||
|
||||
int T2 = 0;
|
||||
long long OFF = 0; // offset at actual temperature
|
||||
long long SENS = 0; // sensitivity at actual temperature
|
||||
int dT = 0; // difference between actual and measured temperature
|
||||
long long OFF2 = 0;
|
||||
long long SENS2 = 0;
|
||||
int P = 0; // compensated pressure value
|
||||
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
if(sensor->ops->read_len < 3) //sensor->ops->read_len = 3
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//D1 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D1 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("\nD1=%d :buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D1,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
//D2 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D2 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("D2=%d:buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D2,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
dT = D2 - ((unsigned int)C[5] << 8);
|
||||
|
||||
g_ms5607_temp = (int)(2000 + ((long long)dT * C[6] >> 23));
|
||||
|
||||
OFF = ((unsigned long long)C[2] << 17) + (C[4] * (long long)dT >> 6);
|
||||
|
||||
SENS = ((long long)C[1] << 16) + (C[3] * (long long)dT >> 7);
|
||||
|
||||
/*calcualte 2nd order pressure and temperature (BP5607 2nd order algorithm)*/
|
||||
if (g_ms5607_temp < -4000 || g_ms5607_temp > 8500)
|
||||
{
|
||||
printk("%s:temperature is error\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_ms5607_temp < 2000)
|
||||
{
|
||||
int tmp;
|
||||
tmp = (g_ms5607_temp - 2000) * (g_ms5607_temp - 2000);
|
||||
|
||||
T2 = (int)((long long)(dT * dT) >> 31);
|
||||
OFF2 = (((long long)tmp * 61)*((long long)tmp * 61)) >> 4;
|
||||
SENS2 = (long long)((tmp*tmp) << 1);
|
||||
|
||||
if (g_ms5607_temp < -1500)
|
||||
{
|
||||
tmp = (g_ms5607_temp + 1500) * (g_ms5607_temp + 1500);
|
||||
OFF2 += 15 * tmp;
|
||||
SENS2 += 8 * tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T2=0;
|
||||
OFF2 = 0;
|
||||
SENS2 = 0;
|
||||
}
|
||||
|
||||
g_ms5607_temp -= T2;
|
||||
OFF -= OFF2;
|
||||
SENS -= SENS2;
|
||||
P = (int)((((D1 * SENS) >> 21) - OFF) >> 15);
|
||||
|
||||
index = pressure_report_value(sensor->input_dev, P);
|
||||
|
||||
DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate pressure_ms5607_ops = {
|
||||
.name = "pr_ms5607",
|
||||
.type = SENSOR_TYPE_PRESSURE, //sensor type and it should be correct
|
||||
.id_i2c = PRESSURE_ID_MS5607, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data
|
||||
.read_len = 3, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 24, //8 bits
|
||||
.ctrl_reg = SENSOR_UNKNOW_DATA, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {100,65535}, //range
|
||||
.brightness = {10,255}, //brightness
|
||||
.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
|
||||
static struct sensor_operate *pressure_get_ops(void)
|
||||
{
|
||||
return &pressure_ms5607_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init pressure_ms5607_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = pressure_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, pressure_get_ops);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit pressure_ms5607_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = pressure_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, pressure_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(pressure_ms5607_init);
|
||||
module_exit(pressure_ms5607_exit);
|
||||
|
||||
|
||||
@@ -1,256 +1,256 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
value = sensor_read_reg(client, CONFIG_REG);
|
||||
value &= ~POWER_MODE_MASK;
|
||||
value |= POWER_DOWN_MODE;
|
||||
result = sensor_write_reg(client, CONFIG_REG, value);
|
||||
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;
|
||||
|
||||
if(enable)
|
||||
sensor_power_updown(client, 1);
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
if( (value & 0x03) == ONLY_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_PROX_ALS_EN;
|
||||
}
|
||||
else if((value & 0x03) == ALL_IDLE )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_PROX_EN;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (value & 0x03) == ONLY_PROX_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_IDLE;
|
||||
}
|
||||
else if((value & 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;
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
value = sensor_read_reg(client, CONFIG_REG);
|
||||
value &= ~POWER_MODE_MASK;
|
||||
value |= POWER_DOWN_MODE;
|
||||
result = sensor_write_reg(client, CONFIG_REG, value);
|
||||
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;
|
||||
|
||||
if(enable)
|
||||
sensor_power_updown(client, 1);
|
||||
|
||||
value = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if(enable)
|
||||
{
|
||||
if( (value & 0x03) == ONLY_ALS_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_PROX_ALS_EN;
|
||||
}
|
||||
else if((value & 0x03) == ALL_IDLE )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ONLY_PROX_EN;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (value & 0x03) == ONLY_PROX_EN )
|
||||
{
|
||||
value &= ~0x03;
|
||||
value |= ALL_IDLE;
|
||||
}
|
||||
else if((value & 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;
|
||||
}
|
||||
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_al3006_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
|
||||
static struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_al3006_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init proximity_al3006_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_al3006_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_al3006_init);
|
||||
module_exit(proximity_al3006_exit);
|
||||
|
||||
|
||||
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_al3006_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
|
||||
static struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_al3006_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init proximity_al3006_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_al3006_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_al3006_init);
|
||||
module_exit(proximity_al3006_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
/* 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>
|
||||
|
||||
|
||||
/* 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>
|
||||
|
||||
|
||||
#define AP3212B_NUM_CACHABLE_REGS 23
|
||||
#define AP3216C_NUM_CACHABLE_REGS 26
|
||||
|
||||
#define AP3216C_NUM_CACHABLE_REGS 26
|
||||
|
||||
#define AP3212B_RAN_COMMAND 0x10
|
||||
#define AP3212B_RAN_MASK 0x30
|
||||
#define AP3212B_RAN_SHIFT (4)
|
||||
|
||||
#define AP3212B_MODE_COMMAND 0x00
|
||||
#define AP3212B_MODE_SHIFT (0)
|
||||
#define AP3212B_MODE_MASK 0x07
|
||||
|
||||
#define AP3212B_MODE_MASK 0x07
|
||||
|
||||
#define AP3212B_INT_COMMAND 0x01
|
||||
#define AP3212B_INT_SHIFT (0)
|
||||
#define AP3212B_INT_MASK 0x03
|
||||
#define AP3212B_INT_PMASK 0x02
|
||||
#define AP3212B_INT_AMASK 0x01
|
||||
|
||||
|
||||
#define AP3212B_OBJ_COMMAND 0x0f
|
||||
#define AP3212B_OBJ_MASK 0x80
|
||||
#define AP3212B_OBJ_SHIFT (7)
|
||||
|
||||
|
||||
#define AP3212B_OBJ_SHIFT (7)
|
||||
|
||||
|
||||
/*
|
||||
* register access helpers
|
||||
*/
|
||||
@@ -62,16 +62,16 @@
|
||||
static int __ap321xx_read_reg(struct i2c_client *client,
|
||||
u32 reg, u8 mask, u8 shift)
|
||||
{
|
||||
u8 val;
|
||||
u8 val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, reg);
|
||||
return (val & mask) >> shift;
|
||||
return (val & mask) >> shift;
|
||||
}
|
||||
|
||||
static int __ap321xx_write_reg(struct i2c_client *client,
|
||||
u32 reg, u8 mask, u8 shift, u8 val)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
u8 tmp;
|
||||
|
||||
tmp = i2c_smbus_read_byte_data(client, reg);
|
||||
@@ -79,16 +79,16 @@ static int __ap321xx_write_reg(struct i2c_client *client,
|
||||
tmp |= val << shift;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, reg, tmp);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* internally used functions
|
||||
*/
|
||||
*/
|
||||
/* range */
|
||||
static int ap321xx_set_range(struct i2c_client *client, int range)
|
||||
static int ap321xx_set_range(struct i2c_client *client, int range)
|
||||
{
|
||||
return __ap321xx_write_reg(client, AP3212B_RAN_COMMAND,
|
||||
AP3212B_RAN_MASK, AP3212B_RAN_SHIFT, range);;
|
||||
@@ -98,36 +98,36 @@ static int ap321xx_set_range(struct i2c_client *client, int range)
|
||||
/* mode */
|
||||
static int ap321xx_get_mode(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
ret = __ap321xx_read_reg(client, sensor->ops->ctrl_reg,
|
||||
AP3212B_MODE_MASK, AP3212B_MODE_SHIFT);
|
||||
return ret;
|
||||
}
|
||||
static int ap321xx_set_mode(struct i2c_client *client, int mode)
|
||||
static int ap321xx_set_mode(struct i2c_client *client, int mode)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
ret = __ap321xx_write_reg(client, sensor->ops->ctrl_reg,
|
||||
AP3212B_MODE_MASK, AP3212B_MODE_SHIFT, mode);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
static int ap321xx_get_intstat(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg);
|
||||
val &= AP3212B_INT_MASK;
|
||||
|
||||
return val >> AP3212B_INT_SHIFT;
|
||||
}
|
||||
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg);
|
||||
val &= AP3212B_INT_MASK;
|
||||
|
||||
return val >> AP3212B_INT_SHIFT;
|
||||
}
|
||||
|
||||
static int ap321xx_get_object(struct i2c_client *client)
|
||||
{
|
||||
int val;
|
||||
@@ -137,33 +137,33 @@ static int ap321xx_get_object(struct i2c_client *client)
|
||||
|
||||
return val >> AP3212B_OBJ_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
static int ap321xx_product_detect(struct i2c_client *client)
|
||||
|
||||
|
||||
static int ap321xx_product_detect(struct i2c_client *client)
|
||||
{
|
||||
int mid = i2c_smbus_read_byte_data(client, 0x03);
|
||||
int pid = i2c_smbus_read_byte_data(client, 0x04);
|
||||
int rid = i2c_smbus_read_byte_data(client, 0x05);
|
||||
|
||||
if ( mid == 0x01 && pid == 0x01 &&
|
||||
if ( mid == 0x01 && pid == 0x01 &&
|
||||
(rid == 0x03 || rid == 0x04) )
|
||||
{
|
||||
//printk("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid);
|
||||
//printk("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid);
|
||||
}
|
||||
else if ( (mid == 0x01 && pid == 0x02 && rid == 0x00) ||
|
||||
else if ( (mid == 0x01 && pid == 0x02 && rid == 0x00) ||
|
||||
(mid == 0x02 && pid == 0x02 && rid == 0x01))
|
||||
{
|
||||
//printk("RevID [%d], ==> DA3212 v2.0 ...... AP3212C/AP3216C detected\n", rid);
|
||||
//printk("RevID [%d], ==> DA3212 v2.0 ...... AP3212C/AP3216C detected\n", rid);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("MakeID[%d] ProductID[%d] RevID[%d] .... can't detect ... bad reversion!!!\n", mid, pid, rid);
|
||||
printk("MakeID[%d] ProductID[%d] RevID[%d] .... can't detect ... bad reversion!!!\n", mid, pid, rid);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int ap321xx_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* set defaults */
|
||||
@@ -171,25 +171,25 @@ static int ap321xx_init_client(struct i2c_client *client)
|
||||
ap321xx_set_mode(client, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int ap321xx_psensor_enable(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0,mode;
|
||||
|
||||
|
||||
mode = ap321xx_get_mode(client);
|
||||
if((mode & 0x02) == 0){
|
||||
mode |= 0x02;
|
||||
ret = ap321xx_set_mode(client,mode);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ap321xx_psensor_disable(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0,mode;
|
||||
|
||||
|
||||
mode = ap321xx_get_mode(client);
|
||||
if(mode & 0x02){
|
||||
mode &= ~0x02;
|
||||
@@ -198,125 +198,125 @@ static int ap321xx_psensor_disable(struct i2c_client *client)
|
||||
ret = ap321xx_set_mode(client,mode);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if (enable){
|
||||
result = ap321xx_psensor_enable(client);
|
||||
}
|
||||
else
|
||||
result = ap321xx_psensor_disable(client);
|
||||
|
||||
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 = ap321xx_product_detect(client);
|
||||
if (result)
|
||||
{
|
||||
dev_err(&client->dev, "ret: %d, product version detect failed.\n",result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* initialize the AP3212B chip */
|
||||
result = ap321xx_init_client(client);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
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;
|
||||
u8 int_stat;
|
||||
|
||||
int_stat = ap321xx_get_intstat(client);
|
||||
// ALS int
|
||||
if (int_stat & AP3212B_INT_PMASK)
|
||||
{
|
||||
value = ap321xx_get_object(client);
|
||||
input_report_abs(sensor->input_dev, ABS_DISTANCE, value);
|
||||
input_sync(sensor->input_dev);
|
||||
}
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
//register setting according to chip datasheet
|
||||
if (enable){
|
||||
result = ap321xx_psensor_enable(client);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate proximity_ap321xx_ops = {
|
||||
.name = "ps_ap321xx",
|
||||
.type = SENSOR_TYPE_PROXIMITY, //sensor type and it should be correct
|
||||
.id_i2c = PROXIMITY_ID_AP321XX, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data //there are two regs, we fix them in code.
|
||||
.read_len = 1, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register //there are 3 regs, we fix them in code.
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = AP3212B_MODE_COMMAND, //enable or disable
|
||||
.int_status_reg = AP3212B_INT_COMMAND, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.trig = IRQF_TRIGGER_FALLING | 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
|
||||
static struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_ap321xx_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init proximity_ap321xx_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_ap321xx_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_ap321xx_init);
|
||||
module_exit(proximity_ap321xx_exit);
|
||||
|
||||
|
||||
else
|
||||
result = ap321xx_psensor_disable(client);
|
||||
|
||||
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 = ap321xx_product_detect(client);
|
||||
if (result)
|
||||
{
|
||||
dev_err(&client->dev, "ret: %d, product version detect failed.\n",result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* initialize the AP3212B chip */
|
||||
result = ap321xx_init_client(client);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = sensor->ops->active(client,0,0);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
sensor->status_cur = SENSOR_OFF;
|
||||
|
||||
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;
|
||||
u8 int_stat;
|
||||
|
||||
int_stat = ap321xx_get_intstat(client);
|
||||
// ALS int
|
||||
if (int_stat & AP3212B_INT_PMASK)
|
||||
{
|
||||
value = ap321xx_get_object(client);
|
||||
input_report_abs(sensor->input_dev, ABS_DISTANCE, value);
|
||||
input_sync(sensor->input_dev);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sensor_operate proximity_ap321xx_ops = {
|
||||
.name = "ps_ap321xx",
|
||||
.type = SENSOR_TYPE_PROXIMITY, //sensor type and it should be correct
|
||||
.id_i2c = PROXIMITY_ID_AP321XX, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data //there are two regs, we fix them in code.
|
||||
.read_len = 1, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register //there are 3 regs, we fix them in code.
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 8, //8 bits
|
||||
.ctrl_reg = AP3212B_MODE_COMMAND, //enable or disable
|
||||
.int_status_reg = AP3212B_INT_COMMAND, //intterupt status register
|
||||
.range = {0,10}, //range
|
||||
.brightness ={10,255}, // brightness
|
||||
.trig = IRQF_TRIGGER_FALLING | 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
|
||||
static struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_ap321xx_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init proximity_ap321xx_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_ap321xx_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_ap321xx_init);
|
||||
module_exit(proximity_ap321xx_exit);
|
||||
|
||||
|
||||
|
||||
@@ -1,262 +1,262 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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<<6)
|
||||
#define ALS_RANGE_28836 (1<<6)
|
||||
|
||||
//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<<4)
|
||||
#define PS_CUR_200MA (1<<4)
|
||||
#define PS_SLP_10MS (0<<5)
|
||||
#define PS_SLP_30MS (1<<5)
|
||||
#define PS_SLP_90MS (2<<5)
|
||||
#define PS_SLP_270MS (3<<5)
|
||||
#define TRIG_PS_OR_LS (0<<7)
|
||||
#define TRIG_PS_AND_LS (1<<7)
|
||||
|
||||
//STA_TUS
|
||||
#define STA_PS_INT (1<<5)
|
||||
#define STA_ALS_INT (1<<4)
|
||||
|
||||
|
||||
/****************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__);
|
||||
|
||||
if(enable)
|
||||
sensor->ops->report(sensor->client);
|
||||
|
||||
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;
|
||||
sensor->ops->ctrl_data &= ~TRIG_PS_AND_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);
|
||||
|
||||
buffer[0] = sensor->ops->read_reg;
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
value = buffer[0];
|
||||
|
||||
input_report_abs(sensor->input_dev, ABS_DISTANCE, (value>>2)?0:1);
|
||||
input_sync(sensor->input_dev);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,(value>>2)?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_stk3171_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
|
||||
static struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_stk3171_ops;
|
||||
}
|
||||
|
||||
static int __init proximity_stk3171_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_stk3171_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_stk3171_init);
|
||||
module_exit(proximity_stk3171_exit);
|
||||
|
||||
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#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<<6)
|
||||
#define ALS_RANGE_28836 (1<<6)
|
||||
|
||||
//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<<4)
|
||||
#define PS_CUR_200MA (1<<4)
|
||||
#define PS_SLP_10MS (0<<5)
|
||||
#define PS_SLP_30MS (1<<5)
|
||||
#define PS_SLP_90MS (2<<5)
|
||||
#define PS_SLP_270MS (3<<5)
|
||||
#define TRIG_PS_OR_LS (0<<7)
|
||||
#define TRIG_PS_AND_LS (1<<7)
|
||||
|
||||
//STA_TUS
|
||||
#define STA_PS_INT (1<<5)
|
||||
#define STA_ALS_INT (1<<4)
|
||||
|
||||
|
||||
/****************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__);
|
||||
|
||||
if(enable)
|
||||
sensor->ops->report(sensor->client);
|
||||
|
||||
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;
|
||||
sensor->ops->ctrl_data &= ~TRIG_PS_AND_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);
|
||||
|
||||
buffer[0] = sensor->ops->read_reg;
|
||||
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
value = buffer[0];
|
||||
|
||||
input_report_abs(sensor->input_dev, ABS_DISTANCE, (value>>2)?0:1);
|
||||
input_sync(sensor->input_dev);
|
||||
DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,(value>>2)?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_stk3171_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
|
||||
static struct sensor_operate *proximity_get_ops(void)
|
||||
{
|
||||
return &proximity_stk3171_ops;
|
||||
}
|
||||
|
||||
static int __init proximity_stk3171_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);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit proximity_stk3171_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_stk3171_init);
|
||||
module_exit(proximity_stk3171_exit);
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,245 +1,245 @@
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#define SENSOR_I2C_RATE 200*1000
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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[1].addr = address;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
msgs[1].buf = data;
|
||||
msgs[1].len = len;
|
||||
|
||||
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)
|
||||
{
|
||||
//struct sensor_private_data* sensor =
|
||||
// (struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
char reg = rxData[0];
|
||||
ret = senosr_i2c_read(client->adapter, client->addr, reg, length, rxData);
|
||||
|
||||
DBG("addr=0x%x,len=%d,rxdata:",reg,length);
|
||||
for(i=0; i<length; i++)
|
||||
DBG("0x%x,",rxData[i]);
|
||||
DBG("\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_rx_data);
|
||||
|
||||
int sensor_tx_data(struct i2c_client *client, char *txData, int length)
|
||||
{
|
||||
//struct sensor_private_data* sensor =
|
||||
//(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
DBG("addr=0x%x,len=%d,txdata:",txData[0],length);
|
||||
for(i=1; i<length; i++)
|
||||
DBG("0x%x,",txData[i]);
|
||||
DBG("\n");
|
||||
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);
|
||||
|
||||
static int i2c_master_normal_recv(const struct i2c_client *client, char *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
int ret;
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags | I2C_M_RD;
|
||||
msg.len = count;
|
||||
msg.buf = (char *)buf;
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
|
||||
return (ret == 1) ? count : ret;
|
||||
}
|
||||
|
||||
static int i2c_master_normal_send(const struct i2c_client *client, const char *buf, int count, int scl_rate)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags;
|
||||
msg.len = count;
|
||||
msg.buf = (char *)buf;
|
||||
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
return (ret == 1) ? count : ret;
|
||||
}
|
||||
|
||||
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[1] = {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);
|
||||
|
||||
/* 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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
#define SENSOR_I2C_RATE 200*1000
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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[1].addr = address;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
msgs[1].buf = data;
|
||||
msgs[1].len = len;
|
||||
|
||||
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)
|
||||
{
|
||||
//struct sensor_private_data* sensor =
|
||||
// (struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
char reg = rxData[0];
|
||||
ret = senosr_i2c_read(client->adapter, client->addr, reg, length, rxData);
|
||||
|
||||
DBG("addr=0x%x,len=%d,rxdata:",reg,length);
|
||||
for(i=0; i<length; i++)
|
||||
DBG("0x%x,",rxData[i]);
|
||||
DBG("\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_rx_data);
|
||||
|
||||
int sensor_tx_data(struct i2c_client *client, char *txData, int length)
|
||||
{
|
||||
//struct sensor_private_data* sensor =
|
||||
//(struct sensor_private_data *)i2c_get_clientdata(client);
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
DBG("addr=0x%x,len=%d,txdata:",txData[0],length);
|
||||
for(i=1; i<length; i++)
|
||||
DBG("0x%x,",txData[i]);
|
||||
DBG("\n");
|
||||
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);
|
||||
|
||||
static int i2c_master_normal_recv(const struct i2c_client *client, char *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
int ret;
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags | I2C_M_RD;
|
||||
msg.len = count;
|
||||
msg.buf = (char *)buf;
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
|
||||
return (ret == 1) ? count : ret;
|
||||
}
|
||||
|
||||
static int i2c_master_normal_send(const struct i2c_client *client, const char *buf, int count, int scl_rate)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags;
|
||||
msg.len = count;
|
||||
msg.buf = (char *)buf;
|
||||
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
return (ret == 1) ? count : ret;
|
||||
}
|
||||
|
||||
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[1] = {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);
|
||||
|
||||
|
||||
@@ -1,309 +1,309 @@
|
||||
/* drivers/input/sensors/temperature/tmp_ms5607.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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define CMD_RESET 0x1E // ADC reset command
|
||||
#define CMD_ADC_READ 0x00 // ADC read command
|
||||
#define CMD_ADC_CONV 0x40 // ADC conversion command
|
||||
#define CMD_ADC_D1 0x00 // ADC D1 conversion
|
||||
#define CMD_ADC_D2 0x10 // ADC D2 conversion
|
||||
#define CMD_ADC_256 0x00 // ADC OSR=256
|
||||
#define CMD_ADC_512 0x02 // ADC OSR=512
|
||||
#define CMD_ADC_1024 0x04 // ADC OSR=1024
|
||||
#define CMD_ADC_2048 0x06 // ADC OSR=2048
|
||||
#define CMD_ADC_4096 0x08 // ADC OSR=4096
|
||||
#define CMD_PROM_RD 0xA0 // Prom read command
|
||||
|
||||
#if defined(CONFIG_PR_MS5607)
|
||||
extern int g_ms5607_temp;
|
||||
extern int g_ms5607_pr_status;
|
||||
#else
|
||||
static int g_ms5607_temp = 0;
|
||||
static int g_ms5607_pr_status = SENSOR_OFF;
|
||||
#endif
|
||||
|
||||
int g_ms5607_temp_status;
|
||||
static int C[8] = {0};
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
char prom[16];
|
||||
|
||||
if((enable)&&(g_ms5607_pr_status == SENSOR_OFF))
|
||||
{
|
||||
result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
if(result)
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
//Read PROM (128 bit of calibration words)
|
||||
memset(prom, 0, 16);
|
||||
prom[0]= CMD_PROM_RD;//CMD_PROM_RD;
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
prom[i*2]= CMD_PROM_RD + i*2;
|
||||
result = sensor_rx_data(client, &prom[i*2], 2);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
C[i] = prom[2*i] << 8 | prom[2*i + 1];
|
||||
//printk("prom[%d]=0x%x,prom[%d]=0x%x",2*i,prom[2*i],(2*i + 1),prom[2*i + 1]);
|
||||
//printk("\nC[%d]=%d,",i+1,C[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g_ms5607_temp_status = enable;
|
||||
|
||||
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;
|
||||
g_ms5607_temp_status = sensor->status_cur;
|
||||
//Reset
|
||||
//result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
//if(result)
|
||||
//printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int temperature_report_value(struct input_dev *input, int data)
|
||||
{
|
||||
//get temperature, high and temperature from register data
|
||||
|
||||
input_report_abs(input, ABS_THROTTLE, data);
|
||||
input_sync(input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 buffer[3];
|
||||
char index = 0;
|
||||
unsigned int D1=0, D2=0;
|
||||
|
||||
int T2 = 0;
|
||||
long long OFF = 0; // offset at actual temperature
|
||||
long long SENS = 0; // sensitivity at actual temperature
|
||||
int dT = 0; // difference between actual and measured temperature
|
||||
long long OFF2 = 0;
|
||||
long long SENS2 = 0;
|
||||
int P = 0; // compensated pressure value
|
||||
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
if(sensor->ops->read_len < 3) //sensor->ops->read_len = 3
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(g_ms5607_pr_status == SENSOR_OFF)
|
||||
{
|
||||
|
||||
//D1 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D1 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("\nD1=%d :buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D1,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
//D2 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D2 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("D2=%d:buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D2,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
dT = D2 - ((unsigned int)C[5] << 8);
|
||||
|
||||
g_ms5607_temp = (int)(2000 + ((long long)dT * C[6] >> 23));
|
||||
|
||||
OFF = ((unsigned long long)C[2] << 17) + (C[4] * (long long)dT >> 6);
|
||||
|
||||
SENS = ((long long)C[1] << 16) + (C[3] * (long long)dT >> 7);
|
||||
|
||||
/*calcualte 2nd order pressure and temperature (BP5607 2nd order algorithm)*/
|
||||
if (g_ms5607_temp < -4000 || g_ms5607_temp > 8500)
|
||||
{
|
||||
printk("%s:temperature is error\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_ms5607_temp < 2000)
|
||||
{
|
||||
int tmp;
|
||||
tmp = (g_ms5607_temp - 2000) * (g_ms5607_temp - 2000);
|
||||
|
||||
T2 = (int)((long long)(dT * dT) >> 31);
|
||||
OFF2 = (((long long)tmp * 61)*((long long)tmp * 61)) >> 4;
|
||||
SENS2 = (long long)((tmp*tmp) << 1);
|
||||
|
||||
if (g_ms5607_temp < -1500)
|
||||
{
|
||||
tmp = (g_ms5607_temp + 1500) * (g_ms5607_temp + 1500);
|
||||
OFF2 += 15 * tmp;
|
||||
SENS2 += 8 * tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T2=0;
|
||||
OFF2 = 0;
|
||||
SENS2 = 0;
|
||||
}
|
||||
|
||||
g_ms5607_temp -= T2;
|
||||
OFF -= OFF2;
|
||||
SENS -= SENS2;
|
||||
P = (int)((((D1 * SENS) >> 21) - OFF) >> 15);
|
||||
|
||||
index = temperature_report_value(sensor->input_dev, g_ms5607_temp);
|
||||
|
||||
DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
index = temperature_report_value(sensor->input_dev, g_ms5607_temp);
|
||||
|
||||
#if defined(CONFIG_PR_MS5607)
|
||||
DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);
|
||||
#else
|
||||
printk("%s:errror,need pr_ms5607\n",__func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate temperature_ms5607_ops = {
|
||||
.name = "tmp_ms5607",
|
||||
.type = SENSOR_TYPE_TEMPERATURE, //sensor type and it should be correct
|
||||
.id_i2c = TEMPERATURE_ID_MS5607, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data
|
||||
.read_len = 3, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 24, //8 bits
|
||||
.ctrl_reg = SENSOR_UNKNOW_DATA, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {100,65535}, //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
|
||||
static struct sensor_operate *temperature_get_ops(void)
|
||||
{
|
||||
return &temperature_ms5607_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init temperature_ms5607_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = temperature_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, temperature_get_ops);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit temperature_ms5607_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = temperature_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, temperature_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(temperature_ms5607_init);
|
||||
module_exit(temperature_ms5607_exit);
|
||||
|
||||
/* drivers/input/sensors/temperature/tmp_ms5607.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 <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
|
||||
|
||||
#define CMD_RESET 0x1E // ADC reset command
|
||||
#define CMD_ADC_READ 0x00 // ADC read command
|
||||
#define CMD_ADC_CONV 0x40 // ADC conversion command
|
||||
#define CMD_ADC_D1 0x00 // ADC D1 conversion
|
||||
#define CMD_ADC_D2 0x10 // ADC D2 conversion
|
||||
#define CMD_ADC_256 0x00 // ADC OSR=256
|
||||
#define CMD_ADC_512 0x02 // ADC OSR=512
|
||||
#define CMD_ADC_1024 0x04 // ADC OSR=1024
|
||||
#define CMD_ADC_2048 0x06 // ADC OSR=2048
|
||||
#define CMD_ADC_4096 0x08 // ADC OSR=4096
|
||||
#define CMD_PROM_RD 0xA0 // Prom read command
|
||||
|
||||
#if defined(CONFIG_PR_MS5607)
|
||||
extern int g_ms5607_temp;
|
||||
extern int g_ms5607_pr_status;
|
||||
#else
|
||||
static int g_ms5607_temp = 0;
|
||||
static int g_ms5607_pr_status = SENSOR_OFF;
|
||||
#endif
|
||||
|
||||
int g_ms5607_temp_status;
|
||||
static int C[8] = {0};
|
||||
|
||||
/****************operate according to sensor chip:start************/
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
char prom[16];
|
||||
|
||||
if((enable)&&(g_ms5607_pr_status == SENSOR_OFF))
|
||||
{
|
||||
result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
if(result)
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
//Read PROM (128 bit of calibration words)
|
||||
memset(prom, 0, 16);
|
||||
prom[0]= CMD_PROM_RD;//CMD_PROM_RD;
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
prom[i*2]= CMD_PROM_RD + i*2;
|
||||
result = sensor_rx_data(client, &prom[i*2], 2);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
C[i] = prom[2*i] << 8 | prom[2*i + 1];
|
||||
//printk("prom[%d]=0x%x,prom[%d]=0x%x",2*i,prom[2*i],(2*i + 1),prom[2*i + 1]);
|
||||
//printk("\nC[%d]=%d,",i+1,C[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g_ms5607_temp_status = enable;
|
||||
|
||||
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;
|
||||
g_ms5607_temp_status = sensor->status_cur;
|
||||
//Reset
|
||||
//result = sensor_write_reg_normal(client, CMD_RESET);
|
||||
//if(result)
|
||||
//printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int temperature_report_value(struct input_dev *input, int data)
|
||||
{
|
||||
//get temperature, high and temperature from register data
|
||||
|
||||
input_report_abs(input, ABS_THROTTLE, data);
|
||||
input_sync(input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 buffer[3];
|
||||
char index = 0;
|
||||
unsigned int D1=0, D2=0;
|
||||
|
||||
int T2 = 0;
|
||||
long long OFF = 0; // offset at actual temperature
|
||||
long long SENS = 0; // sensitivity at actual temperature
|
||||
int dT = 0; // difference between actual and measured temperature
|
||||
long long OFF2 = 0;
|
||||
long long SENS2 = 0;
|
||||
int P = 0; // compensated pressure value
|
||||
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
if(sensor->ops->read_len < 3) //sensor->ops->read_len = 3
|
||||
{
|
||||
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(g_ms5607_pr_status == SENSOR_OFF)
|
||||
{
|
||||
|
||||
//D1 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D1 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("\nD1=%d :buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D1,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
//D2 conversion
|
||||
sensor_write_reg_normal(client, CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096);
|
||||
msleep(10);
|
||||
|
||||
memset(buffer, 0, 3);
|
||||
buffer[0] = CMD_ADC_READ;
|
||||
result = sensor_rx_data(client, &buffer[0], 3);
|
||||
if(result)
|
||||
{
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
D2 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||
DBG("D2=%d:buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D2,buffer[0],buffer[1],buffer[2]);
|
||||
|
||||
dT = D2 - ((unsigned int)C[5] << 8);
|
||||
|
||||
g_ms5607_temp = (int)(2000 + ((long long)dT * C[6] >> 23));
|
||||
|
||||
OFF = ((unsigned long long)C[2] << 17) + (C[4] * (long long)dT >> 6);
|
||||
|
||||
SENS = ((long long)C[1] << 16) + (C[3] * (long long)dT >> 7);
|
||||
|
||||
/*calcualte 2nd order pressure and temperature (BP5607 2nd order algorithm)*/
|
||||
if (g_ms5607_temp < -4000 || g_ms5607_temp > 8500)
|
||||
{
|
||||
printk("%s:temperature is error\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_ms5607_temp < 2000)
|
||||
{
|
||||
int tmp;
|
||||
tmp = (g_ms5607_temp - 2000) * (g_ms5607_temp - 2000);
|
||||
|
||||
T2 = (int)((long long)(dT * dT) >> 31);
|
||||
OFF2 = (((long long)tmp * 61)*((long long)tmp * 61)) >> 4;
|
||||
SENS2 = (long long)((tmp*tmp) << 1);
|
||||
|
||||
if (g_ms5607_temp < -1500)
|
||||
{
|
||||
tmp = (g_ms5607_temp + 1500) * (g_ms5607_temp + 1500);
|
||||
OFF2 += 15 * tmp;
|
||||
SENS2 += 8 * tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T2=0;
|
||||
OFF2 = 0;
|
||||
SENS2 = 0;
|
||||
}
|
||||
|
||||
g_ms5607_temp -= T2;
|
||||
OFF -= OFF2;
|
||||
SENS -= SENS2;
|
||||
P = (int)((((D1 * SENS) >> 21) - OFF) >> 15);
|
||||
|
||||
index = temperature_report_value(sensor->input_dev, g_ms5607_temp);
|
||||
|
||||
DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
index = temperature_report_value(sensor->input_dev, g_ms5607_temp);
|
||||
|
||||
#if defined(CONFIG_PR_MS5607)
|
||||
DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);
|
||||
#else
|
||||
printk("%s:errror,need pr_ms5607\n",__func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
struct sensor_operate temperature_ms5607_ops = {
|
||||
.name = "tmp_ms5607",
|
||||
.type = SENSOR_TYPE_TEMPERATURE, //sensor type and it should be correct
|
||||
.id_i2c = TEMPERATURE_ID_MS5607, //i2c id number
|
||||
.read_reg = SENSOR_UNKNOW_DATA, //read data
|
||||
.read_len = 3, //data length
|
||||
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
|
||||
.id_data = SENSOR_UNKNOW_DATA, //device id
|
||||
.precision = 24, //8 bits
|
||||
.ctrl_reg = SENSOR_UNKNOW_DATA, //enable or disable
|
||||
.int_status_reg = SENSOR_UNKNOW_DATA, //intterupt status register
|
||||
.range = {100,65535}, //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
|
||||
static struct sensor_operate *temperature_get_ops(void)
|
||||
{
|
||||
return &temperature_ms5607_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init temperature_ms5607_init(void)
|
||||
{
|
||||
struct sensor_operate *ops = temperature_get_ops();
|
||||
int result = 0;
|
||||
int type = ops->type;
|
||||
result = sensor_register_slave(type, NULL, NULL, temperature_get_ops);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit temperature_ms5607_exit(void)
|
||||
{
|
||||
struct sensor_operate *ops = temperature_get_ops();
|
||||
int type = ops->type;
|
||||
sensor_unregister_slave(type, NULL, NULL, temperature_get_ops);
|
||||
}
|
||||
|
||||
|
||||
module_init(temperature_ms5607_init);
|
||||
module_exit(temperature_ms5607_exit);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ enum sensor_id {
|
||||
ANGLE_ID_ALL,
|
||||
ANGLE_ID_KXTIK,
|
||||
ANGLE_ID_LIS3DH,
|
||||
|
||||
|
||||
ACCEL_ID_ALL,
|
||||
ACCEL_ID_LIS331,
|
||||
ACCEL_ID_LSM303DLX,
|
||||
@@ -89,15 +89,15 @@ enum sensor_id {
|
||||
LIGHT_ID_STK3171,
|
||||
LIGHT_ID_ISL29023,
|
||||
LIGHT_ID_AP321XX,
|
||||
LIGHT_ID_PHOTORESISTOR,
|
||||
LIGHT_ID_PHOTORESISTOR,
|
||||
LIGHT_ID_US5152,
|
||||
|
||||
PROXIMITY_ID_ALL,
|
||||
PROXIMITY_ID_AL3006,
|
||||
PROXIMITY_ID_STK3171,
|
||||
PROXIMITY_ID_AP321XX,
|
||||
|
||||
TEMPERATURE_ID_ALL,
|
||||
|
||||
TEMPERATURE_ID_ALL,
|
||||
TEMPERATURE_ID_MS5607,
|
||||
|
||||
PRESSURE_ID_ALL,
|
||||
@@ -106,7 +106,7 @@ enum sensor_id {
|
||||
|
||||
HALL_ID_ALL,
|
||||
HALL_ID_OCH165T,
|
||||
|
||||
|
||||
SENSOR_NUM_ID,
|
||||
};
|
||||
|
||||
@@ -118,12 +118,12 @@ struct sensor_axis {
|
||||
};
|
||||
|
||||
struct sensor_flag {
|
||||
atomic_t a_flag;
|
||||
atomic_t m_flag;
|
||||
atomic_t mv_flag;
|
||||
atomic_t a_flag;
|
||||
atomic_t m_flag;
|
||||
atomic_t mv_flag;
|
||||
atomic_t open_flag;
|
||||
atomic_t debug_flag;
|
||||
long long delay;
|
||||
long long delay;
|
||||
wait_queue_head_t open_wq;
|
||||
};
|
||||
|
||||
@@ -133,7 +133,7 @@ struct sensor_operate {
|
||||
int type;
|
||||
int id_i2c;
|
||||
int range[2];
|
||||
int brightness[2];//backlight min_brightness max_brightness
|
||||
int brightness[2];//backlight min_brightness max_brightness
|
||||
int read_reg;
|
||||
int read_len;
|
||||
int id_reg;
|
||||
@@ -144,8 +144,8 @@ struct sensor_operate {
|
||||
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 (*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);
|
||||
@@ -157,16 +157,16 @@ struct sensor_operate {
|
||||
/* Platform data for the sensor */
|
||||
struct sensor_private_data {
|
||||
int type;
|
||||
struct i2c_client *client;
|
||||
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;
|
||||
wait_queue_head_t data_ready_wq;
|
||||
struct mutex data_mutex;
|
||||
struct mutex operation_mutex;
|
||||
struct mutex operation_mutex;
|
||||
struct mutex sensor_mutex;
|
||||
struct mutex i2c_mutex;
|
||||
int status_cur;
|
||||
@@ -175,7 +175,7 @@ struct sensor_private_data {
|
||||
struct sensor_flag flags;
|
||||
struct i2c_device_id *i2c_id;
|
||||
struct sensor_platform_data *pdata;
|
||||
struct sensor_operate *ops;
|
||||
struct sensor_operate *ops;
|
||||
struct file_operations fops;
|
||||
struct miscdevice miscdev;
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
@@ -190,7 +190,7 @@ struct sensor_platform_data {
|
||||
int power_pin;
|
||||
int reset_pin;
|
||||
int standby_pin;
|
||||
int irq_enable; //if irq_enable=1 then use irq else use polling
|
||||
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;
|
||||
@@ -216,13 +216,13 @@ struct sensor_platform_data {
|
||||
int (*gsensor_platform_wakeup)(void);
|
||||
void (*exit_platform_hw)(void);
|
||||
};
|
||||
|
||||
|
||||
struct akm8975_platform_data {
|
||||
short m_layout[4][3][3];
|
||||
char project_name[64];
|
||||
int gpio_DRDY;
|
||||
};
|
||||
|
||||
|
||||
struct akm_platform_data {
|
||||
short m_layout[4][3][3];
|
||||
char project_name[64];
|
||||
@@ -291,8 +291,8 @@ extern int sensor_unregister_slave(int type,struct i2c_client *client,
|
||||
#endif
|
||||
|
||||
#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_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 *)
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
Reference in New Issue
Block a user