ASoC: multi-component - ASoC Multi-Component Support
[deliverable/linux.git] / sound / soc / codecs / tlv320dac33.c
index 65adc77eada1039e562af90d298793712b358ae6..a3c5b521da6a5740a9bf27cf34da2a43668ee4f9 100644 (file)
@@ -49,8 +49,6 @@
 
 #define NSAMPLE_MAX            5700
 
-#define LATENCY_TIME_MS                20
-
 #define MODE7_LTHR             10
 #define MODE7_UTHR             (DAC33_BUFFER_SIZE_SAMPLES - 10)
 
 #define US_TO_SAMPLES(rate, us) \
        (rate / (1000000 / us))
 
+#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
+       ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
+
 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,
@@ -92,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;
@@ -107,6 +106,10 @@ struct tlv320dac33_priv {
                                         * this */
        enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */
        unsigned int nsample;           /* burst read amount from host */
+       int mode1_latency;              /* latency caused by the i2c writes in
+                                        * us */
+       int auto_fifo_config;           /* Configure the FIFO based on the
+                                        * period size */
        u8 burst_bclkdiv;               /* BCLK divider value in burst mode */
        unsigned int burst_rate;        /* Interface speed in Burst modes */
 
@@ -120,7 +123,11 @@ struct tlv320dac33_priv {
                                         * samples */
        unsigned int mode7_us_to_lthr;  /* Time to reach lthr from uthr */
 
+       unsigned int uthr;
+
        enum dac33_state state;
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
 static const u8 dac33_reg[DAC33_CACHEREGNUM] = {
@@ -442,6 +449,39 @@ static int dac33_set_nsample(struct snd_kcontrol *kcontrol,
        return ret;
 }
 
+static int dac33_get_uthr(struct snd_kcontrol *kcontrol,
+                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = dac33->uthr;
+
+       return 0;
+}
+
+static int dac33_set_uthr(struct snd_kcontrol *kcontrol,
+                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0;
+
+       if (dac33->substream)
+               return -EBUSY;
+
+       if (dac33->uthr == ucontrol->value.integer.value[0])
+               return 0;
+
+       if (ucontrol->value.integer.value[0] < (MODE7_LTHR + 10) ||
+           ucontrol->value.integer.value[0] > MODE7_UTHR)
+               ret = -EINVAL;
+       else
+               dac33->uthr = ucontrol->value.integer.value[0];
+
+       return ret;
+}
+
 static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
 {
@@ -503,13 +543,18 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = {
                 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
 };
 
-static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = {
-       SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0,
-                dac33_get_nsample, dac33_set_nsample),
+static const struct snd_kcontrol_new dac33_mode_snd_controls[] = {
        SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum,
                 dac33_get_fifo_mode, dac33_set_fifo_mode),
 };
 
+static const struct snd_kcontrol_new dac33_fifo_snd_controls[] = {
+       SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0,
+               dac33_get_nsample, dac33_set_nsample),
+       SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0,
+                dac33_get_uthr, dac33_set_uthr),
+};
+
 /* Analog bypass */
 static const struct snd_kcontrol_new dac33_dapm_abypassl_control =
        SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1);
@@ -605,14 +650,12 @@ 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:
                dac33_write16(codec, DAC33_NSAMPLE_MSB,
-                       DAC33_THRREG(dac33->nsample + dac33->alarm_threshold));
+                       DAC33_THRREG(dac33->nsample));
 
                /* Take the timestamps */
                spin_lock_irq(&dac33->lock);
@@ -650,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:
@@ -681,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) {
@@ -742,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 */
@@ -756,11 +796,14 @@ 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;
+
+       /* Reset the nSample restrictions */
+       dac33->nsample_min = 0;
+       dac33->nsample_max = NSAMPLE_MAX;
 }
 
 static int dac33_hw_params(struct snd_pcm_substream *substream,
@@ -768,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)) {
@@ -807,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;
@@ -985,7 +1026,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
                 * Configure the threshold levels, and leave 10 sample space
                 * at the bottom, and also at the top of the FIFO
                 */
-               dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(MODE7_UTHR));
+               dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(dac33->uthr));
                dac33_write16(codec, DAC33_LTHR_MSB, DAC33_THRREG(MODE7_LTHR));
                break;
        default:
