]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - sound/soc/codecs/tlv320dac33.c
ASoC: multi-component - ASoC Multi-Component Support
[mv-sheeva.git] / sound / soc / codecs / tlv320dac33.c
index 8651b01ed22358a636abdd7ba2c63e051ae95461..a3c5b521da6a5740a9bf27cf34da2a43668ee4f9 100644 (file)
@@ -66,8 +66,6 @@
 static void dac33_calculate_times(struct snd_pcm_substream *substream);
 static int dac33_prepare_chip(struct snd_pcm_substream *substream);
 
-static struct snd_soc_codec *tlv320dac33_codec;
-
 enum dac33_state {
        DAC33_IDLE = 0,
        DAC33_PREFILL,
@@ -93,7 +91,7 @@ struct tlv320dac33_priv {
        struct mutex mutex;
        struct workqueue_struct *dac33_wq;
        struct work_struct work;
-       struct snd_soc_codec codec;
+       struct snd_soc_codec *codec;
        struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES];
        struct snd_pcm_substream *substream;
        int power_gpio;
@@ -128,6 +126,8 @@ struct tlv320dac33_priv {
        unsigned int uthr;
 
        enum dac33_state state;
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
 static const u8 dac33_reg[DAC33_CACHEREGNUM] = {
@@ -650,9 +650,7 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
 
 static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
 {
-       struct snd_soc_codec *codec;
-
-       codec = &dac33->codec;
+       struct snd_soc_codec *codec = dac33->codec;
 
        switch (dac33->fifo_mode) {
        case DAC33_FIFO_MODE1:
@@ -695,9 +693,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
 
 static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33)
 {
-       struct snd_soc_codec *codec;
-
-       codec = &dac33->codec;
+       struct snd_soc_codec *codec = dac33->codec;
 
        switch (dac33->fifo_mode) {
        case DAC33_FIFO_MODE1:
@@ -726,7 +722,7 @@ static void dac33_work(struct work_struct *work)
        u8 reg;
 
        dac33 = container_of(work, struct tlv320dac33_priv, work);
-       codec = &dac33->codec;
+       codec = dac33->codec;
 
        mutex_lock(&dac33->mutex);
        switch (dac33->state) {
@@ -787,8 +783,7 @@ static int dac33_startup(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
        /* Stream started, save the substream pointer */
@@ -801,8 +796,7 @@ static void dac33_shutdown(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
        dac33->substream = NULL;
@@ -817,8 +811,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* Check parameters for validity */
        switch (params_rate(params)) {
@@ -856,8 +849,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
 static int dac33_prepare_chip(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;
        u8 aictrl_a, aictrl_b, fifoctrl_a;
@@ -1049,8 +1041,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
 static void dac33_calculate_times(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        unsigned int period_size = substream->runtime->period_size;
        unsigned int rate = substream->runtime->rate;
@@ -1129,8 +1120,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
                             struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
@@ -1163,8 +1153,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
                        struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        unsigned long long t0, t1, t_now;
        unsigned int time_delta, uthr;
@@ -1389,24 +1378,47 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
-static int dac33_soc_probe(struct platform_device *pdev)
+static int dac33_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct tlv320dac33_priv *dac33;
+       struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       BUG_ON(!tlv320dac33_codec);
+       codec->control_data = dac33->control_data;
+       codec->hw_write = (hw_write_t) i2c_master_send;
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->idle_bias_off = 1;
+       dac33->codec = codec;
 
-       codec = tlv320dac33_codec;
-       socdev->card->codec = codec;
-       dac33 = snd_soc_codec_get_drvdata(codec);
+       /* Read the tlv320dac33 ID registers */
+       ret = dac33_hard_power(codec, 1);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
+               goto err_power;
+       }
+       dac33_read_id(codec);
+       dac33_hard_power(codec, 0);
 
-       /* 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\n");
-               goto pcm_err;
+       /* Check if the IRQ number is valid and request it */
+       if (dac33->irq >= 0) {
+               ret = request_irq(dac33->irq, dac33_interrupt_handler,
+                                 IRQF_TRIGGER_RISING | IRQF_DISABLED,
+                                 codec->name, codec);
+               if (ret < 0) {
+                       dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
+                                               dac33->irq, ret);
+                       dac33->irq = -1;
+               }
+               if (dac33->irq != -1) {
+                       /* Setup work queue */
+                       dac33->dac33_wq =
+                               create_singlethread_workqueue("tlv320dac33");
+                       if (dac33->dac33_wq == NULL) {
+                               free_irq(dac33->irq, codec);
+                               return -ENOMEM;
+                       }
+
+                       INIT_WORK(&dac33->work, dac33_work);
+               }
        }
 
        snd_soc_add_controls(codec, dac33_snd_controls,
@@ -1420,56 +1432,51 @@ static int dac33_soc_probe(struct platform_device *pdev)
                        snd_soc_add_controls(codec, dac33_fifo_snd_controls,
                                        ARRAY_SIZE(dac33_fifo_snd_controls));
        }
-
        dac33_add_widgets(codec);
 
-       return 0;
-
-pcm_err:
-       dac33_hard_power(codec, 0);
+err_power:
        return ret;
 }
 
-static int dac33_soc_remove(struct platform_device *pdev)
+static int dac33_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
        dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
+       if (dac33->irq >= 0) {
+               free_irq(dac33->irq, dac33->codec);
+               destroy_workqueue(dac33->dac33_wq);
+       }
        return 0;
 }
 
-static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state)
+static int dac33_soc_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;
-
        dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int dac33_soc_resume(struct platform_device *pdev)
+static int dac33_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = {
+static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
+       .read = dac33_read_reg_cache,
+       .write = dac33_write_locked,
+       .set_bias_level = dac33_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(dac33_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = dac33_reg,
        .probe = dac33_soc_probe,
        .remove = dac33_soc_remove,
        .suspend = dac33_soc_suspend,
        .resume = dac33_soc_resume,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
 
 #define DAC33_RATES    (SNDRV_PCM_RATE_44100 | \
                         SNDRV_PCM_RATE_48000)
@@ -1485,8 +1492,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = {
        .set_fmt        = dac33_set_dai_fmt,
 };
 
-struct snd_soc_dai dac33_dai = {
-       .name = "tlv320dac33",
+static struct snd_soc_dai_driver dac33_dai = {
+       .name = "tlv320dac33-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -1495,14 +1502,12 @@ struct snd_soc_dai dac33_dai = {
                .formats = DAC33_FORMATS,},
        .ops = &dac33_dai_ops,
 };
-EXPORT_SYMBOL_GPL(dac33_dai);
 
 static int __devinit dac33_i2c_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        struct tlv320dac33_platform_data *pdata;
        struct tlv320dac33_priv *dac33;
-       struct snd_soc_codec *codec;
        int ret, i;
 
        if (client->dev.platform_data == NULL) {
@@ -1515,33 +1520,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
        if (dac33 == NULL)
                return -ENOMEM;
 
-       codec = &dac33->codec;
-       snd_soc_codec_set_drvdata(codec, dac33);
-       codec->control_data = client;
-
-       mutex_init(&codec->mutex);
+       dac33->control_data = client;
        mutex_init(&dac33->mutex);
        spin_lock_init(&dac33->lock);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "tlv320dac33";
-       codec->owner = THIS_MODULE;
-       codec->read = dac33_read_reg_cache;
-       codec->write = dac33_write_locked;
-       codec->hw_write = (hw_write_t) i2c_master_send;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = dac33_set_bias_level;
-       codec->idle_bias_off = 1;
-       codec->dai = &dac33_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(dac33_reg);
-       codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg),
-                                  GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto error_reg;
-       }
 
        i2c_set_clientdata(client, dac33);
 
@@ -1561,125 +1542,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
        /* Disable FIFO use by default */
        dac33->fifo_mode = DAC33_FIFO_BYPASS;
 
-       tlv320dac33_codec = codec;
-
-       codec->dev = &client->dev;
-       dac33_dai.dev = codec->dev;
-
        /* Check if the reset GPIO number is valid and request it */
        if (dac33->power_gpio >= 0) {
                ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset");
                if (ret < 0) {
-                       dev_err(codec->dev,
+                       dev_err(&client->dev,
                                "Failed to request reset GPIO (%d)\n",
                                dac33->power_gpio);
-                       snd_soc_unregister_dai(&dac33_dai);
-                       snd_soc_unregister_codec(codec);
-                       goto error_gpio;
+                       goto err_gpio;
                }
                gpio_direction_output(dac33->power_gpio, 0);
        }
 
-       /* Check if the IRQ number is valid and request it */
-       if (dac33->irq >= 0) {
-               ret = request_irq(dac33->irq, dac33_interrupt_handler,
-                                 IRQF_TRIGGER_RISING | IRQF_DISABLED,
-                                 codec->name, codec);
-               if (ret < 0) {
-                       dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
-                                               dac33->irq, ret);
-                       dac33->irq = -1;
-               }
-               if (dac33->irq != -1) {
-                       /* Setup work queue */
-                       dac33->dac33_wq =
-                               create_singlethread_workqueue("tlv320dac33");
-                       if (dac33->dac33_wq == NULL) {
-                               free_irq(dac33->irq, &dac33->codec);
-                               ret = -ENOMEM;
-                               goto error_wq;
-                       }
-
-                       INIT_WORK(&dac33->work, dac33_work);
-               }
-       }
-
        for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)
                dac33->supplies[i].supply = dac33_supply_names[i];
 
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies),
+       ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),
                                 dac33->supplies);
 
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               dev_err(&client->dev, "Failed to request supplies: %d\n", ret);
                goto err_get;
        }
 
-       /* Read the tlv320dac33 ID registers */
-       ret = dac33_hard_power(codec, 1);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
-               goto error_codec;
-       }
-       dac33_read_id(codec);
-       dac33_hard_power(codec, 0);
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto error_codec;
-       }
-
-       ret = snd_soc_register_dai(&dac33_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               snd_soc_unregister_codec(codec);
-               goto error_codec;
-       }
+       ret = snd_soc_register_codec(&client->dev,
+                       &soc_codec_dev_tlv320dac33, &dac33_dai, 1);
+       if (ret < 0)
+               goto err_register;
 
        return ret;
