summaryrefslogtreecommitdiff
path: root/drivers/input/misc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-01-18 17:21:35 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-01-18 17:21:35 -0800
commit0f289bdd4102fc870c8b97652c57d41952040d70 (patch)
treeabb62778d9e3dd30c1731db5698a06e13c86ea87 /drivers/input/misc
parent33a9caa49938eff19a3cc5ffab195649d702540b (diff)
parent58f65f9db7e0de366a5a115c2e2c0703858bba69 (diff)
Merge tag 'input-for-v6.8-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - a new driver for Adafruit Seesaw gamepad device - Zforce touchscreen will handle standard device properties for axis swap/inversion - handling of advanced sensitivity settings in Microchip CAP11xx capacitive sensor driver - more drivers have been converted to use newer gpiod API - support for dedicated wakeup IRQs in gpio-keys dirver - support for slider gestures and OTP variants in iqs269a driver - atkbd will report keyboard version as 0xab83 in cases when GET ID command was skipped (to deal with problematic firmware on newer laptops), restoring the previous behavior - other assorted cleanups and changes * tag 'input-for-v6.8-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (44 commits) Input: atkbd - use ab83 as id when skipping the getid command Input: driver for Adafruit Seesaw Gamepad dt-bindings: input: bindings for Adafruit Seesaw Gamepad Input: da9063_onkey - avoid explicitly setting input's parent Input: da9063_onkey - avoid using OF-specific APIs Input: iqs269a - add support for OTP variants dt-bindings: input: iqs269a: Add bindings for OTP variants Input: iqs269a - add support for slider gestures dt-bindings: input: iqs269a: Add bindings for slider gestures Input: gpio-keys - filter gpio_keys -EPROBE_DEFER error messages Input: zforce_ts - accept standard touchscreen properties dt-bindings: touchscreen: neonode,zforce: Use standard properties dt-bindings: touchscreen: convert neonode,zforce to json-schema dt-bindings: input: convert drv266x to json-schema Input: da9063 - use dev_err_probe() Input: da9063 - drop redundant prints in probe() Input: da9063 - simplify obtaining OF match data Input: as5011 - convert to GPIO descriptor Input: omap-keypad - drop optional GPIO support Input: tca6416-keypad - drop unused include ...
Diffstat (limited to 'drivers/input/misc')
-rw-r--r--drivers/input/misc/da9063_onkey.c69
-rw-r--r--drivers/input/misc/ims-pcu.c10
-rw-r--r--drivers/input/misc/iqs269a.c335
-rw-r--r--drivers/input/misc/max77693-haptic.c14
4 files changed, 333 insertions, 95 deletions
diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index 74808bae326a..c338765e0ecd 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -9,11 +9,12 @@
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
+#include <linux/property.h>
#include <linux/workqueue.h>
#include <linux/regmap.h>
-#include <linux/of.h>
#include <linux/mfd/da9063/core.h>
#include <linux/mfd/da9063/registers.h>
#include <linux/mfd/da9062/core.h>
@@ -74,13 +75,6 @@ static const struct da906x_chip_config da9062_regs = {
.name = "da9062-onkey",
};
-static const struct of_device_id da9063_compatible_reg_id_table[] = {
- { .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
- { .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
- { },
-};
-MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
-
static void da9063_poll_on(struct work_struct *work)
{
struct da9063_onkey *onkey = container_of(work,
@@ -187,56 +181,43 @@ static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
static int da9063_onkey_probe(struct platform_device *pdev)
{
struct da9063_onkey *onkey;
- const struct of_device_id *match;
- int irq;
int error;
-
- match = of_match_node(da9063_compatible_reg_id_table,
- pdev->dev.of_node);
- if (!match)
- return -ENXIO;
+ int irq;
onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
GFP_KERNEL);
- if (!onkey) {
- dev_err(&pdev->dev, "Failed to allocate memory.\n");
+ if (!onkey)
return -ENOMEM;
- }
- onkey->config = match->data;
+ onkey->config = device_get_match_data(&pdev->dev);
+ if (!onkey->config)
+ return -ENXIO;
+
onkey->dev = &pdev->dev;
onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
- if (!onkey->regmap) {
- dev_err(&pdev->dev, "Parent regmap unavailable.\n");
- return -ENXIO;
- }
+ if (!onkey->regmap)
+ return dev_err_probe(&pdev->dev, -ENXIO,
+ "Parent regmap unavailable.\n");
- onkey->key_power = !of_property_read_bool(pdev->dev.of_node,
- "dlg,disable-key-power");
+ onkey->key_power = !device_property_read_bool(&pdev->dev,
+ "dlg,disable-key-power");
onkey->input = devm_input_allocate_device(&pdev->dev);
- if (!onkey->input) {
- dev_err(&pdev->dev, "Failed to allocated input device.\n");
+ if (!onkey->input)
return -ENOMEM;
- }
onkey->input->name = onkey->config->name;
snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
onkey->config->name);
onkey->input->phys = onkey->phys;
- onkey->input->dev.parent = &pdev->dev;
input_set_capability(onkey->input, EV_KEY, KEY_POWER);
error = devm_delayed_work_autocancel(&pdev->dev, &onkey->work,
da9063_poll_on);
- if (error) {
- dev_err(&pdev->dev,
- "Failed to add cancel poll action: %d\n",
- error);
+ if (error)
return error;
- }
irq = platform_get_irq_byname(pdev, "ONKEY");
if (irq < 0)
@@ -246,11 +227,9 @@ static int da9063_onkey_probe(struct platform_device *pdev)
NULL, da9063_onkey_irq_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"ONKEY", onkey);
- if (error) {
- dev_err(&pdev->dev,
- "Failed to request IRQ %d: %d\n", irq, error);
- return error;
- }
+ if (error)
+ return dev_err_probe(&pdev->dev, error,
+ "Failed to allocate onkey IRQ\n");
error = dev_pm_set_wake_irq(&pdev->dev, irq);
if (error)
@@ -261,15 +240,19 @@ static int da9063_onkey_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, true);
error = input_register_device(onkey->input);
- if (error) {
- dev_err(&pdev->dev,
- "Failed to register input device: %d\n", error);
+ if (error)
return error;
- }
return 0;
}
+static const struct of_device_id da9063_compatible_reg_id_table[] = {
+ { .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
+ { .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
+ { }
+};
+MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
+
static struct platform_driver da9063_onkey_driver = {
.probe = da9063_onkey_probe,
.driver = {
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index b2f1292e27ef..6e8cc28debd9 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -1050,7 +1050,7 @@ static ssize_t ims_pcu_attribute_show(struct device *dev,
container_of(dattr, struct ims_pcu_attribute, dattr);
char *field = (char *)pcu + attr->field_offset;
- return scnprintf(buf, PAGE_SIZE, "%.*s\n", attr->field_length, field);
+ return sysfs_emit(buf, "%.*s\n", attr->field_length, field);
}
static ssize_t ims_pcu_attribute_store(struct device *dev,
@@ -1206,7 +1206,7 @@ ims_pcu_update_firmware_status_show(struct device *dev,
struct usb_interface *intf = to_usb_interface(dev);
struct ims_pcu *pcu = usb_get_intfdata(intf);
- return scnprintf(buf, PAGE_SIZE, "%d\n", pcu->update_firmware_status);
+ return sysfs_emit(buf, "%d\n", pcu->update_firmware_status);
}
static DEVICE_ATTR(update_firmware_status, S_IRUGO,
@@ -1309,7 +1309,7 @@ static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev,
if (error)
return error;
- return scnprintf(buf, PAGE_SIZE, "%x\n", data);
+ return sysfs_emit(buf, "%x\n", data);
}
static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev,
@@ -1344,7 +1344,7 @@ static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev,
int error;
mutex_lock(&pcu->cmd_mutex);
- error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr);
+ error = sysfs_emit(buf, "%x\n", pcu->ofn_reg_addr);
mutex_unlock(&pcu->cmd_mutex);
return error;
@@ -1397,7 +1397,7 @@ static ssize_t ims_pcu_ofn_bit_show(struct device *dev,
if (error)
return error;
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr)));
+ return sysfs_emit(buf, "%d\n", !!(data & (1 << attr->nr)));
}
static ssize_t ims_pcu_ofn_bit_store(struct device *dev,
diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c
index 3c636c75e8a1..cd14ff9f57cf 100644
--- a/drivers/input/misc/iqs269a.c
+++ b/drivers/input/misc/iqs269a.c
@@ -9,6 +9,7 @@
* axial sliders presented by the device.
*/
+#include <linux/bits.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -26,6 +27,8 @@
#define IQS269_VER_INFO 0x00
#define IQS269_VER_INFO_PROD_NUM 0x4F
+#define IQS269_VER_INFO_FW_NUM_2 0x03
+#define IQS269_VER_INFO_FW_NUM_3 0x10
#define IQS269_SYS_FLAGS 0x02
#define IQS269_SYS_FLAGS_SHOW_RESET BIT(15)
@@ -53,6 +56,7 @@
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MASK GENMASK(10, 8)
#define IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT 8
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MAX 7
+#define IQS269_SYS_SETTINGS_SLIDER_SWIPE BIT(7)
#define IQS269_SYS_SETTINGS_RESEED_OFFSET BIT(6)
#define IQS269_SYS_SETTINGS_EVENT_MODE BIT(5)
#define IQS269_SYS_SETTINGS_EVENT_MODE_LP BIT(4)
@@ -69,6 +73,7 @@
#define IQS269_FILT_STR_MAX 3
#define IQS269_EVENT_MASK_SYS BIT(6)
+#define IQS269_EVENT_MASK_GESTURE BIT(3)
#define IQS269_EVENT_MASK_DEEP BIT(2)
#define IQS269_EVENT_MASK_TOUCH BIT(1)
#define IQS269_EVENT_MASK_PROX BIT(0)
@@ -97,6 +102,15 @@
#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4)
#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0)
+#define IQS269_TOUCH_HOLD_SLIDER_SEL 0x89
+#define IQS269_TOUCH_HOLD_DEFAULT 0x14
+#define IQS269_TOUCH_HOLD_MS_MIN 256
+#define IQS269_TOUCH_HOLD_MS_MAX 65280
+
+#define IQS269_TIMEOUT_TAP_MS_MAX 4080
+#define IQS269_TIMEOUT_SWIPE_MS_MAX 4080
+#define IQS269_THRESH_SWIPE_MAX 255
+
#define IQS269_CHx_ENG_A_MEAS_CAP_SIZE BIT(15)
#define IQS269_CHx_ENG_A_RX_GND_INACTIVE BIT(13)
#define IQS269_CHx_ENG_A_LOCAL_CAP_SIZE BIT(12)
@@ -142,6 +156,10 @@
#define IQS269_MAX_REG 0xFF
+#define IQS269_OTP_OPTION_DEFAULT 0x00
+#define IQS269_OTP_OPTION_TWS 0xD0
+#define IQS269_OTP_OPTION_HOLD BIT(7)
+
#define IQS269_NUM_CH 8
#define IQS269_NUM_SL 2
@@ -175,6 +193,20 @@ enum iqs269_event_id {
IQS269_EVENT_DEEP_UP,
};
+enum iqs269_slider_id {
+ IQS269_SLIDER_NONE,
+ IQS269_SLIDER_KEY,
+ IQS269_SLIDER_RAW,
+};
+
+enum iqs269_gesture_id {
+ IQS269_GESTURE_TAP,
+ IQS269_GESTURE_HOLD,
+ IQS269_GESTURE_FLICK_POS,
+ IQS269_GESTURE_FLICK_NEG,
+ IQS269_NUM_GESTURES,
+};
+
struct iqs269_switch_desc {
unsigned int code;
bool enabled;
@@ -234,7 +266,7 @@ struct iqs269_ver_info {
u8 prod_num;
u8 sw_num;
u8 hw_num;
- u8 padding;
+ u8 fw_num;
} __packed;
struct iqs269_ch_reg {
@@ -285,16 +317,42 @@ struct iqs269_private {
struct regmap *regmap;
struct mutex lock;
struct iqs269_switch_desc switches[ARRAY_SIZE(iqs269_events)];
+ struct iqs269_ver_info ver_info;
struct iqs269_sys_reg sys_reg;
struct completion ati_done;
struct input_dev *keypad;
struct input_dev *slider[IQS269_NUM_SL];
unsigned int keycode[ARRAY_SIZE(iqs269_events) * IQS269_NUM_CH];
+ unsigned int sl_code[IQS269_NUM_SL][IQS269_NUM_GESTURES];
+ unsigned int otp_option;
unsigned int ch_num;
bool hall_enable;
bool ati_current;
};
+static enum iqs269_slider_id iqs269_slider_type(struct iqs269_private *iqs269,
+ int slider_num)
+{
+ int i;
+
+ /*
+ * Slider 1 is unavailable if the touch-and-hold option is enabled via
+ * OTP. In that case, the channel selection register is repurposed for
+ * the touch-and-hold timer ceiling.
+ */
+ if (slider_num && (iqs269->otp_option & IQS269_OTP_OPTION_HOLD))
+ return IQS269_SLIDER_NONE;
+
+ if (!iqs269->sys_reg.slider_select[slider_num])
+ return IQS269_SLIDER_NONE;
+
+ for (i = 0; i < IQS269_NUM_GESTURES; i++)
+ if (iqs269->sl_code[slider_num][i] != KEY_RESERVED)
+ return IQS269_SLIDER_KEY;
+
+ return IQS269_SLIDER_RAW;
+}
+
static int iqs269_ati_mode_set(struct iqs269_private *iqs269,
unsigned int ch_num, unsigned int mode)
{
@@ -525,7 +583,8 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
if (fwnode_property_present(ch_node, "azoteq,slider0-select"))
iqs269->sys_reg.slider_select[0] |= BIT(reg);
- if (fwnode_property_present(ch_node, "azoteq,slider1-select"))
+ if (fwnode_property_present(ch_node, "azoteq,slider1-select") &&
+ !(iqs269->otp_option & IQS269_OTP_OPTION_HOLD))
iqs269->sys_reg.slider_select[1] |= BIT(reg);
ch_reg = &iqs269->sys_reg.ch_reg[reg];
@@ -950,7 +1009,43 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
sys_reg->blocking = 0;
sys_reg->slider_select[0] = 0;
- sys_reg->slider_select[1] = 0;
+
+ /*
+ * If configured via OTP to do so, the device asserts a pulse on the
+ * GPIO4 pin for approximately 60 ms once a selected channel is held
+ * in a state of touch for a configurable length of time.
+ *
+ * In that case, the register used for slider 1 channel selection is
+ * repurposed for the touch-and-hold timer ceiling.
+ */
+ if (iqs269->otp_option & IQS269_OTP_OPTION_HOLD) {
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,touch-hold-ms", &val)) {
+ if (val < IQS269_TOUCH_HOLD_MS_MIN ||
+ val > IQS269_TOUCH_HOLD_MS_MAX) {
+ dev_err(&client->dev,
+ "Invalid touch-and-hold ceiling: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->slider_select[1] = val / 256;
+ } else if (iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3) {
+ /*
+ * The default touch-and-hold timer ceiling initially
+ * read from early revisions of silicon is invalid if
+ * the device experienced a soft reset between power-
+ * on and the read operation.
+ *
+ * To protect against this case, explicitly cache the
+ * default value so that it is restored each time the
+ * device is re-initialized.
+ */
+ sys_reg->slider_select[1] = IQS269_TOUCH_HOLD_DEFAULT;
+ }
+ } else {
+ sys_reg->slider_select[1] = 0;
+ }
sys_reg->event_mask = ~((u8)IQS269_EVENT_MASK_SYS);
@@ -1004,6 +1099,76 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
general |= (val << IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT);
}
+ if (device_property_present(&client->dev, "linux,keycodes")) {
+ int scale = 1;
+ int count = device_property_count_u32(&client->dev,
+ "linux,keycodes");
+ if (count > IQS269_NUM_GESTURES * IQS269_NUM_SL) {
+ dev_err(&client->dev, "Too many keycodes present\n");
+ return -EINVAL;
+ } else if (count < 0) {
+ dev_err(&client->dev, "Failed to count keycodes: %d\n",
+ count);
+ return count;
+ }
+
+ error = device_property_read_u32_array(&client->dev,
+ "linux,keycodes",
+ *iqs269->sl_code, count);
+ if (error) {
+ dev_err(&client->dev, "Failed to read keycodes: %d\n",
+ error);
+ return error;
+ }
+
+ if (device_property_present(&client->dev,
+ "azoteq,gesture-swipe"))
+ general |= IQS269_SYS_SETTINGS_SLIDER_SWIPE;
+
+ /*
+ * Early revisions of silicon use a more granular step size for
+ * tap and swipe gesture timeouts; scale them appropriately.
+ */
+ if (iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3)
+ scale = 4;
+
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,timeout-tap-ms", &val)) {
+ if (val > IQS269_TIMEOUT_TAP_MS_MAX / scale) {
+ dev_err(&client->dev, "Invalid timeout: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->timeout_tap = val / (16 / scale);
+ }
+
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,timeout-swipe-ms",
+ &val)) {
+ if (val > IQS269_TIMEOUT_SWIPE_MS_MAX / scale) {
+ dev_err(&client->dev, "Invalid timeout: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->timeout_swipe = val / (16 / scale);
+ }
+
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,thresh-swipe", &val)) {
+ if (val > IQS269_THRESH_SWIPE_MAX) {
+ dev_err(&client->dev, "Invalid threshold: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->thresh_swipe = val;
+ }
+
+ sys_reg->event_mask &= ~IQS269_EVENT_MASK_GESTURE;
+ }
+
general &= ~IQS269_SYS_SETTINGS_RESEED_OFFSET;
if (device_property_present(&client->dev, "azoteq,reseed-offset"))
general |= IQS269_SYS_SETTINGS_RESEED_OFFSET;
@@ -1012,10 +1177,11 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
/*
* As per the datasheet, enable streaming during normal-power mode if
- * either slider is in use. In that case, the device returns to event
- * mode during low-power mode.
+ * raw coordinates will be read from either slider. In that case, the
+ * device returns to event mode during low-power mode.
*/
- if (sys_reg->slider_select[0] || sys_reg->slider_select[1])
+ if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
+ iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW)
general |= IQS269_SYS_SETTINGS_EVENT_MODE_LP;
general |= IQS269_SYS_SETTINGS_REDO_ATI;
@@ -1026,12 +1192,30 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
return 0;
}
+static const struct reg_sequence iqs269_tws_init[] = {
+ { IQS269_TOUCH_HOLD_SLIDER_SEL, IQS269_TOUCH_HOLD_DEFAULT },
+ { 0xF0, 0x580F },
+ { 0xF0, 0x59EF },
+};
+
static int iqs269_dev_init(struct iqs269_private *iqs269)
{
int error;
mutex_lock(&iqs269->lock);
+ /*
+ * Early revisions of silicon require the following workaround in order
+ * to restore any OTP-enabled functionality after a soft reset.
+ */
+ if (iqs269->otp_option == IQS269_OTP_OPTION_TWS &&
+ iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3) {
+ error = regmap_multi_reg_write(iqs269->regmap, iqs269_tws_init,
+ ARRAY_SIZE(iqs269_tws_init));
+ if (error)
+ goto err_mutex;
+ }
+
error = regmap_update_bits(iqs269->regmap, IQS269_HALL_UI,
IQS269_HALL_UI_ENABLE,
iqs269->hall_enable ? ~0 : 0);
@@ -1106,19 +1290,37 @@ static int iqs269_input_init(struct iqs269_private *iqs269)
}
for (i = 0; i < IQS269_NUM_SL; i++) {
- if (!iqs269->sys_reg.slider_select[i])
+ if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_NONE)
continue;
iqs269->slider[i] = devm_input_allocate_device(&client->dev);
if (!iqs269->slider[i])
return -ENOMEM;
+ iqs269->slider[i]->keycodemax = ARRAY_SIZE(iqs269->sl_code[i]);
+ iqs269->slider[i]->keycode = iqs269->sl_code[i];
+ iqs269->slider[i]->keycodesize = sizeof(**iqs269->sl_code);
+
iqs269->slider[i]->name = i ? "iqs269a_slider_1"
: "iqs269a_slider_0";
iqs269->slider[i]->id.bustype = BUS_I2C;
- input_set_capability(iqs269->slider[i], EV_KEY, BTN_TOUCH);
- input_set_abs_params(iqs269->slider[i], ABS_X, 0, 255, 0, 0);
+ for (j = 0; j < IQS269_NUM_GESTURES; j++)
+ if (iqs269->sl_code[i][j] != KEY_RESERVED)
+ input_set_capability(iqs269->slider[i], EV_KEY,
+ iqs269->sl_code[i][j]);
+
+ /*
+ * Present the slider as a narrow trackpad if one or more chan-
+ * nels have been selected to participate, but no gestures have
+ * been mapped to a keycode.
+ */
+ if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_RAW) {
+ input_set_capability(iqs269->slider[i],
+ EV_KEY, BTN_TOUCH);
+ input_set_abs_params(iqs269->slider[i],
+ ABS_X, 0, 255, 0, 0);
+ }
error = input_register_device(iqs269->slider[i]);
if (error) {
@@ -1167,28 +1369,62 @@ static int iqs269_report(struct iqs269_private *iqs269)
if (be16_to_cpu(flags.system) & IQS269_SYS_FLAGS_IN_ATI)
return 0;
- error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X, slider_x,
- sizeof(slider_x));
- if (error) {
- dev_err(&client->dev, "Failed to read slider position: %d\n",
- error);
- return error;
+ if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
+ iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW) {
+ error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X,
+ slider_x, sizeof(slider_x));
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to read slider position: %d\n", error);
+ return error;
+ }
}
for (i = 0; i < IQS269_NUM_SL; i++) {
- if (!iqs269->sys_reg.slider_select[i])
+ flags.gesture >>= (i * IQS269_NUM_GESTURES);
+
+ switch (iqs269_slider_type(iqs269, i)) {
+ case IQS269_SLIDER_NONE:
continue;
- /*
- * Report BTN_TOUCH if any channel that participates in the
- * slider is in a state of touch.
- */
- if (flags.states[IQS269_ST_OFFS_TOUCH] &
- iqs269->sys_reg.slider_select[i]) {
- input_report_key(iqs269->slider[i], BTN_TOUCH, 1);
- input_report_abs(iqs269->slider[i], ABS_X, slider_x[i]);
- } else {
- input_report_key(iqs269->slider[i], BTN_TOUCH, 0);
+ case IQS269_SLIDER_KEY:
+ for (j = 0; j < IQS269_NUM_GESTURES; j++)
+ input_report_key(iqs269->slider[i],
+ iqs269->sl_code[i][j],
+ flags.gesture & BIT(j));
+
+ if (!(flags.gesture & (BIT(IQS269_GESTURE_FLICK_NEG) |
+ BIT(IQS269_GESTURE_FLICK_POS) |
+ BIT(IQS269_GESTURE_TAP))))
+ break;
+
+ input_sync(iqs269->slider[i]);
+
+ /*
+ * Momentary gestures are followed by a complementary
+ * release cycle so as to emulate a full keystroke.
+ */
+ for (j = 0; j < IQS269_NUM_GESTURES; j++)
+ if (j != IQS269_GESTURE_HOLD)
+ input_report_key(iqs269->slider[i],
+ iqs269->sl_code[i][j],
+ 0);
+ break;
+
+ case IQS269_SLIDER_RAW:
+ /*
+ * The slider is considered to be in a state of touch
+ * if any selected channels are in a state of touch.
+ */
+ state = flags.states[IQS269_ST_OFFS_TOUCH];
+ state &= iqs269->sys_reg.slider_select[i];
+
+ input_report_key(iqs269->slider[i], BTN_TOUCH, state);
+
+ if (state)
+ input_report_abs(iqs269->slider[i],
+ ABS_X, slider_x[i]);
+ break;
}
input_sync(iqs269->slider[i]);
@@ -1286,7 +1522,7 @@ static ssize_t counts_show(struct device *dev,
if (error)
return error;
- return scnprintf(buf, PAGE_SIZE, "%u\n", le16_to_cpu(counts));
+ return sysfs_emit(buf, "%u\n", le16_to_cpu(counts));
}
static ssize_t hall_bin_show(struct device *dev,
@@ -1324,7 +1560,7 @@ static ssize_t hall_bin_show(struct device *dev,
return -EINVAL;
}
- return scnprintf(buf, PAGE_SIZE, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t hall_enable_show(struct device *dev,
@@ -1332,7 +1568,7 @@ static ssize_t hall_enable_show(struct device *dev,
{
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
- return scnprintf(buf, PAGE_SIZE, "%u\n", iqs269->hall_enable);
+ return sysfs_emit(buf, "%u\n", iqs269->hall_enable);
}
static ssize_t hall_enable_store(struct device *dev,
@@ -1362,7 +1598,7 @@ static ssize_t ch_number_show(struct device *dev,
{
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
- return scnprintf(buf, PAGE_SIZE, "%u\n", iqs269->ch_num);
+ return sysfs_emit(buf, "%u\n", iqs269->ch_num);
}
static ssize_t ch_number_store(struct device *dev,
@@ -1391,8 +1627,7 @@ static ssize_t rx_enable_show(struct device *dev,
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;
- return scnprintf(buf, PAGE_SIZE, "%u\n",
- ch_reg[iqs269->ch_num].rx_enable);
+ return sysfs_emit(buf, "%u\n", ch_reg[iqs269->ch_num].rx_enable);
}
static ssize_t rx_enable_store(struct device *dev,
@@ -1432,7 +1667,7 @@ static ssize_t ati_mode_show(struct device *dev,
if (error)
return error;
- return scnprintf(buf, PAGE_SIZE, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t ati_mode_store(struct device *dev,
@@ -1465,7 +1700,7 @@ static ssize_t ati_base_show(struct device *dev,
if (error)
return error;
- return scnprintf(buf, PAGE_SIZE, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t ati_base_store(struct device *dev,
@@ -1498,7 +1733,7 @@ static ssize_t ati_target_show(struct device *dev,
if (error)
return error;
- return scnprintf(buf, PAGE_SIZE, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t ati_target_store(struct device *dev,
@@ -1525,9 +1760,9 @@ static ssize_t ati_trigger_show(struct device *dev,
{
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
- return scnprintf(buf, PAGE_SIZE, "%u\n",
- iqs269->ati_current &&
- completion_done(&iqs269->ati_done));
+ return sysfs_emit(buf, "%u\n",
+ iqs269->ati_current &&
+ completion_done(&iqs269->ati_done));
}
static ssize_t ati_trigger_store(struct device *dev,
@@ -1596,7 +1831,6 @@ static const struct regmap_config iqs269_regmap_config = {
static int iqs269_probe(struct i2c_client *client)
{
- struct iqs269_ver_info ver_info;
struct iqs269_private *iqs269;
int error;
@@ -1618,14 +1852,16 @@ static int iqs269_probe(struct i2c_client *client)
mutex_init(&iqs269->lock);
init_completion(&iqs269->ati_done);
- error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO, &ver_info,
- sizeof(ver_info));
+ iqs269->otp_option = (uintptr_t)device_get_match_data(&client->dev);
+
+ error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO,
+ &iqs269->ver_info, sizeof(iqs269->ver_info));
if (error)
return error;
- if (ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
+ if (iqs269->ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
dev_err(&client->dev, "Unrecognized product number: 0x%02X\n",
- ver_info.prod_num);
+ iqs269->ver_info.prod_num);
return -EINVAL;
}
@@ -1728,7 +1964,18 @@ static int iqs269_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(iqs269_pm, iqs269_suspend, iqs269_resume);
static const struct of_device_id iqs269_of_match[] = {
- { .compatible = "azoteq,iqs269a" },
+ {
+ .compatible = "azoteq,iqs269a",
+ .data = (void *)IQS269_OTP_OPTION_DEFAULT,
+ },
+ {
+ .compatible = "azoteq,iqs269a-00",
+ .data = (void *)IQS269_OTP_OPTION_DEFAULT,
+ },
+ {
+ .compatible = "azoteq,iqs269a-d0",
+ .data = (void *)IQS269_OTP_OPTION_TWS,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, iqs269_of_match);
diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
index 80f4416ffe2f..0e646f1b257b 100644
--- a/drivers/input/misc/max77693-haptic.c
+++ b/drivers/input/misc/max77693-haptic.c
@@ -307,7 +307,7 @@ static int max77693_haptic_probe(struct platform_device *pdev)
haptic->suspend_state = false;
/* Variant-specific init */
- haptic->dev_type = platform_get_device_id(pdev)->driver_data;
+ haptic->dev_type = max77693->type;
switch (haptic->dev_type) {
case TYPE_MAX77693:
haptic->regmap_haptic = max77693->regmap_haptic;
@@ -406,16 +406,24 @@ static DEFINE_SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
max77693_haptic_resume);
static const struct platform_device_id max77693_haptic_id[] = {
- { "max77693-haptic", TYPE_MAX77693 },
- { "max77843-haptic", TYPE_MAX77843 },
+ { "max77693-haptic", },
+ { "max77843-haptic", },
{},
};
MODULE_DEVICE_TABLE(platform, max77693_haptic_id);
+static const struct of_device_id of_max77693_haptic_dt_match[] = {
+ { .compatible = "maxim,max77693-haptic", },
+ { .compatible = "maxim,max77843-haptic", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, of_max77693_haptic_dt_match);
+
static struct platform_driver max77693_haptic_driver = {
.driver = {
.name = "max77693-haptic",
.pm = pm_sleep_ptr(&max77693_haptic_pm_ops),
+ .of_match_table = of_max77693_haptic_dt_match,
},
.probe = max77693_haptic_probe,
.id_table = max77693_haptic_id,