|
@@ -2236,7 +2236,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
|
|
|
int slots, int slot_width)
|
|
|
{
|
|
|
struct snd_soc_codec *codec = dai->codec;
|
|
|
- unsigned int val, mask, slots_active;
|
|
|
+ unsigned int val, mask, slot, slots_active;
|
|
|
|
|
|
mask = BIT(AB8500_DIGIFCONF2_IF0WL0) |
|
|
|
BIT(AB8500_DIGIFCONF2_IF0WL1);
|
|
@@ -2292,27 +2292,34 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
|
|
|
snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
|
|
|
|
|
|
/* Setup TDM DA according to active tx slots */
|
|
|
+
|
|
|
+ if (tx_mask & ~0xff)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
mask = AB8500_DASLOTCONFX_SLTODAX_MASK;
|
|
|
+ tx_mask = tx_mask << AB8500_DA_DATA0_OFFSET;
|
|
|
slots_active = hweight32(tx_mask);
|
|
|
+
|
|
|
dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__,
|
|
|
slots_active);
|
|
|
+
|
|
|
switch (slots_active) {
|
|
|
case 0:
|
|
|
break;
|
|
|
case 1:
|
|
|
- /* Slot 9 -> DA_IN1 & DA_IN3 */
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11);
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11);
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
|
|
|
+ slot = find_first_bit((unsigned long *)&tx_mask, 32);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
|
|
|
break;
|
|
|
case 2:
|
|
|
- /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9);
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9);
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
|
|
|
- snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
|
|
|
-
|
|
|
+ slot = find_first_bit((unsigned long *)&tx_mask, 32);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
|
|
|
+ slot = find_next_bit((unsigned long *)&tx_mask, 32, slot + 1);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
|
|
|
+ snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
|
|
|
break;
|
|
|
case 8:
|
|
|
dev_dbg(dai->codec->dev,
|
|
@@ -2327,25 +2334,36 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
|
|
|
}
|
|
|
|
|
|
/* Setup TDM AD according to active RX-slots */
|
|
|
+
|
|
|
+ if (rx_mask & ~0xff)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ rx_mask = rx_mask << AB8500_AD_DATA0_OFFSET;
|
|
|
slots_active = hweight32(rx_mask);
|
|
|
+
|
|
|
dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__,
|
|
|
slots_active);
|
|
|
+
|
|
|
switch (slots_active) {
|
|
|
case 0:
|
|
|
break;
|
|
|
case 1:
|
|
|
- /* AD_OUT3 -> slot 0 & 1 */
|
|
|
- snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL,
|
|
|
- AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
|
|
|
- AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD);
|
|
|
+ slot = find_first_bit((unsigned long *)&rx_mask, 32);
|
|
|
+ snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot),
|
|
|
+ AB8500_MASK_SLOT(slot),
|
|
|
+ AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
|
|
|
break;
|
|
|
case 2:
|
|
|
- /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */
|
|
|
+ slot = find_first_bit((unsigned long *)&rx_mask, 32);
|
|
|
+ snd_soc_update_bits(codec,
|
|
|
+ AB8500_ADSLOTSEL(slot),
|
|
|
+ AB8500_MASK_SLOT(slot),
|
|
|
+ AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
|
|
|
+ slot = find_next_bit((unsigned long *)&rx_mask, 32, slot + 1);
|
|
|
snd_soc_update_bits(codec,
|
|
|
- AB8500_ADSLOTSEL1,
|
|
|
- AB8500_MASK_ALL,
|
|
|
- AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
|
|
|
- AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD);
|
|
|
+ AB8500_ADSLOTSEL(slot),
|
|
|
+ AB8500_MASK_SLOT(slot),
|
|
|
+ AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT2, slot));
|
|
|
break;
|
|
|
case 8:
|
|
|
dev_dbg(dai->codec->dev,
|
|
@@ -2362,6 +2380,11 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static const struct snd_soc_dai_ops ab8500_codec_ops = {
|
|
|
+ .set_fmt = ab8500_codec_set_dai_fmt,
|
|
|
+ .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
|
|
|
+};
|
|
|
+
|
|
|
static struct snd_soc_dai_driver ab8500_codec_dai[] = {
|
|
|
{
|
|
|
.name = "ab8500-codec-dai.0",
|
|
@@ -2373,12 +2396,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
|
|
|
.rates = AB8500_SUPPORTED_RATE,
|
|
|
.formats = AB8500_SUPPORTED_FMT,
|
|
|
},
|
|
|
- .ops = (struct snd_soc_dai_ops[]) {
|
|
|
- {
|
|
|
- .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
|
|
|
- .set_fmt = ab8500_codec_set_dai_fmt,
|
|
|
- }
|
|
|
- },
|
|
|
+ .ops = &ab8500_codec_ops,
|
|
|
.symmetric_rates = 1
|
|
|
},
|
|
|
{
|
|
@@ -2391,12 +2409,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
|
|
|
.rates = AB8500_SUPPORTED_RATE,
|
|
|
.formats = AB8500_SUPPORTED_FMT,
|
|
|
},
|
|
|
- .ops = (struct snd_soc_dai_ops[]) {
|
|
|
- {
|
|
|
- .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
|
|
|
- .set_fmt = ab8500_codec_set_dai_fmt,
|
|
|
- }
|
|
|
- },
|
|
|
+ .ops = &ab8500_codec_ops,
|
|
|
.symmetric_rates = 1
|
|
|
}
|
|
|
};
|