ASoC: rockchip: sai: Add support for RK3576

Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Change-Id: Icc47d1970afcb4ec9c304952d44267c4c6521d98
This commit is contained in:
Sugar Zhang
2024-02-19 10:09:22 +08:00
committed by Tao Huang
parent 6d4eba5dd5
commit 12df5e18d8
2 changed files with 62 additions and 15 deletions

View File

@@ -54,6 +54,7 @@ struct rk_sai_dev {
unsigned int tx_lanes;
unsigned int rx_lanes;
unsigned int quirks;
unsigned int version;
enum fpw_mode fpw;
int fw_ratio;
bool has_capture;
@@ -73,11 +74,53 @@ static const struct sai_of_quirks {
},
};
static int rockchip_sai_poll_clk_idle(struct rk_sai_dev *sai)
{
unsigned int reg, idle, val;
int ret;
if (sai->version > SAI_VER_2307) {
reg = SAI_STATUS;
idle = SAI_STATUS_FS_IDLE;
} else {
reg = SAI_XFER;
idle = SAI_XFER_FS_IDLE;
}
dev_dbg(sai->dev, "%s: ver: 0x%x\n", __func__, sai->version);
ret = regmap_read_poll_timeout_atomic(sai->regmap, reg, val,
(val & idle), 10, TIMEOUT_US);
if (ret < 0)
dev_warn(sai->dev, "Failed to idle FS\n");
return ret;
}
static int rockchip_sai_poll_stream_idle(struct rk_sai_dev *sai, int stream)
{
unsigned int reg, idle, val;
int ret;
if (sai->version > SAI_VER_2307) {
reg = SAI_STATUS;
idle = stream ? SAI_STATUS_RX_IDLE : SAI_STATUS_TX_IDLE;
} else {
reg = SAI_XFER;
idle = stream ? SAI_XFER_RX_IDLE : SAI_XFER_TX_IDLE;
}
ret = regmap_read_poll_timeout_atomic(sai->regmap, reg, val,
(val & idle), 10, TIMEOUT_US);
if (ret < 0)
dev_warn(sai->dev, "Failed to idle stream\n");
return ret;
}
static int rockchip_sai_runtime_suspend(struct device *dev)
{
struct rk_sai_dev *sai = dev_get_drvdata(dev);
unsigned int val;
int ret;
if (sai->is_master_mode)
regmap_update_bits(sai->regmap, SAI_XFER,
@@ -86,10 +129,7 @@ static int rockchip_sai_runtime_suspend(struct device *dev)
SAI_XFER_CLK_DIS |
SAI_XFER_FSS_DIS);
ret = regmap_read_poll_timeout_atomic(sai->regmap, SAI_XFER, val,
(val & SAI_XFER_FS_IDLE), 10, TIMEOUT_US);
if (ret < 0)
dev_warn(sai->dev, "Failed to idle FS\n");
rockchip_sai_poll_clk_idle(sai);
regcache_cache_only(sai->regmap, true);
/*
@@ -254,27 +294,20 @@ static void rockchip_sai_xfer_start(struct rk_sai_dev *sai, int stream)
static void rockchip_sai_xfer_stop(struct rk_sai_dev *sai, int stream)
{
unsigned int msk, val, clr, idle;
int ret;
unsigned int msk, val, clr;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
msk = SAI_XFER_TXS_MASK;
val = SAI_XFER_TXS_DIS;
clr = SAI_CLR_TXC;
idle = SAI_XFER_TX_IDLE;
} else {
msk = SAI_XFER_RXS_MASK;
val = SAI_XFER_RXS_DIS;
clr = SAI_CLR_RXC;
idle = SAI_XFER_RX_IDLE;
}
regmap_update_bits(sai->regmap, SAI_XFER, msk, val);
ret = regmap_read_poll_timeout_atomic(sai->regmap, SAI_XFER, val,
(val & idle), 10, TIMEOUT_US);
if (ret < 0)
dev_warn(sai->dev, "Failed to idle stream %d\n", stream);
rockchip_sai_poll_stream_idle(sai, stream);
rockchip_sai_clear(sai, clr);
}
@@ -730,6 +763,7 @@ static bool rockchip_sai_rd_reg(struct device *dev, unsigned int reg)
case SAI_RX_DATA_CNT:
case SAI_TX_SHIFT:
case SAI_RX_SHIFT:
case SAI_STATUS:
case SAI_VERSION:
return true;
default:
@@ -750,6 +784,8 @@ static bool rockchip_sai_volatile_reg(struct device *dev, unsigned int reg)
case SAI_RXDR:
case SAI_TX_DATA_CNT:
case SAI_RX_DATA_CNT:
case SAI_STATUS:
case SAI_VERSION:
return true;
default:
return false;
@@ -1444,6 +1480,8 @@ static int rockchip_sai_probe(struct platform_device *pdev)
return PTR_ERR(sai->hclk);
}
regmap_read(sai->regmap, SAI_VERSION, &sai->version);
ret = rockchip_sai_parse_quirks(sai);
if (ret)
return ret;

View File

@@ -132,6 +132,14 @@
#define SAI_FIFOLR_XFL0_SHIFT 0
#define SAI_FIFOLR_XFL0_MASK GENMASK(5, 0)
/* STATUS Status Register (VERSION > 0x23070000) */
#define SAI_STATUS_RX_IDLE BIT(3)
#define SAI_STATUS_TX_IDLE BIT(2)
#define SAI_STATUS_FS_IDLE BIT(1)
/* VERSION */
#define SAI_VER_2307 0x23070000
/* SAI Registers */
#define SAI_TXCR (0x0000)
#define SAI_FSCR (0x0004)
@@ -160,6 +168,7 @@
#define SAI_RX_DATA_CNT (0x0060)
#define SAI_TX_SHIFT (0x0064)
#define SAI_RX_SHIFT (0x0068)
#define SAI_STATUS (0x006c)
#define SAI_VERSION (0x0070)
#endif /* _ROCKCHIP_SAI_H */