ASoC: rockchip: sai: Add support for RX/TX route map from DT

Signed-off-by: Shunhua Lan <lsh@rock-chips.com>
Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Change-Id: Ia25b4d39d2a3ead68b771ff24bd2a78168ef57d1
This commit is contained in:
Shunhua Lan
2024-02-28 16:05:40 +08:00
committed by Tao Huang
parent 93ebae336c
commit 6d567d8138
2 changed files with 114 additions and 0 deletions

View File

@@ -34,6 +34,8 @@
#define WAIT_TIME_MS_MAX 10000
#define QUIRK_ALWAYS_ON BIT(0)
#define MAX_LANES 4
enum fpw_mode {
FPW_ONE_BCLK_WIDTH,
FPW_ONE_SLOT_WIDTH,
@@ -53,6 +55,8 @@ struct rk_sai_dev {
unsigned int wait_time[SNDRV_PCM_STREAM_LAST + 1];
unsigned int tx_lanes;
unsigned int rx_lanes;
unsigned int sdi[MAX_LANES];
unsigned int sdo[MAX_LANES];
unsigned int quirks;
unsigned int version;
enum fpw_mode fpw;
@@ -590,6 +594,104 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream,
return 0;
}
static int rockchip_sai_path_check(struct rk_sai_dev *sai,
int num, bool is_rx)
{
unsigned int *data;
int i;
data = is_rx ? sai->sdi : sai->sdo;
for (i = 0; i < num; i++) {
if (data[i] >= MAX_LANES) {
dev_err(sai->dev, "%s[%d]: %d, Should less than: %d\n",
is_rx ? "RX" : "TX", i, data[i], MAX_LANES);
return -EINVAL;
}
}
return 0;
}
static void rockchip_sai_path_config(struct rk_sai_dev *sai,
int num, bool is_rx)
{
int i;
if (is_rx)
for (i = 0; i < num; i++)
regmap_update_bits(sai->regmap, SAI_PATH_SEL,
SAI_RX_PATH_MASK(i),
SAI_RX_PATH(i, sai->sdi[i]));
else
for (i = 0; i < num; i++)
regmap_update_bits(sai->regmap, SAI_PATH_SEL,
SAI_TX_PATH_MASK(i),
SAI_TX_PATH(i, sai->sdo[i]));
}
static int rockchip_sai_path_prepare(struct rk_sai_dev *sai,
struct device_node *np,
bool is_rx)
{
char *path_prop;
unsigned int *data;
int num, ret;
if (is_rx) {
path_prop = "rockchip,sai-rx-route";
data = sai->sdi;
} else {
path_prop = "rockchip,sai-tx-route";
data = sai->sdo;
}
num = of_count_phandle_with_args(np, path_prop, NULL);
if (num == -ENOENT) {
return 0;
} else if (num != MAX_LANES) {
dev_err(sai->dev, "The property size should be: %d, ret: %d\n",
MAX_LANES, num);
return -EINVAL;
}
ret = device_property_read_u32_array(sai->dev, path_prop, data, num);
if (ret < 0) {
dev_err(sai->dev, "Failed to read '%s': %d\n",
path_prop, ret);
return ret;
}
ret = rockchip_sai_path_check(sai, num, is_rx);
if (ret)
return ret;
rockchip_sai_path_config(sai, num, is_rx);
return 0;
}
static int rockchip_sai_parse_paths(struct rk_sai_dev *sai,
struct device_node *np)
{
int ret;
ret = rockchip_sai_path_prepare(sai, np, 0);
if (ret < 0) {
dev_err(sai->dev, "Failed to prepare TX path: %d\n", ret);
return ret;
}
ret = rockchip_sai_path_prepare(sai, np, 1);
if (ret < 0) {
dev_err(sai->dev, "Failed to prepare RX path: %d\n", ret);
return ret;
}
return ret;
}
static int rockchip_sai_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
@@ -1490,6 +1592,10 @@ static int rockchip_sai_probe(struct platform_device *pdev)
if (ret)
goto err_disable_hclk;
ret = rockchip_sai_parse_paths(sai, node);
if (ret)
goto err_disable_hclk;
ret = rockchip_sai_init_dai(sai, res, &dai);
if (ret)
goto err_disable_hclk;

View File

@@ -118,6 +118,14 @@
#define SAI_INTSR_TXUI_INA 0
#define SAI_INTSR_TXUI_ACT BIT(1)
/* PATH_SEL: Transfer / Receive Path Select Register */
#define SAI_RX_PATH_SHIFT(x) (8 + (x) * 2)
#define SAI_RX_PATH_MASK(x) (0x3 << SAI_RX_PATH_SHIFT(x))
#define SAI_RX_PATH(x, v) ((v) << SAI_RX_PATH_SHIFT(x))
#define SAI_TX_PATH_SHIFT(x) (0 + (x) * 2)
#define SAI_TX_PATH_MASK(x) (0x3 << SAI_TX_PATH_SHIFT(x))
#define SAI_TX_PATH(x, v) ((v) << SAI_TX_PATH_SHIFT(x))
/* XSHIFT: Transfer / Receive Frame Sync Shift Register */
#define SAI_XSHIFT_SEL_MASK GENMASK(23, 0)
#define SAI_XSHIFT_SEL(x) (x)