OrangePi3 LTS 驱动开发-感光芯片veml7700
kernel版本:orange-pi-5.10-media
dts配置在上一章的基础上增加以下内容:
&i2c0 {
clock-frequency = <100000>;
status = "okay";
// at24c02@50{
// compatible = "atmel,24c02";
// reg = <0x50>;
// status = "okay";
// };
veml7700@10{
compatible = "max,veml7700";
reg = <0x10>;
status = "okay";
};
};
驱动主要有以下几个步骤:
1、i2c_driver的注册
2、veml7700的初始化
3、相关节点的创建
4、input设备的注册以及上报。(这一步可以省略,app直接轮询解析也可以,但是上报input子系统后,我们可以解析/dev/input/eventx节点得到我们想要的光感lux值)
相关节点的解析:
cat /sys/class/max_veml7700/veml7700/support 为1 ,表示有光感设备,0表示没有光感设备。
enable 为开关
delay 驱动中上报input的时间间隔
power_mode 表示工作模式
gain 增益调整
it 整合时间调整
lux当前寄存器中光感数值,需要计算得到真实光感值,在APP里处理计算。
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/leds.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/input.h>
#include <linux/of_irq.h>
#include <linux/irq.h>
#include "veml7700.h"
static int max_i2c_read(struct i2c_adapter *i2c_adap,
unsigned char address, unsigned char *wdata,
unsigned int wlen, unsigned char *rdata,unsigned int rlen)
{
struct i2c_msg msgs[2];
int res;
if (!rdata || !i2c_adap)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return -EINVAL;
}
msgs[0].addr = address;
msgs[0].flags = 0; /* write */
msgs[0].buf = wdata;
msgs[0].len = wlen;
msgs[1].addr = address;
msgs[1].flags = I2C_M_RD;
msgs[1].buf = rdata;
msgs[1].len = rlen;
res = i2c_transfer(i2c_adap, msgs, 2);
if (res == 2)
return 0;
else if(res == 0)
return -EBUSY;
else
return res;
return res;
}
int max_i2c_rx_data(struct i2c_client *client, char * txData,int tlen,char *rxData, int rlen)
{
int ret = 0;
int i = 0;
for (i = 0; i < 2; i++)
{
ret = max_i2c_read(client->adapter, client->addr, txData,tlen,rxData,rlen);
if (ret < 0)
{
printk("max_i2c_rx_data error\n");
}
else
{
break;
}
}
return ret;
}
static int max_i2c_veml7700_read(struct i2c_client *client,uint8_t addr,uint8_t *r_data)
{
return max_i2c_rx_data(client,&addr,1,r_data,2);
}
static int max_i2c_write(struct i2c_adapter *i2c_adap,
unsigned char address,
unsigned int len, unsigned char const *data)
{
struct i2c_msg msgs[1];
int res;
if (!data || !i2c_adap)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return -EINVAL;
}
msgs[0].addr = address;
msgs[0].flags = 0;
msgs[0].buf = (unsigned char *)data;
msgs[0].len = len;
res = i2c_transfer(i2c_adap, msgs, 1);
//printk("i2c_transfer res = %d\n",res);
if (res == 1)
return 0;
else if(res == 0)
return -EBUSY;
else
return res;
}
int max_i2c_tx_data(struct i2c_client *client, char *txData, int length)
{
int ret = 0;
int i = 0;
for (i = 0; i < 3; i++)
{
ret = max_i2c_write(client->adapter, client->addr, length, txData);
if (!ret)
break;
}
return ret;
}
static int max_i2c_veml7700_write(struct i2c_client *client,uint8_t addr,uint8_t *w_data)
{
uint8_t w_buff[3] = {0};
w_buff[0] = addr;
w_buff[1] = w_data[0];
w_buff[2] = w_data[1];
return max_i2c_tx_data(client,w_buff,3);
}
static int max_veml7700_get_value(struct i2c_client *client,int command,int mask,int shift,unsigned short *value)
{
int ret = 0;
unsigned short tmp_value = 0;
unsigned char r_data[2] = {0};
ret = max_i2c_veml7700_read(client,command,r_data);
if (ret != 0 )
{
printk("max_i2c_veml7700_read error\n");
}
else
{
tmp_value = ((r_data[1] << 8) | r_data[0]);
tmp_value = (tmp_value & mask ) >> shift;
*value = tmp_value;
}
return ret;
}
static int max_veml7700_set_value(struct i2c_client *client,int command,int mask,int shift,unsigned short value)
{
int ret;
unsigned short tmp_value = 0;
unsigned short w_value = 0;
unsigned char r_data[2] = {0};
unsigned char w_data[2] = {0};
ret = max_i2c_veml7700_read(client,command,r_data);
tmp_value = ((r_data[1] << 8) | r_data[0]);
w_value = (tmp_value & ~mask);
w_value |= ((value << shift) & mask);
w_data[0] = w_value & 0xFF;
w_data[1] = w_value >> 8;
ret = max_i2c_veml7700_write(client,command,w_data);
return ret;
}
static int max_veml7700_get_power_mode(struct i2c_client *client,unsigned short *mode)
{
return max_veml7700_get_value(client,COMMAND_ALS_SD,ALS_SD_MASK,ALS_SD_SHIFT,mode);
}
static int max_veml7700_set_power_mode(struct i2c_client *client,int mode)
{
return max_veml7700_set_value(client,COMMAND_ALS_SD,ALS_SD_MASK,ALS_SD_SHIFT,mode);
}
static int max_veml7700_get_interrupt_mode(struct i2c_client *client,unsigned short *mode)
{
return max_veml7700_get_value(client,COMMAND_ALS_INT_EN,ALS_INT_EN_MASK,ALS_INT_EN_SHIFT,mode);
}
static int max_veml7700_set_interrupt_mode(struct i2c_client *client,unsigned short mode)
{
return max_veml7700_set_value(client,COMMAND_ALS_INT_EN,ALS_INT_EN_MASK,ALS_INT_EN_SHIFT,mode);
}
static int max_veml7700_get_gain(struct i2c_client *client,unsigned short *gain_value)
{
return max_veml7700_get_value(client,COMMAND_ALS_GAIN,ALS_GAIN_MASK,ALS_GAIN_SHIFT,gain_value);
}
static int max_veml7700_set_gain(struct i2c_client *client,unsigned short gain_value)
{
return max_veml7700_set_value(client,COMMAND_ALS_GAIN,ALS_GAIN_MASK,ALS_GAIN_SHIFT,gain_value);
}
static int max_veml7700_get_integration_time(struct i2c_client *client,unsigned short *time)
{
return max_veml7700_get_value(client,COMMAND_ALS_IT,ALS_IT_MASK,ALS_IT_SHIFT,time);
}
static int max_veml7700_set_integration_time(struct i2c_client *client,unsigned short time)
{
return max_veml7700_set_value(client,COMMAND_ALS_IT,ALS_IT_MASK,ALS_IT_SHIFT,time);
}
static int max_veml7700_get_power_saving_mode(struct i2c_client *client,unsigned short *mode)
{
return max_veml7700_get_value(client,COMMAND_PSM,PSM_MASK,PSM_SHIFT,mode);
}
static int max_veml7700_set_power_saving_mode(struct i2c_client *client,unsigned short mode)
{
return max_veml7700_set_value(client,COMMAND_PSM,PSM_MASK,PSM_SHIFT,mode);
}
static int max_veml7700_get_power_saving_enable(struct i2c_client *client,unsigned short *enable)
{
return max_veml7700_get_value(client,COMMAND_PSM_EN,PSM_EN_MASK,PSM_EN_SHIFT,enable);
}
static int max_veml7700_set_power_saving_enable(struct i2c_client *client,unsigned short enable)
{
return max_veml7700_set_value(client,COMMAND_PSM_EN,PSM_EN_MASK,PSM_EN_SHIFT,enable);
}
static int max_veml7700_get_lux(struct i2c_client *client ,unsigned short *lux_value)
{
int ret = 0;
unsigned char r_data[2] = {0};
ret = max_i2c_veml7700_read(client,COMMAND_ALS_DATA,r_data);
*lux_value = ((r_data[1] << 8) | r_data[0]);
return ret;
}
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", DRIVER_NAME);
}
static DEVICE_ATTR(name, 0444, name_show,NULL);
static ssize_t power_mode_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
unsigned short value = 0;
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
max_veml7700_get_power_mode(veml7700_driver->client,&value);
switch (value)
{
case 0/* constant-expression */:
/* code */
return sprintf(buf, "%s\n", "Power On");
break;
case 1:
return sprintf(buf, "%s\n", "Shut Down");
break;
default:
break;
}
return sprintf(buf, "%s\n", "Error");
}
static ssize_t power_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
uint8_t value;
int ret;
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
ret = kstrtou8(buf, 0, &value);// auto data format
if (ret)
{
printk("kstrtou8 error\n");
return -ENODEV;
}
if (value == 0x00 || value == 0x01)
{
ret = max_veml7700_set_power_mode(veml7700_driver->client,value);
}
else
{
printk("input value error,must only one in 0x00/0x01\n");
}
return count;
}
static DEVICE_ATTR(power_mode, 0664, power_mode_show,power_mode_store);
static ssize_t veml7700_lux_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
unsigned short value = 0;
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
if (veml7700_driver->is_support)
{
max_veml7700_get_lux(veml7700_driver->client,&value);
return sprintf(buf, "%d\n", value);
}
else
{
return sprintf(buf, "%s\n", "not support light sensor");
}
}
static DEVICE_ATTR(lux, 0444, veml7700_lux_show,NULL);
static ssize_t veml7700_enable_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
return sprintf(buf, "%d\n", veml7700_driver->enable);
}
static ssize_t veml7700_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
uint8_t value;
int ret;
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
ret = kstrtou8(buf, 0, &value);// auto data format
if (ret)
{
printk("kstrtou8 error\n");
return -ENODEV;
}
if (value == 0x00 || value == 0x01)
{
if (veml7700_driver->enable == 0 && value == 1)
{
schedule_delayed_work(&veml7700_driver->work, msecs_to_jiffies(veml7700_driver->delay));
}
veml7700_driver->enable = value;
}
else
{
printk("input value error,must only one in 0x00/0x01\n");
}
return count;
}
static DEVICE_ATTR(enable, 0664, veml7700_enable_show,veml7700_enable_store);
static ssize_t veml7700_delay_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
return sprintf(buf, "%d\n", veml7700_driver->delay);
}
static ssize_t veml7700_delay_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int value;
int ret;
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
ret = kstrtou32(buf, 0, &value);// auto data format
if (ret)
{
printk("kstrtou8 error\n");
return -ENODEV;
}
veml7700_driver->delay = value;
return count;
}
static DEVICE_ATTR(delay, 0664, veml7700_delay_show,veml7700_delay_store);
static ssize_t veml7700_support_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
return sprintf(buf, "%d\n", veml7700_driver->is_support);
}
static DEVICE_ATTR(support, 0444, veml7700_support_show,NULL);
static ssize_t veml7700_gain_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
unsigned short gain = 0;
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
max_veml7700_get_gain(veml7700_driver->client,&gain);
return sprintf(buf, "%d\n", gain);
}
static ssize_t veml7700_gain_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int value;
int ret;
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
ret = kstrtou32(buf, 0, &value);// auto data format
if (ret)
{
printk("kstrtou8 error\n");
return -ENODEV;
}
if (value == ALS_GAIN_X1 || value == ALS_GAIN_X2 || value == ALS_GAIN_d8 || value == ALS_GAIN_d4)
{
max_veml7700_set_gain(veml7700_driver->client,value);
}
return count;
}
static DEVICE_ATTR(gain, 0664, veml7700_gain_show,veml7700_gain_store);
static ssize_t veml7700_it_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
unsigned short it = 0;
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
max_veml7700_get_integration_time(veml7700_driver->client,&it);
return sprintf(buf, "%d\n", it);
}
static ssize_t veml7700_it_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int value;
int ret;
struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
printk("get max_veml7700_driver error\n");
return -ENODEV;
}
ret = kstrtou32(buf, 0, &value);// auto data format
if (ret)
{
printk("kstrtou8 error\n");
return -ENODEV;
}
if (value == ALS_INTEGRATION_25ms || value == ALS_INTEGRATION_50ms || value == ALS_INTEGRATION_100ms ||
value == ALS_INTEGRATION_200ms || value == ALS_INTEGRATION_400ms|| value == ALS_INTEGRATION_800ms){
max_veml7700_set_integration_time(veml7700_driver->client,value);
}
return count;
}
static DEVICE_ATTR(it, 0664, veml7700_it_show,veml7700_it_store);
static struct attribute *attrs[] = {
&dev_attr_name.attr,
&dev_attr_power_mode.attr,
&dev_attr_lux.attr,
&dev_attr_enable.attr,
&dev_attr_delay.attr,
&dev_attr_support.attr,
&dev_attr_gain.attr,
&dev_attr_it.attr,
NULL, /* need to NULL terminate the list of attributes */
};
static struct attribute_group attr_group = {
.attrs = attrs,
};
/**
* @brief 获取dts注册的信息
*
* @param client
* @return int
*/
static int dts_parse(struct i2c_client *client)
{
//int ret = 0;
struct device_node *node;
//const char *str;
//struct max_veml7700_driver *veml7700_driver = i2c_get_clientdata(client);
node = client->dev.of_node;
if (!node)
{
printk("no node for %s\n",DEVICE_NAME);
goto error;
}
if (!of_device_is_available(node))
{
printk("dts status is not okay \n");
goto error;
}
return 0;
error:
return -EINVAL;
}
static int veml7700_init(struct i2c_client *client)
{
int ret = -1;
unsigned short mode = -1;
ret = max_veml7700_set_power_mode(client,ALS_POWER_SHUTDOWN);
//printk("max_veml7700_set_power_mode ret == %d\n",ret);
ret |= max_veml7700_set_interrupt_mode(client,ALS_INTERRUPT_DISABLE);
//printk("max_veml7700_set_interrupt_mode ret == %d\n",ret);
max_veml7700_get_interrupt_mode(client,&mode);
printk("get interrupt mode == %s \n", mode == 0 ? "disable" : "enable");
ret |= max_veml7700_set_gain(client,ALS_GAIN_X1);
//printk("max_veml7700_set_gain ret == %d\n",ret);
max_veml7700_get_gain(client,&mode);
printk("get gain == %s \n", mode == 0x2 ? "ALS_GAIN_X1" : "other");
ret |= max_veml7700_set_integration_time(client,ALS_INTEGRATION_100ms);
//printk("max_veml7700_set_integration_time ret == %d\n",ret);
max_veml7700_get_integration_time(client,&mode);
printk("get integration time == %s \n", mode == ALS_INTEGRATION_100ms ? "100ms" : "other");
ret |= max_veml7700_set_power_saving_mode(client,ALS_POWER_MODE_3);
//printk("max_veml7700_set_power_saving_mode ret == %d\n",ret);
max_veml7700_get_power_saving_mode(client,&mode);
printk("get power save mode == %s \n", mode == ALS_POWER_MODE_3 ? "ALS_POWER_MODE_3" : "other");
ret |= max_veml7700_set_power_saving_enable(client,ALS_POWER_MODE_DISABLE);
//printk("max_veml7700_set_power_saving_enable ret == %d\n",ret);
max_veml7700_get_power_saving_enable(client,&mode);
printk("max_veml7700_get_power_saving_enable == %s \n", mode == ALS_POWER_MODE_DISABLE ? "ALS_POWER_MODE_DISABLE" : "other");
ret |= max_veml7700_set_power_mode(client,ALS_POWER_ON);
//printk("max_veml7700_set_power_mode ret == %d\n",ret);
max_veml7700_get_power_mode(client,&mode);
printk("max_veml7700_get_power_mode == %s \n", mode == ALS_POWER_ON ? "ALS_POWER_ON" : "other");
return ret;
}
static void veml7700_schedele_work(struct work_struct *work)
{
unsigned short lux_value = 0;
struct max_veml7700_driver *veml7700_driver = container_of((struct delayed_work *)work,
struct max_veml7700_driver, work);
max_veml7700_get_lux(veml7700_driver->client,&lux_value);
//printk("get current lux value == %d \n",lux_value);
input_event(veml7700_driver->input_dev,EV_MSC,MSC_RAW,lux_value);
input_sync(veml7700_driver->input_dev);
if (veml7700_driver->enable)
schedule_delayed_work(&veml7700_driver->work, msecs_to_jiffies(veml7700_driver->delay));
}
static int max_veml7700_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
struct max_veml7700_driver *veml7700_driver = NULL;
static struct class *veml7700_class;
printk("get client addr == 0x%2x\n",client->addr);
veml7700_driver = kzalloc(sizeof(struct max_veml7700_driver), GFP_KERNEL);
if (veml7700_driver == NULL) {
printk("failed to create our veml7700_driver\n");
return -ENOMEM;
}
veml7700_driver->client = client;
i2c_set_clientdata(client,veml7700_driver);
ret = dts_parse(client);
if (ret){
printk("dts parse error\n");
goto dts_error;
}
veml7700_class = class_create(THIS_MODULE, DRIVER_NAME);
if (IS_ERR(veml7700_class)) {
ret= PTR_ERR(veml7700_class);
printk("veml7700_class: class create failed\n");
goto dts_error;
}
veml7700_driver->dev = device_create(veml7700_class,
&client->dev, 0, NULL, DEVICE_NAME);
if (unlikely(IS_ERR(veml7700_driver->dev))) {
ret = PTR_ERR(veml7700_driver->dev);
veml7700_driver->dev = NULL;
goto destory_class;
}
ret = sysfs_create_group(&veml7700_driver->dev->kobj, &attr_group);
if(ret){
printk("sysfs_create_group in msa311 driver\n");
goto destory_device;
}
veml7700_driver->delay = 3000;
veml7700_driver->enable = 0;
//申请注册input系统
veml7700_driver->input_dev = input_allocate_device();
if (!veml7700_driver->input_dev)
{
printk("input_allocate_device error\n");
}
veml7700_driver->input_dev->name = DEVICE_NAME;
veml7700_driver->input_dev->id.bustype = BUS_I2C;
veml7700_driver->input_dev->dev.parent = veml7700_driver->dev;
// 设置所支持的事件类型
__set_bit(EV_MSC,veml7700_driver->input_dev->evbit);
__set_bit(MSC_RAW,veml7700_driver->input_dev->mscbit);
ret = input_register_device(veml7700_driver->input_dev);
if (ret < 0) {
input_free_device(veml7700_driver->input_dev);
goto destory_device;
}
ret = veml7700_init(veml7700_driver->client);
if (ret != 0)
{
printk("veml7700_init error and maybe don't support light sensor\n");
veml7700_driver->enable = 0;
veml7700_driver->is_support = 0;
}
else
{
printk("veml7700_init Success !\n");
veml7700_driver->is_support = 1;
veml7700_driver->enable = 1;
}
INIT_DELAYED_WORK(&veml7700_driver->work, veml7700_schedele_work);
if (veml7700_driver->enable == 1 && veml7700_driver->is_support == 1)
schedule_delayed_work(&veml7700_driver->work, msecs_to_jiffies(veml7700_driver->delay));
input_set_drvdata(veml7700_driver->input_dev,veml7700_driver);
dev_set_drvdata(veml7700_driver->dev, veml7700_driver);
printk("max_veml7700_probe Ok !\n ");
return 0;
destory_device:
device_destroy(veml7700_class,0);
destory_class:
class_destroy(veml7700_class);
dts_error:
kfree(veml7700_driver);
return -ENODEV;
}
/**
* @brief
*
* @param client
* @return int
*/
static int max_veml7700_remove(struct i2c_client *client)
{
return 0;
}
static const struct of_device_id i2c_veml7700_of_match[] = {
{ .compatible = "max,veml7700" },
{ }
};
static const struct i2c_device_id veml_device_id[] = {
{DEVICE_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, veml_device_id);
static struct i2c_driver max_veml7700_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(i2c_veml7700_of_match),
},
.probe = max_veml7700_probe,
.remove = max_veml7700_remove,
.id_table = veml_device_id,
};
static int __init max_veml7700_init(void)
{
printk("max_veml7700_init \n");
i2c_add_driver(&max_veml7700_driver);
return 0;
}
static void __exit max_veml7700_exit(void)
{
i2c_del_driver(&max_veml7700_driver);
}
module_init(max_veml7700_init);
module_exit(max_veml7700_exit);
MODULE_DESCRIPTION("max Veml7700 sensor Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("738270732@qq.com");
veml7700.h
#ifndef __VEML7700_H__
#define __VEML7700_H__
#define DRIVER_NAME "max_veml7700"
#define DEVICE_NAME "veml7700"
#define COMMAND_ALS_DEFAULT_VALUE 0x01
// Gain Register
#define COMMAND_ALS_GAIN 0x00
#define ALS_GAIN_MASK 0x1800
#define ALS_GAIN_SHIFT 11
// ALS IT Register
#define COMMAND_ALS_IT 0x00
#define ALS_IT_MASK 0x03C0
#define ALS_IT_SHIFT 6
// ALS Persistence Register
#define COMMAND_ALS_PER 0x00
#define ALS_PER_MASK 0x0030
#define ALS_PER_SHIFT 4
// ALS INT EN Register
#define COMMAND_ALS_INT_EN 0x00
#define ALS_INT_EN_MASK 0x0002
#define ALS_INT_EN_SHIFT 1
// ALS SD Register
#define COMMAND_ALS_SD 0x00
#define ALS_SD_MASK 0x0001
#define ALS_SD_SHIFT 0
// ALS Window High
#define COMMAND_ALS_WH 0x01
// ALS Window Low
#define COMMAND_ALS_WL 0x02
// ALS Power Save Mode
#define COMMAND_PSM 0x03
#define PSM_MASK 0x0006
#define PSM_SHIFT 1
// ALS Power Save Mode Enable
#define COMMAND_PSM_EN 0x03
#define PSM_EN_MASK 0x0001
#define PSM_EN_SHIFT 0
// ALS High Resolution Output Data
#define COMMAND_ALS_DATA 0x04
//White Channel Output Data
#define COMMAND_WHITE_DATA 0x05
// Interrupt Status
#define COMMAND_ALS_IF_L 0x06
#define ALS_IF_L_MASK 0x8000
#define ALS_IF_L_SHIFT 15
#define COMMAND_ALS_IF_H 0x06
#define ALS_IF_H_MASK 0x4000
#define ALS_IF_H_SHIFT 14
#define ALS_GAIN_X1 0x0
#define ALS_GAIN_X2 0x1
#define ALS_GAIN_d8 0x2
#define ALS_GAIN_d4 0x3
#define ALS_INTEGRATION_25ms 0xC
#define ALS_INTEGRATION_50ms 0x8
#define ALS_INTEGRATION_100ms 0x0
#define ALS_INTEGRATION_200ms 0x1
#define ALS_INTEGRATION_400ms 0x2
#define ALS_INTEGRATION_800ms 0x3
#define ALS_PERSISTENCE_1 0x0
#define ALS_PERSISTENCE_2 0x1
#define ALS_PERSISTENCE_4 0x2
#define ALS_PERSISTENCE_8 0x3
#define ALS_POWER_MODE_1 0x0
#define ALS_POWER_MODE_2 0x1
#define ALS_POWER_MODE_3 0x2
#define ALS_POWER_MODE_4 0x3
#define ALS_POWER_MODE_ENABLE 0x1
#define ALS_POWER_MODE_DISABLE 0x0
#define ALS_INTERRUPT_ENABLE 0x1
#define ALS_INTERRUPT_DISABLE 0x0
//#define ALS_POWER_ON 0x0
//#define ALS_POWER_SHUTDOWN 0x1
#define STATUS_OK 0x0
#define STATUS_FAIL -1
#define TV_LIGHT_SENSOR_GAIN_LOW 0
#define TV_LIGHT_SENSOR_GAIN_MIDDLE 1
#define TV_LIGHT_SENSOR_GAIN_HIGH 2
typedef enum ALS_SD
{
ALS_POWER_ON,
ALS_POWER_SHUTDOWN
} Veml7700_Als_Sd_Mode;
struct max_veml7700_driver {
struct i2c_client *client;
struct device *dev;
struct timer_list timer;
struct delayed_work work;
unsigned int delay;
unsigned int enable;
unsigned int is_support;
struct input_dev *input_dev;
};
#endif