@@ -1000,60 +1041,73 @@ 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;
        unsigned int nsample_limit;
 
        /* In bypass mode we don't need to calculate */
        if (!dac33->fifo_mode)
                return;
 
-       /* Number of samples (16bit, stereo) in one period */
-       dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4;
-
-       /* Number of samples (16bit, stereo) in ALSA buffer */
-       dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4;
-       /* Subtract one period from the total */
-       dac33->nsample_max -= dac33->nsample_min;
-
-       /* Number of samples for LATENCY_TIME_MS / 2 */
-       dac33->alarm_threshold = substream->runtime->rate /
-                                (1000 / (LATENCY_TIME_MS / 2));
-
-       /* Find and fix up the lowest nsmaple limit */
-       nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS);
-
-       if (dac33->nsample_min < nsample_limit)
-               dac33->nsample_min = nsample_limit;
-
-       if (dac33->nsample < dac33->nsample_min)
-               dac33->nsample = dac33->nsample_min;
-
-       /*
-        * Find and fix up the highest nsmaple limit
-        * In order to not overflow the DAC33 buffer substract the
-        * alarm_threshold value from the size of the DAC33 buffer
-        */
-       nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold;
-
-       if (dac33->nsample_max > nsample_limit)
-               dac33->nsample_max = nsample_limit;
-
-       if (dac33->nsample > dac33->nsample_max)
-               dac33->nsample = dac33->nsample_max;
-
        switch (dac33->fifo_mode) {
        case DAC33_FIFO_MODE1:
+               /* Number of samples under i2c latency */
+               dac33->alarm_threshold = US_TO_SAMPLES(rate,
+                                               dac33->mode1_latency);
+               if (dac33->auto_fifo_config) {
+                       if (period_size <= dac33->alarm_threshold)
+                               /*
+                                * Configure nSamaple to number of periods,
+                                * which covers the latency requironment.
+                                */
+                               dac33->nsample = period_size *
+                                      ((dac33->alarm_threshold / period_size) +
+                                      (dac33->alarm_threshold % period_size ?
+                                      1 : 0));
+                       else
+                               dac33->nsample = period_size;
+               } else {
+                       /* nSample time shall not be shorter than i2c latency */
+                       dac33->nsample_min = dac33->alarm_threshold;
+                       /*
+                        * nSample should not be bigger than alsa buffer minus
+                        * size of one period to avoid overruns
+                        */
+                       dac33->nsample_max = substream->runtime->buffer_size -
+                                               period_size;
+                       nsample_limit = DAC33_BUFFER_SIZE_SAMPLES -
+                                       dac33->alarm_threshold;
+                       if (dac33->nsample_max > nsample_limit)
+                               dac33->nsample_max = nsample_limit;
+
+                       /* Correct the nSample if it is outside of the ranges */
+                       if (dac33->nsample < dac33->nsample_min)
+                               dac33->nsample = dac33->nsample_min;
+                       if (dac33->nsample > dac33->nsample_max)
+                               dac33->nsample = dac33->nsample_max;
+               }
+
                dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate,
                                                      dac33->nsample);
                dac33->t_stamp1 = 0;
                dac33->t_stamp2 = 0;
                break;
        case DAC33_FIFO_MODE7:
+               if (dac33->auto_fifo_config) {
+                       dac33->uthr = UTHR_FROM_PERIOD_SIZE(
+                                       period_size,
+                                       rate,
+                                       dac33->burst_rate) + 9;
+                       if (dac33->uthr > MODE7_UTHR)
+                               dac33->uthr = MODE7_UTHR;
+                       if (dac33->uthr < (MODE7_LTHR + 10))
+                               dac33->uthr = (MODE7_LTHR + 10);
+               }
                dac33->mode7_us_to_lthr =
