Loading sound/soc/codecs/max98927.c +104 −16 Original line number Diff line number Diff line Loading @@ -250,6 +250,21 @@ static const int rate_table[] = { 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, struct snd_pcm_hw_params *params) { Loading @@ -275,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927, i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); } switch (blr_clk_ratio) { case 32: value = 2; break; case 48: value = 3; break; case 64: value = 4; break; default: if (!max98927->tdm_mode) { /* BCLK configuration */ value = max98927_get_bclk_sel(blr_clk_ratio); if (!value) { dev_err(codec->dev, "format unsupported %d\n", params_format(params)); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, MAX98927_PCM_CLK_SETUP_BSEL_MASK, value); } return 0; } Loading Loading @@ -391,6 +403,78 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, 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_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ Loading @@ -410,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = { .set_sysclk = max98927_dai_set_sysclk, .set_fmt = max98927_dai_set_fmt, .hw_params = max98927_dai_hw_params, .set_tdm_slot = max98927_dai_tdm_slot, }; static int max98927_dac_event(struct snd_soc_dapm_widget *w, Loading @@ -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); switch (event) { case SND_SOC_DAPM_PRE_PMU: max98927->tdm_mode = 0; break; case SND_SOC_DAPM_POST_PMU: regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, Loading sound/soc/codecs/max98927.h +1 −0 Original line number Diff line number Diff line Loading @@ -270,5 +270,6 @@ struct max98927_priv { unsigned int iface; unsigned int master; unsigned int digital_gain; bool tdm_mode; }; #endif Loading
sound/soc/codecs/max98927.c +104 −16 Original line number Diff line number Diff line Loading @@ -250,6 +250,21 @@ static const int rate_table[] = { 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, struct snd_pcm_hw_params *params) { Loading @@ -275,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927, i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); } switch (blr_clk_ratio) { case 32: value = 2; break; case 48: value = 3; break; case 64: value = 4; break; default: if (!max98927->tdm_mode) { /* BCLK configuration */ value = max98927_get_bclk_sel(blr_clk_ratio); if (!value) { dev_err(codec->dev, "format unsupported %d\n", params_format(params)); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, MAX98927_PCM_CLK_SETUP_BSEL_MASK, value); } return 0; } Loading Loading @@ -391,6 +403,78 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, 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_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ Loading @@ -410,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = { .set_sysclk = max98927_dai_set_sysclk, .set_fmt = max98927_dai_set_fmt, .hw_params = max98927_dai_hw_params, .set_tdm_slot = max98927_dai_tdm_slot, }; static int max98927_dac_event(struct snd_soc_dapm_widget *w, Loading @@ -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); switch (event) { case SND_SOC_DAPM_PRE_PMU: max98927->tdm_mode = 0; break; case SND_SOC_DAPM_POST_PMU: regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, Loading
sound/soc/codecs/max98927.h +1 −0 Original line number Diff line number Diff line Loading @@ -270,5 +270,6 @@ struct max98927_priv { unsigned int iface; unsigned int master; unsigned int digital_gain; bool tdm_mode; }; #endif