return 0;
 }
 
-static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
+static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
+                             int channels)
 {
        int i, active_slots;
+       int total_slots;
+       int active_serializers;
        u32 mask = 0;
        u32 busel = 0;
 
-       active_slots = mcasp->tdm_slots;
+       total_slots = mcasp->tdm_slots;
+
+       /*
+        * If more than one serializer is needed, then use them with
+        * their specified tdm_slots count. Otherwise, one serializer
+        * can cope with the transaction using as many slots as channels
+        * in the stream, requires channels symmetry
+        */
+       active_serializers = (channels + total_slots - 1) / total_slots;
+       if (active_serializers == 1)
+               active_slots = channels;
+       else
+               active_slots = total_slots;
+
        for (i = 0; i < active_slots; i++)
                mask |= (1 << i);
 
        mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
        mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
        mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
-                      FSXMOD(active_slots), FSXMOD(0x1FF));
+                      FSXMOD(total_slots), FSXMOD(0x1FF));
 
        mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
        mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
        mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
-                      FSRMOD(active_slots), FSRMOD(0x1FF));
+                      FSRMOD(total_slots), FSRMOD(0x1FF));
 
        return 0;
 }
        if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
                ret = mcasp_dit_hw_param(mcasp, params_rate(params));
        else
-               ret = mcasp_i2s_hw_param(mcasp, substream->stream);
+               ret = mcasp_i2s_hw_param(mcasp, substream->stream,
+                                        channels);
 
        if (ret)
                return ret;