mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user