Commit 21b15926 authored by Mark Brown's avatar Mark Brown

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.
parents 27744454 8c9b9cfb
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -169,6 +170,7 @@ struct aic31xx_priv { ...@@ -169,6 +170,7 @@ struct aic31xx_priv {
struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES]; struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES]; struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
u32 sysclk_id;
unsigned int sysclk; unsigned int sysclk;
u8 p_div; u8 p_div;
int rate_div_line; int rate_div_line;
...@@ -180,6 +182,7 @@ struct aic31xx_priv { ...@@ -180,6 +182,7 @@ struct aic31xx_priv {
struct aic31xx_rate_divs { struct aic31xx_rate_divs {
u32 mclk_p; u32 mclk_p;
u32 rate; u32 rate;
u8 pll_r;
u8 pll_j; u8 pll_j;
u16 pll_d; u16 pll_d;
u16 dosr; u16 dosr;
...@@ -192,51 +195,71 @@ struct aic31xx_rate_divs { ...@@ -192,51 +195,71 @@ struct aic31xx_rate_divs {
/* ADC dividers can be disabled by configuring them to 0 */ /* ADC dividers can be disabled by configuring them to 0 */
static const struct aic31xx_rate_divs aic31xx_divs[] = { 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 */ /* 8k rate */
{12000000, 8000, 8, 1920, 128, 48, 2, 128, 48, 2}, { 512000, 8000, 4, 48, 0, 128, 48, 2, 128, 48, 2},
{12000000, 8000, 8, 1920, 128, 32, 3, 128, 32, 3}, {12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2},
{12500000, 8000, 7, 8643, 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 */ /* 11.025k rate */
{12000000, 11025, 7, 5264, 128, 32, 2, 128, 32, 2}, { 705600, 11025, 3, 48, 0, 128, 24, 3, 128, 24, 3},
{12000000, 11025, 8, 4672, 128, 24, 3, 128, 24, 3}, {12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2},
{12500000, 11025, 7, 2253, 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 */ /* 16k rate */
{12000000, 16000, 8, 1920, 128, 24, 2, 128, 24, 2}, { 512000, 16000, 4, 48, 0, 128, 16, 3, 128, 16, 3},
{12000000, 16000, 8, 1920, 128, 16, 3, 128, 16, 3}, { 1024000, 16000, 2, 48, 0, 128, 16, 3, 128, 16, 3},
{12500000, 16000, 7, 8643, 128, 24, 2, 128, 24, 2}, {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 */ /* 22.05k rate */
{12000000, 22050, 7, 5264, 128, 16, 2, 128, 16, 2}, { 705600, 22050, 4, 36, 0, 128, 12, 3, 128, 12, 3},
{12000000, 22050, 8, 4672, 128, 12, 3, 128, 12, 3}, { 1411200, 22050, 2, 36, 0, 128, 12, 3, 128, 12, 3},
{12500000, 22050, 7, 2253, 128, 16, 2, 128, 16, 2}, {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 */ /* 32k rate */
{12000000, 32000, 8, 1920, 128, 12, 2, 128, 12, 2}, { 1024000, 32000, 2, 48, 0, 128, 12, 2, 128, 12, 2},
{12000000, 32000, 8, 1920, 128, 8, 3, 128, 8, 3}, { 2048000, 32000, 1, 48, 0, 128, 12, 2, 128, 12, 2},
{12500000, 32000, 7, 8643, 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 */ /* 44.1k rate */
{12000000, 44100, 7, 5264, 128, 8, 2, 128, 8, 2}, { 1411200, 44100, 2, 32, 0, 128, 8, 2, 128, 8, 2},
{12000000, 44100, 8, 4672, 128, 6, 3, 128, 6, 3}, { 2822400, 44100, 1, 32, 0, 128, 8, 2, 128, 8, 2},
{12500000, 44100, 7, 2253, 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 */ /* 48k rate */
{12000000, 48000, 8, 1920, 128, 8, 2, 128, 8, 2}, { 1536000, 48000, 2, 32, 0, 128, 8, 2, 128, 8, 2},
{12000000, 48000, 7, 6800, 96, 5, 4, 96, 5, 4}, { 3072000, 48000, 1, 32, 0, 128, 8, 2, 128, 8, 2},
{12500000, 48000, 7, 8643, 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 */ /* 88.2k rate */
{12000000, 88200, 7, 5264, 64, 8, 2, 64, 8, 2}, { 2822400, 88200, 2, 16, 0, 64, 8, 2, 64, 8, 2},
{12000000, 88200, 8, 4672, 64, 6, 3, 64, 6, 3}, { 5644800, 88200, 1, 16, 0, 64, 8, 2, 64, 8, 2},
{12500000, 88200, 7, 2253, 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 */ /* 96k rate */
{12000000, 96000, 8, 1920, 64, 8, 2, 64, 8, 2}, { 3072000, 96000, 2, 16, 0, 64, 8, 2, 64, 8, 2},
{12000000, 96000, 7, 6800, 48, 5, 4, 48, 5, 4}, { 6144000, 96000, 1, 16, 0, 64, 8, 2, 64, 8, 2},
{12500000, 96000, 7, 8643, 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 */ /* 176.4k rate */
{12000000, 176400, 7, 5264, 32, 8, 2, 32, 8, 2}, { 5644800, 176400, 2, 8, 0, 32, 8, 2, 32, 8, 2},
{12000000, 176400, 8, 4672, 32, 6, 3, 32, 6, 3}, {11289600, 176400, 1, 8, 0, 32, 8, 2, 32, 8, 2},
{12500000, 176400, 7, 2253, 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 */ /* 192k rate */
{12000000, 192000, 8, 1920, 32, 8, 2, 32, 8, 2}, { 6144000, 192000, 2, 8, 0, 32, 8, 2, 32, 8, 2},
{12000000, 192000, 7, 6800, 24, 5, 4, 24, 5, 4}, {12288000, 192000, 1, 8, 0, 32, 8, 2, 32, 8, 2},
{12500000, 192000, 7, 8643, 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[] = { static const char * const ldac_in_text[] = {
...@@ -888,7 +911,7 @@ static int aic31xx_setup_pll(struct snd_soc_component *component, ...@@ -888,7 +911,7 @@ static int aic31xx_setup_pll(struct snd_soc_component *component,
/* PLL configuration */ /* PLL configuration */
snd_soc_component_update_bits(component, AIC31XX_PLLPR, AIC31XX_PLL_MASK, 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_PLLJ, aic31xx_divs[i].pll_j);
snd_soc_component_write(component, AIC31XX_PLLDMSB, snd_soc_component_write(component, AIC31XX_PLLDMSB,
...@@ -941,6 +964,7 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream, ...@@ -941,6 +964,7 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
u8 data = 0; u8 data = 0;
dev_dbg(component->dev, "## %s: width %d rate %d\n", dev_dbg(component->dev, "## %s: width %d rate %d\n",
...@@ -972,6 +996,16 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream, ...@@ -972,6 +996,16 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream,
AIC31XX_IFACE1_DATALEN_MASK, AIC31XX_IFACE1_DATALEN_MASK,
data); 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); return aic31xx_setup_pll(component, params);
} }
...@@ -1156,6 +1190,7 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -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, snd_soc_component_update_bits(component, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK,
clk_id << AIC31XX_PLL_CLKIN_SHIFT); clk_id << AIC31XX_PLL_CLKIN_SHIFT);
aic31xx->sysclk_id = clk_id;
aic31xx->sysclk = freq; aic31xx->sysclk = freq;
return 0; return 0;
......
...@@ -118,7 +118,7 @@ struct aic31xx_pdata { ...@@ -118,7 +118,7 @@ struct aic31xx_pdata {
#define AIC31XX_PLL_CLKIN_MASK GENMASK(3, 2) #define AIC31XX_PLL_CLKIN_MASK GENMASK(3, 2)
#define AIC31XX_PLL_CLKIN_SHIFT (2) #define AIC31XX_PLL_CLKIN_SHIFT (2)
#define AIC31XX_PLL_CLKIN_MCLK 0x00 #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_GPIO1 0x02
#define AIC31XX_PLL_CLKIN_DIN 0x03 #define AIC31XX_PLL_CLKIN_DIN 0x03
#define AIC31XX_CODEC_CLKIN_MASK GENMASK(1, 0) #define AIC31XX_CODEC_CLKIN_MASK GENMASK(1, 0)
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "../codecs/wm8962.h" #include "../codecs/wm8962.h"
#include "../codecs/wm8960.h" #include "../codecs/wm8960.h"
#include "../codecs/wm8994.h" #include "../codecs/wm8994.h"
#include "../codecs/tlv320aic31xx.h"
#define CS427x_SYSCLK_MCLK 0 #define CS427x_SYSCLK_MCLK 0
...@@ -629,6 +630,16 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) ...@@ -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")) { } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) {
codec_dai_name = "tlv320aic32x4-hifi"; codec_dai_name = "tlv320aic32x4-hifi";
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 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")) { } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) {
codec_dai_name = "wm8962"; codec_dai_name = "wm8962";
priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK; priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK;
...@@ -888,6 +899,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { ...@@ -888,6 +899,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = {
{ .compatible = "fsl,imx-audio-cs42888", }, { .compatible = "fsl,imx-audio-cs42888", },
{ .compatible = "fsl,imx-audio-cs427x", }, { .compatible = "fsl,imx-audio-cs427x", },
{ .compatible = "fsl,imx-audio-tlv320aic32x4", }, { .compatible = "fsl,imx-audio-tlv320aic32x4", },
{ .compatible = "fsl,imx-audio-tlv320aic31xx", },
{ .compatible = "fsl,imx-audio-sgtl5000", }, { .compatible = "fsl,imx-audio-sgtl5000", },
{ .compatible = "fsl,imx-audio-wm8962", }, { .compatible = "fsl,imx-audio-wm8962", },
{ .compatible = "fsl,imx-audio-wm8960", }, { .compatible = "fsl,imx-audio-wm8960", },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment