summaryrefslogtreecommitdiff
path: root/sound/soc/fsl/fsl_asrc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/fsl/fsl_asrc.c')
-rw-r--r--sound/soc/fsl/fsl_asrc.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index d1290fb1b020..9293f67035a9 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -50,6 +50,7 @@ static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = {
* The following tables map the relationship between asrc_inclk/asrc_outclk in
* fsl_asrc.h and the registers of ASRCSR
*/
+#define CLK_MAP_NUM 48
static unsigned char input_clk_map_imx35[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -101,7 +102,6 @@ static unsigned char output_clk_map_imx8_1[] = {
0x0, 0x1, 0x2, 0x3, 0xb, 0xc, 0xf, 0xf, 0xd, 0xe, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
0x4, 0x5, 0x6, 0xf, 0x8, 0x9, 0xa, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
};
-static unsigned char *clk_map[2];
/**
* Request ASRC pair
@@ -358,8 +358,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2
}
/* Validate input and output clock sources */
- clk_index[IN] = clk_map[IN][config->inclk];
- clk_index[OUT] = clk_map[OUT][config->outclk];
+ clk_index[IN] = asrc_priv->clk_map[IN][config->inclk];
+ clk_index[OUT] = asrc_priv->clk_map[OUT][config->outclk];
/* We only have output clock for ideal ratio mode */
clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]];
@@ -539,6 +539,30 @@ struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
}
EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel);
+static int fsl_asrc_select_clk(struct fsl_asrc *asrc_priv, int rate, int index)
+{
+ int clk_rate;
+ int clk_index;
+ int i = 0;
+
+ /*select proper clock for asrc p2p mode*/
+ for (i = 0; i < CLK_MAP_NUM; i++) {
+ clk_index = asrc_priv->clk_map[index][i];
+ clk_rate = clk_get_rate(asrc_priv->asrck_clk[clk_index]);
+ if (clk_rate != 0 && clk_rate/rate <= 1024 &&
+ clk_rate%rate == 0)
+ break;
+ }
+
+ if (i == CLK_MAP_NUM)
+ clk_index = index ? OUTCLK_ASRCK1_CLK : INCLK_NONE;
+ else
+ clk_index = i;
+
+
+ return clk_index;
+}
+
static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -573,8 +597,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
config.pair = pair->index;
config.channel_num = channels;
- config.inclk = INCLK_ASRCK1_CLK;
- config.outclk = OUTCLK_ASRCK1_CLK;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
config.input_word_width = width;
@@ -582,6 +604,11 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
config.input_sample_rate = rate;
config.output_sample_rate = asrc_priv->asrc_rate;
+ config.inclk = fsl_asrc_select_clk(asrc_priv,
+ config.input_sample_rate, IN);
+ config.outclk = fsl_asrc_select_clk(asrc_priv,
+ config.output_sample_rate, OUT);
+
ret = fsl_asrc_config_pair(pair, false, true);
if (ret) {
dev_err(dai->dev, "fail to config asrc pair\n");
@@ -594,6 +621,11 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
config.input_sample_rate = asrc_priv->asrc_rate;
config.output_sample_rate = rate;
+ config.inclk = fsl_asrc_select_clk(asrc_priv,
+ config.input_sample_rate, IN);
+ config.outclk = fsl_asrc_select_clk(asrc_priv,
+ config.output_sample_rate, OUT);
+
ret = fsl_asrc_config_pair(pair, true, false);
if (ret) {
dev_err(dai->dev, "fail to config asrc pair\n");
@@ -1073,26 +1105,26 @@ static int fsl_asrc_probe(struct platform_device *pdev)
asrc_priv->channel_bits = 3;
strncpy(asrc_priv->name, "mxc_asrc",
sizeof(asrc_priv->name) - 1);
- clk_map[IN] = input_clk_map_imx35;
- clk_map[OUT] = output_clk_map_imx35;
+ asrc_priv->clk_map[IN] = input_clk_map_imx35;
+ asrc_priv->clk_map[OUT] = output_clk_map_imx35;
} else if (of_device_is_compatible(np, "fsl,imx53-asrc")) {
asrc_priv->channel_bits = 4;
strncpy(asrc_priv->name, "mxc_asrc",
sizeof(asrc_priv->name) - 1);
- clk_map[IN] = input_clk_map_imx53;
- clk_map[OUT] = output_clk_map_imx53;
+ asrc_priv->clk_map[IN] = input_clk_map_imx53;
+ asrc_priv->clk_map[OUT] = output_clk_map_imx53;
} else if (of_device_is_compatible(np, "fsl,imx8qm-asrc0")) {
asrc_priv->channel_bits = 4;
strncpy(asrc_priv->name, "mxc_asrc",
sizeof(asrc_priv->name) - 1);
- clk_map[IN] = input_clk_map_imx8_0;
- clk_map[OUT] = output_clk_map_imx8_0;
+ asrc_priv->clk_map[IN] = input_clk_map_imx8_0;
+ asrc_priv->clk_map[OUT] = output_clk_map_imx8_0;
} else if (of_device_is_compatible(np, "fsl,imx8qm-asrc1")) {
asrc_priv->channel_bits = 4;
strncpy(asrc_priv->name, "mxc_asrc1",
sizeof(asrc_priv->name) - 1);
- clk_map[IN] = input_clk_map_imx8_1;
- clk_map[OUT] = output_clk_map_imx8_1;
+ asrc_priv->clk_map[IN] = input_clk_map_imx8_1;
+ asrc_priv->clk_map[OUT] = output_clk_map_imx8_1;
}
ret = fsl_asrc_init(asrc_priv);