Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 363180
b: refs/heads/master
c: 6fed4d8
h: refs/heads/master
v: v3
  • Loading branch information
Mark Brown committed Apr 2, 2013
1 parent 192dea9 commit 825e0c8
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 40 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: 84eaa13616b6e7d001b7f7b909228087779b677b
refs/heads/master: 6fed4d869a11fdbb4c6a5e444dfb2c22f92c3e46
164 changes: 125 additions & 39 deletions trunk/drivers/extcon/extcon-arizona.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>

#define ARIZONA_NUM_BUTTONS 6
#define ARIZONA_MAX_MICD_RANGE 8

#define ARIZONA_ACCDET_MODE_MIC 0
#define ARIZONA_ACCDET_MODE_HPL 1
Expand All @@ -50,6 +50,9 @@ struct arizona_extcon_info {
const struct arizona_micd_config *micd_modes;
int micd_num_modes;

const struct arizona_micd_range *micd_ranges;
int num_micd_ranges;

bool micd_reva;
bool micd_clamp;

Expand All @@ -71,20 +74,25 @@ struct arizona_extcon_info {
};

static const struct arizona_micd_config micd_default_modes[] = {
{ 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
{ ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 },
{ 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 },
static const struct arizona_micd_range micd_default_ranges[] = {
{ .max = 11, .key = BTN_0 },
{ .max = 28, .key = BTN_1 },
{ .max = 54, .key = BTN_2 },
{ .max = 100, .key = BTN_3 },
{ .max = 186, .key = BTN_4 },
{ .max = 430, .key = BTN_5 },
};

static const int arizona_micd_levels[] = {
3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
1257,
};

#define ARIZONA_CABLE_MECHANICAL 0
Expand Down Expand Up @@ -153,7 +161,7 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
{
struct arizona *arizona = info->arizona;

mode %= info->num_micd_modes;
mode %= info->micd_num_modes;

if (arizona->pdata.micd_pol_gpio > 0)
gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
Expand Down Expand Up @@ -728,7 +736,7 @@ static irqreturn_t arizona_micdet(int irq, void *data)
struct arizona_extcon_info *info = data;
struct arizona *arizona = info->arizona;
unsigned int val, lvl;
int ret, i;
int ret, i, key;

mutex_lock(&info->lock);

Expand Down Expand Up @@ -815,12 +823,13 @@ static irqreturn_t arizona_micdet(int irq, void *data)
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);
WARN_ON(!lvl);
WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
key = info->micd_ranges[ffs(lvl) - 1].key;
input_report_key(info->input, key, 1);
input_sync(info->input);
}

} else if (info->detecting) {
dev_dbg(arizona->dev, "Headphone detected\n");
Expand All @@ -834,9 +843,9 @@ 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++)
for (i = 0; i < info->num_micd_ranges; i++)
input_report_key(info->input,
arizona_lvl_to_key[i].report, 0);
info->micd_ranges[i].key, 0);
input_sync(info->input);
arizona_extcon_pulse_micbias(info);
}
Expand Down Expand Up @@ -923,9 +932,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
info->mic = false;
info->hpdet_done = false;

for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
for (i = 0; i < info->num_micd_ranges; i++)
input_report_key(info->input,
arizona_lvl_to_key[i].report, 0);
info->micd_ranges[i].key, 0);
input_sync(info->input);

ret = extcon_update_state(&info->edev, 0xffffffff, 0);
Expand Down Expand Up @@ -954,13 +963,33 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
return IRQ_HANDLED;
}

/* Map a level onto a slot in the register bank */
static void arizona_micd_set_level(struct arizona *arizona, int index,
unsigned int level)
{
int reg;
unsigned int mask;

reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);

if (!(index % 2)) {
mask = 0x3f00;
level <<= 8;
} else {
mask = 0x3f;
}

/* Program the level itself */
regmap_update_bits(arizona->regmap, reg, mask, level);
}

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;
int ret, mode, i, j;

if (!arizona->dapm || !arizona->dapm->card)
return -EPROBE_DEFER;
Expand Down Expand Up @@ -1013,6 +1042,17 @@ static int arizona_extcon_probe(struct platform_device *pdev)
goto err;
}

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

info->input->name = "Headset";
info->input->phys = "arizona/extcon";
info->input->dev.parent = &pdev->dev;

if (pdata->num_micd_configs) {
info->micd_modes = pdata->micd_configs;
info->micd_num_modes = pdata->num_micd_configs;
Expand Down Expand Up @@ -1068,6 +1108,66 @@ static int arizona_extcon_probe(struct platform_device *pdev)
arizona->pdata.micd_dbtime
<< ARIZONA_MICD_DBTIME_SHIFT);

BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);

if (arizona->pdata.num_micd_ranges) {
info->micd_ranges = pdata->micd_ranges;
info->num_micd_ranges = pdata->num_micd_ranges;
} else {
info->micd_ranges = micd_default_ranges;
info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
}

if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
dev_err(arizona->dev, "Too many MICD ranges: %d\n",
arizona->pdata.num_micd_ranges);
}

if (info->num_micd_ranges > 1) {
for (i = 1; i < info->num_micd_ranges; i++) {
if (info->micd_ranges[i - 1].max >
info->micd_ranges[i].max) {
dev_err(arizona->dev,
"MICD ranges must be sorted\n");
ret = -EINVAL;
goto err_input;
}
}
}

/* Disable all buttons by default */
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
ARIZONA_MICD_LVL_SEL_MASK, 0x81);

/* Set up all the buttons the user specified */
for (i = 0; i < info->num_micd_ranges; i++) {
for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++)
if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
break;

if (j == ARRAY_SIZE(arizona_micd_levels)) {
dev_err(arizona->dev, "Unsupported MICD level %d\n",
info->micd_ranges[i].max);
ret = -EINVAL;
goto err_input;
}

dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
arizona_micd_levels[j], i);

arizona_micd_set_level(arizona, i, j);
input_set_capability(info->input, EV_KEY,
info->micd_ranges[i].key);

/* Enable reporting of that range */
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
1 << i, 1 << i);
}

/* Set all the remaining keys to a maximum */
for (; i < ARIZONA_MAX_MICD_RANGE; i++)
arizona_micd_set_level(arizona, i, 0x3f);

/*
* If we have a clamp use it, activating in conjunction with
* GPIO5 if that is connected for jack detect operation.
Expand Down Expand Up @@ -1095,20 +1195,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)

arizona_extcon_set_mode(info, 0);

info->input = devm_input_allocate_device(&pdev->dev);
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 Down
9 changes: 9 additions & 0 deletions trunk/include/linux/mfd/arizona/pdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ struct arizona_micd_config {
bool gpio;
};

struct arizona_micd_range {
int max; /** Ohms */
int key; /** Key to report to input layer */
};

struct arizona_pdata {
int reset; /** GPIO controlling /RESET, if any */
int ldoena; /** GPIO controlling LODENA, if any */
Expand Down Expand Up @@ -138,6 +143,10 @@ struct arizona_pdata {
/** Force MICBIAS on for mic detect */
bool micd_force_micbias;

/** Mic detect level parameters */
const struct arizona_micd_range *micd_ranges;
int num_micd_ranges;

/** Headset polarity configurations */
struct arizona_micd_config *micd_configs;
int num_micd_configs;
Expand Down

0 comments on commit 825e0c8

Please sign in to comment.