summaryrefslogtreecommitdiff
path: root/drivers/mfd/wm8994-core.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-04-14 13:18:27 +0200
committerIngo Molnar <mingo@kernel.org>2012-04-14 13:19:04 +0200
commit6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e (patch)
tree021cc9f6b477146fcebe6f3be4752abfa2ba18a9 /drivers/mfd/wm8994-core.c
parent682968e0c425c60f0dde37977e5beb2b12ddc4cc (diff)
parenta385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff)
Merge branch 'perf/core' into perf/uprobes
Merge in latest upstream (and the latest perf development tree), to prepare for tooling changes, and also to pick up v3.4 MM changes that the uprobes code needs to take care of. Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/mfd/wm8994-core.c')
-rw-r--r--drivers/mfd/wm8994-core.c108
1 files changed, 91 insertions, 17 deletions
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index f117e7fb9321..9d7ca1e978fa 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -256,6 +256,20 @@ static int wm8994_suspend(struct device *dev)
break;
}
+ switch (wm8994->type) {
+ case WM1811:
+ ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read jackdet: %d\n", ret);
+ } else if (ret & WM1811_JACKDET_MODE_MASK) {
+ dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
/* Disable LDO pulldowns while the device is suspended if we
* don't know that something will be driving them. */
if (!wm8994->ldo_ena_always_driven)
@@ -345,15 +359,38 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
}
#endif
+static const __devinitdata struct reg_default wm8994_revc_patch[] = {
+ { 0x102, 0x3 },
+ { 0x56, 0x3 },
+ { 0x817, 0x0 },
+ { 0x102, 0x0 },
+};
+
+static const __devinitdata struct reg_default wm8958_reva_patch[] = {
+ { 0x102, 0x3 },
+ { 0xcb, 0x81 },
+ { 0x817, 0x0 },
+ { 0x102, 0x0 },
+};
+
+static const __devinitdata struct reg_default wm1811_reva_patch[] = {
+ { 0x102, 0x3 },
+ { 0x56, 0x7 },
+ { 0x5d, 0x7e },
+ { 0x5e, 0x0 },
+ { 0x102, 0x0 },
+};
+
/*
* Instantiate the generic non-control parts of the device.
*/
-static int wm8994_device_init(struct wm8994 *wm8994, int irq)
+static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
{
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
struct regmap_config *regmap_config;
+ const struct reg_default *regmap_patch = NULL;
const char *devname;
- int ret, i;
+ int ret, i, patch_regs;
int pulls = 0;
dev_set_drvdata(wm8994->dev, wm8994);
@@ -365,7 +402,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
NULL, 0);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
- goto err_regmap;
+ goto err;
}
switch (wm8994->type) {
@@ -380,7 +417,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break;
default:
BUG();
- goto err_regmap;
+ goto err;
}
wm8994->supplies = devm_kzalloc(wm8994->dev,
@@ -388,7 +425,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
wm8994->num_supplies, GFP_KERNEL);
if (!wm8994->supplies) {
ret = -ENOMEM;
- goto err_regmap;
+ goto err;
}
switch (wm8994->type) {
@@ -406,14 +443,14 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break;
default:
BUG();
- goto err_regmap;
+ goto err;
}
ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
wm8994->supplies);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
- goto err_regmap;
+ goto err;
}
ret = regulator_bulk_enable(wm8994->num_supplies,
@@ -474,15 +511,44 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
"revision %c not fully supported\n",
'A' + wm8994->revision);
break;
+ case 2:
+ case 3:
+ regmap_patch = wm8994_revc_patch;
+ patch_regs = ARRAY_SIZE(wm8994_revc_patch);
+ break;
default:
break;
}
break;
+
+ case WM8958:
+ switch (wm8994->revision) {
+ case 0:
+ regmap_patch = wm8958_reva_patch;
+ patch_regs = ARRAY_SIZE(wm8958_reva_patch);
+ break;
+ default:
+ break;
+ }
+ break;
+
case WM1811:
/* Revision C did not change the relevant layer */
if (wm8994->revision > 1)
wm8994->revision++;
+ switch (wm8994->revision) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ regmap_patch = wm1811_reva_patch;
+ patch_regs = ARRAY_SIZE(wm1811_reva_patch);
+ break;
+ default:
+ break;
+ }
break;
+
default:
break;
}
@@ -512,6 +578,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
return ret;
}
+ if (regmap_patch) {
+ ret = regmap_register_patch(wm8994->regmap, regmap_patch,
+ patch_regs);
+ if (ret != 0) {
+ dev_err(wm8994->dev, "Failed to register patch: %d\n",
+ ret);
+ goto err;
+ }
+ }
+
if (pdata) {
wm8994->irq_base = pdata->irq_base;
wm8994->gpio_base = pdata->gpio_base;
@@ -563,7 +639,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
}
pm_runtime_enable(wm8994->dev);
- pm_runtime_resume(wm8994->dev);
+ pm_runtime_idle(wm8994->dev);
return 0;
@@ -574,13 +650,12 @@ err_enable:
wm8994->supplies);
err_get:
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
-err_regmap:
- regmap_exit(wm8994->regmap);
+err:
mfd_remove_devices(wm8994->dev);
return ret;
}
-static void wm8994_device_exit(struct wm8994 *wm8994)
+static __devexit void wm8994_device_exit(struct wm8994 *wm8994)
{
pm_runtime_disable(wm8994->dev);
mfd_remove_devices(wm8994->dev);
@@ -588,7 +663,6 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
regulator_bulk_disable(wm8994->num_supplies,
wm8994->supplies);
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
- regmap_exit(wm8994->regmap);
}
static const struct of_device_id wm8994_of_match[] = {
@@ -599,8 +673,8 @@ static const struct of_device_id wm8994_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8994_of_match);
-static int wm8994_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static __devinit int wm8994_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8994 *wm8994;
int ret;
@@ -614,7 +688,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
wm8994->irq = i2c->irq;
wm8994->type = id->driver_data;
- wm8994->regmap = regmap_init_i2c(i2c, &wm8994_base_regmap_config);
+ wm8994->regmap = devm_regmap_init_i2c(i2c, &wm8994_base_regmap_config);
if (IS_ERR(wm8994->regmap)) {
ret = PTR_ERR(wm8994->regmap);
dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
@@ -625,7 +699,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
return wm8994_device_init(wm8994, i2c->irq);
}
-static int wm8994_i2c_remove(struct i2c_client *i2c)
+static __devexit int wm8994_i2c_remove(struct i2c_client *i2c)
{
struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
@@ -654,7 +728,7 @@ static struct i2c_driver wm8994_i2c_driver = {
.of_match_table = wm8994_of_match,
},
.probe = wm8994_i2c_probe,
- .remove = wm8994_i2c_remove,
+ .remove = __devexit_p(wm8994_i2c_remove),
.id_table = wm8994_i2c_id,
};