ldc2114: decouple key reporting and irq handling

Register IRQ handler regardless of input keys reporting

Change-Id: I1aa4d894f8827e9650bb89116f144e09bce84be7
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1213468
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Konstantin Makariev <kmakariev@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2018-07-20 16:56:17 -05:00 • committed by Konstantin Makariev
commit 9d4b780d2e

View file

@ -871,6 +871,29 @@ static ktime_t start_polling_tm;
static int polling_counter;
#endif
static void ldc2114_input_report(struct ldc2114_data *ldc,
int output_bits)
{
int s, i, status;
for (i = 0, s = 0; i < MAX_KEYS; i++) {
status = (output_bits >> i) & 1;
if (status == buttons[i])
continue;
buttons[i] = status;
input_report_key(ldc->input, ldc->button_map[i], status);
s++;
dev_dbg(ldc->dev, "sent key code = %d(%d)\n",
ldc->button_map[i], status);
}
if (s) { /* only send sync if there were keys reported */
input_sync(ldc->input);
dev_dbg(ldc->dev, "sent SYNC\n");
}
}
static void ldc2114_irq_work(struct work_struct *work)
{
struct delayed_work *dw =
@ -881,7 +904,7 @@ static void ldc2114_irq_work(struct work_struct *work)
uint8_t status_reg;
while (1) {
int ret, s, i, status;
int ret;
down(&ldc->semaphore);
@ -889,26 +912,16 @@ static void ldc2114_irq_work(struct work_struct *work)
if (status_reg & ~(LDC2114_REG_STATUS_CHIP_READY))
dev_info(ldc->dev, "STATUS bits 0x%x\n", status_reg);
ret = ldc2114_read_bulk(ldc->dev, LDC2114_OUT, &data, sizeof(data));
if (data.out != output_bits) {
output_bits = data.out;
dev_dbg(ldc->dev, "OUTPUT bits 0x%x\n", output_bits);
}
if (status_reg & LDC2114_REG_STATUS_OUT) {
ret = ldc2114_read_bulk(ldc->dev,
LDC2114_OUT, &data, sizeof(data));
if (data.out != output_bits) {
output_bits = data.out;
dev_dbg(ldc->dev, "OUTPUT bits 0x%x\n", output_bits);
}
for (i = 0, s = 0; i < MAX_KEYS; i++) {
status = (output_bits >> i) & 1;
if (status == buttons[i])
continue;
buttons[i] = status;
input_report_key(ldc->input, ldc->button_map[i], status);
s++;
dev_dbg(ldc->dev, "sent key code = %d(%d)\n",
ldc->button_map[i], status);
}
if (s) { /* only send sync if there were keys reported */
input_sync(ldc->input);
dev_dbg(ldc->dev, "sent SYNC\n");
if (ldc->btn_enabled)
ldc2114_input_report(ldc, output_bits);
}
if (atomic_read(&ldc->irq_work_running)) {
@ -927,17 +940,8 @@ static void ldc2114_irq_work(struct work_struct *work)
#endif
/* TODO: make sure we never miss release :) */
/* Work around missed release */
for (i = 0, s = 0; i < MAX_KEYS; i++) {
if (!buttons[i])
continue;
input_report_key(ldc->input, ldc->button_map[i], 0);
s++;
}
if (s) {
input_sync(ldc->input);
dev_warn(ldc->dev, "missed release for %d key(s)\n", s);
}
if (ldc->btn_enabled)
ldc2114_input_report(ldc, 0);
memset(buttons, 0, sizeof(buttons));
}
@ -1120,6 +1124,8 @@ static inline void ldc2114_of_init(struct i2c_client *client)
static void inline ldc2114_config_init(struct ldc2114_data *ldc,
struct ldc2114_config *cfg, int delay_ms)
{
dev_dbg(ldc->dev, "config_init entered\n");
ldc->config.active = cfg;
ldc->config.delay_ms = delay_ms;
ldc->config.attempts = 0;
@ -1151,6 +1157,8 @@ static void ldc2114_config_work(struct work_struct *work)
bool is_ready = ldc->config.active && ldc->config.active->size;
int i, ret;
dev_dbg(ldc->dev, "config_work entered; is_ready=%d\n", is_ready);
if (is_ready && !ldc->not_connected &&
(gpio_get_value(ldc->intb_gpio) == 0)) {
@ -1163,13 +1171,13 @@ static void ldc2114_config_work(struct work_struct *work)
/* now it's time to toggle LWPM pin, but only toggle it once */
ldc2114_toggle_gpio(ldc, ldc->lpwm_gpio);
ldc->config.toggled = true;
#ifdef LDC2114_CFG_DEBUG
dev_info(ldc->dev, "LWPM toggled\n");
#endif
}
if (!is_ready)
return;
if (!is_ready) {
dev_dbg(ldc->dev, "nothing to apply\n");
goto done;
}
JUMPIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_FULL,
LDC2114_REG_STATUS_CHIP_READY));
@ -1278,8 +1286,8 @@ error_workaround:
ldc2114_config_init(ldc, ldc->config.normal, LDC2114_LONG_DELAY);
queue_delayed_work(ldc->wq, &ldc->config_work,
msecs_to_jiffies(ldc->config.delay_ms));
queue_delayed_work(ldc->wq, &ldc->config_work, 0);
return 0;
}
@ -1294,8 +1302,7 @@ static int ldc2114_poll_enable_cb(struct notifier_block *n,
dev_info(ldc->dev, "polling state changed to %d\n", state);
if (state) {
queue_delayed_work(ldc->wq, &ldc->polling_work,
msecs_to_jiffies(0));
queue_delayed_work(ldc->wq, &ldc->polling_work, 0);
dev_dbg(ldc->dev, "polling resumed\n");
}
@ -1404,7 +1411,7 @@ static int ldc2114_probe(struct i2c_client *client,
sema_init(&ldc->semaphore, 0);
if (ldc->btn_enabled) {
if (!ldc->not_connected) {
/*
* Even though we setup edge triggered irq handler, genirq still
* checks for ONESHOT safety if no primary handler provided
@ -1421,10 +1428,11 @@ static int ldc2114_probe(struct i2c_client *client,
INIT_DELAYED_WORK(&ldc->irq_work, ldc2114_irq_work);
queue_delayed_work(ldc->wq, &ldc->irq_work,
msecs_to_jiffies(LDC2114_SHORT_DELAY));
ldc2114_input_device(ldc);
}
if (ldc->btn_enabled)
ldc2114_input_device(ldc);
ldc->data_polling = true;
ldc->poll_interval = 250;
INIT_DELAYED_WORK(&ldc->polling_work, ldc2114_polling_work);