diff options
-rw-r--r-- | sound/soc/fsl/fsl_asrc.c | 58 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_asrc.h | 1 |
2 files changed, 46 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); diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index 204ac19b5d52..5d2f021846c9 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h @@ -358,6 +358,7 @@ struct fsl_asrc { struct clk *ipg_clk; struct clk *spba_clk; struct clk *asrck_clk[ASRC_CLK_MAX_NUM]; + unsigned char *clk_map[2]; spinlock_t lock; struct snd_pcm_substream *substream[2]; |