-
-error_codec:
+err_register:
        regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
 err_get:
-       if (dac33->irq >= 0) {
-               free_irq(dac33->irq, &dac33->codec);
-               destroy_workqueue(dac33->dac33_wq);
-       }
-error_wq:
        if (dac33->power_gpio >= 0)
                gpio_free(dac33->power_gpio);
-error_gpio:
-       kfree(codec->reg_cache);
-error_reg:
-       tlv320dac33_codec = NULL;
+err_gpio:
        kfree(dac33);
-
        return ret;
 }
 
 static int __devexit dac33_i2c_remove(struct i2c_client *client)
 {
-       struct tlv320dac33_priv *dac33;
-
-       dac33 = i2c_get_clientdata(client);
+       struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
 
        if (unlikely(dac33->chip_power))
-               dac33_hard_power(&dac33->codec, 0);
+               dac33_hard_power(dac33->codec, 0);
 
        if (dac33->power_gpio >= 0)
                gpio_free(dac33->power_gpio);
-       if (dac33->irq >= 0)
-               free_irq(dac33->irq, &dac33->codec);
 
        regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
 
-       destroy_workqueue(dac33->dac33_wq);
-       snd_soc_unregister_dai(&dac33_dai);
-       snd_soc_unregister_codec(&dac33->codec);
-       kfree(dac33->codec.reg_cache);
+       snd_soc_unregister_codec(&client->dev);
        kfree(dac33);
-       tlv320dac33_codec = NULL;
 
        return 0;
 }
@@ -1694,7 +1609,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = {
 
 static struct i2c_driver tlv320dac33_i2c_driver = {
        .driver = {
-               .name = "tlv320dac33",
+               .name = "tlv320dac33-codec",
                .owner = THIS_MODULE,
        },
        .probe          = dac33_i2c_probe,