Add samsung specific changes
This commit is contained in:
18
drivers/optics/Kconfig
Executable file
18
drivers/optics/Kconfig
Executable file
@@ -0,0 +1,18 @@
|
||||
config SENSORS_FLICKER_SELF_TEST
|
||||
tristate "Flicker EOL test use flash"
|
||||
help
|
||||
make Test environment using led flash.
|
||||
|
||||
config SENSORS_STK6D2X
|
||||
tristate "STK STK68210 ALS, Flicker sensor"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here, you get support for the STK STK68210.
|
||||
This driver can also be built as a module.
|
||||
If so, the module will be called flicker_sensor.
|
||||
|
||||
config FLICKER_PWM_CALIBRATION
|
||||
bool "Support Flicker OSC Calibration"
|
||||
help
|
||||
Using PWM pulse, Enhance resolution accuracy
|
||||
This config just enable sensor side functions.
|
12
drivers/optics/Makefile
Executable file
12
drivers/optics/Makefile
Executable file
@@ -0,0 +1,12 @@
|
||||
KBUILD_CFLAGS += -Wno-unused-variable -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-frame-larger-than= -Wno-vla -Wno-uninitialized
|
||||
|
||||
obj-$(CONFIG_SENSORS_FLICKER_SELF_TEST) += flicker_test.o
|
||||
|
||||
KBUILD_CFLAGS += -Wno-unused-variable -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-frame-larger-than= -Wno-vla -Wno-uninitialized -Wno-incompatible-function-pointer-types
|
||||
|
||||
stk-src += stk6d2x.c stk6d2x_fifo.c stk6d2x_sec.c common_i2c.c common_timer.c common_gpio_sec.c
|
||||
|
||||
flicker_sensor-y := $(stk-src:.c=.o)
|
||||
flicker_sensor-$(CONFIG_FLICKER_PWM_CALIBRATION) += stk6d2x_cal.o
|
||||
|
||||
obj-$(CONFIG_SENSORS_STK6D2X) += flicker_sensor.o
|
120
drivers/optics/common_define.h
Executable file
120
drivers/optics/common_define.h
Executable file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
*
|
||||
* $Id: common_define.h
|
||||
*
|
||||
* Copyright (C) 2019 Bk, sensortek Inc.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DEFINE_COMMON_H__
|
||||
#define __DEFINE_COMMON_H__
|
||||
|
||||
#include "platform_config.h"
|
||||
|
||||
typedef struct stk_timer_info stk_timer_info;
|
||||
typedef struct stk_gpio_info stk_gpio_info;
|
||||
|
||||
struct stk_bus_ops
|
||||
{
|
||||
int bustype;
|
||||
int (*init)(void *);
|
||||
int (*read)(int, unsigned int, unsigned char *);
|
||||
int (*read_block)(int, unsigned int, int, void *);
|
||||
int (*write)(int, unsigned int, unsigned char);
|
||||
int (*write_block)(int, unsigned int, void *, int);
|
||||
int (*read_modify_write)(int, unsigned int, unsigned char, unsigned char);
|
||||
int (*remove)(void *);
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SECOND,
|
||||
M_SECOND,
|
||||
U_SECOND,
|
||||
N_SECOND,
|
||||
} TIMER_UNIT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
US_RANGE_DELAY,
|
||||
MS_DELAY,
|
||||
} BUSY_WAIT_TYPE;
|
||||
|
||||
struct stk_timer_info
|
||||
{
|
||||
char wq_name[4096];
|
||||
uint32_t interval_time;
|
||||
TIMER_UNIT timer_unit;
|
||||
void (*timer_cb)(stk_timer_info *t_info);
|
||||
bool is_active;
|
||||
bool is_exist;
|
||||
bool is_periodic;
|
||||
bool change_interval_time;
|
||||
void *any;
|
||||
} ;
|
||||
|
||||
struct stk_timer_ops
|
||||
{
|
||||
int (*register_timer)(stk_timer_info *);
|
||||
int (*start_timer)(stk_timer_info *);
|
||||
int (*stop_timer)(stk_timer_info *);
|
||||
int (*remove)(stk_timer_info *);
|
||||
void (*busy_wait)(unsigned long, unsigned long, BUSY_WAIT_TYPE);
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRIGGER_RISING,
|
||||
TRIGGER_FALLING,
|
||||
TRIGGER_HIGH,
|
||||
TRIGGER_LOW,
|
||||
} GPIO_TRIGGER_TYPE;
|
||||
|
||||
struct stk_gpio_info
|
||||
{
|
||||
char wq_name[4096];
|
||||
char device_name[4096];
|
||||
void (*gpio_cb)(stk_gpio_info *gpio_info);
|
||||
GPIO_TRIGGER_TYPE trig_type;
|
||||
int int_pin;
|
||||
int32_t irq;
|
||||
bool is_active;
|
||||
bool is_exist;
|
||||
void *any;
|
||||
} ;
|
||||
|
||||
struct stk_gpio_ops
|
||||
{
|
||||
int (*register_gpio_irq)(stk_gpio_info *);
|
||||
int (*start_gpio_irq)(stk_gpio_info *);
|
||||
int (*stop_gpio_irq)(stk_gpio_info *);
|
||||
int (*remove)(stk_gpio_info *);
|
||||
};
|
||||
|
||||
struct stk_storage_ops
|
||||
{
|
||||
int (*init_storage)(void);
|
||||
int (*write_to_storage)(char *, uint8_t *, int);
|
||||
int (*read_from_storage)(char *, uint8_t *, int);
|
||||
int (*remove)(void);
|
||||
};
|
||||
|
||||
struct common_function
|
||||
{
|
||||
const struct stk_bus_ops *bops;
|
||||
const struct stk_timer_ops *tops;
|
||||
const struct stk_gpio_ops *gops;
|
||||
};
|
||||
|
||||
typedef struct stk_register_table
|
||||
{
|
||||
uint8_t address;
|
||||
uint8_t value;
|
||||
uint8_t mask_bit;
|
||||
} stk_register_table;
|
||||
|
||||
#endif // __DEFINE_COMMON_H__
|
268
drivers/optics/common_gpio_sec.c
Executable file
268
drivers/optics/common_gpio_sec.c
Executable file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* common_gpio_sec.c - Linux kernel modules for sensortek stk6d2x
|
||||
* ambient light sensor (Common function)
|
||||
*
|
||||
* Copyright (C) 2019 Bk, sensortek Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <common_define.h>
|
||||
|
||||
typedef struct gpio_manager gpio_manager;
|
||||
|
||||
struct gpio_manager
|
||||
{
|
||||
struct work_struct stk_work;
|
||||
struct workqueue_struct *stk_wq;
|
||||
|
||||
stk_gpio_info *gpio_info;
|
||||
} gpio_mgr_default = {.gpio_info = 0};
|
||||
|
||||
#define MAX_LINUX_GPIO_MANAGER_NUM 5
|
||||
|
||||
gpio_manager linux_gpio_mgr[MAX_LINUX_GPIO_MANAGER_NUM];
|
||||
|
||||
static gpio_manager* parser_work(struct work_struct *work)
|
||||
{
|
||||
int gpio_idx = 0;
|
||||
|
||||
if (!work)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (gpio_idx = 0; gpio_idx < MAX_LINUX_GPIO_MANAGER_NUM; gpio_idx ++)
|
||||
{
|
||||
if (&linux_gpio_mgr[gpio_idx].stk_work == work)
|
||||
{
|
||||
return &linux_gpio_mgr[gpio_idx];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gpio_callback(struct work_struct *work)
|
||||
{
|
||||
gpio_manager *gpio_mgr = parser_work(work);
|
||||
|
||||
if (!gpio_mgr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_mgr->gpio_info->gpio_cb(gpio_mgr->gpio_info);
|
||||
enable_irq(gpio_mgr->gpio_info->irq);
|
||||
}
|
||||
|
||||
static irqreturn_t stk_gpio_irq_handler(int irq, void *data)
|
||||
{
|
||||
gpio_manager *pData = data;
|
||||
disable_irq_nosync(irq);
|
||||
queue_work(pData->stk_wq, &pData->stk_work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int register_gpio_irq(stk_gpio_info *gpio_info)
|
||||
{
|
||||
int gpio_idx = 0;
|
||||
int irq;
|
||||
int err = 0;
|
||||
|
||||
if (!gpio_info)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (gpio_idx = 0; gpio_idx < MAX_LINUX_GPIO_MANAGER_NUM; gpio_idx ++)
|
||||
{
|
||||
if (!linux_gpio_mgr[gpio_idx].gpio_info)
|
||||
{
|
||||
linux_gpio_mgr[gpio_idx].gpio_info = gpio_info;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info == gpio_info)
|
||||
{
|
||||
//already register
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_idx >= MAX_LINUX_GPIO_MANAGER_NUM)
|
||||
{
|
||||
printk(KERN_ERR "%s: proper gpio not found", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: irq num = %d \n", __func__, gpio_info->int_pin);
|
||||
err = gpio_request(gpio_info->int_pin, "stk-int");
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
printk(KERN_ERR "%s: gpio_request, err=%d", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
linux_gpio_mgr[gpio_idx].stk_wq = create_singlethread_workqueue(linux_gpio_mgr[gpio_idx].gpio_info->wq_name);
|
||||
INIT_WORK(&linux_gpio_mgr[gpio_idx].stk_work, gpio_callback);
|
||||
err = gpio_direction_input(linux_gpio_mgr[gpio_idx].gpio_info->int_pin);
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
printk(KERN_ERR "%s: gpio_direction_input, err=%d", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
irq = gpio_to_irq(linux_gpio_mgr[gpio_idx].gpio_info->int_pin);
|
||||
printk(KERN_INFO "%s: int pin #=%d, irq=%d\n", __func__, linux_gpio_mgr[gpio_idx].gpio_info->int_pin, irq);
|
||||
|
||||
if (irq < 0)
|
||||
{
|
||||
printk(KERN_ERR "irq number is not specified, irq # = %d, int pin=%d\n", irq, linux_gpio_mgr[gpio_idx].gpio_info->int_pin);
|
||||
return irq;
|
||||
}
|
||||
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->irq = irq;
|
||||
|
||||
switch (linux_gpio_mgr[gpio_idx].gpio_info->trig_type)
|
||||
{
|
||||
case TRIGGER_RISING:
|
||||
err = request_any_context_irq(irq, stk_gpio_irq_handler, IRQF_TRIGGER_RISING, \
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->device_name, &linux_gpio_mgr[gpio_idx]);
|
||||
break;
|
||||
|
||||
case TRIGGER_FALLING:
|
||||
err = request_any_context_irq(irq, stk_gpio_irq_handler, IRQF_TRIGGER_FALLING, \
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->device_name, &linux_gpio_mgr[gpio_idx]);
|
||||
break;
|
||||
|
||||
case TRIGGER_HIGH:
|
||||
case TRIGGER_LOW:
|
||||
err = request_any_context_irq(irq, stk_gpio_irq_handler, IRQF_TRIGGER_LOW, \
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->device_name, &linux_gpio_mgr[gpio_idx]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
printk(KERN_WARNING "%s: request_any_context_irq(%d) failed for (%d)\n", __func__, irq, err);
|
||||
goto err_request_any_context_irq;
|
||||
}
|
||||
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->is_exist = true;
|
||||
return 0;
|
||||
err_request_any_context_irq:
|
||||
gpio_free(linux_gpio_mgr[gpio_idx].gpio_info->int_pin);
|
||||
return err;
|
||||
}
|
||||
|
||||
int start_gpio_irq(stk_gpio_info *gpio_info)
|
||||
{
|
||||
int gpio_idx = 0;
|
||||
|
||||
for (gpio_idx = 0; gpio_idx < MAX_LINUX_GPIO_MANAGER_NUM; gpio_idx ++)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info == gpio_info)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info->is_exist)
|
||||
{
|
||||
if (!linux_gpio_mgr[gpio_idx].gpio_info->is_active)
|
||||
{
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->is_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stop_gpio_irq(stk_gpio_info *gpio_info)
|
||||
{
|
||||
int gpio_idx = 0;
|
||||
|
||||
for (gpio_idx = 0; gpio_idx < MAX_LINUX_GPIO_MANAGER_NUM; gpio_idx ++)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info == gpio_info)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info->is_exist)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info->is_active)
|
||||
{
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->is_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int remove_gpio_irq(stk_gpio_info *gpio_info)
|
||||
{
|
||||
int gpio_idx = 0;
|
||||
|
||||
for (gpio_idx = 0; gpio_idx < MAX_LINUX_GPIO_MANAGER_NUM; gpio_idx ++)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info == gpio_info)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info->is_exist)
|
||||
{
|
||||
if (linux_gpio_mgr[gpio_idx].gpio_info->is_active)
|
||||
{
|
||||
linux_gpio_mgr[gpio_idx].gpio_info->is_active = false;
|
||||
free_irq(linux_gpio_mgr[gpio_idx].gpio_info->irq, &linux_gpio_mgr[gpio_idx]);
|
||||
gpio_free(linux_gpio_mgr[gpio_idx].gpio_info->int_pin);
|
||||
cancel_work_sync(&linux_gpio_mgr[gpio_idx].stk_work);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const struct stk_gpio_ops stk_g_ops =
|
||||
{
|
||||
.register_gpio_irq = register_gpio_irq,
|
||||
.start_gpio_irq = start_gpio_irq,
|
||||
.stop_gpio_irq = stop_gpio_irq,
|
||||
.remove = remove_gpio_irq,
|
||||
|
||||
};
|
347
drivers/optics/common_i2c.c
Executable file
347
drivers/optics/common_i2c.c
Executable file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* common_i2c.c - Linux kernel modules for sensortek stk6d2x
|
||||
* ambient light sensor (Common function)
|
||||
*
|
||||
* Copyright (C) 2019 Bk, sensortek Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pm.h>
|
||||
#include <common_define.h>
|
||||
|
||||
#define MAX_I2C_MANAGER_NUM 5
|
||||
|
||||
struct i2c_manager *pi2c_mgr[MAX_I2C_MANAGER_NUM] = {NULL};
|
||||
|
||||
int i2c_init(void* st)
|
||||
{
|
||||
int i2c_idx = 0;
|
||||
|
||||
if (!st)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i2c_idx = 0; i2c_idx < MAX_I2C_MANAGER_NUM; i2c_idx ++)
|
||||
{
|
||||
if (pi2c_mgr[i2c_idx] == (struct i2c_manager*)st)
|
||||
{
|
||||
printk(KERN_INFO "%s: i2c is exist\n", __func__);
|
||||
break;
|
||||
}
|
||||
else if (pi2c_mgr[i2c_idx] == NULL)
|
||||
{
|
||||
pi2c_mgr[i2c_idx] = (struct i2c_manager*)st;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i2c_idx;
|
||||
}
|
||||
|
||||
int i2c_reg_read(int i2c_idx, unsigned int reg, unsigned char *val)
|
||||
{
|
||||
int error = 0;
|
||||
struct i2c_manager *_pi2c = pi2c_mgr[i2c_idx];
|
||||
I2C_REG_ADDR_TYPE addr_type = _pi2c->addr_type;
|
||||
mutex_lock(&_pi2c->lock);
|
||||
|
||||
if (addr_type == ADDR_8BIT)
|
||||
{
|
||||
unsigned char reg_ = (unsigned char)(reg & 0xFF);
|
||||
error = i2c_smbus_read_byte_data(_pi2c->client, reg_);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
dev_err(&_pi2c->client->dev,
|
||||
"%s: failed to read reg:0x%x error:%d\n",
|
||||
__func__, reg , error);
|
||||
}
|
||||
else
|
||||
{
|
||||
*(unsigned char *)val = error & 0xFF;
|
||||
}
|
||||
}
|
||||
else if (addr_type == ADDR_16BIT)
|
||||
{
|
||||
}
|
||||
|
||||
mutex_unlock(&_pi2c->lock);
|
||||
return error;
|
||||
}
|
||||
|
||||
int i2c_reg_write(int i2c_idx, unsigned int reg, unsigned char val)
|
||||
{
|
||||
int error = 0;
|
||||
struct i2c_manager *_pi2c = pi2c_mgr[i2c_idx];
|
||||
I2C_REG_ADDR_TYPE addr_type = _pi2c->addr_type;
|
||||
mutex_lock(&_pi2c->lock);
|
||||
|
||||
if (addr_type == ADDR_8BIT)
|
||||
{
|
||||
unsigned char reg_ = (unsigned char)(reg & 0xFF);
|
||||
error = i2c_smbus_write_byte_data(_pi2c->client, reg_, val);
|
||||
}
|
||||
else if (addr_type == ADDR_16BIT)
|
||||
{
|
||||
}
|
||||
|
||||
mutex_unlock(&_pi2c->lock);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
dev_err(&_pi2c->client->dev,
|
||||
"%s: failed to write reg:0x%x with val:0x%x error:%d\n",
|
||||
__func__, reg, val, error);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int i2c_reg_write_block(int i2c_idx, unsigned int reg, void *val, int length)
|
||||
{
|
||||
int error = 0;
|
||||
struct i2c_manager *_pi2c = pi2c_mgr[i2c_idx];
|
||||
I2C_REG_ADDR_TYPE addr_type = _pi2c->addr_type;
|
||||
mutex_lock(&_pi2c->lock);
|
||||
|
||||
if (addr_type == ADDR_8BIT)
|
||||
{
|
||||
unsigned char reg_ = (unsigned char)(reg & 0xFF);
|
||||
error = i2c_smbus_write_i2c_block_data(_pi2c->client, reg_, length, val);
|
||||
}
|
||||
else if (addr_type == ADDR_16BIT)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char *buffer_inverse;
|
||||
struct i2c_msg msgs;
|
||||
buffer_inverse = kzalloc((sizeof(unsigned char) * (length + 2)), GFP_KERNEL);
|
||||
buffer_inverse[0] = reg >> 8;
|
||||
buffer_inverse[1] = reg & 0xff;
|
||||
|
||||
for (i = 0; i < length; i ++)
|
||||
{
|
||||
buffer_inverse[2 + i] = *(u8*)((u8*)val + ((length - 1) - i));
|
||||
}
|
||||
|
||||
msgs.addr = _pi2c->client->addr;
|
||||
msgs.flags = _pi2c->client->flags & I2C_M_TEN;
|
||||
msgs.len = length + 2;
|
||||
msgs.buf = buffer_inverse;
|
||||
#ifdef STK_RETRY_I2C
|
||||
i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
error = i2c_transfer(_pi2c->client->adapter, &msgs, 1);
|
||||
}
|
||||
while (error != 1 && ++i < 3);
|
||||
|
||||
#else
|
||||
error = i2c_transfer(_pi2c->client->adapter, &msgs, 1);
|
||||
#endif // STK_RETRY_I2C
|
||||
kfree(buffer_inverse);
|
||||
}
|
||||
|
||||
mutex_unlock(&_pi2c->lock);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
dev_err(&_pi2c->client->dev,
|
||||
"%s: failed to write reg:0x%x\n",
|
||||
__func__, reg);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int i2c_reg_read_modify_write(int i2c_idx, unsigned int reg, unsigned char val, unsigned char mask)
|
||||
{
|
||||
uint8_t rw_buffer = 0;
|
||||
int error = 0;
|
||||
struct i2c_manager *_pi2c = pi2c_mgr[i2c_idx];
|
||||
|
||||
if ((mask == 0xFF) || (mask == 0x0))
|
||||
{
|
||||
error = i2c_reg_write(i2c_idx, reg, val);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
dev_err(&_pi2c->client->dev,
|
||||
"%s: failed to write reg:0x%x with val:0x%x\n",
|
||||
__func__, reg, val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = (uint8_t)i2c_reg_read(i2c_idx, reg, &rw_buffer);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
dev_err(&_pi2c->client->dev,
|
||||
"%s: failed to read reg:0x%x\n",
|
||||
__func__, reg);
|
||||
return error;
|
||||
}
|
||||
else
|
||||
{
|
||||
rw_buffer = (rw_buffer & (~mask)) | (val & mask);
|
||||
error = i2c_reg_write(i2c_idx, reg, rw_buffer);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
dev_err(&_pi2c->client->dev,
|
||||
"%s: failed to write reg(mask):0x%x with val:0x%x\n",
|
||||
__func__, reg, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int i2c_reg_read_block(int i2c_idx, unsigned int reg, int count, void *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
// int loop_cnt = 0;
|
||||
struct i2c_manager *_pi2c = pi2c_mgr[i2c_idx];
|
||||
I2C_REG_ADDR_TYPE addr_type = _pi2c->addr_type;
|
||||
mutex_lock(&_pi2c->lock);
|
||||
|
||||
if (addr_type == ADDR_8BIT)
|
||||
{
|
||||
struct i2c_msg msgs[2] =
|
||||
{
|
||||
{
|
||||
.addr = _pi2c->client->addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = (u8*)®
|
||||
},
|
||||
{
|
||||
.addr = _pi2c->client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = count,
|
||||
.buf = buf
|
||||
}
|
||||
};
|
||||
ret = i2c_transfer(_pi2c->client->adapter, msgs, 2);
|
||||
|
||||
if (2 == ret)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
// unsigned char reg_ = (unsigned char)(reg & 0xFF);
|
||||
|
||||
// while (count)
|
||||
// {
|
||||
// ret = i2c_smbus_read_i2c_block_data(_pi2c->client, reg_,
|
||||
// (count > I2C_SMBUS_BLOCK_MAX) ? I2C_SMBUS_BLOCK_MAX : count,
|
||||
// (buf + (loop_cnt * I2C_SMBUS_BLOCK_MAX))
|
||||
// );
|
||||
// (count > I2C_SMBUS_BLOCK_MAX) ? (count -= I2C_SMBUS_BLOCK_MAX) : (count -= count);
|
||||
// loop_cnt ++;
|
||||
// }
|
||||
}
|
||||
else if (addr_type == ADDR_16BIT)
|
||||
{
|
||||
int i = 0;
|
||||
u16 reg_inverse = (reg & 0x00FF) << 8 | (reg & 0xFF00) >> 8;
|
||||
int read_length = count;
|
||||
u8 buffer_inverse[99] = { 0 };
|
||||
struct i2c_msg msgs[2] =
|
||||
{
|
||||
{
|
||||
.addr = _pi2c->client->addr,
|
||||
.flags = 0,
|
||||
.len = 2,
|
||||
.buf = (u8*)®_inverse
|
||||
},
|
||||
{
|
||||
.addr = _pi2c->client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = read_length,
|
||||
.buf = buffer_inverse
|
||||
}
|
||||
};
|
||||
#ifdef STK_RETRY_I2C
|
||||
i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
ret = i2c_transfer(_pi2c->client->adapter, msgs, 2);
|
||||
}
|
||||
while (ret != 2 && ++i < 3);
|
||||
|
||||
#else
|
||||
ret = i2c_transfer(_pi2c->client->adapter, msgs, 2);
|
||||
#endif // STK_RETRY_I2C
|
||||
|
||||
if (2 == ret)
|
||||
{
|
||||
ret = 0;
|
||||
|
||||
for (i = 0; i < read_length; i ++)
|
||||
{
|
||||
*(u8*)((u8*)buf + i) = ((buffer_inverse[read_length - 1 - i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&_pi2c->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2c_remove(void* st)
|
||||
{
|
||||
int i2c_idx = 0;
|
||||
|
||||
if (!st)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i2c_idx = 0; i2c_idx < MAX_I2C_MANAGER_NUM; i2c_idx ++)
|
||||
{
|
||||
printk(KERN_INFO "%s: i2c_idx = %d\n", __func__, i2c_idx);
|
||||
|
||||
if (pi2c_mgr[i2c_idx] == (struct i2c_manager*)st)
|
||||
{
|
||||
printk(KERN_INFO "%s: release i2c_idx = %d\n", __func__, i2c_idx);
|
||||
pi2c_mgr[i2c_idx] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct stk_bus_ops stk_i2c_bops =
|
||||
{
|
||||
.bustype = BUS_I2C,
|
||||
.init = i2c_init,
|
||||
.write = i2c_reg_write,
|
||||
.write_block = i2c_reg_write_block,
|
||||
.read = i2c_reg_read,
|
||||
.read_block = i2c_reg_read_block,
|
||||
.read_modify_write = i2c_reg_read_modify_write,
|
||||
.remove = i2c_remove,
|
||||
};
|
329
drivers/optics/common_timer.c
Executable file
329
drivers/optics/common_timer.c
Executable file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* common_timer.c - Linux kernel modules for sensortek stk6d2x
|
||||
* ambient light sensor (Common function)
|
||||
*
|
||||
* Copyright (C) 2019 Bk, sensortek Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <common_define.h>
|
||||
|
||||
typedef struct timer_manager timer_manager;
|
||||
|
||||
struct timer_manager
|
||||
{
|
||||
struct work_struct stk_work;
|
||||
struct hrtimer stk_hrtimer;
|
||||
struct workqueue_struct *stk_wq;
|
||||
ktime_t timer_interval;
|
||||
|
||||
stk_timer_info *timer_info;
|
||||
} timer_mgr_default = {.timer_info = 0};
|
||||
|
||||
#define MAX_LINUX_TIMER_MANAGER_NUM 5
|
||||
|
||||
timer_manager linux_timer_mgr[MAX_LINUX_TIMER_MANAGER_NUM];
|
||||
|
||||
static timer_manager* parser_timer(struct hrtimer *timer)
|
||||
{
|
||||
int timer_idx = 0;
|
||||
|
||||
if (timer == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (timer_idx = 0; timer_idx < MAX_LINUX_TIMER_MANAGER_NUM; timer_idx ++)
|
||||
{
|
||||
if (&linux_timer_mgr[timer_idx].stk_hrtimer == timer)
|
||||
{
|
||||
return &linux_timer_mgr[timer_idx];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart timer_func(struct hrtimer *timer)
|
||||
{
|
||||
timer_manager *timer_mgr = parser_timer(timer);
|
||||
|
||||
if (timer_mgr == NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s: timer_mgr is NULL\n", __func__);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
if (timer_mgr->stk_wq == NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s: timer_mgr->stk_wq is NULL\n", __func__);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
if (timer_mgr->timer_info == NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s: timer_mgr->timer_info is NULL\n", __func__);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
queue_work(timer_mgr->stk_wq, &timer_mgr->stk_work);
|
||||
hrtimer_forward_now(&timer_mgr->stk_hrtimer, timer_mgr->timer_interval);
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
static timer_manager* parser_work(struct work_struct *work)
|
||||
{
|
||||
int timer_idx = 0;
|
||||
|
||||
if (work == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (timer_idx = 0; timer_idx < MAX_LINUX_TIMER_MANAGER_NUM; timer_idx ++)
|
||||
{
|
||||
if (&linux_timer_mgr[timer_idx].stk_work == work)
|
||||
{
|
||||
return &linux_timer_mgr[timer_idx];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void timer_callback(struct work_struct *work)
|
||||
{
|
||||
timer_manager *timer_mgr = parser_work(work);
|
||||
|
||||
if (timer_mgr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
timer_mgr->timer_info->timer_cb(timer_mgr->timer_info);
|
||||
}
|
||||
|
||||
int register_timer(stk_timer_info *t_info)
|
||||
{
|
||||
int timer_idx = 0;
|
||||
|
||||
if (t_info == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (timer_idx = 0; timer_idx < MAX_LINUX_TIMER_MANAGER_NUM; timer_idx ++)
|
||||
{
|
||||
if (!linux_timer_mgr[timer_idx].timer_info)
|
||||
{
|
||||
linux_timer_mgr[timer_idx].timer_info = t_info;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info == t_info)
|
||||
{
|
||||
//already register
|
||||
if (linux_timer_mgr[timer_idx].timer_info->change_interval_time)
|
||||
{
|
||||
linux_timer_mgr[timer_idx].timer_info->change_interval_time = 0;
|
||||
printk(KERN_ERR "%s: chang interval time\n", __func__);
|
||||
switch (linux_timer_mgr[timer_idx].timer_info->timer_unit)
|
||||
{
|
||||
case N_SECOND:
|
||||
linux_timer_mgr[timer_idx].timer_interval = ns_to_ktime(linux_timer_mgr[timer_idx].timer_info->interval_time);
|
||||
break;
|
||||
|
||||
case U_SECOND:
|
||||
linux_timer_mgr[timer_idx].timer_interval = ns_to_ktime(linux_timer_mgr[timer_idx].timer_info->interval_time * NSEC_PER_USEC);
|
||||
break;
|
||||
|
||||
case M_SECOND:
|
||||
linux_timer_mgr[timer_idx].timer_interval = ns_to_ktime(linux_timer_mgr[timer_idx].timer_info->interval_time * NSEC_PER_MSEC);
|
||||
break;
|
||||
|
||||
case SECOND:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_ERR "%s: this timer is registered\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if search/register timer manager not successfully
|
||||
if (timer_idx == MAX_LINUX_TIMER_MANAGER_NUM)
|
||||
{
|
||||
printk(KERN_ERR "%s: timer_idx out of range %d\n", __func__, timer_idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk(KERN_ERR "%s: register timer name %s\n", __func__, linux_timer_mgr[timer_idx].timer_info->wq_name);
|
||||
linux_timer_mgr[timer_idx].stk_wq = create_singlethread_workqueue(linux_timer_mgr[timer_idx].timer_info->wq_name);
|
||||
if (linux_timer_mgr[timer_idx].stk_wq == NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s: create single thread workqueue fail\n", __func__);
|
||||
linux_timer_mgr[timer_idx].timer_info = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
INIT_WORK(&linux_timer_mgr[timer_idx].stk_work, timer_callback);
|
||||
hrtimer_init(&linux_timer_mgr[timer_idx].stk_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
|
||||
switch (linux_timer_mgr[timer_idx].timer_info->timer_unit)
|
||||
{
|
||||
case N_SECOND:
|
||||
linux_timer_mgr[timer_idx].timer_interval = ns_to_ktime(linux_timer_mgr[timer_idx].timer_info->interval_time);
|
||||
break;
|
||||
|
||||
case U_SECOND:
|
||||
linux_timer_mgr[timer_idx].timer_interval = ns_to_ktime(linux_timer_mgr[timer_idx].timer_info->interval_time * NSEC_PER_USEC);
|
||||
break;
|
||||
|
||||
case M_SECOND:
|
||||
linux_timer_mgr[timer_idx].timer_interval = ns_to_ktime(linux_timer_mgr[timer_idx].timer_info->interval_time * NSEC_PER_MSEC);
|
||||
break;
|
||||
|
||||
case SECOND:
|
||||
break;
|
||||
}
|
||||
|
||||
linux_timer_mgr[timer_idx].stk_hrtimer.function = timer_func;
|
||||
linux_timer_mgr[timer_idx].timer_info->is_exist = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start_timer(stk_timer_info *t_info)
|
||||
{
|
||||
int timer_idx = 0;
|
||||
|
||||
for (timer_idx = 0; timer_idx < MAX_LINUX_TIMER_MANAGER_NUM; timer_idx ++)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info == t_info)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info->is_exist)
|
||||
{
|
||||
if (!linux_timer_mgr[timer_idx].timer_info->is_active)
|
||||
{
|
||||
hrtimer_start(&linux_timer_mgr[timer_idx].stk_hrtimer, linux_timer_mgr[timer_idx].timer_interval, HRTIMER_MODE_REL);
|
||||
linux_timer_mgr[timer_idx].timer_info->is_active = true;
|
||||
printk(KERN_ERR "%s: start timer name %s\n", __func__, linux_timer_mgr[timer_idx].timer_info->wq_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_INFO "%s: %s was already running\n", __func__, linux_timer_mgr[timer_idx].timer_info->wq_name);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stop_timer(stk_timer_info *t_info)
|
||||
{
|
||||
int timer_idx = 0;
|
||||
|
||||
for (timer_idx = 0; timer_idx < MAX_LINUX_TIMER_MANAGER_NUM; timer_idx ++)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info == t_info)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info->is_exist)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info->is_active)
|
||||
{
|
||||
hrtimer_cancel(&linux_timer_mgr[timer_idx].stk_hrtimer);
|
||||
drain_workqueue(linux_timer_mgr[timer_idx].stk_wq);
|
||||
linux_timer_mgr[timer_idx].timer_info->is_active = false;
|
||||
printk(KERN_ERR "%s: stop timer name %s\n", __func__, linux_timer_mgr[timer_idx].timer_info->wq_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s: %s stop already stop\n", __func__, linux_timer_mgr[timer_idx].timer_info->wq_name);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int remove_timer(stk_timer_info *t_info)
|
||||
{
|
||||
int timer_idx = 0;
|
||||
|
||||
for (timer_idx = 0; timer_idx < MAX_LINUX_TIMER_MANAGER_NUM; timer_idx ++)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info == t_info)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info->is_exist)
|
||||
{
|
||||
if (linux_timer_mgr[timer_idx].timer_info->is_active)
|
||||
{
|
||||
hrtimer_try_to_cancel(&linux_timer_mgr[timer_idx].stk_hrtimer);
|
||||
destroy_workqueue(linux_timer_mgr[timer_idx].stk_wq);
|
||||
cancel_work_sync(&linux_timer_mgr[timer_idx].stk_work);
|
||||
linux_timer_mgr[timer_idx].timer_info->is_active = false;
|
||||
linux_timer_mgr[timer_idx].timer_info->is_exist = false;
|
||||
linux_timer_mgr[timer_idx].timer_info = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void busy_wait(unsigned long min, unsigned long max, BUSY_WAIT_TYPE mode)
|
||||
{
|
||||
if ((!min) || (!max) || (max < min))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == US_RANGE_DELAY)
|
||||
{
|
||||
usleep_range(min, max);
|
||||
}
|
||||
|
||||
if (mode == MS_DELAY)
|
||||
{
|
||||
msleep(max);
|
||||
}
|
||||
}
|
||||
const struct stk_timer_ops stk_t_ops =
|
||||
{
|
||||
.register_timer = register_timer,
|
||||
.start_timer = start_timer,
|
||||
.stop_timer = stop_timer,
|
||||
.remove = remove_timer,
|
||||
.busy_wait = busy_wait,
|
||||
};
|
368
drivers/optics/flicker_test.c
Executable file
368
drivers/optics/flicker_test.c
Executable file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Samsung Electronics Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License, 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "flicker_test.h"
|
||||
|
||||
static struct test_data *data = NULL;
|
||||
static struct result_data *test_result = NULL;
|
||||
|
||||
static void (*err_handler)(void);
|
||||
|
||||
|
||||
void als_eol_set_err_handler(void (*handler)(void)){
|
||||
err_handler = handler;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(als_eol_set_err_handler);
|
||||
|
||||
/**
|
||||
* als_eol_update_als - Record every test value
|
||||
*
|
||||
* @awb : current 'awb' value
|
||||
* (You can use any value as you need. Maybe Infrared value will be used in most cases)
|
||||
* @clear : current clear value detected by sensor. It means visible light in light spectrum
|
||||
* @wideband : current Wideband value detected by sensor.
|
||||
* wideband light include visible light and infrared.
|
||||
*
|
||||
*/
|
||||
void als_eol_update_als(int awb, int clear, int wideband, int uv)
|
||||
{
|
||||
if (data->eol_enable && data->eol_count >= EOL_SKIP_COUNT) {
|
||||
data->eol_awb += awb;
|
||||
data->eol_clear += clear;
|
||||
data->eol_wideband += wideband;
|
||||
data->eol_uv += uv;
|
||||
data->eol_sum_count++;
|
||||
}
|
||||
|
||||
if (data->eol_enable && data->eol_state < EOL_STATE_DONE) {
|
||||
switch (data->eol_state) {
|
||||
case EOL_STATE_INIT:
|
||||
memset(test_result, 0, sizeof(struct result_data));
|
||||
|
||||
data->eol_count = 0;
|
||||
data->eol_sum_count = 0;
|
||||
data->eol_awb = 0;
|
||||
data->eol_clear = 0;
|
||||
data->eol_wideband = 0;
|
||||
data->eol_flicker = 0;
|
||||
data->eol_flicker_sum = 0;
|
||||
data->eol_flicker_sum_count = 0;
|
||||
data->eol_flicker_count = 0;
|
||||
data->eol_flicker_skip_count = EOL_FLICKER_SKIP_COUNT;
|
||||
data->eol_state = EOL_STATE_100;
|
||||
data->eol_pulse_count = 0;
|
||||
data->eol_uv = 0;
|
||||
break;
|
||||
default:
|
||||
data->eol_count++;
|
||||
printk(KERN_INFO"%s - eol_state:%d, eol_cnt:%d (sum_cnt:%d), flk:%d (flk_cnt:%d, sum_cnt:%d), ir:%d, clear:%d, wide:%d, uv:%d\n", __func__,
|
||||
data->eol_state, data->eol_count, data->eol_sum_count, data->eol_flicker, data->eol_flicker_count, data->eol_flicker_sum_count, awb, clear, wideband, uv);
|
||||
|
||||
if ((data->eol_count >= (EOL_COUNT + EOL_SKIP_COUNT)) && (data->eol_flicker_count >= (EOL_COUNT + data->eol_flicker_skip_count))) {
|
||||
if (data->eol_flicker_sum_count) {
|
||||
test_result->flicker[data->eol_state] = data->eol_flicker_sum / data->eol_flicker_sum_count;
|
||||
} else {
|
||||
test_result->flicker[data->eol_state] = data->eol_flicker;
|
||||
}
|
||||
|
||||
if (data->eol_sum_count) {
|
||||
test_result->awb[data->eol_state] = data->eol_awb / data->eol_sum_count;
|
||||
test_result->clear[data->eol_state] = data->eol_clear / data->eol_sum_count;
|
||||
test_result->wideband[data->eol_state] = data->eol_wideband / data->eol_sum_count;
|
||||
test_result->uv[data->eol_state] = data->eol_uv / data->eol_sum_count;
|
||||
} else {
|
||||
test_result->awb[data->eol_state] = awb;
|
||||
test_result->clear[data->eol_state] = clear;
|
||||
test_result->wideband[data->eol_state] = wideband;
|
||||
test_result->uv[data->eol_state] = uv;
|
||||
}
|
||||
|
||||
printk(KERN_INFO"%s - eol_state = %d, pulse_count = %d, flicker_result = %d Hz (%d/%d)\n",
|
||||
__func__, data->eol_state, data->eol_pulse_count, test_result->flicker[data->eol_state], data->eol_flicker_sum, data->eol_flicker_sum_count);
|
||||
|
||||
data->eol_count = 0;
|
||||
data->eol_sum_count = 0;
|
||||
data->eol_awb = 0;
|
||||
data->eol_clear = 0;
|
||||
data->eol_wideband = 0;
|
||||
data->eol_flicker = 0;
|
||||
data->eol_flicker_sum = 0;
|
||||
data->eol_flicker_sum_count = 0;
|
||||
data->eol_flicker_count = 0;
|
||||
data->eol_pulse_count = 0;
|
||||
data->eol_uv = 0;
|
||||
data->eol_state++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(als_eol_update_als);
|
||||
|
||||
/**
|
||||
* als_eol_update_flicker - Record every test value
|
||||
*
|
||||
* @flicker: current Flicker value detected by sensor.
|
||||
*/
|
||||
void als_eol_update_flicker(int Hz)
|
||||
{
|
||||
data->eol_flicker_count++;
|
||||
data->eol_flicker = Hz;
|
||||
|
||||
if ((data->eol_flicker_skip_count < EOL_SKIP_COUNT) && (data->eol_flicker_count >= data->eol_count)) {
|
||||
data->eol_flicker_skip_count = EOL_SKIP_COUNT;
|
||||
}
|
||||
|
||||
if ((data->eol_enable && Hz != 0) && (data->eol_flicker_count > data->eol_flicker_skip_count)) {
|
||||
data->eol_flicker_sum += Hz;
|
||||
data->eol_flicker_sum_count++;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(als_eol_update_flicker);
|
||||
|
||||
void set_led_mode(int led_curr)
|
||||
{
|
||||
#if IS_ENABLED (CONFIG_LEDS_S2MPB02)
|
||||
s2mpb02_led_en(led_mode, led_curr, S2MPB02_LED_TURN_WAY_GPIO);
|
||||
#elif IS_ENABLED(CONFIG_LEDS_KTD2692)
|
||||
ktd2692_led_mode_ctrl(led_mode, led_curr);
|
||||
#elif IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
|
||||
if (led_curr)
|
||||
aw36518_enable_flicker(led_curr, true);
|
||||
else
|
||||
aw36518_enable_flicker(0, false);
|
||||
#elif IS_ENABLED(CONFIG_LEDS_QTI_FLASH) && (IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_STK6DAX) || IS_ENABLED(CONFIG_SENSORS_TSL2511))
|
||||
if(led_curr) {
|
||||
qti_flash_led_set_strobe_sel(switch3_trigger, 1);
|
||||
led_trigger_event(torch2_trigger, led_curr/2);
|
||||
led_trigger_event(torch3_trigger, led_curr/2);
|
||||
led_trigger_event(switch3_trigger, 1);
|
||||
} else {
|
||||
qti_flash_led_set_strobe_sel(switch3_trigger, 0);
|
||||
led_trigger_event(switch3_trigger, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void als_eol_set_env(bool torch, int intensity)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_LEDS_S2MPB02)
|
||||
led_curr = (intensity/20);
|
||||
led_mode = S2MPB02_TORCH_LED_1;
|
||||
#elif IS_ENABLED(CONFIG_LEDS_KTD2692)
|
||||
led_curr = 1400;
|
||||
led_mode = KTD2692_FLICKER_FLASH_MODE;
|
||||
#elif IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
|
||||
led_curr = intensity;
|
||||
#elif IS_ENABLED(CONFIG_LEDS_QTI_FLASH)
|
||||
led_curr = intensity;
|
||||
#endif
|
||||
printk(KERN_INFO "%s - gpio:%d intensity:%d(%d) led_mode:%d",
|
||||
__func__, gpio_torch, intensity, led_curr, led_mode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(als_eol_set_env);
|
||||
|
||||
/**
|
||||
* als_eol_mode - start LED flicker loop
|
||||
*
|
||||
* Return result_data
|
||||
* MUST call als_eol_update* functions to notify the sensor output!!
|
||||
*/
|
||||
struct result_data* als_eol_mode(void)
|
||||
{
|
||||
int pulse_duty = 0;
|
||||
int curr_state = EOL_STATE_INIT;
|
||||
int ret = 0;
|
||||
u32 prev_eol_count = 0, loop_count = 0;
|
||||
|
||||
set_led_mode(0);
|
||||
|
||||
ret = gpio_request(gpio_torch, NULL);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
data->eol_state = EOL_STATE_INIT;
|
||||
data->eol_enable = 1;
|
||||
|
||||
printk(KERN_INFO"%s - eol_loop start", __func__);
|
||||
while (data->eol_state < EOL_STATE_DONE) {
|
||||
if (prev_eol_count == data->eol_count)
|
||||
loop_count++;
|
||||
else
|
||||
loop_count = 0;
|
||||
|
||||
prev_eol_count = data->eol_count;
|
||||
|
||||
switch (data->eol_state) {
|
||||
case EOL_STATE_INIT:
|
||||
pulse_duty = 1000;
|
||||
break;
|
||||
case EOL_STATE_100:
|
||||
pulse_duty = DEFAULT_DUTY_50HZ;
|
||||
break;
|
||||
case EOL_STATE_120:
|
||||
pulse_duty = DEFAULT_DUTY_60HZ;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (data->eol_state >= EOL_STATE_100) {
|
||||
if (curr_state != data->eol_state) {
|
||||
#if IS_ENABLED(CONFIG_LEDS_KTD2692) || IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
|
||||
if(ret >= 0) {
|
||||
gpio_free(gpio_torch);
|
||||
}
|
||||
#endif
|
||||
set_led_mode(led_curr);
|
||||
curr_state = data->eol_state;
|
||||
|
||||
#if IS_ENABLED(CONFIG_LEDS_KTD2692) || IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
|
||||
ret = gpio_request(gpio_torch, NULL);
|
||||
if (ret < 0)
|
||||
break;
|
||||
#endif
|
||||
} else {
|
||||
gpio_direction_output(gpio_torch, 1);
|
||||
udelay(pulse_duty);
|
||||
gpio_direction_output(gpio_torch, 0);
|
||||
data->eol_pulse_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (loop_count > 1000) {
|
||||
printk(KERN_ERR "%s - ERR NO Interrupt", __func__);
|
||||
// Add Debug Code
|
||||
if (err_handler)
|
||||
err_handler();
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(pulse_duty);
|
||||
}
|
||||
printk(KERN_INFO"%s - eol_loop end",__func__);
|
||||
if(ret >= 0) {
|
||||
gpio_free(gpio_torch);
|
||||
}
|
||||
set_led_mode(0);
|
||||
|
||||
if (data->eol_state >= EOL_STATE_DONE) {
|
||||
if(test_result->clear[EOL_STATE_100] != 0) {
|
||||
test_result->ratio[EOL_STATE_100] = test_result->awb[EOL_STATE_100] * 100 / test_result->clear[EOL_STATE_100];
|
||||
}
|
||||
if(test_result->clear[EOL_STATE_120] != 0) {
|
||||
test_result->ratio[EOL_STATE_120] = test_result->awb[EOL_STATE_120] * 100 / test_result->clear[EOL_STATE_120];
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "%s - abnormal termination\n", __func__);
|
||||
}
|
||||
printk(KERN_INFO "%s - RESULT: flicker:%d|%d awb:%d|%d clear:%d|%d wide:%d|%d ratio:%d|%d uv:%d|%d", __func__,
|
||||
test_result->flicker[EOL_STATE_100], test_result->flicker[EOL_STATE_120],
|
||||
test_result->awb[EOL_STATE_100], test_result->awb[EOL_STATE_120],
|
||||
test_result->clear[EOL_STATE_100], test_result->clear[EOL_STATE_120],
|
||||
test_result->wideband[EOL_STATE_100], test_result->wideband[EOL_STATE_120],
|
||||
test_result->ratio[EOL_STATE_100], test_result->ratio[EOL_STATE_120],
|
||||
test_result->uv[EOL_STATE_100], test_result->uv[EOL_STATE_120]);
|
||||
|
||||
data->eol_enable = 0;
|
||||
|
||||
return test_result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(als_eol_mode);
|
||||
|
||||
int als_eol_parse_dt(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
#if KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE
|
||||
enum of_gpio_flags flags;
|
||||
#endif
|
||||
|
||||
np = of_find_node_by_name(NULL, LED_DT_NODE_NAME);
|
||||
if (np == NULL) {
|
||||
printk(KERN_ERR "%s - Can't find node", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if KERNEL_VERSION(6, 2, 0) <= LINUX_VERSION_CODE
|
||||
gpio_torch = of_get_named_gpio(np, "flicker_test,torch-gpio", 0);
|
||||
#else
|
||||
gpio_torch = of_get_named_gpio_flags(np, "flicker_test,torch-gpio", 0, &flags);
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "%s - torch : %d", __func__, gpio_torch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init als_eol_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
printk(KERN_INFO "%s - EOL_TEST Module init", __func__);
|
||||
|
||||
data = (struct test_data*)kzalloc(sizeof(struct test_data), GFP_KERNEL);
|
||||
if (data == NULL) {
|
||||
printk(KERN_INFO "%s - data alloc err", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
test_result = (struct result_data*)kzalloc(sizeof(struct result_data), GFP_KERNEL);
|
||||
if (test_result == NULL) {
|
||||
printk(KERN_INFO "%s - test_result alloc err", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = als_eol_parse_dt();
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s - dt parse fail!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !IS_ENABLED(CONFIG_LEDS_S2MPB02) && !IS_ENABLED(CONFIG_LEDS_KTD2692) && IS_ENABLED(CONFIG_LEDS_QTI_FLASH) \
|
||||
&& (IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_STK6DAX) || IS_ENABLED(CONFIG_SENSORS_TSL2511)) && !IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
|
||||
led_trigger_register_simple("torch2_trigger", &torch2_trigger);
|
||||
led_trigger_register_simple("torch3_trigger", &torch3_trigger);
|
||||
led_trigger_register_simple("switch3_trigger", &switch3_trigger);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit als_eol_exit(void)
|
||||
{
|
||||
printk(KERN_INFO "%s - EOL_TEST Module exit\n", __func__);
|
||||
|
||||
#if !IS_ENABLED(CONFIG_LEDS_S2MPB02) && !IS_ENABLED(CONFIG_LEDS_KTD2692) && IS_ENABLED(CONFIG_LEDS_QTI_FLASH) \
|
||||
&& (IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_STK6DAX) || IS_ENABLED(CONFIG_SENSORS_TSL2511)) && !IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
|
||||
led_trigger_unregister_simple(torch2_trigger);
|
||||
led_trigger_unregister_simple(torch3_trigger);
|
||||
led_trigger_unregister_simple(switch3_trigger);
|
||||
#endif
|
||||
|
||||
if(data) {
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
if(test_result) {
|
||||
kfree(test_result);
|
||||
}
|
||||
}
|
||||
|
||||
module_init(als_eol_init);
|
||||
module_exit(als_eol_exit);
|
||||
|
||||
MODULE_AUTHOR("Samsung Electronics");
|
||||
MODULE_DESCRIPTION("Flicker Sensor Test Driver");
|
||||
MODULE_LICENSE("GPL");
|
123
drivers/optics/flicker_test.h
Executable file
123
drivers/optics/flicker_test.h
Executable file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Samsung Electronics Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License, 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EOL_TEST_H
|
||||
#define EOL_TEST_H
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
/*
|
||||
* Flicker Sensor Self test module
|
||||
*
|
||||
* Uses LEDs in the system.
|
||||
* If you want to add a new LED,
|
||||
* add a header below and define dt node name.
|
||||
*
|
||||
* You can build this with CONFIG_EOL_TEST
|
||||
*/
|
||||
|
||||
#if IS_ENABLED(CONFIG_LEDS_S2MPB02)
|
||||
#include <linux/leds-s2mpb02.h>
|
||||
#elif IS_ENABLED(CONFIG_LEDS_KTD2692)
|
||||
#include <linux/leds-ktd2692.h>
|
||||
#elif IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
|
||||
#include <linux/leds-aw36518.h>
|
||||
#elif IS_ENABLED(CONFIG_LEDS_QTI_FLASH) && (IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_STK6DAX) || IS_ENABLED(CONFIG_SENSORS_TSL2511))
|
||||
#include <linux/leds.h>
|
||||
#include <linux/leds-qti-flash.h>
|
||||
DEFINE_LED_TRIGGER(torch2_trigger);
|
||||
DEFINE_LED_TRIGGER(torch3_trigger);
|
||||
DEFINE_LED_TRIGGER(switch3_trigger);
|
||||
#endif
|
||||
|
||||
#define LED_DT_NODE_NAME "flicker_test"
|
||||
|
||||
#define DEFAULT_DUTY_50HZ 5000
|
||||
#define DEFAULT_DUTY_60HZ 4166
|
||||
|
||||
#define MAX_TEST_RESULT 256
|
||||
#if IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_STK6DAX)
|
||||
#define EOL_COUNT 4
|
||||
#define EOL_SKIP_COUNT 4
|
||||
#else
|
||||
#define EOL_COUNT 5
|
||||
#define EOL_SKIP_COUNT 5
|
||||
#endif
|
||||
#define EOL_FLICKER_SKIP_COUNT 2
|
||||
|
||||
static int gpio_torch;
|
||||
static int led_curr;
|
||||
static int led_mode;
|
||||
|
||||
static char result_str[MAX_TEST_RESULT];
|
||||
|
||||
enum TEST_STATE {
|
||||
EOL_STATE_INIT = -1,
|
||||
EOL_STATE_100,
|
||||
EOL_STATE_120,
|
||||
EOL_STATE_DONE,
|
||||
};
|
||||
|
||||
struct test_data {
|
||||
u8 eol_enable;
|
||||
s16 eol_state;
|
||||
u32 eol_count;
|
||||
u32 eol_sum_count;
|
||||
u32 eol_awb;
|
||||
u32 eol_clear;
|
||||
u32 eol_wideband;
|
||||
u32 eol_flicker;
|
||||
u32 eol_flicker_sum;
|
||||
u32 eol_flicker_sum_count;
|
||||
u32 eol_flicker_count;
|
||||
u32 eol_flicker_skip_count;
|
||||
u32 eol_pulse_count;
|
||||
u32 eol_uv;
|
||||
};
|
||||
|
||||
struct result_data {
|
||||
int result;
|
||||
u32 flicker[EOL_STATE_DONE];
|
||||
u32 awb[EOL_STATE_DONE];
|
||||
u32 clear[EOL_STATE_DONE];
|
||||
u32 wideband[EOL_STATE_DONE];
|
||||
u32 ratio[EOL_STATE_DONE];
|
||||
u32 uv[EOL_STATE_DONE];
|
||||
};
|
||||
|
||||
enum GPIO_TYPE {
|
||||
EOL_FLASH,
|
||||
EOL_TORCH,
|
||||
};
|
||||
|
||||
void als_eol_set_env(bool torch, int intensity);
|
||||
struct result_data* als_eol_mode(void);
|
||||
|
||||
void als_eol_update_als(int awb, int clear, int wideband, int uv);
|
||||
void als_eol_update_flicker(int Hz);
|
||||
void als_eol_set_err_handler(void (*handler)(void));
|
||||
#endif /* EOL_TEST_H */
|
74
drivers/optics/platform_config.h
Executable file
74
drivers/optics/platform_config.h
Executable file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
*
|
||||
* $Id: platform_config.h
|
||||
*
|
||||
* Copyright (C) 2019 Bk, sensortek Inc.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PLATFORM_CONFIG_H__
|
||||
#define __PLATFORM_CONFIG_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#ifdef CONFIG_IIO
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ADDR_8BIT,
|
||||
ADDR_16BIT,
|
||||
} I2C_REG_ADDR_TYPE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPI_MODE0,
|
||||
SPI_MODE1,
|
||||
SPI_MODE2,
|
||||
SPI_MODE3,
|
||||
} SPI_TRANSFER_MODE;
|
||||
|
||||
struct spi_manager
|
||||
{
|
||||
struct spi_device *spi;
|
||||
struct mutex lock;
|
||||
SPI_TRANSFER_MODE trans_mode;
|
||||
void *any;
|
||||
u8 *spi_buffer; /* SPI buffer, used for SPI transfer. */
|
||||
} ;
|
||||
|
||||
struct i2c_manager
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct mutex lock;
|
||||
I2C_REG_ADDR_TYPE addr_type;
|
||||
void *any;
|
||||
} ;
|
||||
|
||||
#define kzalloc(size, mode) kzalloc(size, mode)
|
||||
#define kfree(ptr) kfree(ptr)
|
||||
|
||||
extern const struct stk_bus_ops stk_spi_bops;
|
||||
extern const struct stk_bus_ops stk_i2c_bops;
|
||||
extern const struct stk_timer_ops stk_t_ops;
|
||||
extern const struct stk_gpio_ops stk_g_ops;
|
||||
|
||||
#endif // __PLATFORM_CONFIG_H__
|
1368
drivers/optics/stk6d2x.c
Executable file
1368
drivers/optics/stk6d2x.c
Executable file
File diff suppressed because it is too large
Load Diff
668
drivers/optics/stk6d2x.h
Executable file
668
drivers/optics/stk6d2x.h
Executable file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
*
|
||||
* $Id: stk6d2x.h
|
||||
*
|
||||
* Copyright (C) 2012~2018 Bk, sensortek Inc.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __STK6D2X_H__
|
||||
#define __STK6D2X_H__
|
||||
|
||||
#if IS_ENABLED(CONFIG_SENSORS_FLICKER_SELF_TEST)
|
||||
#include "flicker_test.h"
|
||||
#endif
|
||||
|
||||
#include "common_define.h"
|
||||
#include "stk6d2x_ver.h"
|
||||
|
||||
#define STK6D2X_DEV_NAME "STK6D2X"
|
||||
//#define ALS_NAME "lightsensor-level"
|
||||
#define MODULE_NAME_ALS "als_rear"
|
||||
#define APS_TAG "[ALS/PS] "
|
||||
#define APS_FUN(f) printk(KERN_INFO APS_TAG" %s\n", __FUNCTION__)
|
||||
#define APS_ERR(fmt, args...) printk(KERN_ERR APS_TAG" %s %d: "fmt"\n", __FUNCTION__, __LINE__, ##args)
|
||||
#define APS_LOG(fmt, args...) printk(KERN_INFO APS_TAG" %s %d: "fmt"\n", __FUNCTION__, __LINE__, ##args)
|
||||
#define APS_DBG(fmt, args...) printk(KERN_INFO APS_TAG" %s %d: "fmt"\n", __FUNCTION__, __LINE__, ##args)
|
||||
|
||||
/* Driver Settings */
|
||||
#define STK_ALS_ENABLE
|
||||
// #define STK_ALS_CALI
|
||||
#define STK_FIFO_ENABLE
|
||||
#define STK_ALS_AGC
|
||||
#define STK_CHK_XFLG
|
||||
#define CONFIG_AMS_ALS_COMPENSATION_FOR_AUTO_BRIGHTNESS
|
||||
#define CONFIG_AMS_ALWAYS_ON_MODE_FOR_AUTO_BRIGHTNESS
|
||||
|
||||
#ifdef STK_FIFO_ENABLE
|
||||
// #define STK_DATA_SUMMATION
|
||||
// #define STK_FIFO_DATA_SUMMATION
|
||||
#define STK_FFT_FLICKER
|
||||
#ifdef STK_FFT_FLICKER
|
||||
#define STK_CHK_CLK_SRC
|
||||
#define SEC_FFT_FLICKER_1024
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define Register Map */
|
||||
#define STK6D2X_REG_STATE 0x00
|
||||
#define STK6D2X_REG_ALS01_DGAIN 0x01
|
||||
#define STK6D2X_REG_ALS2_DGAIN 0x02
|
||||
#define STK6D2X_REG_IT1 0x03
|
||||
#define STK6D2X_REG_IT2 0x04
|
||||
#define STK6D2X_REG_WAIT1 0x05
|
||||
#define STK6D2X_REG_WAIT2 0x06
|
||||
#define STK6D2X_REG_ALS_SUM_GAIN1 0x08
|
||||
#define STK6D2X_REG_ALS_SUM_GAIN2 0x09
|
||||
#define STK6D2X_REG_THDH1_ALS 0x0A
|
||||
#define STK6D2X_REG_THDH2_ALS 0x0B
|
||||
#define STK6D2X_REG_THDL1_ALS 0x0C
|
||||
#define STK6D2X_REG_THDL2_ALS 0x0D
|
||||
#define STK6D2X_REG_ALS_IT_EXT 0x0E
|
||||
#define STK6D2X_REG_FLAG 0x10
|
||||
#define STK6D2X_REG_DATA1_ALS0 0x11
|
||||
#define STK6D2X_REG_DATA2_ALS0 0x12
|
||||
#define STK6D2X_REG_DATA1_ALS1 0x13
|
||||
#define STK6D2X_REG_DATA2_ALS1 0x14
|
||||
#define STK6D2X_REG_DATA1_ALS2 0x15
|
||||
#define STK6D2X_REG_DATA2_ALS2 0x16
|
||||
#define STK6D2X_REG_AGC1_DG 0x17
|
||||
#define STK6D2X_REG_AGC2_DG 0x18
|
||||
#define STK6D2X_REG_AGC_CROS_THD_FLAG 0x19
|
||||
#define STK6D2X_REG_AGC_AG 0x1A
|
||||
#define STK6D2X_REG_AGC_PD 0x1B
|
||||
#define STK6D2X_REG_DATA1_ALS0_SUM 0x1C
|
||||
#define STK6D2X_REG_DATA2_ALS0_SUM 0x1D
|
||||
#define STK6D2X_REG_DATA1_ALS1_SUM 0x1E
|
||||
#define STK6D2X_REG_DATA2_ALS1_SUM 0x1F
|
||||
#define STK6D2X_REG_DATA1_ALS2_SUM 0x20
|
||||
#define STK6D2X_REG_DATA2_ALS2_SUM 0x21
|
||||
#define STK6D2X_REG_DATA_AGC_SUM 0x22
|
||||
#define STK6D2X_REG_RID 0x3F
|
||||
#define STK6D2X_REG_ALS_PRST 0x40
|
||||
#define STK6D2X_REG_FIFO1 0x60
|
||||
#define STK6D2X_REG_FIFO1_WM_LV 0x61
|
||||
#define STK6D2X_REG_FIFO2_WM_LV 0x62
|
||||
#define STK6D2X_REG_FIFO_FCNT1 0x64
|
||||
#define STK6D2X_REG_FIFO_FCNT2 0x65
|
||||
#define STK6D2X_REG_FIFO_OUT 0x66
|
||||
#define STK6D2X_REG_AGC1 0x6A
|
||||
#define STK6D2X_REG_AGC2 0x6B
|
||||
#define STK6D2X_REG_ALS_SUM 0x70
|
||||
#define STK6D2X_REG_SW_RESET 0x80
|
||||
#define STK6D2X_REG_PDT_ID 0x92
|
||||
#define STK6D2X_REG_INT2 0xA5
|
||||
#define STK6D2X_REG_XFLAG 0xA6
|
||||
#define STK6D2X_REG_ALS_AGAIN 0xDB
|
||||
#define STK6D2X_REG_ALS_PD_REDUCE 0xF4
|
||||
|
||||
/* Define state reg */
|
||||
#define STK6D2X_STATE_EN_SUMMATION_SHIFT 3
|
||||
#define STK6D2X_STATE_EN_WAIT_SHIFT 2
|
||||
#define STK6D2X_STATE_EN_ALS_SHIFT 1
|
||||
#define STK6D2X_STATE_EN_FSM_RESTART_MASK 0x10
|
||||
#define STK6D2X_STATE_EN_SUMMATION_MASK 0x08
|
||||
#define STK6D2X_STATE_EN_WAIT_MASK 0x04
|
||||
#define STK6D2X_STATE_EN_ALS_MASK 0x02
|
||||
|
||||
/* Define ALS DGAIN reg */
|
||||
#define STK6D2X_ALS2_DGAIN_SHIFT 4
|
||||
#define STK6D2X_ALS1_DGAIN_SHIFT 0
|
||||
#define STK6D2X_ALS0_DGAIN_SHIFT 4
|
||||
#define STK6D2X_ALS2_DGAIN_MASK 0x70
|
||||
#define STK6D2X_ALS1_DGAIN_MASK 0x07
|
||||
#define STK6D2X_ALS0_DGAIN_MASK 0x70
|
||||
|
||||
/* Define interrupt reg */
|
||||
#define STK6D2X_INT_ALS_SHIFT 3
|
||||
#define STK6D2X_INT_ALS_MASK 0x08
|
||||
#define STK6D2X_INT_ALS 0x08
|
||||
|
||||
/* Define flag reg */
|
||||
#define STK6D2X_FLG_ALSDR_SHIFT 7
|
||||
#define STK6D2X_FLG_ALSINT_SHIFT 5
|
||||
#define STK6D2X_FLG_ALSSAT_SHIFT 2
|
||||
|
||||
#define STK6D2X_FLG_ALSDR_MASK 0x80
|
||||
#define STK6D2X_FLG_ALSINT_MASK 0x20
|
||||
#define STK6D2X_FLG_ALSSAT_MASK 0x04
|
||||
|
||||
/* Define ALS parameters */
|
||||
#define STK6D2X_ALS_PRS1 0x00
|
||||
#define STK6D2X_ALS_PRS2 0x40
|
||||
#define STK6D2X_ALS_PRS4 0x80
|
||||
#define STK6D2X_ALS_PRS8 0xC0
|
||||
|
||||
#define STK6D2X_ALS_DGAIN1 0x00
|
||||
#define STK6D2X_ALS_DGAIN4 0x01
|
||||
#define STK6D2X_ALS_DGAIN16 0x02
|
||||
#define STK6D2X_ALS_DGAIN64 0x03
|
||||
#define STK6D2X_ALS_DGAIN128 0x04
|
||||
#define STK6D2X_ALS_DGAIN256 0x05
|
||||
#define STK6D2X_ALS_DGAIN512 0x06
|
||||
#define STK6D2X_ALS_DGAIN1024 0x07
|
||||
#define STK6D2X_ALS_DGAIN_MASK 0x07
|
||||
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV1 0x00
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV2 0x01
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV4 0x02
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV8 0x03
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV6 0x04
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV32 0x05
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV64 0x06
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV128 0x07
|
||||
#define STK6D2X_ALS_SUM_GAIN_DIV256 0x08
|
||||
#define STK6D2X_ALS_SUM_GAIN_MASK 0x0F
|
||||
|
||||
#define STK6D2X_ALS_CI_2_0 0x00
|
||||
#define STK6D2X_ALS_CI_1_0 0x01
|
||||
#define STK6D2X_ALS_CI_0_5 0x02
|
||||
|
||||
#define STK6D2X_ALS_PD_REDUCE_DIS 0x00
|
||||
#define STK6D2X_ALS_PD_REDUCE_LV1 0x01
|
||||
#define STK6D2X_ALS_PD_REDUCE_LV2 0x02
|
||||
|
||||
#define STK6D2X_ALS_IT25 0x3A9
|
||||
#define STK6D2X_ALS_IT40 0x5DB
|
||||
#define STK6D2X_ALS_IT50 0x753
|
||||
#define STK6D2X_ALS_IT100 0xEA6
|
||||
#define STK6D2X_ALS_IT200 0x1D4D
|
||||
#define STK6D2X_ALS_IT1_MASK 0x3F
|
||||
|
||||
#define STK6D2X_ALS_IT_EXT_MASK 0x3F
|
||||
|
||||
#define STK6D2X_WAIT20 0x359
|
||||
#define STK6D2X_WAIT50 0x85F
|
||||
#define STK6D2X_WAIT100 0x10BE
|
||||
|
||||
#define STK6D2X_PRST1 0x00
|
||||
#define STK6D2X_PRST2 0x01
|
||||
#define STK6D2X_PRST4 0x02
|
||||
#define STK6D2X_PRST8 0x03
|
||||
|
||||
#define STK6D2X_FLG_ALS2_DG_MASK 0x40
|
||||
#define STK6D2X_FLG_ALS1_DG_MASK 0x20
|
||||
#define STK6D2X_FLG_ALS0_DG_MASK 0x10
|
||||
#define STK6D2X_ALS2_AGC_DG_MASK 0x07
|
||||
#define STK6D2X_ALS1_AGC_DG_MASK 0x70
|
||||
#define STK6D2X_ALS0_AGC_DG_MASK 0x07
|
||||
|
||||
#define STK6D2X_ALS2_AGC_AG_MASK 0x30
|
||||
#define STK6D2X_ALS1_AGC_AG_MASK 0x0C
|
||||
#define STK6D2X_ALS0_AGC_AG_MASK 0x03
|
||||
#define STK6D2X_ALS2_AGC_PD_MASK 0x30
|
||||
#define STK6D2X_ALS1_AGC_PD_MASK 0x0C
|
||||
#define STK6D2X_ALS0_AGC_PD_MASK 0x01
|
||||
#define STK6D2X_ALS0_AGC_PDMODE_MASK 0xC0
|
||||
#define STK6D2X_ALS0_AGC_PDMODE0 0x00
|
||||
#define STK6D2X_ALS0_AGC_PDMODE1 0x01
|
||||
#define STK6D2X_ALS0_AGC_PDMODE_SHIFT 6
|
||||
|
||||
#define STK6D2X_FLG_ALS2_SUM_AGC_MASK 0x40
|
||||
#define STK6D2X_FLG_ALS1_SUM_AGC_MASK 0x20
|
||||
#define STK6D2X_FLG_ALS0_SUM_AGC_MASK 0x10
|
||||
|
||||
#define STK6D2X_TYPE_ALS0 0
|
||||
#define STK6D2X_TYPE_ALS1 1
|
||||
#define STK6D2X_TYPE_ALS2 2
|
||||
|
||||
/** sw reset value */
|
||||
#define STK_STK6D2X_SWRESET 0x00
|
||||
|
||||
/** Off to idle time */
|
||||
#define STK6D2X_OFF_TO_IDLE_MS 10 //ms
|
||||
|
||||
/** ALS threshold */
|
||||
#define STK6D2X_ALS_THD_ADJ 0.05
|
||||
#define STK6D2X_NUM_AXES 3
|
||||
#define STK6D2X_MAX_MIN_DIFF 200
|
||||
#define STK6D2X_LT_N_CT 1700
|
||||
#define STK6D2X_HT_N_CT 2200
|
||||
|
||||
#define STK6D2X_ALS_DATA_READY_TIME 60
|
||||
#define STK6D2X_ALS_THRESHOLD 30
|
||||
|
||||
#define STK6D2X_ALS_SUMMATION_CNT 51
|
||||
|
||||
#ifdef STK_ALS_CALI
|
||||
#define STK6D2X_ALS_CALI_DATA_READY_US 55000000
|
||||
#define STK6D2X_ALS_CALI_TARGET_LUX 500
|
||||
#endif
|
||||
|
||||
#ifdef STK_UV_CALI
|
||||
#define STK6D2X_UV_CALI_TARGET 10
|
||||
#endif
|
||||
|
||||
#define STK_FLICKER_IT 0x0C
|
||||
#define STK_FLICKER_EXT_IT 0x0D
|
||||
|
||||
#ifdef STK_FIFO_ENABLE
|
||||
#define STK_FIFO_DATA_BUFFER_LEN 1024
|
||||
#define STK_FIFO_I2C_READ_FRAME 30//get fifo data one time
|
||||
#define STK_FIFO_I2C_READ_FRAME_BUF_SIZE STK_FIFO_I2C_READ_FRAME * 10
|
||||
#define STK_FIFO_I2C_READ_FRAME_TARGET 102
|
||||
|
||||
#ifdef STK_FFT_FLICKER
|
||||
#define FFT_BLOCK_SIZE 128
|
||||
#define FFT_BUF_SIZE 1024
|
||||
#endif
|
||||
|
||||
#define STK6D2X_FIFO_SEL_ALS0 0x00
|
||||
#define STK6D2X_FIFO_SEL_ALS1 0x01
|
||||
#define STK6D2X_FIFO_SEL_ALS2 0x02
|
||||
#define STK6D2X_FIFO_SEL_ALS0_ALS1 0x03
|
||||
#define STK6D2X_FIFO_SEL_ALS0_ALS2 0x04
|
||||
#define STK6D2X_FIFO_SEL_ALS1_ALS2 0x05
|
||||
#define STK6D2X_FIFO_SEL_ALS0_ALS1_ALS2 0x06
|
||||
#define STK6D2X_FIFO_SEL_STA0_ALS0 0x08
|
||||
#define STK6D2X_FIFO_SEL_STA1_ALS1 0x09
|
||||
#define STK6D2X_FIFO_SEL_STA2_ALS2 0x0A
|
||||
#define STK6D2X_FIFO_SEL_STA01_ALS0_ALS1 0x0B
|
||||
#define STK6D2X_FIFO_SEL_STA02_ALS0_ALS2 0x0C
|
||||
#define STK6D2X_FIFO_SEL_STA12_ALS1_ALS2 0x0D
|
||||
#define STK6D2X_FIFO_SEL_STA01_STA2_ALS0_ALS1_ALS2 0x0E
|
||||
#define STK6D2X_FIFO_SEL_MASK 0x0F
|
||||
|
||||
#define STK6D2X_FIFO_MODE_OFF 0x00
|
||||
#define STK6D2X_FIFO_MODE_BYPASS 0x10
|
||||
#define STK6D2X_FIFO_MODE_NORMAL 0x20
|
||||
#define STK6D2X_FIFO_MODE_STREAM 0x30
|
||||
|
||||
#define STK6D2X_FOVR_EN_MASK 0x04
|
||||
#define STK6D2X_FWM_EN_MASK 0x02
|
||||
#define STK6D2X_FFULL_EN_MASK 0x01
|
||||
|
||||
#define STK6D2X_FLG_FIFO_OVR_MASK 0x04
|
||||
#define STK6D2X_FLG_FIFO_WM_MASK 0x02
|
||||
#define STK6D2X_FLG_FIFO_FULL_MASK 0x01
|
||||
#endif
|
||||
|
||||
#define STK_ALSPS_TIMER_MS 90
|
||||
|
||||
#define STK6D2X_CALI_FILE "/persist/sensors/stkalpscali.conf"
|
||||
#define STK_CHANNEL_NUMBER 3
|
||||
#define STK_CHANNEL_OFFSET 3
|
||||
#define STK_CHANNEL_GOLDEN 10
|
||||
|
||||
#define STK6D2X_REG_READ(stk_data, reg, val) ((stk_data)->bops->read((stk_data)->bus_idx, reg, val))
|
||||
#define STK6D2X_REG_WRITE(stk_data, reg, val) ((stk_data)->bops->write((stk_data)->bus_idx, reg, val))
|
||||
#define STK6D2X_REG_WRITE_BLOCK(stk_data, reg, val, len) ((stk_data)->bops->write_block((stk_data)->bus_idx, reg, val, len))
|
||||
#define STK6D2X_REG_READ_MODIFY_WRITE(stk_data, reg, val, mask) ((stk_data)->bops->read_modify_write((stk_data)->bus_idx, reg, val, mask))
|
||||
#define STK6D2X_REG_BLOCK_READ(stk_data, reg, count, buf) ((stk_data)->bops->read_block((stk_data)->bus_idx, reg, count, buf))
|
||||
|
||||
#define STK6D2X_TIMER_REGISTER(stk_data, t_info) ((stk_data)->tops->register_timer(t_info))
|
||||
#define STK6D2X_TIMER_START(stk_data, t_info) ((stk_data)->tops->start_timer(t_info))
|
||||
#define STK6D2X_TIMER_STOP(stk_data, t_info) ((stk_data)->tops->stop_timer(t_info))
|
||||
#define STK6D2X_TIMER_REMOVE(stk_data, t_info) ((stk_data)->tops->remove(t_info))
|
||||
#define STK6D2X_TIMER_BUSY_WAIT(stk_data, min, max, mode) ((stk_data)->tops->busy_wait(min, max, mode))
|
||||
|
||||
#define STK6D2X_GPIO_IRQ_REGISTER(stk_data, g_info) ((stk_data)->gops->register_gpio_irq(g_info))
|
||||
#define STK6D2X_GPIO_IRQ_START(stk_data, g_info) ((stk_data)->gops->start_gpio_irq(g_info))
|
||||
#define STK6D2X_GPIO_IRQ_STOP(stk_data, g_info) ((stk_data)->gops->stop_gpio_irq(g_info))
|
||||
#define STK6D2X_GPIO_IRQ_REMOVE(stk_data, g_info) ((stk_data)->gops->remove(g_info))
|
||||
|
||||
#define STK6D2X_ALS_REPORT(stk_data, als_data, num) if ((stk_data)->als_report_cb) ((stk_data)->als_report_cb(stk_data, als_data, num))
|
||||
|
||||
#define STK_ABS(x) ((x < 0)? (-x):(x))
|
||||
|
||||
enum fft_size {
|
||||
FFT_128 = 128,
|
||||
FFT_256 = 256,
|
||||
FFT_512 = 512,
|
||||
FFT_1024 = 1024,
|
||||
//FFT_2048 = 2048, // not ready
|
||||
};
|
||||
|
||||
// sec_fft
|
||||
#define SEC_FFT_SIZE FFT_1024
|
||||
#define SAMPLING_TIME (488319) /* nsec (2048Hz) */
|
||||
//#define FLICKER_AVG_SHIFT 7
|
||||
#define FLICKER_AVG_SHIFT 14
|
||||
#define SEC_LOCAL_AVG_SIZE 128 // 1024/n recommended, no 1024
|
||||
|
||||
// average/max thd
|
||||
#define FLICKER_AVGMAX_THD 65LL
|
||||
#define FLICKER_AVGMAX_THD2 29LL
|
||||
|
||||
// sec_ calc_thd
|
||||
#define FLICKER_THD_CLEAR 1800LL /* 1.8 * 1000 */
|
||||
#define FLICKER_THD_RATIO 3LL /* 0.003 * 1000 */
|
||||
#define FLICKER_GAIN_MAX 256LL /* 256 */
|
||||
#define FLICKER_THD_RATIO_AUTO 1000LL /* 1 * 1000 */
|
||||
|
||||
typedef struct stk6d2x_data stk6d2x_data;
|
||||
typedef void (*STK_REPORT_CB)(stk6d2x_data *, uint32_t*, uint32_t);
|
||||
|
||||
/* platform data */
|
||||
struct stk6d2x_platform_data
|
||||
{
|
||||
uint32_t als_scale;
|
||||
uint32_t int_flags;
|
||||
};
|
||||
typedef enum
|
||||
{
|
||||
STK6D2X_NONE = 0x0,
|
||||
STK6D2X_ALS = 0x1,
|
||||
STK6D2X_ALL = 0x2,
|
||||
} stk6d2x_sensor_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STK6D2X_DATA_TIMER_ALPS,
|
||||
#ifdef STK_FIFO_ENABLE
|
||||
//STK6D2X_FIFO_RELEASE_TIMER,
|
||||
#endif
|
||||
} stk6d2x_timer_type;
|
||||
|
||||
typedef struct stk6d2x_register_table
|
||||
{
|
||||
uint8_t address;
|
||||
uint8_t value;
|
||||
uint8_t mask_bit;
|
||||
} stk6d2x_register_table;
|
||||
|
||||
#ifdef STK_FIFO_ENABLE
|
||||
typedef enum
|
||||
{
|
||||
STK6D2X_FIFO_ALS0 = 0x0,
|
||||
STK6D2X_FIFO_ALS1 = 0x1,
|
||||
STK6D2X_FIFO_ALS2 = 0x2,
|
||||
STK6D2X_FIFO_ALS0_ALS1 = 0x3,
|
||||
STK6D2X_FIFO_ALS0_ALS2 = 0x4,
|
||||
STK6D2X_FIFO_ALS1_ALS2 = 0x5,
|
||||
STK6D2X_FIFO_ALS0_ALS1_ALS2 = 0x6,
|
||||
STK6D2X_FIFO_STA0_ALS0 = 0x8,
|
||||
STK6D2X_FIFO_STA1_ALS1 = 0x9,
|
||||
STK6D2X_FIFO_STA2_ALS2 = 0xA,
|
||||
STK6D2X_FIFO_STA01_ALS0_ALS1 = 0xB,
|
||||
STK6D2X_FIFO_STA02_ALS0_ALS2 = 0xC,
|
||||
STK6D2X_FIFO_STA12_ALS1_ALS2 = 0xD,
|
||||
STK6D2X_FIFO_STA01_STA2_ALS0_ALS1_ALS2 = 0xE,
|
||||
STK6D2X_FIFO_UNAVAILABLE = 0xF,
|
||||
} stk6d2x_frame_type;
|
||||
#endif
|
||||
|
||||
#ifdef STK_ALS_CALI
|
||||
typedef enum
|
||||
{
|
||||
STK6D2X_CALI_IDLE,
|
||||
STK6D2X_CALI_RUNNING,
|
||||
STK6D2X_CALI_FAILED,
|
||||
STK6D2X_CALI_DONE
|
||||
} stk6d2x_calibration_status;
|
||||
#endif
|
||||
|
||||
#ifdef STK_ALS_AGC
|
||||
typedef enum
|
||||
{
|
||||
STK6D2X_ALS_DGAIN_MULTI1 = 1,
|
||||
STK6D2X_ALS_DGAIN_MULTI4 = 4,
|
||||
STK6D2X_ALS_DGAIN_MULTI16 = 16,
|
||||
STK6D2X_ALS_DGAIN_MULTI64 = 64,
|
||||
STK6D2X_ALS_DGAIN_MULTI128 = 128,
|
||||
STK6D2X_ALS_DGAIN_MULTI256 = 256,
|
||||
STK6D2X_ALS_DGAIN_MULTI512 = 512,
|
||||
STK6D2X_ALS_DGAIN_MULTI1024 = 1024,
|
||||
} stk6d2x_als_dgain_multi;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STK6D2X_ALS_AGAIN_MULTI1 = 1,
|
||||
STK6D2X_ALS_AGAIN_MULTI2 = 2,
|
||||
STK6D2X_ALS_AGAIN_MULTI4 = 4,
|
||||
} stk6d2x_als_again_multi;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STK6D2X_ALS_PD_REDUCE_MULTI1 = 1,
|
||||
STK6D2X_ALS_PD_REDUCE_MULTI2 = 2,
|
||||
STK6D2X_ALS_PD_REDUCE_MULTI3 = 3,
|
||||
STK6D2X_ALS_PD_REDUCE_MULTI4 = 4,
|
||||
} stk6d2x_als_pd_reduce_multi;
|
||||
#endif
|
||||
|
||||
typedef struct stk6d2x_cali_table
|
||||
{
|
||||
uint32_t als_version;
|
||||
uint32_t als_scale;
|
||||
uint32_t als_bias;
|
||||
} stk6d2x_cali_table;
|
||||
|
||||
typedef struct stk6d2x_cali_info
|
||||
{
|
||||
#ifdef STK_ALS_CALI
|
||||
stk6d2x_calibration_status cali_status;
|
||||
#endif
|
||||
stk6d2x_cali_table cali_para;
|
||||
} stk6d2x_cali_info;
|
||||
|
||||
typedef struct stk6d2x_als_info
|
||||
{
|
||||
bool first_init;
|
||||
bool cali_enable;
|
||||
bool enable;
|
||||
uint32_t scale;
|
||||
bool is_data_ready;
|
||||
uint16_t als_it;
|
||||
uint8_t cali_failed_count;
|
||||
uint64_t last_raw_data[3];
|
||||
uint16_t als_cali_data;
|
||||
uint16_t last_lux;
|
||||
#ifdef STK_ALS_AGC
|
||||
uint16_t als_agc_sum;
|
||||
uint16_t als_cur_dgain[3];
|
||||
uint16_t als_cur_again[3];
|
||||
uint16_t als_cur_pd_reduce[3];
|
||||
uint8_t als_cur_pd_mode;
|
||||
uint32_t als_cur_ratio[3];
|
||||
uint8_t als_agc_sum_flag;
|
||||
uint32_t als_sum_gain_div[3];
|
||||
#endif
|
||||
} stk6d2x_als_info;
|
||||
|
||||
#ifdef STK_FIFO_ENABLE
|
||||
typedef struct stk6d2x_fifo_info
|
||||
{
|
||||
bool fifo_enable;
|
||||
bool is_fifobuf_alloc;
|
||||
uint32_t fifo_data0[FFT_BUF_SIZE];
|
||||
uint32_t fifo_data1[FFT_BUF_SIZE];
|
||||
uint32_t fifo_data2[FFT_BUF_SIZE];
|
||||
#ifdef SEC_FFT_FLICKER_1024
|
||||
uint32_t fifo_data_clear[FFT_BUF_SIZE];
|
||||
uint32_t fifo_data_uv[FFT_BUF_SIZE];
|
||||
uint32_t fifo_data_ir[FFT_BUF_SIZE];
|
||||
uint32_t fifo_gain_clear[FFT_BUF_SIZE];
|
||||
uint32_t fifo_gain_uv[FFT_BUF_SIZE];
|
||||
uint32_t fifo_gain_ir[FFT_BUF_SIZE];
|
||||
uint8_t fifo_xflag[FFT_BUF_SIZE];
|
||||
#endif
|
||||
uint64_t fifo_sum_als0;
|
||||
uint64_t fifo_sum_als1;
|
||||
uint64_t fifo_sum_als2;
|
||||
uint32_t fifo_sum_cnt;
|
||||
uint16_t target_frame_count;
|
||||
uint16_t read_frame;
|
||||
uint16_t read_max_data_byte;
|
||||
uint8_t latency_status;
|
||||
stk6d2x_frame_type data_type;
|
||||
bool sel_mode;
|
||||
uint8_t frame_byte;
|
||||
uint8_t frame_data;
|
||||
uint16_t last_frame_count;
|
||||
bool fifo_reading;
|
||||
bool ext_clk_chk;
|
||||
bool pre_ext_clk_chk;
|
||||
uint16_t block_size;
|
||||
#ifdef STK_FFT_FLICKER
|
||||
uint32_t fft_buf[FFT_BUF_SIZE];
|
||||
uint32_t fft_uv_buf[FFT_BUF_SIZE];
|
||||
uint32_t fft_ir_buf[FFT_BUF_SIZE];
|
||||
uint32_t fft_gain_clear[FFT_BUF_SIZE];
|
||||
uint32_t fft_gain_uv[FFT_BUF_SIZE];
|
||||
uint32_t fft_gain_ir[FFT_BUF_SIZE];
|
||||
uint8_t fft_xflag[FFT_BUF_SIZE];
|
||||
uint32_t fft_buf_idx;
|
||||
#endif
|
||||
} stk6d2x_fifo_info;
|
||||
#endif
|
||||
|
||||
#define PWR_ON 1
|
||||
#define PWR_OFF 0
|
||||
#define PM_RESUME 1
|
||||
#define PM_SUSPEND 0
|
||||
|
||||
struct stk6d2x_data
|
||||
{
|
||||
struct stk6d2x_platform_data *pdata;
|
||||
const struct stk_bus_ops *bops;
|
||||
struct mutex config_lock;
|
||||
#if defined(CONFIG_AMS_ALS_COMPENSATION_FOR_AUTO_BRIGHTNESS)
|
||||
struct mutex enable_lock;
|
||||
#endif
|
||||
const struct stk_timer_ops *tops;
|
||||
const struct stk_gpio_ops *gops;
|
||||
int bus_idx;
|
||||
stk_gpio_info gpio_info;
|
||||
#ifdef STK_ALS_CALI
|
||||
stk_timer_info cali_timer_info;
|
||||
#endif
|
||||
stk6d2x_cali_info cali_info;
|
||||
stk6d2x_als_info als_info;
|
||||
stk_timer_info alps_timer_info;
|
||||
bool saturation;
|
||||
#ifdef STK_FIFO_ENABLE
|
||||
stk6d2x_fifo_info fifo_info;
|
||||
// fifo control timer
|
||||
stk_timer_info fifo_release_timer_info;
|
||||
uint64_t clear_local_average;
|
||||
uint64_t uv_local_average;
|
||||
uint64_t ir_local_average;
|
||||
bool is_clear_local_sat;
|
||||
bool is_uv_local_sat;
|
||||
bool is_ir_local_sat;
|
||||
int index_last;
|
||||
bool is_first;
|
||||
bool is_local_avg_update;
|
||||
uint32_t flicker;
|
||||
uint32_t uv_gain;
|
||||
uint32_t clear_gain;
|
||||
uint32_t ir_gain;
|
||||
#endif
|
||||
uint8_t rid;
|
||||
uint8_t xflag;
|
||||
STK_REPORT_CB als_report_cb;
|
||||
bool first_init;
|
||||
bool is_long_it;
|
||||
bool pm_state;
|
||||
u8 regulator_state;
|
||||
struct regulator* regulator_vdd_1p8;
|
||||
struct regulator* regulator_vbus_1p8;
|
||||
bool vdd_1p8_enable;
|
||||
bool vbus_1p8_enable;
|
||||
struct pinctrl *als_pinctrl;
|
||||
struct pinctrl_state *pins_sleep;
|
||||
struct pinctrl_state *pins_active;
|
||||
#if IS_ENABLED(CONFIG_SENSORS_FLICKER_SELF_TEST)
|
||||
bool eol_enabled;
|
||||
bool recover_state;
|
||||
#endif
|
||||
int isTrimmed;
|
||||
#if defined(CONFIG_AMS_ALS_COMPENSATION_FOR_AUTO_BRIGHTNESS)
|
||||
bool als_flag;
|
||||
bool flicker_flag;
|
||||
#endif
|
||||
int ext_clk_gpio;
|
||||
struct clk *pclk;
|
||||
struct rcg_clk *camcc_mclk5_rcg_clk;
|
||||
struct regulator *reg;
|
||||
bool reg_enable;
|
||||
bool use_ext_clk;
|
||||
} ;
|
||||
|
||||
extern int als_debug;
|
||||
extern int als_info;
|
||||
|
||||
#define ALS_DBG
|
||||
//#define ALS_INFO
|
||||
|
||||
#ifndef ALS_dbg
|
||||
#if defined(ALS_DBG)
|
||||
#define ALS_dbg(format, arg...) \
|
||||
printk(KERN_DEBUG "ALS_dbg : %s: %d " format, __func__, __LINE__, ##arg)
|
||||
#define ALS_err(format, arg...) \
|
||||
printk(KERN_DEBUG "ALS_err : %s: %d " format, __func__, __LINE__, ##arg)
|
||||
#else
|
||||
#define ALS_dbg(format, arg...) {if (als_debug)\
|
||||
printk(KERN_DEBUG "ALS_dbg : %s: %d " format, __func__, __LINE__, ##arg);\
|
||||
}
|
||||
#define ALS_err(format, arg...) {if (als_debug)\
|
||||
printk(KERN_DEBUG "ALS_err : %s: %d " format, __func__, __LINE__, ##arg);\
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALS_info
|
||||
#if defined(ALS_INFO)
|
||||
#define ALS_info(format, arg...) \
|
||||
printk(KERN_INFO "ALS_info : %s: %d " format, __func__, __LINE__, ##arg);
|
||||
#else
|
||||
#define ALS_info(format, arg...) {if (als_info)\
|
||||
printk(KERN_INFO "ALS_info : %s: %d " format, __func__, __LINE__, ##arg);\
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int32_t stk6d2x_cali_als(struct stk6d2x_data *alps_data);
|
||||
void stk6d2x_get_reg_default_setting(uint8_t reg, uint16_t* value);
|
||||
int32_t stk6d2x_request_registry(struct stk6d2x_data *alps_data);
|
||||
int32_t stk6d2x_update_registry(struct stk6d2x_data *alps_data);
|
||||
int32_t stk6d2x_alps_set_config(stk6d2x_data *alps_data, bool en);
|
||||
int32_t stk6d2x_init_all_setting(stk6d2x_data *alps_data);
|
||||
int32_t stk6d2x_als_get_data(stk6d2x_data *alps_data, bool is_skip);
|
||||
void stk6d2x_dump_reg(struct stk6d2x_data *alps_data);
|
||||
void stk6d2x_force_stop(stk6d2x_data *alps_data);
|
||||
|
||||
extern int sensors_create_symlink(struct kobject *target, const char *name);
|
||||
extern void sensors_remove_symlink(struct kobject *target, const char *name);
|
||||
extern int sensors_register(struct device **dev, void *drvdata,
|
||||
struct device_attribute *attributes[], char *name);
|
||||
extern void sensors_unregister(struct device *dev,
|
||||
struct device_attribute *attributes[]);
|
||||
|
||||
int32_t stk6d2x_enable_als(stk6d2x_data *alps_data, bool en);
|
||||
|
||||
#ifdef STK_ALS_AGC
|
||||
int32_t stk6d2x_cal_curDGain(uint8_t gain_val);
|
||||
uint8_t stk6d2x_als_get_again_multiple(uint8_t gain);
|
||||
uint8_t stk6d2x_als_get_pd_multiple(uint8_t gain, uint8_t pd_mode, uint8_t data_type);
|
||||
int32_t stk6d2x_get_curGain(struct stk6d2x_data *alps_data);
|
||||
void stk6d2x_get_als_ratio(struct stk6d2x_data *alps_data);
|
||||
#ifdef SEC_FFT_FLICKER_1024
|
||||
uint8_t stk6d2x_sec_dgain(uint8_t gain_val);
|
||||
uint8_t stk6d2x_sec_again(uint8_t gain);
|
||||
uint8_t stk6d2x_sec_pd_multiple(uint8_t gain, uint8_t pd_mode, uint8_t data_type);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef STK_FIFO_ENABLE
|
||||
void stk6d2x_free_fifo_data(struct stk6d2x_data *alps_data);
|
||||
void stk6d2x_alloc_fifo_data(struct stk6d2x_data *alps_data, uint32_t size);
|
||||
void stk6d2x_fifo_init(struct stk6d2x_data *alps_data);
|
||||
int32_t stk6d2x_enable_fifo(struct stk6d2x_data *alps_data, bool en);
|
||||
void stk6d2x_fifo_get_data(struct stk6d2x_data *alps_data, uint16_t frame_num);
|
||||
void stk6d2x_get_fifo_data_polling(struct stk6d2x_data *alps_data);
|
||||
void stk6d2x_fifo_stop_control(stk_timer_info *t_info);
|
||||
#endif
|
||||
#if defined(CONFIG_AMS_ALS_COMPENSATION_FOR_AUTO_BRIGHTNESS)
|
||||
void stk_als_init(struct stk6d2x_data *alps_data);
|
||||
void stk_als_start(struct stk6d2x_data *alps_data);
|
||||
void stk_als_stop(struct stk6d2x_data *alps_data);
|
||||
#endif
|
||||
int32_t stk_power_ctrl(struct stk6d2x_data *alps_data, bool en);
|
||||
void stk6d2x_pin_control(struct stk6d2x_data *alps_data, bool pin_set);
|
||||
void stk_sec_report(struct stk6d2x_data *alps_data);
|
||||
#endif // __STK6D2X_H__
|
138
drivers/optics/stk6d2x_cal_gpio.c
Executable file
138
drivers/optics/stk6d2x_cal_gpio.c
Executable file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License, 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stk6d2x.h>
|
||||
#include <linux/pwm.h>
|
||||
|
||||
#define OSC_CAL_FREQ (40)
|
||||
|
||||
static u16 cal_period = 0xffff;
|
||||
|
||||
u16 ams_pwm_gpio_period(struct stk6d2x_data *alps_data);
|
||||
|
||||
int stk6d2x_setup_pwm(struct stk6d2x_data *alps_data, long pwm_freq)
|
||||
{
|
||||
int ret = 0;
|
||||
stk6d2x_wrapper *stk_wrapper = container_of(alps_data, stk6d2x_wrapper, alps_data);
|
||||
struct device *dev = stk_wrapper->dev;
|
||||
struct clk *pclk = NULL;
|
||||
|
||||
ALS_dbg("setup gpio pwm %d Hz\n", pwm_freq);
|
||||
|
||||
pclk = devm_clk_get(dev, "gpio_pwm_default-clk");
|
||||
if (NULL == pclk) {
|
||||
ALS_err("get pclk (gpio_pwm_default-clk) error. \n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pwm_freq > 0) {
|
||||
#if 0
|
||||
if (__clk_is_enabled(pclk)) {
|
||||
ALS_dbg("clk_disable_unprepare (pclk) start! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
|
||||
clk_disable_unprepare(pclk);
|
||||
}
|
||||
|
||||
msleep_interruptible(10);
|
||||
#endif
|
||||
ret = clk_set_rate(pclk, pwm_freq);
|
||||
if (ret) {
|
||||
ALS_err("clk_set_rate (pclk) fail! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
|
||||
return ret;
|
||||
} else {
|
||||
ALS_dbg("clk_set_rate (pclk) success! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
|
||||
}
|
||||
|
||||
if (!__clk_is_enabled(pclk)) {
|
||||
ret = clk_prepare_enable(pclk);
|
||||
if (ret) {
|
||||
ALS_err("clk_prepare_enable (pclk) fail! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
|
||||
return ret;
|
||||
} else {
|
||||
ALS_dbg("clk_prepare_enable (pclk) success! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (__clk_is_enabled(pclk)) {
|
||||
clk_disable_unprepare(pclk);
|
||||
ALS_dbg("clk_disable_unprepare (pclk) start! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t stk6d2x_osc_cal_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
stk6d2x_wrapper *stk_wrapper = dev_get_drvdata(dev);
|
||||
stk6d2x_data *alps_data = &stk_wrapper->alps_data;
|
||||
int pwm_Hz = 0;
|
||||
int err = 0;
|
||||
|
||||
if (!data->osc_cal) {
|
||||
ALS_err("no osc calibration mode\n");
|
||||
return size;
|
||||
}
|
||||
|
||||
err = kstrtoint(buf, 10, &pwm_Hz);
|
||||
|
||||
if (err < 0) {
|
||||
ALS_err("kstrtoint failed.(%d)\n", err);
|
||||
return size;
|
||||
}
|
||||
|
||||
if (pwm_Hz == 0) {
|
||||
ALS_dbg("pwm output stop! (%d Hz)\n", pwm_Hz);
|
||||
stk6d2x_setup_pwm(alps_data, 0);
|
||||
} else if ((pwm_Hz > 0) && (pwm_Hz <= 120)) {
|
||||
stk6d2x_pin_control(alps_data, true);
|
||||
|
||||
if (pwm_Hz == 1) {
|
||||
ALS_dbg("pwm output start! (%d Hz)\n", OSC_CAL_FREQ);
|
||||
stk6d2x_osc_cal(alps_data);
|
||||
} else {
|
||||
ALS_dbg("pwm output start! (%d Hz)\n", pwm_Hz);
|
||||
stk6d2x_setup_pwm(alps_data, pwm_Hz);
|
||||
}
|
||||
} else {
|
||||
ALS_err("pwm out of range error! (%d Hz)\n", pwm_Hz);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void stk6d2x_osc_cal(struct stk6d2x_data *alps_data)
|
||||
{
|
||||
u16 ret;
|
||||
|
||||
stk6d2x_setup_pwm(alps_data, OSC_CAL_FREQ);
|
||||
|
||||
ret = ams_pwm_gpio_period(alps_data);
|
||||
if (ret != 0) {
|
||||
cal_period = ret;
|
||||
}
|
||||
ALS_dbg("cal_period = %d", ret);
|
||||
|
||||
stk6d2x_setup_pwm(alps_data, 0);
|
||||
}
|
||||
|
||||
u16 stk6d2x_get_pwm_calibration(void)
|
||||
{
|
||||
if (cal_period == 0)
|
||||
return 0xffff;
|
||||
return cal_period;
|
||||
}
|
86
drivers/optics/stk6d2x_cal_pwm.c
Executable file
86
drivers/optics/stk6d2x_cal_pwm.c
Executable file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License, 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stk6d2x.h>
|
||||
#include <linux/pwm.h>
|
||||
|
||||
#define OSC_CAL_FREQ 40
|
||||
|
||||
static u16 cal_period = -1;
|
||||
|
||||
u16 ams_pwm_gpio_period(struct stk6d2x_data *alps_data);
|
||||
static struct pwm_device *pwm = NULL;
|
||||
|
||||
int stk6d2x_setup_pwm(struct stk6d2x_data *alps_data, bool onoff)
|
||||
{
|
||||
stk6d2x_wrapper *stk_wrapper = container_of(alps_data, stk6d2x_wrapper, alps_data);
|
||||
struct device_node *np = stk_wrapper->dev->of_node;
|
||||
long period = 1000000000 / OSC_CAL_FREQ;
|
||||
long duty = period >> 1;
|
||||
int ret = 0;
|
||||
|
||||
if (onoff) {
|
||||
if (pwm == NULL) {
|
||||
pwm = devm_of_pwm_get(dev, np, NULL);
|
||||
if (IS_ERR(pwm)) {
|
||||
ALS_dbg("pwm_get error %d", PTR_ERR(pwm));
|
||||
return PTR_ERR(pwm);
|
||||
}
|
||||
}
|
||||
|
||||
ret = pwm_config(pwm, duty, period);
|
||||
pwm_enable(pwm);
|
||||
} else {
|
||||
pwm_disable(pwm);
|
||||
pwm_put(pwm);
|
||||
pwm = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t stk6d2x_osc_cal_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
stk6d2x_wrapper *stk_wrapper = dev_get_drvdata(dev);
|
||||
stk6d2x_data *alps_data = &stk_wrapper->alps_data;
|
||||
u16 ret;
|
||||
|
||||
stk6d2x_osc_cal(alps_data);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void stk6d2x_osc_cal(struct stk6d2x_data *alps_data)
|
||||
{
|
||||
u16 ret;
|
||||
|
||||
stk6d2x_setup_pwm(alps_data, true);
|
||||
|
||||
ret = ams_pwm_gpio_period(alps_data);
|
||||
if (ret != 0)
|
||||
cal_period = ret;
|
||||
ALS_dbg("period : %d", ret);
|
||||
|
||||
stk6d2x_setup_pwm(alps_data, false);
|
||||
}
|
||||
|
||||
u16 tsl2585_get_pwm_calibration(void)
|
||||
{
|
||||
if (cal_period == 0)
|
||||
return 0xffff;
|
||||
return cal_period;
|
||||
}
|
1614
drivers/optics/stk6d2x_fifo.c
Executable file
1614
drivers/optics/stk6d2x_fifo.c
Executable file
File diff suppressed because it is too large
Load Diff
1581
drivers/optics/stk6d2x_sec.c
Executable file
1581
drivers/optics/stk6d2x_sec.c
Executable file
File diff suppressed because it is too large
Load Diff
35
drivers/optics/stk6d2x_sec.h
Executable file
35
drivers/optics/stk6d2x_sec.h
Executable file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
*
|
||||
* $Id: stk6d2x_sec.h
|
||||
*
|
||||
* Copyright (C) 2012~2018 Bk, sensortek Inc.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __STK6D2X_SEC_H__
|
||||
#define __STK6D2X_SEC_H__
|
||||
|
||||
#include <stk6d2x.h>
|
||||
#include <common_define.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
// #define SUPPORT_SENSOR_CLASS
|
||||
|
||||
typedef struct stk6d2x_wrapper
|
||||
{
|
||||
struct i2c_manager i2c_mgr;
|
||||
stk6d2x_data alps_data;
|
||||
struct device *dev;
|
||||
struct device *sensor_dev;
|
||||
#ifdef SUPPORT_SENSOR_CLASS
|
||||
struct sensors_classdev als_cdev;
|
||||
#endif
|
||||
struct input_dev *als_input_dev;
|
||||
atomic_t recv_reg;
|
||||
} stk6d2x_wrapper;
|
||||
|
||||
#endif // __STK6D2X_SEC_H__
|
38
drivers/optics/stk6d2x_ver.h
Executable file
38
drivers/optics/stk6d2x_ver.h
Executable file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file stk6d2x_ver.h
|
||||
*
|
||||
* Copyright (c) 2020, Sensortek.
|
||||
* All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
Change Log:
|
||||
|
||||
EDIT HISTORY FOR FILE
|
||||
|
||||
Nov 17 2022 STK - 1.0.0
|
||||
- First Draft Version
|
||||
- Basic Function
|
||||
- Flicker 1Hz (1024 data bytes)
|
||||
Dec 9 2022 STK - 2.0.0
|
||||
- Add IT Switch and Checking External Clock Exist or Not
|
||||
- Check RID
|
||||
- Add HW/SW Summation
|
||||
- Add Check XFLAG
|
||||
- Integrate Gain Ratio Function
|
||||
- Change FIFO Mode to STA01_STA2_ALS0_ALS1_ALS2
|
||||
============================================================================*/
|
||||
|
||||
#ifndef _STK6D2X_VER_H
|
||||
#define _STK6D2X_VER_H
|
||||
|
||||
// 32-bit version number represented as major[31:16].minor[15:8].rev[7:0]
|
||||
#define STK6D2X_MAJOR 2
|
||||
#define STK6D2X_MINOR 0
|
||||
#define STK6D2X_REV 0
|
||||
#define VERSION_STK6D2X ((STK6D2X_MAJOR<<16) | (STK6D2X_MINOR<<8) | STK6D2X_REV)
|
||||
#define DRIVER_VERSION "2.0.0"
|
||||
|
||||
#endif //_STK6D2X_VER_H
|
Reference in New Issue
Block a user