#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);
 
        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 */
 
                 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
 };
 
-static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = {
+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),
+               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),
 };
 
 /* Analog bypass */
                /* 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;
+               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_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,
                                        dac33->uthr - MODE7_LTHR + 1);
 
        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);
 
        /* 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 */