Message ID | 1570083176-8231-5-git-send-email-michal.vokac@ysoft.com (mailing list archive) |
---|---|
State | Accepted |
Commit | ee358cb45984f4569098d3a97edfd0067576ad2f |
Headers | show |
Series | Add polling mode to the MPR121 touchkey | expand |
On Thu, Oct 03, 2019 at 08:12:55AM +0200, Michal Vokáč wrote: > In case the interrupt line is not available, polling can be used > to read out the state of the keys. Period of the polling needs to > be configured by the poll-interval DT property. > > Signed-off-by: Michal Vokáč <michal.vokac@ysoft.com> Applied, thank you. > --- > Changes since v2: > - None > > Changes since v1: > - Use poll-interval property name instead of linux,poll-interval. > > drivers/input/keyboard/mpr121_touchkey.c | 69 +++++++++++++++++++++++--------- > 1 file changed, 51 insertions(+), 18 deletions(-) > > diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c > index ee80de44ce3f..40d6e5087cde 100644 > --- a/drivers/input/keyboard/mpr121_touchkey.c > +++ b/drivers/input/keyboard/mpr121_touchkey.c > @@ -54,6 +54,9 @@ > /* MPR121 has 12 keys */ > #define MPR121_MAX_KEY_COUNT 12 > > +#define MPR121_MIN_POLL_INTERVAL 10 > +#define MPR121_MAX_POLL_INTERVAL 200 > + > struct mpr121_touchkey { > struct i2c_client *client; > struct input_dev *input_dev; > @@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev) > return vdd_supply; > } > > -static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) > +static void mpr_touchkey_report(struct input_dev *dev) > { > - struct mpr121_touchkey *mpr121 = dev_id; > - struct i2c_client *client = mpr121->client; > + struct mpr121_touchkey *mpr121 = input_get_drvdata(dev); > struct input_dev *input = mpr121->input_dev; > + struct i2c_client *client = mpr121->client; > unsigned long bit_changed; > unsigned int key_num; > int reg; > @@ -127,14 +130,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) > reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR); > if (reg < 0) { > dev_err(&client->dev, "i2c read error [%d]\n", reg); > - goto out; > + return; > } > > reg <<= 8; > reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR); > if (reg < 0) { > dev_err(&client->dev, "i2c read error [%d]\n", reg); > - goto out; > + return; > } > > reg &= TOUCH_STATUS_MASK; > @@ -155,8 +158,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) > > } > input_sync(input); > +} > + > +static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) > +{ > + struct mpr121_touchkey *mpr121 = dev_id; > + > + mpr_touchkey_report(mpr121->input_dev); > > -out: > return IRQ_HANDLED; > } > > @@ -229,14 +238,10 @@ static int mpr_touchkey_probe(struct i2c_client *client, > int vdd_uv; > struct mpr121_touchkey *mpr121; > struct input_dev *input_dev; > + u32 poll_interval = 0; > int error; > int i; > > - if (!client->irq) { > - dev_err(dev, "irq number should not be zero\n"); > - return -EINVAL; > - } > - > vdd_supply = mpr121_vdd_supply_init(dev); > if (IS_ERR(vdd_supply)) > return PTR_ERR(vdd_supply); > @@ -274,6 +279,7 @@ static int mpr_touchkey_probe(struct i2c_client *client, > if (device_property_read_bool(dev, "autorepeat")) > __set_bit(EV_REP, input_dev->evbit); > input_set_capability(input_dev, EV_MSC, MSC_SCAN); > + input_set_drvdata(input_dev, mpr121); > > input_dev->keycode = mpr121->keycodes; > input_dev->keycodesize = sizeof(mpr121->keycodes[0]); > @@ -288,13 +294,40 @@ static int mpr_touchkey_probe(struct i2c_client *client, > return error; > } > > - error = devm_request_threaded_irq(dev, client->irq, NULL, > - mpr_touchkey_interrupt, > - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, > - dev->driver->name, mpr121); > - if (error) { > - dev_err(dev, "Failed to register interrupt\n"); > - return error; > + device_property_read_u32(dev, "poll-interval", &poll_interval); > + > + if (client->irq) { > + error = devm_request_threaded_irq(dev, client->irq, NULL, > + mpr_touchkey_interrupt, > + IRQF_TRIGGER_FALLING | > + IRQF_ONESHOT, > + dev->driver->name, mpr121); > + if (error) { > + dev_err(dev, "Failed to register interrupt\n"); > + return error; > + } > + } else if (poll_interval) { > + if (poll_interval < MPR121_MIN_POLL_INTERVAL) > + return -EINVAL; > + > + if (poll_interval > MPR121_MAX_POLL_INTERVAL) > + return -EINVAL; > + > + error = input_setup_polling(input_dev, mpr_touchkey_report); > + if (error) { > + dev_err(dev, "Failed to setup polling\n"); > + return error; > + } > + > + input_set_poll_interval(input_dev, poll_interval); > + input_set_min_poll_interval(input_dev, > + MPR121_MIN_POLL_INTERVAL); > + input_set_max_poll_interval(input_dev, > + MPR121_MAX_POLL_INTERVAL); > + } else { > + dev_err(dev, > + "invalid IRQ number and polling not configured\n"); > + return -EINVAL; > } > > error = input_register_device(input_dev); > -- > 2.1.4 >
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index ee80de44ce3f..40d6e5087cde 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -54,6 +54,9 @@ /* MPR121 has 12 keys */ #define MPR121_MAX_KEY_COUNT 12 +#define MPR121_MIN_POLL_INTERVAL 10 +#define MPR121_MAX_POLL_INTERVAL 200 + struct mpr121_touchkey { struct i2c_client *client; struct input_dev *input_dev; @@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev) return vdd_supply; } -static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) +static void mpr_touchkey_report(struct input_dev *dev) { - struct mpr121_touchkey *mpr121 = dev_id; - struct i2c_client *client = mpr121->client; + struct mpr121_touchkey *mpr121 = input_get_drvdata(dev); struct input_dev *input = mpr121->input_dev; + struct i2c_client *client = mpr121->client; unsigned long bit_changed; unsigned int key_num; int reg; @@ -127,14 +130,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR); if (reg < 0) { dev_err(&client->dev, "i2c read error [%d]\n", reg); - goto out; + return; } reg <<= 8; reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR); if (reg < 0) { dev_err(&client->dev, "i2c read error [%d]\n", reg); - goto out; + return; } reg &= TOUCH_STATUS_MASK; @@ -155,8 +158,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) } input_sync(input); +} + +static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) +{ + struct mpr121_touchkey *mpr121 = dev_id; + + mpr_touchkey_report(mpr121->input_dev); -out: return IRQ_HANDLED; } @@ -229,14 +238,10 @@ static int mpr_touchkey_probe(struct i2c_client *client, int vdd_uv; struct mpr121_touchkey *mpr121; struct input_dev *input_dev; + u32 poll_interval = 0; int error; int i; - if (!client->irq) { - dev_err(dev, "irq number should not be zero\n"); - return -EINVAL; - } - vdd_supply = mpr121_vdd_supply_init(dev); if (IS_ERR(vdd_supply)) return PTR_ERR(vdd_supply); @@ -274,6 +279,7 @@ static int mpr_touchkey_probe(struct i2c_client *client, if (device_property_read_bool(dev, "autorepeat")) __set_bit(EV_REP, input_dev->evbit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(input_dev, mpr121); input_dev->keycode = mpr121->keycodes; input_dev->keycodesize = sizeof(mpr121->keycodes[0]); @@ -288,13 +294,40 @@ static int mpr_touchkey_probe(struct i2c_client *client, return error; } - error = devm_request_threaded_irq(dev, client->irq, NULL, - mpr_touchkey_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev->driver->name, mpr121); - if (error) { - dev_err(dev, "Failed to register interrupt\n"); - return error; + device_property_read_u32(dev, "poll-interval", &poll_interval); + + if (client->irq) { + error = devm_request_threaded_irq(dev, client->irq, NULL, + mpr_touchkey_interrupt, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + dev->driver->name, mpr121); + if (error) { + dev_err(dev, "Failed to register interrupt\n"); + return error; + } + } else if (poll_interval) { + if (poll_interval < MPR121_MIN_POLL_INTERVAL) + return -EINVAL; + + if (poll_interval > MPR121_MAX_POLL_INTERVAL) + return -EINVAL; + + error = input_setup_polling(input_dev, mpr_touchkey_report); + if (error) { + dev_err(dev, "Failed to setup polling\n"); + return error; + } + + input_set_poll_interval(input_dev, poll_interval); + input_set_min_poll_interval(input_dev, + MPR121_MIN_POLL_INTERVAL); + input_set_max_poll_interval(input_dev, + MPR121_MAX_POLL_INTERVAL); + } else { + dev_err(dev, + "invalid IRQ number and polling not configured\n"); + return -EINVAL; } error = input_register_device(input_dev);
In case the interrupt line is not available, polling can be used to read out the state of the keys. Period of the polling needs to be configured by the poll-interval DT property. Signed-off-by: Michal Vokáč <michal.vokac@ysoft.com> --- Changes since v2: - None Changes since v1: - Use poll-interval property name instead of linux,poll-interval. drivers/input/keyboard/mpr121_touchkey.c | 69 +++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 18 deletions(-)