From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/iio/light/tsl2772.c | 186 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 161 insertions(+), 25 deletions(-)
diff --git a/kernel/drivers/iio/light/tsl2772.c b/kernel/drivers/iio/light/tsl2772.c
index f2e308c..ff33ad3 100644
--- a/kernel/drivers/iio/light/tsl2772.c
+++ b/kernel/drivers/iio/light/tsl2772.c
@@ -20,6 +20,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/platform_data/tsl2772.h>
+#include <linux/regulator/consumer.h>
/* Cal defs */
#define PROX_STAT_CAL 0
@@ -107,6 +108,11 @@
#define TSL2772_ALS_GAIN_TRIM_MIN 250
#define TSL2772_ALS_GAIN_TRIM_MAX 4000
+#define TSL2772_MAX_PROX_LEDS 2
+
+#define TSL2772_BOOT_MIN_SLEEP_TIME 10000
+#define TSL2772_BOOT_MAX_SLEEP_TIME 28000
+
/* Device family members */
enum {
tsl2571,
@@ -118,13 +124,20 @@
tsl2672,
tmd2672,
tsl2772,
- tmd2772
+ tmd2772,
+ apds9930,
};
enum {
TSL2772_CHIP_UNKNOWN = 0,
TSL2772_CHIP_WORKING = 1,
TSL2772_CHIP_SUSPENDED = 2
+};
+
+enum {
+ TSL2772_SUPPLY_VDD = 0,
+ TSL2772_SUPPLY_VDDIO = 1,
+ TSL2772_NUM_SUPPLIES = 2
};
/* Per-device data */
@@ -141,11 +154,20 @@
const struct iio_info *info;
};
+static const int tsl2772_led_currents[][2] = {
+ { 100000, TSL2772_100_mA },
+ { 50000, TSL2772_50_mA },
+ { 25000, TSL2772_25_mA },
+ { 13000, TSL2772_13_mA },
+ { 0, 0 }
+};
+
struct tsl2772_chip {
kernel_ulong_t id;
struct mutex prox_mutex;
struct mutex als_mutex;
struct i2c_client *client;
+ struct regulator_bulk_data supplies[TSL2772_NUM_SUPPLIES];
u16 prox_data;
struct tsl2772_als_info als_cur_info;
struct tsl2772_settings settings;
@@ -197,6 +219,12 @@
{ 0, 0 },
};
+static const struct tsl2772_lux apds9930_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = {
+ { 52000, 96824 },
+ { 38792, 67132 },
+ { 0, 0 },
+};
+
static const struct tsl2772_lux *tsl2772_default_lux_table_group[] = {
[tsl2571] = tsl2x71_lux_table,
[tsl2671] = tsl2x71_lux_table,
@@ -208,6 +236,7 @@
[tmd2672] = tmd2x72_lux_table,
[tsl2772] = tsl2x72_lux_table,
[tmd2772] = tmd2x72_lux_table,
+ [apds9930] = apds9930_lux_table,
};
static const struct tsl2772_settings tsl2772_default_settings = {
@@ -258,6 +287,7 @@
[tmd2672] = { 0, 2730, 0, 2730, 0, 699000 },
[tsl2772] = { 0, 2730, 0, 2730, 0, 699000 },
[tmd2772] = { 0, 2730, 0, 2730, 0, 699000 },
+ [apds9930] = { 0, 2730, 0, 2730, 0, 699000 },
};
static int tsl2772_int_calibscale_avail[] = { 1, 8, 16, 120 };
@@ -283,7 +313,8 @@
[tsl2672] = PRX2,
[tmd2672] = PRX2,
[tsl2772] = ALSPRX2,
- [tmd2772] = ALSPRX2
+ [tmd2772] = ALSPRX2,
+ [apds9930] = ALSPRX2,
};
static int tsl2772_read_status(struct tsl2772_chip *chip)
@@ -497,6 +528,7 @@
case tmd2672:
case tsl2772:
case tmd2772:
+ case apds9930:
if (!(ret & TSL2772_STA_PRX_VALID)) {
ret = -EINVAL;
goto prox_poll_err;
@@ -513,6 +545,76 @@
mutex_unlock(&chip->prox_mutex);
return ret;
+}
+
+static int tsl2772_read_prox_led_current(struct tsl2772_chip *chip)
+{
+ struct device_node *of_node = chip->client->dev.of_node;
+ int ret, tmp, i;
+
+ ret = of_property_read_u32(of_node, "led-max-microamp", &tmp);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; tsl2772_led_currents[i][0] != 0; i++) {
+ if (tmp == tsl2772_led_currents[i][0]) {
+ chip->settings.prox_power = tsl2772_led_currents[i][1];
+ return 0;
+ }
+ }
+
+ dev_err(&chip->client->dev, "Invalid value %d for led-max-microamp\n",
+ tmp);
+
+ return -EINVAL;
+
+}
+
+static int tsl2772_read_prox_diodes(struct tsl2772_chip *chip)
+{
+ struct device_node *of_node = chip->client->dev.of_node;
+ int i, ret, num_leds, prox_diode_mask;
+ u32 leds[TSL2772_MAX_PROX_LEDS];
+
+ ret = of_property_count_u32_elems(of_node, "amstaos,proximity-diodes");
+ if (ret < 0)
+ return ret;
+
+ num_leds = ret;
+ if (num_leds > TSL2772_MAX_PROX_LEDS)
+ num_leds = TSL2772_MAX_PROX_LEDS;
+
+ ret = of_property_read_u32_array(of_node, "amstaos,proximity-diodes",
+ leds, num_leds);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "Invalid value for amstaos,proximity-diodes: %d.\n",
+ ret);
+ return ret;
+ }
+
+ prox_diode_mask = 0;
+ for (i = 0; i < num_leds; i++) {
+ if (leds[i] == 0)
+ prox_diode_mask |= TSL2772_DIODE0;
+ else if (leds[i] == 1)
+ prox_diode_mask |= TSL2772_DIODE1;
+ else {
+ dev_err(&chip->client->dev,
+ "Invalid value %d in amstaos,proximity-diodes.\n",
+ leds[i]);
+ return -EINVAL;
+ }
+ }
+ chip->settings.prox_diode = prox_diode_mask;
+
+ return 0;
+}
+
+static void tsl2772_parse_dt(struct tsl2772_chip *chip)
+{
+ tsl2772_read_prox_led_current(chip);
+ tsl2772_read_prox_diodes(chip);
}
/**
@@ -541,6 +643,8 @@
memcpy(chip->tsl2772_device_lux,
tsl2772_default_lux_table_group[chip->id],
TSL2772_DEFAULT_TABLE_BYTES);
+
+ tsl2772_parse_dt(chip);
}
/**
@@ -593,6 +697,13 @@
chip->settings.als_gain_trim = ret;
return ret;
+}
+
+static void tsl2772_disable_regulators_action(void *_data)
+{
+ struct tsl2772_chip *chip = _data;
+
+ regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies);
}
static int tsl2772_chip_on(struct iio_dev *indio_dev)
@@ -822,7 +933,7 @@
{
struct tsl2772_chip *chip = iio_priv(dev_to_iio_dev(dev));
- return snprintf(buf, PAGE_SIZE, "%d\n", chip->settings.als_cal_target);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", chip->settings.als_cal_target);
}
static ssize_t in_illuminance0_target_input_store(struct device *dev,
@@ -876,7 +987,7 @@
int offset = 0;
while (i < TSL2772_MAX_LUX_TABLE_SIZE) {
- offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,",
+ offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%u,%u,",
chip->tsl2772_device_lux[i].ch0,
chip->tsl2772_device_lux[i].ch1);
if (chip->tsl2772_device_lux[i].ch0 == 0) {
@@ -890,7 +1001,7 @@
i++;
}
- offset += snprintf(buf + offset, PAGE_SIZE, "\n");
+ offset += scnprintf(buf + offset, PAGE_SIZE - offset, "\n");
return offset;
}
@@ -1267,6 +1378,7 @@
case tmd2672:
case tsl2772:
case tmd2772:
+ case apds9930:
return (id & 0xf0) == SWORDFISH_ID;
}
@@ -1659,6 +1771,33 @@
chip->client = clientp;
i2c_set_clientdata(clientp, indio_dev);
+ chip->supplies[TSL2772_SUPPLY_VDD].supply = "vdd";
+ chip->supplies[TSL2772_SUPPLY_VDDIO].supply = "vddio";
+
+ ret = devm_regulator_bulk_get(&clientp->dev,
+ ARRAY_SIZE(chip->supplies),
+ chip->supplies);
+ if (ret < 0)
+ return dev_err_probe(&clientp->dev, ret, "Failed to get regulators\n");
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies);
+ if (ret < 0) {
+ dev_err(&clientp->dev, "Failed to enable regulators: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&clientp->dev,
+ tsl2772_disable_regulators_action,
+ chip);
+ if (ret < 0) {
+ dev_err(&clientp->dev, "Failed to setup regulator cleanup action %d\n",
+ ret);
+ return ret;
+ }
+
+ usleep_range(TSL2772_BOOT_MIN_SLEEP_TIME, TSL2772_BOOT_MAX_SLEEP_TIME);
+
ret = i2c_smbus_read_byte_data(chip->client,
TSL2772_CMD_REG | TSL2772_CHIPID);
if (ret < 0)
@@ -1689,7 +1828,6 @@
&tsl2772_chip_info_tbl[device_channel_config[id->driver_data]];
indio_dev->info = chip->chip_info->info;
- indio_dev->dev.parent = &clientp->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = chip->client->name;
indio_dev->num_channels = chip->chip_info->chan_table_elements;
@@ -1724,37 +1862,34 @@
if (ret < 0)
return ret;
- ret = iio_device_register(indio_dev);
- if (ret) {
- dev_err(&clientp->dev,
- "%s: iio registration failed\n", __func__);
- return ret;
- }
-
- return 0;
+ return devm_iio_device_register(&clientp->dev, indio_dev);
}
static int tsl2772_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct tsl2772_chip *chip = iio_priv(indio_dev);
+ int ret;
- return tsl2772_chip_off(indio_dev);
+ ret = tsl2772_chip_off(indio_dev);
+ regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies);
+
+ return ret;
}
static int tsl2772_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct tsl2772_chip *chip = iio_priv(indio_dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(TSL2772_BOOT_MIN_SLEEP_TIME, TSL2772_BOOT_MAX_SLEEP_TIME);
return tsl2772_chip_on(indio_dev);
-}
-
-static int tsl2772_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
-
- return 0;
}
static const struct i2c_device_id tsl2772_idtable[] = {
@@ -1768,6 +1903,7 @@
{ "tmd2672", tmd2672 },
{ "tsl2772", tsl2772 },
{ "tmd2772", tmd2772 },
+ { "apds9930", apds9930},
{}
};
@@ -1784,6 +1920,7 @@
{ .compatible = "amstaos,tmd2672" },
{ .compatible = "amstaos,tsl2772" },
{ .compatible = "amstaos,tmd2772" },
+ { .compatible = "avago,apds9930" },
{}
};
MODULE_DEVICE_TABLE(of, tsl2772_of_match);
@@ -1801,7 +1938,6 @@
},
.id_table = tsl2772_idtable,
.probe = tsl2772_probe,
- .remove = tsl2772_remove,
};
module_i2c_driver(tsl2772_driver);
--
Gitblit v1.6.2