]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - sound/soc/codecs/wm9090.c
ASoC: multi-component - ASoC Multi-Component Support
[mv-sheeva.git] / sound / soc / codecs / wm9090.c
index 1592250daec0ff0eda0896536d2a8d1234951b17..7a1825418ee49a47d0d4bcbbb8ce8b28d298b143 100644 (file)
@@ -34,8 +34,6 @@
 
 #include "wm9090.h"
 
-static struct snd_soc_codec *wm9090_codec;
-
 static const u16 wm9090_reg_defaults[] = {
        0x9093,     /* R0   - Software Reset */
        0x0006,     /* R1   - Power Management (1) */
@@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = {
 
 /* This struct is used to save the context */
 struct wm9090_priv {
-       /* We're not really registering as a CODEC since ASoC core
-        * does not yet support multiple CODECs but having the CODEC
-        * structure means we can reuse some of the ASoC core
-        * features.
-        */
-       struct snd_soc_codec codec;
        struct mutex mutex;
        u16 reg_cache[WM9090_MAX_REGISTER + 1];
        struct wm9090_platform_data pdata;
+       void *control_data;
 };
 
 static int wm9090_volatile(unsigned int reg)
@@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Restore the register cache */
-                       for (i = 1; i < codec->reg_cache_size; i++) {
+                       for (i = 1; i < codec->driver->reg_cache_size; i++) {
                                if (reg_cache[i] == wm9090_reg_defaults[i])
                                        continue;
                                if (wm9090_volatile(i))
@@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm9090_probe(struct platform_device *pdev)
+static int wm9090_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
+       struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
-       if (wm9090_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
+       codec->control_data = wm9090->control_data;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
-       socdev->card->codec = wm9090_codec;
-       codec = wm9090_codec;
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
-               goto pcm_err;
+       ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
+       if (ret < 0)
+               return ret;
+       if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
+               dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
+               return -EINVAL;
        }
 
+       ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Configure some defaults; they will be written out when we
+        * bring the bias up.
+        */
+       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
+               | WM9090_IN1A_ZC;
+       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
+               | WM9090_IN1B_ZC;
+       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
+               | WM9090_IN2A_ZC;
+       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
+               | WM9090_IN2B_ZC;
+       wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
+               WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
+       wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
+               WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
+       wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
+               WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
+
+       wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
+
+       wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
        wm9090_add_controls(codec);
 
        return 0;
-
-pcm_err:
-       return ret;
 }
 
 #ifdef CONFIG_PM
-static int wm9090_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm9090_resume(struct platform_device *pdev)
+static int wm9090_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev)
 #define wm9090_resume NULL
 #endif
 
-static int wm9090_remove(struct platform_device *pdev)
+static int wm9090_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm9090 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
        .probe =        wm9090_probe,
        .remove =       wm9090_remove,
        .suspend =      wm9090_suspend,
        .resume =       wm9090_resume,
+       .set_bias_level = wm9090_set_bias_level,
+       .reg_cache_size = (WM9090_MAX_REGISTER + 1),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm9090_reg_defaults,
+       .volatile_register = wm9090_volatile,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090);
 
 static int wm9090_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm9090_priv *wm9090;
-       struct snd_soc_codec *codec;
        int ret;
 
        wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL);
@@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
                dev_err(&i2c->dev, "Can not allocate memory\n");
                return -ENOMEM;
        }
-       codec = &wm9090->codec;
 
        if (i2c->dev.platform_data)
                memcpy(&wm9090->pdata, i2c->dev.platform_data,
                       sizeof(wm9090->pdata));
 
-       wm9090_codec = codec;
-
        i2c_set_clientdata(i2c, wm9090);
+       wm9090->control_data = i2c;
+       mutex_init(&wm9090->mutex);
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->control_data = i2c;
-       snd_soc_codec_set_drvdata(codec, wm9090);
-       codec->dev = &i2c->dev;
-       codec->name = "WM9090";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm9090_set_bias_level,
-       codec->reg_cache_size = WM9090_MAX_REGISTER + 1;
-       codec->reg_cache = &wm9090->reg_cache;
-       codec->volatile_register = wm9090_volatile;
-
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
-       }
-
-       memcpy(&wm9090->reg_cache, wm9090_reg_defaults,
-              sizeof(wm9090->reg_cache));
-
-       ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
-       if (ret < 0)
-               goto err;
-       if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
-               dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret);
-               ret = -EINVAL;
-               goto err;
-       }
-
-       ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm9090,  NULL, 0);
        if (ret < 0)
-               goto err;
-
-       /* Configure some defaults; they will be written out when we
-        * bring the bias up.
-        */
-       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
-               | WM9090_IN1A_ZC;
-       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
-               | WM9090_IN1B_ZC;
-       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
-               | WM9090_IN2A_ZC;
-       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
-               | WM9090_IN2B_ZC;
-       wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
-               WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
-       wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= 
-               WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
-       wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
-               WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
-
-       wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
-
-       wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
-               goto err_bias;
-       }
-
-       return 0;
-
-err_bias:
-       wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
-err:
-       kfree(wm9090);
-       i2c_set_clientdata(i2c, NULL);
-       wm9090_codec = NULL;
-
+               kfree(wm9090);
        return ret;
 }
 
 static int wm9090_i2c_remove(struct i2c_client *i2c)
 {
        struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
-       struct snd_soc_codec *codec = &wm9090->codec;
 
-       snd_soc_unregister_codec(codec);
-       wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       snd_soc_unregister_codec(&i2c->dev);
        kfree(wm9090);
-       wm9090_codec = NULL;
 
        return 0;
 }
@@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id);
 
 static struct i2c_driver wm9090_i2c_driver = {
        .driver = {
-               .name = "wm9090",
+               .name = "wm9090-codec",
                .owner = THIS_MODULE,
        },
        .probe = wm9090_i2c_probe,