Merge tag 'mfd_3.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / mfd / wm8994-core.c
index a04b3c108c8ca38a06f54ac946f77ce4ec920f0c..9d7ca1e978fad30775d1de8b6913333a137118c6 100644 (file)
@@ -359,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);
@@ -379,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) {
@@ -394,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,
@@ -402,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) {
@@ -420,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,
@@ -488,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;
        }
@@ -526,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;
@@ -577,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;
 
@@ -588,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);
@@ -602,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[] = {
@@ -613,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;
@@ -628,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",
@@ -639,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);
 
@@ -668,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,
 };