From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Mike Rapoport <mike@compulab.co.il>
Cc: Jean Delvare <khali@linux-fr.org>,
grinberg <grinberg@compulab.co.il>,
linux-input <linux-input@vger.kernel.org>
Subject: Re: [PATCH v2] input: add synaptics_i2c driver
Date: Thu, 11 Jun 2009 00:14:29 -0700 [thread overview]
Message-ID: <20090611071428.GC8035@dtor-d630.eng.vmware.com> (raw)
In-Reply-To: <4A262D5F.1070803@compulab.co.il>
Hi Mike,
On Wed, Jun 03, 2009 at 10:59:27AM +0300, Mike Rapoport wrote:
>
> This driver supports Synaptics I2C touchpad controller on eXeda
> mobile device.
>
>
Looks much better, one concern still though:
> +
> +/* Work Handler */
> +static void synaptics_i2c_work_handler(struct work_struct *work)
> +{
> + int data = 1;
> + struct synaptics_i2c *touch =
> + container_of(work, struct synaptics_i2c, dwork.work);
> + unsigned long delay;
> +
> + synaptics_i2c_check_params(touch);
> +
> + do {
> + data = synaptics_i2c_get_input(touch);
> + delay = synaptics_i2c_fix_delay(touch, data);
> + } while (data);
> +
This will spin in the work handler for the duration of the touch
hogging keventd on this CPU and delaying all other scheduled works. I
don't think we can do that.
Please try the patchg below and if it still works I will fold it all
together and queue for upstream. Thanks!
--
Dmitry
Input: synaptics_i2c fixups
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/mouse/synaptics_i2c.c | 94 ++++++++++++++++++++---------------
1 files changed, 53 insertions(+), 41 deletions(-)
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 32a5d87..eac9fdd 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -241,10 +241,10 @@ static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg)
int ret;
ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
- if (ret)
- return ret;
+ if (ret == 0)
+ ret = i2c_smbus_read_byte_data(client, reg & 0xff);
- return i2c_smbus_read_byte_data(client, reg & 0xff);
+ return ret;
}
static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val)
@@ -252,10 +252,10 @@ static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val)
int ret;
ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
- if (ret)
- return ret;
+ if (ret == 0)
+ ret = i2c_smbus_write_byte_data(client, reg & 0xff, val);
- return i2c_smbus_write_byte_data(client, reg & 0xff, val);
+ return ret;
}
static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg)
@@ -263,10 +263,10 @@ static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg)
int ret;
ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
- if (ret)
- return ret;
+ if (ret == 0)
+ ret = i2c_smbus_read_word_data(client, reg & 0xff);
- return i2c_smbus_read_word_data(client, reg & 0xff);
+ return ret;
}
static int synaptics_i2c_config(struct i2c_client *client)
@@ -287,11 +287,11 @@ static int synaptics_i2c_config(struct i2c_client *client)
control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG);
/* No Deceleration */
- control |= (no_decel) ? 1 << NO_DECELERATION : 0;
+ control |= no_decel ? 1 << NO_DECELERATION : 0;
/* Reduced Reporting */
- control |= (reduce_report) ? 1 << REDUCE_REPORTING : 0;
+ control |= reduce_report ? 1 << REDUCE_REPORTING : 0;
/* No Filter */
- control |= (no_filter) ? 1 << NO_FILTER : 0;
+ control |= no_filter ? 1 << NO_FILTER : 0;
ret = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control);
if (ret)
return ret;
@@ -302,6 +302,7 @@ static int synaptics_i2c_config(struct i2c_client *client)
static int synaptics_i2c_reset_config(struct i2c_client *client)
{
int ret;
+
/* Reset the Touchpad */
ret = synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND);
if (ret) {
@@ -329,10 +330,11 @@ static int synaptics_i2c_check_error(struct i2c_client *client)
return ret;
}
-static int synaptics_i2c_get_input(struct synaptics_i2c *touch)
+static bool synaptics_i2c_get_input(struct synaptics_i2c *touch)
{
struct input_dev *input = touch->input;
int xy_delta, gesture;
+ s32 data;
s8 x_delta, y_delta;
/* Deal with spontanious resets and errors */
@@ -340,8 +342,8 @@ static int synaptics_i2c_get_input(struct synaptics_i2c *touch)
return 0;
/* Get Gesture Bit */
- gesture = (synaptics_i2c_reg_get(touch->client, DATA_REG0)
- >> GESTURE) & 0x1;
+ data = synaptics_i2c_reg_get(touch->client, DATA_REG0);
+ gesture = (data >> GESTURE) & 0x1;
/*
* Get Relative axes. we have to get them in one shot,
@@ -361,7 +363,7 @@ static int synaptics_i2c_get_input(struct synaptics_i2c *touch)
input_report_rel(input, REL_Y, -y_delta);
input_sync(input);
- return (xy_delta || gesture) ? 1 : 0;
+ return xy_delta || gesture;
}
static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id)
@@ -369,8 +371,9 @@ static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id)
struct synaptics_i2c *touch = dev_id;
/*
- * This cancels the work scheduled in work handler.
- * See explanation on this in work handler func.
+ * We want to have the work run immediately but it might have
+ * already been scheduled with a delay, that's why we have to
+ * cancel it first.
*/
cancel_delayed_work(&touch->dwork);
schedule_delayed_work(&touch->dwork, 0);
@@ -380,34 +383,39 @@ static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id)
static void synaptics_i2c_check_params(struct synaptics_i2c *touch)
{
- int reset = 0;
+ bool reset = false;
+
if (scan_rate != touch->scan_rate_param)
set_scan_rate(touch, scan_rate);
if (no_decel != touch->no_decel_param) {
touch->no_decel_param = no_decel;
- reset = 1;
+ reset = true;
}
+
if (no_filter != touch->no_filter_param) {
touch->no_filter_param = no_filter;
- reset = 1;
+ reset = true;
}
+
if (reduce_report != touch->reduce_report_param) {
touch->reduce_report_param = reduce_report;
- reset = 1;
+ reset = true;
}
+
if (reset)
synaptics_i2c_reset_config(touch->client);
}
/* Control the Device polling rate / Work Handler sleep time */
-unsigned long synaptics_i2c_fix_delay(struct synaptics_i2c *touch, int data)
+unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch,
+ bool have_data)
{
- int delay, nodata_count_thres;
+ unsigned long delay, nodata_count_thres;
if (polling_req) {
delay = touch->scan_ms;
- if (data) {
+ if (have_data) {
touch->no_data_count = 0;
} else {
nodata_count_thres = NO_DATA_THRES / touch->scan_ms;
@@ -416,26 +424,25 @@ unsigned long synaptics_i2c_fix_delay(struct synaptics_i2c *touch, int data)
else
delay = NO_DATA_SLEEP_MSECS;
}
- } else
- delay = THREAD_IRQ_SLEEP_MSECS;
-
- return msecs_to_jiffies(delay);
+ return msecs_to_jiffies(delay);
+ } else {
+ delay = msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS);
+ return round_jiffies_relative(delay);
+ }
}
/* Work Handler */
static void synaptics_i2c_work_handler(struct work_struct *work)
{
- int data = 1;
+ bool have_data;
struct synaptics_i2c *touch =
container_of(work, struct synaptics_i2c, dwork.work);
unsigned long delay;
synaptics_i2c_check_params(touch);
- do {
- data = synaptics_i2c_get_input(touch);
- delay = synaptics_i2c_fix_delay(touch, data);
- } while (data);
+ have_data = synaptics_i2c_get_input(touch);
+ delay = synaptics_i2c_adjust_delay(touch, have_data);
/*
* While interrupt driven, there is no real need to poll the device.
@@ -450,8 +457,8 @@ static void synaptics_i2c_work_handler(struct work_struct *work)
static int synaptics_i2c_open(struct input_dev *input)
{
- int ret = 0;
struct synaptics_i2c *touch = input_get_drvdata(input);
+ int ret;
ret = synaptics_i2c_reset_config(touch->client);
if (ret)
@@ -461,7 +468,7 @@ static int synaptics_i2c_open(struct input_dev *input)
schedule_delayed_work(&touch->dwork,
msecs_to_jiffies(NO_DATA_SLEEP_MSECS));
- return ret;
+ return 0;
}
static void synaptics_i2c_close(struct input_dev *input)
@@ -492,13 +499,13 @@ static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch)
input_set_drvdata(input, touch);
/* Register the device as mouse */
- set_bit(EV_REL, input->evbit);
- set_bit(REL_X, input->relbit);
- set_bit(REL_Y, input->relbit);
+ __set_bit(EV_REL, input->evbit);
+ __set_bit(REL_X, input->relbit);
+ __set_bit(REL_Y, input->relbit);
/* Register device's buttons and keys */
- set_bit(EV_KEY, input->evbit);
- set_bit(BTN_LEFT, input->keybit);
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(BTN_LEFT, input->keybit);
}
struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client)
@@ -598,6 +605,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
return 0;
}
+#ifdef CONFIG_PM
static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
{
struct synaptics_i2c *touch = i2c_get_clientdata(client);
@@ -624,6 +632,10 @@ static int synaptics_i2c_resume(struct i2c_client *client)
return 0;
}
+#else
+#define synaptics_i2c_suspend NULL
+#define synaptics_i2c_resume NULL
+#endif
static const struct i2c_device_id synaptics_i2c_id_table[] = {
{ "synaptics_i2c", 0 },
next prev parent reply other threads:[~2009-06-11 7:20 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-20 12:36 [PATCH v2] input: add synaptics_i2c driver Mike Rapoport
2009-05-20 12:49 ` Jean Delvare
2009-06-02 5:40 ` Mike Rapoport
2009-06-02 11:58 ` Dmitry Torokhov
2009-06-03 7:59 ` Mike Rapoport
2009-06-11 5:52 ` Mike Rapoport
2009-06-11 7:14 ` Dmitry Torokhov [this message]
2009-06-11 10:35 ` Mike Rapoport
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090611071428.GC8035@dtor-d630.eng.vmware.com \
--to=dmitry.torokhov@gmail.com \
--cc=grinberg@compulab.co.il \
--cc=khali@linux-fr.org \
--cc=linux-input@vger.kernel.org \
--cc=mike@compulab.co.il \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.