|
@@ -629,13 +629,29 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
|
|
return 0;
|
|
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 i, active_slots;
|
|
|
|
+ int total_slots;
|
|
|
|
+ int active_serializers;
|
|
u32 mask = 0;
|
|
u32 mask = 0;
|
|
u32 busel = 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++)
|
|
for (i = 0; i < active_slots; i++)
|
|
mask |= (1 << i);
|
|
mask |= (1 << i);
|
|
|
|
|
|
@@ -647,12 +663,12 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
|
|
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
|
|
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
|
|
mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
|
|
mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
|
|
mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
|
|
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_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
|
|
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
|
|
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
|
|
mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
|
|
mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
|
|
- FSRMOD(active_slots), FSRMOD(0x1FF));
|
|
|
|
|
|
+ FSRMOD(total_slots), FSRMOD(0x1FF));
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -766,7 +782,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
|
|
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
|
|
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
|
|
ret = mcasp_dit_hw_param(mcasp, params_rate(params));
|
|
ret = mcasp_dit_hw_param(mcasp, params_rate(params));
|
|
else
|
|
else
|
|
- ret = mcasp_i2s_hw_param(mcasp, substream->stream);
|
|
|
|
|
|
+ ret = mcasp_i2s_hw_param(mcasp, substream->stream,
|
|
|
|
+ channels);
|
|
|
|
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|