ASoC: rockchip: i2s-tdm: Simplify clk sync on TRCM mode

There are clk sync issue on TRCM mode for RK3308/RK1808/PX30,
and the previous soluation is to make TX/RX reset at the same
time to fix that. Unfortunately, it fails on PX30-I2S0, because
the reset-TX and reset-RX bits can't be addressed at the same time.

Now, we use another way to fix it:

  reset_control_assert(i2s_tdm->tx_reset);
  reset_control_assert(i2s_tdm->rx_reset);
                   |
          gate the i2s src clk
                   |
  reset_control_deassert(i2s_tdm->tx_reset);
  reset_control_deassert(i2s_tdm->rx_reset);
                   |
         ungate the i2s src clk

as shown above, use the pair gate/ungate src clk to make the
TX/RX reset at the same time.

Change-Id: Ib320ad13350516100eb11c7717e1bd9005abaf39
Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
This commit is contained in:
Sugar Zhang
2023-03-15 09:20:34 +08:00
committed by Tao Huang
parent 7ae6fd2b0e
commit 5f7f65028a
2 changed files with 213 additions and 187 deletions

View File

@@ -85,6 +85,8 @@ struct txrx_config {
u32 rxonly;
};
struct rk_i2s_tdm_dev;
struct rk_i2s_soc_data {
u32 softrst_offset;
u32 grf_reg_offset;
@@ -92,6 +94,7 @@ struct rk_i2s_soc_data {
int config_count;
const struct txrx_config *configs;
int (*init)(struct device *dev, u32 addr);
void (*src_clk_ctrl)(struct rk_i2s_tdm_dev *i2s_tdm, bool en);
};
struct rk_i2s_tdm_dev {
@@ -126,9 +129,8 @@ struct rk_i2s_tdm_dev {
struct pinctrl_state *clk_state;
const struct rk_i2s_soc_data *soc_data;
#ifdef HAVE_SYNC_RESET
int id;
void __iomem *cru_base;
int tx_reset_id;
int rx_reset_id;
#endif
bool is_master_mode;
bool io_multiplex;
@@ -229,148 +231,146 @@ static inline bool is_dma_active(struct rk_i2s_tdm_dev *i2s_tdm, int stream)
}
#ifdef HAVE_SYNC_RESET
#if defined(CONFIG_ARM) && !defined(writeq)
static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
static void rockchip_i2s_tdm_src_clk_ctrl(struct rk_i2s_tdm_dev *i2s_tdm, bool en,
unsigned int gate_reg, unsigned int gate_val,
unsigned int sel_reg)
{
asm volatile("strd %0, %H0, [%1]" : : "r" (val), "r" (addr));
int val = readl(i2s_tdm->cru_base + sel_reg);
if (!gate_reg || !sel_reg)
return;
if (IS_I2S_CLK_SRC_MCLKIN(val) && en)
writel(I2S_CLK_SRC_MCLKIN, i2s_tdm->cru_base + sel_reg);
writel(gate_val, i2s_tdm->cru_base + gate_reg);
if (IS_I2S_CLK_SRC_MCLKIN(val) && !en)
writel(I2S_CLK_SRC_PLL, i2s_tdm->cru_base + sel_reg);
}
static void rockchip_i2s_tdm_px30_src_clk_ctrl(struct rk_i2s_tdm_dev *i2s_tdm, bool en)
{
unsigned int gate_reg = 0, gate_val = 0, sel_reg = 0;
switch (i2s_tdm->clk_trcm) {
case I2S_CKR_TRCM_TXONLY:
sel_reg = PX30_CLKSEL_CON28_I2S0_TX;
gate_reg = PX30_CLKGATE_CON9;
gate_val = en ? PX30_CLKGATE_CON9_I2S0_TX_PLL_EN :
PX30_CLKGATE_CON9_I2S0_TX_PLL_DIS;
break;
case I2S_CKR_TRCM_RXONLY:
sel_reg = PX30_CLKSEL_CON58_I2S0_RX;
gate_reg = PX30_CLKGATE_CON17;
gate_val = en ? PX30_CLKGATE_CON17_I2S0_RX_PLL_EN :
PX30_CLKGATE_CON17_I2S0_RX_PLL_DIS;
break;
}
rockchip_i2s_tdm_src_clk_ctrl(i2s_tdm, en, gate_reg, gate_val, sel_reg);
}
static void rockchip_i2s_tdm_rk1808_src_clk_ctrl(struct rk_i2s_tdm_dev *i2s_tdm, bool en)
{
unsigned int gate_reg = 0, gate_val = 0, sel_reg = 0;
switch (i2s_tdm->clk_trcm) {
case I2S_CKR_TRCM_TXONLY:
sel_reg = RK1808_CLKSEL_CON32_I2S0_TX;
gate_reg = RK1808_CLKGATE_CON17;
gate_val = en ? RK1808_CLKGATE_CON17_I2S0_TX_PLL_EN :
RK1808_CLKGATE_CON17_I2S0_TX_PLL_DIS;
break;
case I2S_CKR_TRCM_RXONLY:
sel_reg = RK1808_CLKSEL_CON34_I2S0_RX;
gate_reg = RK1808_CLKGATE_CON18;
gate_val = en ? RK1808_CLKGATE_CON18_I2S0_RX_PLL_EN :
RK1808_CLKGATE_CON18_I2S0_RX_PLL_DIS;
break;
}
rockchip_i2s_tdm_src_clk_ctrl(i2s_tdm, en, gate_reg, gate_val, sel_reg);
}
static void rockchip_i2s_tdm_rk3308_src_clk_ctrl(struct rk_i2s_tdm_dev *i2s_tdm, bool en)
{
unsigned int gate_reg = 0, gate_val = 0, sel_reg = 0;
/* I2S_8CH_2 used for internal and TRCM-none mode default */
switch (i2s_tdm->id) {
case 0:
switch (i2s_tdm->clk_trcm) {
case I2S_CKR_TRCM_TXONLY:
sel_reg = RK3308_CLKSEL_CON52_I2S0_TX;
gate_reg = RK3308_CLKGATE_CON10;
gate_val = en ? RK3308_CLKGATE_CON10_I2S0_TX_PLL_EN :
RK3308_CLKGATE_CON10_I2S0_TX_PLL_DIS;
break;
case I2S_CKR_TRCM_RXONLY:
sel_reg = RK3308_CLKSEL_CON54_I2S0_RX;
gate_reg = RK3308_CLKGATE_CON11;
gate_val = en ? RK3308_CLKGATE_CON11_I2S0_RX_PLL_EN :
RK3308_CLKGATE_CON11_I2S0_RX_PLL_DIS;
break;
}
break;
case 1:
switch (i2s_tdm->clk_trcm) {
case I2S_CKR_TRCM_TXONLY:
sel_reg = RK3308_CLKSEL_CON56_I2S1_TX;
gate_reg = RK3308_CLKGATE_CON11;
gate_val = en ? RK3308_CLKGATE_CON11_I2S1_TX_PLL_EN :
RK3308_CLKGATE_CON11_I2S1_TX_PLL_DIS;
break;
case I2S_CKR_TRCM_RXONLY:
sel_reg = RK3308_CLKSEL_CON58_I2S1_RX;
gate_reg = RK3308_CLKGATE_CON11;
gate_val = en ? RK3308_CLKGATE_CON11_I2S1_RX_PLL_EN :
RK3308_CLKGATE_CON11_I2S1_RX_PLL_DIS;
break;
}
break;
}
rockchip_i2s_tdm_src_clk_ctrl(i2s_tdm, en, gate_reg, gate_val, sel_reg);
}
#define writeq(v,c) ({ __iowmb(); __raw_writeq((__force u64) cpu_to_le64(v), c); })
#endif
static void rockchip_i2s_tdm_reset_assert(struct rk_i2s_tdm_dev *i2s_tdm)
{
int tx_bank, rx_bank, tx_offset, rx_offset, tx_id, rx_id;
void __iomem *cru_reset, *addr;
unsigned long flags;
u64 val;
if (!i2s_tdm->cru_base || !i2s_tdm->soc_data || !i2s_tdm->is_master_mode)
return;
tx_id = i2s_tdm->tx_reset_id;
rx_id = i2s_tdm->rx_reset_id;
if (tx_id < 0 || rx_id < 0)
if (IS_ERR_OR_NULL(i2s_tdm->tx_reset) || IS_ERR_OR_NULL(i2s_tdm->rx_reset))
return;
tx_bank = tx_id / 16;
tx_offset = tx_id % 16;
rx_bank = rx_id / 16;
rx_offset = rx_id % 16;
reset_control_assert(i2s_tdm->tx_reset);
reset_control_assert(i2s_tdm->rx_reset);
dev_dbg(i2s_tdm->dev,
"tx_bank: %d, rx_bank: %d,tx_offset: %d, rx_offset: %d\n",
tx_bank, rx_bank, tx_offset, rx_offset);
cru_reset = i2s_tdm->cru_base + i2s_tdm->soc_data->softrst_offset;
switch (abs(tx_bank - rx_bank)) {
case 0:
writel(BIT(tx_offset) | BIT(rx_offset) |
(BIT(tx_offset) << 16) | (BIT(rx_offset) << 16),
cru_reset + (tx_bank * 4));
break;
case 1:
if (tx_bank < rx_bank) {
val = BIT(rx_offset) | (BIT(rx_offset) << 16);
val <<= 32;
val |= BIT(tx_offset) | (BIT(tx_offset) << 16);
addr = cru_reset + (tx_bank * 4);
} else {
val = BIT(tx_offset) | (BIT(tx_offset) << 16);
val <<= 32;
val |= BIT(rx_offset) | (BIT(rx_offset) << 16);
addr = cru_reset + (rx_bank * 4);
}
if (IS_ALIGNED((uintptr_t)addr, 8)) {
writeq(val, addr);
break;
}
fallthrough;
default:
local_irq_save(flags);
writel(BIT(tx_offset) | (BIT(tx_offset) << 16),
cru_reset + (tx_bank * 4));
writel(BIT(rx_offset) | (BIT(rx_offset) << 16),
cru_reset + (rx_bank * 4));
local_irq_restore(flags);
break;
}
/* delay for reset assert done */
udelay(10);
}
static void rockchip_i2s_tdm_reset_deassert(struct rk_i2s_tdm_dev *i2s_tdm)
{
int tx_bank, rx_bank, tx_offset, rx_offset, tx_id, rx_id;
void __iomem *cru_reset, *addr;
unsigned long flags;
u64 val;
if (!i2s_tdm->cru_base || !i2s_tdm->soc_data || !i2s_tdm->is_master_mode)
return;
tx_id = i2s_tdm->tx_reset_id;
rx_id = i2s_tdm->rx_reset_id;
if (tx_id < 0 || rx_id < 0)
if (IS_ERR_OR_NULL(i2s_tdm->tx_reset) || IS_ERR_OR_NULL(i2s_tdm->rx_reset))
return;
tx_bank = tx_id / 16;
tx_offset = tx_id % 16;
rx_bank = rx_id / 16;
rx_offset = rx_id % 16;
if (i2s_tdm->soc_data && i2s_tdm->soc_data->src_clk_ctrl)
i2s_tdm->soc_data->src_clk_ctrl(i2s_tdm, 0);
dev_dbg(i2s_tdm->dev,
"tx_bank: %d, rx_bank: %d,tx_offset: %d, rx_offset: %d\n",
tx_bank, rx_bank, tx_offset, rx_offset);
reset_control_deassert(i2s_tdm->tx_reset);
reset_control_deassert(i2s_tdm->rx_reset);
cru_reset = i2s_tdm->cru_base + i2s_tdm->soc_data->softrst_offset;
if (i2s_tdm->soc_data && i2s_tdm->soc_data->src_clk_ctrl)
i2s_tdm->soc_data->src_clk_ctrl(i2s_tdm, 1);
switch (abs(tx_bank - rx_bank)) {
case 0:
writel((BIT(tx_offset) << 16) | (BIT(rx_offset) << 16),
cru_reset + (tx_bank * 4));
break;
case 1:
if (tx_bank < rx_bank) {
val = (BIT(rx_offset) << 16);
val <<= 32;
val |= (BIT(tx_offset) << 16);
addr = cru_reset + (tx_bank * 4);
} else {
val = (BIT(tx_offset) << 16);
val <<= 32;
val |= (BIT(rx_offset) << 16);
addr = cru_reset + (rx_bank * 4);
}
if (IS_ALIGNED((uintptr_t)addr, 8)) {
writeq(val, addr);
break;
}
fallthrough;
default:
local_irq_save(flags);
writel((BIT(tx_offset) << 16),
cru_reset + (tx_bank * 4));
writel((BIT(rx_offset) << 16),
cru_reset + (rx_bank * 4));
local_irq_restore(flags);
break;
}
/* delay for reset deassert done */
udelay(10);
}
/*
* make sure both tx and rx are reset at the same time for sync lrck
* when clk_trcm > 0
*/
static void rockchip_i2s_tdm_sync_reset(struct rk_i2s_tdm_dev *i2s_tdm)
{
rockchip_i2s_tdm_reset_assert(i2s_tdm);
rockchip_i2s_tdm_reset_deassert(i2s_tdm);
}
#else
static inline void rockchip_i2s_tdm_reset_assert(struct rk_i2s_tdm_dev *i2s_tdm)
{
@@ -378,44 +378,35 @@ static inline void rockchip_i2s_tdm_reset_assert(struct rk_i2s_tdm_dev *i2s_tdm)
static inline void rockchip_i2s_tdm_reset_deassert(struct rk_i2s_tdm_dev *i2s_tdm)
{
}
static inline void rockchip_i2s_tdm_sync_reset(struct rk_i2s_tdm_dev *i2s_tdm)
{
}
#endif
static void rockchip_i2s_tdm_reset(struct reset_control *rc)
static void rockchip_i2s_tdm_reset(struct rk_i2s_tdm_dev *i2s_tdm, unsigned int clr)
{
if (IS_ERR_OR_NULL(rc))
return;
if ((clr & I2S_CLR_TXC) && !IS_ERR_OR_NULL(i2s_tdm->tx_reset)) {
reset_control_assert(i2s_tdm->tx_reset);
/* delay for reset assert done */
udelay(10);
reset_control_deassert(i2s_tdm->tx_reset);
/* delay for reset deassert done */
udelay(10);
}
reset_control_assert(rc);
/* delay for reset assert done */
udelay(10);
reset_control_deassert(rc);
/* delay for reset deassert done */
udelay(10);
if ((clr & I2S_CLR_RXC) && !IS_ERR_OR_NULL(i2s_tdm->rx_reset)) {
reset_control_assert(i2s_tdm->rx_reset);
/* delay for reset assert done */
udelay(10);
reset_control_deassert(i2s_tdm->rx_reset);
/* delay for reset deassert done */
udelay(10);
}
}
static int rockchip_i2s_tdm_clear(struct rk_i2s_tdm_dev *i2s_tdm,
unsigned int clr)
{
struct reset_control *rst = NULL;
unsigned int val = 0;
int ret = 0;
switch (clr) {
case I2S_CLR_TXC:
rst = i2s_tdm->tx_reset;
break;
case I2S_CLR_RXC:
rst = i2s_tdm->rx_reset;
break;
case I2S_CLR_TXC | I2S_CLR_RXC:
break;
default:
return -EINVAL;
}
regmap_update_bits(i2s_tdm->regmap, I2S_CLR, clr, clr);
ret = regmap_read_poll_timeout_atomic(i2s_tdm->regmap, I2S_CLR, val,
!(val & clr), 10, 100);
@@ -453,10 +444,7 @@ static int rockchip_i2s_tdm_clear(struct rk_i2s_tdm_dev *i2s_tdm,
return 0;
reset:
if (i2s_tdm->clk_trcm)
rockchip_i2s_tdm_sync_reset(i2s_tdm);
else
rockchip_i2s_tdm_reset(rst);
rockchip_i2s_tdm_reset(i2s_tdm, clr);
return 0;
}
@@ -2282,6 +2270,9 @@ static const struct rk_i2s_soc_data px30_i2s_soc_data = {
.configs = px30_txrx_config,
.config_count = ARRAY_SIZE(px30_txrx_config),
.init = common_soc_init,
#ifdef HAVE_SYNC_RESET
.src_clk_ctrl = rockchip_i2s_tdm_px30_src_clk_ctrl,
#endif
};
static const struct rk_i2s_soc_data rk1808_i2s_soc_data = {
@@ -2289,6 +2280,9 @@ static const struct rk_i2s_soc_data rk1808_i2s_soc_data = {
.configs = rk1808_txrx_config,
.config_count = ARRAY_SIZE(rk1808_txrx_config),
.init = common_soc_init,
#ifdef HAVE_SYNC_RESET
.src_clk_ctrl = rockchip_i2s_tdm_rk1808_src_clk_ctrl,
#endif
};
static const struct rk_i2s_soc_data rk3308_i2s_soc_data = {
@@ -2298,6 +2292,9 @@ static const struct rk_i2s_soc_data rk3308_i2s_soc_data = {
.configs = rk3308_txrx_config,
.config_count = ARRAY_SIZE(rk3308_txrx_config),
.init = common_soc_init,
#ifdef HAVE_SYNC_RESET
.src_clk_ctrl = rockchip_i2s_tdm_rk3308_src_clk_ctrl,
#endif
};
static const struct rk_i2s_soc_data rk3568_i2s_soc_data = {
@@ -2339,26 +2336,6 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = {
{},
};
#ifdef HAVE_SYNC_RESET
static int of_i2s_resetid_get(struct device_node *node,
const char *id)
{
struct of_phandle_args args;
int index = 0;
int ret;
if (id)
index = of_property_match_string(node,
"reset-names", id);
ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
index, &args);
if (ret)
return ret;
return args.args[0];
}
#endif
static int rockchip_i2s_tdm_dai_prepare(struct platform_device *pdev,
struct snd_soc_dai_driver **soc_dai)
{
@@ -2878,24 +2855,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
}
}
#ifdef HAVE_SYNC_RESET
sync = of_device_is_compatible(node, "rockchip,px30-i2s-tdm") ||
of_device_is_compatible(node, "rockchip,rk1808-i2s-tdm") ||
of_device_is_compatible(node, "rockchip,rk3308-i2s-tdm");
if (i2s_tdm->clk_trcm && sync) {
struct device_node *cru_node;
cru_node = of_parse_phandle(node, "rockchip,cru", 0);
i2s_tdm->cru_base = of_iomap(cru_node, 0);
if (!i2s_tdm->cru_base)
return -ENOENT;
i2s_tdm->tx_reset_id = of_i2s_resetid_get(node, "tx-m");
i2s_tdm->rx_reset_id = of_i2s_resetid_get(node, "rx-m");
}
#endif
i2s_tdm->tx_reset = devm_reset_control_get(&pdev->dev, "tx-m");
if (IS_ERR(i2s_tdm->tx_reset)) {
ret = PTR_ERR(i2s_tdm->tx_reset);
@@ -3017,6 +2976,23 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
return ret;
}
#ifdef HAVE_SYNC_RESET
sync = of_device_is_compatible(node, "rockchip,px30-i2s-tdm") ||
of_device_is_compatible(node, "rockchip,rk1808-i2s-tdm") ||
of_device_is_compatible(node, "rockchip,rk3308-i2s-tdm");
if (i2s_tdm->clk_trcm && sync) {
struct device_node *cru_node;
cru_node = of_parse_phandle(node, "rockchip,cru", 0);
i2s_tdm->cru_base = of_iomap(cru_node, 0);
if (!i2s_tdm->cru_base)
return -ENOENT;
i2s_tdm->id = (res->start >> 16) & GENMASK(3, 0);
}
#endif
/*
* MUST: after pm_runtime_enable step, any register R/W
* should be wrapped with pm_runtime_get_sync/put.

View File

@@ -324,7 +324,25 @@ enum {
#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16))
/* PX30 GRF CONFIGS*/
/* I2Sx CLK SRC Mux Common Define */
#define I2S_CLK_SRC(v) (((v) & GENMASK(11, 10)) >> 10)
#define I2S_CLK_SRC_MCLKIN HIWORD_UPDATE(2, 11, 10)
#define I2S_CLK_SRC_PLL HIWORD_UPDATE(0, 11, 10)
#define IS_I2S_CLK_SRC_MCLKIN(v) (I2S_CLK_SRC(v) == 2)
/* PX30 CRU CONFIGS */
#define PX30_CLKSEL_CON28_I2S0_TX 0x170
#define PX30_CLKSEL_CON58_I2S0_RX 0x1e8
#define PX30_CLKGATE_CON9 0x224
#define PX30_CLKGATE_CON9_I2S0_TX_PLL_DIS HIWORD_UPDATE(1, 12, 12)
#define PX30_CLKGATE_CON9_I2S0_TX_PLL_EN HIWORD_UPDATE(0, 12, 12)
#define PX30_CLKGATE_CON17 0x244
#define PX30_CLKGATE_CON17_I2S0_RX_PLL_DIS HIWORD_UPDATE(1, 0, 0)
#define PX30_CLKGATE_CON17_I2S0_RX_PLL_EN HIWORD_UPDATE(0, 0, 0)
/* PX30 GRF CONFIGS */
#define PX30_I2S0_CLK_IN_SRC_FROM_TX HIWORD_UPDATE(1, 13, 12)
#define PX30_I2S0_CLK_IN_SRC_FROM_RX HIWORD_UPDATE(2, 13, 12)
#define PX30_I2S0_MCLK_OUT_SRC_FROM_TX HIWORD_UPDATE(1, 5, 5)
@@ -336,7 +354,19 @@ enum {
#define PX30_I2S0_CLK_RXONLY \
(PX30_I2S0_MCLK_OUT_SRC_FROM_RX | PX30_I2S0_CLK_IN_SRC_FROM_RX)
/* RK1808 GRF CONFIGS*/
/* RK1808 CRU CONFIGS */
#define RK1808_CLKSEL_CON32_I2S0_TX 0x180
#define RK1808_CLKSEL_CON34_I2S0_RX 0x188
#define RK1808_CLKGATE_CON17 0x274
#define RK1808_CLKGATE_CON17_I2S0_TX_PLL_DIS HIWORD_UPDATE(1, 12, 12)
#define RK1808_CLKGATE_CON17_I2S0_TX_PLL_EN HIWORD_UPDATE(0, 12, 12)
#define RK1808_CLKGATE_CON18 0x278
#define RK1808_CLKGATE_CON18_I2S0_RX_PLL_DIS HIWORD_UPDATE(1, 0, 0)
#define RK1808_CLKGATE_CON18_I2S0_RX_PLL_EN HIWORD_UPDATE(0, 0, 0)
/* RK1808 GRF CONFIGS */
#define RK1808_I2S0_MCLK_OUT_SRC_FROM_RX HIWORD_UPDATE(1, 2, 2)
#define RK1808_I2S0_MCLK_OUT_SRC_FROM_TX HIWORD_UPDATE(0, 2, 2)
#define RK1808_I2S0_CLK_IN_SRC_FROM_TX HIWORD_UPDATE(1, 1, 0)
@@ -348,7 +378,27 @@ enum {
#define RK1808_I2S0_CLK_RXONLY \
(RK1808_I2S0_MCLK_OUT_SRC_FROM_RX | RK1808_I2S0_CLK_IN_SRC_FROM_RX)
/* RK3308 GRF CONFIGS*/
/* RK3308 CRU CONFIGS */
#define RK3308_CLKSEL_CON52_I2S0_TX 0x1d0
#define RK3308_CLKSEL_CON54_I2S0_RX 0x1d8
#define RK3308_CLKSEL_CON56_I2S1_TX 0x1e0
#define RK3308_CLKSEL_CON58_I2S1_RX 0x1e8
#define RK3308_CLKGATE_CON10 0x328
#define RK3308_CLKGATE_CON10_I2S0_TX_PLL_DIS HIWORD_UPDATE(1, 12, 12)
#define RK3308_CLKGATE_CON10_I2S0_TX_PLL_EN HIWORD_UPDATE(0, 12, 12)
#define RK3308_CLKGATE_CON11 0x32c
#define RK3308_CLKGATE_CON11_I2S0_RX_PLL_DIS HIWORD_UPDATE(1, 0, 0)
#define RK3308_CLKGATE_CON11_I2S0_RX_PLL_EN HIWORD_UPDATE(0, 0, 0)
#define RK3308_CLKGATE_CON11_I2S1_TX_PLL_DIS HIWORD_UPDATE(1, 4, 4)
#define RK3308_CLKGATE_CON11_I2S1_TX_PLL_EN HIWORD_UPDATE(0, 4, 4)
#define RK3308_CLKGATE_CON11_I2S1_RX_PLL_DIS HIWORD_UPDATE(1, 8, 8)
#define RK3308_CLKGATE_CON11_I2S1_RX_PLL_EN HIWORD_UPDATE(0, 8, 8)
/* RK3308 GRF CONFIGS */
#define RK3308_I2S0_8CH_MCLK_OUT_SRC_FROM_RX HIWORD_UPDATE(1, 10, 10)
#define RK3308_I2S0_8CH_MCLK_OUT_SRC_FROM_TX HIWORD_UPDATE(0, 10, 10)
#define RK3308_I2S0_8CH_CLK_IN_RX_SRC_FROM_TX HIWORD_UPDATE(1, 9, 9)