Support BCLK input clock in tlv320aic31xx

Merge series from Ariel D'Alessandro <ariel.dalessandro@collabora.com>:

	This patchset modifies the tlv320aic31xx driver to update its sysclk if
	BCLK is used as the input clock. This allows to be used by the generic
	fsl-asoc-card, without having to add a specific driver.
This commit is contained in:
Mark Brown 2021-11-22 23:56:00 +00:00
commit 21b159264d
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 83 additions and 36 deletions

View File

@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
@ -169,6 +170,7 @@ struct aic31xx_priv {
struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
struct snd_soc_jack *jack;
u32 sysclk_id;
unsigned int sysclk;
u8 p_div;
int rate_div_line;
@ -180,6 +182,7 @@ struct aic31xx_priv {
struct aic31xx_rate_divs {
u32 mclk_p;
u32 rate;
u8 pll_r;
u8 pll_j;
u16 pll_d;
u16 dosr;
@ -192,51 +195,71 @@ struct aic31xx_rate_divs {
/* ADC dividers can be disabled by configuring them to 0 */
static const struct aic31xx_rate_divs aic31xx_divs[] = {
/* mclk/p rate pll: j d dosr ndac mdac aors nadc madc */
/* mclk/p rate pll: r j d dosr ndac mdac aors nadc madc */
/* 8k rate */
{12000000, 8000, 8, 1920, 128, 48, 2, 128, 48, 2},
{12000000, 8000, 8, 1920, 128, 32, 3, 128, 32, 3},
{12500000, 8000, 7, 8643, 128, 48, 2, 128, 48, 2},
{ 512000, 8000, 4, 48, 0, 128, 48, 2, 128, 48, 2},
{12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2},
{12000000, 8000, 1, 8, 1920, 128, 32, 3, 128, 32, 3},
{12500000, 8000, 1, 7, 8643, 128, 48, 2, 128, 48, 2},
/* 11.025k rate */
{12000000, 11025, 7, 5264, 128, 32, 2, 128, 32, 2},
{12000000, 11025, 8, 4672, 128, 24, 3, 128, 24, 3},
{12500000, 11025, 7, 2253, 128, 32, 2, 128, 32, 2},
{ 705600, 11025, 3, 48, 0, 128, 24, 3, 128, 24, 3},
{12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2},
{12000000, 11025, 1, 8, 4672, 128, 24, 3, 128, 24, 3},
{12500000, 11025, 1, 7, 2253, 128, 32, 2, 128, 32, 2},
/* 16k rate */
{12000000, 16000, 8, 1920, 128, 24, 2, 128, 24, 2},
{12000000, 16000, 8, 1920, 128, 16, 3, 128, 16, 3},
{12500000, 16000, 7, 8643, 128, 24, 2, 128, 24, 2},
{ 512000, 16000, 4, 48, 0, 128, 16, 3, 128, 16, 3},
{ 1024000, 16000, 2, 48, 0, 128, 16, 3, 128, 16, 3},
{12000000, 16000, 1, 8, 1920, 128, 24, 2, 128, 24, 2},
{12000000, 16000, 1, 8, 1920, 128, 16, 3, 128, 16, 3},
{12500000, 16000, 1, 7, 8643, 128, 24, 2, 128, 24, 2},
/* 22.05k rate */
{12000000, 22050, 7, 5264, 128, 16, 2, 128, 16, 2},
{12000000, 22050, 8, 4672, 128, 12, 3, 128, 12, 3},
{12500000, 22050, 7, 2253, 128, 16, 2, 128, 16, 2},
{ 705600, 22050, 4, 36, 0, 128, 12, 3, 128, 12, 3},
{ 1411200, 22050, 2, 36, 0, 128, 12, 3, 128, 12, 3},
{12000000, 22050, 1, 7, 5264, 128, 16, 2, 128, 16, 2},
{12000000, 22050, 1, 8, 4672, 128, 12, 3, 128, 12, 3},
{12500000, 22050, 1, 7, 2253, 128, 16, 2, 128, 16, 2},
/* 32k rate */
{12000000, 32000, 8, 1920, 128, 12, 2, 128, 12, 2},
{12000000, 32000, 8, 1920, 128, 8, 3, 128, 8, 3},
{12500000, 32000, 7, 8643, 128, 12, 2, 128, 12, 2},
{ 1024000, 32000, 2, 48, 0, 128, 12, 2, 128, 12, 2},
{ 2048000, 32000, 1, 48, 0, 128, 12, 2, 128, 12, 2},
{12000000, 32000, 1, 8, 1920, 128, 12, 2, 128, 12, 2},
{12000000, 32000, 1, 8, 1920, 128, 8, 3, 128, 8, 3},
{12500000, 32000, 1, 7, 8643, 128, 12, 2, 128, 12, 2},
/* 44.1k rate */
{12000000, 44100, 7, 5264, 128, 8, 2, 128, 8, 2},
{12000000, 44100, 8, 4672, 128, 6, 3, 128, 6, 3},
{12500000, 44100, 7, 2253, 128, 8, 2, 128, 8, 2},
{ 1411200, 44100, 2, 32, 0, 128, 8, 2, 128, 8, 2},
{ 2822400, 44100, 1, 32, 0, 128, 8, 2, 128, 8, 2},
{12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2},
{12000000, 44100, 1, 8, 4672, 128, 6, 3, 128, 6, 3},
{12500000, 44100, 1, 7, 2253, 128, 8, 2, 128, 8, 2},
/* 48k rate */
{12000000, 48000, 8, 1920, 128, 8, 2, 128, 8, 2},
{12000000, 48000, 7, 6800, 96, 5, 4, 96, 5, 4},
{12500000, 48000, 7, 8643, 128, 8, 2, 128, 8, 2},
{ 1536000, 48000, 2, 32, 0, 128, 8, 2, 128, 8, 2},
{ 3072000, 48000, 1, 32, 0, 128, 8, 2, 128, 8, 2},
{12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2},
{12000000, 48000, 1, 7, 6800, 96, 5, 4, 96, 5, 4},
{12500000, 48000, 1, 7, 8643, 128, 8, 2, 128, 8, 2},
/* 88.2k rate */
{12000000, 88200, 7, 5264, 64, 8, 2, 64, 8, 2},
{12000000, 88200, 8, 4672, 64, 6, 3, 64, 6, 3},
{12500000, 88200, 7, 2253, 64, 8, 2, 64, 8, 2},
{ 2822400, 88200, 2, 16, 0, 64, 8, 2, 64, 8, 2},
{ 5644800, 88200, 1, 16, 0, 64, 8, 2, 64, 8, 2},
{12000000, 88200, 1, 7, 5264, 64, 8, 2, 64, 8, 2},
{12000000, 88200, 1, 8, 4672, 64, 6, 3, 64, 6, 3},
{12500000, 88200, 1, 7, 2253, 64, 8, 2, 64, 8, 2},
/* 96k rate */
{12000000, 96000, 8, 1920, 64, 8, 2, 64, 8, 2},
{12000000, 96000, 7, 6800, 48, 5, 4, 48, 5, 4},
{12500000, 96000, 7, 8643, 64, 8, 2, 64, 8, 2},
{ 3072000, 96000, 2, 16, 0, 64, 8, 2, 64, 8, 2},
{ 6144000, 96000, 1, 16, 0, 64, 8, 2, 64, 8, 2},
{12000000, 96000, 1, 8, 1920, 64, 8, 2, 64, 8, 2},
{12000000, 96000, 1, 7, 6800, 48, 5, 4, 48, 5, 4},
{12500000, 96000, 1, 7, 8643, 64, 8, 2, 64, 8, 2},
/* 176.4k rate */
{12000000, 176400, 7, 5264, 32, 8, 2, 32, 8, 2},
{12000000, 176400, 8, 4672, 32, 6, 3, 32, 6, 3},
{12500000, 176400, 7, 2253, 32, 8, 2, 32, 8, 2},
{ 5644800, 176400, 2, 8, 0, 32, 8, 2, 32, 8, 2},
{11289600, 176400, 1, 8, 0, 32, 8, 2, 32, 8, 2},
{12000000, 176400, 1, 7, 5264, 32, 8, 2, 32, 8, 2},
{12000000, 176400, 1, 8, 4672, 32, 6, 3, 32, 6, 3},
{12500000, 176400, 1, 7, 2253, 32, 8, 2, 32, 8, 2},
/* 192k rate */
{12000000, 192000, 8, 1920, 32, 8, 2, 32, 8, 2},
{12000000, 192000, 7, 6800, 24, 5, 4, 24, 5, 4},
{12500000, 192000, 7, 8643, 32, 8, 2, 32, 8, 2},
{ 6144000, 192000, 2, 8, 0, 32, 8, 2, 32, 8, 2},
{12288000, 192000, 1, 8, 0, 32, 8, 2, 32, 8, 2},
{12000000, 192000, 1, 8, 1920, 32, 8, 2, 32, 8, 2},
{12000000, 192000, 1, 7, 6800, 24, 5, 4, 24, 5, 4},
{12500000, 192000, 1, 7, 8643, 32, 8, 2, 32, 8, 2},
};
static const char * const ldac_in_text[] = {
@ -888,7 +911,7 @@ static int aic31xx_setup_pll(struct snd_soc_component *component,
/* PLL configuration */
snd_soc_component_update_bits(component, AIC31XX_PLLPR, AIC31XX_PLL_MASK,
(aic31xx->p_div << 4) | 0x01);
(aic31xx->p_div << 4) | aic31xx_divs[i].pll_r);
snd_soc_component_write(component, AIC31XX_PLLJ, aic31xx_divs[i].pll_j);
snd_soc_component_write(component, AIC31XX_PLLDMSB,
@ -941,6 +964,7 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
u8 data = 0;
dev_dbg(component->dev, "## %s: width %d rate %d\n",
@ -972,6 +996,16 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
AIC31XX_IFACE1_DATALEN_MASK,
data);
/*
* If BCLK is used as PLL input, the sysclk is determined by the hw
* params. So it must be updated here to match the input frequency.
*/
if (aic31xx->sysclk_id == AIC31XX_PLL_CLKIN_BCLK) {
aic31xx->sysclk = params_rate(params) * params_width(params) *
params_channels(params);
aic31xx->p_div = 1;
}
return aic31xx_setup_pll(component, params);
}
@ -1156,6 +1190,7 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
snd_soc_component_update_bits(component, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK,
clk_id << AIC31XX_PLL_CLKIN_SHIFT);
aic31xx->sysclk_id = clk_id;
aic31xx->sysclk = freq;
return 0;

View File

@ -118,7 +118,7 @@ struct aic31xx_pdata {
#define AIC31XX_PLL_CLKIN_MASK GENMASK(3, 2)
#define AIC31XX_PLL_CLKIN_SHIFT (2)
#define AIC31XX_PLL_CLKIN_MCLK 0x00
#define AIC31XX_PLL_CLKIN_BCKL 0x01
#define AIC31XX_PLL_CLKIN_BCLK 0x01
#define AIC31XX_PLL_CLKIN_GPIO1 0x02
#define AIC31XX_PLL_CLKIN_DIN 0x03
#define AIC31XX_CODEC_CLKIN_MASK GENMASK(1, 0)

View File

@ -26,6 +26,7 @@
#include "../codecs/wm8962.h"
#include "../codecs/wm8960.h"
#include "../codecs/wm8994.h"
#include "../codecs/tlv320aic31xx.h"
#define CS427x_SYSCLK_MCLK 0
@ -629,6 +630,16 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
} else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) {
codec_dai_name = "tlv320aic32x4-hifi";
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
} else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic31xx")) {
codec_dai_name = "tlv320dac31xx-hifi";
priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
priv->dai_link[1].dpcm_capture = 0;
priv->dai_link[2].dpcm_capture = 0;
priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
priv->codec_priv.mclk_id = AIC31XX_PLL_CLKIN_BCLK;
priv->card.dapm_routes = audio_map_tx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) {
codec_dai_name = "wm8962";
priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK;
@ -888,6 +899,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = {
{ .compatible = "fsl,imx-audio-cs42888", },
{ .compatible = "fsl,imx-audio-cs427x", },
{ .compatible = "fsl,imx-audio-tlv320aic32x4", },
{ .compatible = "fsl,imx-audio-tlv320aic31xx", },
{ .compatible = "fsl,imx-audio-sgtl5000", },
{ .compatible = "fsl,imx-audio-wm8962", },
{ .compatible = "fsl,imx-audio-wm8960", },