]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas256xsw-android/tas2562-stereo-android-driver.git/commitdiff
TDM Mode support has been added
authorPeeyush Gupta <a0875211@ti.com>
Sat, 16 May 2020 19:56:27 +0000 (01:26 +0530)
committerPeeyush Gupta <a0875211@ti.com>
Sat, 16 May 2020 19:56:27 +0000 (01:26 +0530)
tas2562-codec.c
tas2562.h

index b5a4b75930a725ba9b1f359202264903e0de6ef0..0d42c100d04021cd84d9f316451954d159b74192 100644 (file)
@@ -454,9 +454,16 @@ static int tas2562_set_power_state(struct tas2562_priv *p_tas2562,
        case TAS2562_POWER_ACTIVE:
                /* if set format was not called by asoc, then set it default */
                if (p_tas2562->mn_asi_format == 0)
-                       p_tas2562->mn_asi_format = SND_SOC_DAIFMT_CBS_CFS
-                               | SND_SOC_DAIFMT_IB_NF
-                               | SND_SOC_DAIFMT_I2S;
+               {
+                       if(p_tas2562->mn_tdm_mode)
+                               p_tas2562->mn_asi_format = SND_SOC_DAIFMT_CBS_CFS
+                                       | SND_SOC_DAIFMT_IB_NF
+                                       | SND_SOC_DAIFMT_DSP_B;
+                       else
+                               p_tas2562->mn_asi_format = SND_SOC_DAIFMT_CBS_CFS
+                                       | SND_SOC_DAIFMT_IB_NF
+                                       | SND_SOC_DAIFMT_I2S;
+               }
                n_result = tas2562_set_fmt(p_tas2562, p_tas2562->mn_asi_format);
                if (n_result < 0)
                        return n_result;
@@ -686,6 +693,126 @@ static int tas2562_iv_slot_config(struct tas2562_priv *p_tas2562)
        dev_info(p_tas2562->dev, "%s, %d\n", __func__,
                        p_tas2562->mn_slot_width);
 
+       if (p_tas2562->mn_tdm_mode) {
+               if (p_tas2562->mn_channels == 2) {
+                       if (p_tas2562->mn_slot_width == 16) {
+                               if (p_tas2562->mn_vbat == 1) {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x41);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_right,
+                                               TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x45);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_right,
+                                               TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x44);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x43);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_right,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x47);
+                               } else {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x42);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_right,
+                                               TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x46);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_right,
+                                               TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x44);
+                               }
+
+                       } else if (p_tas2562->mn_slot_width == 24) {
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x43);
+
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+
+                               p_tas2562->update_bits(p_tas2562, channel_right,
+                                       TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x49);
+
+                               p_tas2562->update_bits(p_tas2562, channel_right,
+                                       TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x46);
+
+                               if (p_tas2562->mn_vbat == 1) {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x45);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_right,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x4a);
+                               }
+                       } else { /*Assumed 32bit*/
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x44);
+
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+
+                               p_tas2562->update_bits(p_tas2562, channel_right,
+                                       TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x4c);
+
+                               p_tas2562->update_bits(p_tas2562, channel_right,
+                                       TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x48);
+
+                               if (p_tas2562->mn_vbat == 1) {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x46);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_right,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x4e);
+                               }
+                       }
+               } else { /*Assumed Mono Channels*/
+                       if (p_tas2562->mn_slot_width == 16) {
+                               if (p_tas2562->mn_vbat == 1) {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x41);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x43);
+
+                               } else {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x42);
+
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+                               }
+                       } else if (p_tas2562->mn_slot_width == 24) {
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x43);
+
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+
+                               if (p_tas2562->mn_vbat == 1) {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x45);
+                               }
+                       } else { /*Assumed 32bit*/
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG5, 0xff, 0x44);
+
+                               p_tas2562->update_bits(p_tas2562, channel_left,
+                                       TAS2562_TDMCONFIGURATIONREG6, 0xff, 0x40);
+
+                               if (p_tas2562->mn_vbat == 1) {
+                                       p_tas2562->update_bits(p_tas2562, channel_left,
+                                               TAS2562_TDMCONFIGURATIONREG7, 0xff, 0x46);
+                               }
+                       }
+               }
+       } else { /*I2S Mode*/
        if (p_tas2562->mn_channels == 2) {
                if (p_tas2562->mn_slot_width == 16) {
                        p_tas2562->update_bits(p_tas2562, channel_left,
@@ -788,6 +915,7 @@ static int tas2562_iv_slot_config(struct tas2562_priv *p_tas2562)
                dev_err(p_tas2562->dev, "%s, wrong params, %d\n",
                __func__, p_tas2562->mn_slot_width);
        }
+       }
 
        return ret;
 }
@@ -797,15 +925,30 @@ static int tas2562_iv_bitwidth_config(struct tas2562_priv *p_tas2562)
        int ret = 0;
 
        if ((p_tas2562->mn_channels == 2) && (p_tas2562->mn_slot_width == 16)){
-               ret = p_tas2562->update_bits(p_tas2562, channel_both,
-                       TAS2562_TDMCONFIGURATIONREG2,
-                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_MASK,
-                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS);
+               if (p_tas2562->mn_tdm_mode) {
+                       if (p_tas2562->mn_vbat == 1) {
+                               ret = p_tas2562->update_bits(p_tas2562, channel_both,
+                                       TAS2562_TDMCONFIGURATIONREG2,
+                                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_MASK,
+                                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_12BITS);
+                       } else {
+                               ret = p_tas2562->update_bits(p_tas2562, channel_both,
+                                       TAS2562_TDMCONFIGURATIONREG2,
+                                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_MASK,
+                                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_16BITS);
+                       }
+
+               } else {
+                       ret = p_tas2562->update_bits(p_tas2562, channel_both,
+                               TAS2562_TDMCONFIGURATIONREG2,
+                               TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_MASK,
+                               TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS);
+               }
        } else { /*mn_iv_width == 12 || 16*/
-               p_tas2562->update_bits(p_tas2562, channel_left,
+               p_tas2562->update_bits(p_tas2562, channel_both,
                        TAS2562_TDMCONFIGURATIONREG2,
-                       TAS2562_TDMCONFIGURATIONREG2_IVLEN76_MASK,
-                       TAS2562_TDMCONFIGURATIONREG2_IVLENCFG76_16BITS);
+                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_MASK,
+                       TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_16BITS);
        }
 
        return ret;
@@ -1101,11 +1244,13 @@ static int tas2562_hw_params(struct snd_pcm_substream *substream,
 
        mutex_lock(&p_tas2562->codec_lock);
 
-       n_result = tas2562_set_bitwidth(p_tas2562,
-                       params_format(params));
-       if (n_result < 0) {
-               dev_info(p_tas2562->dev, "set bitwidth failed, %d\n", n_result);
-               goto ret;
+       if (p_tas2562->mn_tdm_mode == false) {
+               n_result = tas2562_set_bitwidth(p_tas2562,
+                               params_format(params));
+               if (n_result < 0) {
+                       dev_info(p_tas2562->dev, "set bitwidth failed, %d\n", n_result);
+                       goto ret;
+               }
        }
 
        dev_info(p_tas2562->dev, "%s, sample rate: %d\n", __func__,
@@ -1122,12 +1267,13 @@ ret:
 static int tas2562_set_fmt(struct tas2562_priv *p_tas2562,
                                                unsigned int fmt)
 {
-       u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
+       u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0, asi_cfg_2 = 0;
        int ret = 0;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                asi_cfg_1 = 0x00;
+               asi_cfg_2 = 0x00;
                break;
        default:
                dev_err(p_tas2562->dev, "ASI format master is not found\n");
@@ -1138,10 +1284,22 @@ static int tas2562_set_fmt(struct tas2562_priv *p_tas2562,
        case SND_SOC_DAIFMT_NB_NF:
                dev_info(p_tas2562->dev, "INV format: NBNF\n");
                asi_cfg_1 |= TAS2562_TDMCONFIGURATIONREG1_RXEDGE_RISING;
+               asi_cfg_2 |= TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_HIGHTOLOW;
                break;
        case SND_SOC_DAIFMT_IB_NF:
                dev_info(p_tas2562->dev, "INV format: IBNF\n");
                asi_cfg_1 |= TAS2562_TDMCONFIGURATIONREG1_RXEDGE_FALLING;
+               asi_cfg_2 |= TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_HIGHTOLOW;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               dev_info(p_tas2562->dev, "INV format: NBIF\n");
+               asi_cfg_1 |= TAS2562_TDMCONFIGURATIONREG1_RXEDGE_RISING;
+               asi_cfg_2 |= TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_LOWTOHIGH;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               dev_info(p_tas2562->dev, "INV format: IBIF\n");
+               asi_cfg_1 |= TAS2562_TDMCONFIGURATIONREG1_RXEDGE_FALLING;
+               asi_cfg_2 |= TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_LOWTOHIGH;
                break;
        default:
                dev_err(p_tas2562->dev, "ASI format Inverse is not found\n");
@@ -1153,14 +1311,20 @@ static int tas2562_set_fmt(struct tas2562_priv *p_tas2562,
                TAS2562_TDMCONFIGURATIONREG1_RXEDGE_MASK,
                asi_cfg_1);
 
+       p_tas2562->update_bits(p_tas2562, channel_both,
+               TAS2562_TDMCONFIGURATIONREG0,
+               TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_MASK,
+               asi_cfg_2);
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case (SND_SOC_DAIFMT_I2S):
                tdm_rx_start_slot = 1;
                break;
        case (SND_SOC_DAIFMT_DSP_A):
-       case (SND_SOC_DAIFMT_DSP_B):
                tdm_rx_start_slot = 1;
                break;
+       case (SND_SOC_DAIFMT_DSP_B):
+               tdm_rx_start_slot = 0;
+               break;
        case (SND_SOC_DAIFMT_LEFT_J):
                tdm_rx_start_slot = 0;
                break;
@@ -1206,6 +1370,80 @@ static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        return ret;
 }
 
+static int tas2562_set_tdm_rx_slot(struct tas2562_priv *p_tas2562,
+       int slots, int slot_width)
+{
+       int ret = -1;
+
+       if ((p_tas2562->mn_slot_width != 16) ||
+               (p_tas2562->mn_slot_width != 24) ||
+               (p_tas2562->mn_slot_width != 32)) {
+                       dev_err(p_tas2562->dev, "Unspoorted slotwidth %d\n", slot_width);
+                       return ret;
+               }
+       p_tas2562->mn_slot_width = slot_width;
+
+       ret = tas2562_set_slot(p_tas2562, slot_width);
+
+       if (((p_tas2562->mn_channels ==1) && (slots < 1)) ||
+               ((p_tas2562->mn_channels ==2) && (slots < 2))) {
+               dev_err(p_tas2562->dev, "Invalid Slots %d\n", slots);
+               return ret;
+       }
+       p_tas2562->mn_slots = slots;
+
+       switch (slot_width) {
+       case 16:
+               ret = p_tas2562->update_bits(p_tas2562, channel_both,
+                       TAS2562_TDMCONFIGURATIONREG2,
+                       TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_MASK,
+                       TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_16BITS);
+               break;
+       case 24:
+               ret = p_tas2562->update_bits(p_tas2562, channel_both,
+                       TAS2562_TDMCONFIGURATIONREG2,
+                       TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_MASK,
+                       TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_24BITS);
+               break;
+       case 32:
+               ret = p_tas2562->update_bits(p_tas2562, channel_both,
+                       TAS2562_TDMCONFIGURATIONREG2,
+                       TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_MASK,
+                       TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_32BITS);
+                       p_tas2562->mn_ch_size = 32;
+               break;
+       default:
+               dev_info(p_tas2562->dev, "Not supported params format\n");
+       }
+
+       return ret;
+}
+
+static int tas2562_set_tdm_tx_slot(struct tas2562_priv *p_tas2562,
+       int slots, int slot_width)
+{
+       int ret = -1;
+
+       if ((p_tas2562->mn_slot_width != 16) ||
+               (p_tas2562->mn_slot_width != 24) ||
+               (p_tas2562->mn_slot_width != 32)) {
+                       dev_err(p_tas2562->dev, "Unspoorted slotwidth %d\n", slot_width);
+                       return ret;
+               }
+       p_tas2562->mn_slot_width = slot_width;
+
+       if (((p_tas2562->mn_channels ==1) && (slots < 2)) ||
+               ((p_tas2562->mn_channels ==2) && (slots < 4))) {
+               dev_err(p_tas2562->dev, "Invalid Slots %d\n", slots);
+               return ret;
+       }
+       p_tas2562->mn_slots = slots;
+
+       ret = tas2562_iv_slot_config(p_tas2562);
+       ret = tas2562_iv_bitwidth_config(p_tas2562);
+
+       return ret;
+}
 static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai,
                unsigned int tx_mask, unsigned int rx_mask,
                int slots, int slot_width)
@@ -1222,7 +1460,17 @@ static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai,
                                         __func__, tx_mask, rx_mask);
        dev_dbg(p_tas2562->dev, "%s, slots:%d,slot_width:%d",
                                                __func__, slots, slot_width);
-       ret = tas2562_set_slot(p_tas2562, slot_width);
+       if (rx_mask) {
+               p_tas2562->mn_tdm_mode = true;
+               ret = tas2562_set_tdm_rx_slot(p_tas2562, slots, slot_width);
+       } else if (tx_mask) {
+               p_tas2562->mn_tdm_mode = true;
+               ret = tas2562_set_tdm_tx_slot(p_tas2562, slots, slot_width);
+       } else {
+               dev_err(p_tas2562->dev, "%s, Invalid Mask",
+                               __func__);
+               p_tas2562->mn_tdm_mode = false;
+       }
 
        return ret;
 }
@@ -1621,9 +1869,23 @@ void tas2562_load_config(struct tas2562_priv *p_tas2562)
                        TAS2562_SOFTWARERESET_SOFTWARERESET_RESET);
        msleep(20);
 
-       ret = tas2562_iv_slot_config(p_tas2562);
-       if (ret < 0)
-               goto end;
+       if (p_tas2562->mn_tdm_mode) {
+               ret = tas2562_set_tdm_tx_slot(p_tas2562,
+                       p_tas2562->mn_slots, p_tas2562->mn_slot_width);
+               if (ret < 0)
+                       goto end;
+               ret = tas2562_set_tdm_tx_slot(p_tas2562,
+                       p_tas2562->mn_slots, p_tas2562->mn_slot_width);
+               if (ret < 0)
+                       goto end;
+       } else {
+               ret = tas2562_set_bitwidth(p_tas2562, p_tas2562->mn_pcm_format);
+               if (ret < 0)
+                       goto end;
+               ret = tas2562_iv_slot_config(p_tas2562);
+               if (ret < 0)
+                       goto end;
+       }
 
        tas2562_load_init(p_tas2562);
        tas2562_iv_enable(p_tas2562, tas2562iv_enable);
@@ -1636,10 +1898,6 @@ void tas2562_load_config(struct tas2562_priv *p_tas2562)
        if (ret < 0)
                goto end;
 
-       ret = tas2562_set_bitwidth(p_tas2562, p_tas2562->mn_pcm_format);
-       if (ret < 0)
-               goto end;
-
        ret = tas2562_set_samplerate(p_tas2562, p_tas2562->mn_sampling_rate);
        if (ret < 0)
                goto end;
index 9a2f3310bf07fa19ed10183531136b9656959d60..d844ebe1025c5bb9597797cd6b07fff0e8a66db4 100644 (file)
--- a/tas2562.h
+++ b/tas2562.h
@@ -641,6 +641,8 @@ int mn_slot_width;
 int mn_pcm_format;
 int mn_iv_width;
 int mn_vbat;
+int mn_slots;
+bool mn_tdm_mode;
 bool mb_mute;
 bool dac_mute;
 bool i2c_suspend;