diff options
Diffstat (limited to 'drivers/extcon/extcon-arizona.c')
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 76 |
1 files changed, 58 insertions, 18 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 3ef3bee7d1e6..b5190a811601 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -290,13 +290,21 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
290 | { | 290 | { |
291 | struct arizona_extcon_info *info = data; | 291 | struct arizona_extcon_info *info = data; |
292 | struct arizona *arizona = info->arizona; | 292 | struct arizona *arizona = info->arizona; |
293 | unsigned int val; | 293 | unsigned int val, present, mask; |
294 | int ret, i; | 294 | int ret, i; |
295 | 295 | ||
296 | pm_runtime_get_sync(info->dev); | 296 | pm_runtime_get_sync(info->dev); |
297 | 297 | ||
298 | mutex_lock(&info->lock); | 298 | mutex_lock(&info->lock); |
299 | 299 | ||
300 | if (arizona->pdata.jd_gpio5) { | ||
301 | mask = ARIZONA_MICD_CLAMP_STS; | ||
302 | present = 0; | ||
303 | } else { | ||
304 | mask = ARIZONA_JD1_STS; | ||
305 | present = ARIZONA_JD1_STS; | ||
306 | } | ||
307 | |||
300 | ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); | 308 | ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); |
301 | if (ret != 0) { | 309 | if (ret != 0) { |
302 | dev_err(arizona->dev, "Failed to read jackdet status: %d\n", | 310 | dev_err(arizona->dev, "Failed to read jackdet status: %d\n", |
@@ -306,7 +314,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
306 | return IRQ_NONE; | 314 | return IRQ_NONE; |
307 | } | 315 | } |
308 | 316 | ||
309 | if (val & ARIZONA_JD1_STS) { | 317 | if ((val & mask) == present) { |
310 | dev_dbg(arizona->dev, "Detected jack\n"); | 318 | dev_dbg(arizona->dev, "Detected jack\n"); |
311 | ret = extcon_set_cable_state_(&info->edev, | 319 | ret = extcon_set_cable_state_(&info->edev, |
312 | ARIZONA_CABLE_MECHANICAL, true); | 320 | ARIZONA_CABLE_MECHANICAL, true); |
@@ -321,6 +329,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
321 | 329 | ||
322 | arizona_stop_mic(info); | 330 | arizona_stop_mic(info); |
323 | 331 | ||
332 | |||
324 | for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) | 333 | for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) |
325 | input_report_key(info->input, | 334 | input_report_key(info->input, |
326 | arizona_lvl_to_key[i].report, 0); | 335 | arizona_lvl_to_key[i].report, 0); |
@@ -345,6 +354,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
345 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 354 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
346 | struct arizona_pdata *pdata; | 355 | struct arizona_pdata *pdata; |
347 | struct arizona_extcon_info *info; | 356 | struct arizona_extcon_info *info; |
357 | int jack_irq_fall, jack_irq_rise; | ||
348 | int ret, mode, i; | 358 | int ret, mode, i; |
349 | 359 | ||
350 | pdata = dev_get_platdata(arizona->dev); | 360 | pdata = dev_get_platdata(arizona->dev); |
@@ -426,12 +436,24 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
426 | << ARIZONA_MICD_BIAS_STARTTIME_SHIFT); | 436 | << ARIZONA_MICD_BIAS_STARTTIME_SHIFT); |
427 | 437 | ||
428 | /* | 438 | /* |
429 | * If we have a clamp use it. | 439 | * If we have a clamp use it, activating in conjunction with |
440 | * GPIO5 if that is connected for jack detect operation. | ||
430 | */ | 441 | */ |
431 | if (info->micd_clamp) { | 442 | if (info->micd_clamp) { |
432 | regmap_update_bits(arizona->regmap, | 443 | if (arizona->pdata.jd_gpio5) { |
433 | ARIZONA_MICD_CLAMP_CONTROL, | 444 | /* Put the GPIO into input mode */ |
434 | ARIZONA_MICD_CLAMP_MODE_MASK, 4); | 445 | regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL, |
446 | 0xc101); | ||
447 | |||
448 | regmap_update_bits(arizona->regmap, | ||
449 | ARIZONA_MICD_CLAMP_CONTROL, | ||
450 | ARIZONA_MICD_CLAMP_MODE_MASK, 0x9); | ||
451 | } else { | ||
452 | regmap_update_bits(arizona->regmap, | ||
453 | ARIZONA_MICD_CLAMP_CONTROL, | ||
454 | ARIZONA_MICD_CLAMP_MODE_MASK, 0x4); | ||
455 | } | ||
456 | |||
435 | regmap_update_bits(arizona->regmap, | 457 | regmap_update_bits(arizona->regmap, |
436 | ARIZONA_JACK_DETECT_DEBOUNCE, | 458 | ARIZONA_JACK_DETECT_DEBOUNCE, |
437 | ARIZONA_MICD_CLAMP_DB, | 459 | ARIZONA_MICD_CLAMP_DB, |
@@ -458,7 +480,15 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
458 | pm_runtime_idle(&pdev->dev); | 480 | pm_runtime_idle(&pdev->dev); |
459 | pm_runtime_get_sync(&pdev->dev); | 481 | pm_runtime_get_sync(&pdev->dev); |
460 | 482 | ||
461 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_RISE, | 483 | if (arizona->pdata.jd_gpio5) { |
484 | jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; | ||
485 | jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; | ||
486 | } else { | ||
487 | jack_irq_rise = ARIZONA_IRQ_JD_RISE; | ||
488 | jack_irq_fall = ARIZONA_IRQ_JD_FALL; | ||
489 | } | ||
490 | |||
491 | ret = arizona_request_irq(arizona, jack_irq_rise, | ||
462 | "JACKDET rise", arizona_jackdet, info); | 492 | "JACKDET rise", arizona_jackdet, info); |
463 | if (ret != 0) { | 493 | if (ret != 0) { |
464 | dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", | 494 | 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) | |||
466 | goto err_input; | 496 | goto err_input; |
467 | } | 497 | } |
468 | 498 | ||
469 | ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1); | 499 | ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); |
470 | if (ret != 0) { | 500 | if (ret != 0) { |
471 | dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", | 501 | dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", |
472 | ret); | 502 | ret); |
473 | goto err_rise; | 503 | goto err_rise; |
474 | } | 504 | } |
475 | 505 | ||
476 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_FALL, | 506 | ret = arizona_request_irq(arizona, jack_irq_fall, |
477 | "JACKDET fall", arizona_jackdet, info); | 507 | "JACKDET fall", arizona_jackdet, info); |
478 | if (ret != 0) { | 508 | if (ret != 0) { |
479 | dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); | 509 | dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); |
480 | goto err_rise_wake; | 510 | goto err_rise_wake; |
481 | } | 511 | } |
482 | 512 | ||
483 | ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 1); | 513 | ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1); |
484 | if (ret != 0) { | 514 | if (ret != 0) { |
485 | dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", | 515 | dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", |
486 | ret); | 516 | ret); |
@@ -522,13 +552,13 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
522 | err_micdet: | 552 | err_micdet: |
523 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); | 553 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); |
524 | err_fall_wake: | 554 | err_fall_wake: |
525 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); | 555 | arizona_set_irq_wake(arizona, jack_irq_fall, 0); |
526 | err_fall: | 556 | err_fall: |
527 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info); | 557 | arizona_free_irq(arizona, jack_irq_fall, info); |
528 | err_rise_wake: | 558 | err_rise_wake: |
529 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); | 559 | arizona_set_irq_wake(arizona, jack_irq_rise, 0); |
530 | err_rise: | 560 | err_rise: |
531 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); | 561 | arizona_free_irq(arizona, jack_irq_rise, info); |
532 | err_input: | 562 | err_input: |
533 | err_register: | 563 | err_register: |
534 | pm_runtime_disable(&pdev->dev); | 564 | pm_runtime_disable(&pdev->dev); |
@@ -541,6 +571,7 @@ static int arizona_extcon_remove(struct platform_device *pdev) | |||
541 | { | 571 | { |
542 | struct arizona_extcon_info *info = platform_get_drvdata(pdev); | 572 | struct arizona_extcon_info *info = platform_get_drvdata(pdev); |
543 | struct arizona *arizona = info->arizona; | 573 | struct arizona *arizona = info->arizona; |
574 | int jack_irq_rise, jack_irq_fall; | ||
544 | 575 | ||
545 | pm_runtime_disable(&pdev->dev); | 576 | pm_runtime_disable(&pdev->dev); |
546 | 577 | ||
@@ -548,11 +579,20 @@ static int arizona_extcon_remove(struct platform_device *pdev) | |||
548 | ARIZONA_MICD_CLAMP_CONTROL, | 579 | ARIZONA_MICD_CLAMP_CONTROL, |
549 | ARIZONA_MICD_CLAMP_MODE_MASK, 0); | 580 | ARIZONA_MICD_CLAMP_MODE_MASK, 0); |
550 | 581 | ||
551 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); | 582 | if (arizona->pdata.jd_gpio5) { |
552 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); | 583 | jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; |
584 | jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; | ||
585 | } else { | ||
586 | jack_irq_rise = ARIZONA_IRQ_JD_RISE; | ||
587 | jack_irq_fall = ARIZONA_IRQ_JD_FALL; | ||
588 | } | ||
589 | |||
590 | arizona_set_irq_wake(arizona, jack_irq_rise, 0); | ||
591 | arizona_set_irq_wake(arizona, jack_irq_fall, 0); | ||
592 | arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info); | ||
553 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); | 593 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); |
554 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); | 594 | arizona_free_irq(arizona, jack_irq_rise, info); |
555 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info); | 595 | arizona_free_irq(arizona, jack_irq_fall, info); |
556 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, | 596 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, |
557 | ARIZONA_JD1_ENA, 0); | 597 | ARIZONA_JD1_ENA, 0); |
558 | arizona_clk32k_disable(arizona); | 598 | arizona_clk32k_disable(arizona); |