audio: make loopback compitable with chips [1/1]
authorShuai Li <shuai.li@amlogic.com>
Fri, 30 Aug 2019 10:38:21 +0000 (18:38 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Fri, 6 Sep 2019 01:24:15 +0000 (18:24 -0700)
PD#TV-8363

Problem:
Loopback doesn't work on TM2.
TL1 doesn't support loopback in OE pins.

Solution:
Make it compitable with chips.
Add tdm_lb format and chmasks.

Verify:
TM2 AB311 and TL1 X301.

Change-Id: If878fe75fc87857eae7a44439a451c5b2f494c67
Signed-off-by: Shuai Li <shuai.li@amlogic.com>
sound/soc/amlogic/auge/Makefile
sound/soc/amlogic/auge/card.c
sound/soc/amlogic/auge/loopback.c
sound/soc/amlogic/auge/loopback.h
sound/soc/amlogic/auge/loopback_hw.c
sound/soc/amlogic/auge/loopback_hw.h
sound/soc/amlogic/auge/tdm.c
sound/soc/amlogic/auge/tdm_hw.c
sound/soc/amlogic/auge/tdm_hw.h
sound/soc/amlogic/auge/tdm_match_table.c

index fb7a97342ce91d3a242b10b4d10c8d0776c8001d..f5d514c344549866589db625020956f031bdd4a2 100644 (file)
@@ -6,7 +6,6 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE)      += audio_controller.o \
                                                tl1,clocks.o \
                                                sm1,clocks.o \
                                                tm2,clocks.o \
-                                               card.o \
                                                card_utils.o \
                                                tdm.o \
                                                tdm_hw.o \
@@ -37,4 +36,5 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE)    += audio_controller.o \
                                                vad_hw.o \
                                                vad_dev.o \
                                                earc.o \
