extcon: arizona: Support use of GPIO5 as an input to jack detection

Some system designs provide an input on GPIO5 which in conjunction with
the jack detection feature indicates the presence of an accessory.
Support such systems, using the microphone clamp feature to minimise
wakeups of the processor.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Myungjoo Ham <myungjoo.ham@samsung.com>
This commit is contained in:
Mark Brown 2013-01-11 08:55:39 +09:00 committed by Chanwoo Choi
parent dab63eb25c
commit 92a49871b3
2 changed files with 61 additions and 18 deletions

View File

@ -290,13 +290,21 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
{
struct arizona_extcon_info *info = data;
struct arizona *arizona = info->arizona;
unsigned int val;
unsigned int val, present, mask;
int ret, i;
pm_runtime_get_sync(info->dev);
mutex_lock(&info->lock);
if (arizona->pdata.jd_gpio5) {
mask = ARIZONA_MICD_CLAMP_STS;
present = 0;
} else {
mask = ARIZONA_JD1_STS;
present = ARIZONA_JD1_STS;
}
ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
if (ret != 0) {
dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
@ -306,7 +314,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
return IRQ_NONE;
}
if (val & ARIZONA_JD1_STS) {
if ((val & mask) == present) {
dev_dbg(arizona->dev, "Detected jack\n");
ret = extcon_set_cable_state_(&info->edev,
ARIZONA_CABLE_MECHANICAL, true);
@ -321,6 +329,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
arizona_stop_mic(info);
for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
input_report_key(info->input,
arizona_lvl_to_key[i].report, 0);
@ -345,6 +354,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_pdata *pdata;
struct arizona_extcon_info *info;
int jack_irq_fall, jack_irq_rise;
int ret, mode, i;
pdata = dev_get_platdata(arizona->dev);
@ -426,12 +436,24 @@ static int arizona_extcon_probe(struct platform_device *pdev)
<< ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
/*
* If we have a clamp use it.
* If we have a clamp use it, activating in conjunction with
* GPIO5 if that is connected for jack detect operation.
*/
if (info->micd_clamp) {
if (arizona->pdata.jd_gpio5) {
/* Put the GPIO into input mode */
regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
0xc101);
regmap_update_bits(arizona->regmap,
ARIZONA_MICD_CLAMP_CONTROL,
ARIZONA_MICD_CLAMP_MODE_MASK, 4);
ARIZONA_MICD_CLAMP_MODE_MASK, 0x9);
} else {
regmap_update_bits(arizona->regmap,
ARIZONA_MICD_CLAMP_CONTROL,
ARIZONA_MICD_CLAMP_MODE_MASK, 0x4);
}
regmap_update_bits(arizona->regmap,
ARIZONA_JACK_DETECT_DEBOUNCE,
ARIZONA_MICD_CLAMP_DB,
@ -458,7 +480,15 @@ static int arizona_extcon_probe(struct platform_device *pdev)
pm_runtime_idle(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_RISE,
if (arizona->pdata.jd_gpio5) {
jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
} else {
jack_irq_rise = ARIZONA_IRQ_JD_RISE;
jack_irq_fall = ARIZONA_IRQ_JD_FALL;
}
ret = arizona_request_irq(arizona, jack_irq_rise,
"JACKDET rise", arizona_jackdet, info);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
@ -466,21 +496,21 @@ static int arizona_extcon_probe(struct platform_device *pdev)
goto err_input;
}
ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1);
ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
ret);
goto err_rise;
}
ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_FALL,
ret = arizona_request_irq(arizona, jack_irq_fall,
"JACKDET fall", arizona_jackdet, info);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
goto err_rise_wake;
}
ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 1);
ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
ret);
@ -522,13 +552,13 @@ static int arizona_extcon_probe(struct platform_device *pdev)
err_micdet:
arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
err_fall_wake:
arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0);
arizona_set_irq_wake(arizona, jack_irq_fall, 0);
err_fall:
arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info);
arizona_free_irq(arizona, jack_irq_fall, info);
err_rise_wake:
arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0);
arizona_set_irq_wake(arizona, jack_irq_rise, 0);
err_rise:
arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info);
arizona_free_irq(arizona, jack_irq_rise, info);
err_input:
err_register:
pm_runtime_disable(&pdev->dev);
@ -541,6 +571,7 @@ static int arizona_extcon_remove(struct platform_device *pdev)
{
struct arizona_extcon_info *info = platform_get_drvdata(pdev);
struct arizona *arizona = info->arizona;
int jack_irq_rise, jack_irq_fall;
pm_runtime_disable(&pdev->dev);
@ -548,11 +579,20 @@ static int arizona_extcon_remove(struct platform_device *pdev)
ARIZONA_MICD_CLAMP_CONTROL,
ARIZONA_MICD_CLAMP_MODE_MASK, 0);
arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0);
arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0);
if (arizona->pdata.jd_gpio5) {
jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
} else {
jack_irq_rise = ARIZONA_IRQ_JD_RISE;
jack_irq_fall = ARIZONA_IRQ_JD_FALL;
}
arizona_set_irq_wake(arizona, jack_irq_rise, 0);
arizona_set_irq_wake(arizona, jack_irq_fall, 0);
arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info);
arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info);
arizona_free_irq(arizona, jack_irq_rise, info);
arizona_free_irq(arizona, jack_irq_fall, info);
regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
ARIZONA_JD1_ENA, 0);
arizona_clk32k_disable(arizona);

View File

@ -96,6 +96,9 @@ struct arizona_pdata {
/** Pin state for GPIO pins */
int gpio_defaults[ARIZONA_MAX_GPIO];
/** GPIO5 is used for jack detection */
bool jd_gpio5;
/** GPIO for mic detection polarity */
int micd_pol_gpio;