Commit d4a8bce8 authored by Ryan Lee's avatar Ryan Lee Committed by Mark Brown

ASoC: max98927: Added max98927_dai_tdm_slot function

Signed-off-by: default avatarRyan Lee <ryans.lee@maximintegrated.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 4eee2024
...@@ -250,6 +250,21 @@ static const int rate_table[] = { ...@@ -250,6 +250,21 @@ static const int rate_table[] = {
13000000, 19200000, 13000000, 19200000,
}; };
/* BCLKs per LRCLK */
static const int bclk_sel_table[] = {
32, 48, 64, 96, 128, 192, 256, 384, 512,
};
static int max98927_get_bclk_sel(int bclk)
{
int i;
/* match BCLKs per LRCLK */
for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
if (bclk_sel_table[i] == bclk)
return i + 2;
}
return 0;
}
static int max98927_set_clock(struct max98927_priv *max98927, static int max98927_set_clock(struct max98927_priv *max98927,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
...@@ -275,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927, ...@@ -275,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927,
i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
} }
switch (blr_clk_ratio) { if (!max98927->tdm_mode) {
case 32: /* BCLK configuration */
value = 2; value = max98927_get_bclk_sel(blr_clk_ratio);
break; if (!value) {
case 48: dev_err(codec->dev, "format unsupported %d\n",
value = 3; params_format(params));
break;
case 64:
value = 4;
break;
default:
return -EINVAL; return -EINVAL;
} }
regmap_update_bits(max98927->regmap, regmap_update_bits(max98927->regmap,
MAX98927_R0022_PCM_CLK_SETUP, MAX98927_R0022_PCM_CLK_SETUP,
MAX98927_PCM_CLK_SETUP_BSEL_MASK, MAX98927_PCM_CLK_SETUP_BSEL_MASK,
value); value);
}
return 0; return 0;
} }
...@@ -391,6 +403,78 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -391,6 +403,78 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
static int max98927_dai_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask,
int slots, int slot_width)
{
struct snd_soc_codec *codec = dai->codec;
struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
int bsel = 0;
unsigned int chan_sz = 0;
max98927->tdm_mode = true;
/* BCLK configuration */
bsel = max98927_get_bclk_sel(slots * slot_width);
if (bsel == 0) {
dev_err(codec->dev, "BCLK %d not supported\n",
slots * slot_width);
return -EINVAL;
}
regmap_update_bits(max98927->regmap,
MAX98927_R0022_PCM_CLK_SETUP,
MAX98927_PCM_CLK_SETUP_BSEL_MASK,
bsel);
/* Channel size configuration */
switch (slot_width) {
case 16:
chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16;
break;
case 24:
chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24;
break;
case 32:
chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32;
break;
default:
dev_err(codec->dev, "format unsupported %d\n",
slot_width);
return -EINVAL;
}
regmap_update_bits(max98927->regmap,
MAX98927_R0020_PCM_MODE_CFG,
MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
/* Rx slot configuration */
regmap_write(max98927->regmap,
MAX98927_R0018_PCM_RX_EN_A,
rx_mask & 0xFF);
regmap_write(max98927->regmap,
MAX98927_R0019_PCM_RX_EN_B,
(rx_mask & 0xFF00) >> 8);
/* Tx slot configuration */
regmap_write(max98927->regmap,
MAX98927_R001A_PCM_TX_EN_A,
tx_mask & 0xFF);
regmap_write(max98927->regmap,
MAX98927_R001B_PCM_TX_EN_B,
(tx_mask & 0xFF00) >> 8);
/* Tx slot Hi-Z configuration */
regmap_write(max98927->regmap,
MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
~tx_mask & 0xFF);
regmap_write(max98927->regmap,
MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
(~tx_mask & 0xFF00) >> 8);
return 0;
}
#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 #define MAX98927_RATES SNDRV_PCM_RATE_8000_48000
#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ #define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
...@@ -410,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = { ...@@ -410,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = {
.set_sysclk = max98927_dai_set_sysclk, .set_sysclk = max98927_dai_set_sysclk,
.set_fmt = max98927_dai_set_fmt, .set_fmt = max98927_dai_set_fmt,
.hw_params = max98927_dai_hw_params, .hw_params = max98927_dai_hw_params,
.set_tdm_slot = max98927_dai_tdm_slot,
}; };
static int max98927_dac_event(struct snd_soc_dapm_widget *w, static int max98927_dac_event(struct snd_soc_dapm_widget *w,
...@@ -419,6 +504,9 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w, ...@@ -419,6 +504,9 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w,
struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU:
max98927->tdm_mode = 0;
break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
regmap_update_bits(max98927->regmap, regmap_update_bits(max98927->regmap,
MAX98927_R003A_AMP_EN, MAX98927_R003A_AMP_EN,
......
...@@ -270,5 +270,6 @@ struct max98927_priv { ...@@ -270,5 +270,6 @@ struct max98927_priv {
unsigned int iface; unsigned int iface;
unsigned int master; unsigned int master;
unsigned int digital_gain; unsigned int digital_gain;
bool tdm_mode;
}; };
#endif #endif
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