Commit 7c7d9170 authored by Marek Vasut's avatar Marek Vasut Committed by Jonathan Cameron

iio: light: ltrf216a: Add LTR-308 support

Add LiteOn LTR-308 support into LTR-F216A kernel driver.

The two devices seem to have almost identical register map, except that
the LTR-308 does not have three CLEAR_DATA registers, which are unused
by this driver. Furthermore, LTR-308 and LTR-F216A use different lux
calculation constants, 0.6 and 0.45 respectively. Both differences are
handled using chip info data.

https://optoelectronics.liteon.com/upload/download/DS86-2016-0027/LTR-308ALS_Final_%20DS_V1%201.pdf
https://optoelectronics.liteon.com/upload/download/DS86-2019-0016/LTR-F216A_Final_DS_V1.4.PDFSigned-off-by: default avatarMarek Vasut <marex@denx.de>
Link: https://patch.msgid.link/20240708114227.18283-2-marex@denx.deSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 14c09562
...@@ -68,6 +68,13 @@ static const int ltrf216a_int_time_reg[][2] = { ...@@ -68,6 +68,13 @@ static const int ltrf216a_int_time_reg[][2] = {
{ 25, 0x40 }, { 25, 0x40 },
}; };
struct ltr_chip_info {
/* Chip contains CLEAR_DATA_0/1/2 registers at offset 0xa..0xc */
bool has_clear_data;
/* Lux calculation multiplier for ALS data */
int lux_multiplier;
};
/* /*
* Window Factor is needed when the device is under Window glass * Window Factor is needed when the device is under Window glass
* with coated tinted ink. This is to compensate for the light loss * with coated tinted ink. This is to compensate for the light loss
...@@ -79,6 +86,7 @@ static const int ltrf216a_int_time_reg[][2] = { ...@@ -79,6 +86,7 @@ static const int ltrf216a_int_time_reg[][2] = {
struct ltrf216a_data { struct ltrf216a_data {
struct regmap *regmap; struct regmap *regmap;
struct i2c_client *client; struct i2c_client *client;
const struct ltr_chip_info *info;
u32 int_time; u32 int_time;
u16 int_time_fac; u16 int_time_fac;
u8 als_gain_fac; u8 als_gain_fac;
...@@ -246,7 +254,7 @@ static int ltrf216a_get_lux(struct ltrf216a_data *data) ...@@ -246,7 +254,7 @@ static int ltrf216a_get_lux(struct ltrf216a_data *data)
ltrf216a_set_power_state(data, false); ltrf216a_set_power_state(data, false);
lux = greendata * 45 * LTRF216A_WIN_FAC; lux = greendata * data->info->lux_multiplier * LTRF216A_WIN_FAC;
return lux; return lux;
} }
...@@ -334,15 +342,15 @@ static const struct iio_info ltrf216a_info = { ...@@ -334,15 +342,15 @@ static const struct iio_info ltrf216a_info = {
static bool ltrf216a_readable_reg(struct device *dev, unsigned int reg) static bool ltrf216a_readable_reg(struct device *dev, unsigned int reg)
{ {
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct ltrf216a_data *data = iio_priv(indio_dev);
switch (reg) { switch (reg) {
case LTRF216A_MAIN_CTRL: case LTRF216A_MAIN_CTRL:
case LTRF216A_ALS_MEAS_RES: case LTRF216A_ALS_MEAS_RES:
case LTRF216A_ALS_GAIN: case LTRF216A_ALS_GAIN:
case LTRF216A_PART_ID: case LTRF216A_PART_ID:
case LTRF216A_MAIN_STATUS: case LTRF216A_MAIN_STATUS:
case LTRF216A_ALS_CLEAR_DATA_0:
case LTRF216A_ALS_CLEAR_DATA_1:
case LTRF216A_ALS_CLEAR_DATA_2:
case LTRF216A_ALS_DATA_0: case LTRF216A_ALS_DATA_0:
case LTRF216A_ALS_DATA_1: case LTRF216A_ALS_DATA_1:
case LTRF216A_ALS_DATA_2: case LTRF216A_ALS_DATA_2:
...@@ -355,6 +363,10 @@ static bool ltrf216a_readable_reg(struct device *dev, unsigned int reg) ...@@ -355,6 +363,10 @@ static bool ltrf216a_readable_reg(struct device *dev, unsigned int reg)
case LTRF216A_ALS_THRES_LOW_1: case LTRF216A_ALS_THRES_LOW_1:
case LTRF216A_ALS_THRES_LOW_2: case LTRF216A_ALS_THRES_LOW_2:
return true; return true;
case LTRF216A_ALS_CLEAR_DATA_0:
case LTRF216A_ALS_CLEAR_DATA_1:
case LTRF216A_ALS_CLEAR_DATA_2:
return data->info->has_clear_data;
default: default:
return false; return false;
} }
...@@ -382,15 +394,23 @@ static bool ltrf216a_writable_reg(struct device *dev, unsigned int reg) ...@@ -382,15 +394,23 @@ static bool ltrf216a_writable_reg(struct device *dev, unsigned int reg)
static bool ltrf216a_volatile_reg(struct device *dev, unsigned int reg) static bool ltrf216a_volatile_reg(struct device *dev, unsigned int reg)
{ {
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct ltrf216a_data *data = iio_priv(indio_dev);
switch (reg) { switch (reg) {
case LTRF216A_MAIN_STATUS: case LTRF216A_MAIN_STATUS:
case LTRF216A_ALS_CLEAR_DATA_0:
case LTRF216A_ALS_CLEAR_DATA_1:
case LTRF216A_ALS_CLEAR_DATA_2:
case LTRF216A_ALS_DATA_0: case LTRF216A_ALS_DATA_0:
case LTRF216A_ALS_DATA_1: case LTRF216A_ALS_DATA_1:
case LTRF216A_ALS_DATA_2: case LTRF216A_ALS_DATA_2:
return true; return true;
/*
* If these registers are not present on a chip (like LTR-308),
* the missing registers are not considered volatile.
*/
case LTRF216A_ALS_CLEAR_DATA_0:
case LTRF216A_ALS_CLEAR_DATA_1:
case LTRF216A_ALS_CLEAR_DATA_2:
return data->info->has_clear_data;
default: default:
return false; return false;
} }
...@@ -433,6 +453,7 @@ static int ltrf216a_probe(struct i2c_client *client) ...@@ -433,6 +453,7 @@ static int ltrf216a_probe(struct i2c_client *client)
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
data->client = client; data->client = client;
data->info = i2c_get_match_data(client);
mutex_init(&data->lock); mutex_init(&data->lock);
...@@ -520,15 +541,27 @@ static int ltrf216a_runtime_resume(struct device *dev) ...@@ -520,15 +541,27 @@ static int ltrf216a_runtime_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(ltrf216a_pm_ops, ltrf216a_runtime_suspend, static DEFINE_RUNTIME_DEV_PM_OPS(ltrf216a_pm_ops, ltrf216a_runtime_suspend,
ltrf216a_runtime_resume, NULL); ltrf216a_runtime_resume, NULL);
static const struct ltr_chip_info ltr308_chip_info = {
.has_clear_data = false,
.lux_multiplier = 60,
};
static const struct ltr_chip_info ltrf216a_chip_info = {
.has_clear_data = true,
.lux_multiplier = 45,
};
static const struct i2c_device_id ltrf216a_id[] = { static const struct i2c_device_id ltrf216a_id[] = {
{ "ltrf216a" }, { "ltr308", .driver_data = (kernel_ulong_t)&ltr308_chip_info },
{ "ltrf216a", .driver_data = (kernel_ulong_t)&ltrf216a_chip_info },
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, ltrf216a_id); MODULE_DEVICE_TABLE(i2c, ltrf216a_id);
static const struct of_device_id ltrf216a_of_match[] = { static const struct of_device_id ltrf216a_of_match[] = {
{ .compatible = "liteon,ltrf216a" }, { .compatible = "liteon,ltr308", .data = &ltr308_chip_info },
{ .compatible = "ltr,ltrf216a" }, { .compatible = "liteon,ltrf216a", .data = &ltrf216a_chip_info },
{ .compatible = "ltr,ltrf216a", .data = &ltrf216a_chip_info },
{} {}
}; };
MODULE_DEVICE_TABLE(of, ltrf216a_of_match); MODULE_DEVICE_TABLE(of, ltrf216a_of_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment