linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] Input: qt2160 - tweak check for i2c adapter functionality
@ 2023-07-24  5:13 Dmitry Torokhov
  2023-07-24  5:13 ` [PATCH 2/4] Input: qt2160 - switch to using threaded interrupt handler Dmitry Torokhov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Dmitry Torokhov @ 2023-07-24  5:13 UTC (permalink / raw)
  To: linux-input; +Cc: Yangtao Li, linux-kernel

i2c_check_functionality() returns essentially a boolean and not an error
code, so treat it as such.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/keyboard/qt2160.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 599ea85cfd30..b0b9d7a2691e 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -345,12 +345,9 @@ static int qt2160_probe(struct i2c_client *client)
 	int i;
 	int error;
 
-	/* Check functionality */
-	error = i2c_check_functionality(client->adapter,
-			I2C_FUNC_SMBUS_BYTE);
-	if (!error) {
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
 		dev_err(&client->dev, "%s adapter not supported\n",
-				dev_driver_string(&client->adapter->dev));
+			dev_driver_string(&client->adapter->dev));
 		return -ENODEV;
 	}
 
-- 
2.41.0.487.g6d72f3e995-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/4] Input: qt2160 - switch to using threaded interrupt handler
  2023-07-24  5:13 [PATCH 1/4] Input: qt2160 - tweak check for i2c adapter functionality Dmitry Torokhov
@ 2023-07-24  5:13 ` Dmitry Torokhov
  2023-07-24  5:13 ` [PATCH 3/4] Input: qt2160 - do not hard code interrupt trigger Dmitry Torokhov
  2023-07-24  5:13 ` [PATCH 4/4] Input: qt2160 - convert to use devm_* api Dmitry Torokhov
  2 siblings, 0 replies; 4+ messages in thread
From: Dmitry Torokhov @ 2023-07-24  5:13 UTC (permalink / raw)
  To: linux-input; +Cc: Yangtao Li, linux-kernel

Instead of using combination of normal IRQ and work item which required
careful handling on device teardown, use standard threaded interrupt that
allows communication wityh the chip over slow (I2C) bus directly in the
interrupt handler.

To support polling mode switch to standard polling support implemented by
the input core.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/keyboard/qt2160.c | 53 ++++++++++++---------------------
 1 file changed, 19 insertions(+), 34 deletions(-)

diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index b0b9d7a2691e..b8c0f0ebf604 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -32,7 +32,7 @@
 
 #define QT2160_NUM_LEDS_X	8
 
-#define QT2160_CYCLE_INTERVAL	(2*HZ)
+#define QT2160_CYCLE_INTERVAL	2000 /* msec - 2 sec */
 
 static unsigned char qt2160_key2code[] = {
 	KEY_0, KEY_1, KEY_2, KEY_3,
@@ -54,7 +54,6 @@ struct qt2160_led {
 struct qt2160_data {
 	struct i2c_client *client;
 	struct input_dev *input;
-	struct delayed_work dwork;
 	unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)];
 	u16 key_matrix;
 #ifdef CONFIG_LEDS_CLASS
@@ -155,10 +154,10 @@ static int qt2160_read_block(struct i2c_client *client,
 	return 0;
 }
 
-static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
+static void qt2160_get_key_matrix(struct input_dev *input)
 {
+	struct qt2160_data *qt2160 = input_get_drvdata(input);
 	struct i2c_client *client = qt2160->client;
-	struct input_dev *input = qt2160->input;
 	u8 regs[6];
 	u16 old_matrix, new_matrix;
 	int ret, i, mask;
@@ -173,7 +172,7 @@ static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
 	if (ret) {
 		dev_err(&client->dev,
 			"could not perform chip read.\n");
-		return ret;
+		return;
 	}
 
 	old_matrix = qt2160->key_matrix;
@@ -191,37 +190,17 @@ static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
 	}
 
 	input_sync(input);
-
-	return 0;
 }
 
-static irqreturn_t qt2160_irq(int irq, void *_qt2160)
+static irqreturn_t qt2160_irq(int irq, void *data)
 {
-	struct qt2160_data *qt2160 = _qt2160;
+	struct input_dev *input = data;
 
-	mod_delayed_work(system_wq, &qt2160->dwork, 0);
+	qt2160_get_key_matrix(input);
 
 	return IRQ_HANDLED;
 }
 
-static void qt2160_schedule_read(struct qt2160_data *qt2160)
-{
-	schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL);
-}
-
-static void qt2160_worker(struct work_struct *work)
-{
-	struct qt2160_data *qt2160 =
-		container_of(work, struct qt2160_data, dwork.work);
-
-	dev_dbg(&qt2160->client->dev, "worker\n");
-
-	qt2160_get_key_matrix(qt2160);
-
-	/* Avoid device lock up by checking every so often */
-	qt2160_schedule_read(qt2160);
-}
-
 static int qt2160_read(struct i2c_client *client, u8 reg)
 {
 	int ret;
@@ -365,7 +344,6 @@ static int qt2160_probe(struct i2c_client *client)
 
 	qt2160->client = client;
 	qt2160->input = input;
-	INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker);
 
 	input->name = "AT42QT2160 Touch Sense Keyboard";
 	input->id.bustype = BUS_I2C;
@@ -382,6 +360,8 @@ static int qt2160_probe(struct i2c_client *client)
 	}
 	__clear_bit(KEY_RESERVED, input->keybit);
 
+	input_set_drvdata(input, qt2160);
+
 	/* Calibrate device */
 	error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1);
 	if (error) {
@@ -390,13 +370,21 @@ static int qt2160_probe(struct i2c_client *client)
 	}
 
 	if (client->irq) {
-		error = request_irq(client->irq, qt2160_irq,
-				    IRQF_TRIGGER_FALLING, "qt2160", qt2160);
+		error = request_threaded_irq(client->irq, NULL, qt2160_irq,
+					     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					     "qt2160", input);
 		if (error) {
 			dev_err(&client->dev,
 				"failed to allocate irq %d\n", client->irq);
 			goto err_free_mem;
 		}
+	} else {
+		error = input_setup_polling(input, qt2160_get_key_matrix);
+		if (error) {
+			dev_err(&client->dev, "Failed to setup polling\n");
+			goto err_free_mem;
+		}
+		input_set_poll_interval(input, QT2160_CYCLE_INTERVAL);
 	}
 
 	error = qt2160_register_leds(qt2160);
@@ -413,7 +401,6 @@ static int qt2160_probe(struct i2c_client *client)
 	}
 
 	i2c_set_clientdata(client, qt2160);
-	qt2160_schedule_read(qt2160);
 
 	return 0;
 
@@ -438,8 +425,6 @@ static void qt2160_remove(struct i2c_client *client)
 	if (client->irq)
 		free_irq(client->irq, qt2160);
 
-	cancel_delayed_work_sync(&qt2160->dwork);
-
 	input_unregister_device(qt2160->input);
 	kfree(qt2160);
 }
-- 
2.41.0.487.g6d72f3e995-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/4] Input: qt2160 - do not hard code interrupt trigger
  2023-07-24  5:13 [PATCH 1/4] Input: qt2160 - tweak check for i2c adapter functionality Dmitry Torokhov
  2023-07-24  5:13 ` [PATCH 2/4] Input: qt2160 - switch to using threaded interrupt handler Dmitry Torokhov
@ 2023-07-24  5:13 ` Dmitry Torokhov
  2023-07-24  5:13 ` [PATCH 4/4] Input: qt2160 - convert to use devm_* api Dmitry Torokhov
  2 siblings, 0 replies; 4+ messages in thread
From: Dmitry Torokhov @ 2023-07-24  5:13 UTC (permalink / raw)
  To: linux-input; +Cc: Yangtao Li, linux-kernel

Rely on the platform and ACPI/DT to set up the interrupt trigger.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/keyboard/qt2160.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index b8c0f0ebf604..6cfaabd10482 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -371,8 +371,7 @@ static int qt2160_probe(struct i2c_client *client)
 
 	if (client->irq) {
 		error = request_threaded_irq(client->irq, NULL, qt2160_irq,
-					     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					     "qt2160", input);
+					     IRQF_ONESHOT, "qt2160", input);
 		if (error) {
 			dev_err(&client->dev,
 				"failed to allocate irq %d\n", client->irq);
-- 
2.41.0.487.g6d72f3e995-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 4/4] Input: qt2160 - convert to use devm_* api
  2023-07-24  5:13 [PATCH 1/4] Input: qt2160 - tweak check for i2c adapter functionality Dmitry Torokhov
  2023-07-24  5:13 ` [PATCH 2/4] Input: qt2160 - switch to using threaded interrupt handler Dmitry Torokhov
  2023-07-24  5:13 ` [PATCH 3/4] Input: qt2160 - do not hard code interrupt trigger Dmitry Torokhov
@ 2023-07-24  5:13 ` Dmitry Torokhov
  2 siblings, 0 replies; 4+ messages in thread
From: Dmitry Torokhov @ 2023-07-24  5:13 UTC (permalink / raw)
  To: linux-input; +Cc: Yangtao Li, linux-kernel

From: Yangtao Li <frank.li@vivo.com>

Use devm_* api to simplify code, this makes it unnecessary to explicitly
release resources.

Signed-off-by: Yangtao Li <frank.li@vivo.com>
Link: https://lore.kernel.org/r/20230714080611.81302-7-frank.li@vivo.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/keyboard/qt2160.c | 77 +++++++++------------------------
 1 file changed, 20 insertions(+), 57 deletions(-)

diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 6cfaabd10482..7e3b09642ab7 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -239,7 +239,7 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data)
 static int qt2160_register_leds(struct qt2160_data *qt2160)
 {
 	struct i2c_client *client = qt2160->client;
-	int ret;
+	int error;
 	int i;
 
 	for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
@@ -252,9 +252,9 @@ static int qt2160_register_leds(struct qt2160_data *qt2160)
 		led->id = i;
 		led->qt2160 = qt2160;
 
-		ret = led_classdev_register(&client->dev, &led->cdev);
-		if (ret < 0)
-			return ret;
+		error = devm_led_classdev_register(&client->dev, &led->cdev);
+		if (error)
+			return error;
 	}
 
 	/* Tur off LEDs */