-                                               earc_hw.o
+                                               earc_hw.o \
+                                               card.o
index a5569c2c047e4f7e024aac5974b321a422ff20f9..23b0ef52109ca08132971ff9d0ddda6c03bd42cc 100644 (file)
@@ -825,6 +825,7 @@ static int aml_card_parse_of(struct device_node *node,
                        ret = aml_card_dai_link_of(np, priv,
                                                           i, false);
                        if (ret < 0) {
+                               dev_err(dev, "parse dai_link-%d fail\n", i);
                                of_node_put(np);
                                goto card_parse_end;
                        }
index d8b1fb0d8a50a739e2f43640223f57bcb4f0129e..a5e622c8abc8acdf634b1ae41c5c201681afc3b8 100644 (file)
@@ -79,7 +79,8 @@ struct loopback {
        unsigned int datalb_chnum;
        unsigned int datalb_chmask;
        unsigned int datalb_lane_mask; /* related with data lane */
-
+       unsigned int lb_format;
+       unsigned int lb_lane_chmask;
        unsigned int sysclk_freq;
 
        struct toddr *tddr;
@@ -434,7 +435,7 @@ static int loopback_dai_startup(
 
        /* datalb */
        switch (p_loopback->datalb_src) {
-       case TDMINLB_TDMOUTA ... TDMINLB_PAD_TDMINC:
+       case TDMINLB_TDMOUTA ... TDMINLB_PAD_TDMINC_D:
                /*tdminlb_startup(p_loopback);*/
                break;
        case SPDIFINLB_SPDIFOUTA ... SPDIFINLB_SPDIFOUTB:
@@ -476,7 +477,7 @@ static void loopback_dai_shutdown(
 
        /* datalb */
        switch (p_loopback->datalb_src) {
-       case TDMINLB_TDMOUTA ... TDMINLB_PAD_TDMINC:
+       case TDMINLB_TDMOUTA ... TDMINLB_PAD_TDMINC_D:
                /*tdminlb_shutdown(p_loopback);*/
                break;
        case SPDIFINLB_SPDIFOUTA ... SPDIFINLB_SPDIFOUTB:
@@ -558,12 +559,7 @@ static int loopback_set_ctrl(struct loopback *p_loopback, int bitwidth)
        }
 
        switch (p_loopback->datalb_src) {
-       case TDMINLB_TDMOUTA:
-       case TDMINLB_TDMOUTB:
-       case TDMINLB_TDMOUTC:
-       case TDMINLB_PAD_TDMINA:
-       case TDMINLB_PAD_TDMINB:
-       case TDMINLB_PAD_TDMINC:
+       case TDMINLB_TDMOUTA ... TDMINLB_PAD_TDMINC_D:
                if (bitwidth == 24) {
                        datalb_toddr_type = 4;
                        datalb_msb = 32 - 1;
@@ -607,9 +603,10 @@ static int loopback_set_ctrl(struct loopback *p_loopback, int bitwidth)
        lb_set_datain_cfg(p_loopback->id, &datain_cfg);
        lb_set_datalb_cfg(p_loopback->id, &datalb_cfg);
 
-       tdminlb_set_format(1); /* tdmin_lb i2s mode */
+       tdminlb_set_format(p_loopback->lb_format == SND_SOC_DAIFMT_I2S);
        tdminlb_set_lanemask_and_chswap(0x76543210,
-               p_loopback->datalb_lane_mask);
+               p_loopback->datalb_lane_mask,
+               p_loopback->lb_lane_chmask);
        tdminlb_set_ctrl(p_loopback->datalb_src);
 
        return 0;
@@ -722,6 +719,10 @@ static int loopback_dai_prepare(
                case TDMINLB_PAD_TDMINB:
                case TDMINLB_PAD_TDMINC:
                        break;
+               case TDMINLB_PAD_TDMINA_D:
+               case TDMINLB_PAD_TDMINB_D:
+               case TDMINLB_PAD_TDMINC_D:
+                       break;
                case SPDIFINLB_SPDIFOUTA:
                case SPDIFINLB_SPDIFOUTB:
                        break;
@@ -891,7 +892,7 @@ static int loopback_dai_hw_params(
 
        /* datalb */
        switch (p_loopback->datalb_src) {
-       case TDMINLB_TDMOUTA ... TDMINLB_PAD_TDMINC:
+       case TDMINLB_TDMOUTA ... TDMINLB_PAD_TDMINC_D:
                /*datalb_tdminlb_set_clk(p_loopback);*/
                break;
        case SPDIFINLB_SPDIFOUTA ... SPDIFINLB_SPDIFOUTB:
@@ -1038,6 +1039,9 @@ static const char *const datalb_tdminlb_texts[] = {
        "TDMIN_A",
        "TDMIN_B",
        "TDMIN_C",
+       "TDMIN_A_D",
+       "TDMIN_B_D",
+       "TDMIN_C_D",
 };
 
 static const struct soc_enum datalb_tdminlb_enum =
@@ -1277,6 +1281,39 @@ err:
        return -EINVAL;
 }
 
+static unsigned int loopback_parse_format(struct device_node *node)
+{
+       unsigned int format = 0;
+       int ret = 0;
+       const char *str;
+       struct {
+               char *name;
+               unsigned int val;
+       } fmt_table[] = {
+               {"i2s", SND_SOC_DAIFMT_I2S},
+               {"dsp_a", SND_SOC_DAIFMT_DSP_A},
+               {"dsp_b", SND_SOC_DAIFMT_DSP_B}
+       };
+
+       ret = of_property_read_string(node, "datalb-format", &str);
+       if (ret == 0) {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(fmt_table); i++) {
+                       if (strcmp(str, fmt_table[i].name) == 0) {
+                               format |= fmt_table[i].val;
+                               break;
+                       }
+               }
+       }
+
+       /* default format is I2S */
+       if (format == 0)
+               format = SND_SOC_DAIFMT_I2S;
+
+       return format;
+}
+
 static int loopback_parse_of(
        struct device_node *node,
        struct loopback *p_loopback)
@@ -1350,6 +1387,15 @@ static int loopback_parse_of(
                goto fail;
        }
 
+       p_loopback->lb_format = loopback_parse_format(node);
+       snd_soc_of_get_slot_mask
+               (node,
+               "datalb-channels-mask",
+               &p_loopback->lb_lane_chmask);
+       if (p_loopback->lb_lane_chmask == 0) {
+               /* default format is I2S and mask two channels */
+               p_loopback->lb_lane_chmask = 0x3;
+       }
        pr_info("\tdatain_src:%d, datain_chnum:%d, datain_chumask:%x\n",
                p_loopback->datain_src,
                p_loopback->datain_chnum,
@@ -1361,6 +1407,8 @@ static int loopback_parse_of(
        pr_info("\tdatain_lane_mask:0x%x, datalb_lane_mask:0x%x\n",
                p_loopback->datain_lane_mask,
                p_loopback->datalb_lane_mask);
+       pr_info("datalb_format: %d, chmask for lanes: %#x\n",
+               p_loopback->lb_format, p_loopback->lb_lane_chmask);
 
        ret = datain_parse_of(node, p_loopback);
        if (ret) {
index bc0c075974a1f97542c873c9eb43ea3cd85d6bcd..3fcd434bb227428d43cca6e21e81ead8ee0686af 100644 (file)
@@ -55,6 +55,10 @@ enum datalb_src {
        TDMINLB_PAD_TDMINB,
        TDMINLB_PAD_TDMINC,
 
+       TDMINLB_PAD_TDMINA_D,
+       TDMINLB_PAD_TDMINB_D,
+       TDMINLB_PAD_TDMINC_D,
+
        SPDIFINLB_SPDIFOUTA,
        SPDIFINLB_SPDIFOUTB,
 };
index 8b23f137ebce72627e09b5f8288d0f68d6539494..14a3ef6cf92e83d95158639e749a94f46744b2f2 100644 (file)
 #include "regs.h"
 #include "iomap.h"
 
+static unsigned int
+get_tdmin_id_from_lb_src(enum datalb_src lb_src)
+{
+       return lb_src % TDMINLB_PAD_TDMINA;
+}
 
-void tdminlb_set_clk(int datatlb_src, int sclk_div, int ratio, bool enable)
+void tdminlb_set_clk(enum datalb_src lb_src,
+                    int sclk_div, int ratio, bool enable)
 {
        unsigned int bclk_sel, fsclk_sel;
        unsigned int tdmin_src;
 
        /* config for external codec */
-       if (datatlb_src >= 3) {
-               unsigned int clk_id = datatlb_src - 3;
+       if (lb_src >= TDMINLB_PAD_TDMINA) {
+               unsigned int id = get_tdmin_id_from_lb_src(lb_src);
                unsigned int offset, reg;
                unsigned int fsclk_hi;
 
                fsclk_hi = ratio / 2;
-               bclk_sel = clk_id;
-               fsclk_sel = clk_id;
+               bclk_sel = id;
+               fsclk_sel = id;
 
                /*sclk, lrclk*/
                offset = EE_AUDIO_MST_B_SCLK_CTRL0 - EE_AUDIO_MST_A_SCLK_CTRL0;
-               reg = EE_AUDIO_MST_A_SCLK_CTRL0 + offset * clk_id;
+               reg = EE_AUDIO_MST_A_SCLK_CTRL0 + offset * id;
                audiobus_update_bits(reg,
                        0x3 << 30 | 0x3ff << 20 | 0x3ff<<10 | 0x3ff,
                        (enable ? 0x3 : 0x0) << 30
                        | sclk_div << 20 | fsclk_hi << 10
                        | ratio);
 
-
-               tdmin_src = datatlb_src - 3;
+               tdmin_src = id;
        } else
-               tdmin_src = datatlb_src;
+               tdmin_src = lb_src;
 
        audiobus_update_bits(
                EE_AUDIO_CLK_TDMIN_LB_CTRL,
@@ -72,11 +77,11 @@ void tdminlb_set_format(int i2s_fmt)
 {
        audiobus_update_bits(EE_AUDIO_TDMIN_LB_CTRL,
                0x1 << 30,
-               i2s_fmt << 30 /* 0:tdm mode; 1: i2s mode; */
+               !!i2s_fmt << 30 /* 0:tdm mode; 1: i2s mode; */
        );
 }
 
-void tdminlb_set_ctrl(int src)
+void tdminlb_set_ctrl(enum datalb_src src)
 {
        audiobus_update_bits(
                EE_AUDIO_TDMIN_LB_CTRL,
@@ -101,14 +106,13 @@ static void tdminlb_set_lane_mask(int lane, int mask)
        audiobus_write(EE_AUDIO_TDMIN_LB_MASK0 + lane, mask);
 }
 
-void tdminlb_set_lanemask_and_chswap(int swap, int lane_mask)
+void tdminlb_set_lanemask_and_chswap(int swap, int lane_mask, unsigned int mask)
 {
-       unsigned int mask;
        unsigned int i;
 
-       pr_debug("tdmin_lb lane swap:0x%x mask:0x%x\n", swap, lane_mask);
-
-       mask = 0x3; /* i2s format */
+       pr_debug
+               ("%s() lane swap:0x%x lane mask:0x%x, chmask:%#x\n",
+               __func__, swap, lane_mask, mask);
 
        /* channel swap */
        audiobus_write(EE_AUDIO_TDMIN_LB_SWAP0, swap);
index a64afc4db776b2b17ea86c44d9afde9e24c0cd10..4878f2c2e97e6eeb5fbb112830fcc83f24049fcc 100644 (file)
@@ -19,6 +19,7 @@
 #define __AML_LOOPBACK_HW_H__
 
 #include <linux/types.h>
+#include "loopback.h"
 
 struct data_cfg {
        /*
@@ -46,20 +47,20 @@ struct data_cfg {
        bool ch_ctrl_switch;
 };
 
-extern void tdminlb_set_clk(int datatlb_src,
-       int sclk_div, int ratio, bool enable);
+void tdminlb_set_clk(enum datalb_src lb_src,
+                    int sclk_div, int ratio, bool enable);
 
 extern void tdminlb_set_format(int i2s_fmt);
 
-extern void tdminlb_set_ctrl(int src);
+void tdminlb_set_ctrl(enum datalb_src src);
 
 extern void tdminlb_enable(int tdm_index, int in_enable);
 
 extern void tdminlb_fifo_enable(int is_enable);
 
 extern void tdminlb_set_format(int i2s_fmt);
-extern void tdminlb_set_lanemask_and_chswap(int swap, int lane_mask);
-
+void tdminlb_set_lanemask_and_chswap
+       (int swap, int lane_mask, unsigned int mask);
 
 extern void tdminlb_set_src(int src);
 extern void lb_set_datain_src(int id, int src);
index ea098f2e57355d2daff80cf021fa8e52ffe0b155..4cf0dafb8d0323a2a6e1aa518a6cb829892e8412 100644 (file)
@@ -789,12 +789,11 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
 #if 1
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* set lanes mask acordingly */
-               if (p_tdm->chipinfo
-                       && p_tdm->chipinfo->oe_fn
-                       && p_tdm->setting.lane_oe_mask_out)
+               lane_mask = setting->lane_mask_out;
+               /* compatible using oe masks */
+               if (!lane_mask && setting->lane_oe_mask_out)
                        lane_mask = setting->lane_oe_mask_out;
-               else
-                       lane_mask = setting->lane_mask_out;
+
                for (i = 0; i < p_tdm->lane_cnt; i++) {
                        if (((1 << i) & lane_mask) && lanes) {
                                aml_tdm_set_channel_mask(p_tdm->actrl,
@@ -1199,21 +1198,17 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
        unsigned int lanes_oe_out_cnt = 0, lanes_oe_in_cnt = 0;
        unsigned int force_oe = 0, oe_val = 0;
        unsigned int lanes_lb_cnt = 0;
-       int out_lanes, in_lanes;
+       int out_lanes = 0, in_lanes = 0;
        int in_src = -1;
 
        lanes_out_cnt = pop_count(p_tdm->setting.lane_mask_out);
        lanes_in_cnt = pop_count(p_tdm->setting.lane_mask_in);
-       lanes_oe_out_cnt = pop_count(p_tdm->setting.lane_oe_mask_out);
-       lanes_oe_in_cnt = pop_count(p_tdm->setting.lane_oe_mask_in);
        lanes_lb_cnt = pop_count(p_tdm->setting.lane_lb_mask_in);
 
        pr_debug("%s(), txmask(%#x), rxmask(%#x)\n",
                __func__, tx_mask, rx_mask);
        pr_debug("\tlanes_out_cnt(%d), lanes_in_cnt(%d)\n",
                lanes_out_cnt, lanes_in_cnt);
-       pr_debug("\tlanes_oe_out_cnt(%d), lanes_oe_in_cnt(%d)\n",
-               lanes_oe_out_cnt, lanes_oe_in_cnt);
        pr_debug("\tlanes_lb_cnt(%d)\n",
                lanes_lb_cnt);
        pr_debug("\tslots(%d), slot_width(%d)\n",
@@ -1247,9 +1242,30 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
                                p_tdm->setting.lane_lb_mask_in
                                        & p_tdm->setting.lane_oe_mask_in);
 
+               lanes_oe_out_cnt = pop_count(p_tdm->setting.lane_oe_mask_out);
+               lanes_oe_in_cnt = pop_count(p_tdm->setting.lane_oe_mask_in);
+               pr_debug
+                       ("\tlanes_oe_out_cnt(%d), lanes_oe_in_cnt(%d)\n",
+                       lanes_oe_out_cnt, lanes_oe_in_cnt);
+
                if (lanes_oe_out_cnt) {
-                       force_oe = p_tdm->setting.lane_oe_mask_out;
+                       unsigned int oe_fn_version = p_tdm->chipinfo->oe_fn;
+
+                       force_oe = (1 << p_tdm->chipinfo->lane_cnt) - 1;
                        oe_val = p_tdm->setting.lane_oe_mask_out;
+                       if (oe_fn_version == OE_FUNCTION_V1) {
+                               aml_tdm_set_oe_v1
+                                       (p_tdm->actrl, p_tdm->id,
+                                       force_oe, oe_val);
+                       } else if (oe_fn_version == OE_FUNCTION_V2) {
+                               aml_tdm_set_oe_v2
+                                       (p_tdm->actrl, p_tdm->id,
+                                       force_oe, oe_val);
+                       } else {
+                               pr_err
+                                       ("%s(), oe version(%d) not support\n",
+                                       __func__, oe_fn_version);
+                       }
                }
 
                if (lanes_lb_cnt)
@@ -1269,7 +1285,7 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
                }
        }
 
-       out_lanes = lanes_out_cnt + lanes_oe_out_cnt;
+       out_lanes = lanes_out_cnt;
        in_lanes = lanes_in_cnt + lanes_oe_in_cnt + lanes_lb_cnt;
 
        if (p_tdm->chipinfo
@@ -1284,8 +1300,7 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
 
        if (out_lanes > 0 && out_lanes <= LANE_MAX3)
                aml_tdm_set_slot_out(p_tdm->actrl,
-                       p_tdm->id, slots, slot_width,
-                       force_oe, oe_val);
+                       p_tdm->id, slots, slot_width);
 
        /* constrains hw channels_max by DTS configs */
        drv->playback.channels_max = slots * out_lanes;
index 15016a4a5335572fb2ede3b41a9b0fb01ab0a35d..96e8c02945a5ea44a236f26726468fa8b8734060 100644 (file)
@@ -454,34 +454,64 @@ void aml_update_tdmin_rev_ws(struct aml_audio_controller *actrl,
 
        off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
        reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * idx;
-       aml_audiobus_update_bits(actrl, reg_in,
+       aml_audiobus_update_bits
+               (actrl, reg_in,
                0x1 << 25, is_rev << 25);
 }
 
-void aml_tdm_set_slot_out(
+void aml_tdm_set_oe_v1(
        struct aml_audio_controller *actrl,
-       int index, int slots, int slot_width,
-       int force_oe, int oe_val)
+       int index, int force_oe, int oe_val)
 {
        unsigned int reg, offset;
 
        offset = EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0;
        reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index;
-       aml_audiobus_update_bits(actrl, reg,
-                               0x3ff, ((slots - 1) << 5) | (slot_width - 1));
 
        if (force_oe) {
+               offset = EE_AUDIO_TDMOUT_B_CTRL2 - EE_AUDIO_TDMOUT_A_CTRL2;
+               reg = EE_AUDIO_TDMOUT_A_CTRL2 + offset * index;
+
                aml_audiobus_update_bits(actrl, reg, 0xf << 24, force_oe << 24);
 
+               /* force oe val, in or out */
+               reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * index;
+               aml_audiobus_update_bits(actrl, reg, 0xf, oe_val);
+       }
+}
+
+void aml_tdm_set_oe_v2(
+       struct aml_audio_controller *actrl,
+       int index, int force_oe, int oe_val)
+{
+       unsigned int reg, offset;
+
+       if (force_oe) {
+               offset = EE_AUDIO_TDMOUT_B_CTRL2 - EE_AUDIO_TDMOUT_A_CTRL2;
+               reg = EE_AUDIO_TDMOUT_A_CTRL2 + offset * index;
+
+               aml_audiobus_update_bits(actrl, reg, 0xff << 8, force_oe << 8);
+
                /* force oe val, in or out */
                if (oe_val) {
-                       reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * index;
-                       aml_audiobus_update_bits(actrl, reg,
-                               0xf << 0, oe_val << 0);
+                       aml_audiobus_update_bits
+                               (actrl, reg, 0xff << 16, oe_val << 16);
                }
        }
 }
 
+void aml_tdm_set_slot_out(
+       struct aml_audio_controller *actrl,
+       int index, int slots, int slot_width)
+{
+       unsigned int reg, offset;
+
+       offset = EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0;
+       reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index;
+       aml_audiobus_update_bits
+               (actrl, reg, 0x3ff, ((slots - 1) << 5) | (slot_width - 1));
+}
+
 void aml_tdm_set_slot_in(
        struct aml_audio_controller *actrl,
        int index, int in_src, int slot_width)
index 6a4b5a843b1d855a2ff16a43296cdad50d94c449..656fa29234c2b681624db16f3d0d8bcb5b6e714b 100644 (file)
@@ -107,8 +107,7 @@ extern void aml_update_tdmin_rev_ws(struct aml_audio_controller *actrl,
 
 extern void aml_tdm_set_slot_out(
        struct aml_audio_controller *actrl,
-       int index, int slots, int slot_width,
-       int force_oe, int oe_val);
+       int index, int slots, int slot_width);
 
 extern void aml_tdm_set_slot_in(
        struct aml_audio_controller *actrl,
@@ -164,4 +163,11 @@ void aml_tdm_mute_capture(
                bool mute,
                int lane_cnt);
 void aml_tdm_out_reset(unsigned int tdm_id, int offset);
+void aml_tdm_set_oe_v1(
+       struct aml_audio_controller *actrl,
+       int index, int force_oe, int oe_val);
+void aml_tdm_set_oe_v2(
+       struct aml_audio_controller *actrl,
+       int index, int force_oe, int oe_val);
+
 #endif
index 957bb1e2da50b1b114f2da1ea53f9d7a80a21c61..71c67ff7a9310b835ee83703da811af7e5643376 100644 (file)
  *
  */
 
+/* For OE function V1:
+ * OE is set by EE_AUDIO_TDMOUT_A_CTRL0 & EE_AUDIO_TDMOUT_A_CTRL1
+ */
+#define OE_FUNCTION_V1 1
+/* For OE function V2:
+ * OE is set by EE_AUDIO_TDMOUT_A_CTRL2
+ */
+#define OE_FUNCTION_V2 2
+
 struct tdm_chipinfo {
        /* device id */
        unsigned int id;
@@ -26,7 +35,7 @@ struct tdm_chipinfo {
        bool sclk_ws_inv;
 
        /* output en (oe) for pinmux */
-       bool oe_fn;
+       unsigned int oe_fn;
 
        /* clk pad */
        bool no_mclkpad_ctrl;
@@ -82,7 +91,7 @@ struct tdm_chipinfo g12a_tdma_chipinfo = {
 struct tdm_chipinfo g12a_tdmb_chipinfo = {
        .id          = TDM_B,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V1,
        .same_src_fn = true,
        .mclkpad_no_offset = true,
 };
@@ -90,7 +99,7 @@ struct tdm_chipinfo g12a_tdmb_chipinfo = {
 struct tdm_chipinfo g12a_tdmc_chipinfo = {
        .id          = TDM_C,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V1,
        .same_src_fn = true,
        .mclkpad_no_offset = true,
 };
@@ -98,7 +107,7 @@ struct tdm_chipinfo g12a_tdmc_chipinfo = {
 struct tdm_chipinfo g12a_tdminlb_chipinfo = {
        .id          = TDM_LB,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V1,
        .same_src_fn = true,
        .mclkpad_no_offset = true,
 };
@@ -106,7 +115,7 @@ struct tdm_chipinfo g12a_tdminlb_chipinfo = {
 struct tdm_chipinfo tl1_tdma_chipinfo = {
        .id          = TDM_A,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V1,
        .same_src_fn = true,
        .adc_fn      = true,
        .reset_reg_offset = 1,
@@ -116,7 +125,7 @@ struct tdm_chipinfo tl1_tdma_chipinfo = {
 struct tdm_chipinfo tl1_tdmb_chipinfo = {
        .id          = TDM_B,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V1,
        .same_src_fn = true,
        .adc_fn      = true,
        .reset_reg_offset = 1,
@@ -126,7 +135,7 @@ struct tdm_chipinfo tl1_tdmb_chipinfo = {
 struct tdm_chipinfo tl1_tdmc_chipinfo = {
        .id          = TDM_C,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V1,
        .same_src_fn = true,
        .adc_fn      = true,
        .reset_reg_offset = 1,
@@ -136,7 +145,7 @@ struct tdm_chipinfo tl1_tdmc_chipinfo = {
 struct tdm_chipinfo tl1_tdminlb_chipinfo = {
        .id          = TDM_LB,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V1,
        .same_src_fn = true,
        .adc_fn      = true,
        .async_fifo  = true,
@@ -145,7 +154,7 @@ struct tdm_chipinfo tl1_tdminlb_chipinfo = {
 struct tdm_chipinfo sm1_tdma_chipinfo = {
        .id          = TDM_A,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .lane_cnt    = LANE_MAX0,
        .reset_reg_offset = 1,
@@ -155,7 +164,7 @@ struct tdm_chipinfo sm1_tdma_chipinfo = {
 struct tdm_chipinfo sm1_tdmb_chipinfo = {
        .id          = TDM_B,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .lane_cnt    = LANE_MAX3,
        .reset_reg_offset = 1,
@@ -165,7 +174,7 @@ struct tdm_chipinfo sm1_tdmb_chipinfo = {
 struct tdm_chipinfo sm1_tdmc_chipinfo = {
        .id          = TDM_C,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .lane_cnt    = LANE_MAX1,
        .reset_reg_offset = 1,
@@ -175,7 +184,7 @@ struct tdm_chipinfo sm1_tdmc_chipinfo = {
 struct tdm_chipinfo sm1_tdminlb_chipinfo = {
        .id          = TDM_LB,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .lane_cnt    = LANE_MAX3,
        .async_fifo  = true,
@@ -184,7 +193,7 @@ struct tdm_chipinfo sm1_tdminlb_chipinfo = {
 struct tdm_chipinfo tm2_tdma_chipinfo = {
        .id          = TDM_A,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .adc_fn      = true,
        .lane_cnt    = LANE_MAX3,
@@ -195,7 +204,7 @@ struct tdm_chipinfo tm2_tdma_chipinfo = {
 struct tdm_chipinfo tm2_tdmb_chipinfo = {
        .id          = TDM_B,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .adc_fn      = true,
        .lane_cnt    = LANE_MAX1,
@@ -206,7 +215,7 @@ struct tdm_chipinfo tm2_tdmb_chipinfo = {
 struct tdm_chipinfo tm2_tdmc_chipinfo = {
        .id          = TDM_C,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .adc_fn      = true,
        .lane_cnt    = LANE_MAX1,
@@ -217,7 +226,7 @@ struct tdm_chipinfo tm2_tdmc_chipinfo = {
 struct tdm_chipinfo tm2_tdminlb_chipinfo = {
        .id          = TDM_LB,
        .sclk_ws_inv = true,
-       .oe_fn       = true,
+       .oe_fn       = OE_FUNCTION_V2,
        .same_src_fn = true,
        .lane_cnt    = LANE_MAX3,
        .async_fifo  = true,