mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
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:
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user