From 12df5e18d85a4bc8578255a7dfbd0cd90bae4ae6 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 19 Feb 2024 10:09:22 +0800 Subject: [PATCH] ASoC: rockchip: sai: Add support for RK3576 Signed-off-by: Sugar Zhang Change-Id: Icc47d1970afcb4ec9c304952d44267c4c6521d98 --- sound/soc/rockchip/rockchip_sai.c | 68 ++++++++++++++++++++++++------- sound/soc/rockchip/rockchip_sai.h | 9 ++++ 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index 77499246ee59..e01de2930023 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -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; diff --git a/sound/soc/rockchip/rockchip_sai.h b/sound/soc/rockchip/rockchip_sai.h index 58e3aa58e1c1..f9e29e0dfb04 100644 --- a/sound/soc/rockchip/rockchip_sai.h +++ b/sound/soc/rockchip/rockchip_sai.h @@ -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 */