From 8ea227886002718ce522001de9c08515e75dc11f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 25 Jan 2017 09:34:06 +0000 Subject: extcon: arizona: Wait for any running HPDETs to complete on jack removal As the HPDET can't be aborted mid way through we should not allow any new insertion to be processed until the previous HPDET has finished. It is very unlikely but with low enough debounce settings you could start a new HPDET before the old one has completed, which results in an erroneous reading. Signed-off-by: Charles Keepax Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-arizona.c | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index ed78b7c26627..e2d78cd7030d 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -51,6 +51,9 @@ #define HPDET_DEBOUNCE 500 #define DEFAULT_MICD_TIMEOUT 2000 +#define ARIZONA_HPDET_WAIT_COUNT 15 +#define ARIZONA_HPDET_WAIT_DELAY_MS 20 + #define QUICK_HEADPHONE_MAX_OHM 3 #define MICROPHONE_MIN_OHM 1257 #define MICROPHONE_MAX_OHM 30000 @@ -1049,6 +1052,40 @@ static void arizona_hpdet_work(struct work_struct *work) mutex_unlock(&info->lock); } +static int arizona_hpdet_wait(struct arizona_extcon_info *info) +{ + struct arizona *arizona = info->arizona; + unsigned int val; + int i, ret; + + for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) { + ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, + &val); + if (ret) { + dev_err(arizona->dev, + "Failed to read HPDET state: %d\n", ret); + return ret; + } + + switch (info->hpdet_ip_version) { + case 0: + if (val & ARIZONA_HP_DONE) + return 0; + break; + default: + if (val & ARIZONA_HP_DONE_B) + return 0; + break; + } + + msleep(ARIZONA_HPDET_WAIT_DELAY_MS); + } + + dev_warn(arizona->dev, "HPDET did not appear to complete\n"); + + return -ETIMEDOUT; +} + static irqreturn_t arizona_jackdet(int irq, void *data) { struct arizona_extcon_info *info = data; @@ -1155,6 +1192,15 @@ static irqreturn_t arizona_jackdet(int irq, void *data) "Removal report failed: %d\n", ret); } + /* + * If the jack was removed during a headphone detection we + * need to wait for the headphone detection to finish, as + * it can not be aborted. We don't want to be able to start + * a new headphone detection from a fresh insert until this + * one is finished. + */ + arizona_hpdet_wait(info); + regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE, ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, -- cgit v1.2.3 From 4b1db7514e1baa5fcc5cfdbb88d6c23d6cda0216 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Mon, 13 Feb 2017 17:21:52 +0800 Subject: extcon: usb-gpio: Do not enable USB as wakeup source by default Whether the USB port as a wakeup source should be determined by user, but not enabled by default. Signed-off-by: Peter Chen Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-usb-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c index a5e1882b4ca6..66c749d3cecd 100644 --- a/drivers/extcon/extcon-usb-gpio.c +++ b/drivers/extcon/extcon-usb-gpio.c @@ -195,7 +195,7 @@ static int usb_extcon_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, info); - device_init_wakeup(dev, true); + device_set_wakeup_capable(&pdev->dev, true); /* Perform initial detection */ usb_extcon_detect_cable(&info->wq_detcable.work); -- cgit v1.2.3 From 2043cf1ddfdd68c0cd5ab9f7bed00980cfc67415 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 15 Feb 2017 14:31:28 +0200 Subject: extcon: usb-gpio: Don't miss event during suspend/resume We must check for ID/VBUS changes during resume irrespective of whether our device wakeup is enabled or not. Without this we seem to be missing ID/VBUS events after system suspend/resume. Signed-off-by: Roger Quadros Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-usb-gpio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c index 66c749d3cecd..d47573a31e17 100644 --- a/drivers/extcon/extcon-usb-gpio.c +++ b/drivers/extcon/extcon-usb-gpio.c @@ -282,9 +282,8 @@ static int usb_extcon_resume(struct device *dev) if (info->vbus_gpiod) enable_irq(info->vbus_irq); - if (!device_may_wakeup(dev)) - queue_delayed_work(system_power_efficient_wq, - &info->wq_detcable, 0); + queue_delayed_work(system_power_efficient_wq, + &info->wq_detcable, 0); return ret; } -- cgit v1.2.3 From 3573d97d840ca1e6062876cdfdb404e4e67b4a3c Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 15 Feb 2017 14:31:29 +0200 Subject: extcon: palmas: Don't miss GPIO events during suspend/resume The USB cable state can change during suspend/resume so be sure to check and update the extcon state. Signed-off-by: Roger Quadros Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-palmas.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index ca904e8b3235..2af4369a2d73 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c @@ -413,6 +413,12 @@ static int palmas_usb_resume(struct device *dev) if (palmas_usb->enable_gpio_id_detection) disable_irq_wake(palmas_usb->gpio_id_irq); } + + /* check if GPIO states changed while suspend/resume */ + if (palmas_usb->enable_gpio_vbus_detection) + palmas_vbus_irq_handler(palmas_usb->gpio_vbus_irq, palmas_usb); + palmas_gpio_id_detect(&palmas_usb->wq_detectid.work); + return 0; }; #endif -- cgit v1.2.3