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