ASoC: tlv320dac33: Revisit the FIFO Mode1 handling
[deliverable/linux.git] / sound / soc / codecs / tlv320dac33.c
index 65adc77eada1039e562af90d298793712b358ae6..ced6fbbc9d913f0df4019bd234c5e8a00c25e4d8 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)
 
@@ -107,6 +105,8 @@ 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 */
        u8 burst_bclkdiv;               /* BCLK divider value in burst mode */
        unsigned int burst_rate;        /* Interface speed in Burst modes */
 
@@ -120,6 +120,8 @@ struct tlv320dac33_priv {
                                         * samples */
        unsigned int mode7_us_to_lthr;  /* Time to reach lthr from uthr */
 
+       unsigned int uthr;
+
        enum dac33_state state;
 };
 
@@ -442,6 +444,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)
 {
@@ -506,6 +541,8 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = {
 static const struct snd_kcontrol_new dac33_nsample_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),
        SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum,
                 dac33_get_fifo_mode, dac33_set_fifo_mode),
 };
@@ -612,7 +649,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
        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);
@@ -761,6 +798,10 @@ static void dac33_shutdown(struct snd_pcm_substream *substream,
        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,
@@ -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:
@@ -1003,48 +1044,38 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->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);
+               /* 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;
@@ -1052,8 +1083,8 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
                break;
        case DAC33_FIFO_MODE7:
                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:
@@ -1104,7 +1135,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
        struct snd_soc_codec *codec = socdev->card->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 +1213,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 +1226,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 +1240,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 +1259,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:
@@ -1481,9 +1513,13 @@ 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->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;
 
This page took 0.033808 seconds and 5 git commands to generate.