ASoC/mpc5200: Track DMA position by period number instead of bytes
[safe/jmp/linux-2.6] / sound / soc / codecs / wm8731.c
index d3fd4f2..e3675e7 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 static struct snd_soc_codec *wm8731_codec;
 struct snd_soc_codec_device soc_codec_dev_wm8731;
 
+#define WM8731_NUM_SUPPLIES 4
+static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
+       "AVDD",
+       "HPVDD",
+       "DCVDD",
+       "DBVDD",
+};
+
 /* codec private data */
 struct wm8731_priv {
        struct snd_soc_codec codec;
+       struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
        u16 reg_cache[WM8731_CACHEREGNUM];
        unsigned int sysclk;
 };
@@ -422,9 +432,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8731_priv *wm8731 = codec->private_data;
 
        snd_soc_write(codec, WM8731_ACTIVE, 0x0);
        wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
+                              wm8731->supplies);
        return 0;
 }
 
@@ -432,10 +445,16 @@ static int wm8731_resume(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->card->codec;
-       int i;
+       struct wm8731_priv *wm8731 = codec->private_data;
+       int i, ret;
        u8 data[2];
        u16 *cache = codec->reg_cache;
 
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
+                                   wm8731->supplies);
+       if (ret != 0)
+               return ret;
+
        /* Sync reg_cache with the hardware */
        for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
                data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
@@ -444,6 +463,7 @@ static int wm8731_resume(struct platform_device *pdev)
        }
        wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        wm8731_set_bias_level(codec, codec->suspend_bias_level);
+
        return 0;
 }
 #else
@@ -475,17 +495,9 @@ static int wm8731_probe(struct platform_device *pdev)
        snd_soc_add_controls(codec, wm8731_snd_controls,
                             ARRAY_SIZE(wm8731_snd_controls));
        wm8731_add_widgets(codec);
-       ret = snd_soc_init_card(socdev);
-       if (ret < 0) {
-               dev_err(codec->dev, "failed to register card: %d\n", ret);
-               goto card_err;
-       }
 
        return ret;
 
-card_err:
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
 pcm_err:
        return ret;
 }
@@ -512,7 +524,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
 static int wm8731_register(struct wm8731_priv *wm8731,
                           enum snd_soc_control_type control)
 {
-       int ret;
+       int ret, i;
        struct snd_soc_codec *codec = &wm8731->codec;
 
        if (wm8731_codec) {
@@ -543,10 +555,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
                goto err;
        }
 
+       for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
+               wm8731->supplies[i].supply = wm8731_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
+                                wm8731->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
+                                   wm8731->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_regulator_get;
+       }
+
        ret = wm8731_reset(codec);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
-               goto err;
+               goto err_regulator_enable;
        }
 
        wm8731_dai.dev = codec->dev;
@@ -567,7 +596,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
        ret = snd_soc_register_codec(codec);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err;
+               goto err_regulator_enable;
        }
 
        ret = snd_soc_register_dai(&wm8731_dai);
@@ -581,6 +610,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
 
 err_codec:
        snd_soc_unregister_codec(codec);
+err_regulator_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
+err_regulator_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
 err:
        kfree(wm8731);
        return ret;
@@ -591,6 +624,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
        wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
        snd_soc_unregister_dai(&wm8731_dai);
        snd_soc_unregister_codec(&wm8731->codec);
+       regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
+       regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
        kfree(wm8731);
        wm8731_codec = NULL;
 }
@@ -623,21 +658,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
-{
-       return snd_soc_suspend_device(&spi->dev);
-}
-
-static int wm8731_spi_resume(struct spi_device *spi)
-{
-       return snd_soc_resume_device(&spi->dev);
-}
-#else
-#define wm8731_spi_suspend NULL
-#define wm8731_spi_resume NULL
-#endif
-
 static struct spi_driver wm8731_spi_driver = {
        .driver = {
                .name   = "wm8731",
@@ -645,8 +665,6 @@ static struct spi_driver wm8731_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = wm8731_spi_probe,
-       .suspend        = wm8731_spi_suspend,
-       .resume         = wm8731_spi_resume,
        .remove         = __devexit_p(wm8731_spi_remove),
 };
 #endif /* CONFIG_SPI_MASTER */
@@ -679,21 +697,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
-{
-       return snd_soc_suspend_device(&i2c->dev);
-}
-
-static int wm8731_i2c_resume(struct i2c_client *i2c)
-{
-       return snd_soc_resume_device(&i2c->dev);
-}
-#else
-#define wm8731_i2c_suspend NULL
-#define wm8731_i2c_resume NULL
-#endif
-
 static const struct i2c_device_id wm8731_i2c_id[] = {
        { "wm8731", 0 },
        { }
@@ -707,8 +710,6 @@ static struct i2c_driver wm8731_i2c_driver = {
        },
        .probe =    wm8731_i2c_probe,
        .remove =   __devexit_p(wm8731_i2c_remove),
-       .suspend =  wm8731_i2c_suspend,
-       .resume =   wm8731_i2c_resume,
        .id_table = wm8731_i2c_id,
 };
 #endif