sensors: import ASH drivers
Change-Id: I25085520ec10434c270cff80684d2d8676e00887
This commit is contained in:
parent
8d81bf7933
commit
755665a8e2
183
drivers/sensors/ASH/ASH_ATTR/ASH_ATTR.c
Normal file
183
drivers/sensors/ASH/ASH_ATTR/ASH_ATTR.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************/
|
||||
/* Asus Sensor Hub Attribute */
|
||||
/*****************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
static int g_devMajor = -1;
|
||||
static struct class *g_property_class = NULL;
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_ATTR"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_ATTR_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s]"fmt,MODULE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s]"fmt,MODULE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s]"fmt,MODULE_NAME,##args)
|
||||
|
||||
static int ASH_class_open(struct inode * inode, struct file * file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations ASH_class_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ASH_class_open,
|
||||
};
|
||||
|
||||
static int create_ASH_chrdev(void)
|
||||
{
|
||||
/*create character device*/
|
||||
g_devMajor = register_chrdev(0, "sensors", &ASH_class_fops);
|
||||
if (g_devMajor < 0) {
|
||||
err("%s: could not get major number\n", __FUNCTION__);
|
||||
return g_devMajor;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_ASH_class(void)
|
||||
{
|
||||
/* create sys/class file node*/
|
||||
g_property_class = class_create(THIS_MODULE, "sensors");
|
||||
if (IS_ERR(g_property_class)) {
|
||||
err("%s: class_create ERROR.\n", __FUNCTION__);
|
||||
return PTR_ERR(g_property_class);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Return NULL for error handling
|
||||
*/
|
||||
struct device *ASH_ATTR_device_create(ASH_type type)
|
||||
{
|
||||
int ret = 0;
|
||||
dev_t dev;
|
||||
struct device *sensor_dev=NULL;
|
||||
|
||||
/*prepare character device and return for error handling*/
|
||||
if(g_devMajor < 0){
|
||||
ret=create_ASH_chrdev();
|
||||
if(ret < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*prepare sys/class file node and return for error handling*/
|
||||
if(g_property_class == NULL || IS_ERR(g_property_class) ){
|
||||
ret=create_ASH_class();
|
||||
if(ret < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(type){
|
||||
case psensor:
|
||||
dev = MKDEV(g_devMajor, psensor);
|
||||
sensor_dev = device_create(g_property_class, NULL, dev, NULL, "%s", "psensor");
|
||||
break;
|
||||
case psensor_2nd:
|
||||
dev = MKDEV(g_devMajor, psensor_2nd);
|
||||
sensor_dev = device_create(g_property_class, NULL, dev, NULL, "%s", "psensor_2nd");
|
||||
break;
|
||||
case lsensor:
|
||||
dev = MKDEV(g_devMajor, lsensor);
|
||||
sensor_dev = device_create(g_property_class, NULL, dev, NULL, "%s", "lsensor");
|
||||
break;
|
||||
case lsensor_2nd:
|
||||
dev = MKDEV(g_devMajor, lsensor_2nd);
|
||||
sensor_dev = device_create(g_property_class, NULL, dev, NULL, "%s", "lsensor_2nd");
|
||||
break;
|
||||
case frgbsensor:
|
||||
dev = MKDEV(g_devMajor, frgbsensor);
|
||||
sensor_dev = device_create(g_property_class, NULL, dev, NULL, "%s", "frgbsensor");
|
||||
break;
|
||||
case hallsensor:
|
||||
dev = MKDEV(g_devMajor, hallsensor);
|
||||
sensor_dev = device_create(g_property_class, NULL, dev, NULL, "%s", "hallsensor");
|
||||
break;
|
||||
case sarsensor:
|
||||
dev = MKDEV(g_devMajor, sarsensor);
|
||||
sensor_dev = device_create(g_property_class, NULL, dev, NULL, "%s", "sarsensor");
|
||||
break;
|
||||
default:
|
||||
err("%s: Type ERROR.(%d)\n", __FUNCTION__, type);
|
||||
|
||||
}
|
||||
|
||||
if (IS_ERR(sensor_dev)) {
|
||||
ret = PTR_ERR(sensor_dev);
|
||||
err("%s: sensor_dev pointer is ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sensor_dev;
|
||||
}
|
||||
EXPORT_SYMBOL(ASH_ATTR_device_create);
|
||||
|
||||
void ASH_ATTR_device_remove(ASH_type type)
|
||||
{
|
||||
dev_t dev;
|
||||
|
||||
switch(type){
|
||||
case psensor:
|
||||
dev = MKDEV(g_devMajor, psensor);
|
||||
device_destroy(g_property_class, dev);
|
||||
break;
|
||||
case psensor_2nd:
|
||||
dev = MKDEV(g_devMajor, psensor_2nd);
|
||||
device_destroy(g_property_class, dev);
|
||||
break;
|
||||
case lsensor:
|
||||
dev = MKDEV(g_devMajor, lsensor);
|
||||
device_destroy(g_property_class, dev);
|
||||
break;
|
||||
case lsensor_2nd:
|
||||
dev = MKDEV(g_devMajor, lsensor_2nd);
|
||||
device_destroy(g_property_class, dev);
|
||||
break;
|
||||
case frgbsensor:
|
||||
dev = MKDEV(g_devMajor, frgbsensor);
|
||||
device_destroy(g_property_class, dev);
|
||||
break;
|
||||
case hallsensor:
|
||||
dev = MKDEV(g_devMajor, hallsensor);
|
||||
device_destroy(g_property_class, dev);
|
||||
break;
|
||||
case sarsensor:
|
||||
dev = MKDEV(g_devMajor, sarsensor);
|
||||
device_destroy(g_property_class, dev);
|
||||
break;
|
||||
default:
|
||||
err("%s: ASH_ATTR_device_remove Type ERROR.(%d)\n", __FUNCTION__, type);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(ASH_ATTR_device_remove);
|
504
drivers/sensors/ASH/ASH_ATTR/lsensor_2nd_ATTR.c
Normal file
504
drivers/sensors/ASH/ASH_ATTR/lsensor_2nd_ATTR.c
Normal file
@ -0,0 +1,504 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/****************************/
|
||||
/* Light Sensor Atrribute */
|
||||
/***************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
#define RGB 1
|
||||
#define BUF_SIZE (10)
|
||||
static lsensor_ATTR *g_light_ATTR = NULL;
|
||||
static struct device *g_lsensor_dev;
|
||||
|
||||
/*******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_ATTR"
|
||||
#define SENSOR_TYPE_NAME "light"
|
||||
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_ATTR_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
static ssize_t ATT_light_show_vendor(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_light_ATTR->info_type->vendor, "") == 0) {
|
||||
err("2nd Show vendor NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_light_ATTR->info_type->vendor);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_module_number(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_light_ATTR->info_type->module_number, "") == 0) {
|
||||
err("2nd Show module number NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_light_ATTR->info_type->module_number);
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/*Calibration Function*/
|
||||
/************************/
|
||||
static ssize_t ATT_light_show_calibration(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_light_ATTR->ATTR_Calibration->light_show_calibration == NULL) {
|
||||
err("2nd light_show_calibration NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_light_ATTR->ATTR_Calibration->light_show_calibration();
|
||||
dbg("2nd Light Sensor show Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_calibration(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_light_ATTR->ATTR_Calibration->light_store_calibration == NULL) {
|
||||
err("2nd light_store_calibration NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("Light Sensor store Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Light Sensor store Calibration: %lu\n", calvalue);
|
||||
if(g_light_ATTR->ATTR_Calibration->light_store_calibration(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_gain(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int gainvalue = 0;
|
||||
if(g_light_ATTR->ATTR_Calibration->light_show_gain == NULL) {
|
||||
err("2nd light_show_gain NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
gainvalue = g_light_ATTR->ATTR_Calibration->light_show_gain();
|
||||
return sprintf(buf, "%d.%05d\n",
|
||||
gainvalue/LIGHT_GAIN_ACCURACY_CALVALUE, gainvalue%LIGHT_GAIN_ACCURACY_CALVALUE);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_adc(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int adc = 0;
|
||||
if(g_light_ATTR->ATTR_Calibration->light_show_adc == NULL) {
|
||||
err("2nd light_show_adc NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
adc = g_light_ATTR->ATTR_Calibration->light_show_adc();
|
||||
return sprintf(buf, "%d\n", adc);
|
||||
}
|
||||
|
||||
/********************/
|
||||
/*BMMI Function*/
|
||||
/*******************/
|
||||
static ssize_t ATT_light_show_atd_test(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool atd_test = false;
|
||||
if(g_light_ATTR->ATTR_BMMI->light_show_atd_test== NULL) {
|
||||
err("2nd light_show_atd_test NOT SUPPORT. \n");
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
atd_test = g_light_ATTR->ATTR_BMMI->light_show_atd_test();
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Hardware Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_light_show_read_reg(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Hardware->light_show_reg== NULL) {
|
||||
err("2nd IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
i2c_reg_addr = g_light_ATTR->ATTR_Hardware->show_reg_addr;
|
||||
i2c_reg_value = g_light_ATTR->ATTR_Hardware->light_show_reg(i2c_reg_addr);
|
||||
|
||||
return sprintf(buf, "%d\n", i2c_reg_value);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_read_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Hardware->light_show_reg== NULL) {
|
||||
err("2nd IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x", &i2c_reg_addr);
|
||||
g_light_ATTR->ATTR_Hardware->show_reg_addr=i2c_reg_addr;
|
||||
|
||||
return count;
|
||||
}
|
||||
static ssize_t ATT_light_store_write_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Hardware->light_store_reg== NULL) {
|
||||
err("2nd IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x %d", &i2c_reg_addr, &i2c_reg_value);
|
||||
|
||||
log("2nd IRsensor_store_reg, addr=%02X, value=%02X\n", i2c_reg_addr, i2c_reg_value);
|
||||
if(g_light_ATTR->ATTR_Hardware->light_store_reg(i2c_reg_addr, i2c_reg_value) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/******************/
|
||||
/*HAL Function*/
|
||||
/*****************/
|
||||
static ssize_t ATT_light_show_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_light_ATTR->ATTR_HAL->light_show_switch_onoff== NULL) {
|
||||
err("2nd light_show_switch_onoff NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_light_ATTR->ATTR_HAL->light_show_switch_onoff();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_light_ATTR->ATTR_HAL->light_store_switch_onoff == NULL) {
|
||||
err("2nd light_store_switch_onoff NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
/*check input character*/
|
||||
if (0 == strncmp(buf, "off", 3))
|
||||
bOn = false;
|
||||
else if (0 == strncmp(buf, "on", 2))
|
||||
bOn = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
log("2nd Light Sensor switch %s\n", bOn?"on":"off");
|
||||
if(g_light_ATTR->ATTR_HAL->light_store_switch_onoff(bOn) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_lux(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int lux;
|
||||
if(g_light_ATTR->ATTR_HAL->light_show_lux== NULL) {
|
||||
err("2nd light_show_lux NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
lux = g_light_ATTR->ATTR_HAL->light_show_lux();
|
||||
return sprintf(buf, "%d\n", lux);
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Extension Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_light_show_allreg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_allreg== NULL) {
|
||||
err("2nd IRsensor_show_allreg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
ret=g_light_ATTR->ATTR_Extension->light_show_allreg(dev, attr, buf);
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_sensitivity(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int sensitivity = 0;
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_sensitivity == NULL) {
|
||||
err("2nd light_show_sensitivity NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
sensitivity = g_light_ATTR->ATTR_Extension->light_show_sensitivity();
|
||||
return sprintf(buf, "%d\n", sensitivity);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_sensitivity(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long sensitivity;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_sensitivity == NULL) {
|
||||
err("2nd light_store_sensitivity NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &sensitivity) < 0))
|
||||
return -EINVAL;
|
||||
if(sensitivity < 0) {
|
||||
err("2nd Light Sensor store Sensitivity with NEGATIVE value. (%lu) \n", sensitivity);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Light Sensor store Sensitivity: %lu\n", sensitivity);
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_sensitivity(sensitivity) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_log_threshold(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int log_threshold = 0;
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_log_threshold == NULL) {
|
||||
err("2nd light_show_log_threshold NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
log_threshold = g_light_ATTR->ATTR_Extension->light_show_log_threshold();
|
||||
return sprintf(buf, "%d\n", log_threshold);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_log_threshold(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long log_threshold;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_log_threshold == NULL) {
|
||||
err("2nd light_store_log_threshold NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &log_threshold) < 0))
|
||||
return -EINVAL;
|
||||
if(log_threshold < 0) {
|
||||
err("2nd Light Sensor store Log Threshold with NEGATIVE value. (%lu) \n", log_threshold);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Light Sensor store Log Threshold: %lu\n", log_threshold);
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_log_threshold(log_threshold) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* +++ For stress test debug +++ */
|
||||
static ssize_t ATT_light_show_int_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int l_int_counter=0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_int_count == NULL) {
|
||||
err("2nd light_show_int_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
l_int_counter = g_light_ATTR->ATTR_Extension->light_show_int_count();
|
||||
return sprintf(buf, "%d\n", l_int_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_event_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int l_event_counter=0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_event_count == NULL) {
|
||||
err("2nd light_show_event_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
l_event_counter = g_light_ATTR->ATTR_Extension->light_show_event_count();
|
||||
return sprintf(buf, "%d\n", l_event_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_error_mesg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
char* error_mesg=kzalloc(sizeof(char [ERROR_MESG_SIZE]), GFP_KERNEL);
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_error_mesg== NULL) {
|
||||
err("2nd IRsensor_show_error_mesg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
ret = g_light_ATTR->ATTR_Extension->light_show_error_mesg(error_mesg);
|
||||
|
||||
return sprintf(buf, "%s\n", error_mesg);
|
||||
}
|
||||
/* --- For stress test debug --- */
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
static ssize_t ATT_light_show_selection(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int selection = 0;
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_selection == NULL) {
|
||||
err("2nd light_show_selection NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
selection = g_light_ATTR->ATTR_Extension->light_show_selection();
|
||||
return sprintf(buf, "%d\n", selection);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_selection(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long selection;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_selection == NULL) {
|
||||
err("2nd light_store_selection NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &selection) < 0))
|
||||
return -EINVAL;
|
||||
if(selection < 0) {
|
||||
err("2nd Light Sensor store selection with NEGATIVE value. (%lu) \n", selection);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Light Sensor store selection: %lu\n", selection);
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_selection(selection) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute light_property_attrs[] = {
|
||||
/*read only*/
|
||||
__ATTR(vendor, 0444, ATT_light_show_vendor, NULL),
|
||||
__ATTR(module_number, 0444, ATT_light_show_module_number, NULL),
|
||||
__ATTR(adc, 0444, ATT_light_show_adc, NULL),
|
||||
__ATTR(gain, 0444, ATT_light_show_gain, NULL),
|
||||
__ATTR(atd_status, 0444, ATT_light_show_atd_test, NULL),
|
||||
__ATTR(lux, 0444, ATT_light_show_lux, NULL),
|
||||
__ATTR(dump_reg, 0444, ATT_light_show_allreg, NULL),
|
||||
/* +++ For stress test debug +++ */
|
||||
__ATTR(int_counter, 0444, ATT_light_show_int_count, NULL),
|
||||
__ATTR(event_counter, 0444, ATT_light_show_event_count, NULL),
|
||||
__ATTR(error_mesg, 0444, ATT_light_show_error_mesg, NULL),
|
||||
/* --- For stress test debug --- */
|
||||
/*read/write*/
|
||||
__ATTR(switch, 0664, ATT_light_show_switch_onoff, ATT_light_store_switch_onoff),
|
||||
__ATTR(cal, 0664, ATT_light_show_calibration, ATT_light_store_calibration),
|
||||
__ATTR(sensitivity, 0664, ATT_light_show_sensitivity, ATT_light_store_sensitivity),
|
||||
__ATTR(read_reg, 0664, ATT_light_show_read_reg, ATT_light_store_read_reg),
|
||||
__ATTR(write_reg, 0220, NULL, ATT_light_store_write_reg),
|
||||
__ATTR(log_threshold, 0664, ATT_light_show_log_threshold, ATT_light_store_log_threshold),
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
__ATTR(selection, 0664, ATT_light_show_selection, ATT_light_store_selection),
|
||||
};
|
||||
|
||||
int lsensor_ATTR_register_2nd(lsensor_ATTR *mATTR)
|
||||
{
|
||||
int ret = 0;
|
||||
int ATTR_index;
|
||||
|
||||
g_light_ATTR=mATTR;
|
||||
|
||||
/*lsensor device*/
|
||||
g_lsensor_dev = ASH_ATTR_device_create(lsensor_2nd);
|
||||
if (IS_ERR(g_lsensor_dev) || g_lsensor_dev == NULL) {
|
||||
err("%s: 2nd lsensor create ERROR.\n", __FUNCTION__);
|
||||
ret = PTR_ERR(g_lsensor_dev);
|
||||
return ret;
|
||||
}
|
||||
for (ATTR_index=0; ATTR_index < ARRAY_SIZE(light_property_attrs); ATTR_index++) {
|
||||
ret = device_create_file(g_lsensor_dev, &light_property_attrs[ATTR_index]);
|
||||
if (ret){
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_ATTR_register_2nd);
|
||||
|
||||
int lsensor_ATTR_unregister_2nd(void)
|
||||
{
|
||||
ASH_ATTR_device_remove(lsensor_2nd);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_ATTR_unregister_2nd);
|
||||
|
||||
int lsensor_ATTR_create_2nd(struct device_attribute *mlsensor_attr)
|
||||
{
|
||||
int ret = 0;
|
||||
if(mlsensor_attr == NULL) {
|
||||
err("%s: 2nd the device_attribute is NULL point. \n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = device_create_file(g_lsensor_dev, mlsensor_attr);
|
||||
if (ret){
|
||||
err("%s: 2nd device_create_file ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_ATTR_create_2nd);
|
||||
|
502
drivers/sensors/ASH/ASH_ATTR/lsensor_ATTR.c
Normal file
502
drivers/sensors/ASH/ASH_ATTR/lsensor_ATTR.c
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/****************************/
|
||||
/* Light Sensor Atrribute */
|
||||
/***************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
#define RGB 1
|
||||
#define BUF_SIZE (10)
|
||||
static lsensor_ATTR *g_light_ATTR = NULL;
|
||||
static struct device *g_lsensor_dev;
|
||||
|
||||
/*******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_ATTR"
|
||||
#define SENSOR_TYPE_NAME "light"
|
||||
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_ATTR_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
static ssize_t ATT_light_show_vendor(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_light_ATTR->info_type->vendor, "") == 0) {
|
||||
err("Show vendor NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_light_ATTR->info_type->vendor);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_module_number(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_light_ATTR->info_type->module_number, "") == 0) {
|
||||
err("Show module number NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_light_ATTR->info_type->module_number);
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/*Calibration Function*/
|
||||
/************************/
|
||||
static ssize_t ATT_light_show_calibration(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_light_ATTR->ATTR_Calibration->light_show_calibration == NULL) {
|
||||
err("light_show_calibration NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_light_ATTR->ATTR_Calibration->light_show_calibration();
|
||||
dbg("Light Sensor show Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_calibration(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_light_ATTR->ATTR_Calibration->light_store_calibration == NULL) {
|
||||
err("light_store_calibration NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("Light Sensor store Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Light Sensor store Calibration: %lu\n", calvalue);
|
||||
if(g_light_ATTR->ATTR_Calibration->light_store_calibration(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_gain(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int gainvalue = 0;
|
||||
if(g_light_ATTR->ATTR_Calibration->light_show_gain == NULL) {
|
||||
err("light_show_gain NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
gainvalue = g_light_ATTR->ATTR_Calibration->light_show_gain();
|
||||
return sprintf(buf, "%d.%05d\n",
|
||||
gainvalue/LIGHT_GAIN_ACCURACY_CALVALUE, gainvalue%LIGHT_GAIN_ACCURACY_CALVALUE);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_adc(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int adc = 0;
|
||||
if(g_light_ATTR->ATTR_Calibration->light_show_adc == NULL) {
|
||||
err("light_show_adc NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
adc = g_light_ATTR->ATTR_Calibration->light_show_adc();
|
||||
return sprintf(buf, "%d\n", adc);
|
||||
}
|
||||
|
||||
/********************/
|
||||
/*BMMI Function*/
|
||||
/*******************/
|
||||
static ssize_t ATT_light_show_atd_test(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool atd_test = false;
|
||||
if(g_light_ATTR->ATTR_BMMI->light_show_atd_test== NULL) {
|
||||
err("light_show_atd_test NOT SUPPORT. \n");
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
atd_test = g_light_ATTR->ATTR_BMMI->light_show_atd_test();
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Hardware Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_light_show_read_reg(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Hardware->light_show_reg== NULL) {
|
||||
err("IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
i2c_reg_addr = g_light_ATTR->ATTR_Hardware->show_reg_addr;
|
||||
i2c_reg_value = g_light_ATTR->ATTR_Hardware->light_show_reg(i2c_reg_addr);
|
||||
|
||||
return sprintf(buf, "%d\n", i2c_reg_value);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_read_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Hardware->light_show_reg== NULL) {
|
||||
err("IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x", &i2c_reg_addr);
|
||||
g_light_ATTR->ATTR_Hardware->show_reg_addr=i2c_reg_addr;
|
||||
|
||||
return count;
|
||||
}
|
||||
static ssize_t ATT_light_store_write_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Hardware->light_store_reg== NULL) {
|
||||
err("IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x %d", &i2c_reg_addr, &i2c_reg_value);
|
||||
|
||||
log("IRsensor_store_reg, addr=%02X, value=%02X\n", i2c_reg_addr, i2c_reg_value);
|
||||
if(g_light_ATTR->ATTR_Hardware->light_store_reg(i2c_reg_addr, i2c_reg_value) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/******************/
|
||||
/*HAL Function*/
|
||||
/*****************/
|
||||
static ssize_t ATT_light_show_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_light_ATTR->ATTR_HAL->light_show_switch_onoff== NULL) {
|
||||
err("light_show_switch_onoff NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_light_ATTR->ATTR_HAL->light_show_switch_onoff();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_light_ATTR->ATTR_HAL->light_store_switch_onoff == NULL) {
|
||||
err("light_store_switch_onoff NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
/*check input character*/
|
||||
if (0 == strncmp(buf, "off", 3))
|
||||
bOn = false;
|
||||
else if (0 == strncmp(buf, "on", 2))
|
||||
bOn = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
log("Light Sensor switch %s\n", bOn?"on":"off");
|
||||
if(g_light_ATTR->ATTR_HAL->light_store_switch_onoff(bOn) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_lux(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int lux;
|
||||
if(g_light_ATTR->ATTR_HAL->light_show_lux== NULL) {
|
||||
err("light_show_lux NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
lux = g_light_ATTR->ATTR_HAL->light_show_lux();
|
||||
return sprintf(buf, "%d\n", lux);
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Extension Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_light_show_allreg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_allreg== NULL) {
|
||||
err("IRsensor_show_allreg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
log("print all reg");
|
||||
return g_light_ATTR->ATTR_Extension->light_show_allreg(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_sensitivity(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int sensitivity = 0;
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_sensitivity == NULL) {
|
||||
err("light_show_sensitivity NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
sensitivity = g_light_ATTR->ATTR_Extension->light_show_sensitivity();
|
||||
return sprintf(buf, "%d\n", sensitivity);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_sensitivity(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long sensitivity;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_sensitivity == NULL) {
|
||||
err("light_store_sensitivity NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &sensitivity) < 0))
|
||||
return -EINVAL;
|
||||
if(sensitivity < 0) {
|
||||
err("Light Sensor store Sensitivity with NEGATIVE value. (%lu) \n", sensitivity);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Light Sensor store Sensitivity: %lu\n", sensitivity);
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_sensitivity(sensitivity) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_log_threshold(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int log_threshold = 0;
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_log_threshold == NULL) {
|
||||
err("light_show_log_threshold NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
log_threshold = g_light_ATTR->ATTR_Extension->light_show_log_threshold();
|
||||
return sprintf(buf, "%d\n", log_threshold);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_log_threshold(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long log_threshold;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_log_threshold == NULL) {
|
||||
err("light_store_log_threshold NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &log_threshold) < 0))
|
||||
return -EINVAL;
|
||||
if(log_threshold < 0) {
|
||||
err("Light Sensor store Log Threshold with NEGATIVE value. (%lu) \n", log_threshold);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Light Sensor store Log Threshold: %lu\n", log_threshold);
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_log_threshold(log_threshold) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* +++ For stress test debug +++ */
|
||||
static ssize_t ATT_light_show_int_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int l_int_counter=0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_int_count == NULL) {
|
||||
err("light_show_int_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
l_int_counter = g_light_ATTR->ATTR_Extension->light_show_int_count();
|
||||
return sprintf(buf, "%d\n", l_int_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_event_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int l_event_counter=0;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_event_count == NULL) {
|
||||
err("light_show_event_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
l_event_counter = g_light_ATTR->ATTR_Extension->light_show_event_count();
|
||||
return sprintf(buf, "%d\n", l_event_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_show_error_mesg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
char* error_mesg=kzalloc(sizeof(char [ERROR_MESG_SIZE]), GFP_KERNEL);
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_error_mesg== NULL) {
|
||||
err("IRsensor_show_error_mesg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
ret = g_light_ATTR->ATTR_Extension->light_show_error_mesg(error_mesg);
|
||||
|
||||
return sprintf(buf, "%s\n", error_mesg);
|
||||
}
|
||||
/* --- For stress test debug --- */
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
static ssize_t ATT_light_show_selection(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int selection = 0;
|
||||
if(g_light_ATTR->ATTR_Extension->light_show_selection == NULL) {
|
||||
err("light_show_selection NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
selection = g_light_ATTR->ATTR_Extension->light_show_selection();
|
||||
return sprintf(buf, "%d\n", selection);
|
||||
}
|
||||
|
||||
static ssize_t ATT_light_store_selection(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long selection;
|
||||
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_selection == NULL) {
|
||||
err("light_store_selection NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &selection) < 0))
|
||||
return -EINVAL;
|
||||
if(selection < 0) {
|
||||
err("Light Sensor store selection with NEGATIVE value. (%lu) \n", selection);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Light Sensor store selection: %lu\n", selection);
|
||||
if(g_light_ATTR->ATTR_Extension->light_store_selection(selection) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute light_property_attrs[] = {
|
||||
/*read only*/
|
||||
__ATTR(vendor, 0444, ATT_light_show_vendor, NULL),
|
||||
__ATTR(module_number, 0444, ATT_light_show_module_number, NULL),
|
||||
__ATTR(adc, 0444, ATT_light_show_adc, NULL),
|
||||
__ATTR(gain, 0444, ATT_light_show_gain, NULL),
|
||||
__ATTR(atd_status, 0444, ATT_light_show_atd_test, NULL),
|
||||
__ATTR(lux, 0444, ATT_light_show_lux, NULL),
|
||||
__ATTR(dump_reg, 0444, ATT_light_show_allreg, NULL),
|
||||
/* +++ For stress test debug +++ */
|
||||
__ATTR(int_counter, 0444, ATT_light_show_int_count, NULL),
|
||||
__ATTR(event_counter, 0444, ATT_light_show_event_count, NULL),
|
||||
__ATTR(error_mesg, 0444, ATT_light_show_error_mesg, NULL),
|
||||
/* --- For stress test debug --- */
|
||||
/*read/write*/
|
||||
__ATTR(switch, 0664, ATT_light_show_switch_onoff, ATT_light_store_switch_onoff),
|
||||
__ATTR(cal, 0664, ATT_light_show_calibration, ATT_light_store_calibration),
|
||||
__ATTR(sensitivity, 0664, ATT_light_show_sensitivity, ATT_light_store_sensitivity),
|
||||
__ATTR(read_reg, 0664, ATT_light_show_read_reg, ATT_light_store_read_reg),
|
||||
__ATTR(write_reg, 0220, NULL, ATT_light_store_write_reg),
|
||||
__ATTR(log_threshold, 0664, ATT_light_show_log_threshold, ATT_light_store_log_threshold),
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
__ATTR(selection, 0664, ATT_light_show_selection, ATT_light_store_selection),
|
||||
};
|
||||
|
||||
int lsensor_ATTR_register(lsensor_ATTR *mATTR)
|
||||
{
|
||||
int ret = 0;
|
||||
int ATTR_index;
|
||||
|
||||
g_light_ATTR=mATTR;
|
||||
|
||||
/*lsensor device*/
|
||||
g_lsensor_dev = ASH_ATTR_device_create(lsensor);
|
||||
if (IS_ERR(g_lsensor_dev) || g_lsensor_dev == NULL) {
|
||||
err("%s: lsensor create ERROR.\n", __FUNCTION__);
|
||||
ret = PTR_ERR(g_lsensor_dev);
|
||||
return ret;
|
||||
}
|
||||
for (ATTR_index=0; ATTR_index < ARRAY_SIZE(light_property_attrs); ATTR_index++) {
|
||||
ret = device_create_file(g_lsensor_dev, &light_property_attrs[ATTR_index]);
|
||||
if (ret){
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_ATTR_register);
|
||||
|
||||
int lsensor_ATTR_unregister(void)
|
||||
{
|
||||
ASH_ATTR_device_remove(lsensor);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_ATTR_unregister);
|
||||
|
||||
int lsensor_ATTR_create(struct device_attribute *mlsensor_attr)
|
||||
{
|
||||
int ret = 0;
|
||||
if(mlsensor_attr == NULL) {
|
||||
err("%s: the device_attribute is NULL point. \n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = device_create_file(g_lsensor_dev, mlsensor_attr);
|
||||
if (ret){
|
||||
err("%s: device_create_file ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_ATTR_create);
|
||||
|
794
drivers/sensors/ASH/ASH_ATTR/psensor_2nd_ATTR.c
Normal file
794
drivers/sensors/ASH/ASH_ATTR/psensor_2nd_ATTR.c
Normal file
@ -0,0 +1,794 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************************/
|
||||
/* Proximity Sensor Atrribute */
|
||||
/********************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
#define RGB 1
|
||||
#define BUF_SIZE (10)
|
||||
static psensor_ATTR *g_psensor_ATTR = NULL;
|
||||
static struct device *g_psensor_dev;
|
||||
|
||||
/*******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_ATTR"
|
||||
#define SENSOR_TYPE_NAME "proximity_2nd"
|
||||
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_ATTR_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
static void proximity_onoff(struct work_struct *work);
|
||||
static DECLARE_WORK(proximity_onoff_work, proximity_onoff);
|
||||
static int g_psensor_on_flag = false;
|
||||
bool g_Psensor2_load_cal_status = false;
|
||||
|
||||
static ssize_t ATT_proximity_show_vendor(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_psensor_ATTR->info_type->vendor, "") == 0) {
|
||||
err("2nd Show vendor NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_psensor_ATTR->info_type->vendor);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_module_number(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_psensor_ATTR->info_type->module_number, "") == 0) {
|
||||
err("2nd Show module number NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_psensor_ATTR->info_type->module_number);
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/*Calibration Function*/
|
||||
/************************/
|
||||
static ssize_t ATT_proximity_show_calibration_hi(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_hi== NULL) {
|
||||
err("2nd proximity_show_calibration_hi NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_hi();
|
||||
dbg("2nd Proximity show High Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_calibration_hi(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_hi == NULL) {
|
||||
err("2nd proximity_store_calibration_hi NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("2nd Proximity store High Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Proximity store High Calibration: %lu\n", calvalue);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_hi(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_calibration_lo(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_lo == NULL) {
|
||||
err("2nd proximity_show_calibration_lo NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_lo();
|
||||
dbg("2nd Proximity show Low Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_calibration_lo(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_lo == NULL) {
|
||||
err("2nd proximity_store_calibration_lo NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("2nd Proximity store Low Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Proximity store Low Calibration: %lu\n", calvalue);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_lo(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_calibration_inf(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_inf == NULL) {
|
||||
err("2nd proximity_show_calibration_inf NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_inf();
|
||||
dbg("2nd Proximity show Inf Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_calibration_inf(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_inf == NULL) {
|
||||
err("2nd proximity_store_calibration_inf NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("2nd Proximity store Inf Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store Inf Calibration: %lu\n", calvalue);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_inf(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_adc(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int adc = 0;
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_adc == NULL) {
|
||||
err("2nd proximity_show_adc NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
adc = g_psensor_ATTR->ATTR_Calibration->proximity_show_adc();
|
||||
return sprintf(buf, "%d\n", adc);
|
||||
}
|
||||
|
||||
/********************/
|
||||
/*BMMI Function*/
|
||||
/*******************/
|
||||
static ssize_t ATT_proximity_show_atd_test(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool atd_test = false;
|
||||
if(g_psensor_ATTR->ATTR_BMMI->proximity_show_atd_test== NULL) {
|
||||
err("2nd proximity_show_atd_test NOT SUPPORT. \n");
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
atd_test = g_psensor_ATTR->ATTR_BMMI->proximity_show_atd_test();
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Hardware Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_proximity_show_read_reg(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_show_reg== NULL) {
|
||||
err("2nd IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
i2c_reg_addr = g_psensor_ATTR->ATTR_Hardware->show_reg_addr;
|
||||
i2c_reg_value = g_psensor_ATTR->ATTR_Hardware->proximity_show_reg(i2c_reg_addr);
|
||||
|
||||
return sprintf(buf, "%d\n", i2c_reg_value);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_read_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_show_reg== NULL) {
|
||||
err("2nd IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x", &i2c_reg_addr);
|
||||
g_psensor_ATTR->ATTR_Hardware->show_reg_addr=i2c_reg_addr;
|
||||
|
||||
return count;
|
||||
}
|
||||
static ssize_t ATT_proximity_store_write_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_store_reg== NULL) {
|
||||
err("2nd IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x %d", &i2c_reg_addr, &i2c_reg_value);
|
||||
|
||||
log("2nd IRsensor_store_reg, addr=%02X, value=%02X\n", i2c_reg_addr, i2c_reg_value);
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_store_reg(i2c_reg_addr, i2c_reg_value) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/******************/
|
||||
/*HAL Function*/
|
||||
/*****************/
|
||||
static void proximity_onoff(struct work_struct *work){
|
||||
log("2nd Proximity switch %s\n", g_psensor_on_flag?"on":"off");
|
||||
g_psensor_ATTR->ATTR_HAL->proximity_store_switch_onoff(g_psensor_on_flag);
|
||||
}
|
||||
static ssize_t ATT_proximity_show_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_show_switch_onoff== NULL) {
|
||||
err("2nd proximity_show_switch_onoff NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_psensor_ATTR->ATTR_HAL->proximity_show_switch_onoff();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_store_switch_onoff == NULL) {
|
||||
err("2nd proximity_store_switch_onoff NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
/*check input character*/
|
||||
if (0 == strncmp(buf, "off", 3)){
|
||||
bOn = false;
|
||||
g_psensor_on_flag = false;
|
||||
}else if (0 == strncmp(buf, "on", 2)){
|
||||
bOn = true;
|
||||
g_psensor_on_flag = true;
|
||||
}else{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Proximity workqueue to switch %s\n", bOn?"on":"off");
|
||||
schedule_work(&proximity_onoff_work);
|
||||
|
||||
/*
|
||||
log("2nd Proximity switch %s\n", bOn?"on":"off");
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_store_switch_onoff(bOn) < 0)
|
||||
return -EINVAL;
|
||||
*/
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_status(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool proximity_status;
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_show_status== NULL) {
|
||||
err("2nd proximity_show_status NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
proximity_status = g_psensor_ATTR->ATTR_HAL->proximity_show_status();
|
||||
if(proximity_status)
|
||||
return sprintf(buf, "close\n");
|
||||
else
|
||||
return sprintf(buf, "away\n");
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Extension Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_proximity_show_allreg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_allreg== NULL) {
|
||||
err("2nd IRsensor_show_allreg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
ret=g_psensor_ATTR->ATTR_Extension->proximity_show_allreg(dev, attr, buf);
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_polling_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_polling_mode == NULL) {
|
||||
err("2nd proximity_show_polling_mode NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_psensor_ATTR->ATTR_Extension->proximity_show_polling_mode();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_polling_mode(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_polling_mode== NULL) {
|
||||
err("2nd proximity_store_polling_mode NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
/*check input character*/
|
||||
if (0 == strncmp(buf, "off", 3))
|
||||
bOn = false;
|
||||
else if (0 == strncmp(buf, "on", 2))
|
||||
bOn = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
log("2nd Proximity polling mode %s\n", bOn?"on":"off");
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_polling_mode(bOn) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* +++ For stress test debug +++ */
|
||||
static ssize_t ATT_proximity_show_int_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int p_int_counter=0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_int_count == NULL) {
|
||||
err("2nd proximity_show_int_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
p_int_counter = g_psensor_ATTR->ATTR_Extension->proximity_show_int_count();
|
||||
return sprintf(buf, "%d\n", p_int_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_event_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int p_event_counter=0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_event_count == NULL) {
|
||||
err("2nd proximity_show_event_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
p_event_counter = g_psensor_ATTR->ATTR_Extension->proximity_show_event_count();
|
||||
return sprintf(buf, "%d\n", p_event_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_error_mesg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
char* error_mesg=kzalloc(sizeof(char [ERROR_MESG_SIZE]), GFP_KERNEL);
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_error_mesg== NULL) {
|
||||
err("2nd IRsensor_show_error_mesg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
ret = g_psensor_ATTR->ATTR_Extension->proximity_show_error_mesg(error_mesg);
|
||||
|
||||
return sprintf(buf, "%s\n", error_mesg);
|
||||
}
|
||||
/* --- For stress test debug --- */
|
||||
|
||||
/*For auto calibration*/
|
||||
static ssize_t ATT_proximity_show_autok(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_autok == NULL) {
|
||||
err("2nd proximity_show_autok NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_psensor_ATTR->ATTR_Extension->proximity_show_autok();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_autok(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autok== NULL) {
|
||||
err("2nd proximity_store_autok NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
/*check input character*/
|
||||
if (0 == strncmp(buf, "off", 3))
|
||||
bOn = false;
|
||||
else if (0 == strncmp(buf, "on", 2))
|
||||
bOn = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
log("2nd Proximity autok %s\n", bOn?"on":"off");
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autok(bOn) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_autokmin(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int autokmin = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_autokmin== NULL) {
|
||||
err("2nd proximity_show_autokmin NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
autokmin = g_psensor_ATTR->ATTR_Extension->proximity_show_autokmin();
|
||||
return sprintf(buf, "%d\n", autokmin);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_autokmin(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long autokmin;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmin== NULL) {
|
||||
err("2nd proximity_store_autokmin NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &autokmin) < 0))
|
||||
return -EINVAL;
|
||||
if(autokmin < 0) {
|
||||
err("2nd Proximity store autokmin with NEGATIVE value. (%lu) \n", autokmin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Proximity store autokmin: %lu\n", autokmin);
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmin(autokmin) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_autokmax(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int autokmax = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_autokmax== NULL) {
|
||||
err("2nd proximity_show_autokmax NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
autokmax = g_psensor_ATTR->ATTR_Extension->proximity_show_autokmax();
|
||||
return sprintf(buf, "%d\n", autokmax);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_autokmax(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long autokmax;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmax== NULL) {
|
||||
err("2nd proximity_store_autokmax NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &autokmax) < 0))
|
||||
return -EINVAL;
|
||||
if(autokmax < 0) {
|
||||
err("2nd Proximity store autokmax with NEGATIVE value. (%lu) \n", autokmax);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Proximity store autokmax: %lu\n", autokmax);
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmax(autokmax) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
static ssize_t ATT_proximity_show_selection(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int selection = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_selection== NULL) {
|
||||
err("2nd proximity_show_selection NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
selection = g_psensor_ATTR->ATTR_Extension->proximity_show_selection();
|
||||
return sprintf(buf, "%d\n", selection);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_selection(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long selection;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_selection== NULL) {
|
||||
err("2nd proximity_store_selection NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &selection) < 0))
|
||||
return -EINVAL;
|
||||
if(selection < 0) {
|
||||
err("2nd Proximity store selection with NEGATIVE value. (%lu) \n", selection);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("2nd Proximity store selection: %lu\n", selection);
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_selection(selection) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For power key turn on screen and enable touch*/
|
||||
static ssize_t ATT_proximity_show_enable_touch(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int touch_enable = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_touch_enable== NULL) {
|
||||
err("2nd proximity_show_touch_enable NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
touch_enable = g_psensor_ATTR->ATTR_Extension->proximity_show_touch_enable();
|
||||
return sprintf(buf, "%d\n", touch_enable);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_enable_touch(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long touch_enable;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_touch_enable== NULL) {
|
||||
err("2nd proximity_store_touch_enable NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &touch_enable) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
if(touch_enable == 1){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_touch_enable(true) < 0)
|
||||
return -EINVAL;
|
||||
}else if(touch_enable == 0){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_touch_enable(false) < 0)
|
||||
return -EINVAL;
|
||||
}else {
|
||||
err("2nd Proximity store touch enable with NEGATIVE value. (%lu) \n", touch_enable);
|
||||
return -EINVAL;
|
||||
}
|
||||
log("2nd Proximity store touch_enable: %lu\n", touch_enable);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For load calibration data*/
|
||||
static ssize_t ATT_proximity_store_load_calibration_data(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long load_calibration_data;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_load_calibration_data== NULL) {
|
||||
err("2nd proximity_store_load_calibration_data NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &load_calibration_data) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
g_Psensor2_load_cal_status = (bool)load_calibration_data;
|
||||
|
||||
log("2nd Proximity store load_calibration_data: %lu\n", load_calibration_data);
|
||||
|
||||
if(load_calibration_data == 1){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_load_calibration_data() < 0)
|
||||
return -EINVAL;
|
||||
}else {
|
||||
err("2nd Proximity store load calibration data is not 1. (%lu) \n", load_calibration_data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For enable anti-oil workaround*/
|
||||
static ssize_t ATT_proximity_show_anti_oil_enable(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int anti_oil_enable = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_anti_oil_enable== NULL) {
|
||||
err("2nd proximity_show_anti_oil_enable NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
anti_oil_enable = g_psensor_ATTR->ATTR_Extension->proximity_show_anti_oil_enable();
|
||||
return sprintf(buf, "%d\n", anti_oil_enable);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_anti_oil_enable(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long anti_oil_enable;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_anti_oil_enable== NULL) {
|
||||
err("2nd proximity_store_anti_oil_enable NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &anti_oil_enable) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
if(anti_oil_enable == 1){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_anti_oil_enable(true) < 0)
|
||||
return -EINVAL;
|
||||
}else if(anti_oil_enable == 0){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_anti_oil_enable(false) < 0)
|
||||
return -EINVAL;
|
||||
}else {
|
||||
err("2nd Proximity store anti-oil enable with NEGATIVE value. (%lu) \n", anti_oil_enable);
|
||||
return -EINVAL;
|
||||
}
|
||||
log("2nd Proximity store anti_oil_enable: %lu\n", anti_oil_enable);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute proximity_property_attrs[] = {
|
||||
/*read only*/
|
||||
__ATTR(vendor, 0444, ATT_proximity_show_vendor, NULL),
|
||||
__ATTR(module_number, 0444, ATT_proximity_show_module_number, NULL),
|
||||
__ATTR(proxm, 0444, ATT_proximity_show_adc, NULL),
|
||||
__ATTR(atd_status, 0444, ATT_proximity_show_atd_test, NULL),
|
||||
__ATTR(proxm_status, 0444, ATT_proximity_show_status, NULL),
|
||||
__ATTR(dump_reg, 0444, ATT_proximity_show_allreg, NULL),
|
||||
/* +++ For stress test debug +++ */
|
||||
__ATTR(int_counter, 0444, ATT_proximity_show_int_count, NULL),
|
||||
__ATTR(event_counter, 0444, ATT_proximity_show_event_count, NULL),
|
||||
__ATTR(error_mesg, 0444, ATT_proximity_show_error_mesg, NULL),
|
||||
/* --- For stress test debug --- */
|
||||
/*read/write*/
|
||||
__ATTR(switch, 0664, ATT_proximity_show_switch_onoff, ATT_proximity_store_switch_onoff),
|
||||
__ATTR(hi_cal, 0664, ATT_proximity_show_calibration_hi, ATT_proximity_store_calibration_hi),
|
||||
__ATTR(low_cal, 0664, ATT_proximity_show_calibration_lo, ATT_proximity_store_calibration_lo),
|
||||
__ATTR(inf_cal, 0664, ATT_proximity_show_calibration_inf, ATT_proximity_store_calibration_inf),
|
||||
__ATTR(poll_mode, 0664, ATT_proximity_show_polling_mode, ATT_proximity_store_polling_mode),
|
||||
__ATTR(read_reg, 0664, ATT_proximity_show_read_reg, ATT_proximity_store_read_reg),
|
||||
__ATTR(write_reg, 0220, NULL, ATT_proximity_store_write_reg),
|
||||
__ATTR(autok, 0664, ATT_proximity_show_autok, ATT_proximity_store_autok),
|
||||
__ATTR(autokmin, 0664, ATT_proximity_show_autokmin, ATT_proximity_store_autokmin),
|
||||
__ATTR(autokmax, 0664, ATT_proximity_show_autokmax, ATT_proximity_store_autokmax),
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
__ATTR(selection, 0664, ATT_proximity_show_selection, ATT_proximity_store_selection),
|
||||
|
||||
/*For power key turn on screen and enable touch*/
|
||||
__ATTR(enable_touch, 0664, ATT_proximity_show_enable_touch, ATT_proximity_store_enable_touch),
|
||||
|
||||
/*For load calibration data*/
|
||||
__ATTR(load_cal, 0220, NULL, ATT_proximity_store_load_calibration_data),
|
||||
|
||||
/*For power key turn on screen and enable touch*/
|
||||
__ATTR(enable_anti_oil, 0664, ATT_proximity_show_anti_oil_enable, ATT_proximity_store_anti_oil_enable),
|
||||
};
|
||||
|
||||
int psensor_ATTR_register_2nd(psensor_ATTR *mATTR)
|
||||
{
|
||||
int ret = 0;
|
||||
int ATTR_index;
|
||||
|
||||
g_psensor_ATTR=mATTR;
|
||||
|
||||
/* psensor device */
|
||||
g_psensor_dev = ASH_ATTR_device_create(psensor_2nd);
|
||||
if (IS_ERR(g_psensor_dev) || g_psensor_dev == NULL) {
|
||||
ret = PTR_ERR(g_psensor_dev);
|
||||
err("%s: 2nd psensor create ERROR.\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
for (ATTR_index=0; ATTR_index < ARRAY_SIZE(proximity_property_attrs); ATTR_index++) {
|
||||
ret = device_create_file(g_psensor_dev, &proximity_property_attrs[ATTR_index]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_ATTR_register_2nd);
|
||||
|
||||
int psensor_ATTR_unregister_2nd(void)
|
||||
{
|
||||
ASH_ATTR_device_remove(psensor_2nd);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_ATTR_unregister_2nd);
|
||||
|
||||
int psensor_ATTR_create_2nd(struct device_attribute *mpsensor_attr)
|
||||
{
|
||||
int ret = 0;
|
||||
if(mpsensor_attr == NULL) {
|
||||
err("%s: 2nd the device_attribute is NULL point. \n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = device_create_file(g_psensor_dev, mpsensor_attr);
|
||||
if (ret){
|
||||
err("%s: 2nd device_create_file ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_ATTR_create_2nd);
|
||||
|
966
drivers/sensors/ASH/ASH_ATTR/psensor_ATTR.c
Normal file
966
drivers/sensors/ASH/ASH_ATTR/psensor_ATTR.c
Normal file
@ -0,0 +1,966 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************************/
|
||||
/* Proximity Sensor Atrribute */
|
||||
/********************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
#define RGB 1
|
||||
#define BUF_SIZE (10)
|
||||
static psensor_ATTR *g_psensor_ATTR = NULL;
|
||||
static struct device *g_psensor_dev;
|
||||
|
||||
/*******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_ATTR"
|
||||
#define SENSOR_TYPE_NAME "proximity"
|
||||
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_ATTR_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
static void proximity_onoff(struct work_struct *work);
|
||||
static DECLARE_WORK(proximity_onoff_work, proximity_onoff);
|
||||
static int g_psensor_on_flag = false;
|
||||
bool g_Psensor_load_cal_status = false;
|
||||
|
||||
static ssize_t ATT_proximity_show_vendor(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_psensor_ATTR->info_type->vendor, "") == 0) {
|
||||
err("Show vendor NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_psensor_ATTR->info_type->vendor);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_module_number(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(strcmp(g_psensor_ATTR->info_type->module_number, "") == 0) {
|
||||
err("Show module number NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", g_psensor_ATTR->info_type->module_number);
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/*Calibration Function*/
|
||||
/************************/
|
||||
static ssize_t ATT_proximity_show_calibration_hi(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_hi== NULL) {
|
||||
err("proximity_show_calibration_hi NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_hi();
|
||||
dbg("Proximity show High Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_calibration_hi(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_hi == NULL) {
|
||||
err("proximity_store_calibration_hi NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("Proximity store High Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store High Calibration: %lu\n", calvalue);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_hi(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_calibration_lo(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_lo == NULL) {
|
||||
err("proximity_show_calibration_lo NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_lo();
|
||||
dbg("Proximity show Low Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_calibration_lo(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_lo == NULL) {
|
||||
err("proximity_store_calibration_lo NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("Proximity store Low Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store Low Calibration: %lu\n", calvalue);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_lo(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_calibration_inf(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_inf == NULL) {
|
||||
err("proximity_show_calibration_inf NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_inf();
|
||||
dbg("Proximity show Inf Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_calibration_inf(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_inf == NULL) {
|
||||
err("proximity_store_calibration_inf NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("Proximity store Inf Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store Inf Calibration: %lu\n", calvalue);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_inf(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_adc(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int adc = 0;
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_adc == NULL) {
|
||||
err("proximity_show_adc NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
adc = g_psensor_ATTR->ATTR_Calibration->proximity_show_adc();
|
||||
return sprintf(buf, "%d\n", adc);
|
||||
}
|
||||
|
||||
/********************/
|
||||
/*BMMI Function*/
|
||||
/*******************/
|
||||
static ssize_t ATT_proximity_show_atd_test(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool atd_test = false;
|
||||
if(g_psensor_ATTR->ATTR_BMMI->proximity_show_atd_test== NULL) {
|
||||
err("proximity_show_atd_test NOT SUPPORT. \n");
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
atd_test = g_psensor_ATTR->ATTR_BMMI->proximity_show_atd_test();
|
||||
return sprintf(buf, "%d\n", atd_test);
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Hardware Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_proximity_show_read_reg(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_show_reg== NULL) {
|
||||
err("IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
i2c_reg_addr = g_psensor_ATTR->ATTR_Hardware->show_reg_addr;
|
||||
i2c_reg_value = g_psensor_ATTR->ATTR_Hardware->proximity_show_reg(i2c_reg_addr);
|
||||
|
||||
return sprintf(buf, "0x%x\n", i2c_reg_value);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_read_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_show_reg== NULL) {
|
||||
err("IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x", &i2c_reg_addr);
|
||||
g_psensor_ATTR->ATTR_Hardware->show_reg_addr=i2c_reg_addr;
|
||||
|
||||
return count;
|
||||
}
|
||||
static ssize_t ATT_proximity_store_write_reg(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int i2c_reg_addr = 0, i2c_reg_value = 0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_store_reg== NULL) {
|
||||
err("IRsensor_store_reg NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
sscanf(buf, "%x %x", &i2c_reg_addr, &i2c_reg_value);
|
||||
|
||||
log("IRsensor_store_reg, addr=0x%02X, value=0x%02X\n", i2c_reg_addr, i2c_reg_value);
|
||||
if(g_psensor_ATTR->ATTR_Hardware->proximity_store_reg(i2c_reg_addr, (int)i2c_reg_value) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/******************/
|
||||
/*HAL Function*/
|
||||
/*****************/
|
||||
static void proximity_onoff(struct work_struct *work){
|
||||
log("Proximity switch %s\n", g_psensor_on_flag?"on":"off");
|
||||
g_psensor_ATTR->ATTR_HAL->proximity_store_switch_onoff(g_psensor_on_flag);
|
||||
}
|
||||
static ssize_t ATT_proximity_show_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_show_switch_onoff== NULL) {
|
||||
err("proximity_show_switch_onoff NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_psensor_ATTR->ATTR_HAL->proximity_show_switch_onoff();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_switch_onoff(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_store_switch_onoff == NULL) {
|
||||
err("proximity_store_switch_onoff NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if (0 == strncmp(buf, "off", 3)){
|
||||
bOn = false;
|
||||
g_psensor_on_flag = false;
|
||||
}else if (0 == strncmp(buf, "on", 2)){
|
||||
bOn = true;
|
||||
g_psensor_on_flag = true;
|
||||
}else
|
||||
return -EINVAL;
|
||||
|
||||
log("Proximity workqueue to switch %s\n", bOn?"on":"off");
|
||||
schedule_work(&proximity_onoff_work);
|
||||
|
||||
/*check input character*/
|
||||
/*
|
||||
if (0 == strncmp(buf, "off", 3))
|
||||
bOn = false;
|
||||
else if (0 == strncmp(buf, "on", 2))
|
||||
bOn = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
log("Proximity switch %s\n", bOn?"on":"off");
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_store_switch_onoff(bOn) < 0)
|
||||
return -EINVAL;
|
||||
*/
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_status(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool proximity_status;
|
||||
if(g_psensor_ATTR->ATTR_HAL->proximity_show_status== NULL) {
|
||||
err("proximity_show_status NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
proximity_status = g_psensor_ATTR->ATTR_HAL->proximity_show_status();
|
||||
if(proximity_status)
|
||||
return sprintf(buf, "close\n");
|
||||
else
|
||||
return sprintf(buf, "away\n");
|
||||
}
|
||||
|
||||
/************************/
|
||||
/*Extension Function*/
|
||||
/***********************/
|
||||
static ssize_t ATT_proximity_show_allreg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_allreg== NULL) {
|
||||
err("IRsensor_show_allreg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
log("print all reg");
|
||||
return g_psensor_ATTR->ATTR_Extension->proximity_show_allreg(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_polling_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_polling_mode == NULL) {
|
||||
err("proximity_show_polling_mode NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_psensor_ATTR->ATTR_Extension->proximity_show_polling_mode();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_polling_mode(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_polling_mode== NULL) {
|
||||
err("proximity_store_polling_mode NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
/*check input character*/
|
||||
if (0 == strncmp(buf, "off", 3))
|
||||
bOn = false;
|
||||
else if (0 == strncmp(buf, "on", 2))
|
||||
bOn = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
log("Proximity polling mode %s\n", bOn?"on":"off");
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_polling_mode(bOn) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* +++ For stress test debug +++ */
|
||||
static ssize_t ATT_proximity_show_int_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int p_int_counter=0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_int_count == NULL) {
|
||||
err("proximity_show_int_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
p_int_counter = g_psensor_ATTR->ATTR_Extension->proximity_show_int_count();
|
||||
return sprintf(buf, "%d\n", p_int_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_event_count(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int p_event_counter=0;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_event_count == NULL) {
|
||||
err("proximity_show_event_count NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
p_event_counter = g_psensor_ATTR->ATTR_Extension->proximity_show_event_count();
|
||||
return sprintf(buf, "%d\n", p_event_counter);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_error_mesg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
char* error_mesg=kzalloc(sizeof(char [ERROR_MESG_SIZE]), GFP_KERNEL);
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_error_mesg== NULL) {
|
||||
err("IRsensor_show_error_mesg NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
ret = g_psensor_ATTR->ATTR_Extension->proximity_show_error_mesg(error_mesg);
|
||||
|
||||
return sprintf(buf, "%s\n", error_mesg);
|
||||
}
|
||||
/* --- For stress test debug --- */
|
||||
|
||||
/*For auto calibration*/
|
||||
static ssize_t ATT_proximity_show_autok(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
bool bOn;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_autok == NULL) {
|
||||
err("proximity_show_autok NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
bOn = g_psensor_ATTR->ATTR_Extension->proximity_show_autok();
|
||||
if(bOn)
|
||||
return sprintf(buf, "on\n");
|
||||
else
|
||||
return sprintf(buf, "off\n");
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_autok(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
bool bOn;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autok== NULL) {
|
||||
err("proximity_store_autok NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
/*check input character*/
|
||||
if (0 == strncmp(buf, "off", 3))
|
||||
bOn = false;
|
||||
else if (0 == strncmp(buf, "on", 2))
|
||||
bOn = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
log("Proximity autok %s\n", bOn?"on":"off");
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autok(bOn) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_autokmin(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int autokmin = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_autokmin== NULL) {
|
||||
err("proximity_show_autokmin NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
autokmin = g_psensor_ATTR->ATTR_Extension->proximity_show_autokmin();
|
||||
return sprintf(buf, "%d\n", autokmin);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_autokmin(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long autokmin;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmin== NULL) {
|
||||
err("proximity_store_autokmin NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &autokmin) < 0))
|
||||
return -EINVAL;
|
||||
if(autokmin < 0) {
|
||||
err("Proximity store autokmin with NEGATIVE value. (%lu) \n", autokmin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store autokmin: %lu\n", autokmin);
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmin(autokmin) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_autokmax(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int autokmax = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_autokmax== NULL) {
|
||||
err("proximity_show_autokmax NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
autokmax = g_psensor_ATTR->ATTR_Extension->proximity_show_autokmax();
|
||||
return sprintf(buf, "%d\n", autokmax);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_autokmax(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long autokmax;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmax== NULL) {
|
||||
err("proximity_store_autokmax NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &autokmax) < 0))
|
||||
return -EINVAL;
|
||||
if(autokmax < 0) {
|
||||
err("Proximity store autokmax with NEGATIVE value. (%lu) \n", autokmax);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store autokmax: %lu\n", autokmax);
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_autokmax(autokmax) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
static ssize_t ATT_proximity_show_selection(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int selection = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_selection== NULL) {
|
||||
err("proximity_show_selection NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
selection = g_psensor_ATTR->ATTR_Extension->proximity_show_selection();
|
||||
return sprintf(buf, "%d\n", selection);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_selection(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long selection;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_selection== NULL) {
|
||||
err("proximity_store_selection NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &selection) < 0))
|
||||
return -EINVAL;
|
||||
if(selection < 0) {
|
||||
err("Proximity store selection with NEGATIVE value. (%lu) \n", selection);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store selection: %lu\n", selection);
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_selection(selection) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For power key turn on screen and enable touch*/
|
||||
static ssize_t ATT_proximity_show_enable_touch(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int touch_enable = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_touch_enable== NULL) {
|
||||
err("proximity_show_touch_enable NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
touch_enable = g_psensor_ATTR->ATTR_Extension->proximity_show_touch_enable();
|
||||
return sprintf(buf, "%d\n", touch_enable);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_enable_touch(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long touch_enable;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_touch_enable== NULL) {
|
||||
err("proximity_store_touch_enable NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &touch_enable) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
if(touch_enable == 1){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_touch_enable(true) < 0)
|
||||
return -EINVAL;
|
||||
}else if(touch_enable == 0){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_touch_enable(false) < 0)
|
||||
return -EINVAL;
|
||||
}else {
|
||||
err("Proximity store touch enable with NEGATIVE value. (%lu) \n", touch_enable);
|
||||
return -EINVAL;
|
||||
}
|
||||
log("Proximity store touch_enable: %lu\n", touch_enable);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For load calibration data*/
|
||||
static ssize_t ATT_proximity_store_load_calibration_data(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long load_calibration_data;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_load_calibration_data== NULL) {
|
||||
err("proximity_store_load_calibration_data NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &load_calibration_data) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
g_Psensor_load_cal_status = (bool)load_calibration_data;
|
||||
|
||||
log("Proximity store load_calibration_data: %lu\n", load_calibration_data);
|
||||
|
||||
if(load_calibration_data == 1){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_load_calibration_data() < 0)
|
||||
return -EINVAL;
|
||||
}else {
|
||||
err("Proximity store load calibration data is not 1. (%lu) \n", load_calibration_data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*For enable anti-oil workaround*/
|
||||
static ssize_t ATT_proximity_show_anti_oil_enable(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int anti_oil_enable = 0;
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_show_anti_oil_enable== NULL) {
|
||||
err("proximity_show_anti_oil_enable NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
anti_oil_enable = g_psensor_ATTR->ATTR_Extension->proximity_show_anti_oil_enable();
|
||||
return sprintf(buf, "%d\n", anti_oil_enable);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_anti_oil_enable(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long anti_oil_enable;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_anti_oil_enable== NULL) {
|
||||
err("proximity_store_anti_oil_enable NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &anti_oil_enable) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
if(anti_oil_enable == 1){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_anti_oil_enable(true) < 0)
|
||||
return -EINVAL;
|
||||
}else if(anti_oil_enable == 0){
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_anti_oil_enable(false) < 0)
|
||||
return -EINVAL;
|
||||
}else {
|
||||
err("Proximity store anti-oil enable with NEGATIVE value. (%lu) \n", anti_oil_enable);
|
||||
return -EINVAL;
|
||||
}
|
||||
log("Proximity store anti_oil_enable: %lu\n", anti_oil_enable);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_calibration_offset(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_offset == NULL) {
|
||||
err("proximity_show_calibration_offset NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
calvalue = g_psensor_ATTR->ATTR_Calibration->proximity_show_calibration_offset();
|
||||
dbg("Proximity show Inf Calibration: %d\n", calvalue);
|
||||
return sprintf(buf, "%d\n", calvalue);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_calibration_offset(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long calvalue;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_offset == NULL) {
|
||||
err("proximity_store_calibration_offset NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &calvalue) < 0))
|
||||
return -EINVAL;
|
||||
if(calvalue < 0) {
|
||||
err("Proximity store Inf Calibration with NEGATIVE value. (%lu) \n", calvalue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store Inf Calibration: %lu\n", calvalue);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_calibration_offset(calvalue) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_oil_flag(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long flag;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_oil_flag == NULL) {
|
||||
err("proximity_show oil_flag NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
flag = g_psensor_ATTR->ATTR_Calibration->proximity_show_oil_flag();
|
||||
dbg("Proximity show oil_flag: %d\n", flag);
|
||||
return sprintf(buf, "%d\n", flag);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_oil_flag(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long flag;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_oil_flag == NULL) {
|
||||
err("proximity_store_oil_flag NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &flag) < 0))
|
||||
return -EINVAL;
|
||||
if(flag < 0) {
|
||||
err("Proximity store oil_flag with NEGATIVE value. (%d) \n", flag);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store oil_flag: %d\n", flag);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_oil_flag(flag) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_show_oil_timer(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long time;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_show_oil_timer == NULL) {
|
||||
err("proximity_show oil_timer NOT SUPPORT. \n");
|
||||
return sprintf(buf, "NOT SUPPORT\n");
|
||||
}
|
||||
|
||||
time = g_psensor_ATTR->ATTR_Calibration->proximity_show_oil_timer();
|
||||
dbg("Proximity show oil_timer: %d\n", time);
|
||||
return sprintf(buf, "%d\n", time);
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_oil_timer(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long time;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_oil_timer == NULL) {
|
||||
err("proximity_store_oil_timer NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &time) < 0))
|
||||
return -EINVAL;
|
||||
if(time < 0) {
|
||||
err("Proximity store oil_timer with NEGATIVE value. (%d) \n", time);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log("Proximity store oil_timer: %d\n", time);
|
||||
if(g_psensor_ATTR->ATTR_Calibration->proximity_store_oil_timer(time) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_chip_cal_en(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long enable;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_chip_cal_en== NULL) {
|
||||
err("proximity_store_anti_oil_enable NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &enable) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
g_psensor_ATTR->ATTR_Extension->proximity_chip_cal_en(enable);
|
||||
log("Proximity store chip cal flag: %lu\n", enable);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ATT_proximity_store_pocket_en(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long enable;
|
||||
|
||||
if(g_psensor_ATTR->ATTR_Extension->proximity_store_pocket_en== NULL) {
|
||||
err("proximity_store_pocket_en NOT SUPPORT. \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
if ((kstrtoul(buf, 10, &enable) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
g_psensor_ATTR->ATTR_Extension->proximity_store_pocket_en(enable);
|
||||
log("Proximity store pocket flag: %lu\n", enable);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute proximity_property_attrs[] = {
|
||||
/*read only*/
|
||||
__ATTR(vendor, 0444, ATT_proximity_show_vendor, NULL),
|
||||
__ATTR(module_number, 0444, ATT_proximity_show_module_number, NULL),
|
||||
__ATTR(proxm, 0444, ATT_proximity_show_adc, NULL),
|
||||
__ATTR(atd_status, 0444, ATT_proximity_show_atd_test, NULL),
|
||||
__ATTR(proxm_status, 0444, ATT_proximity_show_status, NULL),
|
||||
__ATTR(dump_reg, 0444, ATT_proximity_show_allreg, NULL),
|
||||
/* +++ For stress test debug +++ */
|
||||
__ATTR(int_counter, 0444, ATT_proximity_show_int_count, NULL),
|
||||
__ATTR(event_counter, 0444, ATT_proximity_show_event_count, NULL),
|
||||
__ATTR(error_mesg, 0444, ATT_proximity_show_error_mesg, NULL),
|
||||
/* --- For stress test debug --- */
|
||||
/*read/write*/
|
||||
__ATTR(switch, 0664, ATT_proximity_show_switch_onoff, ATT_proximity_store_switch_onoff),
|
||||
__ATTR(hi_cal, 0664, ATT_proximity_show_calibration_hi, ATT_proximity_store_calibration_hi),
|
||||
__ATTR(low_cal, 0664, ATT_proximity_show_calibration_lo, ATT_proximity_store_calibration_lo),
|
||||
__ATTR(inf_cal, 0664, ATT_proximity_show_calibration_inf, ATT_proximity_store_calibration_inf),
|
||||
__ATTR(poll_mode, 0664, ATT_proximity_show_polling_mode, ATT_proximity_store_polling_mode),
|
||||
__ATTR(read_reg, 0664, ATT_proximity_show_read_reg, ATT_proximity_store_read_reg),
|
||||
__ATTR(write_reg, 0220, NULL, ATT_proximity_store_write_reg),
|
||||
__ATTR(autok, 0664, ATT_proximity_show_autok, ATT_proximity_store_autok),
|
||||
__ATTR(autokmin, 0664, ATT_proximity_show_autokmin, ATT_proximity_store_autokmin),
|
||||
__ATTR(autokmax, 0664, ATT_proximity_show_autokmax, ATT_proximity_store_autokmax),
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
__ATTR(selection, 0664, ATT_proximity_show_selection, ATT_proximity_store_selection),
|
||||
|
||||
/*For power key turn on screen and enable touch*/
|
||||
__ATTR(enable_touch, 0664, ATT_proximity_show_enable_touch, ATT_proximity_store_enable_touch),
|
||||
|
||||
/*For load calibration data*/
|
||||
__ATTR(load_cal, 0220, NULL, ATT_proximity_store_load_calibration_data),
|
||||
|
||||
/*For power key turn on screen and enable touch*/
|
||||
__ATTR(enable_anti_oil, 0664, ATT_proximity_show_anti_oil_enable, ATT_proximity_store_anti_oil_enable),
|
||||
|
||||
/* tmd2755 autok results */
|
||||
__ATTR(offset_cal, 0664, ATT_proximity_show_calibration_offset, ATT_proximity_store_calibration_offset),
|
||||
|
||||
/* For oil issue during phone call */
|
||||
__ATTR(oil_flag, 0664, ATT_proximity_show_oil_flag, ATT_proximity_store_oil_flag),
|
||||
|
||||
/* set oil timer to do oil check during phone call */
|
||||
__ATTR(oil_timer, 0664, ATT_proximity_show_oil_timer, ATT_proximity_store_oil_timer),
|
||||
|
||||
/* tmd2755 autok behavior on/off */
|
||||
__ATTR(chip_cal_en, 0220, NULL, ATT_proximity_store_chip_cal_en),
|
||||
__ATTR(pocket_en, 0664, NULL, ATT_proximity_store_pocket_en),
|
||||
};
|
||||
|
||||
int psensor_ATTR_register(psensor_ATTR *mATTR)
|
||||
{
|
||||
int ret = 0;
|
||||
int ATTR_index;
|
||||
|
||||
g_psensor_ATTR=mATTR;
|
||||
|
||||
/* psensor device */
|
||||
g_psensor_dev = ASH_ATTR_device_create(psensor);
|
||||
if (IS_ERR(g_psensor_dev) || g_psensor_dev == NULL) {
|
||||
ret = PTR_ERR(g_psensor_dev);
|
||||
err("%s: psensor create ERROR.\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
for (ATTR_index=0; ATTR_index < ARRAY_SIZE(proximity_property_attrs); ATTR_index++) {
|
||||
ret = device_create_file(g_psensor_dev, &proximity_property_attrs[ATTR_index]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_ATTR_register);
|
||||
|
||||
int psensor_ATTR_unregister(void)
|
||||
{
|
||||
ASH_ATTR_device_remove(psensor);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_ATTR_unregister);
|
||||
|
||||
int psensor_ATTR_create(struct device_attribute *mpsensor_attr)
|
||||
{
|
||||
int ret = 0;
|
||||
if(mpsensor_attr == NULL) {
|
||||
err("%s: the device_attribute is NULL point. \n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = device_create_file(g_psensor_dev, mpsensor_attr);
|
||||
if (ret){
|
||||
err("%s: device_create_file ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_ATTR_create);
|
||||
|
3431
drivers/sensors/ASH/ASH_Algo/ALSPSsensor.c
Normal file
3431
drivers/sensors/ASH/ASH_Algo/ALSPSsensor.c
Normal file
File diff suppressed because it is too large
Load Diff
129
drivers/sensors/ASH/ASH_Algo/ALSPSsensor.h
Normal file
129
drivers/sensors/ASH/ASH_Algo/ALSPSsensor.h
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_IRSENSOR_H
|
||||
#define __LINUX_IRSENSOR_H
|
||||
|
||||
/**
|
||||
* @LIGHT_CALVALUE_200LUX_DEFAULT :
|
||||
* @LIGHT_CALVALUE_1000LUX_DEFAULT : The default value of 200/1000 lux calibration,
|
||||
* which are independent of platforms and hardware.
|
||||
*/
|
||||
#define LIGHT_CALVALUE_200LUX_DEFAULT (200)
|
||||
#define LIGHT_CALVALUE_1000LUX_DEFAULT (1000)
|
||||
|
||||
/**
|
||||
* LIGHT_CHANGE_SENSITIVITY - These define the sensitivity of light sensor.
|
||||
* @LIGHT_CHANGE_LOW_SENSITIVITY : >= 1000 lux.
|
||||
* @LIGHT_CHANGE_MID_SENSITIVITY : < 1000 lux, > 200 lux.
|
||||
* @LIGHT_CHANGE_HI_SENSITIVITY : <= 200 lux.
|
||||
* @LIGHT_CHANGE_FACTORY_SENSITIVITY : for factory build.
|
||||
* @LIGHT_CHANGE_MIN_SENSITIVITY : for dynamic change sensitivity.
|
||||
*/
|
||||
#define LIGHT_CHANGE_LOW_SENSITIVITY (10)
|
||||
#define LIGHT_CHANGE_MID_SENSITIVITY (5)
|
||||
#define LIGHT_CHANGE_HI_SENSITIVITY (2)
|
||||
#define LIGHT_CHANGE_FACTORY_SENSITIVITY (0)
|
||||
|
||||
/**
|
||||
* @LIGHT_MAX_LUX : Report 0~20000 Lux.
|
||||
*/
|
||||
#define LIGHT_MAX_LUX (20000)
|
||||
|
||||
/**
|
||||
* @LIGHT_TURNON_DELAY_TIME : After light sensor turn on 250ms,
|
||||
* driver will cat first correct adc/lux value.
|
||||
*/
|
||||
#if defined ASUS_SAKE_PROJECT
|
||||
#define LIGHT_CALDATA_TRANSFER_RATIO1 (17)
|
||||
#define LIGHT_CALDATA_TRANSFER_RATIO2 (10)
|
||||
#define PROXIMITY_POCKET_MODE_RATIO (30)
|
||||
#define PROXIMITY_POCKET_MODE_OFFSET_RATIO (25)
|
||||
#define PROXIMITY_ADC_PER_OFFSET (11)
|
||||
#else
|
||||
#define PROXIMITY_POCKET_MODE_RATIO (100)
|
||||
#endif
|
||||
#ifdef CONFIG_TMD2755_FLAG
|
||||
/* AMS proximity autok will change adc value, since autok need time, wait for ams chip */
|
||||
#define PROXIMITY_CALIBRATION_DELAY (150)
|
||||
#define LIGHT_TURNON_DELAY_TIME (10)
|
||||
#else
|
||||
#define PROXIMITY_CALIBRATION_DELAY (0)
|
||||
#define LIGHT_TURNON_DELAY_TIME (10)
|
||||
#endif
|
||||
|
||||
#define PROXIMITY_OIL_ALGO_DEFAULT_FLAG (false)
|
||||
|
||||
#define PROXIMITY_TURNON_DELAY_TIME (11)
|
||||
|
||||
#define PROXIMITY_POLLING_TIME (1000)
|
||||
#define LIGHT_POLLING_TIME (500)
|
||||
|
||||
/**
|
||||
* LIGHT_LOG_THRESHOLD : We print light sensor log
|
||||
* when the current lux value change over 100 lux from the last lux.
|
||||
*/
|
||||
#define LIGHT_LOG_THRESHOLD (100)
|
||||
#define LIGHT_LOG_LOW_LUX_THRESHOLD (20)
|
||||
|
||||
/**
|
||||
* @ALSPS_DEFAULT_VALUE : Define the default value for driver data.
|
||||
*/
|
||||
#define ALSPS_DEFAULT_VALUE (-1)
|
||||
|
||||
|
||||
#ifdef ONE_PL_CHIP
|
||||
#define PROXIMITY_INF_ER_DEFAULT (85)
|
||||
#define PROXIMITY_THDL_ER_DEFAULT (134)
|
||||
#define PROXIMITY_THDH_ER_DEFAULT (249)
|
||||
#define PROXIMITY_POCKET_ER_DEFAULT (4073)
|
||||
#ifdef CONFIG_TMD2755_FLAG
|
||||
#define PROXIMITY_POCKET_DEFAULT (3800)
|
||||
#else
|
||||
#define PROXIMITY_POCKET_DEFAULT (4073)
|
||||
#endif //CONFIG_TMD2755_FLAG
|
||||
#define PROXIMITY_NOISE_PERIOD (11)
|
||||
#define LIGHT_ER_CALIBRATION_DEFAULT (1526)
|
||||
/* ASUS BSP +++ Clay: shift lux to mitigate psensor noise when psensor on and lux < offset */
|
||||
#define LIGHT_LOW_LUX_NOISE_OFFSET (0)
|
||||
/* ASUS BSP--- */
|
||||
/* ASUS BSP+++ Clay: average 5 lux for offset behavior to mitigate the low lux gap */
|
||||
#define LIGHT_LOW_LUX_AVG_COUNT (5)
|
||||
/* ASUS BSP--- */
|
||||
#else
|
||||
#define PROXIMITY_INF_ER_DEFAULT (513)
|
||||
#define PROXIMITY_THDL_ER_DEFAULT (607)
|
||||
#define PROXIMITY_THDH_ER_DEFAULT (879)
|
||||
#define PROXIMITY_POCKET_ER_DEFAULT (4094)
|
||||
#define PROXIMITY_INF_ER2_DEFAULT (466)
|
||||
#define PROXIMITY_THDL_ER2_DEFAULT (547)
|
||||
#define PROXIMITY_THDH_ER2_DEFAULT (788)
|
||||
#define PROXIMITY_POCKET_ER2_DEFAULT (4093)
|
||||
#define PROXIMITY_POCKET_DEFAULT (4091)
|
||||
#define PROXIMITY_NOISE_PERIOD (20)
|
||||
#define LIGHT_ER_CALIBRATION_DEFAULT (4563)
|
||||
#define LIGHT_ER2_CALIBRATION_DEFAULT (3372)
|
||||
/* ASUS BSP Clay: shift lux to mitigate psensor noise when psensor on and lux < offset +++ */
|
||||
#define LIGHT_LOW_LUX_NOISE_OFFSET (30)
|
||||
/* ASUS BSP Clay: shift lux to mitigate psensor noise when psensor on and lux < offset --- */
|
||||
/* ASUS BSP Clay: average 5 lux for offset behavior to mitigate the low lux gap +++ */
|
||||
#define LIGHT_LOW_LUX_AVG_COUNT (5)
|
||||
/* ASUS BSP Clay: average 5 lux for offset behavior to mitigate the low lux gap --- */
|
||||
#endif
|
||||
#define PROXIMITY_BASIC_PERIOD (11)
|
||||
#define CS_IT_400MS (3)
|
||||
#define CS_IT_100MS (1)
|
||||
#define CS_IT_50MS (0)
|
||||
#endif
|
||||
|
2535
drivers/sensors/ASH/ASH_Algo/ALSPSsensor_2nd.c
Normal file
2535
drivers/sensors/ASH/ASH_Algo/ALSPSsensor_2nd.c
Normal file
File diff suppressed because it is too large
Load Diff
76
drivers/sensors/ASH/ASH_Algo/ALSPSsensor_2nd.h
Normal file
76
drivers/sensors/ASH/ASH_Algo/ALSPSsensor_2nd.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_IRSENSOR_H
|
||||
#define __LINUX_IRSENSOR_H
|
||||
|
||||
/**
|
||||
* @LIGHT_CALVALUE_200LUX_DEFAULT :
|
||||
* @LIGHT_CALVALUE_1000LUX_DEFAULT : The default value of 200/1000 lux calibration,
|
||||
* which are independent of platforms and hardware.
|
||||
*/
|
||||
#define LIGHT_CALVALUE_200LUX_DEFAULT (200)
|
||||
#define LIGHT_CALVALUE_1000LUX_DEFAULT (1000)
|
||||
|
||||
/**
|
||||
* LIGHT_CHANGE_SENSITIVITY - These define the sensitivity of light sensor.
|
||||
* @LIGHT_CHANGE_LOW_SENSITIVITY : >= 1000 lux.
|
||||
* @LIGHT_CHANGE_MID_SENSITIVITY : < 1000 lux, > 200 lux.
|
||||
* @LIGHT_CHANGE_HI_SENSITIVITY : <= 200 lux.
|
||||
* @LIGHT_CHANGE_FACTORY_SENSITIVITY : for factory build.
|
||||
* @LIGHT_CHANGE_MIN_SENSITIVITY : for dynamic change sensitivity.
|
||||
*/
|
||||
#define LIGHT_CHANGE_LOW_SENSITIVITY (10)
|
||||
#define LIGHT_CHANGE_MID_SENSITIVITY (5)
|
||||
#define LIGHT_CHANGE_HI_SENSITIVITY (2)
|
||||
#define LIGHT_CHANGE_FACTORY_SENSITIVITY (0)
|
||||
|
||||
/**
|
||||
* @LIGHT_MAX_LUX : Report 0~20000 Lux.
|
||||
*/
|
||||
#define LIGHT_MAX_LUX (20000)
|
||||
|
||||
/**
|
||||
* @LIGHT_TURNON_DELAY_TIME : After light sensor turn on 250ms,
|
||||
* driver will cat first correct adc/lux value.
|
||||
*/
|
||||
#define LIGHT_TURNON_DELAY_TIME (10)
|
||||
#define PROXIMITY_TURNON_DELAY_TIME (50)
|
||||
|
||||
#define PROXIMITY_POLLING_TIME (1000)
|
||||
#define LIGHT_POLLING_TIME (500)
|
||||
|
||||
/**
|
||||
* LIGHT_LOG_THRESHOLD : We print light sensor log
|
||||
* when the current lux value change over 100 lux from the last lux.
|
||||
*/
|
||||
#define LIGHT_LOG_THRESHOLD (100)
|
||||
|
||||
/**
|
||||
* @ALSPS_DEFAULT_VALUE : Define the default value for driver data.
|
||||
*/
|
||||
#define ALSPS_DEFAULT_VALUE (-1)
|
||||
|
||||
#define PROXIMITY_INF_ER_DEFAULT (283)
|
||||
#define PROXIMITY_THDL_ER_DEFAULT (534)
|
||||
#define PROXIMITY_THDH_ER_DEFAULT (1237)
|
||||
#define PROXIMITY_POCKET_ER_DEFAULT (4095)
|
||||
#define PROXIMITY_INF_ER2_DEFAULT (358)
|
||||
#define PROXIMITY_THDL_ER2_DEFAULT (582)
|
||||
#define PROXIMITY_THDH_ER2_DEFAULT (1289)
|
||||
#define PROXIMITY_POCKET_ER2_DEFAULT (4095)
|
||||
#define PROXIMITY_POCKET_DEFAULT (4095)
|
||||
|
||||
#endif
|
||||
|
67
drivers/sensors/ASH/ASH_Algo/ASH_Wakelock.h
Normal file
67
drivers/sensors/ASH/ASH_Algo/ASH_Wakelock.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* include/linux/wakelock.h
|
||||
*
|
||||
* Copyright (C) 2007-2012 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_WAKELOCK_H
|
||||
#define _LINUX_WAKELOCK_H
|
||||
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
/* A wake_lock prevents the system from entering suspend or other low power
|
||||
* states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock
|
||||
* prevents a full system suspend.
|
||||
*/
|
||||
|
||||
enum {
|
||||
WAKE_LOCK_SUSPEND, /* Prevent suspend */
|
||||
WAKE_LOCK_TYPE_COUNT
|
||||
};
|
||||
|
||||
struct wake_lock {
|
||||
struct wakeup_source *ws;
|
||||
};
|
||||
|
||||
static inline void wake_lock_init(struct wake_lock *lock, struct device *dev,
|
||||
const char *name)
|
||||
{
|
||||
lock->ws = wakeup_source_register(dev, name);
|
||||
}
|
||||
|
||||
static inline void wake_lock_destroy(struct wake_lock *lock)
|
||||
{
|
||||
wakeup_source_unregister(lock->ws);
|
||||
}
|
||||
|
||||
static inline void wake_lock(struct wake_lock *lock)
|
||||
{
|
||||
__pm_stay_awake(lock->ws);
|
||||
}
|
||||
|
||||
static inline void wake_lock_timeout(struct wake_lock *lock, long timeout)
|
||||
{
|
||||
__pm_wakeup_event(lock->ws, jiffies_to_msecs(timeout));
|
||||
}
|
||||
|
||||
static inline void wake_unlock(struct wake_lock *lock)
|
||||
{
|
||||
__pm_relax(lock->ws);
|
||||
}
|
||||
|
||||
static inline int wake_lock_active(struct wake_lock *lock)
|
||||
{
|
||||
return lock->ws->active;
|
||||
}
|
||||
|
||||
#endif
|
767
drivers/sensors/ASH/ASH_Algo/SARsensor.c
Normal file
767
drivers/sensors/ASH/ASH_Algo/SARsensor.c
Normal file
@ -0,0 +1,767 @@
|
||||
/*
|
||||
* Copyright (C) 2019 ASUSTek Inc.
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
//#include <linux/wakelock.h>
|
||||
#include "ASH_Wakelock.h"
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_ALGO"
|
||||
#define SENSOR_TYPE_NAME "SAR"
|
||||
#undef dbg
|
||||
#ifdef ASH_ALGO_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#define err(fmt, args...) do{ \
|
||||
printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args); \
|
||||
sprintf(g_error_mesg, "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args); \
|
||||
}while(0)
|
||||
|
||||
/******************************/
|
||||
/* SAR Sensor Global Variables */
|
||||
/*****************************/
|
||||
static int ASUS_SAR_SENSOR_IRQ;
|
||||
//static int ASUS_SAR_SENSOR_INT_STATUS;
|
||||
static struct ASUS_sar_sensor_data *g_sar_sensor_data;
|
||||
static struct SAR_sensor_hw *sar_sensor_hw_client;
|
||||
static struct workqueue_struct *SAR_sensor_workqueue;
|
||||
static struct mutex g_sar_sensor_lock;
|
||||
static struct wake_lock g_sar_sensor_wake_lock;
|
||||
static struct i2c_client *g_i2c_client;
|
||||
static char *g_error_mesg;
|
||||
|
||||
/***********************/
|
||||
/* SAR Sensor Functions*/
|
||||
/**********************/
|
||||
/*Device Layer Part*/
|
||||
static int SAR_sensor_turn_onoff(bool bOn);
|
||||
|
||||
/*Interrupt Service Routine Part*/
|
||||
static void SAR_sensor_ist(struct work_struct *work);
|
||||
|
||||
/*Initialization Part*/
|
||||
static int init_data(void);
|
||||
|
||||
/*Work Queue*/
|
||||
static DECLARE_WORK(SAR_sensor_ist_work, SAR_sensor_ist);
|
||||
|
||||
/********************/
|
||||
/* SAR sensor data structure */
|
||||
/********************/
|
||||
|
||||
struct ASUS_sar_sensor_data
|
||||
{
|
||||
bool Device_switch_on; /* this var. means is turning on sensor or not */
|
||||
int Device_Interrupt_detect_status; /* this var. means is for member detect status */
|
||||
bool Device_detected_status[4]; /* this var. means is for which channels have detected near */
|
||||
|
||||
bool HAL_switch_on; /* this var. means if HAL is turning on sar or not */
|
||||
};
|
||||
|
||||
/**********************************/
|
||||
/* SAR sensor Info Type*/
|
||||
/*********************************/
|
||||
static SAR_sensor_info_type mSAR_sensor_info_type = {{0}};
|
||||
|
||||
/*=======================
|
||||
*|| I2c Stress Test Part ||
|
||||
*=======================
|
||||
*/
|
||||
|
||||
/*====================
|
||||
*|| Device Layer Part ||
|
||||
*====================
|
||||
*/
|
||||
static int SAR_sensor_turn_onoff(bool bOn)
|
||||
{
|
||||
int ret=0;
|
||||
|
||||
/* Check Hardware Support First */
|
||||
if(sar_sensor_hw_client->SAR_sensor_hw_turn_onoff == NULL) {
|
||||
err("SAR_sensor_hw_turn_onoff NOT SUPPORT.\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (bOn == 1) { /* power on */
|
||||
if(g_sar_sensor_data->Device_switch_on == false){
|
||||
/* Power On */
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw_turn_onoff(true);
|
||||
if (ret < 0) {
|
||||
err("SAR sensor turn on ERROR\n");
|
||||
} else {
|
||||
g_sar_sensor_data->Device_switch_on = bOn;
|
||||
/* Enable IRQ */
|
||||
log("[IRQ] Enable irq !!\n");
|
||||
enable_irq(ASUS_SAR_SENSOR_IRQ);
|
||||
/*change the Device Status*/
|
||||
g_sar_sensor_data->Device_switch_on = true;
|
||||
}
|
||||
}
|
||||
} else { /* power off */
|
||||
if(g_sar_sensor_data->Device_switch_on == true){
|
||||
/*disable IRQ before switch off*/
|
||||
log("[IRQ] Disable irq !!\n");
|
||||
disable_irq_nosync(ASUS_SAR_SENSOR_IRQ);
|
||||
|
||||
/*Power OFF*/
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw_turn_onoff(false);
|
||||
if (ret < 0) {
|
||||
err("SAR sensor turn off ERROR\n");
|
||||
}
|
||||
g_sar_sensor_data->Device_switch_on = false;
|
||||
|
||||
/* reset global variable */
|
||||
g_sar_sensor_data->Device_Interrupt_detect_status = -EBUSY;
|
||||
g_sar_sensor_data->Device_detected_status[0] = false;
|
||||
g_sar_sensor_data->Device_detected_status[1] = false;
|
||||
g_sar_sensor_data->Device_detected_status[2] = false;
|
||||
g_sar_sensor_data->Device_detected_status[3] = false;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/*BMMI Function*/
|
||||
/*******************/
|
||||
bool mSAR_sensor_show_atd_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int round = 0;
|
||||
|
||||
mutex_lock(&g_sar_sensor_lock);
|
||||
|
||||
/* Check SAR sensor HW ID */
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw_check_ID();
|
||||
if (ret < 0) {
|
||||
err("SAR sensor ATD test check ID ERROR\n");
|
||||
goto SAR_sensor_atd_test_fail;
|
||||
}
|
||||
|
||||
if(g_sar_sensor_data->Device_switch_on == false) {
|
||||
/* Trun on SAR sensor */
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw_turn_onoff(true);
|
||||
if (ret < 0) {
|
||||
err("SAR sensor ATD test turn on ERROR\n");
|
||||
goto SAR_sensor_atd_test_fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read SAR sensor raw data 4 time */
|
||||
for(round = 0; round < 4; round++) {
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw__get_proxuserful(round);
|
||||
if (ret < 0) {
|
||||
err("SAR sensor ATD test get raw data ERROR\n");
|
||||
goto SAR_sensor_atd_test_fail;
|
||||
}
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if(g_sar_sensor_data->HAL_switch_on == false) {
|
||||
/* Trun off SAR sensor */
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw_turn_onoff(false);
|
||||
if(ret < 0) {
|
||||
err("SAR sensor ATD test turn off ERROR\n");
|
||||
goto SAR_sensor_atd_test_fail;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&g_sar_sensor_lock);
|
||||
|
||||
return true;
|
||||
SAR_sensor_atd_test_fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
int mSAR_sensor_show_raw_data(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(sar_sensor_hw_client->SAR_sensor_hw_read_rawData == NULL) {
|
||||
err("SAR_sensor_hw_read_rawData NOT SUPPORT.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&g_sar_sensor_lock);
|
||||
|
||||
if(g_sar_sensor_data->Device_switch_on == false) {
|
||||
SAR_sensor_turn_onoff(true);
|
||||
}
|
||||
|
||||
/* Read SAR sensor raw data */
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw_read_rawData();
|
||||
if (ret < 0)
|
||||
err("SAR sensor get raw data ERROR\n");
|
||||
|
||||
if(g_sar_sensor_data->HAL_switch_on == false) {
|
||||
SAR_sensor_turn_onoff(false);
|
||||
}
|
||||
|
||||
mutex_unlock(&g_sar_sensor_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* AP Interface Function*/
|
||||
/*****************************/
|
||||
bool mSAR_sensor_show_switch_onoff(void)
|
||||
{
|
||||
return g_sar_sensor_data->Device_switch_on;
|
||||
}
|
||||
|
||||
int mSAR_sensor_store_switch_onoff(bool bOn)
|
||||
{
|
||||
mutex_lock(&g_sar_sensor_lock);
|
||||
|
||||
log("SAR switch = %d.\n", bOn);
|
||||
if((g_sar_sensor_data->Device_switch_on != bOn)) {
|
||||
if (bOn) {
|
||||
/* Turn on SAR */
|
||||
g_sar_sensor_data->HAL_switch_on = true;
|
||||
SAR_sensor_turn_onoff(true);
|
||||
} else {
|
||||
/* Turn off SAR */
|
||||
g_sar_sensor_data->HAL_switch_on = false;
|
||||
SAR_sensor_turn_onoff(false);
|
||||
}
|
||||
} else {
|
||||
log("SAR Sensor is already %s\n", bOn?"ON":"OFF");
|
||||
}
|
||||
|
||||
mutex_unlock(&g_sar_sensor_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mSAR_sensor_show_Interrupt_detect_status(void)
|
||||
{
|
||||
return g_sar_sensor_data->Device_Interrupt_detect_status;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/*Hardware Function*/
|
||||
/*************************/
|
||||
int mSAR_sensor_show_reg(uint8_t addr)
|
||||
{
|
||||
int value;
|
||||
if (sar_sensor_hw_client->SAR_sensor_hw_get_register == NULL) {
|
||||
err("SAR_sensor_hw_get_register NOT SUPPORT.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value = sar_sensor_hw_client->SAR_sensor_hw_get_register(addr);
|
||||
log("mSAR_sensor_show_reg, addr=0X%02x, value=0x%x.\n", addr, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
int mSAR_sensor_store_reg(uint8_t addr, int value)
|
||||
{
|
||||
if (sar_sensor_hw_client->SAR_sensor_hw_set_register == NULL) {
|
||||
err("SAR_sensor_hw_set_register NOT SUPPORT.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sar_sensor_hw_client->SAR_sensor_hw_set_register(addr, value);
|
||||
log("mSAR_sensor_store_reg, addr=0x%02x, value=0x%x.\n", addr, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mSAR_sensor_show_manual_offset_calibration(void)
|
||||
{
|
||||
int value;
|
||||
if (sar_sensor_hw_client->SAR_sensor_hw_get_manual_offset_cal == NULL) {
|
||||
err("SAR_sensor_hw_get_manual_offset_calibration NOT SUPPORT. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value = sar_sensor_hw_client->SAR_sensor_hw_get_manual_offset_cal();
|
||||
log("SAR_sensor_hw_get_manual_offset_cal, value=0x%x.\n", value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int mSAR_sensor_store_manual_offset_calibration(int value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (sar_sensor_hw_client->SAR_sensor_hw_manual_offset_cal == NULL) {
|
||||
err("SAR_sensor_hw_manual_offset_calibration NOT SUPPORT. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = sar_sensor_hw_client->SAR_sensor_hw_manual_offset_cal(value);
|
||||
log("SAR_sensor_hw_manual_offset_cal, value=%d.(ret=%d)\n", value, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*=======================
|
||||
*|| For Sar check status ||
|
||||
*========================
|
||||
*/
|
||||
bool mSAR_sensor_show_sar_status(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
bool status = false;
|
||||
|
||||
mutex_unlock(&g_sar_sensor_lock);
|
||||
|
||||
if(g_sar_sensor_data->Device_switch_on == false) {
|
||||
/* Trun on SAR sensor */
|
||||
ret = SAR_sensor_turn_onoff(true);
|
||||
if (ret < 0) {
|
||||
err("SAR sensor status turn on ERROR\n");
|
||||
goto SAR_sensor_status_fail;
|
||||
}
|
||||
} else {
|
||||
log("Sar has been opened, Sar_check_status : %s",
|
||||
g_sar_sensor_data->Device_Interrupt_detect_status?"Close":"Away");
|
||||
status = (g_sar_sensor_data->Device_Interrupt_detect_status?true:false);
|
||||
goto SAR_sensor_status_fail;
|
||||
}
|
||||
|
||||
/* Check SAR sensor status */
|
||||
for(i = 0; i < 5; i++){
|
||||
if(g_sar_sensor_data->Device_Interrupt_detect_status == OBJECT_NEAR ||
|
||||
g_sar_sensor_data->Device_Interrupt_detect_status == OBJECT_FAR){
|
||||
log("Sar_check_status : %s",
|
||||
g_sar_sensor_data->Device_Interrupt_detect_status?"Close":"Away");
|
||||
status = g_sar_sensor_data->Device_Interrupt_detect_status;
|
||||
break;
|
||||
}
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if(g_sar_sensor_data->HAL_switch_on == false) {
|
||||
/* Trun off SAR sensor */
|
||||
ret = SAR_sensor_turn_onoff(false);
|
||||
if(ret < 0) {
|
||||
err("SAR sensor status turn off ERROR\n");
|
||||
goto SAR_sensor_status_fail;
|
||||
}
|
||||
}
|
||||
|
||||
SAR_sensor_status_fail:
|
||||
mutex_unlock(&g_sar_sensor_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Extension Function */
|
||||
/**************************/
|
||||
bool mSAR_sensor_show_allreg(void)
|
||||
{
|
||||
if(sar_sensor_hw_client->SAR_sensor_hw_show_allreg == NULL) {
|
||||
err("SAR_sensor_hw_show_allreg NOT SUPPORT.\n");
|
||||
return false;
|
||||
}
|
||||
sar_sensor_hw_client->SAR_sensor_hw_show_allreg();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************** ATTR Structure ****************/
|
||||
static SAR_sensor_ATTR_BMMI mSAR_sensor_ATTR_BMMI = {
|
||||
.SAR_sensor_show_atd_test = mSAR_sensor_show_atd_test,
|
||||
.SAR_sensor_show_raw_data = mSAR_sensor_show_raw_data,
|
||||
};
|
||||
|
||||
static SAR_sensor_ATTR_HAL mSAR_sensor_ATTR_HAL = {
|
||||
.SAR_sensor_show_switch_onoff = mSAR_sensor_show_switch_onoff,
|
||||
.SAR_sensor_store_switch_onoff = mSAR_sensor_store_switch_onoff,
|
||||
.SAR_sensor_show_Interrupt_detect_status = mSAR_sensor_show_Interrupt_detect_status,
|
||||
.SAR_sensor_show_sar_status = mSAR_sensor_show_sar_status,
|
||||
};
|
||||
|
||||
static SAR_sensor_ATTR_Hardware mSAR_sensor_ATTR_Hardware = {
|
||||
.SAR_show_reg = mSAR_sensor_show_reg,
|
||||
.SAR_store_reg = mSAR_sensor_store_reg,
|
||||
.SAR_sensor_show_manual_offset_cal = mSAR_sensor_show_manual_offset_calibration,
|
||||
.SAR_sensor_store_manual_offset_cal = mSAR_sensor_store_manual_offset_calibration,
|
||||
};
|
||||
|
||||
static SAR_sensor_ATTR_Extension mSAR_sensor_ATTR_Extension = {
|
||||
.SAR_sensor_show_allreg = mSAR_sensor_show_allreg,
|
||||
};
|
||||
|
||||
static SAR_sensor_ATTR mSAR_sensor_ATTR = {
|
||||
.info_type = &mSAR_sensor_info_type,
|
||||
.ATTR_BMMI = &mSAR_sensor_ATTR_BMMI,
|
||||
.ATTR_HAL = &mSAR_sensor_ATTR_HAL,
|
||||
.ATTR_Hardware = &mSAR_sensor_ATTR_Hardware,
|
||||
.ATTR_Extension = &mSAR_sensor_ATTR_Extension,
|
||||
};
|
||||
|
||||
/*==========================
|
||||
*|| Interrupt Service Routine Part ||
|
||||
*===========================
|
||||
*/
|
||||
static void SAR_get_detected_cs(int irq_status, int sensor_status)
|
||||
{
|
||||
if(irq_status == OBJECT_NEAR){
|
||||
if((sensor_status & PROXSTAT0) == PROXSTAT0 &&
|
||||
g_sar_sensor_data->Device_detected_status[0] == false) {
|
||||
log("SAR sensor CS0 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[0] = true;
|
||||
}
|
||||
if((sensor_status & PROXSTAT1) == PROXSTAT1 &&
|
||||
g_sar_sensor_data->Device_detected_status[1] == false) {
|
||||
log("SAR sensor CS1 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[1] = true;
|
||||
}
|
||||
if((sensor_status & PROXSTAT2) == PROXSTAT2 &&
|
||||
g_sar_sensor_data->Device_detected_status[2] == false) {
|
||||
log("SAR sensor CS2 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[2] = true;
|
||||
}
|
||||
if((sensor_status & PROXSTAT3) == PROXSTAT3 &&
|
||||
g_sar_sensor_data->Device_detected_status[3] == false) {
|
||||
log("SAR sensor CS3 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[3] = true;
|
||||
}
|
||||
} else if(irq_status == OBJECT_FAR){
|
||||
if((sensor_status & PROXSTAT0) == 0x00 &&
|
||||
g_sar_sensor_data->Device_detected_status[0] == true) {
|
||||
log("SAR sensor CS0 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[0] = false;
|
||||
}
|
||||
if((sensor_status & PROXSTAT1) == 0x00 &&
|
||||
g_sar_sensor_data->Device_detected_status[1] == true) {
|
||||
log("SAR sensor CS1 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[1] = false;
|
||||
}
|
||||
if((sensor_status & PROXSTAT2) == 0x00 &&
|
||||
g_sar_sensor_data->Device_detected_status[2] == true) {
|
||||
log("SAR sensor CS2 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[2] = false;
|
||||
}
|
||||
if((sensor_status & PROXSTAT3) == 0x00 &&
|
||||
g_sar_sensor_data->Device_detected_status[3] == true) {
|
||||
log("SAR sensor CS3 is detected.\n");
|
||||
g_sar_sensor_data->Device_detected_status[3] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int SAR_sensor_work(void)
|
||||
{
|
||||
int sensor_status = 0, irq_status = 0;
|
||||
|
||||
sensor_status = sar_sensor_hw_client->SAR_sensor_hw_get_interrupt();
|
||||
if (sensor_status < 0) {
|
||||
err("sensor_status ERROR(err:%d)\n", sensor_status);
|
||||
return sensor_status;
|
||||
}
|
||||
|
||||
/* Clean interrupt */
|
||||
irq_status = sar_sensor_hw_client->SAR_sensor_hw_read_regStat();
|
||||
if (irq_status < 0) {
|
||||
err("irq_status ERROR(err:%d)\n", irq_status);
|
||||
return irq_status;
|
||||
}
|
||||
|
||||
dbg("sensor status:0x%x, irq status:0x%x\n", sensor_status, irq_status);
|
||||
|
||||
if(irq_status == OBJECT_NEAR) {
|
||||
if(g_sar_sensor_data->Device_Interrupt_detect_status != OBJECT_NEAR){
|
||||
SAR_sensor_report_abs(SAR_SENSOR_REPORT_CLOSE);
|
||||
log("SAR sensor Detect object Near.\n");
|
||||
g_sar_sensor_data->Device_Interrupt_detect_status = OBJECT_NEAR;
|
||||
}
|
||||
} else if(irq_status == OBJECT_FAR) {
|
||||
if(g_sar_sensor_data->Device_Interrupt_detect_status != OBJECT_FAR) {
|
||||
SAR_sensor_report_abs(SAR_SENSOR_REPORT_AWAY);
|
||||
log("SAR sensor Detect object Far.\n");
|
||||
g_sar_sensor_data->Device_Interrupt_detect_status = OBJECT_FAR;
|
||||
}
|
||||
} else {
|
||||
err("Unknown irq status(0x%02x)\n", irq_status);
|
||||
}
|
||||
|
||||
SAR_get_detected_cs(irq_status, sensor_status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SAR_sensor_ist(struct work_struct *work)
|
||||
{
|
||||
mutex_lock(&g_sar_sensor_lock);
|
||||
if (g_sar_sensor_data->Device_switch_on == false) {
|
||||
err("SAR sensor are disabled and ignore IST.\n");
|
||||
goto ist_err;
|
||||
}
|
||||
dbg("SAR sensor ist +++\n");
|
||||
if (sar_sensor_hw_client == NULL) {
|
||||
dbg("sar_sensor_hw_client is NULL\n");
|
||||
goto ist_err;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Check IRQ Status and refresh status */
|
||||
/* Read INT_FLAG will clean the interrupt */
|
||||
/**************************************************/
|
||||
SAR_sensor_work();
|
||||
dbg("SAR sensor ist ---\n");
|
||||
ist_err:
|
||||
wake_unlock(&g_sar_sensor_wake_lock);
|
||||
if (g_sar_sensor_data->Device_switch_on == true ) {
|
||||
dbg("[IRQ] Enable irq !!\n");
|
||||
enable_irq(ASUS_SAR_SENSOR_IRQ);
|
||||
}
|
||||
mutex_unlock(&g_sar_sensor_lock);
|
||||
}
|
||||
|
||||
void SAR_sensor_irq_handler(void)
|
||||
{
|
||||
dbg("[IRQ] Disable irq !!\n");
|
||||
disable_irq_nosync(ASUS_SAR_SENSOR_IRQ);
|
||||
|
||||
if(sar_sensor_hw_client->SAR_sensor_hw_get_interrupt == NULL) {
|
||||
err("SAR_sensor_hw_get_interrupt NOT SUPPORT.\n");
|
||||
goto irq_err;
|
||||
}
|
||||
|
||||
/*Queue work will enbale IRQ and unlock wake_lock*/
|
||||
queue_work(SAR_sensor_workqueue, &SAR_sensor_ist_work);
|
||||
wake_lock(&g_sar_sensor_wake_lock);
|
||||
|
||||
return;
|
||||
irq_err:
|
||||
dbg("[IRQ] Enable irq !!\n");
|
||||
enable_irq(ASUS_SAR_SENSOR_IRQ);
|
||||
}
|
||||
|
||||
static SAR_sensor_GPIO mSAR_sensor_GPIO = {
|
||||
.SAR_sensor_isr = SAR_sensor_irq_handler,
|
||||
};
|
||||
|
||||
/*====================
|
||||
*|| Initialization Part ||
|
||||
*====================
|
||||
*/
|
||||
static int init_data(void)
|
||||
{
|
||||
int ret = 0;
|
||||
log("sar sensor init_data");
|
||||
/* Reset ASUS_SAR_sensor_data */
|
||||
g_sar_sensor_data = kmalloc(sizeof(struct ASUS_sar_sensor_data), GFP_KERNEL);
|
||||
if (!g_sar_sensor_data) {
|
||||
err("g_sar_sensor_data kmalloc ERROR\n");
|
||||
ret = -ENOMEM;
|
||||
goto init_data_err;
|
||||
}
|
||||
memset(g_sar_sensor_data, 0, sizeof(struct ASUS_sar_sensor_data));
|
||||
g_sar_sensor_data->Device_switch_on = false;
|
||||
g_sar_sensor_data->HAL_switch_on = false;
|
||||
g_sar_sensor_data->Device_Interrupt_detect_status = -EBUSY;
|
||||
g_sar_sensor_data->Device_detected_status[0] = false;
|
||||
g_sar_sensor_data->Device_detected_status[1] = false;
|
||||
g_sar_sensor_data->Device_detected_status[2] = false;
|
||||
g_sar_sensor_data->Device_detected_status[3] = false;
|
||||
return 0;
|
||||
init_data_err:
|
||||
err("Init Data ERROR\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mSAR_sensor_algo_probe(struct i2c_client *client)
|
||||
{
|
||||
log("Driver PROBE +++\n");
|
||||
|
||||
/*check i2c client*/
|
||||
if (client == NULL) {
|
||||
err("i2c Client is NUll\n");
|
||||
goto probe_err;
|
||||
}
|
||||
|
||||
/*link driver data to i2c client*/
|
||||
strlcpy(client->name, SENSOR_TYPE_NAME, I2C_NAME_SIZE);
|
||||
i2c_set_clientdata(client, g_sar_sensor_data);
|
||||
|
||||
/* i2c client */
|
||||
g_i2c_client = client;
|
||||
if (ASUS_SAR_SENSOR_IRQ < 0)
|
||||
goto probe_err;
|
||||
|
||||
log("Driver PROBE ---\n");
|
||||
return ;
|
||||
probe_err:
|
||||
err("Driver PROBE ERROR ---\n");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void SAR_sensor_algo_remove(void)
|
||||
{
|
||||
log("Driver REMOVE +++\n");
|
||||
|
||||
SAR_sensor_gpio_unregister(ASUS_SAR_SENSOR_IRQ);
|
||||
|
||||
log("Driver REMOVE ---\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mSAR_sensor_algo_shutdown(void)
|
||||
{
|
||||
log("Driver SHUTDOWN +++\n");
|
||||
|
||||
/* Disable sensor */
|
||||
if (g_sar_sensor_data->Device_switch_on == true) {
|
||||
log("turn off sar sensor");
|
||||
SAR_sensor_turn_onoff(false);
|
||||
|
||||
}
|
||||
|
||||
log("Driver SHUTDOWN ---\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mSAR_sensor_algo_suspend(void)
|
||||
{
|
||||
log("Driver SUSPEND +++\n");
|
||||
|
||||
/* Disable SAR sensor IRQ */
|
||||
log("[IRQ] Disable irq !!\n");
|
||||
disable_irq_nosync(ASUS_SAR_SENSOR_IRQ);
|
||||
|
||||
log("Driver SUSPEND ---\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mSAR_sensor_algo_resume(void)
|
||||
{
|
||||
log("Driver RESUME +++\n");
|
||||
|
||||
/* Enable SAR sensor IRQ */
|
||||
log("[IRQ] Enable irq !!\n");
|
||||
enable_irq(ASUS_SAR_SENSOR_IRQ);
|
||||
|
||||
log("Driver RESUME ---\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static SAR_sensor_I2C mSAR_sensor_I2C = {
|
||||
.SAR_sensor_probe = mSAR_sensor_algo_probe,
|
||||
.SAR_sensor_remove = SAR_sensor_algo_remove,
|
||||
.SAR_sensor_shutdown = mSAR_sensor_algo_shutdown,
|
||||
.SAR_sensor_suspend = mSAR_sensor_algo_suspend,
|
||||
.SAR_sensor_resume = mSAR_sensor_algo_resume,
|
||||
};
|
||||
|
||||
static int __init SAR_sensor_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
log("Driver INIT +++\n");
|
||||
|
||||
/*Record the error message*/
|
||||
g_error_mesg = kzalloc(sizeof(char [ERROR_MESG_SIZE]), GFP_KERNEL);
|
||||
|
||||
/* Work Queue */
|
||||
SAR_sensor_workqueue = create_singlethread_workqueue(SENSOR_TYPE_NAME"_wq");
|
||||
|
||||
/* Initialize the Mutex */
|
||||
mutex_init(&g_sar_sensor_lock);
|
||||
|
||||
/* Initialize the wake lock */
|
||||
wake_lock_init(&g_sar_sensor_wake_lock, WAKE_LOCK_SUSPEND, "SAR_sensor_wake_lock");
|
||||
|
||||
/* i2c Registration for probe/suspend/resume */
|
||||
ret = SAR_sensor_i2c_register(&mSAR_sensor_I2C);
|
||||
if (ret < 0)
|
||||
goto init_err;
|
||||
|
||||
/* Hardware Register Initialization */
|
||||
sar_sensor_hw_client = SAR_sensor_hw_getHardware();
|
||||
if(sar_sensor_hw_client == NULL)
|
||||
goto init_err;
|
||||
|
||||
/* driver data structure initialize */
|
||||
ret = init_data();
|
||||
if (ret < 0)
|
||||
goto init_err;
|
||||
|
||||
/* string copy the character of vendor and module number */
|
||||
strcpy(mSAR_sensor_ATTR.info_type->vendor, sar_sensor_hw_client->vendor);
|
||||
strcpy(mSAR_sensor_ATTR.info_type->module_number, sar_sensor_hw_client->module_number);
|
||||
|
||||
/* Attribute */
|
||||
ret = SAR_sensor_ATTR_register(&mSAR_sensor_ATTR);
|
||||
if (ret < 0)
|
||||
goto init_err;
|
||||
|
||||
/* Input Device */
|
||||
ret = SAR_sensor_report_register();
|
||||
if (ret < 0)
|
||||
goto init_err;
|
||||
|
||||
ASUS_SAR_SENSOR_IRQ = SAR_sensor_gpio_register(g_i2c_client, &mSAR_sensor_GPIO);
|
||||
if (ASUS_SAR_SENSOR_IRQ < 0)
|
||||
goto init_err;
|
||||
|
||||
log("Driver INIT ---\n");
|
||||
return 0;
|
||||
|
||||
init_err:
|
||||
err("Driver INIT ERROR ---\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit SAR_sensor_exit(void)
|
||||
{
|
||||
log("Driver EXIT +++\n");
|
||||
|
||||
/* i2c Unregistration */
|
||||
SAR_sensor_i2c_unregister();
|
||||
|
||||
/*Report Unregistration*/
|
||||
SAR_sensor_report_unregister();
|
||||
|
||||
/*ATTR Unregistration*/
|
||||
SAR_sensor_ATTR_unregister();
|
||||
|
||||
wake_lock_destroy(&g_sar_sensor_wake_lock);
|
||||
mutex_destroy(&g_sar_sensor_lock);
|
||||
kfree(g_sar_sensor_data);
|
||||
|
||||
destroy_workqueue(SAR_sensor_workqueue);
|
||||
|
||||
log("Driver EXIT ---\n");
|
||||
}
|
||||
|
||||
module_init(SAR_sensor_init);
|
||||
module_exit(SAR_sensor_exit);
|
||||
|
||||
MODULE_AUTHOR("Show_Cai <show_cai@asus.com>");
|
||||
MODULE_DESCRIPTION("SAR sensor");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
484
drivers/sensors/ASH/ASH_Factory/lsensor_Factory.c
Normal file
484
drivers/sensors/ASH/ASH_Factory/lsensor_Factory.c
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/************************************/
|
||||
/* Light Sensor Factory Module */
|
||||
/***********************************/
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_Factory"
|
||||
#define SENSOR_TYPE_NAME "light"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_FACTORY_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
/*******************************************/
|
||||
/* Light Sensor read/write Calibration*/
|
||||
/******************************************/
|
||||
int lsensor_factory_read_200lux(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[16];
|
||||
int cal_val = 0, readlen = 0;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor read 200lux Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 16, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Light Sensor read 200lux Calibration f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Light Sensor read 200lux Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Light Sensor read 200lux Calibration: Cal: %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_read_200lux);
|
||||
|
||||
bool lsensor_factory_write_200lux(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor write 200lux Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Light Sensor write 200lux Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Light Sensor write 200lux Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_write_200lux);
|
||||
|
||||
int lsensor_factory_read_1000lux(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[16];
|
||||
int cal_val = 0, readlen = 0;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor read 1000lux Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 16, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Light Sensor read 1000lux Calibration f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Light Sensor read 1000lux Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Light Sensor read 1000lux Calibration: Cal: %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_read_1000lux);
|
||||
|
||||
bool lsensor_factory_write_1000lux(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor write 1000lux Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Light Sensor write 1000lux Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Light Sensor write 1000lux Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_write_1000lux);
|
||||
|
||||
int lsensor_factory_read(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[16];
|
||||
int cal_val = 0, readlen = 0;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor read Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 16, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Light Sensor read Calibration f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Light Sensor read Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Light Sensor read Calibration: Cal: %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_read);
|
||||
|
||||
bool lsensor_factory_write(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor write Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Light Sensor write Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Light Sensor write Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_write);
|
||||
|
||||
/*For transition period from 100ms to 50ms +++*/
|
||||
int lsensor_factory_read_50ms(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[16];
|
||||
int cal_val = 0, readlen = 0;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor read 50MS Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 16, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Light Sensor read 50MS Calibration f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Light Sensor read 50MS Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Light Sensor read 50MS Calibration: Cal: %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_read_50ms);
|
||||
|
||||
bool lsensor_factory_write_50ms(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor write 50MS Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Light Sensor write 50MS Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Light Sensor write 50MS Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_write_50ms);
|
||||
|
||||
int lsensor_factory_read_100ms(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[16];
|
||||
int cal_val = 0, readlen = 0;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor read 100MS Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 16, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Light Sensor read 100MS Calibration f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Light Sensor read 100MS Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Light Sensor read 100MS Calibration: Cal: %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_read_100ms);
|
||||
|
||||
bool lsensor_factory_write_100ms(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Light Sensor write 100MS Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Light Sensor write 100MS Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Light Sensor write 100MS Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_factory_write_100ms);
|
||||
|
||||
/*For transition period from 100ms to 50ms ---*/
|
759
drivers/sensors/ASH/ASH_Factory/psensor_Factory.c
Normal file
759
drivers/sensors/ASH/ASH_Factory/psensor_Factory.c
Normal file
@ -0,0 +1,759 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************/
|
||||
/* Proximity Sensor Factory Module */
|
||||
/****************************************/
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_Factory"
|
||||
#define SENSOR_TYPE_NAME "proximity"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_FACTORY_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
/***************************************/
|
||||
/* Proximity read/write Calibration File*/
|
||||
/**************************************/
|
||||
int psensor_factory_read_high(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read High Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read High Calibration strlen: f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read High Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read High Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_high);
|
||||
|
||||
bool psensor_factory_write_high(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write High Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity Hi-Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write High Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_high);
|
||||
|
||||
int psensor_factory_read_low(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read Low Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read Low Calibration strlen f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read Low Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read Low Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_low);
|
||||
|
||||
bool psensor_factory_write_low(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write Low Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity Lo-Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write Low Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_low);
|
||||
|
||||
|
||||
/********************************/
|
||||
/* Proximity Inf calibration*/
|
||||
/*******************************/
|
||||
int psensor_factory_read_inf(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read INF Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read INF Calibration strlen: f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read INF Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read INF Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_inf);
|
||||
|
||||
bool psensor_factory_write_inf(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write INF Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity INF-Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write INF Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_inf);
|
||||
|
||||
/*For transition period from 3/5 to 2/4*/
|
||||
int psensor_factory_read_2cm(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read 2CM Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read 2CM Calibration strlen: f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read 2CM Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read 2CM Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_2cm);
|
||||
|
||||
bool psensor_factory_write_2cm(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write 2CM Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity 2CM Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write 2CM Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_2cm);
|
||||
|
||||
int psensor_factory_read_4cm(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read 4CM Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read 4CM Calibration strlen: f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read 4CM Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read 4CM Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_4cm);
|
||||
|
||||
bool psensor_factory_write_4cm(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write 4CM Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity 4CM Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write 4CM Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_4cm);
|
||||
|
||||
int psensor_factory_read_3cm(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read 3CM Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read 3CM Calibration strlen: f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read 3CM Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read 3CM Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_3cm);
|
||||
|
||||
bool psensor_factory_write_3cm(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write 3CM Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity 3CM Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write 3CM Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_3cm);
|
||||
|
||||
int psensor_factory_read_5cm(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read 5CM Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read 5CM Calibration strlen: f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read 5CM Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read 5CM Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_5cm);
|
||||
|
||||
bool psensor_factory_write_5cm(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write 5CM Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity 5CM Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write 5CM Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_5cm);
|
||||
|
||||
int psensor_factory_read_1cm(const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
int cal_val = 0;
|
||||
int readlen = 0;
|
||||
|
||||
fp = filp_open(str, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity read 1CM Calibration open (%s) fail\n", str);
|
||||
return -ENOENT; /*No such file or directory*/
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
readlen = kernel_read(fp, buf, 16, &pos_lsts);
|
||||
#else
|
||||
readlen = vfs_read(fp, buf, 6, &pos_lsts);
|
||||
#endif
|
||||
buf[readlen] = '\0';
|
||||
} else {
|
||||
err("Proximity read 1CM Calibration strlen: f_op=NULL or op->read=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return -ENXIO; /*No such device or address*/
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
sscanf(buf, "%d", &cal_val);
|
||||
if(cal_val < 0) {
|
||||
err("Proximity read 1CM Calibration is FAIL. (%d)\n", cal_val);
|
||||
return -EINVAL; /*Invalid argument*/
|
||||
} else {
|
||||
dbg("Proximity read 1CM Calibration : %d\n", cal_val);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_read_1cm);
|
||||
|
||||
bool psensor_factory_write_1cm(int calvalue, const char *str)
|
||||
{
|
||||
struct file *fp = NULL;
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos_lsts = 0;
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%d", calvalue);
|
||||
|
||||
fp = filp_open(str, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (IS_ERR_OR_NULL(fp)) {
|
||||
err("Proximity write 1CM Calibration open (%s) fail\n", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*For purpose that can use read/write system call*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
if (fp->f_op != NULL) {
|
||||
pos_lsts = 0;
|
||||
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)))
|
||||
kernel_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#else
|
||||
vfs_write(fp, buf, strlen(buf), &fp->f_pos);
|
||||
#endif
|
||||
} else {
|
||||
err("Proximity 1CM Calibration strlen: f_op=NULL or op->write=NULL\n");
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
return false;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
filp_close(fp, NULL);
|
||||
|
||||
log("Proximity write 1CM Calibration : %s\n", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_factory_write_1cm);
|
||||
|
153
drivers/sensors/ASH/ASH_GPIO/ALSPSsensor_GPIO.c
Normal file
153
drivers/sensors/ASH/ASH_GPIO/ALSPSsensor_GPIO.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*************************************/
|
||||
/* ALSPS Sensor GPIO Module */
|
||||
/************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
#define ALSPS_INTEL_NAME "ALSPS_INT#"
|
||||
#define ALSPS_QCOM_NAME "qcom,alsps-gpio"
|
||||
#define ALSPS_IRQ_NAME "ALSPS_SENSOR_IRQ"
|
||||
#define ALSPS_INT_NAME "ALSPS_SENSOR_INT"
|
||||
|
||||
static int ALSPS_SENSOR_GPIO;
|
||||
static ALSPSsensor_GPIO * mALSPSsensor_GPIO;
|
||||
|
||||
/******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_GPIO"
|
||||
#define SENSOR_TYPE_NAME "ALSPS"
|
||||
static struct i2c_client * g_i2c_client = NULL;
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_GPIO_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
static irqreturn_t ALSPSsensor_irq_handler(int irq, void *dev_id);
|
||||
|
||||
#include <linux/of_gpio.h>
|
||||
#ifdef ALSP_GPIO_NO_PULL
|
||||
#define GPIO_LOOKUP_STATE "alsps_gpio_no_pull"
|
||||
#else
|
||||
#define GPIO_LOOKUP_STATE "alsps_gpio_high"
|
||||
#endif //ALSP_GPIO_NO_PULL
|
||||
|
||||
static void set_pinctrl(struct i2c_client *client)
|
||||
{
|
||||
int ret;
|
||||
struct pinctrl *key_pinctrl;
|
||||
struct pinctrl_state *set_state;
|
||||
|
||||
key_pinctrl = devm_pinctrl_get(&client->dev);
|
||||
set_state = pinctrl_lookup_state(key_pinctrl, GPIO_LOOKUP_STATE);
|
||||
ret = pinctrl_select_state(key_pinctrl, set_state);
|
||||
if(ret < 0)
|
||||
err("%s: pinctrl_select_state ERROR(%d).\n", __FUNCTION__, ret);
|
||||
}
|
||||
|
||||
static int init_irq (void)
|
||||
{
|
||||
int ret = 0;
|
||||
int irq = 0;
|
||||
|
||||
/* GPIO to IRQ */
|
||||
irq = gpio_to_irq(ALSPS_SENSOR_GPIO);
|
||||
if (irq < 0) {
|
||||
err("%s: gpio_to_irq ERROR(%d). \n", __FUNCTION__, irq);
|
||||
return irq;
|
||||
}else {
|
||||
log("gpio_to_irq IRQ %d successed on GPIO:%d\n", irq, ALSPS_SENSOR_GPIO);
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(irq, NULL, ALSPSsensor_irq_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT, ALSPS_INT_NAME, NULL);
|
||||
|
||||
if (ret < 0) {
|
||||
err("%s: request_irq/request_threaded_irq ERROR(%d).\n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}else {
|
||||
dbg("Disable irq !! \n");
|
||||
disable_irq(irq);
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
irqreturn_t ALSPSsensor_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
dbg("ALSPSensor isr");
|
||||
mALSPSsensor_GPIO->ALSPSsensor_isr();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int ALSPSsensor_gpio_register(struct i2c_client *client, ALSPSsensor_GPIO *gpio_ist)
|
||||
{
|
||||
int ret = 0;
|
||||
int irq = 0;
|
||||
g_i2c_client = client;
|
||||
|
||||
mALSPSsensor_GPIO = gpio_ist;
|
||||
|
||||
log("Qcom GPIO \n");
|
||||
|
||||
#ifdef ALSP_GPIO_NO_PULL
|
||||
log("ALSP_GPIO_NO_PULL applied");
|
||||
#else
|
||||
log("ALSP_GPIO_HIGH applied");
|
||||
#endif
|
||||
|
||||
set_pinctrl(client);
|
||||
// ALSPS_SENSOR_GPIO = of_get_named_gpio_flags(client->dev.of_node, ALSPS_QCOM_NAME, 0, NULL);
|
||||
ALSPS_SENSOR_GPIO = of_get_named_gpio(client->dev.of_node, ALSPS_QCOM_NAME, 0);
|
||||
|
||||
log("[GPIO] GPIO =%d(%d)\n", ALSPS_SENSOR_GPIO, gpio_get_value(ALSPS_SENSOR_GPIO));
|
||||
/* GPIO Request */
|
||||
ret = gpio_request(ALSPS_SENSOR_GPIO, ALSPS_IRQ_NAME);
|
||||
if (ret) {
|
||||
err("%s: gpio_request ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* GPIO Direction */
|
||||
ret = gpio_direction_input(ALSPS_SENSOR_GPIO);
|
||||
|
||||
if (ret < 0) {
|
||||
err("%s: gpio_direction_input ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
/*IRQ*/
|
||||
irq = init_irq();
|
||||
return irq;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPSsensor_gpio_register);
|
||||
|
||||
int ALSPSsensor_gpio_unregister(int irq)
|
||||
{
|
||||
free_irq(irq, NULL);
|
||||
gpio_free(ALSPS_SENSOR_GPIO);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPSsensor_gpio_unregister);
|
141
drivers/sensors/ASH/ASH_GPIO/ALSPSsensor_GPIO_2nd.c
Normal file
141
drivers/sensors/ASH/ASH_GPIO/ALSPSsensor_GPIO_2nd.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*************************************/
|
||||
/* ALSPS Sensor GPIO Module */
|
||||
/************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
#define ALSPS_INTEL_NAME "ALSPS_INT#_2nd"
|
||||
#define ALSPS_QCOM_NAME "qcom,alsps-gpio_2nd"
|
||||
#define ALSPS_IRQ_NAME "ALSPS_SENSOR_IRQ_2nd"
|
||||
#define ALSPS_INT_NAME "ALSPS_SENSOR_INT_2nd"
|
||||
|
||||
static int ALSPS_SENSOR_GPIO;
|
||||
static ALSPSsensor_GPIO * mALSPSsensor_GPIO;
|
||||
|
||||
/******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_GPIO"
|
||||
#define SENSOR_TYPE_NAME "ALSPS_2nd"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_GPIO_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
static irqreturn_t ALSPSsensor_irq_handler(int irq, void *dev_id);
|
||||
|
||||
#include <linux/of_gpio.h>
|
||||
#define GPIO_LOOKUP_STATE "alsps_gpio_high_2nd"
|
||||
|
||||
static void set_pinctrl(struct i2c_client *client)
|
||||
{
|
||||
int ret;
|
||||
struct pinctrl *key_pinctrl;
|
||||
struct pinctrl_state *set_state;
|
||||
|
||||
key_pinctrl = devm_pinctrl_get(&client->dev);
|
||||
set_state = pinctrl_lookup_state(key_pinctrl, GPIO_LOOKUP_STATE);
|
||||
ret = pinctrl_select_state(key_pinctrl, set_state);
|
||||
if(ret < 0)
|
||||
err("%s: pinctrl_select_state ERROR(%d).\n", __FUNCTION__, ret);
|
||||
}
|
||||
static int init_irq (void)
|
||||
{
|
||||
int ret = 0;
|
||||
int irq = 0;
|
||||
|
||||
/* GPIO to IRQ */
|
||||
irq = gpio_to_irq(ALSPS_SENSOR_GPIO);
|
||||
if (irq < 0) {
|
||||
err("%s: gpio_to_irq ERROR(%d). \n", __FUNCTION__, irq);
|
||||
return irq;
|
||||
}else {
|
||||
log("gpio_to_irq IRQ %d successed on GPIO:%d\n", irq, ALSPS_SENSOR_GPIO);
|
||||
}
|
||||
|
||||
/*Request IRQ*/
|
||||
ret = request_threaded_irq(irq, NULL, ALSPSsensor_irq_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT, ALSPS_INT_NAME, NULL);
|
||||
if (ret < 0) {
|
||||
err("%s: request_irq/request_threaded_irq ERROR(%d).\n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}else {
|
||||
dbg("Disable irq !! \n");
|
||||
disable_irq(irq);
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
irqreturn_t ALSPSsensor_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
mALSPSsensor_GPIO->ALSPSsensor_isr();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int ALSPSsensor_gpio_register_2nd(struct i2c_client *client, ALSPSsensor_GPIO *gpio_ist)
|
||||
{
|
||||
int ret = 0;
|
||||
int irq = 0;
|
||||
|
||||
mALSPSsensor_GPIO = gpio_ist;
|
||||
|
||||
/* GPIO */
|
||||
log("Qcom GPIO \n");
|
||||
set_pinctrl(client);
|
||||
ALSPS_SENSOR_GPIO = of_get_named_gpio(client->dev.of_node, ALSPS_QCOM_NAME, 0);
|
||||
|
||||
dbg("[GPIO] GPIO =%d(%d)\n", ALSPS_SENSOR_GPIO, gpio_get_value(ALSPS_SENSOR_GPIO));
|
||||
/* GPIO Request */
|
||||
ret = gpio_request(ALSPS_SENSOR_GPIO, ALSPS_IRQ_NAME);
|
||||
if (ret) {
|
||||
err("%s: gpio_request ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* GPIO Direction */
|
||||
ret = gpio_direction_input(ALSPS_SENSOR_GPIO);
|
||||
|
||||
if (ret < 0) {
|
||||
err("%s: gpio_direction_input ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
/*IRQ*/
|
||||
irq = init_irq();
|
||||
|
||||
return irq;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPSsensor_gpio_register_2nd);
|
||||
|
||||
|
||||
int ALSPSsensor_gpio_unregister_2nd(int irq)
|
||||
{
|
||||
free_irq(irq, NULL);
|
||||
gpio_free(ALSPS_SENSOR_GPIO);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPSsensor_gpio_unregister_2nd);
|
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/********************************/
|
||||
/* ALSPS Sensor Hardware Module */
|
||||
/******************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include "ALSPSsensor_Hardware.h"
|
||||
#include <linux/input/ASH.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_HW"
|
||||
#define SENSOR_TYPE_NAME "ALSPS"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_HW_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
/********************/
|
||||
/* Global Variables */
|
||||
/******************/
|
||||
static ALSPS_I2C* g_ALSPS_I2C;
|
||||
static struct i2c_client * g_i2c_client = NULL;
|
||||
|
||||
extern struct ALSPS_hw *g_ALSPS_hw_client;
|
||||
static int mALSPS_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_probe == NULL){
|
||||
err("ALSPS_probe NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We use Probe function to get i2c client */
|
||||
g_i2c_client = client;
|
||||
|
||||
g_ALSPS_I2C->ALSPS_probe(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mALSPS_remove(struct i2c_client *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_remove == NULL){
|
||||
err("ALSPS_remove NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_remove();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mALSPS_shutdown(struct i2c_client *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_shutdown == NULL){
|
||||
err("ALSPS_shutdown NOT implement. \n");
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_shutdown();
|
||||
}
|
||||
|
||||
static int mALSPS_suspend(struct device *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_suspend == NULL){
|
||||
err("ALSPS_suspend NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_suspend();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mALSPS_resume(struct device *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_resume == NULL){
|
||||
err("ALSPS_resume NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_resume();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops alsps_dev_pm_ops = {
|
||||
.suspend = mALSPS_suspend,
|
||||
.resume = mALSPS_resume,
|
||||
};
|
||||
|
||||
static struct i2c_driver ALSPS_i2c_driver_client = {
|
||||
.probe = mALSPS_probe,
|
||||
.remove = mALSPS_remove,
|
||||
.shutdown = mALSPS_shutdown,
|
||||
.driver.pm = &alsps_dev_pm_ops,
|
||||
};
|
||||
|
||||
int ALSPS_i2c_register(ALSPS_I2C *alsps_i2c)
|
||||
{
|
||||
if(alsps_i2c == NULL){
|
||||
err("%s : ALSPS_I2C is NULL pointer. \n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C = alsps_i2c;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_i2c_register);
|
||||
|
||||
int ALSPS_i2c_unregister(void)
|
||||
{
|
||||
i2c_del_driver(&ALSPS_i2c_driver_client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_i2c_unregister);
|
||||
|
||||
/***********************/
|
||||
/*VCNL36866 I2c Driver*/
|
||||
/**********************/
|
||||
#ifdef CONFIG_TMD2755_FLAG
|
||||
static struct i2c_device_id tmd2755_idtable[] = {
|
||||
{ "tmd2755", 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct of_device_id tmd2755_of_match[] = {
|
||||
{ .compatible = "ams,tmd2755" },
|
||||
{}
|
||||
};
|
||||
#else
|
||||
static const struct i2c_device_id vcnl36866_i2c_id[] = {
|
||||
{"vcnl36866", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct of_device_id vcnl36866_match_table[] = {
|
||||
{ .compatible = "qcom,vcnl36866",},
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
static int ALSPS_hw_setI2cDriver(struct i2c_driver* i2c_driver_client,
|
||||
int hardware_source)
|
||||
{
|
||||
switch(hardware_source) {
|
||||
#ifdef CONFIG_TMD2755_FLAG
|
||||
case ALSPS_hw_source_tmd2755:
|
||||
log("set i2c client : tmd2755\n");
|
||||
i2c_driver_client->driver.name = "tmd2755";
|
||||
i2c_driver_client->driver.owner = THIS_MODULE;
|
||||
i2c_driver_client->driver.of_match_table = tmd2755_of_match;
|
||||
i2c_driver_client->id_table = tmd2755_idtable;
|
||||
break;
|
||||
#else
|
||||
case ALSPS_hw_source_vcnl36866:
|
||||
log("set i2c client : vcnl36866 \n");
|
||||
i2c_driver_client->driver.name = "vcnl36866";
|
||||
i2c_driver_client->driver.owner = THIS_MODULE;
|
||||
i2c_driver_client->driver.of_match_table = vcnl36866_match_table;
|
||||
i2c_driver_client->id_table = vcnl36866_i2c_id;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
err("get hardware client ERROR : hardware enum=%d\n", hardware_source);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALSPS_hw* ALSPS_hw_getHardwareClient(int hardware_source)
|
||||
{
|
||||
ALSPS_hw* ALSPS_hw_client = NULL;
|
||||
|
||||
switch(hardware_source) {
|
||||
#ifdef CONFIG_TMD2755_FLAG
|
||||
case ALSPS_hw_source_tmd2755:
|
||||
log("get hardware client : tmd2755 \n");
|
||||
ALSPS_hw_client = ALSPS_hw_tmd2755_getHardware();
|
||||
break;
|
||||
#else
|
||||
case ALSPS_hw_source_vcnl36866:
|
||||
log("get hardware client : vcnl36866 \n");
|
||||
ALSPS_hw_client = ALSPS_hw_vcnl36866_getHardware();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
err("get hardware client ERROR : hardware enum=%d\n", hardware_source);
|
||||
}
|
||||
|
||||
return ALSPS_hw_client;
|
||||
}
|
||||
|
||||
int ALSPS_i2c_add_driver(void)
|
||||
{
|
||||
int ALSPS_sensor_source;
|
||||
int ret = 0;
|
||||
|
||||
/*check i2c function pointer*/
|
||||
if(g_ALSPS_I2C == NULL) {
|
||||
err("g_ALSPS_I2C is NULL. Please use 'ALSPS_i2c_register' first. \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* i2c Registration */
|
||||
for (ALSPS_sensor_source = 0; ALSPS_sensor_source < ALSPS_hw_source_max;
|
||||
ALSPS_sensor_source++) {
|
||||
|
||||
/* i2c Registration and g_client will get i2c client */
|
||||
ALSPS_hw_setI2cDriver(&ALSPS_i2c_driver_client, ALSPS_sensor_source);
|
||||
ret = i2c_add_driver(&ALSPS_i2c_driver_client);
|
||||
if ( ret != 0 ) {
|
||||
err("%s: i2c_add_driver ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return -1;
|
||||
}else{
|
||||
log("%s %s add_driver Success. \n", __FUNCTION__, ALSPS_i2c_driver_client.driver.name);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
if(g_i2c_client == NULL){
|
||||
err("%s: g_i2c_client is NULL pointer. \n", __FUNCTION__);
|
||||
msleep(10000);
|
||||
log("wait i2c client");
|
||||
if(g_i2c_client == NULL){
|
||||
err("%s: g_i2c_client is NULL pointer....... \n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// get hardware client and check the i2c status
|
||||
ALSPS_hw_client = ALSPS_hw_getHardwareClient(ALSPS_sensor_source);
|
||||
if(ALSPS_hw_client == NULL){
|
||||
err("ALSPS_hw_client is NULL pointer. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ALSPS_hw_client->ALSPS_hw_init == NULL){
|
||||
err("ALSPS_hw_init is NULL pointer. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ALSPS_hw_client->ALSPS_hw_init(g_i2c_client);
|
||||
if (ret < 0) {
|
||||
i2c_del_driver(&ALSPS_i2c_driver_client);
|
||||
log("%s %s Probe Fail. \n", __FUNCTION__, ALSPS_i2c_driver_client.driver.name);
|
||||
continue;
|
||||
}else{
|
||||
log("%s %s Probe Success. \n", __FUNCTION__, ALSPS_i2c_driver_client.driver.name);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_i2c_add_driver);
|
||||
|
||||
|
||||
ALSPS_hw* ALSPS_hw_getHardware(void)
|
||||
{
|
||||
int ALSPS_sensor_source;
|
||||
int ret = 0;
|
||||
ALSPS_hw* ALSPS_hw_client = NULL;
|
||||
|
||||
/*check i2c function pointer*/
|
||||
if(g_ALSPS_I2C == NULL) {
|
||||
err("g_ALSPS_I2C is NULL. Please use 'ALSPS_i2c_register' first. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* i2c Registration */
|
||||
for (ALSPS_sensor_source = 0; ALSPS_sensor_source < ALSPS_hw_source_max;
|
||||
ALSPS_sensor_source++) {
|
||||
|
||||
if(g_i2c_client == NULL){
|
||||
err("%s: g_i2c_client is NULL pointer. \n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get hardware client and check the i2c status
|
||||
ALSPS_hw_client = ALSPS_hw_getHardwareClient(ALSPS_sensor_source);
|
||||
if(ALSPS_hw_client == NULL){
|
||||
err("ALSPS_hw_client is NULL pointer. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ALSPS_hw_client->ALSPS_hw_init == NULL){
|
||||
err("ALSPS_hw_init is NULL pointer. \n");
|
||||
return NULL;
|
||||
}
|
||||
ret = ALSPS_hw_client->ALSPS_hw_init(g_i2c_client);
|
||||
if (ret < 0) {
|
||||
//i2c_del_driver(&ALSPS_i2c_driver_client);
|
||||
log("%s %s Probe Fail. \n", __FUNCTION__, ALSPS_i2c_driver_client.driver.name);
|
||||
return NULL ;
|
||||
}else{
|
||||
log("%s %s Probe Success. \n", __FUNCTION__, ALSPS_i2c_driver_client.driver.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ALSPS_sensor_source == ALSPS_hw_source_max) {
|
||||
err("There is NO source can Probe.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ALSPS_hw_client;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_hw_getHardware);
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*******************************/
|
||||
/* ALSPS Sensor Hardware Module */
|
||||
/******************************/
|
||||
#ifndef __LINUX_ALSPS_HARDWARE_H
|
||||
#define __LINUX_ALSPS_HARDWARE_H
|
||||
|
||||
/****************************/
|
||||
/* ALSPS Sensor Configuration */
|
||||
/**************************/
|
||||
#ifdef CONFIG_TMD2755_FLAG
|
||||
enum hardware_source {
|
||||
ALSPS_hw_source_tmd2755=0,
|
||||
ALSPS_hw_source_max,
|
||||
};
|
||||
#else
|
||||
enum hardware_source {
|
||||
ALSPS_hw_source_vcnl36866=0,
|
||||
ALSPS_hw_source_max,
|
||||
};
|
||||
#endif
|
||||
|
||||
#include <linux/input/ASH.h>
|
||||
extern ALSPS_hw* ALSPS_hw_vcnl36866_getHardware(void);
|
||||
extern ALSPS_hw* ALSPS_hw_vcnl36866_getHardware_2nd(void);
|
||||
extern ALSPS_hw* ALSPS_hw_cm36686_getHardware(void);
|
||||
extern ALSPS_hw* ALSPS_hw_ap3045_getHardware(void);
|
||||
extern ALSPS_hw* ALSPS_hw_tmd2755_getHardware(void);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/********************************/
|
||||
/* ALSPS Sensor Hardware Module */
|
||||
/******************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include "ALSPSsensor_Hardware_2nd.h"
|
||||
#include <linux/input/ASH.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_HW"
|
||||
#define SENSOR_TYPE_NAME "ALSPS_2nd"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_HW_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
/********************/
|
||||
/* Global Variables */
|
||||
/******************/
|
||||
static ALSPS_I2C* g_ALSPS_I2C;
|
||||
static struct i2c_client * g_i2c_client = NULL;
|
||||
|
||||
extern struct ALSPS_hw *g_ALSPS_hw_client_2nd;
|
||||
static int mALSPS_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_probe == NULL){
|
||||
err("ALSPS_probe NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We use Probe function to get i2c client */
|
||||
g_i2c_client = client;
|
||||
|
||||
g_ALSPS_I2C->ALSPS_probe(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mALSPS_remove(struct i2c_client *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_remove == NULL){
|
||||
err("ALSPS_remove NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_remove();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mALSPS_shutdown(struct i2c_client *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_shutdown == NULL){
|
||||
err("ALSPS_shutdown NOT implement. \n");
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_shutdown();
|
||||
}
|
||||
|
||||
static int mALSPS_suspend(struct device *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_suspend == NULL){
|
||||
err("ALSPS_suspend NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_suspend();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mALSPS_resume(struct device *client)
|
||||
{
|
||||
if(g_ALSPS_I2C->ALSPS_resume == NULL){
|
||||
err("ALSPS_resume NOT implement. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C->ALSPS_resume();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops alsps_dev_pm_ops = {
|
||||
.suspend = mALSPS_suspend,
|
||||
.resume = mALSPS_resume,
|
||||
};
|
||||
|
||||
static struct i2c_driver ALSPS_i2c_driver_client = {
|
||||
.probe = mALSPS_probe,
|
||||
.remove = mALSPS_remove,
|
||||
.shutdown = mALSPS_shutdown,
|
||||
.driver.pm = &alsps_dev_pm_ops,
|
||||
};
|
||||
|
||||
int ALSPS_i2c_register_2nd(ALSPS_I2C *alsps_i2c)
|
||||
{
|
||||
if(alsps_i2c == NULL){
|
||||
err("%s : ALSPS_I2C is NULL pointer. \n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_ALSPS_I2C = alsps_i2c;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_i2c_register_2nd);
|
||||
|
||||
int ALSPS_i2c_unregister_2nd(void)
|
||||
{
|
||||
i2c_del_driver(&ALSPS_i2c_driver_client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_i2c_unregister_2nd);
|
||||
|
||||
/***********************/
|
||||
/*VCNL36866 I2c Driver*/
|
||||
/**********************/
|
||||
static const struct i2c_device_id vcnl36866_i2c_id[] = {
|
||||
{"vcnl36866_2nd", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct of_device_id vcnl36866_match_table[] = {
|
||||
{ .compatible = "qcom,vcnl36866_2nd",},
|
||||
{},
|
||||
};
|
||||
|
||||
static int ALSPS_hw_setI2cDriver(struct i2c_driver* i2c_driver_client,
|
||||
int hardware_source)
|
||||
{
|
||||
switch(hardware_source) {
|
||||
case ALSPS_hw_source_vcnl36866:
|
||||
log("set i2c client : vcnl36866_2nd \n");
|
||||
i2c_driver_client->driver.name = "vcnl36866_2nd";
|
||||
i2c_driver_client->driver.owner = THIS_MODULE;
|
||||
i2c_driver_client->driver.of_match_table = vcnl36866_match_table;
|
||||
i2c_driver_client->id_table = vcnl36866_i2c_id;
|
||||
break;
|
||||
|
||||
default:
|
||||
err("get hardware client ERROR : hardware enum=%d\n", hardware_source);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALSPS_hw* ALSPS_hw_getHardwareClient(int hardware_source)
|
||||
{
|
||||
ALSPS_hw* ALSPS_hw_client = NULL;
|
||||
|
||||
switch(hardware_source) {
|
||||
case ALSPS_hw_source_vcnl36866:
|
||||
log("get hardware client : vcnl36866_2nd \n");
|
||||
ALSPS_hw_client = ALSPS_hw_vcnl36866_getHardware_2nd();
|
||||
break;
|
||||
|
||||
default:
|
||||
err("get hardware client ERROR : hardware enum=%d\n", hardware_source);
|
||||
}
|
||||
|
||||
return ALSPS_hw_client;
|
||||
}
|
||||
|
||||
int ALSPS_i2c_add_driver_2nd(void)
|
||||
{
|
||||
int ALSPS_sensor_source;
|
||||
int ret = 0;
|
||||
|
||||
/*check i2c function pointer*/
|
||||
if(g_ALSPS_I2C == NULL) {
|
||||
err("g_ALSPS_I2C is NULL. Please use 'ALSPS_i2c_register' first. \n");
|
||||
return -1;
|
||||
}
|
||||
/* i2c Registration */
|
||||
for (ALSPS_sensor_source = 0; ALSPS_sensor_source < ALSPS_hw_source_max;
|
||||
ALSPS_sensor_source++) {
|
||||
|
||||
/* i2c Registration and g_client will get i2c client */
|
||||
ALSPS_hw_setI2cDriver(&ALSPS_i2c_driver_client, ALSPS_sensor_source);
|
||||
ret = i2c_add_driver(&ALSPS_i2c_driver_client);
|
||||
if ( ret != 0 ) {
|
||||
err("%s: i2c_add_driver ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_i2c_add_driver_2nd);
|
||||
|
||||
ALSPS_hw* ALSPS_hw_getHardware_2nd(void)
|
||||
{
|
||||
int ALSPS_sensor_source;
|
||||
int ret = 0;
|
||||
ALSPS_hw* ALSPS_hw_client = NULL;
|
||||
|
||||
/*check i2c function pointer*/
|
||||
if(g_ALSPS_I2C == NULL) {
|
||||
err("g_ALSPS_I2C is NULL. Please use 'ALSPS_i2c_register' first. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* i2c Registration */
|
||||
for (ALSPS_sensor_source = 0; ALSPS_sensor_source < ALSPS_hw_source_max;
|
||||
ALSPS_sensor_source++) {
|
||||
|
||||
if(g_i2c_client == NULL){
|
||||
err("%s: g_i2c_client is NULL pointer. \n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get hardware client and check the i2c status
|
||||
ALSPS_hw_client = ALSPS_hw_getHardwareClient(ALSPS_sensor_source);
|
||||
if(ALSPS_hw_client == NULL){
|
||||
err("ALSPS_hw_client is NULL pointer. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ALSPS_hw_client->ALSPS_hw_init == NULL){
|
||||
err("ALSPS_hw_init is NULL pointer. \n");
|
||||
return NULL;
|
||||
}
|
||||
ret = ALSPS_hw_client->ALSPS_hw_init(g_i2c_client);
|
||||
if (ret < 0) {
|
||||
//i2c_del_driver(&ALSPS_i2c_driver_client);
|
||||
log("%s %s Probe Fail. \n", __FUNCTION__, ALSPS_i2c_driver_client.driver.name);
|
||||
continue;
|
||||
}else{
|
||||
log("%s %s Probe Success. \n", __FUNCTION__, ALSPS_i2c_driver_client.driver.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ALSPS_sensor_source == ALSPS_hw_source_max) {
|
||||
err("There is NO source can Probe.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ALSPS_hw_client;
|
||||
}
|
||||
EXPORT_SYMBOL(ALSPS_hw_getHardware_2nd);
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*******************************/
|
||||
/* ALSPS Sensor Hardware Module */
|
||||
/******************************/
|
||||
#ifndef __LINUX_ALSPS_HARDWARE_H
|
||||
#define __LINUX_ALSPS_HARDWARE_H
|
||||
|
||||
/****************************/
|
||||
/* ALSPS Sensor Configuration */
|
||||
/**************************/
|
||||
enum hardware_source {
|
||||
ALSPS_hw_source_vcnl36866=0,
|
||||
ALSPS_hw_source_max,
|
||||
};
|
||||
|
||||
#include <linux/input/ASH.h>
|
||||
extern ALSPS_hw* ALSPS_hw_vcnl36866_getHardware(void);
|
||||
extern ALSPS_hw* ALSPS_hw_vcnl36866_getHardware_2nd(void);
|
||||
extern ALSPS_hw* ALSPS_hw_cm36686_getHardware(void);
|
||||
extern ALSPS_hw* ALSPS_hw_ap3045_getHardware(void);
|
||||
#endif
|
||||
|
@ -0,0 +1,234 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
static int log_count_limit = 500;
|
||||
int ams_i2c_blk_read(struct i2c_client *client, u8 reg, u8 *val, int size)
|
||||
{
|
||||
s32 ret;
|
||||
static int log_count = 0;
|
||||
|
||||
ret = i2c_smbus_read_i2c_block_data(client, reg, size, val);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed at address %x (%d bytes)\n", __func__, reg, size);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ams_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
|
||||
{
|
||||
return ams_i2c_blk_read(client, reg, val, 1);
|
||||
}
|
||||
|
||||
int ams_i2c_blk_read_direct(struct i2c_client *client, u8 reg, u8 *val, int size)
|
||||
{
|
||||
s32 ret;
|
||||
static int log_count = 0;
|
||||
|
||||
ret = i2c_smbus_read_i2c_block_data(client, reg, size, val);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed at address %x (%d bytes)\n", __func__, reg, size);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ams_i2c_write_direct(struct i2c_client *client, u8 reg, u8 val)
|
||||
{
|
||||
int ret;
|
||||
static int log_count = 0;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, reg, val);
|
||||
if (ret < 0) {
|
||||
mdelay(3);
|
||||
ret = i2c_smbus_write_byte_data(client, reg, val);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed to write register %x err= %d\n", __func__, reg, ret);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ams_i2c_write(struct i2c_client *client, u8 *shadow, u8 reg, u8 val)
|
||||
{
|
||||
int ret;
|
||||
static int log_count = 0;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, reg, val);
|
||||
if (ret < 0) {
|
||||
mdelay(3);
|
||||
ret = i2c_smbus_write_byte_data(client, reg, val);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed to write register %x err= %d\n", __func__, reg, ret);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
}
|
||||
shadow[reg] = val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ams_i2c_reg_blk_write(struct i2c_client *client, u8 reg, u8 *val, int size)
|
||||
{
|
||||
s32 ret;
|
||||
static int log_count = 0;
|
||||
|
||||
ret = i2c_smbus_write_i2c_block_data(client, reg, size, val);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed 2X at address %x (%d bytes)\n", __func__, reg, size);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ams_i2c_ram_blk_write(struct i2c_client *client, u8 reg, u8 *val, int size)
|
||||
{
|
||||
s32 ret = 0;
|
||||
int i;
|
||||
int bsize = 0;
|
||||
int breg = reg;
|
||||
int validx = 0;
|
||||
int maxblocksize = 32;
|
||||
static int log_count = 0;
|
||||
|
||||
for (i = 0; i < size; i += maxblocksize) {
|
||||
if ((size - i) >= maxblocksize)
|
||||
bsize = maxblocksize;
|
||||
else
|
||||
bsize = size - i;
|
||||
|
||||
ret = i2c_smbus_write_i2c_block_data(client, breg, bsize, &val[validx]);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed at address %x (%d bytes)\n", __func__, reg, size);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
|
||||
breg += bsize;
|
||||
validx += bsize;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ams_i2c_ram_blk_read(struct i2c_client *client, u8 reg, u8 *val, int size)
|
||||
{
|
||||
s32 ret = 0;
|
||||
int i;
|
||||
int bsize = 0;
|
||||
int breg = reg;
|
||||
int validx = 0;
|
||||
int maxblocksize = 32;
|
||||
static int log_count = 0;
|
||||
|
||||
for (i = 0; i < size; i += maxblocksize) {
|
||||
if ((size - i) >= maxblocksize)
|
||||
bsize = maxblocksize;
|
||||
else
|
||||
bsize = size - i;
|
||||
|
||||
ret = i2c_smbus_read_i2c_block_data(client, breg, bsize, &val[validx]);
|
||||
if (ret < 0)
|
||||
ret = i2c_smbus_read_i2c_block_data(client, breg, bsize, &val[validx]);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed 2X at address %x (%d bytes)\n", __func__, reg, size);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_write_i2c_block_data(client, breg, bsize, &val[validx]);
|
||||
if (ret < 0){
|
||||
if(log_count % log_count_limit == 0){
|
||||
dev_err(&client->dev, "%s: failed at address %x (%d bytes)\n", __func__, reg, size);
|
||||
}
|
||||
log_count++;
|
||||
}
|
||||
|
||||
breg += bsize;
|
||||
validx += bsize;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ams_i2c_modify(struct i2c_client *client, u8 *shadow, u8 reg, u8 mask, u8 val)
|
||||
{
|
||||
int ret;
|
||||
u8 temp;
|
||||
|
||||
ret = ams_i2c_read(client, reg, &temp);
|
||||
temp &= ~mask;
|
||||
temp |= val;
|
||||
ret = ams_i2c_write(client, shadow, reg, temp);
|
||||
|
||||
shadow[reg] = temp;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ams_i2c_set_field(struct i2c_client *client, u8 *shadow, u8 reg, u8 pos, u8 nbits, u8 val)
|
||||
{
|
||||
u8 tmp;
|
||||
u8 mask = (1 << nbits) - 1;
|
||||
|
||||
ams_i2c_read(client, reg, &tmp);
|
||||
tmp &= ~(mask << pos);
|
||||
tmp |= (val << pos);
|
||||
ams_i2c_write(client, shadow, reg, tmp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ams_i2c_get_field(struct i2c_client *client, u8 reg, u8 pos, u8 nbits, u8 *val)
|
||||
{
|
||||
u8 tmp;
|
||||
u8 mask = (1 << nbits) - 1;
|
||||
|
||||
ams_i2c_read(client, reg, &tmp);
|
||||
tmp &= mask << pos;
|
||||
*val = tmp >> pos;
|
||||
|
||||
return;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __AMS_I2C_H__
|
||||
#define __AMS_I2C_H__
|
||||
|
||||
int ams_i2c_blk_read(struct i2c_client *client, u8 reg, u8 *val, int size);
|
||||
int ams_i2c_read(struct i2c_client *client, u8 reg, u8 *val);
|
||||
int ams_i2c_blk_read_direct(struct i2c_client *client, u8 reg, u8 *val, int size);
|
||||
int ams_i2c_write_direct(struct i2c_client *client, u8 reg, u8 val);
|
||||
int ams_i2c_write(struct i2c_client *client, u8 *shadow, u8 reg, u8 val);
|
||||
int ams_i2c_reg_blk_write(struct i2c_client *client, u8 reg, u8 *val, int size);
|
||||
int ams_i2c_ram_blk_write(struct i2c_client *client, u8 reg, u8 *val, int size);
|
||||
int ams_i2c_ram_blk_read(struct i2c_client *client, u8 reg, u8 *val, int size);
|
||||
int ams_i2c_modify(struct i2c_client *client, u8 *shadow, u8 reg, u8 mask, u8 val);
|
||||
void ams_i2c_set_field(struct i2c_client *client, u8 *shadow, u8 reg, u8 pos, u8 nbits, u8 val);
|
||||
void ams_i2c_get_field(struct i2c_client *client, u8 reg, u8 pos, u8 nbits, u8 *val);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,472 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Device driver for monitoring ambient light intensity in (lux)
|
||||
* proximity detection (prox), and color temperature functionality within the
|
||||
* AMS TMD2755 family of devices.
|
||||
*/
|
||||
|
||||
#ifndef __AMS_TMD2755_H__
|
||||
#define __AMS_TMD2755_H__
|
||||
|
||||
/* Linux Include Files */
|
||||
#include <linux/types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/***********************************************
|
||||
* Flags for adding/removing code *
|
||||
***********************************************/
|
||||
/* Flag for enabling Debug input device dump */
|
||||
/* and set all registers. */
|
||||
#define DEBUG_ABI_SET_GET_REGISTERS
|
||||
#define REMOVE_INPUT_DEVICE
|
||||
|
||||
extern void psensor_report_abs(int abs);
|
||||
extern void lsensor_report_lux(int lux);
|
||||
extern struct mutex g_alsps_lock;
|
||||
extern tmd2755_status_param g_tmd2755_status_param;
|
||||
|
||||
/* Debugging Prox feature - during development */
|
||||
#define DEBUG_PROX_FEATURE
|
||||
// #define AMS_MUTEX_DEBUG
|
||||
|
||||
#if defined(AMS_MUTEX_DEBUG)
|
||||
#define AMS_MUTEX_LOCK(m) { \
|
||||
printk(KERN_INFO "%s:%s() --> Mutex Lock\n", __FILE__, __func__); \
|
||||
mutex_lock(m); \
|
||||
}
|
||||
#define AMS_MUTEX_UNLOCK(m) { \
|
||||
printk(KERN_INFO "%s:%s() --> Mutex Unlock\n", __FILE__, __func__); \
|
||||
mutex_unlock(m); \
|
||||
}
|
||||
#else
|
||||
#define AMS_MUTEX_LOCK(m) { \
|
||||
mutex_lock(m); \
|
||||
}
|
||||
#define AMS_MUTEX_UNLOCK(m) { \
|
||||
mutex_unlock(m); \
|
||||
}
|
||||
#endif
|
||||
#define MIN_KERNEL_LOG_LEN (28)
|
||||
#define MAX_KERNEL_LOG_LEN MIN_KERNEL_LOG_LEN
|
||||
#define LINE_NUM_KERNEL_LOG_LEN (3)
|
||||
|
||||
#define MAX_REGS 256
|
||||
|
||||
#define BASE_10 (10)
|
||||
|
||||
|
||||
/* Mandatory register values */
|
||||
#define CFG8_REG_REQUIRED_VAL 0x29
|
||||
#define TST3_REG_REQUIRED_VAL 0x04 /* changed 4/13/2020 */
|
||||
#define TST9_REG_REQUIRED_VAL 0x02 /* changed from 0x0B per Whitney 11/13/2019 */
|
||||
|
||||
enum tmd2755_regs {
|
||||
TMD2755_REG_ENABLE = 0x80,
|
||||
TMD2755_REG_ATIME = 0x81,
|
||||
TMD2755_REG_PRATE = 0x82, /* PTIME, PRATE */
|
||||
TMD2755_REG_AWTIME = 0x83,
|
||||
TMD2755_REG_AILTL = 0x84,
|
||||
TMD2755_REG_AILTH = 0x85,
|
||||
TMD2755_REG_AIHTL = 0x86,
|
||||
TMD2755_REG_AIHTH = 0x87,
|
||||
TMD2755_REG_PILTL = 0x88,
|
||||
TMD2755_REG_PILTH = 0x89,
|
||||
TMD2755_REG_PIHTL = 0x8A,
|
||||
TMD2755_REG_PIHTH = 0x8B,
|
||||
TMD2755_REG_PERS = 0x8C, /* als and prox interrupt pers*/
|
||||
TMD2755_REG_CFG0 = 0x8D,
|
||||
TMD2755_REG_PCFG0 = 0x8E,
|
||||
TMD2755_REG_PCFG1 = 0x8F,
|
||||
TMD2755_REG_PCFG2 = 0x90,
|
||||
TMD2755_REG_CFG1 = 0x91,
|
||||
TMD2755_REG_REVID = 0x92,
|
||||
TMD2755_REG_DEVICEID = 0x93,
|
||||
TMD2755_REG_STATUS = 0x94,
|
||||
TMD2755_REG_ALSL = 0x95,
|
||||
TMD2755_REG_ALSH = 0x96,
|
||||
TMD2755_REG_IRL = 0x97,
|
||||
TMD2755_REG_IRH = 0x98,
|
||||
|
||||
TMD2755_REG_PDATAL = 0x99,
|
||||
TMD2755_REG_PDATAH = 0x9A,
|
||||
|
||||
TMD2755_REG_REVID2 = 0xA6,
|
||||
|
||||
TMD2755_REG_SOFTRST = 0xA8,
|
||||
|
||||
TMD2755_REG_PWTIME = 0xA9,
|
||||
|
||||
TMD2755_REG_CFG8 = 0xAA,
|
||||
TMD2755_REG_CFG3 = 0xAB,
|
||||
TMD2755_REG_CFG6 = 0xAE,
|
||||
|
||||
TMD2755_REG_POFFSET_L = 0xC0,
|
||||
TMD2755_REG_POFFSET_H = 0xC1,
|
||||
|
||||
TMD2755_REG_CALIB = 0xD7,
|
||||
TMD2755_REG_CALIB_OFF = 0xD8,
|
||||
TMD2755_REG_CALIBCFG = 0xD9,
|
||||
TMD2755_REG_CALIBSTAT = 0xDC,
|
||||
|
||||
TMD2755_REG_INTENAB = 0xDD,
|
||||
|
||||
TMD2755_REG_FAC_L = 0xE6,
|
||||
TMD2755_REG_FAC_H = 0xE7,
|
||||
|
||||
/* TODO remove me after new datasheet rev */
|
||||
TMD2755_REG_TEST3 = 0xF3,
|
||||
TMD2755_REG_TEST9 = 0xF9,
|
||||
|
||||
TMD2755_REG_LAST = 0xFF,
|
||||
};
|
||||
|
||||
enum tmd2755_mask_shift_reg {
|
||||
TMD2755_MASK_DEVICEID = 0xFC,
|
||||
TMD2755_SHIFT_DEVICEID = 2,
|
||||
|
||||
TMD2755_MASK_REVID = 0x07,
|
||||
TMD2755_SHIFT_REVID = 0,
|
||||
|
||||
TMD2755_MASK_REVID2 = 0x0F,
|
||||
TMD2755_SHIFT_REVID2 = 0,
|
||||
|
||||
TMD2755_MASK_PGAIN1 = 0xC0,
|
||||
TMD2755_SHIFT_PGAIN1 = 6,
|
||||
|
||||
TMD2755_MASK_PGAIN2 = 0x60,
|
||||
TMD2755_SHIFT_PGAIN2 = 5,
|
||||
|
||||
TMD2755_MASK_PPULSE = 0x3F,
|
||||
TMD2755_SHIFT_PPULSE = 0,
|
||||
|
||||
TMD2755_MASK_PILTL = 0xFF,
|
||||
TMD2755_SHIFT_PILTL = 0,
|
||||
TMD2755_MASK_PILTH = 0x3F,
|
||||
TMD2755_SHIFT_PILTH = 0,
|
||||
|
||||
TMD2755_MASK_PIHTL = 0xFF,
|
||||
TMD2755_SHIFT_PIHTL = 0,
|
||||
TMD2755_MASK_PIHTH = 0x3F,
|
||||
TMD2755_SHIFT_PIHTH = 0,
|
||||
|
||||
TMD2755_MASK_PROX_PERS = 0xF0,
|
||||
TMD2755_SHIFT_PROX_PERS = 4,
|
||||
|
||||
TMD2755_MASK_START_OFFSET_CALIB = 0x01,
|
||||
TMD2755_SHIFT_START_OFFSET_CALIB = 0,
|
||||
|
||||
TMD2755_MASK_CALPRATE_CALIB = 0x10,
|
||||
TMD2755_SHIFT_CALPRATE_CALIB = 4,
|
||||
|
||||
TMD2755_MASK_ELEC_OPTO_CALIB = 0x20,
|
||||
TMD2755_SHIFT_ELEC_OPTO_CALIB = 5,
|
||||
|
||||
TMD2755_MASK_CALAVG_CALIB = 0x80,
|
||||
TMD2755_SHIFT_CALAVG_CALIB = 7,
|
||||
|
||||
TMD2755_MASK_ENABLE_ORE = 0x20,
|
||||
TMD2755_SHIFT_ENABLE_ORE = 5,
|
||||
|
||||
TMD2755_MASK_ORE = 0x1F,
|
||||
TMD2755_SHIFT_ORE = 0,
|
||||
|
||||
|
||||
TMD2755_MASK_BINSRCH_TARGET = 0xE0,
|
||||
TMD2755_SHIFT_BINSRCH_TARGET = 5,
|
||||
|
||||
TMD2755_MASK_PROX_AUTO_OFFSET_ADJUST = 0x08,
|
||||
TMD2755_SHIFT_PROX_AUTO_OFFSET_ADJUST = 3,
|
||||
|
||||
TMD2755_MASK_PROX_DATA_AVG = 0x07,
|
||||
TMD2755_SHIFT_PROX_DATA_AVG = 0,
|
||||
|
||||
TMD2755_MASK_POFFSET_H = 0x01,
|
||||
TMD2755_SHIFT_POFFSET_H = 0,
|
||||
|
||||
TMD2755_MASK_PPULSE_LEN_L = 0x0FF,
|
||||
TMD2755_SHIFT_PPULSE_LEN_L = 0,
|
||||
|
||||
TMD2755_MASK_REG_PPULSE_LEN_H = 0xC0, // mask for register PCFG1
|
||||
TMD2755_MASK_DATA_PPULSE_LEN_H = 0x300, // mask for data structure - 10 bit value
|
||||
TMD2755_SHIFT_PPULSE_LEN_H = 2,
|
||||
|
||||
TMD2755_MASK_APC = 0x40,
|
||||
TMD2755_SHIFT_APC = 6,
|
||||
|
||||
TMD2755_MASK_AGAIN = 0x1F,
|
||||
TMD2755_SHIFT_AGAIN = 0,
|
||||
|
||||
TMD2755_MASK_AWLONG = 0x04,
|
||||
TMD2755_SHIFT_AWLONG = 2,
|
||||
|
||||
TMD2755_MASK_ALS_PERS = 0x0F,
|
||||
TMD2755_SHIFT_ALS_PERS = 0,
|
||||
|
||||
};
|
||||
|
||||
enum tmd2755_pwr_state {
|
||||
POWER_ON,
|
||||
POWER_OFF,
|
||||
POWER_STANDBY,
|
||||
};
|
||||
|
||||
enum tmd2755_prox_state {
|
||||
PROX_STATE_NONE = 0,
|
||||
PROX_STATE_INIT,
|
||||
PROX_STATE_CALIB,
|
||||
PROX_STATE_WAIT_AND_CALIB
|
||||
};
|
||||
|
||||
enum tmd2755_feature_state {
|
||||
TMD2755_FEATURE_OFF = 0,
|
||||
TMD2755_FEATURE_ON = 1,
|
||||
};
|
||||
|
||||
enum tmd2755_enable_state {
|
||||
TMD2755_ENABLE_OFF = 0,
|
||||
TMD2755_ENABLE_ON = 1,
|
||||
};
|
||||
|
||||
enum tmd2755_ctrl_reg {
|
||||
AGAIN_16 = (5 << 0),
|
||||
AGAIN_128 = (8 << 0),
|
||||
AGAIN_1024 = (11 << 0),
|
||||
PGAIN1_1 = (0 << TMD2755_SHIFT_PGAIN1),
|
||||
PGAIN1_2 = (1 << TMD2755_SHIFT_PGAIN1),
|
||||
PGAIN1_4 = (2 << TMD2755_SHIFT_PGAIN1),
|
||||
PGAIN1_8 = (3 << TMD2755_SHIFT_PGAIN1),
|
||||
PGAIN2_1 = (0 << TMD2755_SHIFT_PGAIN2),
|
||||
PGAIN2_2_5 = (1 << TMD2755_SHIFT_PGAIN2),
|
||||
PGAIN2_5 = (2 << TMD2755_SHIFT_PGAIN2),
|
||||
PGAIN2_10 = (3 << TMD2755_SHIFT_PGAIN2),
|
||||
};
|
||||
|
||||
enum tmd2755_enable_reg {
|
||||
TMD2755_PON = (1 << 0),
|
||||
TMD2755_AEN = (1 << 1),
|
||||
TMD2755_PEN = (1 << 2),
|
||||
TMD2755_AWEN = (1 << 3),
|
||||
TMD2755_PWEN = (1 << 4),
|
||||
TMD2755_EN_ALL = (TMD2755_AEN |TMD2755_PEN | TMD2755_AWEN | TMD2755_PWEN),
|
||||
};
|
||||
|
||||
|
||||
enum tmd2755_int_shift {
|
||||
TMD2755_INT_PRX_SAT_SHIFT = 6,
|
||||
};
|
||||
|
||||
enum tmd2755_int_status {
|
||||
TMD2755_INT_ST_PSAT_AMBIENT_IRQ = (1 << 0),
|
||||
TMD2755_INT_ST_PSAT_REFLECT_IRQ = (1 << 1),
|
||||
TMD2755_INT_ST_ZERODET_IRQ = (1 << 2),
|
||||
TMD2755_INT_ST_CALIB_IRQ = (1 << 3),
|
||||
TMD2755_INT_ST_ALS_IRQ = (1 << 4),
|
||||
TMD2755_INT_ST_PRX_IRQ = (1 << 5),
|
||||
TMD2755_INT_ST_PRX_SAT_IRQ = (1 << 6),
|
||||
TMD2755_INT_ST_ALS_SAT_IRQ = (1 << 7),
|
||||
};
|
||||
|
||||
enum tmd2755_intenab_reg {
|
||||
TMD2755_ZIEN = (1 << 2),
|
||||
TMD2755_CIEN = (1 << 3),
|
||||
TMD2755_AIEN = (1 << 4),
|
||||
TMD2755_PIEN = (1 << 5),
|
||||
TMD2755_PSIEN = (1 << 6),
|
||||
TMD2755_ASIEN = (1 << 7),
|
||||
};
|
||||
/* Group all the prox interrupts */
|
||||
#define TMD2755_PROX_INTS (TMD2755_ZIEN | TMD2755_PIEN | TMD2755_PSIEN | TMD2755_CIEN)
|
||||
|
||||
// pldrive Ivcsel = (PLDRIVE + 2) mA
|
||||
#define PDRIVE_MA(p) ({ \
|
||||
u8 __reg = (((u8)((p) - 2)) & 0x0F); \
|
||||
__reg = (__reg > 0x0A) ? 0x0A : __reg; \
|
||||
__reg; \
|
||||
})
|
||||
|
||||
// pulse length (PULSE_LEN + 2) usec - 10 bits
|
||||
#define PPULSE_LEN_US(p) ({ \
|
||||
u16 __reg; \
|
||||
if (p < 2) { \
|
||||
__reg = 0; \
|
||||
} else { \
|
||||
__reg = (((u16)((p) - 2)) & 0x3FF); \
|
||||
__reg = (__reg > 0x3FF) ? 0x03FF : __reg; \
|
||||
} \
|
||||
__reg; \
|
||||
})
|
||||
|
||||
#define P_TIME_US(p) ((((p) / 88) - 1.0) + 0.5)
|
||||
#define INTEGRATION_CYCLE 2780
|
||||
|
||||
/* Used for ALS Wait time and ALS Time */
|
||||
#define AW_TIME_MS(p) ((((p) * 1000) + (INTEGRATION_CYCLE - 1)) / INTEGRATION_CYCLE)
|
||||
|
||||
struct als_prox_pers
|
||||
{
|
||||
u8 apers : 4;
|
||||
u8 ppers : 4;
|
||||
};
|
||||
|
||||
union tmd2755_persist
|
||||
{
|
||||
struct als_prox_pers pers;
|
||||
u8 persistance;
|
||||
};
|
||||
|
||||
#define PROX_PERSIST(p) (((p) & 0x0F) << 4)
|
||||
|
||||
#define ALS_PERSIST(p) (((p) & 0x0F) << 0)
|
||||
|
||||
struct tmd2755_parameters {
|
||||
/* Common both als and prox */
|
||||
union tmd2755_persist persist;
|
||||
|
||||
/* Prox */
|
||||
u16 prox_thresh_min;
|
||||
u16 prox_thresh_max;
|
||||
u8 prox_apc;
|
||||
u8 prox_pulse_cnt;
|
||||
u16 prox_pulse_len;
|
||||
u8 prox_gain1;
|
||||
u8 prox_gain2;
|
||||
s16 poffset;
|
||||
u8 prox_drive;
|
||||
u8 prox_time;
|
||||
u8 prox_wtime;
|
||||
/* prox calibration - These registers are set during */
|
||||
/* prox offset calibration and are currently cannot */
|
||||
/* be adjusted programatically */
|
||||
u8 prox_calavg;
|
||||
u8 prox_calprate;
|
||||
u8 prox_enable_ore;
|
||||
u8 prox_ore;
|
||||
u8 prox_binsrch_tgt;
|
||||
u8 prox_auto_off_adj;
|
||||
u8 prox_avg;
|
||||
|
||||
/* ALS / Color */
|
||||
u8 als_gain;
|
||||
u32 als_auto_gain;
|
||||
u16 als_deltaP;
|
||||
u8 als_time;
|
||||
u8 als_wtime;
|
||||
u32 dgf;
|
||||
u32 ch0_coef0;
|
||||
u32 ch0_coef1;
|
||||
u32 ch1_coef0;
|
||||
u32 ch1_coef1;
|
||||
u32 coef_scale;
|
||||
s16 poffset_fac;
|
||||
s16 poffset_limit;
|
||||
s16 poffset_last;
|
||||
};
|
||||
|
||||
struct tmd2755_als_info {
|
||||
u32 counts_per_lux;
|
||||
u32 saturation;
|
||||
u16 ch0_raw;
|
||||
u16 ch1_raw;
|
||||
u16 lux;
|
||||
};
|
||||
|
||||
struct tmd2755_prox_info {
|
||||
u16 raw;
|
||||
int detected;
|
||||
};
|
||||
|
||||
// Must match definition in ../arch file
|
||||
struct tmd2755_i2c_platform_data {
|
||||
/* The following callback for power events received and handled by
|
||||
the driver. Currently only for SUSPEND and RESUME */
|
||||
int (*platform_power)(struct device *dev, enum tmd2755_pwr_state state);
|
||||
int (*platform_init)(void);
|
||||
void (*platform_teardown)(struct device *dev);
|
||||
|
||||
char const *prox_name;
|
||||
char const *als_name;
|
||||
int device_index;
|
||||
struct tmd2755_parameters parameters;
|
||||
// TODO: ??? bool proximity_can_wake;
|
||||
// TODO: ??? bool als_can_wake;
|
||||
#if defined(CONFIG_OF)
|
||||
struct device_node *of_node;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct tmd2755_chip {
|
||||
struct mutex lock;
|
||||
struct completion calibration_done;
|
||||
struct i2c_client *client;
|
||||
struct gpio_desc *gpiod_interrupt;
|
||||
struct tmd2755_prox_info prox_info;
|
||||
struct tmd2755_als_info als_info;
|
||||
struct tmd2755_parameters params;
|
||||
struct tmd2755_i2c_platform_data *pdata;
|
||||
u8 shadow[MAX_REGS];
|
||||
|
||||
struct input_dev *prox_idev;
|
||||
struct input_dev *als_idev;
|
||||
#ifdef DEBUG_ABI_SET_GET_REGISTERS
|
||||
struct input_dev *dbg_idev;
|
||||
#endif // #ifdef DEBUG_ABI_SET_GET_REGISTERS
|
||||
|
||||
int in_suspend;
|
||||
int wake_irq;
|
||||
int irq_pending;
|
||||
|
||||
int in_psat;
|
||||
bool in_asat;
|
||||
bool in_calib;
|
||||
bool unpowered;
|
||||
bool als_enable;
|
||||
bool prox_enable;
|
||||
bool amsCalComplete;
|
||||
|
||||
bool cal_en;
|
||||
|
||||
u8 device_index;
|
||||
};
|
||||
|
||||
#define TMD2755_PROXIMITY_INF_DEFAULT (0)
|
||||
#define TMD2755_PROXIMITY_OFFSET_DEFAULT (76)
|
||||
#define TMD2755_PROXIMITY_THDL_DEFAULT (145)
|
||||
#define TMD2755_PROXIMITY_THDH_DEFAULT (437)
|
||||
#define TMD2755_PROXIMITY_AUTOK_MIN (3)
|
||||
#define TMD2755_PROXIMITY_AUTOK_MAX (300)
|
||||
#define TMD2755_LIGHT_CALIBRATION_DEFAULT (1440)
|
||||
#define TMD2755_LIGHT_MAX_THRESHOLD (65534)
|
||||
|
||||
#define TMD2755_WAIT_I2C_DELAY 5
|
||||
|
||||
|
||||
#endif // __AMS_TMD2755_H__
|
@ -0,0 +1,979 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Device driver for monitoring ambient light intensity in (lux)
|
||||
* proximity detection (prox) functionality within the
|
||||
* AMS TMD2755 family of devices.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "ams_tmd2755.h"
|
||||
#include "ams_tmd2755_als.h"
|
||||
#include "ams_i2c.h"
|
||||
|
||||
/******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_tmd2755"
|
||||
#define SENSOR_TYPE_NAME "ALSPS"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_GPIO_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s]"fmt,MODULE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
extern struct tmd2755_chip *g_tmd2755_chip;
|
||||
|
||||
/*********************************/
|
||||
|
||||
/*****************************************************************
|
||||
* Local globals for als module *
|
||||
*****************************************************************/
|
||||
static u8 const restorable_als_regs[] = {
|
||||
TMD2755_REG_ATIME,
|
||||
TMD2755_REG_AWTIME,
|
||||
TMD2755_REG_PERS,
|
||||
TMD2755_REG_CFG0,
|
||||
TMD2755_REG_CFG1,
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* Local Functions *
|
||||
*****************************************************************/
|
||||
static int tmd2755_convert_again(int reg_value)
|
||||
{
|
||||
int ret_val = ALS_GAIN_128;
|
||||
|
||||
switch (reg_value)
|
||||
{
|
||||
case ALS_GAIN_REG_VAL_16:
|
||||
{
|
||||
ret_val = ALS_GAIN_16;
|
||||
break;
|
||||
}
|
||||
case ALS_GAIN_REG_VAL_128:
|
||||
{
|
||||
ret_val = ALS_GAIN_128;
|
||||
break;
|
||||
}
|
||||
case ALS_GAIN_REG_VAL_1024:
|
||||
{
|
||||
ret_val = ALS_GAIN_1024;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(ret_val);
|
||||
}
|
||||
|
||||
static int tmd2755_flush_als_regs(struct tmd2755_chip *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
int rc;
|
||||
u8 reg;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(restorable_als_regs); i++) {
|
||||
reg = restorable_als_regs[i];
|
||||
rc = ams_i2c_write(chip->client, chip->shadow, reg, chip->shadow[reg]);
|
||||
if (rc) {
|
||||
dev_err(&chip->client->dev, "%*.*s():%*d --> err on reg 0x%02X\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refer to Design Notebook 40 for a better understanding of CPL.
|
||||
*/
|
||||
static void tmd2755_calc_counts_per_lux(struct tmd2755_chip *chip)
|
||||
{
|
||||
u64 cpl;
|
||||
u32 sat;
|
||||
u8 atime;
|
||||
u16 again;
|
||||
|
||||
atime = chip->shadow[TMD2755_REG_ATIME];
|
||||
|
||||
cpl = (u64) atime + 1; /* add one because atime reg is base 0: 0 = 1 integration time */
|
||||
cpl *= INTEGRATION_CYCLE; /* using microseconds cancels out the scale factor of the coeffs */
|
||||
|
||||
again = tmd2755_convert_again(chip->shadow[TMD2755_REG_CFG1] & TMD2755_MASK_AGAIN);
|
||||
|
||||
cpl *= again;
|
||||
|
||||
/* Optimization if coefficients are scaled by 1000, adjust accordingly */
|
||||
if (chip->params.coef_scale != ALS_COEFF_SCALE_FACTOR) {
|
||||
/* Possible overflow if coefficients are scaled > 1000 */
|
||||
cpl *= chip->params.coef_scale; /* rgb coeff scaling factor */
|
||||
/* do_div returns the quotient in the divident */
|
||||
do_div(cpl, (chip->params.dgf * ALS_COEFF_SCALE_FACTOR));
|
||||
} else {
|
||||
do_div(cpl, chip->params.dgf);
|
||||
}
|
||||
|
||||
|
||||
/* min of max_als for max amount based on atime - see datasheet for atime */
|
||||
/* each 2.78 ms, increase max count by 1024 - left shift of 10 multiplies by */
|
||||
/* 1024 */
|
||||
sat = min_t(u32, TMD2755_MAX_ALS_VALUE, (u32) (((atime + 1) << TMD2755_SHIFT_MULT_BY_1024) - 1));
|
||||
|
||||
chip->als_info.counts_per_lux = (u32) cpl;
|
||||
/* Set saturation at 90% of max count*/
|
||||
chip->als_info.saturation = TENTH_FRACTION_OF_VAL(sat, TMD2755_SATURATION_THRESHOLD);
|
||||
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> Calculating cpl = %llu, count_per_lux=%u, saturation = %d (%d0%% of %d)\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, cpl,
|
||||
chip->als_info.counts_per_lux, chip->als_info.saturation,
|
||||
TMD2755_SATURATION_THRESHOLD, sat);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int tmd2755_set_als_gain(struct tmd2755_chip *chip, u8 gain)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 saved_enable;
|
||||
|
||||
/* Turn off ALS, so that new ALS gain value will take effect at start of
|
||||
* new integration cycle.
|
||||
* New ALS gain value will then be used in next lux calculation.
|
||||
*/
|
||||
ams_i2c_read(chip->client, TMD2755_REG_ENABLE, &saved_enable);
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_ENABLE, 0); /* turn off everything */
|
||||
rc = ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_CFG1, TMD2755_MASK_AGAIN, gain);
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_ENABLE, saved_enable);
|
||||
|
||||
if (rc >= 0) {
|
||||
chip->params.als_gain = chip->shadow[TMD2755_REG_CFG1] & TMD2755_MASK_AGAIN;
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> New ALS Gain set %d (%dx)\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, gain,
|
||||
tmd2755_convert_again(gain));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void tmd2755_get_rawdata(struct tmd2755_chip *chip)
|
||||
{
|
||||
u8 *sh = chip->shadow;
|
||||
|
||||
/* extract raw channel data */
|
||||
chip->als_info.ch0_raw = le16_to_cpup((const __le16 *)&sh[TMD2755_REG_ALSL]);
|
||||
chip->als_info.ch1_raw = le16_to_cpup((const __le16 *)&sh[TMD2755_REG_IRL]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void tmd2755_inc_gain(struct tmd2755_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
u8 gain = (chip->shadow[TMD2755_REG_CFG1] & TMD2755_MASK_AGAIN);
|
||||
|
||||
if (gain == ALS_GAIN_REG_VAL_1024) {
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d -->\tCannot Increment ALS Gain: already at maximum (%d x).\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, ALS_GAIN_1024);
|
||||
return; /* already at highest gain setting */
|
||||
}
|
||||
|
||||
/* if gain is set to 16x, move it to 128x. If it is 128x, move it to 1024 */
|
||||
gain = ((gain == ALS_GAIN_REG_VAL_16) ? ALS_GAIN_REG_VAL_128 : ALS_GAIN_REG_VAL_1024);
|
||||
|
||||
rc = tmd2755_set_als_gain(chip, gain);
|
||||
if (rc == 0)
|
||||
tmd2755_calc_counts_per_lux(chip);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void tmd2755_dec_gain(struct tmd2755_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
u8 gain = (chip->shadow[TMD2755_REG_CFG1] & TMD2755_MASK_AGAIN);
|
||||
|
||||
if (gain == ALS_GAIN_REG_VAL_16) {
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> \tCannot Decrement ALS Gain: already at minimum (%d x).\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, ALS_GAIN_16);
|
||||
return; /* already at lowest gain */
|
||||
}
|
||||
|
||||
gain = ((gain == ALS_GAIN_REG_VAL_1024) ? ALS_GAIN_REG_VAL_128 : ALS_GAIN_REG_VAL_16);
|
||||
|
||||
rc = tmd2755_set_als_gain(chip, gain);
|
||||
if (rc == 0)
|
||||
tmd2755_calc_counts_per_lux(chip);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int tmd2755_max_als_value(struct tmd2755_chip *chip)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = chip->shadow[TMD2755_REG_ATIME];
|
||||
if (val > ALS_ATIME_FOR_MAX_CNT) /* after a certain atime, the max als count stays the same */
|
||||
val = ALS_FULL_SCALE_CNT;
|
||||
else
|
||||
val = ((val * ALS_ATIME_INCREMENT_CNT) + ALS_ATIME_INCREMENT_CNT-1); /* Initial atime only causes (1024 -1) full scale */
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int tmd2755_update_als_threshold(struct tmd2755_chip *chip, enum tmd2755_enable_state on_enable)
|
||||
{
|
||||
s32 ret = 0;
|
||||
u16 deltaP = chip->params.als_deltaP; /* integer percentage to generate thresholds */
|
||||
u16 from, to, cur;
|
||||
u16 saturation = chip->als_info.saturation;
|
||||
static u16 last_from = 0, last_to = 0;
|
||||
cur = chip->als_info.ch0_raw;
|
||||
|
||||
if (on_enable == TMD2755_ENABLE_ON) {
|
||||
/* move deltaP far away from current position to force an irq */
|
||||
from = to = cur > (saturation / 2) ? 0 : saturation;
|
||||
} else {
|
||||
deltaP = cur * deltaP / 100;
|
||||
if (!deltaP)
|
||||
deltaP = 1;
|
||||
|
||||
if (cur > deltaP)
|
||||
from = cur - deltaP;
|
||||
else
|
||||
from = 0;
|
||||
|
||||
to = cur + deltaP;
|
||||
/* prevent high threshold overflow */
|
||||
if(to > TMD2755_CH0_MAXIMUM){
|
||||
to = TMD2755_CH0_MAXIMUM;
|
||||
}
|
||||
}
|
||||
|
||||
*((__le16 *) &chip->shadow[TMD2755_REG_AILTL]) = cpu_to_le16(from);
|
||||
*((__le16 *) &chip->shadow[TMD2755_REG_AIHTL]) = cpu_to_le16(to);
|
||||
|
||||
if(from != last_from || to != last_to || true == g_tmd2755_status_param.log_first_evt){
|
||||
last_from = from;
|
||||
last_to = to;
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> Low Thresh: %d High Thresh: : %d Current Ch0: %d deltaP: %d Sat Level: %d\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__,
|
||||
from, to, cur, deltaP, saturation);
|
||||
g_tmd2755_status_param.log_first_evt = false;
|
||||
}
|
||||
|
||||
ret = ams_i2c_reg_blk_write(chip->client, TMD2755_REG_AILTL, &chip->shadow[TMD2755_REG_AILTL],
|
||||
(TMD2755_REG_AIHTH - TMD2755_REG_AILTL) + 1);
|
||||
|
||||
return (ret < 0) ? ret : 0;
|
||||
}
|
||||
|
||||
int tmd2755_get_lux(struct tmd2755_chip *chip)
|
||||
{
|
||||
s64 _lux1, _lux2, _lux3;
|
||||
s32 __lux1, __lux2, __lux3;
|
||||
//long lux1, lux2, lux3;
|
||||
s32 lux = 0;
|
||||
//s64 sf;
|
||||
//s32 coefa = chip->params.ch0_coef0;
|
||||
//s32 coefc = chip->params.ch0_coef1;
|
||||
//s32 coefb = chip->params.ch1_coef0;
|
||||
//s32 coefd = chip->params.ch1_coef1;
|
||||
long ch0 = (long)chip->als_info.ch0_raw;
|
||||
long ch1 = (long)chip->als_info.ch1_raw;
|
||||
long coefa = 678; //should / 1000
|
||||
long coefb = 1050; //should /1000
|
||||
long coefc = 4;
|
||||
|
||||
long DFA = 3850;
|
||||
long DFB = 18000;
|
||||
long DFC = 16500;
|
||||
long div_val = 1000;
|
||||
long diff1 = 1500; //should /10000
|
||||
long diff2 = 9900; //should /10000
|
||||
long ch_temp = 0; // ch0/ch1
|
||||
int low_thres;
|
||||
s64 sf = 0;
|
||||
long ch_data_limit = 0;
|
||||
static long ch0_last = 0;
|
||||
|
||||
// use time in ms get scaling factor
|
||||
tmd2755_calc_counts_per_lux(chip);
|
||||
if (!chip->als_info.counts_per_lux) {
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> CPL = 0... Setting to 1\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__);
|
||||
chip->als_info.counts_per_lux = 1;
|
||||
}
|
||||
dbg("count_per_lux=%u", chip->als_info.counts_per_lux);
|
||||
sf = (s64)chip->als_info.counts_per_lux; // atime_ms*again/DGF
|
||||
sf = div64_s64(sf, 1000); // atime_ms*again/DGF
|
||||
dbg("sf=%lld, count_per_lux=%u", sf, chip->als_info.counts_per_lux);
|
||||
dbg("DFA=%ld, DFB=%ld, DFC=%ld, coefa=%ld, coefb=%ld, coefc=%ld", DFA, DFB, DFC, coefa, coefb, coefc);
|
||||
dbg("ch0=%ld, ch1=%ld", ch0, ch1);
|
||||
dbg("DFA*ch0=%ld, DFA*coefa*ch1=%ld", DFA*ch0, DFA*coefa*ch1);
|
||||
dbg("DFB*ch0=%ld (/1000, DFB*coefb*ch1=%ld (/1000000", DFB*ch0, DFB*coefb*ch1);
|
||||
dbg("DFC*ch0=%ld, DFC*coefc*ch1=%ld", DFC*ch0, DFC*coefc*ch1);
|
||||
_lux1 = (s64)DFA*ch0-(DFA*coefa*ch1)/div_val;
|
||||
_lux2 = (s64)(DFB*ch0)-(DFB*coefb*ch1)/div_val;
|
||||
_lux3 = (s64)DFC*ch0-DFC*coefc*ch1;
|
||||
|
||||
__lux1 = (s32)div64_s64(_lux1, sf);
|
||||
__lux2 = (s32)div64_s64(_lux2, sf);
|
||||
__lux3 = (s32)div64_s64(_lux3, sf);
|
||||
|
||||
ch_temp = (ch1*10000)/ch0;
|
||||
if(diff2 < ch_temp){
|
||||
lux = __lux1;
|
||||
}else if((diff2 >= ch_temp) && (diff1 < ch_temp)){
|
||||
lux = __lux2;
|
||||
}else{
|
||||
lux = __lux3;
|
||||
}
|
||||
|
||||
if(ch0 > 1000){
|
||||
ch_data_limit = ch0_last / 10;
|
||||
}else{
|
||||
ch_data_limit = ch0_last * 98 / 100;
|
||||
}
|
||||
|
||||
if(ch0 != ch0_last){
|
||||
if((ch0_last >= (ch0+ch_data_limit)) || (ch0_last <= (ch0-ch_data_limit)) || g_tmd2755_status_param.log_first_evt == true){
|
||||
log("lux=%ld, ch0=%u, ch1=%u, ch0_last=%ld, (ch1*10000/ch0)=%ld, sf=%lld",
|
||||
lux, ch0, ch1, ch0_last, ch_temp, sf);
|
||||
}
|
||||
}
|
||||
ch0_last = ch0;
|
||||
|
||||
if (lux < 0) {
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> lux < 0, Use previous value.\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__);
|
||||
return chip->als_info.lux; /* use previous value */
|
||||
} else {
|
||||
lux = min(ALS_MAX_LUX_VAL, max(0, lux));
|
||||
}
|
||||
|
||||
/* Determine threshold for switching gains */
|
||||
low_thres = tmd2755_max_als_value(chip) / TMD2755_THRESHOLD_PERCENT;
|
||||
|
||||
/* clamp counts to prevent flip-flopping between gains */
|
||||
low_thres = clamp(low_thres, 0, TMD2755_AUTO_GAIN_CLAMP_CNT);
|
||||
|
||||
/* There is a case where one channel can saturate and the other channel can be below the clamping value. */
|
||||
/* This algorithm does not gracefully handle it. */
|
||||
if (!chip->params.als_auto_gain) { /* auto gain is off */
|
||||
if ((chip->als_info.ch0_raw <= TMD2755_MIN_ALS_VALUE) || (chip->als_info.ch1_raw <= TMD2755_MIN_ALS_VALUE)) {
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> Darkness entered: Channel count less than minimum ([%d || %d] <= %d).\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__,
|
||||
chip->als_info.ch0_raw, chip->als_info.ch1_raw, TMD2755_MIN_ALS_VALUE);
|
||||
} else if ((chip->als_info.ch0_raw >= chip->als_info.saturation) || (chip->als_info.ch1_raw >= chip->als_info.saturation)) {
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> Saturation occurred: Channel count exceeds maximum ([%d || %d] >= %d).\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__,
|
||||
chip->als_info.ch0_raw, chip->als_info.ch1_raw, chip->als_info.saturation);
|
||||
}
|
||||
} else {
|
||||
if (chip->als_info.ch0_raw < low_thres || chip->als_info.ch1_raw < low_thres) {
|
||||
if((chip->shadow[TMD2755_REG_CFG1] & TMD2755_MASK_AGAIN) != ALS_GAIN_REG_VAL_1024){
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> Autogain Incrementing, ch0:%d, ch1:%d, low_thres=%d\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN,
|
||||
__LINE__, chip->als_info.ch0_raw, chip->als_info.ch1_raw, low_thres);
|
||||
tmd2755_inc_gain(chip);
|
||||
}
|
||||
tmd2755_flush_als_regs(chip);
|
||||
} else if ((chip->als_info.ch0_raw >= chip->als_info.saturation) || (chip->als_info.ch1_raw >= chip->als_info.saturation) || chip->in_asat) {
|
||||
if ((chip->shadow[TMD2755_REG_CFG1] & TMD2755_MASK_AGAIN) != ALS_GAIN_REG_VAL_16) {
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> Autogain Decrementing, sat=%d, in_asat=%d \n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN,
|
||||
__LINE__, chip->als_info.saturation, chip->in_asat);
|
||||
tmd2755_dec_gain(chip);
|
||||
}
|
||||
tmd2755_flush_als_regs(chip);
|
||||
}
|
||||
}
|
||||
|
||||
chip->als_info.lux = lux;
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> Lux Calculation: %d, lux=%d\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__,
|
||||
lux, chip->als_info.lux);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* Utility Calls *
|
||||
*****************************************************************/
|
||||
int tmd2755_configure_als_mode(struct tmd2755_chip *chip, u8 state)
|
||||
{
|
||||
struct i2c_client *client = chip->client;
|
||||
u8 *sh = chip->shadow;
|
||||
|
||||
if (state) { /* Enable ALS */
|
||||
g_tmd2755_status_param.log_first_evt = true;
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> Enabling and Configuring ALS\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__);
|
||||
|
||||
chip->shadow[TMD2755_REG_ATIME] = chip->params.als_time;
|
||||
tmd2755_calc_counts_per_lux(chip);
|
||||
|
||||
/* only adjust als peristance */
|
||||
chip->shadow[TMD2755_REG_PERS] &= (~TMD2755_MASK_ALS_PERS);
|
||||
chip->shadow[TMD2755_REG_PERS] |= chip->params.persist.pers.apers;
|
||||
|
||||
tmd2755_flush_als_regs(chip);
|
||||
|
||||
/* AWTIME */
|
||||
ams_i2c_write(client, sh, TMD2755_REG_AWTIME, chip->params.als_wtime);
|
||||
|
||||
/* Enable ALS interrupt */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_INTENAB, TMD2755_AIEN, TMD2755_AIEN);
|
||||
/* When enabling ALS - AEN in Register 0x80, PWEN must be set to 1 if prox is enabled - See datasheet */
|
||||
/* As of release 1.9, PWEN is active when proximity is turned oa - see ams_tmd2755_prox.c filen */
|
||||
/* Also Power On */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_AEN | TMD2755_PON,
|
||||
TMD2755_AEN | TMD2755_PON);
|
||||
chip->als_enable = true;
|
||||
|
||||
/* Enable PWTIME */
|
||||
if(chip->prox_enable == true){
|
||||
log("pon, enable PWEN");
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_PWEN, TMD2755_PWEN);
|
||||
}
|
||||
} else { /* Disable ALS */
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> Disable ALS\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__);
|
||||
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_INTENAB, TMD2755_AIEN, 0);
|
||||
/* Cannot turn off PWEN, in case prox feature is still using it */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_AEN, 0);
|
||||
chip->als_enable = false;
|
||||
|
||||
*((__le16 *) &chip->shadow[TMD2755_REG_AILTL]) = cpu_to_le16(0);
|
||||
*((__le16 *) &chip->shadow[TMD2755_REG_AIHTL]) = cpu_to_le16(0);
|
||||
ams_i2c_reg_blk_write(chip->client, TMD2755_REG_AILTL, &chip->shadow[TMD2755_REG_AILTL],
|
||||
(TMD2755_REG_AIHTH - TMD2755_REG_AILTL) + 1);
|
||||
log("set hi/low threshold to 0");
|
||||
|
||||
/* Close PWTIME */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_PWEN, 0);
|
||||
|
||||
/* If Prox is not on, turn off chip */
|
||||
if (!(sh[TMD2755_REG_ENABLE] & TMD2755_EN_ALL)){
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_PON, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tmd2755_read_als(struct tmd2755_chip *chip)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ams_i2c_blk_read(chip->client, TMD2755_REG_ALSL, &chip->shadow[TMD2755_REG_ALSL], ALS_NUM_CH * ALS_CH_SIZE);
|
||||
|
||||
if (ret >= 0) {
|
||||
tmd2755_get_rawdata(chip);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int light_get_lux(int adc);
|
||||
void tmd2755_report_als(struct tmd2755_chip *chip)
|
||||
{
|
||||
int lux;
|
||||
int rc;
|
||||
static int last_lux = 0;
|
||||
#ifdef REMOVE_INPUT_DEVICE
|
||||
rc = tmd2755_get_lux(chip); /* always returns 0 */
|
||||
if (!rc) {
|
||||
lux = chip->als_info.lux;
|
||||
lux = light_get_lux(chip->als_info.lux);
|
||||
lsensor_report_lux(lux);
|
||||
if(g_tmd2755_status_param.log_first_evt == true){
|
||||
log("ALS lux First= %d (orig lux=%d)", lux, chip->als_info.lux);
|
||||
}else if(lux != last_lux){
|
||||
log("ALS lux = %d (orig lux=%d), last_lux=%d", lux, chip->als_info.lux, last_lux);
|
||||
}
|
||||
last_lux = lux;
|
||||
tmd2755_update_als_threshold(chip, TMD2755_ENABLE_OFF);
|
||||
} else {
|
||||
tmd2755_update_als_threshold(chip, TMD2755_ENABLE_ON);
|
||||
}
|
||||
|
||||
#else
|
||||
if (chip->als_idev) {
|
||||
rc = tmd2755_get_lux(chip); /* always returns 0 */
|
||||
if (!rc) {
|
||||
lux = chip->als_info.lux;
|
||||
input_report_abs(chip->als_idev, ABS_MISC, lux);
|
||||
input_sync(chip->als_idev);
|
||||
dbg("ALS lux = %d", lux);
|
||||
tmd2755_update_als_threshold(chip, TMD2755_ENABLE_OFF);
|
||||
} else
|
||||
tmd2755_update_als_threshold(chip, TMD2755_ENABLE_ON);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* sysfs utility functions *
|
||||
*****************************************************************/
|
||||
static ssize_t tmd2755_als_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
u8 idx, temp;
|
||||
int val;
|
||||
ssize_t ret = 0;
|
||||
if(chip == NULL){
|
||||
log("chip null");
|
||||
return ret;
|
||||
}else{
|
||||
log("chip on");
|
||||
}
|
||||
|
||||
for (idx = 0; idx < tmd2755_als_attrs_size; idx++) {
|
||||
if (!strncmp(tmd2755_als_attrs[idx].attr.name, attr->attr.name, strlen(attr->attr.name))) {
|
||||
if(NULL == chip){
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> lock = NULL\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__);
|
||||
return ret;
|
||||
}else{
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
}
|
||||
switch (idx) {
|
||||
case ALS_ATIME_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d (~%d us)\n", chip->shadow[TMD2755_REG_ATIME],
|
||||
(chip->shadow[TMD2755_REG_ATIME]+1)*INTEGRATION_CYCLE);
|
||||
break;
|
||||
case ALS_AWTIME_ATTR:
|
||||
temp = (chip->shadow[TMD2755_REG_CFG0] & TMD2755_MASK_AWLONG) >> TMD2755_SHIFT_AWLONG;
|
||||
/* if long bit is set, multiply by 12 */
|
||||
val = (temp ? AWTIME_LONG_FACTOR : 1);
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d (~%d us %s)\n", chip->shadow[TMD2755_REG_AWTIME],
|
||||
(chip->shadow[TMD2755_REG_AWTIME]+1)*val*INTEGRATION_CYCLE,
|
||||
val == AWTIME_LONG_FACTOR ? "<awlong bit set:12x>" : "<>");
|
||||
break;
|
||||
case ALS_AWLONG_ATTR:
|
||||
temp = (chip->shadow[TMD2755_REG_CFG0] & TMD2755_MASK_AWLONG) >> TMD2755_SHIFT_AWLONG;
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", temp);
|
||||
break;
|
||||
case ALS_LUX_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->als_info.lux);
|
||||
break;
|
||||
case ALS_GAIN_ATTR:
|
||||
if(NULL == chip){
|
||||
log("chip null1");
|
||||
return ret;
|
||||
}
|
||||
|
||||
log("get als_gain params, 0x%x", chip->params.als_gain);
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d (%dx)\n", chip->params.als_gain, tmd2755_convert_again(chip->params.als_gain));
|
||||
break;
|
||||
case ALS_CPL_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d (atime_us*again/DGF)\n", chip->als_info.counts_per_lux);
|
||||
break;
|
||||
case ALS_CH0_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->als_info.ch0_raw);
|
||||
break;
|
||||
case ALS_CH1_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->als_info.ch1_raw);
|
||||
break;
|
||||
case ALS_THRESH_DELTAP_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.als_deltaP);
|
||||
break;
|
||||
case ALS_AUTO_GAIN_ATTR:
|
||||
ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->params.als_auto_gain);
|
||||
break;
|
||||
case ALS_LUX_COEFF_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "DGF = %d\nSCALE FACTOR = %d\nCOEFF_A = %d/1000\nCOEFF_B = %d\nCOEFF_C = %d/1000\nCOEFF_D = %d\n",
|
||||
chip->params.dgf, chip->params.coef_scale, chip->params.ch0_coef0, chip->params.ch1_coef0,
|
||||
chip->params.ch0_coef1, chip->params.ch1_coef1);
|
||||
break;
|
||||
case ALS_ENABLE_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->als_enable);
|
||||
break;
|
||||
case ALS_PERSIST_ATTR: /* see datasheet for pattern */
|
||||
if (chip->params.persist.pers.apers >= 4)
|
||||
val = 10 + ((chip->params.persist.pers.apers - 5) * 5);
|
||||
else
|
||||
val = chip->params.persist.pers.apers;
|
||||
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d (%d consecutive OOR)\n", chip->params.persist.pers.apers, val);
|
||||
break;
|
||||
case ALS_SATURATION_ATTR:
|
||||
/* Determine if ALS is in saturation */
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%s\n", (chip->in_asat ? "ALS_Saturation" : "Normal_Operation"));
|
||||
break;
|
||||
case ALS_ADC_ATTR:
|
||||
tmd2755_get_lux(chip);
|
||||
ret = scnprintf(buf, PAGE_SIZE, "lux: %d, ch0: %d, ch1:%d\n", chip->als_info.lux,
|
||||
chip->als_info.ch0_raw, chip->als_info.ch1_raw);
|
||||
break;
|
||||
default:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "not found\n");
|
||||
break;
|
||||
}
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* sysfs utility functions *
|
||||
*****************************************************************/
|
||||
static ssize_t tmd2755_als_atime_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_atime_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long atime;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &atime);
|
||||
if (rc || (atime > ALS_TIME_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
log("atime value = %lu", atime);
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_ATIME, atime);
|
||||
chip->params.als_time = chip->shadow[TMD2755_REG_ATIME];
|
||||
tmd2755_calc_counts_per_lux(chip);
|
||||
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_wtime_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_wtime_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long awtime;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &awtime);
|
||||
if (rc || (awtime > ALS_WTIME_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_AWTIME, awtime);
|
||||
chip->params.als_wtime = chip->shadow[TMD2755_REG_AWTIME];
|
||||
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_wlong_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_wlong_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long awlong;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &awlong);
|
||||
if (rc || (awlong > ALS_WLONG_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_CFG0, TMD2755_MASK_AWLONG, (u8)(awlong << TMD2755_SHIFT_AWLONG));
|
||||
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_lux_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
|
||||
tmd2755_read_als(chip);
|
||||
tmd2755_get_lux(chip);
|
||||
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_gain_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_gain_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long again;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &again);
|
||||
if (rc || ((again != ALS_GAIN_MIN) && (again != ALS_GAIN_MAX) && (again != ALS_GAIN_DEFAULT)))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_CFG1, TMD2755_MASK_AGAIN, (u8)(again << TMD2755_SHIFT_AGAIN));
|
||||
chip->params.als_gain = (u8)again;
|
||||
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_cpl_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_ch0_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_ch1_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_deltaP_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_deltaP_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long deltaP;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &deltaP);
|
||||
if (rc || (deltaP > ALS_DELTA_P_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
chip->params.als_deltaP = deltaP;
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_auto_gain_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
static ssize_t tmd2755_auto_gain_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long auto_gain;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, 10, &auto_gain);
|
||||
/* if error on conversion, value greater than 1(true) */
|
||||
if (rc || (auto_gain > 1))
|
||||
return -EINVAL;
|
||||
/* if its the same, no need to do any work. */
|
||||
if (auto_gain == chip->params.als_auto_gain)
|
||||
return size;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
chip->params.als_auto_gain = auto_gain;
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_lux_coef_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
static ssize_t tmd2755_lux_coef_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
u32 dgf, ch0_coeff_0, ch1_coeff_0, ch0_coeff_1, ch1_coeff_1, coeff_scale;
|
||||
|
||||
if (sscanf(buf, "%10d,%10d,%10d,%10d,%10d,%10d", &dgf, &coeff_scale, &ch0_coeff_0, &ch1_coeff_0, &ch0_coeff_1, &ch1_coeff_1) != 6)
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
chip->params.dgf = dgf;
|
||||
chip->params.coef_scale = coeff_scale;
|
||||
chip->params.ch0_coef0 = ch0_coeff_0;
|
||||
chip->params.ch0_coef1 = ch0_coeff_1;
|
||||
chip->params.ch1_coef0 = ch1_coeff_0;
|
||||
chip->params.ch1_coef1 = ch1_coeff_1;
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long enable;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, 10, &enable);
|
||||
/* if error on conversion, or value greater than 1(true) */
|
||||
if (rc || (enable > 1))
|
||||
return -EINVAL;
|
||||
/* if its the same, no need to do any work. */
|
||||
if (enable == chip->als_enable)
|
||||
return size;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
|
||||
if (enable)
|
||||
tmd2755_configure_als_mode(chip, TMD2755_FEATURE_ON);
|
||||
else /* disable */
|
||||
tmd2755_configure_als_mode(chip, TMD2755_FEATURE_OFF);
|
||||
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_persist_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_persist_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long persist;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &persist);
|
||||
if (rc || (persist > ALS_PERSIST_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
ams_i2c_modify(chip->client, chip->shadow,
|
||||
TMD2755_REG_PERS, TMD2755_MASK_ALS_PERS, persist << TMD2755_SHIFT_ALS_PERS);
|
||||
chip->params.persist.persistance = chip->shadow[TMD2755_REG_PERS];
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_sat_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
static ssize_t tmd2755_als_adc_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_als_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_als_adc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
u32 ch0, ch1;
|
||||
|
||||
if (sscanf(buf, "%10d,%10d", &ch0, &ch1) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
ALS_OFF();
|
||||
chip->als_info.ch0_raw = ch0;
|
||||
chip->als_info.ch1_raw = ch1;
|
||||
ALS_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
struct device_attribute tmd2755_als_attrs[] = {
|
||||
__ATTR(als_atime, 0664, tmd2755_als_atime_show, tmd2755_als_atime_store),
|
||||
__ATTR(als_wtime, 0664, tmd2755_als_wtime_show, tmd2755_als_wtime_store),
|
||||
__ATTR(als_wlong, 0664, tmd2755_als_wlong_show, tmd2755_als_wlong_store),
|
||||
__ATTR(als_lux, 0444, tmd2755_als_lux_show, NULL),
|
||||
__ATTR(als_gain, 0664, tmd2755_als_gain_show, tmd2755_als_gain_store),
|
||||
__ATTR(als_cpl, 0444, tmd2755_als_cpl_show, NULL),
|
||||
__ATTR(als_ch0, 0444, tmd2755_als_ch0_show, NULL),
|
||||
__ATTR(als_ch1, 0444, tmd2755_als_ch1_show, NULL),
|
||||
__ATTR(als_thresh_deltaP, 0664, tmd2755_als_deltaP_show, tmd2755_als_deltaP_store),
|
||||
__ATTR(als_auto_gain, 0664, tmd2755_auto_gain_enable_show, tmd2755_auto_gain_enable_store),
|
||||
__ATTR(als_lux_coef, 0664, tmd2755_lux_coef_show, tmd2755_lux_coef_store),
|
||||
__ATTR(als_enable, 0664, tmd2755_als_enable_show, tmd2755_als_enable_store),
|
||||
__ATTR(als_persist, 0664, tmd2755_als_persist_show, tmd2755_als_persist_store),
|
||||
__ATTR(als_sat, 0444, tmd2755_als_sat_show, NULL),
|
||||
__ATTR(regs, 0644, tmd2755_registers_show, tmd2755_registers_store),
|
||||
__ATTR(als_adc, 0664, tmd2755_als_adc_show, tmd2755_als_adc_store),
|
||||
};
|
||||
|
||||
int tmd2755_als_attrs_size = ARRAY_SIZE(tmd2755_als_attrs);
|
@ -0,0 +1,187 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __AMS_TMD2755_ALS_H__
|
||||
#define __AMS_TMD2755_ALS_H__
|
||||
|
||||
/* Debug flags for ALS specific */
|
||||
// #define DEBUG_LUX
|
||||
|
||||
#define ALS_MAX_LUX_VAL (65535) /* (USHRT_MAX) */
|
||||
#define ALS_FULL_SCALE_CNT (ALS_MAX_LUX_VAL)
|
||||
#define ALS_ATIME_FOR_MAX_CNT (0x3F) /* this is the first atime value that maxes out the counts - full scale */
|
||||
#define ALS_ATIME_INCREMENT_CNT (1024) /* each increase in atime, causes, this increase in full scale count */
|
||||
|
||||
#define ALS_GAIN_REG_VAL_16 (5) /* Bit value in register */
|
||||
#define ALS_GAIN_16 (16) /* magnitude of gain */
|
||||
#define ALS_GAIN_REG_VAL_128 (8) /* Bit value in register */
|
||||
#define ALS_GAIN_128 (128) /* magnitude of gain */
|
||||
#define ALS_GAIN_REG_VAL_1024 (11)
|
||||
#define ALS_GAIN_1024 (1024)
|
||||
|
||||
#define ALS_COEFF_SCALE_FACTOR (1000) /* retrieved from DTS */
|
||||
|
||||
#define AWTIME_LONG_FACTOR (12)
|
||||
|
||||
/* This only works if the channel data is stored in consecutive registers */
|
||||
#define ALS_NUM_CH (2) /* number of channels performing ALS */
|
||||
#define ALS_CH_SIZE (sizeof(u8) * 2) /* 16 bit registers */
|
||||
|
||||
#define TMD2755_MAX_ALS_VALUE (0xFFFF) /* 16 bit */
|
||||
#define TMD2755_MIN_ALS_VALUE (10)
|
||||
|
||||
#define TMD2755_THRESHOLD_PERCENT (200) /* equates to 0.5% */
|
||||
|
||||
#define TMD2755_SATURATION_THRESHOLD (9) /* 90% of max ALS count */
|
||||
|
||||
#define TMD2755_CH0_MAXIMUM (65535)
|
||||
|
||||
#define TMD2755_AUTO_GAIN_CLAMP_CNT (8)
|
||||
|
||||
#define TMD2755_SHIFT_MULT_BY_1024 (10)
|
||||
|
||||
/* fraction out of 10 */
|
||||
#define TENTH_FRACTION_OF_VAL(v, x) ({ \
|
||||
int __frac = v; \
|
||||
if (((x) > 0) && ((x) < 10)) \
|
||||
__frac = (__frac*(x)) / 10 ; \
|
||||
__frac; \
|
||||
})
|
||||
|
||||
#define ALS_ON() do { \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_ENABLE, TMD2755_AEN, TMD2755_AEN); \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_INTENAB, TMD2755_AIEN, TMD2755_AIEN); \
|
||||
chip->als_enable = true; \
|
||||
} while (0)
|
||||
|
||||
#define ALS_OFF() do { \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_INTENAB, TMD2755_AIEN, 0); \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_ENABLE, TMD2755_AEN, 0); \
|
||||
chip->als_enable = false; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Min/Max/Default Values for parameters */
|
||||
/**********************************************************************************/
|
||||
#define ALS_PERSIST_MIN (0)
|
||||
#define ALS_PERSIST_MAX (0x0F)
|
||||
#define ALS_PERSIST_DEFAULT (2)
|
||||
|
||||
#define ALS_GAIN_MIN (5) /* 16x */
|
||||
#define ALS_GAIN_MAX (11) /* 1024x - only 5, 8 and 11 are acceptable values */
|
||||
#define ALS_GAIN_DEFAULT (8) /* 128x */
|
||||
|
||||
#define ALS_AUTO_GAIN_MIN (0)
|
||||
#define ALS_AUTO_GAIN_MAX (1)
|
||||
#define ALS_AUTO_GAIN_DEFAULT (1)
|
||||
|
||||
/* Variation allowed in ALS to cause interrupt */
|
||||
#define ALS_DELTA_P_MIN (0)
|
||||
#define ALS_DELTA_P_MAX (20)
|
||||
#define ALS_DELTA_P_DEFAULT (10)
|
||||
|
||||
#define ALS_TIME_MIN (0)
|
||||
#define ALS_TIME_MAX (0xFF)
|
||||
#define ALS_TIME_DEFAULT (0x3F)
|
||||
|
||||
#define ALS_WTIME_MIN (0)
|
||||
#define ALS_WTIME_MAX (0xFF)
|
||||
#define ALS_WTIME_DEFAULT (0)
|
||||
|
||||
#define ALS_WLONG_MIN (0)
|
||||
#define ALS_WLONG_MAX (1)
|
||||
#define ALS_WLONG_DEFAULT (0)
|
||||
|
||||
|
||||
|
||||
/* coefficient limits are assumed to be scaled */
|
||||
/* Coefficients vary so placing a limit on them may be difficult */
|
||||
/* to validate - While these values are here, the actual values */
|
||||
/* read in from the DT overlay are not boundary checked */
|
||||
|
||||
/* Device & Glass Factor */
|
||||
#define ALS_DGF_MIN (0)
|
||||
#define ALS_DGF_MAX (200)
|
||||
#define ALS_DGF_DEFAULT (123)
|
||||
|
||||
/* Coeff A */
|
||||
#define ALS_CH0_COEFF0_MIN (0)
|
||||
#define ALS_CH0_COEFF0_MAX (1000)
|
||||
#define ALS_CH0_COEFF0_DEFAULT (1000)
|
||||
|
||||
/* Coeff B */
|
||||
#define ALS_CH1_COEFF0_MIN (0)
|
||||
#define ALS_CH1_COEFF0_MAX (1000)
|
||||
#define ALS_CH1_COEFF0_DEFAULT (1427)
|
||||
|
||||
/* Coeff C */
|
||||
#define ALS_CH0_COEFF1_MIN (0)
|
||||
#define ALS_CH0_COEFF1_MAX (1000)
|
||||
#define ALS_CH0_COEFF1_DEFAULT (849)
|
||||
|
||||
/* Coeff D */
|
||||
#define ALS_CH1_COEFF1_MIN (0)
|
||||
#define ALS_CH1_COEFF1_MAX (1000)
|
||||
#define ALS_CH1_COEFF1_DEFAULT (834)
|
||||
|
||||
#define ALS_COEFF_SCALE_MIN (1)
|
||||
#define ALS_COEFF_SCALE_MAX (1000)
|
||||
#define ALS_COEFF_SCALE_DEFAULT (1000)
|
||||
|
||||
/*
|
||||
* This must match the order of ATTR defined in
|
||||
* struct device_attribute tmd2755_als_attrs[]
|
||||
* in ams_tmd2755_als.c
|
||||
*/
|
||||
enum tmd2755_als_attrs {
|
||||
ALS_ATIME_ATTR,
|
||||
ALS_AWTIME_ATTR,
|
||||
ALS_AWLONG_ATTR,
|
||||
ALS_LUX_ATTR,
|
||||
ALS_GAIN_ATTR,
|
||||
ALS_CPL_ATTR,
|
||||
ALS_CH0_ATTR,
|
||||
ALS_CH1_ATTR,
|
||||
ALS_THRESH_DELTAP_ATTR,
|
||||
ALS_AUTO_GAIN_ATTR,
|
||||
ALS_LUX_COEFF_ATTR,
|
||||
ALS_ENABLE_ATTR,
|
||||
ALS_PERSIST_ATTR,
|
||||
ALS_SATURATION_ATTR,
|
||||
ALS_ADC_ATTR,
|
||||
};
|
||||
|
||||
extern struct device_attribute tmd2755_als_attrs[];
|
||||
extern int tmd2755_als_attrs_size;
|
||||
|
||||
|
||||
int tmd2755_configure_als_mode(struct tmd2755_chip *chip, u8 state);
|
||||
int tmd2755_read_als(struct tmd2755_chip *chip);
|
||||
void tmd2755_report_als(struct tmd2755_chip *chip);
|
||||
extern ssize_t tmd2755_registers_show(struct device *dev, struct device_attribute *attr, char *buf);
|
||||
extern ssize_t tmd2755_registers_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size);
|
||||
extern void light_polling_work_assing(void);
|
||||
#endif // __AMS_TMD2755_ALS_H__
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is meant to be used as defensive programming to protect invalid
|
||||
* values passed in via the DTS overlay. Only include this file once in the entire
|
||||
* project. Include it in the source file that reads the DTS database.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CHECK_LIMITS(val, y) ({ \
|
||||
s32 ret_val = val; \
|
||||
if ((val < y.min) || (val > y.max)) { \
|
||||
ret_val = y.def; \
|
||||
printk(KERN_WARNING "WARNING: Default parameter value being used: %s (attempted val=%d min=%d max=%d def=%d)\n", y.name, val, y.min, y.max, y.def); \
|
||||
} \
|
||||
ret_val; \
|
||||
})
|
||||
|
||||
enum dts_parameters {
|
||||
PROX_PERIST_CFG,
|
||||
PROX_THRESH_MIN_CFG,
|
||||
PROX_THRESH_MAX_CFG,
|
||||
PROX_PULSE_CNT_CFG,
|
||||
PROX_APC_CFG,
|
||||
PROX_PULSE_LEN_CFG,
|
||||
PROX_GAIN_1_CFG,
|
||||
PROX_GAIN_2_CFG,
|
||||
PROX_OFFSET_CFG,
|
||||
PROX_DRIVE_CFG,
|
||||
PROX_TIME_CFG,
|
||||
PROX_WTIME_CFG,
|
||||
/*********************/
|
||||
ALS_PERSIST_CFG,
|
||||
ALS_GAIN_CFG,
|
||||
ALS_AUTO_GAIN_CFG,
|
||||
ALS_DELTA_P_CFG,
|
||||
ALS_TIME_CFG,
|
||||
ALS_WTIME_CFG,
|
||||
ALS_DGF_CFG,
|
||||
ALS_CH0_COEFF0_CFG,
|
||||
ALS_CH1_COEFF0_CFG,
|
||||
ALS_CH0_COEFF1_CFG,
|
||||
ALS_CH1_COEFF1_CFG,
|
||||
ALS_COEFF_SCALE_CFG,
|
||||
};
|
||||
|
||||
static struct {
|
||||
s32 min;
|
||||
s32 max;
|
||||
s32 def;
|
||||
char *name;
|
||||
} tmd2755_cfg_limits[] = {
|
||||
/********************************** PROX *******************************************************/
|
||||
[PROX_PERIST_CFG] = {PROX_PERSIST_MIN, PROX_PERSIST_MAX, PROX_PERSIST_DEFAULT, "ppersist"},
|
||||
[PROX_THRESH_MIN_CFG] = {PROX_THRESH_MIN, PROX_THRESH_MAX, PROX_THRESH_DEFAULT, "pmin_thresh"},
|
||||
[PROX_THRESH_MAX_CFG] = {PROX_THRESH_MIN, PROX_THRESH_MAX, PROX_THRESH_DEFAULT, "pmax_thresh"},
|
||||
[PROX_PULSE_CNT_CFG] = {PROX_PULSE_CNT_MIN, PROX_PULSE_CNT_MAX, PROX_PULSE_CNT_DEFAULT, "ppulse_cnt"},
|
||||
[PROX_APC_CFG] = {PROX_APC_MIN, PROX_APC_MAX, PROX_APC_DEFAULT, "papc"},
|
||||
[PROX_PULSE_LEN_CFG] = {PROX_PULSE_LEN_MIN, PROX_PULSE_LEN_MAX, PROX_PULSE_LEN_DEFAULT, "ppulse_len"},
|
||||
[PROX_GAIN_1_CFG] = {PROX_GAIN_MIN, PROX_GAIN_MAX, PROX_GAIN_DEFAULT, "pgain_1"},
|
||||
[PROX_GAIN_2_CFG] = {PROX_GAIN_MIN, PROX_GAIN_MAX, PROX_GAIN_DEFAULT, "pgain_2"}, /* cannot be 2 */
|
||||
[PROX_OFFSET_CFG] = {PROX_OFFSET_MIN, PROX_OFFSET_MAX, PROX_OFFSET_DEFAULT, "poffset"},
|
||||
[PROX_DRIVE_CFG] = {PROX_DRIVE_MIN, PROX_DRIVE_MAX, PROX_DRIVE_DEFAULT, "pdrive"},
|
||||
[PROX_TIME_CFG] = {PROX_TIME_MIN, PROX_TIME_MAX, PROX_TIME_DEFAULT, "ptime"},
|
||||
[PROX_WTIME_CFG] = {PROX_WTIME_MIN, PROX_WTIME_MAX, PROX_WTIME_DEFAULT, "pwtime"},
|
||||
/****************************************************************************************************/
|
||||
/********************************** ALS *******************************************************/
|
||||
[ALS_PERSIST_CFG] = {ALS_PERSIST_MIN, ALS_PERSIST_MAX, ALS_PERSIST_DEFAULT, "apers"},
|
||||
[ALS_GAIN_CFG] = {ALS_GAIN_MIN, ALS_GAIN_MAX, ALS_GAIN_DEFAULT, "als_gain"}, /* 5, 8 or 11 */
|
||||
[ALS_AUTO_GAIN_CFG] = {ALS_AUTO_GAIN_MIN, ALS_AUTO_GAIN_MAX, ALS_AUTO_GAIN_DEFAULT, "als_auto_gain"},
|
||||
[ALS_DELTA_P_CFG] = {ALS_DELTA_P_MIN, ALS_DELTA_P_MAX, ALS_DELTA_P_DEFAULT, "als_deltap"},
|
||||
[ALS_TIME_CFG] = {ALS_TIME_MIN, ALS_TIME_MAX, ALS_TIME_DEFAULT, "als_time"},
|
||||
[ALS_WTIME_CFG] = {ALS_WTIME_MIN, ALS_WTIME_MAX, ALS_WTIME_DEFAULT, "als_wtime"},
|
||||
[ALS_DGF_CFG] = {ALS_DGF_MIN, ALS_DGF_MAX, ALS_DGF_DEFAULT, "dgf"},
|
||||
[ALS_CH0_COEFF0_CFG] = {ALS_CH0_COEFF0_MIN, ALS_CH0_COEFF0_MAX, ALS_CH0_COEFF0_DEFAULT, "ch0_coef0"},
|
||||
[ALS_CH1_COEFF0_CFG] = {ALS_CH1_COEFF0_MIN, ALS_CH1_COEFF0_MAX, ALS_CH1_COEFF0_DEFAULT, "ch1_coef0"},
|
||||
[ALS_CH0_COEFF1_CFG] = {ALS_CH0_COEFF1_MIN, ALS_CH0_COEFF1_MAX, ALS_CH0_COEFF1_DEFAULT, "ch0_coef1"},
|
||||
[ALS_CH1_COEFF1_CFG] = {ALS_CH1_COEFF1_MIN, ALS_CH1_COEFF1_MAX, ALS_CH1_COEFF1_DEFAULT, "ch1_coef1"},
|
||||
[ALS_COEFF_SCALE_CFG] = {ALS_COEFF_SCALE_MIN, ALS_COEFF_SCALE_MAX, ALS_COEFF_SCALE_DEFAULT, "coef_scale"},
|
||||
/****************************************************************************************************/
|
||||
};
|
@ -0,0 +1,863 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*! \file
|
||||
* \brief Device driver for monitoring ambient light intensity in (lux)
|
||||
* proximity detection (prox) functionality within the
|
||||
* AMS TMD2755 family of devices.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "ams_tmd2755.h"
|
||||
#include "ams_tmd2755_prox.h"
|
||||
#include "ams_i2c.h"
|
||||
|
||||
/******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_tmd2755"
|
||||
#define SENSOR_TYPE_NAME "ALSPS"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_GPIO_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s]"fmt,MODULE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
extern struct tmd2755_chip *g_tmd2755_chip;
|
||||
|
||||
/*********************************/
|
||||
|
||||
/*****************************************************************
|
||||
* Local globals for prox module *
|
||||
*****************************************************************/
|
||||
|
||||
/*****************************************************************
|
||||
* Utility Calls *
|
||||
*****************************************************************/
|
||||
void tmd2755_read_poffset(struct tmd2755_chip *chip){
|
||||
ams_i2c_blk_read(chip->client, TMD2755_REG_POFFSET_L, &chip->shadow[TMD2755_REG_POFFSET_L], 2);
|
||||
chip->params.poffset = chip->shadow[TMD2755_REG_POFFSET_L];
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> Optical Xtalk calib complete(poffsetl=%d, poffseth=%d, ore=%d, ore_en=%d)\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, chip->params.poffset,
|
||||
chip->shadow[TMD2755_REG_POFFSET_H] & TMD2755_MASK_POFFSET_H, chip->shadow[TMD2755_REG_CALIB_OFF] & TMD2755_MASK_ORE,
|
||||
(chip->shadow[TMD2755_REG_CALIB_OFF] & TMD2755_MASK_ENABLE_ORE) > TMD2755_SHIFT_ENABLE_ORE);
|
||||
|
||||
if (chip->shadow[TMD2755_REG_POFFSET_H] & TMD2755_MASK_POFFSET_H)
|
||||
chip->params.poffset *= -1;
|
||||
}
|
||||
EXPORT_SYMBOL(tmd2755_read_poffset);
|
||||
|
||||
static void tmd2755_write_poffset(struct tmd2755_chip *chip){
|
||||
u8 *sh = chip->shadow;
|
||||
if(chip->params.poffset >= 0){
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_POFFSET_H, 0);
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_POFFSET_L, chip->params.poffset);
|
||||
log("wrote offset = %d", chip->params.poffset);
|
||||
}else{
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_POFFSET_H, 1);
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_POFFSET_L, -chip->params.poffset);
|
||||
log("wrote -offset = %d", chip->params.poffset);
|
||||
}
|
||||
log("set offset = %d", chip->params.poffset);
|
||||
}
|
||||
|
||||
void tmd2755_read_prox(struct tmd2755_chip *chip)
|
||||
{
|
||||
/* Read low and high bytes - 14 bits */
|
||||
ams_i2c_blk_read(chip->client, TMD2755_REG_PDATAL, &chip->shadow[TMD2755_REG_PDATAL], sizeof(chip->prox_info.raw));
|
||||
if (chip->params.prox_apc == 0) {
|
||||
chip->prox_info.raw = le16_to_cpu(*((const __le16 *)&chip->shadow[TMD2755_REG_PDATAL]));
|
||||
}else{
|
||||
//8bit pdata
|
||||
chip->prox_info.raw = chip->shadow[TMD2755_REG_PDATAL];
|
||||
}
|
||||
|
||||
tmd2755_read_poffset(chip);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void tmd2755_get_prox(struct tmd2755_chip *chip)
|
||||
{
|
||||
u8 *sh = chip->shadow;
|
||||
|
||||
//#if defined(DEBUG_PROX_FEATURE)
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> \t\tcurrent state: %s Raw: %d Min Thresh: %d Max Thresh:%d, offset =%d\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__,
|
||||
chip->prox_info.detected ? "<Detect>" : "<Release>", chip->prox_info.raw,
|
||||
le16_to_cpu(*((const __le16 *)&sh[TMD2755_REG_PILTL])), le16_to_cpu(*((const __le16
|
||||
*)&sh[TMD2755_REG_PIHTL])), chip->params.poffset);
|
||||
//#endif
|
||||
dbg("threshold %d, %d", chip->params.prox_thresh_min, chip->params.prox_thresh_max);
|
||||
dbg("chip->prox_info.detected=%d, chip->prox_info.raw=%d", chip->prox_info.detected, chip->prox_info.raw);
|
||||
if (chip->prox_info.raw >= chip->params.prox_thresh_max) {
|
||||
chip->prox_info.detected = true;
|
||||
log("new state: <Detect>, New Threshold limits = [%d, %d], offset=%d",
|
||||
chip->params.prox_thresh_min, PROX_THRESH_MAX, chip->params.poffset);
|
||||
/*If proximity is detected, set the lower limit to find */
|
||||
/* proximity release and set the higher limit to avoid */
|
||||
/* repeated interrupts. */
|
||||
if (chip->params.prox_apc == 0) {
|
||||
// apc --> 0 means APC is ENABLED
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PILTL,
|
||||
(chip->params.prox_thresh_min & TMD2755_MASK_PILTL));
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PILTH,
|
||||
((chip->params.prox_thresh_min >> 8) & TMD2755_MASK_PILTH));
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PIHTL,
|
||||
(PROX_THRESH_MAX & TMD2755_MASK_PIHTL));
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PIHTH,
|
||||
((PROX_THRESH_MAX >> 8) & TMD2755_MASK_PIHTH));
|
||||
} else {
|
||||
// apc --> 1 means APC is DISABLED
|
||||
// The PIxTH register is ignored and
|
||||
// and the PIxTL is compared to the upper 8 bits of pdata
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PILTL,
|
||||
((chip->params.prox_thresh_min >> 6) & TMD2755_MASK_PIHTL));
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PILTH, 0);
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PIHTL,
|
||||
((PROX_THRESH_MAX >> 6) & 0xFF));
|
||||
ams_i2c_write(chip->client, sh, TMD2755_REG_PIHTH, 0);
|
||||
}
|
||||
} else if (chip->prox_info.raw <= chip->params.prox_thresh_min) {
|
||||
chip->prox_info.detected = false;
|
||||
log("new state: <Release>, offset=%d", chip->params.poffset);
|
||||
|
||||
/* If proximity is released, set the higher limit to find */
|
||||
/* proximity and set the lower limit to avoid repeated interrupts */
|
||||
/* This is same as the init state */
|
||||
tmd2755_init_prox_mode(chip);
|
||||
}else{
|
||||
log("Lose condition, raw=%d, min=%d, max=%d", chip->prox_info.raw,
|
||||
chip->params.prox_thresh_min, chip->params.prox_thresh_max);
|
||||
}
|
||||
//Since chip may send two times INT for near case,
|
||||
//clear psensor int flag again after set new threshold
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_STATUS,
|
||||
TMD2755_INT_ST_PRX_IRQ, TMD2755_INT_ST_PRX_IRQ);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Value Meaning
|
||||
* 0. Prox release event
|
||||
* 1. Prox detect event
|
||||
* 2. Prox saturation event
|
||||
*/
|
||||
void tmd2755_prox_report_inp_event(struct tmd2755_chip *chip, int value)
|
||||
{
|
||||
#ifdef REMOVE_INPUT_DEVICE
|
||||
proximity_work(value? ALSPS_INT_PS_CLOSE : ALSPS_INT_PS_AWAY);
|
||||
#else
|
||||
if (chip->prox_idev) {
|
||||
input_report_abs(chip->prox_idev, ABS_DISTANCE, value);
|
||||
input_sync(chip->prox_idev);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void tmd2755_process_prox_irq(struct tmd2755_chip *chip)
|
||||
{
|
||||
tmd2755_read_prox(chip);
|
||||
tmd2755_get_prox(chip);
|
||||
tmd2755_prox_report_inp_event(chip, chip->prox_info.detected ? 1 : 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void tmd2755_process_saturation_event(struct tmd2755_chip *chip)
|
||||
{
|
||||
tmd2755_prox_report_inp_event(chip, PROX_SAT_EVENT);
|
||||
|
||||
/* Disable PSAT interrupt otherwise the processor will be over-burdened processing */
|
||||
/* saturation interrupts */
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_INTENAB, TMD2755_PSIEN, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void tmd2755_init_prox_mode(struct tmd2755_chip *chip)
|
||||
{
|
||||
/* Init Low threshold to 0 - Only looking for Detect events after init */
|
||||
log("Setting Initial Thresholds = [%d, %d], (low=%d), offset=%d", MIN_PROX_THRESHOLD,
|
||||
chip->params.prox_thresh_max, chip->params.prox_thresh_min, chip->params.poffset);
|
||||
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PILTL, MIN_PROX_THRESHOLD);
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PILTH, MIN_PROX_THRESHOLD);
|
||||
chip->prox_info.raw = 0;
|
||||
|
||||
if (chip->params.prox_apc == PROX_APC_ENABLED) {
|
||||
// apc == 0 means APC is ENABLED
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTL, (chip->params.prox_thresh_max & 0xFF));
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTH, ((chip->params.prox_thresh_max >> 8) & TMD2755_MASK_PIHTH));
|
||||
} else {
|
||||
// apc == 1 means APC is DISABLED, only 8 MSB of PITH are used - threshold is only 14 bit number (i.e. right shift 6)
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTL, ((chip->params.prox_thresh_max >> 6) & 0xFF));
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTH, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Enable PSAT interrupt during init or after release event */
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_INTENAB, TMD2755_PSIEN, TMD2755_PSIEN);
|
||||
return;
|
||||
}
|
||||
|
||||
int tmd2755_offset_calibration(struct tmd2755_chip *chip)
|
||||
{
|
||||
u8 *sh = chip->shadow;
|
||||
u8 saveenab, saveint;
|
||||
int ret;
|
||||
unsigned long wt;
|
||||
static int time=1;
|
||||
/* clean up the sync mechanism between here and ISR */
|
||||
reinit_completion(&(chip->calibration_done));
|
||||
|
||||
/* save PEN state */
|
||||
ams_i2c_read(chip->client, TMD2755_REG_ENABLE, &saveenab);
|
||||
|
||||
/* save prox intr state */
|
||||
ams_i2c_read(chip->client, TMD2755_REG_INTENAB, &saveint);
|
||||
|
||||
/* turn on power, disable prox */
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_ENABLE, TMD2755_PEN | TMD2755_PON, TMD2755_PON);
|
||||
|
||||
/* enable calib intr, disable prox intr */
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_INTENAB, TMD2755_PIEN | TMD2755_CIEN, TMD2755_CIEN);
|
||||
|
||||
/*
|
||||
** Prox Offset calibration
|
||||
** binsrch_target (15 counts)
|
||||
** prox averaging (2 reading window)
|
||||
** prox_auto_offset_adjust
|
||||
*/
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_CALIBCFG,
|
||||
TMD2755_MASK_BINSRCH_TARGET | TMD2755_MASK_PROX_AUTO_OFFSET_ADJUST | TMD2755_MASK_PROX_DATA_AVG,
|
||||
(PROX_BINSRCH_TARGET_VALUE << TMD2755_SHIFT_BINSRCH_TARGET) | (PROX_AUTO_OFFSET_ADJ_VAL << TMD2755_SHIFT_PROX_AUTO_OFFSET_ADJUST) |
|
||||
(PROX_AVG_VAL << TMD2755_SHIFT_PROX_DATA_AVG));
|
||||
/*
|
||||
** Calibration Offset
|
||||
** enable offset range extension
|
||||
** set ORE to PROX_ORE_VAL
|
||||
*/
|
||||
/*
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_CALIB_OFF,
|
||||
TMD2755_MASK_ENABLE_ORE | TMD2755_MASK_ORE,
|
||||
(PROX_ORE_EN << TMD2755_SHIFT_ENABLE_ORE) | (PROX_ORE_VAL << TMD2755_SHIFT_ORE));
|
||||
*/
|
||||
|
||||
/*
|
||||
* CALAVG: Enable to allow HW averaging
|
||||
* ELEC_CALIB: perform both electrical and optical - default
|
||||
* CALPRATE: Enables PRATE during calibration
|
||||
*/
|
||||
|
||||
//ams_i2c_modify(chip->client, sh, TMD2755_REG_CALIB, TMD2755_MASK_CALAVG_CALIB | TMD2755_MASK_CALPRATE_CALIB,
|
||||
// (PROX_HWAVG_CAL << TMD2755_SHIFT_CALAVG_CALIB) | (PROX_PRATE_CAL << TMD2755_SHIFT_CALPRATE_CALIB));
|
||||
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_CALIB, TMD2755_MASK_CALPRATE_CALIB,
|
||||
(PROX_PRATE_CAL << TMD2755_SHIFT_CALPRATE_CALIB));
|
||||
|
||||
/* trigger calibration sequence */
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> offset calibration started (waiting for completion).\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__);
|
||||
chip->amsCalComplete = false;
|
||||
|
||||
chip->in_calib = true;
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_CALIB, TMD2755_MASK_START_OFFSET_CALIB, (0x01 << TMD2755_SHIFT_START_OFFSET_CALIB));
|
||||
|
||||
/* wait for ISR to signal calibration int complete */
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
wt = wait_for_completion_interruptible_timeout(&(chip->calibration_done), msecs_to_jiffies(PROX_CALIB_TIMEOUT_MS*(time)));
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
if (wt <= 0) {
|
||||
dev_info(&chip->client->dev, "%*.*s():%*d --> Proximity Calibration timeout occurred: %lu\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, wt);
|
||||
ret = -1;
|
||||
tmd2755_read_poffset(chip);
|
||||
} else {
|
||||
ret = 0;
|
||||
chip->in_calib = false;
|
||||
chip->amsCalComplete = true;
|
||||
/* get updated prox offset */
|
||||
tmd2755_read_poffset(chip);
|
||||
}
|
||||
/* Restore register enable and interrupt enable */
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_ENABLE, TMD2755_PEN, saveenab);
|
||||
ams_i2c_modify(chip->client, sh, TMD2755_REG_INTENAB, TMD2755_PIEN, saveint);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tmd2755_configure_prox_mode(struct tmd2755_chip *chip, u8 state)
|
||||
{
|
||||
struct i2c_client *client = chip->client;
|
||||
u8 *sh = chip->shadow;
|
||||
|
||||
dev_dbg(&chip->client->dev, "%*.*s():%*d --> Configuring Prox Mode %s\n",
|
||||
MIN_KERNEL_LOG_LEN, MAX_KERNEL_LOG_LEN, __func__, LINE_NUM_KERNEL_LOG_LEN, __LINE__, state ? "ON" : "OFF");
|
||||
|
||||
/* Turning on prox */
|
||||
if (state) {
|
||||
/* Configure default proximity settings - thresholds */
|
||||
tmd2755_init_prox_mode(chip);
|
||||
if(chip->cal_en){
|
||||
tmd2755_offset_calibration(chip);
|
||||
}else{
|
||||
log("use previous offset=%d", chip->params.poffset);
|
||||
if(chip->params.poffset <= 0){
|
||||
chip->params.poffset = TMD2755_PROXIMITY_OFFSET_DEFAULT;
|
||||
}
|
||||
tmd2755_write_poffset(chip);
|
||||
}
|
||||
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_PERS, TMD2755_MASK_PROX_PERS, chip->params.persist.persistance & TMD2755_MASK_PROX_PERS);
|
||||
ams_i2c_write(client, sh, TMD2755_REG_PCFG2, (chip->params.prox_pulse_len & TMD2755_MASK_PPULSE_LEN_L));
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_PCFG1, TMD2755_MASK_REG_PPULSE_LEN_H,
|
||||
(chip->params.prox_pulse_len & TMD2755_MASK_DATA_PPULSE_LEN_H) >> TMD2755_SHIFT_PPULSE_LEN_H);
|
||||
|
||||
/* PGAIN2 */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_CFG1, TMD2755_MASK_PGAIN2, (chip->params.prox_gain2 << TMD2755_SHIFT_PGAIN2));
|
||||
/* PGAIN1 */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_PCFG0, TMD2755_MASK_PGAIN1, (chip->params.prox_gain1 << TMD2755_SHIFT_PGAIN1));
|
||||
|
||||
/* PRATE defaults to 0x1F */
|
||||
ams_i2c_write(client, sh, TMD2755_REG_PRATE, chip->params.prox_time/* P_TIME_US(INTEGRATION_CYCLE) */);
|
||||
|
||||
/* PWTIME */
|
||||
ams_i2c_write(client, sh, TMD2755_REG_PWTIME, chip->params.prox_wtime);
|
||||
|
||||
/* Enable Proximity and Proximity Interrupt */
|
||||
/* PWEN is required to be enabled if ALS feature is enabled */
|
||||
/* By default, enable PWTIME with Bit 4 in REG_ENABLE */
|
||||
//ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_PWEN | TMD2755_PEN | TMD2755_PON, TMD2755_PWEN | TMD2755_PEN | TMD2755_PON);
|
||||
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_PWEN | TMD2755_PEN | TMD2755_PON, 0| TMD2755_PEN | TMD2755_PON);
|
||||
|
||||
/* Enable Prox interrupt, saturation interrupt and zero detect interrupt */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_INTENAB, TMD2755_PIEN | TMD2755_PSIEN | TMD2755_ZIEN,
|
||||
TMD2755_PIEN | TMD2755_PSIEN | TMD2755_ZIEN);
|
||||
|
||||
chip->prox_enable = true;
|
||||
chip->prox_info.detected = true;
|
||||
chip->prox_info.raw = 0;
|
||||
} else {
|
||||
chip->params.poffset_last = chip->params.poffset;
|
||||
/* Turning off prox */
|
||||
/* Disable Proximity feature, and all interrupts associated with prox */
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_PEN, 0);
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_INTENAB, TMD2755_PROX_INTS, 0);
|
||||
|
||||
/* If nothing else is enabled set PON = 0 */
|
||||
if (!(sh[TMD2755_REG_ENABLE] & TMD2755_EN_ALL))
|
||||
ams_i2c_modify(client, sh, TMD2755_REG_ENABLE, TMD2755_PON, 0x00);
|
||||
|
||||
chip->prox_enable = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void tmd2755_offset_recalibration(void){
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
tmd2755_offset_calibration(chip);
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* sysfs utility functions *
|
||||
*****************************************************************/
|
||||
static ssize_t tmd2755_prox_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
u8 idx;
|
||||
ssize_t ret = 0;
|
||||
|
||||
for (idx = 0; idx < tmd2755_prox_attrs_size; idx++) {
|
||||
if (!strncmp(tmd2755_prox_attrs[idx].attr.name, attr->attr.name, strlen(attr->attr.name))) {
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
switch (idx) {
|
||||
case PROX_RAW_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->prox_info.raw);
|
||||
break;
|
||||
case PROX_GAIN1_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.prox_gain1);
|
||||
break;
|
||||
case PROX_GAIN2_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.prox_gain2);
|
||||
break;
|
||||
case PROX_OFFSET_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.poffset);
|
||||
break;
|
||||
case PROX_PERSIST_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.persist.pers.ppers);
|
||||
break;
|
||||
case PROX_PULSE_LEN_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.prox_pulse_len);
|
||||
break;
|
||||
case PROX_ENABLE_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->prox_enable);
|
||||
break;
|
||||
case PROX_TIME_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.prox_time);
|
||||
break;
|
||||
case PROX_WTIME_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.prox_wtime);
|
||||
break;
|
||||
case PROX_LOW_THRESH_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.prox_thresh_min);
|
||||
break;
|
||||
case PROX_HIGH_THRESH_ATTR:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", chip->params.prox_thresh_max);
|
||||
break;
|
||||
case PROX_SATURATION_ATTR:
|
||||
/* Determine if prox is in saturation */
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
(chip->in_psat == PROX_NO_SAT ? "Normal_Operation" :
|
||||
(chip->in_psat == PROX_AMBIENT_SAT ? "Ambient_Saturation" : "Reflective_Saturation")));
|
||||
break;
|
||||
default:
|
||||
ret = scnprintf(buf, PAGE_SIZE, "not found\n");
|
||||
break;
|
||||
}
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* ABI FUNCTIONS - sysfs callbacks *
|
||||
*****************************************************************/
|
||||
static ssize_t tmd2755_prox_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
/* populates the prox_info structure */
|
||||
tmd2755_read_prox(chip);
|
||||
|
||||
/* Use scnprintf() */
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_detected_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
u8 val;
|
||||
|
||||
/* if prox INT is enabled, just grab the data flag that is defined in prox_info */
|
||||
/* Otherwise read the prox */
|
||||
ams_i2c_read(chip->client, TMD2755_REG_INTENAB, &val);
|
||||
if (!(val & TMD2755_PIEN)) {
|
||||
tmd2755_read_prox(chip);
|
||||
tmd2755_get_prox(chip);
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", chip->prox_info.detected ? "detected" : "released");
|
||||
}
|
||||
|
||||
|
||||
/* gains */
|
||||
/* stage 1 - */
|
||||
static ssize_t tmd2755_prox_gain1_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_gain1_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long gain;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &gain);
|
||||
|
||||
if (rc || (gain > PROX_GAIN_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
rc = ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_PCFG0, TMD2755_MASK_PGAIN1, gain << TMD2755_SHIFT_PGAIN1);
|
||||
chip->params.prox_gain1 = gain;
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* stage 2 - proximity IR sensor */
|
||||
static ssize_t tmd2755_prox_gain2_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_gain2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long gain;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &gain);
|
||||
|
||||
if (rc || (gain > PROX_GAIN_MAX) || (gain == 2)) /* 2 is a reserved value for pgain2 */
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
rc = ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_CFG1, TMD2755_MASK_PGAIN2, gain << TMD2755_SHIFT_PGAIN2);
|
||||
chip->params.prox_gain2 = gain;
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_offset_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_offset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long offset;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &offset);
|
||||
log("apply offset = %d, input=%s", chip->params.poffset, buf);
|
||||
|
||||
chip->params.poffset = offset;
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_persist_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_persist_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long persist;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &persist);
|
||||
if (rc || (persist > PROX_PERSIST_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
ams_i2c_modify(chip->client, chip->shadow,
|
||||
TMD2755_REG_PERS, TMD2755_MASK_PROX_PERS, persist << TMD2755_SHIFT_PROX_PERS);
|
||||
chip->params.persist.persistance = chip->shadow[TMD2755_REG_PERS];
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_pulse_len_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_pulse_len_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long pulse_len;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &pulse_len);
|
||||
if (rc || (pulse_len < PROX_PULSE_LEN_MIN) || (pulse_len > PROX_PULSE_LEN_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
|
||||
/* pulse length is 10 bits: 8 bits in PCFG2 and 2 MSBs in PCFG1 */
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PCFG2, (pulse_len & TMD2755_MASK_PPULSE_LEN_L));
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_PCFG1, TMD2755_MASK_REG_PPULSE_LEN_H,
|
||||
(pulse_len & TMD2755_MASK_DATA_PPULSE_LEN_H) >> TMD2755_SHIFT_PPULSE_LEN_H);
|
||||
chip->params.prox_pulse_len = pulse_len;
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_time_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_time_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long prate;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &prate);
|
||||
if (rc || (prate > PROX_TIME_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
ams_i2c_write(chip->client, chip->shadow,
|
||||
TMD2755_REG_PRATE, prate);
|
||||
chip->params.prox_time = chip->shadow[TMD2755_REG_PRATE];
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_wtime_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_wtime_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long pwtime;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &pwtime);
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
ams_i2c_write(chip->client, chip->shadow,
|
||||
TMD2755_REG_PWTIME, pwtime);
|
||||
chip->params.prox_wtime = chip->shadow[TMD2755_REG_PWTIME];
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long enable;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, 10, &enable);
|
||||
/* if error on conversion, value greater than 1(true) */
|
||||
if (rc || (enable > 1))
|
||||
return -EINVAL;
|
||||
/* if its the same, no need to do any work. */
|
||||
if (enable == chip->prox_enable)
|
||||
return size;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
|
||||
if (enable)
|
||||
tmd2755_configure_prox_mode(chip, TMD2755_FEATURE_ON);
|
||||
else /* disable */
|
||||
tmd2755_configure_prox_mode(chip, TMD2755_FEATURE_OFF);
|
||||
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_low_thresh_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_low_thresh_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long low_thresh;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &low_thresh);
|
||||
if (rc || (low_thresh > PROX_THRESH_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
if (chip->params.prox_apc == PROX_APC_ENABLED) {
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PILTL, (low_thresh & 0xFF));
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PILTH, ((low_thresh >> 8) & TMD2755_MASK_PILTH));
|
||||
chip->params.prox_thresh_min = low_thresh;
|
||||
} else {
|
||||
/* apc == 1 means APC is DISABLED, only 8 MSB of PILT are used - threshold is only 14 bit number (i.e. right shift 6) */
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PILTL, ((low_thresh >> 6) & 0xFF));
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PILTH, 0);
|
||||
chip->params.prox_thresh_min = low_thresh/64;
|
||||
}
|
||||
|
||||
log("APC disable, thresh_min=%d", chip->params.prox_thresh_min);
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_high_thresh_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_high_thresh_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
unsigned long high_thresh;
|
||||
int rc;
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
rc = kstrtoul(buf, BASE_10, &high_thresh);
|
||||
if (rc || (high_thresh > PROX_THRESH_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
AMS_MUTEX_LOCK(&chip->lock);
|
||||
PROX_OFF();
|
||||
if (chip->params.prox_apc == PROX_APC_ENABLED) {
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTL, (high_thresh & 0xFF));
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTH, ((high_thresh >> 8) & TMD2755_MASK_PIHTH));
|
||||
chip->params.prox_thresh_max = high_thresh;
|
||||
} else {
|
||||
/* apc == 1 means APC is DISABLED, only 8 MSB of PIHT are used - threshold is only 14 bit number (i.e. right shift 6) */
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTL, ((high_thresh >> 6) & 0xFF));
|
||||
ams_i2c_write(chip->client, chip->shadow, TMD2755_REG_PIHTH, 0);
|
||||
chip->params.prox_thresh_max = high_thresh/64;
|
||||
}
|
||||
log("APC disable, thresh_max=%d", chip->params.prox_thresh_max);
|
||||
PROX_ON();
|
||||
AMS_MUTEX_UNLOCK(&chip->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_regs_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tmd2755_chip *chip = g_tmd2755_chip;
|
||||
|
||||
u8 rEnable = 0, rPrate = 0, rPiltl = 0, rPilth = 0;
|
||||
u8 rPihtl = 0, rPihth = 0, rPers = 0, rCfg0 = 0;
|
||||
u8 rPcfg0 = 0, rCfg1 = 0, rStatus = 0, rPcfg1 = 0;
|
||||
u8 rCfg8 = 0, rCfg3 = 0, rCfg6 = 0, rIntenab = 0;
|
||||
u8 rPwtime = 0, rCalib = 0, rCalOff = 0, rCalcfg = 0;
|
||||
u8 rPcfg2 = 0, rCalstat = 0;
|
||||
|
||||
ams_i2c_read(chip->client, TMD2755_REG_ENABLE, &rEnable);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PRATE, &rPrate);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PILTL, &rPiltl);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PILTH, &rPilth);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PIHTL, &rPihtl);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PIHTH, &rPihth);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PERS, &rPers);
|
||||
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CFG0, &rCfg0);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CFG1, &rCfg1);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CFG8, &rCfg8);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CFG3, &rCfg3);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CFG6, &rCfg6);
|
||||
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PCFG0, &rPcfg0);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PCFG1, &rPcfg1);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PCFG2, &rPcfg2);
|
||||
|
||||
ams_i2c_read(chip->client, TMD2755_REG_STATUS, &rStatus);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_PWTIME, &rPwtime);
|
||||
|
||||
ams_i2c_read(chip->client, TMD2755_REG_INTENAB, &rIntenab);
|
||||
|
||||
/* Calibration Registers */
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CALIB, &rCalib);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CALIB_OFF, &rCalOff);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CALIBCFG, &rCalcfg);
|
||||
ams_i2c_read(chip->client, TMD2755_REG_CALIBSTAT, &rCalstat);
|
||||
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
"ENABLE = 0x%02X\nPRATE = 0x%02X\nPILT = 0x%04X\nPIHT = 0x%04X\n"
|
||||
"PERS = 0x%02X\nPCFG0 = 0x%02X\nPCFG1 = 0x%02X\nPCFG2 = 0x%02X\n"
|
||||
"CFG0 = 0x%02X\nCFG1 = 0x%02X\nCFG8 = 0x%02X\nCFG3 = 0x%02X\n"
|
||||
"CFG6 = 0x%02X\nSTATUS = 0x%02X\nPWTIME = 0x%02X\nINTENAB = 0x%02X\n"
|
||||
"CALIB = 0x%02X\nCAL_OFF = 0x%02X\nCAL_CFG = 0x%02X\nCAL_STAT = 0x%02X\n"
|
||||
"%s\n",
|
||||
rEnable, rPrate, (rPilth << 8) | rPiltl, (rPihth << 8) | rPihtl, rPers,
|
||||
rPcfg0, rPcfg1, rPcfg2,
|
||||
rCfg0, rCfg1, rCfg8, rCfg3, rCfg6,
|
||||
rStatus, rPwtime, rIntenab,
|
||||
rCalib, rCalOff, rCalcfg, rCalstat,
|
||||
chip->prox_info.detected ? "Prox Detect" : "Prox Release");
|
||||
}
|
||||
|
||||
static ssize_t tmd2755_prox_sat_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return tmd2755_prox_show(dev, attr, buf);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************
|
||||
* END OF SYSFS FUNCTIONS *
|
||||
**********************************************************************************************************************/
|
||||
|
||||
/**************************************************************
|
||||
* Global Sys Fs definitions *
|
||||
**************************************************************/
|
||||
extern ssize_t tmd2755_registers_show(struct device *dev, struct device_attribute *attr, char *buf);
|
||||
extern ssize_t tmd2755_registers_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size);
|
||||
struct device_attribute tmd2755_prox_attrs[] = {
|
||||
__ATTR(prox_raw, 0444, tmd2755_prox_raw_show, NULL),
|
||||
__ATTR(prox_detect, 0444, tmd2755_prox_detected_show, NULL),
|
||||
__ATTR(prox_gain1, 0644, tmd2755_prox_gain1_show, tmd2755_prox_gain1_store),
|
||||
__ATTR(prox_gain2, 0644, tmd2755_prox_gain2_show, tmd2755_prox_gain2_store),
|
||||
__ATTR(prox_offset, 0644, tmd2755_prox_offset_show, tmd2755_prox_offset_store),
|
||||
__ATTR(prox_persist, 0644, tmd2755_prox_persist_show, tmd2755_prox_persist_store),
|
||||
__ATTR(prox_pulse_len, 0644, tmd2755_prox_pulse_len_show, tmd2755_prox_pulse_len_store),
|
||||
__ATTR(prox_enable, 0644, tmd2755_prox_enable_show, tmd2755_prox_enable_store),
|
||||
__ATTR(prox_time, 0644, tmd2755_prox_time_show, tmd2755_prox_time_store),
|
||||
__ATTR(prox_wtime, 0644, tmd2755_prox_wtime_show, tmd2755_prox_wtime_store),
|
||||
__ATTR(prox_low_thresh, 0644, tmd2755_prox_low_thresh_show, tmd2755_prox_low_thresh_store),
|
||||
__ATTR(prox_high_thresh, 0644, tmd2755_prox_high_thresh_show, tmd2755_prox_high_thresh_store),
|
||||
__ATTR(prox_regs, 0444, tmd2755_prox_regs_show, NULL),
|
||||
__ATTR(prox_sat, 0444, tmd2755_prox_sat_show, NULL),
|
||||
__ATTR(regs, 0644, tmd2755_registers_show, tmd2755_registers_store),
|
||||
};
|
||||
|
||||
int tmd2755_prox_attrs_size = ARRAY_SIZE(tmd2755_prox_attrs);
|
||||
|
@ -0,0 +1,158 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Copyright by ams AG *
|
||||
* All rights are reserved. *
|
||||
* *
|
||||
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
|
||||
* THE SOFTWARE. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED FOR USE ONLY IN CONJUNCTION WITH AMS PRODUCTS. *
|
||||
* USE OF THE SOFTWARE IN CONJUNCTION WITH NON-AMS-PRODUCTS IS EXPLICITLY *
|
||||
* EXCLUDED. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __AMS_TMD2755_PROX_H__
|
||||
#define __AMS_TMD2755_PROX_H__
|
||||
|
||||
#define MIN_PROX_THRESHOLD (0)
|
||||
|
||||
/* Values used during calibration */
|
||||
#define PROX_BINSRCH_TARGET_VALUE (4) /* pdata target = 31 */
|
||||
#define PROX_AUTO_OFFSET_ADJ_VAL (1) /* enabled */
|
||||
//#define PROX_AVG_VAL (2) /* enabled */
|
||||
#define PROX_AVG_VAL (0) /* disabled will save 30ms int */
|
||||
|
||||
#define PROX_ORE_EN (1) /* enable */
|
||||
#define PROX_ORE_VAL (0x01) /* nominal + 1 step */
|
||||
|
||||
#define PROX_HWAVG_CAL (1) /* Allows hardware averaging during calibration */
|
||||
#define PROX_PRATE_CAL (0) /* enables PRATE during calibration */
|
||||
|
||||
#define PROX_CALIB_TIMEOUT_MS (80)
|
||||
|
||||
#define PROX_APC_ENABLED (0)
|
||||
#define PROX_APC_DISABLED (1)
|
||||
|
||||
#define PROX_SAT_EVENT (2)
|
||||
|
||||
/* Min/Max/Default Values for parameters */
|
||||
/**********************************************************************************/
|
||||
#define PROX_PERSIST_MIN (0)
|
||||
#define PROX_PERSIST_MAX (15)
|
||||
#define PROX_PERSIST_DEFAULT (1)
|
||||
|
||||
#define PROX_OFFSET_INIT (100)
|
||||
|
||||
|
||||
/* Thresholds limits - up to the user to determine if min < max */
|
||||
/* Routines adjust value based on APC */
|
||||
#define PROX_THRESH_MIN (0)
|
||||
#define PROX_THRESH_MAX (0x3FFF)
|
||||
#define PROX_THRESH_DEFAULT (55)
|
||||
|
||||
#define PROX_PULSE_CNT_MIN (0)
|
||||
#define PROX_PULSE_CNT_MAX (63)
|
||||
#define PROX_PULSE_CNT_DEFAULT (15)
|
||||
|
||||
#define PROX_APC_MIN PROX_APC_ENABLED
|
||||
#define PROX_APC_MAX PROX_APC_DISABLED
|
||||
#define PROX_APC_DEFAULT PROX_APC_ENABLED
|
||||
|
||||
#define PROX_PULSE_LEN_MIN (30)
|
||||
#define PROX_PULSE_LEN_MAX (0x3FF)
|
||||
#define PROX_PULSE_LEN_DEFAULT (30)
|
||||
|
||||
#define PROX_GAIN_MIN (0)
|
||||
#define PROX_GAIN_MAX (3) /* 2 bits gain_1 and gain_2 */
|
||||
#define PROX_GAIN_DEFAULT (2)
|
||||
|
||||
#define PROX_OFFSET_MIN (-255)
|
||||
#define PROX_OFFSET_MAX (255)
|
||||
#define PROX_OFFSET_DEFAULT (6)
|
||||
|
||||
#define PROX_DRIVE_MIN (5)
|
||||
#define PROX_DRIVE_MAX (8)
|
||||
#define PROX_DRIVE_DEFAULT (5)
|
||||
|
||||
#define PROX_TIME_MIN (0)
|
||||
#define PROX_TIME_MAX (255)
|
||||
#define PROX_TIME_DEFAULT (31)
|
||||
|
||||
#define PROX_WTIME_MIN (0)
|
||||
#define PROX_WTIME_MAX (255)
|
||||
#define PROX_WTIME_DEFAULT (0)
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#define PROX_ON() do { \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_ENABLE, TMD2755_PEN, TMD2755_PEN); \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_INTENAB, TMD2755_PIEN, TMD2755_PIEN); \
|
||||
} while (0)
|
||||
|
||||
#define PROX_OFF() do { \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_INTENAB, TMD2755_PIEN, 0); \
|
||||
ams_i2c_modify(chip->client, chip->shadow, TMD2755_REG_ENABLE, TMD2755_PEN, 0); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This must match the order of ATTR defined in
|
||||
* struct device_attribute tmd2755_prox_attrs[]
|
||||
* in ams_tmd2755_prox.c
|
||||
*/
|
||||
enum tmd2755_prox_attrs {
|
||||
PROX_RAW_ATTR,
|
||||
PROX_DETECT_ATTR,
|
||||
PROX_GAIN1_ATTR,
|
||||
PROX_GAIN2_ATTR,
|
||||
PROX_OFFSET_ATTR,
|
||||
PROX_PERSIST_ATTR,
|
||||
PROX_PULSE_LEN_ATTR,
|
||||
PROX_ENABLE_ATTR,
|
||||
PROX_TIME_ATTR,
|
||||
PROX_WTIME_ATTR,
|
||||
PROX_LOW_THRESH_ATTR,
|
||||
PROX_HIGH_THRESH_ATTR,
|
||||
PROX_REGS_ATTR,
|
||||
PROX_SATURATION_ATTR,
|
||||
};
|
||||
|
||||
enum tmd2755_prox_sat_states {
|
||||
PROX_NO_SAT,
|
||||
PROX_SAT, /* general saturation */
|
||||
PROX_AMBIENT_SAT,
|
||||
PROX_REFLECTIVE_SAT,
|
||||
};
|
||||
|
||||
|
||||
extern struct device_attribute tmd2755_prox_attrs[];
|
||||
extern int tmd2755_prox_attrs_size;
|
||||
|
||||
|
||||
int tmd2755_configure_prox_mode(struct tmd2755_chip *chip, u8 state);
|
||||
void tmd2755_init_prox_mode(struct tmd2755_chip *chip);
|
||||
void tmd2755_process_prox_irq(struct tmd2755_chip *chip);
|
||||
void tmd2755_prox_report_inp_event(struct tmd2755_chip *chip, int value);
|
||||
void tmd2755_process_saturation_event(struct tmd2755_chip *chip);
|
||||
extern void proximity_work(int state);
|
||||
void tmd2755_read_poffset(struct tmd2755_chip *chip);
|
||||
|
||||
|
||||
#endif // __AMS_TMD2755_PROX_H__
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (C) 2014 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*******************************/
|
||||
/* IR Sensor Hardware Module */
|
||||
/******************************/
|
||||
#ifndef __LINUX_ALSPS_VCNL36866_H
|
||||
#define __LINUX_ALSPS_VCNL36866_H
|
||||
|
||||
#ifdef ONE_PL_CHIP
|
||||
#define VCNL36866_PROXIMITY_INF_DEFAULT (92)
|
||||
#define VCNL36866_PROXIMITY_THDL_DEFAULT (139)
|
||||
#define VCNL36866_PROXIMITY_THDH_DEFAULT (215)
|
||||
#define VCNL36866_PROXIMITY_AUTOK_MIN (3)
|
||||
#define VCNL36866_PROXIMITY_AUTOK_MAX (2200)
|
||||
#define VCNL36866_LIGHT_CALIBRATION_DEFAULT (846)
|
||||
#else
|
||||
#define VCNL36866_PROXIMITY_INF_DEFAULT (416)
|
||||
#define VCNL36866_PROXIMITY_THDL_DEFAULT (520)
|
||||
#define VCNL36866_PROXIMITY_THDH_DEFAULT (832)
|
||||
#define VCNL36866_PROXIMITY_AUTOK_MIN (3)
|
||||
#define VCNL36866_PROXIMITY_AUTOK_MAX (2500)
|
||||
#define VCNL36866_LIGHT_CALIBRATION_DEFAULT (1658)
|
||||
#endif
|
||||
#define VCNL36866_LIGHT_MAX_THRESHOLD (65534)
|
||||
#define VCNL36866_NUM_REGS (15)
|
||||
|
||||
#define VCNL36866_I2C_NAME "vcnl36866"
|
||||
|
||||
/* Define Slave Address*/
|
||||
#define VCNL36866_SLAVE_ADDR 0x60
|
||||
|
||||
/* Define Chip ID */
|
||||
#define VCNL36866_ID 0x62
|
||||
|
||||
/*Define Command Code*/
|
||||
#define CS_CONF1 0x00
|
||||
#define CS_CONF2 0x00
|
||||
#define CS_THDH 0x01
|
||||
#define CS_THDL 0x02
|
||||
#define PS_CONF1 0x03
|
||||
#define PS_CONF2 0x03
|
||||
#define PS_CONF3 0x04
|
||||
#define PS_CONF4 0x04
|
||||
|
||||
#define PS_THDL 0x05
|
||||
#define PS_THDH 0x06
|
||||
#define PS_CANC 0x07
|
||||
|
||||
#define PS_AC 0x08
|
||||
|
||||
#define ALS_DATA 0xF1
|
||||
#define IR_DATA 0xF3
|
||||
#define PS_DATA 0xF4
|
||||
|
||||
#define INT_FLAG 0xF5
|
||||
#define ID_REG 0xF6
|
||||
|
||||
#define PS_AC_DATA 0xF7
|
||||
|
||||
struct vcnl36866_reg {
|
||||
uint8_t reg;
|
||||
};
|
||||
|
||||
static struct vcnl36866_reg vcnl36866_regs[] = {
|
||||
{.reg = CS_CONF1, }, // 0x00
|
||||
{.reg = CS_THDH, }, // 0x01
|
||||
{.reg = CS_THDL, }, // 0x02
|
||||
{.reg = PS_CONF1, }, // 0x03
|
||||
{.reg = PS_CONF3, }, // 0x04
|
||||
{.reg = PS_THDL, }, // 0x05
|
||||
{.reg = PS_THDH, }, // 0x06
|
||||
{.reg = PS_CANC, }, // 0x07
|
||||
{.reg = PS_AC, }, // 0x08
|
||||
{.reg = ALS_DATA, }, // 0xF1
|
||||
{.reg = IR_DATA, }, // 0xF3
|
||||
{.reg = PS_DATA, }, // 0xF4
|
||||
{.reg = INT_FLAG, }, // 0xF5
|
||||
{.reg = ID_REG, }, // 0xF6
|
||||
{.reg = PS_AC_DATA,}, // 0xF7
|
||||
};
|
||||
|
||||
/**
|
||||
* for ALS CONF command
|
||||
**/
|
||||
|
||||
/*** CS CONF1 ***/
|
||||
//PS start
|
||||
#define VCNL36866_CS_START_MASK 0x7F
|
||||
#define VCNL36866_CS_START_SHIFT (7)
|
||||
#define VCNL36866_CS_START (1)
|
||||
//Integration
|
||||
#define VCNL36866_CS_IT_MAX (3)
|
||||
#define VCNL36866_CS_IT_MASK 0xF3
|
||||
#define VCNL36866_CS_IT_NOT_MASK 0x0C
|
||||
#define VCNL36866_CS_IT_SHIFT (2)
|
||||
#define VCNL36866_CS_IT_50MS (0)
|
||||
#define VCNL36866_CS_IT_100MS (1)
|
||||
#define VCNL36866_CS_IT_200MS (2)
|
||||
#define VCNL36866_CS_IT_400MS (3)
|
||||
|
||||
#define VCNL36866_CS_STANDBY (1 << 1)
|
||||
#define VCNL36866_CS_STANDBY_MASK 0xFD
|
||||
|
||||
#define VCNL36866_CS_SD (1 << 0) /*enable/disable ALS func, 1:disable , 0: enable*/
|
||||
#define VCNL36866_CS_SD_MASK 0xFE
|
||||
|
||||
/*** CS CONF2 ***/
|
||||
//Persistence
|
||||
#define VCNL36866_CS_PERS_MAX (3)
|
||||
#define VCNL36866_CS_PERS_MASK 0xF3
|
||||
#define VCNL36866_CS_PERS_SHIFT (2)
|
||||
#define VCNL36866_CS_PERS_1 (0)
|
||||
#define VCNL36866_CS_PERS_2 (1)
|
||||
#define VCNL36866_CS_PERS_4 (2)
|
||||
#define VCNL36866_CS_PERS_8 (3)
|
||||
|
||||
#define VCNL36866_CS_START2_MASK 0xFD
|
||||
#define VCNL36866_CS_START2_SHIFT (1)
|
||||
#define VCNL36866_CS_START2 (1)
|
||||
|
||||
#define VCNL36866_CS_RSV_MASK 0xDF
|
||||
#define VCNL36866_CS_RSV_SHIFT (5)
|
||||
#define VCNL36866_CS_RSV (1)
|
||||
|
||||
#define VCNL36866_CS_INT_EN (1 << 0) /*enable/disable Interrupt*/
|
||||
#define VCNL36866_CS_INT_MASK 0xFE
|
||||
|
||||
#define VCNL36866_CS_HD_DISABLE (0)
|
||||
#define VCNL36866_CS_HD_ENABLE (1)
|
||||
/**
|
||||
* for PS CONF command
|
||||
**/
|
||||
|
||||
/*** PS CONF1 ***/
|
||||
//LED Duty Ratio
|
||||
#define VCNL36866_PS_DR_MAX (3)
|
||||
#define VCNL36866_PS_DR_MASK 0x3F
|
||||
#define VCNL36866_PS_DR_SHIFT (6)
|
||||
#define VCNL36866_PS_PERIOD_10 (0)
|
||||
#define VCNL36866_PS_PERIOD_20 (1)
|
||||
#define VCNL36866_PS_PERIOD_40 (2)
|
||||
#define VCNL36866_PS_PERIOD_80 (3)
|
||||
|
||||
//Persistence
|
||||
#define VCNL36866_PS_PERS_MAX (3)
|
||||
#define VCNL36866_PS_PERS_MASK 0xCF
|
||||
#define VCNL36866_PS_PERS_SHIFT (4)
|
||||
#define VCNL36866_PS_PERS_1 (0)
|
||||
#define VCNL36866_PS_PERS_2 (1)
|
||||
#define VCNL36866_PS_PERS_3 (2)
|
||||
#define VCNL36866_PS_PERS_4 (3)
|
||||
|
||||
#define VCNL36866_PS_INT_IN_AND_OUT (2 << 2) /*enable/disable Interrupt*/
|
||||
#define VCNL36866_PS_INT_MASK 0xF3 /*enable/disable Interrupt*/
|
||||
|
||||
#define VCNL36866_PS_SMART_PERS (1 << 1)
|
||||
#define VCNL36866_PS_SMART_PERS_MASK 0xFD
|
||||
|
||||
#define VCNL36866_PS_SD (1 << 0)/*enable/disable PS func, 1:disable , 0: enable*/
|
||||
#define VCNL36866_PS_SD_MASK 0xFE
|
||||
|
||||
/*** PS CONF2 ***/
|
||||
//Integration
|
||||
#define VCNL36866_PS_IT_MAX (3)
|
||||
#define VCNL36866_PS_IT_MASK 0x3F
|
||||
#define VCNL36866_PS_IT_SHIFT (6)
|
||||
#define VCNL36866_PS_IT_1T (0)
|
||||
#define VCNL36866_PS_IT_2T (1)
|
||||
#define VCNL36866_PS_IT_4T (2)
|
||||
#define VCNL36866_PS_IT_8T (3)
|
||||
|
||||
//Multi-Pulse setting
|
||||
#define VCNL36866_PS_MPS_MAX (3)
|
||||
#define VCNL36866_PS_MPS_MASK 0xCF
|
||||
#define VCNL36866_PS_MPS_SHIFT (4)
|
||||
#define VCNL36866_PS_MPS_1 (0)
|
||||
#define VCNL36866_PS_MPS_2 (1)
|
||||
#define VCNL36866_PS_MPS_4 (2)
|
||||
#define VCNL36866_PS_MPS_8 (3)
|
||||
|
||||
//PS start
|
||||
#define VCNL36866_PS_START_MASK 0xF7
|
||||
#define VCNL36866_PS_START_SHIFT (3)
|
||||
#define VCNL36866_PS_START (1)
|
||||
|
||||
//PS high gain mode enable
|
||||
#define VCNL36866_PS_HG_ENABLE_MASK 0xFB
|
||||
#define VCNL36866_PS_HG_ENABLE_SHIFT (2)
|
||||
#define VCNL36866_PS_HG_ENABLE (1)
|
||||
|
||||
#define VCNL36866_PS_INT_SEL (1 << 0)
|
||||
#define VCNL36866_PS_INT_SEL_MASK 0xFE
|
||||
|
||||
/*** PS CONF3 ***/
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_MODE_MASK 0xBF
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_MODE_SHIFT (6)
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_MODE (1)
|
||||
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_TRIG_MASK 0xDF
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_TRIG_SHIFT (5)
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_TRIG (1)
|
||||
|
||||
#define VCNL36866_PS_START2_MASK 0xF7
|
||||
#define VCNL36866_PS_START2_SHIFT (3)
|
||||
#define VCNL36866_PS_START2 (1)
|
||||
|
||||
/*** PS CONF4 ***/
|
||||
#define VCNL36866_PS_SUNLIGHT_DEFAULT_MASK 0x1F
|
||||
#define VCNL36866_LED_I_SHIFT (5)
|
||||
#define VCNL36866_PS_SUNLIGHT_DEFAULT (7)
|
||||
|
||||
//LED Current
|
||||
#define VCNL36866_VCSEL_I_MAX (4)
|
||||
#define VCNL36866_VCSEL_I_MASK 0xFC
|
||||
#define VCNL36866_VCSEL_I_SHIFT (0)
|
||||
#define VCNL36866_VCSEL_I_7mA (0)
|
||||
#define VCNL36866_VCSEL_I_11mA (1)
|
||||
#define VCNL36866_VCSEL_I_14mA (2)
|
||||
#define VCNL36866_VCSEL_I_17mA (3)
|
||||
#define VCNL36866_VCSEL_I_20mA (4)
|
||||
|
||||
/*** INT FLAG ***/
|
||||
#define INT_FLAG_PS_ACFLAG (1 << 5) //After PS finishing auto calibration, INT raise.
|
||||
#define INT_FLAG_PS_SPFLAG (1 << 4) //PS entering protection mode
|
||||
#define INT_FLAG_CS_IF_L (1 << 3)
|
||||
#define INT_FLAG_CS_IF_H (1 << 2)
|
||||
#define INT_FLAG_PS_IF_CLOSE (1 << 1) //PS rises above PS_THDH INT trigger event
|
||||
#define INT_FLAG_PS_IF_AWAY (1 << 0) //PS drops below PS_THDL INT trigger event
|
||||
|
||||
/**
|
||||
* for ALS Dynamic control array
|
||||
**/
|
||||
|
||||
struct vcnl36866_dynamic {
|
||||
uint8_t IT_TIME;
|
||||
int sensitivity;
|
||||
u64 evt_skip_time_ns;
|
||||
};
|
||||
static int ALS_dynamic_status = 0;
|
||||
|
||||
#ifdef LONG_LENGTH_LOGN_IT_NON_PERF
|
||||
static struct vcnl36866_dynamic vcnl36866_dynamic_array[] = {
|
||||
{.IT_TIME = VCNL36866_CS_IT_400MS, .sensitivity = 1, .evt_skip_time_ns = 0},
|
||||
{.IT_TIME = VCNL36866_CS_IT_400MS, .sensitivity = 1, .evt_skip_time_ns = 0},
|
||||
{.IT_TIME = VCNL36866_CS_IT_400MS, .sensitivity = 1, .evt_skip_time_ns = 0},
|
||||
};
|
||||
#elif defined LONG_LENGTH_LOGN_IT_PERF
|
||||
static struct vcnl36866_dynamic vcnl36866_dynamic_array[] = {
|
||||
{.IT_TIME = VCNL36866_CS_IT_100MS, .sensitivity = 4, .evt_skip_time_ns = 100000000},
|
||||
{.IT_TIME = VCNL36866_CS_IT_400MS, .sensitivity = 1, .evt_skip_time_ns = 500000000},
|
||||
{.IT_TIME = VCNL36866_CS_IT_50MS, .sensitivity = 8, .evt_skip_time_ns = 100000000},
|
||||
};
|
||||
#else
|
||||
static struct vcnl36866_dynamic vcnl36866_dynamic_array[] = {
|
||||
{.IT_TIME = VCNL36866_CS_IT_50MS, .sensitivity=1, .evt_skip_time_ns = 0},
|
||||
{.IT_TIME = VCNL36866_CS_IT_50MS, .sensitivity=1, .evt_skip_time_ns = 0},
|
||||
{.IT_TIME = VCNL36866_CS_IT_50MS, .sensitivity=1, .evt_skip_time_ns = 0},
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2014 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*******************************/
|
||||
/* IR Sensor Hardware Module */
|
||||
/******************************/
|
||||
#ifndef __LINUX_ALSPS_VCNL36866_H
|
||||
#define __LINUX_ALSPS_VCNL36866_H
|
||||
|
||||
#define VCNL36866_PROXIMITY_INF_DEFAULT (182)
|
||||
#define VCNL36866_PROXIMITY_THDL_DEFAULT (426)
|
||||
#define VCNL36866_PROXIMITY_THDH_DEFAULT (1194)
|
||||
#define VCNL36866_PROXIMITY_AUTOK_MIN (3)
|
||||
#define VCNL36866_PROXIMITY_AUTOK_MAX (2500)
|
||||
#define VCNL36866_LIGHT_CALIBRATION_DEFAULT (4563)
|
||||
#define VCNL36866_LIGHT_MAX_THRESHOLD (65534)
|
||||
#define VCNL36866_NUM_REGS (15)
|
||||
|
||||
#define VCNL36866_I2C_NAME "vcnl36866"
|
||||
|
||||
/* Define Slave Address*/
|
||||
#define VCNL36866_SLAVE_ADDR 0x60
|
||||
|
||||
/* Define Chip ID */
|
||||
#define VCNL36866_ID 0x62
|
||||
|
||||
/*Define Command Code*/
|
||||
#define CS_CONF1 0x00
|
||||
#define CS_CONF2 0x00
|
||||
#define CS_THDH 0x01
|
||||
#define CS_THDL 0x02
|
||||
#define PS_CONF1 0x03
|
||||
#define PS_CONF2 0x03
|
||||
#define PS_CONF3 0x04
|
||||
#define PS_CONF4 0x04
|
||||
|
||||
#define PS_THDL 0x05
|
||||
#define PS_THDH 0x06
|
||||
#define PS_CANC 0x07
|
||||
|
||||
#define PS_AC 0x08
|
||||
|
||||
#define ALS_DATA 0xF1
|
||||
#define IR_DATA 0xF3
|
||||
#define PS_DATA 0xF4
|
||||
|
||||
#define INT_FLAG 0xF5
|
||||
#define ID_REG 0xF6
|
||||
|
||||
#define PS_AC_DATA 0xF7
|
||||
|
||||
struct vcnl36866_reg {
|
||||
uint8_t reg;
|
||||
};
|
||||
|
||||
static struct vcnl36866_reg vcnl36866_regs[] = {
|
||||
{.reg = CS_CONF1, }, // 0x00
|
||||
{.reg = CS_THDH, }, // 0x01
|
||||
{.reg = CS_THDL, }, // 0x02
|
||||
{.reg = PS_CONF1, }, // 0x03
|
||||
{.reg = PS_CONF3, }, // 0x04
|
||||
{.reg = PS_THDL, }, // 0x05
|
||||
{.reg = PS_THDH, }, // 0x06
|
||||
{.reg = PS_CANC, }, // 0x07
|
||||
{.reg = PS_AC, }, // 0x08
|
||||
{.reg = ALS_DATA, }, // 0xF1
|
||||
{.reg = IR_DATA, }, // 0xF3
|
||||
{.reg = PS_DATA, }, // 0xF4
|
||||
{.reg = INT_FLAG, }, // 0xF5
|
||||
{.reg = ID_REG, }, // 0xF6
|
||||
{.reg = PS_AC_DATA,}, // 0xF7
|
||||
};
|
||||
|
||||
/**
|
||||
* for ALS CONF command
|
||||
**/
|
||||
|
||||
/*** CS CONF1 ***/
|
||||
//PS start
|
||||
#define VCNL36866_CS_START_MASK 0x7F
|
||||
#define VCNL36866_CS_START_SHIFT (7)
|
||||
#define VCNL36866_CS_START (1)
|
||||
|
||||
//Integration
|
||||
#define VCNL36866_CS_IT_MAX (3)
|
||||
#define VCNL36866_CS_IT_MASK 0xF3
|
||||
#define VCNL36866_CS_IT_NOT_MASK 0x0C
|
||||
#define VCNL36866_CS_IT_SHIFT (2)
|
||||
#define VCNL36866_CS_IT_50MS (0)
|
||||
#define VCNL36866_CS_IT_100MS (1)
|
||||
#define VCNL36866_CS_IT_200MS (2)
|
||||
#define VCNL36866_CS_IT_400MS (3)
|
||||
|
||||
#define VCNL36866_CS_STANDBY (1 << 1)
|
||||
#define VCNL36866_CS_STANDBY_MASK 0xFD
|
||||
|
||||
#define VCNL36866_CS_SD (1 << 0) /*enable/disable ALS func, 1:disable , 0: enable*/
|
||||
#define VCNL36866_CS_SD_MASK 0xFE
|
||||
|
||||
/*** CS CONF2 ***/
|
||||
//Persistence
|
||||
#define VCNL36866_CS_PERS_MAX (3)
|
||||
#define VCNL36866_CS_PERS_MASK 0xF3
|
||||
#define VCNL36866_CS_PERS_SHIFT (2)
|
||||
#define VCNL36866_CS_PERS_1 (0)
|
||||
#define VCNL36866_CS_PERS_2 (1)
|
||||
#define VCNL36866_CS_PERS_4 (2)
|
||||
#define VCNL36866_CS_PERS_8 (3)
|
||||
|
||||
#define VCNL36866_CS_START2_MASK 0xFD
|
||||
#define VCNL36866_CS_START2_SHIFT (1)
|
||||
#define VCNL36866_CS_START2 (1)
|
||||
|
||||
#define VCNL36866_CS_INT_EN (1 << 0) /*enable/disable Interrupt*/
|
||||
#define VCNL36866_CS_INT_MASK 0xFE
|
||||
|
||||
#define VCNL36866_CS_HD_DISABLE (0)
|
||||
#define VCNL36866_CS_HD_ENABLE (1)
|
||||
/**
|
||||
* for PS CONF command
|
||||
**/
|
||||
|
||||
/*** PS CONF1 ***/
|
||||
//LED Duty Ratio
|
||||
#define VCNL36866_PS_DR_MAX (3)
|
||||
#define VCNL36866_PS_DR_MASK 0x3F
|
||||
#define VCNL36866_PS_DR_SHIFT (6)
|
||||
#define VCNL36866_PS_PERIOD_10 (0)
|
||||
#define VCNL36866_PS_PERIOD_20 (1)
|
||||
#define VCNL36866_PS_PERIOD_40 (2)
|
||||
#define VCNL36866_PS_PERIOD_80 (3)
|
||||
|
||||
//Persistence
|
||||
#define VCNL36866_PS_PERS_MAX (3)
|
||||
#define VCNL36866_PS_PERS_MASK 0xCF
|
||||
#define VCNL36866_PS_PERS_SHIFT (4)
|
||||
#define VCNL36866_PS_PERS_1 (0)
|
||||
#define VCNL36866_PS_PERS_2 (1)
|
||||
#define VCNL36866_PS_PERS_3 (2)
|
||||
#define VCNL36866_PS_PERS_4 (3)
|
||||
|
||||
#define VCNL36866_PS_INT_IN_AND_OUT (2 << 2) /*enable/disable Interrupt*/
|
||||
#define VCNL36866_PS_INT_MASK 0xF3 /*enable/disable Interrupt*/
|
||||
|
||||
#define VCNL36866_PS_SMART_PERS (1 << 1)
|
||||
#define VCNL36866_PS_SMART_PERS_MASK 0xFD
|
||||
|
||||
#define VCNL36866_PS_SD (1 << 0)/*enable/disable PS func, 1:disable , 0: enable*/
|
||||
#define VCNL36866_PS_SD_MASK 0xFE
|
||||
|
||||
/*** PS CONF2 ***/
|
||||
//Integration
|
||||
#define VCNL36866_PS_IT_MAX (3)
|
||||
#define VCNL36866_PS_IT_MASK 0x3F
|
||||
#define VCNL36866_PS_IT_SHIFT (6)
|
||||
#define VCNL36866_PS_IT_1T (0)
|
||||
#define VCNL36866_PS_IT_2T (1)
|
||||
#define VCNL36866_PS_IT_4T (2)
|
||||
#define VCNL36866_PS_IT_8T (3)
|
||||
|
||||
//Multi-Pulse setting
|
||||
#define VCNL36866_PS_MPS_MAX (3)
|
||||
#define VCNL36866_PS_MPS_MASK 0xCF
|
||||
#define VCNL36866_PS_MPS_SHIFT (4)
|
||||
#define VCNL36866_PS_MPS_1 (0)
|
||||
#define VCNL36866_PS_MPS_2 (1)
|
||||
#define VCNL36866_PS_MPS_4 (2)
|
||||
#define VCNL36866_PS_MPS_8 (3)
|
||||
|
||||
//PS start
|
||||
#define VCNL36866_PS_START_MASK 0xF7
|
||||
#define VCNL36866_PS_START_SHIFT (3)
|
||||
#define VCNL36866_PS_START (1)
|
||||
|
||||
//PS high gain mode enable
|
||||
#define VCNL36866_PS_HG_ENABLE_MASK 0xFB
|
||||
#define VCNL36866_PS_HG_ENABLE_SHIFT (2)
|
||||
#define VCNL36866_PS_HG_ENABLE (1)
|
||||
|
||||
#define VCNL36866_PS_INT_SEL (1 << 0)
|
||||
#define VCNL36866_PS_INT_SEL_MASK 0xFE
|
||||
|
||||
/*** PS CONF3 ***/
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_MODE_MASK 0xBF
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_MODE_SHIFT (6)
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_MODE (1)
|
||||
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_TRIG_MASK 0xDF
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_TRIG_SHIFT (5)
|
||||
#define VCNL36866_PS_ACTIVE_FORCE_TRIG (1)
|
||||
|
||||
#define VCNL36866_PS_START2_MASK 0xF7
|
||||
#define VCNL36866_PS_START2_SHIFT (3)
|
||||
#define VCNL36866_PS_START2 (1)
|
||||
|
||||
/*** PS CONF4 ***/
|
||||
#define VCNL36866_PS_SUNLIGHT_DEFAULT_MASK 0x1F
|
||||
#define VCNL36866_LED_I_SHIFT (5)
|
||||
#define VCNL36866_PS_SUNLIGHT_DEFAULT (7)
|
||||
|
||||
//LED Current
|
||||
#define VCNL36866_VCSEL_I_MAX (4)
|
||||
#define VCNL36866_VCSEL_I_MASK 0xFC
|
||||
#define VCNL36866_VCSEL_I_SHIFT (0)
|
||||
#define VCNL36866_VCSEL_I_7mA (0)
|
||||
#define VCNL36866_VCSEL_I_11mA (1)
|
||||
#define VCNL36866_VCSEL_I_14mA (2)
|
||||
#define VCNL36866_VCSEL_I_17mA (3)
|
||||
#define VCNL36866_VCSEL_I_20mA (4)
|
||||
|
||||
/*** INT FLAG ***/
|
||||
#define INT_FLAG_PS_ACFLAG (1 << 5) //After PS finishing auto calibration, INT raise.
|
||||
#define INT_FLAG_PS_SPFLAG (1 << 4) //PS entering protection mode
|
||||
#define INT_FLAG_CS_IF_L (1 << 3)
|
||||
#define INT_FLAG_CS_IF_H (1 << 2)
|
||||
#define INT_FLAG_PS_IF_CLOSE (1 << 1) //PS rises above PS_THDH INT trigger event
|
||||
#define INT_FLAG_PS_IF_AWAY (1 << 0) //PS drops below PS_THDL INT trigger event
|
||||
|
||||
#endif
|
159
drivers/sensors/ASH/ASH_Hardware/ASH_Hardware.c
Normal file
159
drivers/sensors/ASH/ASH_Hardware/ASH_Hardware.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/***********************************/
|
||||
/* Asus Sensor Hub Hardware */
|
||||
/**********************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_i2c"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_I2C_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s]"fmt,MODULE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s]"fmt,MODULE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s]"fmt,MODULE_NAME,##args)
|
||||
|
||||
/****************************/
|
||||
/*i2c read/write function*/
|
||||
/****************************/
|
||||
uint8_t i2c_read_reg_u8(struct i2c_client* client, u8 reg)
|
||||
{
|
||||
uint8_t data =0 ;
|
||||
|
||||
if(client == NULL) {
|
||||
err("%s: i2c client is NULL.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data = i2c_smbus_read_byte_data(client, reg);
|
||||
if (data < 0) {
|
||||
err("%s: i2c_smbus_read_byte_data ERROR(0x%02X). \n", __FUNCTION__, reg);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_read_reg_u8);
|
||||
|
||||
int i2c_write_reg_u8(struct i2c_client* client, u8 reg, uint8_t data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(client == NULL) {
|
||||
err("%s: i2c client is NULL.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, reg, data);
|
||||
if (ret < 0) {
|
||||
err("%s: i2c_smbus_write_byte_data ERROR(0x%02X). \n", __FUNCTION__, reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_write_reg_u8);
|
||||
|
||||
int i2c_read_reg_u16(struct i2c_client* client, u8 reg, uint8_t* data)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0, //write
|
||||
.len = 1,
|
||||
.buf = ®,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD, //read
|
||||
.len = 2,
|
||||
.buf = data,
|
||||
}
|
||||
};
|
||||
|
||||
if(client == NULL) {
|
||||
err("%s: i2c client is NULL.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!client->adapter) {
|
||||
return -ENODEV;
|
||||
}
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
|
||||
|
||||
/*return 2 is expected.*/
|
||||
if (ret != ARRAY_SIZE(msg)) {
|
||||
err("%s: i2c_transfer ERROR(0x%0X). \n", __FUNCTION__, reg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_read_reg_u16);
|
||||
|
||||
int i2c_write_reg_u16(struct i2c_client* client, u8 reg, uint8_t* data)
|
||||
{
|
||||
int ret = 0;
|
||||
int len = 3;
|
||||
//uint8_t buf[len];
|
||||
uint8_t buf[3];
|
||||
struct i2c_msg msg;
|
||||
|
||||
if(client == NULL) {
|
||||
err("%s: i2c client is NULL.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(data == NULL) {
|
||||
err("%s: data is NULL.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = 0; /*write*/
|
||||
msg.len = len;
|
||||
msg.buf = buf;
|
||||
|
||||
if (!client->adapter)
|
||||
return -ENODEV;
|
||||
|
||||
buf[0] = reg;
|
||||
memcpy(buf + 1, &data[0], sizeof(data[0]));
|
||||
memcpy(buf + 2, &data[1], sizeof(data[1]));
|
||||
|
||||
|
||||
ret = i2c_transfer(client->adapter, &msg, 1);
|
||||
|
||||
/*return postive is expected.*/
|
||||
if(ret < 0){
|
||||
err("%s: i2c_transfer ERROR. (reg=0x%x, data_l=%d, data_h=%d, err = 0x%x)\n",
|
||||
__FUNCTION__, reg, data[0], data[1], ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_write_reg_u16);
|
136
drivers/sensors/ASH/ASH_Report/LwithRGBsensor_Report.c
Normal file
136
drivers/sensors/ASH/ASH_Report/LwithRGBsensor_Report.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************/
|
||||
/* IR Sensor Report Module */
|
||||
/***************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/*******************************/
|
||||
/* Debug and Log System */
|
||||
/*****************************/
|
||||
#define MODULE_NAME "ASH_Report"
|
||||
#define SENSOR_TYPE_NAME "light"
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_REPORT_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
/**********************/
|
||||
/*Global Variables*/
|
||||
/********************/
|
||||
static struct input_dev *input_dev_als = NULL;
|
||||
static int report_data[5] = {-1};
|
||||
void lrgbsensor_report_lux(void);
|
||||
|
||||
int lsensor_report_register(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Light Sensor Input event allocate */
|
||||
input_dev_als = input_allocate_device();
|
||||
if (!input_dev_als) {
|
||||
err("%s: lsensor input_allocate_device is return NULL Pointer. \n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Set Light Sensor input device */
|
||||
input_dev_als->name = "ASUS Lightsensor";
|
||||
input_dev_als->id.bustype = BUS_I2C;
|
||||
|
||||
input_set_capability(input_dev_als, EV_ABS, ABS_MISC);
|
||||
__set_bit(EV_ABS, input_dev_als->evbit);
|
||||
__set_bit(ABS_MISC, input_dev_als->absbit);
|
||||
input_set_abs_params(input_dev_als, ABS_MISC, 0, 65535, 0, 0);
|
||||
//input_set_drvdata(input_dev_als, g_als_data);
|
||||
|
||||
/* R raw data */
|
||||
input_set_capability(input_dev_als, EV_ABS, ABS_HAT0X);
|
||||
__set_bit(ABS_HAT0X, input_dev_als->absbit);
|
||||
input_set_abs_params(input_dev_als, ABS_HAT0X, 0, 65535, 0, 0);
|
||||
|
||||
/* G raw data */
|
||||
input_set_capability(input_dev_als, EV_ABS, ABS_HAT0Y);
|
||||
__set_bit(ABS_HAT0Y, input_dev_als->absbit);
|
||||
input_set_abs_params(input_dev_als, ABS_HAT0Y, 0, 65535, 0, 0);
|
||||
|
||||
/* B raw data */
|
||||
input_set_capability(input_dev_als, EV_ABS, ABS_HAT1X);
|
||||
__set_bit(ABS_HAT1X, input_dev_als->absbit);
|
||||
input_set_abs_params(input_dev_als, ABS_HAT1X, 0, 65535, 0, 0);
|
||||
|
||||
/* IR raw data */
|
||||
input_set_capability(input_dev_als, EV_ABS, ABS_HAT1Y);
|
||||
__set_bit(ABS_HAT1Y, input_dev_als->absbit);
|
||||
input_set_abs_params(input_dev_als, ABS_HAT1Y, 0, 65535, 0, 0);
|
||||
|
||||
/* Register Light Sensor input device */
|
||||
ret = input_register_device(input_dev_als);
|
||||
if (ret < 0) {
|
||||
err("%s: lsensor input_register_device ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbg("Input Event Success Registration\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_report_register);
|
||||
|
||||
void lsensor_report_unregister(void)
|
||||
{
|
||||
input_unregister_device(input_dev_als);
|
||||
input_free_device(input_dev_als);
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_report_unregister);
|
||||
|
||||
void lsensor_report_lux(int lux)
|
||||
{
|
||||
report_data[0] = lux;
|
||||
lrgbsensor_report_lux();
|
||||
}
|
||||
EXPORT_SYMBOL(lsensor_report_lux);
|
||||
|
||||
void FRGBsensor_report_raw(int *data, int size)
|
||||
{
|
||||
report_data[1] = data[0]; /* R */
|
||||
report_data[2] = data[1]; /* G */
|
||||
report_data[3] = data[2]; /* B */
|
||||
report_data[4] = data[3]; /* IR */
|
||||
lrgbsensor_report_lux();
|
||||
}
|
||||
EXPORT_SYMBOL(FRGBsensor_report_raw);
|
||||
|
||||
void lrgbsensor_report_lux(void)
|
||||
{
|
||||
static int count = 0;
|
||||
log("report lux=%d, count=%d", report_data[0], count);
|
||||
input_report_abs(input_dev_als, ABS_MISC, report_data[0]); /* LUX */
|
||||
input_report_abs(input_dev_als, ABS_HAT0X, count); /* R */
|
||||
input_report_abs(input_dev_als, ABS_HAT0Y, report_data[2]); /* G */
|
||||
input_report_abs(input_dev_als, ABS_HAT1X, report_data[3]); /* B */
|
||||
input_report_abs(input_dev_als, ABS_HAT1Y, report_data[4]); /* IR */
|
||||
input_event(input_dev_als, EV_SYN, SYN_REPORT, 5);
|
||||
input_sync(input_dev_als);
|
||||
count++;
|
||||
}
|
||||
|
97
drivers/sensors/ASH/ASH_Report/SARsensor_Report.c
Normal file
97
drivers/sensors/ASH/ASH_Report/SARsensor_Report.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************/
|
||||
/* Proximity Sensor Report Module */
|
||||
/***************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_Report"
|
||||
#define SENSOR_TYPE_NAME "SAR"
|
||||
#define SAR_SENSOR_INIT -1
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_REPORT_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
/******************/
|
||||
/*Global Variables*/
|
||||
/*****************/
|
||||
static struct input_dev *input_dev_sar = NULL;
|
||||
|
||||
int SAR_sensor_report_register(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* SAR Input event allocate */
|
||||
input_dev_sar = input_allocate_device();
|
||||
if (!input_dev_sar) {
|
||||
err("%s: SAR sensor input_allocate_device is return NULL Pointer. \n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Set SAR input device */
|
||||
input_dev_sar->name = "ASUS SARsensor";
|
||||
input_dev_sar->id.bustype = BUS_I2C;
|
||||
input_set_capability(input_dev_sar, EV_ABS, ABS_DISTANCE);
|
||||
__set_bit(EV_ABS, input_dev_sar->evbit);
|
||||
__set_bit(ABS_DISTANCE, input_dev_sar->absbit);
|
||||
input_set_abs_params(input_dev_sar, ABS_DISTANCE, 0, 1, 0, 0);
|
||||
//input_set_drvdata(input_dev_ps, g_ps_data);
|
||||
|
||||
/* Register SAR input device */
|
||||
ret = input_register_device(input_dev_sar);
|
||||
if (ret < 0) {
|
||||
err("%s: sar sensor input_register_device ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbg("Input Event Success Registration\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(SAR_sensor_report_register);
|
||||
|
||||
void SAR_sensor_report_unregister(void)
|
||||
{
|
||||
input_unregister_device(input_dev_sar);
|
||||
input_free_device(input_dev_sar);
|
||||
}
|
||||
EXPORT_SYMBOL(SAR_sensor_report_unregister);
|
||||
|
||||
void SAR_sensor_report_abs(int abs)
|
||||
{
|
||||
|
||||
if(abs != SAR_SENSOR_REPORT_AWAY &&
|
||||
abs != SAR_SENSOR_REPORT_CLOSE) {
|
||||
if (abs != SAR_SENSOR_INIT) {
|
||||
err("%s: Sar Detect Object ERROR.\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
input_report_abs(input_dev_sar, ABS_DISTANCE, abs);
|
||||
input_sync(input_dev_sar);
|
||||
}
|
||||
EXPORT_SYMBOL(SAR_sensor_report_abs);
|
||||
|
123
drivers/sensors/ASH/ASH_Report/psensor_Report.c
Normal file
123
drivers/sensors/ASH/ASH_Report/psensor_Report.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************/
|
||||
/* Proximity Sensor Report Module */
|
||||
/***************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/ASH.h>
|
||||
|
||||
/**************************/
|
||||
/* Debug and Log System */
|
||||
/************************/
|
||||
#define MODULE_NAME "ASH_Report"
|
||||
#define SENSOR_TYPE_NAME "proximity"
|
||||
#define PSENSOR_INIT -1
|
||||
|
||||
#undef dbg
|
||||
#ifdef ASH_REPORT_DEBUG
|
||||
#define dbg(fmt, args...) printk(KERN_DEBUG "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
#define log(fmt, args...) printk(KERN_INFO "[%s][%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,__func__,##args)
|
||||
#define err(fmt, args...) printk(KERN_ERR "[%s][%s]"fmt,MODULE_NAME,SENSOR_TYPE_NAME,##args)
|
||||
|
||||
/******************/
|
||||
/*Global Variables*/
|
||||
/*****************/
|
||||
static struct input_dev *input_dev_ps = NULL;
|
||||
static bool g_input_dev_reg_status = false;
|
||||
int psensor_report_register(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(true == g_input_dev_reg_status){
|
||||
err("%s: psensor input_register_device has been registered(%d). \n",
|
||||
__FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Proximity Input event allocate */
|
||||
input_dev_ps = input_allocate_device();
|
||||
if (!input_dev_ps) {
|
||||
err("%s: psensor input_allocate_device is return NULL Pointer. \n",
|
||||
__FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Set Proximity input device */
|
||||
input_dev_ps->name = "ASUS Proximitysensor";
|
||||
input_dev_ps->id.bustype = BUS_I2C;
|
||||
input_set_capability(input_dev_ps, EV_ABS, ABS_DISTANCE);
|
||||
__set_bit(EV_ABS, input_dev_ps->evbit);
|
||||
__set_bit(ABS_DISTANCE, input_dev_ps->absbit);
|
||||
input_set_abs_params(input_dev_ps, ABS_DISTANCE, 0, 1, 0, 0);
|
||||
//input_set_drvdata(input_dev_ps, g_ps_data);
|
||||
|
||||
/* Register Proximity input device */
|
||||
ret = input_register_device(input_dev_ps);
|
||||
if (ret < 0) {
|
||||
err("%s: psensor input_register_device ERROR(%d). \n", __FUNCTION__, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_input_dev_reg_status = true;
|
||||
dbg("Input Event Success Registration\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_report_register);
|
||||
|
||||
void psensor_report_unregister(void)
|
||||
{
|
||||
if(true == g_input_dev_reg_status){
|
||||
input_unregister_device(input_dev_ps);
|
||||
input_free_device(input_dev_ps);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_report_unregister);
|
||||
|
||||
void psensor_report_abs(int abs)
|
||||
{
|
||||
if(false == g_input_dev_reg_status){
|
||||
return;
|
||||
}
|
||||
#ifndef ONE_PL_CHIP
|
||||
if(abs != PSENSOR_REPORT_PS_AWAY &&
|
||||
abs != PSENSOR_REPORT_PS_CLOSE &&
|
||||
abs != PSENSOR_REPORT_PS_POCKET &&
|
||||
abs != PSENSOR_2ND_REPORT_PS_AWAY &&
|
||||
abs != PSENSOR_2ND_REPORT_PS_CLOSE &&
|
||||
abs != PSENSOR_2ND_REPORT_PS_POCKET) {
|
||||
if (abs != PSENSOR_INIT) {
|
||||
err("%s: Proximity Detect Object ERROR.\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(abs != PSENSOR_REPORT_PS_AWAY &&
|
||||
abs != PSENSOR_REPORT_PS_CLOSE &&
|
||||
abs != PSENSOR_REPORT_PS_POCKET) {
|
||||
if (abs != PSENSOR_INIT) {
|
||||
err("%s: Proximity Detect Object ERROR.\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
input_report_abs(input_dev_ps, ABS_DISTANCE, abs);
|
||||
input_sync(input_dev_ps);
|
||||
}
|
||||
EXPORT_SYMBOL(psensor_report_abs);
|
||||
|
24
drivers/sensors/ASH/Makefile
Normal file
24
drivers/sensors/ASH/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=ANDROID_GKI_VFS_EXPORT_ONLY
|
||||
ccflags-y += -DANDROID_GKI_VFS_EXPORT_ONLY=VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver
|
||||
|
||||
obj-m := sensors_vcnl36866.o
|
||||
sensors_vcnl36866-y += ASH_Algo/ALSPSsensor.o
|
||||
sensors_vcnl36866-y += ASH_ATTR/lsensor_ATTR.o ASH_ATTR/psensor_ATTR.o ASH_ATTR/ASH_ATTR.o
|
||||
sensors_vcnl36866-y += ASH_Report/psensor_Report.o ASH_Report/LwithRGBsensor_Report.o
|
||||
sensors_vcnl36866-y += ASH_Factory/psensor_Factory.o ASH_Factory/lsensor_Factory.o
|
||||
sensors_vcnl36866-y += ASH_GPIO/ALSPSsensor_GPIO.o
|
||||
sensors_vcnl36866-y += ASH_Hardware/ASH_Hardware.o ASH_Hardware/ALSPSsensor_Hardware/ALSPSsensor_Hardware.o ASH_Hardware/ALSPSsensor_Hardware/vcnl36866/vcnl36866.o
|
||||
|
||||
ifeq ($(CONFIG_MACH_ASUS_SAKE),y)
|
||||
sensors_vcnl36866-y += ASH_Hardware/ALSPSsensor_Hardware/ams_tmd2755/ams_tmd2755.o
|
||||
sensors_vcnl36866-y += ASH_Hardware/ALSPSsensor_Hardware/ams_tmd2755/ams_tmd2755_prox.o
|
||||
sensors_vcnl36866-y += ASH_Hardware/ALSPSsensor_Hardware/ams_tmd2755/ams_tmd2755_als.o
|
||||
sensors_vcnl36866-y += ASH_Hardware/ALSPSsensor_Hardware/ams_tmd2755/ams_i2c.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MACH_ASUS_VODKA),y)
|
||||
sensors_vcnl36866-y += ASH_Algo/ALSPSsensor_2nd.o
|
||||
sensors_vcnl36866-y += ASH_ATTR/lsensor_2nd_ATTR.o ASH_ATTR/psensor_2nd_ATTR.o
|
||||
sensors_vcnl36866-y += ASH_GPIO/ALSPSsensor_GPIO_2nd.o
|
||||
sensors_vcnl36866-y += ASH_Hardware/ALSPSsensor_Hardware/ALSPSsensor_Hardware_2nd.o ASH_Hardware/ALSPSsensor_Hardware/vcnl36866_2nd/vcnl36866_2nd.o
|
||||
endif
|
@ -1 +1,14 @@
|
||||
obj-m += icm206xx.o
|
||||
obj-y += ASH/
|
||||
|
||||
ifeq ($(CONFIG_MACH_ASUS_SAKE),y)
|
||||
KBUILD_CFLAGS += -DCONFIG_TMD2755_FLAG=1
|
||||
KBUILD_CFLAGS += -DONE_PL_CHIP
|
||||
KBUILD_CFLAGS += -DPSENSOR_CAL24
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MACH_ASUS_VODKA),y)
|
||||
KBUILD_CFLAGS += -DLONG_LENGTH_LOGN_IT_PERF=1
|
||||
KBUILD_CFLAGS += -DRECOVERY_PSENSOR
|
||||
KBUILD_CFLAGS += -DPSENSOR_CAL24
|
||||
endif
|
||||
|
1129
include/linux/input/ASH.h
Normal file
1129
include/linux/input/ASH.h
Normal file
File diff suppressed because it is too large
Load Diff
216
include/linux/input/SAR.h
Normal file
216
include/linux/input/SAR.h
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (C) 2019 ASUSTek Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SAR_H
|
||||
#define __LINUX_SAR_H
|
||||
|
||||
#define NAME_SIZE (10)
|
||||
|
||||
/**
|
||||
* Define the SAR report event values.
|
||||
* @SAR_SENSOR_REPORT_PS_CLOSE : report close event.
|
||||
* @SAE_SENSOR_REPORT_PS_AWAY : report away event.
|
||||
*/
|
||||
#define SAR_SENSOR_REPORT_CLOSE (1)
|
||||
#define SAR_SENSOR_REPORT_AWAY (0)
|
||||
|
||||
#define OBJECT_NEAR (1)
|
||||
#define OBJECT_FAR (0)
|
||||
|
||||
/**
|
||||
* Define the proxstat bit of SAR sensor,
|
||||
* which indicates if proximity is currently detected by CSx.
|
||||
* @PROXSTAT0 : CS0 detect
|
||||
* @RROXSTAT1 : CS1 detect
|
||||
* @PROXSTAT2 : CS2 detect
|
||||
* @PROXSTAT3 : CS3 detect
|
||||
*/
|
||||
#define PROXSTAT0 (0x00)
|
||||
#define PROXSTAT1 (0x02)
|
||||
#define PROXSTAT2 (0x04)
|
||||
#define PROXSTAT3 (0x08)
|
||||
|
||||
/**
|
||||
* SAR_sensor_report_register - before report SAR sensor event
|
||||
* you need to register first. This will create input device for SAR sensor.
|
||||
*/
|
||||
extern int SAR_sensor_report_register(void);
|
||||
|
||||
/**
|
||||
* SAR_sensor_report_unregister - Remove the input device for SAR sensor.
|
||||
*/
|
||||
extern void SAR_sensor_report_unregister(void);
|
||||
|
||||
/**
|
||||
* SAR_sensor_report_abs - report the SAR abs.
|
||||
* @ abs=SAR_SENSOR_REPORT_CLOSE : report close event.
|
||||
* @ abs=SAR_SENSOR_REPORT_AWAY : report away event.
|
||||
*/
|
||||
extern void SAR_sensor_report_abs(int abs);
|
||||
|
||||
/**
|
||||
* SAR_sensor_GPIO
|
||||
*/
|
||||
typedef struct SAR_sensor_GPIO {
|
||||
void (*SAR_sensor_isr)(void);
|
||||
}SAR_sensor_GPIO;
|
||||
|
||||
/**
|
||||
* SAR_sensor_gpio_register - register the GPIO setting and set the IRQ handler.
|
||||
* Return the IRQ.
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
extern int SAR_sensor_gpio_register(struct i2c_client *client, SAR_sensor_GPIO *gpio_ist);
|
||||
|
||||
/**
|
||||
* SAR_sensor_gpio_unregister - unregister the GPIO setting.
|
||||
*/
|
||||
extern int SAR_sensor_gpio_unregister(int irq);
|
||||
|
||||
/**
|
||||
* SAR_sensor_gpio_value - return the gpio value.
|
||||
*/
|
||||
extern int SAR_sensor_gpio_value(void);
|
||||
|
||||
/**
|
||||
SAR_sensor_I2C - We define functions for i2c driver.
|
||||
* @SAR_sensor_probe : It will be run when "i2c_add_driver" has been called.
|
||||
* @SAR_sensor_remove : Remove all Memory.
|
||||
* @SAR_sensor_shutdown : Turn off all sensors.
|
||||
* @SAR_sensor_suspend : Do what suspend should do.
|
||||
* @SAR_sensor_resume : Do what resume should do.
|
||||
*/
|
||||
typedef struct SAR_sensor_I2C {
|
||||
void (*SAR_sensor_probe)(struct i2c_client *client);
|
||||
void (*SAR_sensor_remove)(void);
|
||||
void (*SAR_sensor_shutdown)(void);
|
||||
void (*SAR_sensor_suspend)(void);
|
||||
void (*SAR_sensor_resume)(void);
|
||||
}SAR_sensor_I2C;
|
||||
|
||||
/**
|
||||
* SAR_sensor_hw - the i2c control functions for SAR sensor
|
||||
*/
|
||||
typedef struct SAR_sensor_hw {
|
||||
char vendor[NAME_SIZE];
|
||||
char module_number[NAME_SIZE];
|
||||
|
||||
int (*SAR_sensor_hw_check_ID)(void);
|
||||
int (*SAR_sensor_hw_init)(struct i2c_client* client);
|
||||
int (*SAR_sensor_hw_read_regStat)(void);
|
||||
int (*SAR_sensor_hw_get_interrupt)(void);
|
||||
int (*SAR_sensor_hw_show_allreg)(void);
|
||||
int (*SAR_sensor_hw_set_register)(uint8_t reg, int value);
|
||||
int (*SAR_sensor_hw_get_register)(uint8_t reg);
|
||||
int (*SAR_sensor_hw_turn_onoff)(bool bOn);
|
||||
int (*SAR_sensor_hw__get_proxuserful)(uint8_t cs);
|
||||
int (*SAR_sensor_hw_read_rawData)(void);
|
||||
int (*SAR_sensor_hw_get_manual_offset_cal)(void);
|
||||
int (*SAR_sensor_hw_manual_offset_cal)(int value);
|
||||
}SAR_sensor_hw;
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR_BMMI - attributes for SAR_sensor BMMI.
|
||||
*/
|
||||
typedef struct{
|
||||
bool (*SAR_sensor_show_atd_test)(void);
|
||||
int (*SAR_sensor_show_raw_data)(void);
|
||||
}SAR_sensor_ATTR_BMMI;
|
||||
|
||||
/**
|
||||
* SAR_sensor_info_type - define the SAR_sensor information.
|
||||
* @vendor : ASUS.
|
||||
* @version : driver version.
|
||||
* @module_number : hardware chip serial number.
|
||||
*/
|
||||
#define NAME_SIZE (10)
|
||||
typedef struct{
|
||||
char vendor[NAME_SIZE];
|
||||
char module_number[NAME_SIZE];
|
||||
}SAR_sensor_info_type;
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR_HAL - attributes for SAR_sensor HAL function.
|
||||
*/
|
||||
typedef struct{
|
||||
bool (*SAR_sensor_show_switch_onoff)(void);
|
||||
int (*SAR_sensor_store_switch_onoff)(bool bOn);
|
||||
int (*SAR_sensor_show_Interrupt_detect_status)(void);
|
||||
bool (*SAR_sensor_show_sar_status)(void);
|
||||
}SAR_sensor_ATTR_HAL;
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR_Hardware - attributes for SAR_sensor hardware read/write.
|
||||
*/
|
||||
typedef struct{
|
||||
uint8_t show_reg_addr;
|
||||
int (*SAR_show_reg)(uint8_t addr);
|
||||
int (*SAR_store_reg)(uint8_t addr, int value);
|
||||
int (*SAR_sensor_show_manual_offset_cal)(void);
|
||||
int (*SAR_sensor_store_manual_offset_cal)(int value);
|
||||
}SAR_sensor_ATTR_Hardware;
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR_Extension - attributes for SAR_sensor extensive functions.
|
||||
*/
|
||||
typedef struct{
|
||||
bool (*SAR_sensor_show_allreg)(void);
|
||||
}SAR_sensor_ATTR_Extension;
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR - attributes for lsensor.
|
||||
*/
|
||||
typedef struct{
|
||||
SAR_sensor_info_type *info_type;
|
||||
SAR_sensor_ATTR_BMMI *ATTR_BMMI;
|
||||
SAR_sensor_ATTR_HAL *ATTR_HAL;
|
||||
SAR_sensor_ATTR_Hardware *ATTR_Hardware;
|
||||
SAR_sensor_ATTR_Extension *ATTR_Extension;
|
||||
}SAR_sensor_ATTR;
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR_register - assign a psensor only file node and create the attributes.
|
||||
*
|
||||
* The attributes will be created at /sys/class/sensors/SAR_sensor.
|
||||
*/
|
||||
extern int SAR_sensor_ATTR_register(SAR_sensor_ATTR *mATTR);
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR_unregister - remove the SAR_sensor attributes.
|
||||
*/
|
||||
extern int SAR_sensor_ATTR_unregister(void);
|
||||
|
||||
/**
|
||||
* SAR_sensor_ATTR_create - create SAR_sensor customize attributes.
|
||||
* @mSAR_sensor_attr : the pointer of device_attribute, which you want to create attribute.
|
||||
*/
|
||||
extern int SAR_sensor_ATTR_create(struct device_attribute *mSAR_sensor_attr);
|
||||
|
||||
|
||||
/**
|
||||
* SAR_sensor_i2c_register - struct SAR_sensor_I2C wrapped by i2c driver.
|
||||
*/
|
||||
extern int SAR_sensor_i2c_register(SAR_sensor_I2C *ir_i2c);
|
||||
|
||||
/**
|
||||
* SAR_sensor_hw_getHardware - Before this function, you SHOULD execute SAR_sensor_i2c_register first.
|
||||
*/
|
||||
extern SAR_sensor_hw* SAR_sensor_hw_getHardware(void);
|
||||
|
||||
/**
|
||||
* SAR_sensor_i2c_unregister - i2c_del_driver.
|
||||
*/
|
||||
extern int SAR_sensor_i2c_unregister(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user