Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 324360
b: refs/heads/master
c: 34efe4d
h: refs/heads/master
v: v3
  • Loading branch information
Mark Brown authored and Greg Kroah-Hartman committed Aug 16, 2012
1 parent 0ebf2f1 commit fc0b0c8
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 689ae231afbac8979f96100b372a5a73458baaa9
refs/heads/master: 34efe4dc47227264a38e60c878b4831d5f0d5a33
72 changes: 65 additions & 7 deletions trunk/drivers/extcon/extcon-arizona.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
Expand All @@ -30,11 +31,14 @@
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>

#define ARIZONA_NUM_BUTTONS 6

struct arizona_extcon_info {
struct device *dev;
struct arizona *arizona;
struct mutex lock;
struct regulator *micvdd;
struct input_dev *input;

int micd_mode;
const struct arizona_micd_config *micd_modes;
Expand All @@ -54,6 +58,18 @@ static const struct arizona_micd_config micd_default_modes[] = {
{ 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
};

static struct {
u16 status;
int report;
} arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = {
{ 0x1, BTN_0 },
{ 0x2, BTN_1 },
{ 0x4, BTN_2 },
{ 0x8, BTN_3 },
{ 0x10, BTN_4 },
{ 0x20, BTN_5 },
};

#define ARIZONA_CABLE_MECHANICAL 0
#define ARIZONA_CABLE_MICROPHONE 1
#define ARIZONA_CABLE_HEADPHONE 2
Expand Down Expand Up @@ -133,6 +149,7 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)

if (change) {
regulator_disable(info->micvdd);
pm_runtime_mark_last_busy(info->dev);
pm_runtime_put_autosuspend(info->dev);
}
}
Expand All @@ -141,8 +158,8 @@ static irqreturn_t arizona_micdet(int irq, void *data)
{
struct arizona_extcon_info *info = data;
struct arizona *arizona = info->arizona;
unsigned int val;
int ret;
unsigned int val, lvl;
int ret, i;

mutex_lock(&info->lock);

Expand Down Expand Up @@ -219,13 +236,22 @@ static irqreturn_t arizona_micdet(int irq, void *data)

/*
* If we're still detecting and we detect a short then we've
* got a headphone. Otherwise it's a button press, the
* button reporting is stubbed out for now.
* got a headphone. Otherwise it's a button press.
*/
if (val & 0x3fc) {
if (info->mic) {
dev_dbg(arizona->dev, "Mic button detected\n");

lvl = val & ARIZONA_MICD_LVL_MASK;
lvl >>= ARIZONA_MICD_LVL_SHIFT;

for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
if (lvl & arizona_lvl_to_key[i].status)
input_report_key(info->input,
arizona_lvl_to_key[i].report,
1);
input_sync(info->input);

} else if (info->detecting) {
dev_dbg(arizona->dev, "Headphone detected\n");
info->detecting = false;
Expand All @@ -244,6 +270,10 @@ static irqreturn_t arizona_micdet(int irq, void *data)
}
} else {
dev_dbg(arizona->dev, "Mic button released\n");
for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
input_report_key(info->input,
arizona_lvl_to_key[i].report, 0);
input_sync(info->input);
}

handled:
Expand All @@ -258,7 +288,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
struct arizona_extcon_info *info = data;
struct arizona *arizona = info->arizona;
unsigned int val;
int ret;
int ret, i;

pm_runtime_get_sync(info->dev);

Expand Down Expand Up @@ -288,6 +318,11 @@ 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);
input_sync(info->input);

ret = extcon_update_state(&info->edev, 0xffffffff, 0);
if (ret != 0)
dev_err(arizona->dev, "Removal report failed: %d\n",
Expand All @@ -307,7 +342,7 @@ static int __devinit 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 ret, mode;
int ret, mode, i;

pdata = dev_get_platdata(arizona->dev);

Expand Down Expand Up @@ -382,6 +417,20 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)

arizona_extcon_set_mode(info, 0);

info->input = input_allocate_device();
if (!info->input) {
dev_err(arizona->dev, "Can't allocate input dev\n");
ret = -ENOMEM;
goto err_register;
}

for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
input_set_capability(info->input, EV_KEY,
arizona_lvl_to_key[i].report);
info->input->name = "Headset";
info->input->phys = "arizona/extcon";
info->input->dev.parent = &pdev->dev;

pm_runtime_enable(&pdev->dev);
pm_runtime_idle(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
Expand All @@ -391,7 +440,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
if (ret != 0) {
dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
ret);
goto err_register;
goto err_input;
}

ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1);
Expand Down Expand Up @@ -436,6 +485,12 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)

pm_runtime_put(&pdev->dev);

ret = input_register_device(info->input);
if (ret) {
dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
goto err_fall_wake;
}

return 0;

err_fall_wake:
Expand All @@ -446,6 +501,8 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0);
err_rise:
arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info);
err_input:
input_free_device(info->input);
err_register:
pm_runtime_disable(&pdev->dev);
extcon_dev_unregister(&info->edev);
Expand All @@ -468,6 +525,7 @@ static int __devexit arizona_extcon_remove(struct platform_device *pdev)
regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
ARIZONA_JD1_ENA, 0);
arizona_clk32k_disable(arizona);
input_unregister_device(info->input);
extcon_dev_unregister(&info->edev);

return 0;
Expand Down

0 comments on commit fc0b0c8

Please sign in to comment.