-                                       SAMPLES_TO_US(substream->runtime->rate,
-                                               MODE7_UTHR - MODE7_LTHR + 1);
+                               SAMPLES_TO_US(substream->runtime->rate,
+                                       dac33->uthr - MODE7_LTHR + 1);
                dac33->t_stamp1 = 0;
                break;
        default:
@@ -1066,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;
 
@@ -1100,11 +1153,10 @@ 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;
+       unsigned int time_delta, uthr;
        int samples_out, samples_in, samples;
        snd_pcm_sframes_t delay = 0;
 
@@ -1182,6 +1234,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
        case DAC33_FIFO_MODE7:
                spin_lock(&dac33->lock);
                t0 = dac33->t_stamp1;
+               uthr = dac33->uthr;
                spin_unlock(&dac33->lock);
                t_now = ktime_to_us(ktime_get());
 
@@ -1194,7 +1247,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
                         * Either the timestamps are messed or equal. Report
                         * maximum delay
                         */
-                       delay = MODE7_UTHR;
+                       delay = uthr;
                        goto out;
                }
 
@@ -1208,8 +1261,8 @@ static snd_pcm_sframes_t dac33_dai_delay(
                                        substream->runtime->rate,
                                        time_delta);
 
-                       if (likely(MODE7_UTHR > samples_out))
-                               delay = MODE7_UTHR - samples_out;
+                       if (likely(uthr > samples_out))
+                               delay = uthr - samples_out;
                        else
                                delay = 0;
                } else {
@@ -1227,8 +1280,8 @@ static snd_pcm_sframes_t dac33_dai_delay(
                                        time_delta);
                        delay = MODE7_LTHR + samples_in - samples_out;
 
-                       if (unlikely(delay > MODE7_UTHR))
-                               delay = MODE7_UTHR;
+                       if (unlikely(delay > uthr))
+                               delay = uthr;
                }
                break;
        default:
@@ -1325,82 +1378,105 @@ 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);
+
+       /* 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;
+                       }
 
-       /* 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;
+                       INIT_WORK(&dac33->work, dac33_work);
+               }
        }
 
        snd_soc_add_controls(codec, dac33_snd_controls,
                             ARRAY_SIZE(dac33_snd_controls));
-       /* Only add the nSample controls, if we have valid IRQ number */
-       if (dac33->irq >= 0)
-               snd_soc_add_controls(codec, dac33_nsample_snd_controls,
-                                    ARRAY_SIZE(dac33_nsample_snd_controls));
-
+       /* Only add the FIFO controls, if we have valid IRQ number */
+       if (dac33->irq >= 0) {
+               snd_soc_add_controls(codec, dac33_mode_snd_controls,
+                                    ARRAY_SIZE(dac33_mode_snd_controls));
+               /* FIFO usage controls only, if autoio config is not selected */
+               if (!dac33->auto_fifo_config)
+                       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)
@@ -1416,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,
@@ -1426,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) {
@@ -1446,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);
 
@@ -1481,131 +1531,70 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
        /* Pre calculate the burst rate */
        dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32;
        dac33->keep_bclk = pdata->keep_bclk;
+       dac33->auto_fifo_config = pdata->auto_fifo_config;
+       dac33->mode1_latency = pdata->mode1_latency;
+       if (!dac33->mode1_latency)
+               dac33->mode1_latency = 10000; /* 10ms */
        dac33->irq = client->irq;
        dac33->nsample = NSAMPLE_MAX;
        dac33->nsample_max = NSAMPLE_MAX;
+       dac33->uthr = MODE7_UTHR;
        /* 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;
 }
@@ -1620,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,
This page took 0.033954 seconds and 5 git commands to generate.