From e9ba5a3542c60d8ace62e66415bc06f89a9c1c9a Mon Sep 17 00:00:00 2001 From: Greg Meiste Date: Mon, 29 Nov 2010 15:52:46 -0600 Subject: [PATCH] mfd: cpcap-3mm5: Fix for missing key event on resume The key_handler was checking the sense bits to see whether a press or release occurred. The problem with this is it takes so long to resume from LP0/LP1, that the key state could have changed again before the handler has even ran. The driver would see the key was currently released, which was the same state it last reported, and not send a new event. This patch changes the handler so it does not check the sense bits. It simply sends a press when the MB2 interrupt occurs and a release when the MACRO_5 interrupt occurs. This fixes the kernel portion of bug 3225781. Change-Id: I38a89417a0053315c93dc6c696a34a8974252d2a Signed-off-by: Greg Meiste --- drivers/mfd/cpcap-3mm5.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/mfd/cpcap-3mm5.c b/drivers/mfd/cpcap-3mm5.c index 29e39749d623..709e415ede7c 100644 --- a/drivers/mfd/cpcap-3mm5.c +++ b/drivers/mfd/cpcap-3mm5.c @@ -153,11 +153,11 @@ static void hs_handler(enum cpcap_irqs irq, void *data) new_state); } -static void key_handler(enum cpcap_irqs irq, void *data) +static void mb2_handler(enum cpcap_irqs irq, void *data) { struct cpcap_3mm5_data *data_3mm5 = data; - if ((irq != CPCAP_IRQ_MB2) && (irq != CPCAP_IRQ_UC_PRIMACRO_5)) + if (irq != CPCAP_IRQ_MB2) return; if ((cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_HS, 1) == 1) || @@ -166,21 +166,24 @@ static void key_handler(enum cpcap_irqs irq, void *data) return; } - if ((cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_MB2, 0) == 0) || - (cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_PTT, 0) == 0)) { - send_key_event(data_3mm5, 1); + send_key_event(data_3mm5, 1); + cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_MB2); +} - /* If macro not available, only short presses are supported */ - if (!cpcap_uc_status(data_3mm5->cpcap, CPCAP_MACRO_5)) { - send_key_event(data_3mm5, 0); +static void mac5_handler(enum cpcap_irqs irq, void *data) +{ + struct cpcap_3mm5_data *data_3mm5 = data; - /* Attempt to restart the macro for next time. */ - cpcap_uc_start(data_3mm5->cpcap, CPCAP_MACRO_5); - } - } else - send_key_event(data_3mm5, 0); + if (irq != CPCAP_IRQ_UC_PRIMACRO_5) + return; - cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_MB2); + if ((cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_HS, 1) == 1) || + (switch_get_state(&data_3mm5->sdev) != HEADSET_WITH_MIC)) { + hs_handler(CPCAP_IRQ_HS, data_3mm5); + return; + } + + send_key_event(data_3mm5, 0); cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5); } @@ -248,13 +251,13 @@ static int cpcap_3mm5_probe(struct platform_device *pdev) if (retval) goto reg_put; - retval = cpcap_irq_register(data->cpcap, CPCAP_IRQ_MB2, key_handler, + retval = cpcap_irq_register(data->cpcap, CPCAP_IRQ_MB2, mb2_handler, data); if (retval) goto free_hs; retval = cpcap_irq_register(data->cpcap, CPCAP_IRQ_UC_PRIMACRO_5, - key_handler, data); + mac5_handler, data); if (retval) goto free_mb2; -- 2.34.1