@@ -265,14 +265,6 @@ static int qt2160_register_leds(struct qt2160_data *qt2160)
 	return 0;
 }
 
-static void qt2160_unregister_leds(struct qt2160_data *qt2160)
-{
-	int i;
-
-	for (i = 0; i < QT2160_NUM_LEDS_X; i++)
-		led_classdev_unregister(&qt2160->leds[i].cdev);
-}
-
 #else
 
 static inline int qt2160_register_leds(struct qt2160_data *qt2160)
@@ -280,10 +272,6 @@ static inline int qt2160_register_leds(struct qt2160_data *qt2160)
 	return 0;
 }
 
-static inline void qt2160_unregister_leds(struct qt2160_data *qt2160)
-{
-}
-
 #endif
 
 static bool qt2160_identify(struct i2c_client *client)
@@ -334,13 +322,13 @@ static int qt2160_probe(struct i2c_client *client)
 		return -ENODEV;
 
 	/* Chip is valid and active. Allocate structure */
-	qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL);
-	input = input_allocate_device();
-	if (!qt2160 || !input) {
-		dev_err(&client->dev, "insufficient memory\n");
-		error = -ENOMEM;
-		goto err_free_mem;
-	}
+	qt2160 = devm_kzalloc(&client->dev, sizeof(*qt2160), GFP_KERNEL);
+	if (!qt2160)
+		return -ENOMEM;
+
+	input = devm_input_allocate_device(&client->dev);
+	if (!input)
+		return -ENOMEM;
 
 	qt2160->client = client;
 	qt2160->input = input;
@@ -366,22 +354,24 @@ static int qt2160_probe(struct i2c_client *client)
 	error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1);
 	if (error) {
 		dev_err(&client->dev, "failed to calibrate device\n");
-		goto err_free_mem;
+		return error;
 	}
 
 	if (client->irq) {
-		error = request_threaded_irq(client->irq, NULL, qt2160_irq,
-					     IRQF_ONESHOT, "qt2160", input);
+		error = devm_request_threaded_irq(&client->dev, client->irq,
+						  NULL, qt2160_irq,
+						  IRQF_ONESHOT,
+						  "qt2160", input);
 		if (error) {
 			dev_err(&client->dev,
 				"failed to allocate irq %d\n", client->irq);
-			goto err_free_mem;
+			return error;
 		}
 	} else {
 		error = input_setup_polling(input, qt2160_get_key_matrix);
 		if (error) {
 			dev_err(&client->dev, "Failed to setup polling\n");
-			goto err_free_mem;
+			return error;
 		}
 		input_set_poll_interval(input, QT2160_CYCLE_INTERVAL);
 	}
@@ -389,43 +379,17 @@ static int qt2160_probe(struct i2c_client *client)
 	error = qt2160_register_leds(qt2160);
 	if (error) {
 		dev_err(&client->dev, "Failed to register leds\n");
-		goto err_free_irq;
+		return error;
 	}
 
 	error = input_register_device(qt2160->input);
 	if (error) {
 		dev_err(&client->dev,
 			"Failed to register input device\n");
-		goto err_unregister_leds;
+		return error;
 	}
 
-	i2c_set_clientdata(client, qt2160);
-
 	return 0;
-
-err_unregister_leds:
-	qt2160_unregister_leds(qt2160);
-err_free_irq:
-	if (client->irq)
-		free_irq(client->irq, qt2160);
-err_free_mem:
-	input_free_device(input);
-	kfree(qt2160);
-	return error;
-}
-
-static void qt2160_remove(struct i2c_client *client)
-{
-	struct qt2160_data *qt2160 = i2c_get_clientdata(client);
-
-	qt2160_unregister_leds(qt2160);
-
-	/* Release IRQ so no queue will be scheduled */
-	if (client->irq)
-		free_irq(client->irq, qt2160);
-
-	input_unregister_device(qt2160->input);
-	kfree(qt2160);
 }
 
 static const struct i2c_device_id qt2160_idtable[] = {
@@ -442,7 +406,6 @@ static struct i2c_driver qt2160_driver = {
 
 	.id_table	= qt2160_idtable,
 	.probe		= qt2160_probe,
-	.remove		= qt2160_remove,
 };
 
 module_i2c_driver(qt2160_driver);
-- 
2.41.0.487.g6d72f3e995-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-07-24  5:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-24  5:13 [PATCH 1/4] Input: qt2160 - tweak check for i2c adapter functionality Dmitry Torokhov
2023-07-24  5:13 ` [PATCH 2/4] Input: qt2160 - switch to using threaded interrupt handler Dmitry Torokhov
2023-07-24  5:13 ` [PATCH 3/4] Input: qt2160 - do not hard code interrupt trigger Dmitry Torokhov
2023-07-24  5:13 ` [PATCH 4/4] Input: qt2160 - convert to use devm_* api Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).