diff options
| author | Ryan Lee <ryans.lee@maximintegrated.com> | 2017-09-14 20:30:39 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2017-09-25 15:48:14 -0400 |
| commit | d4a8bce81cbd53420988f5db0d096ad04960f189 (patch) | |
| tree | 608cee91e2c2011b65da6bd0cc79f9f3397d2ead | |
| parent | 4eee20246c0fa77a7a7b189ac806d5f78d675546 (diff) | |
ASoC: max98927: Added max98927_dai_tdm_slot function
Signed-off-by: Ryan Lee <ryans.lee@maximintegrated.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
| -rw-r--r-- | sound/soc/codecs/max98927.c | 120 | ||||
| -rw-r--r-- | sound/soc/codecs/max98927.h | 1 |
2 files changed, 105 insertions, 16 deletions
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 6f7b3ef48e25..a1d39353719d 100644 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c | |||
| @@ -250,6 +250,21 @@ static const int rate_table[] = { | |||
| 250 | 13000000, 19200000, | 250 | 13000000, 19200000, |
| 251 | }; | 251 | }; |
| 252 | 252 | ||
| 253 | /* BCLKs per LRCLK */ | ||
| 254 | static const int bclk_sel_table[] = { | ||
| 255 | 32, 48, 64, 96, 128, 192, 256, 384, 512, | ||
| 256 | }; | ||
| 257 | |||
| 258 | static int max98927_get_bclk_sel(int bclk) | ||
| 259 | { | ||
| 260 | int i; | ||
| 261 | /* match BCLKs per LRCLK */ | ||
| 262 | for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { | ||
| 263 | if (bclk_sel_table[i] == bclk) | ||
| 264 | return i + 2; | ||
| 265 | } | ||
| 266 | return 0; | ||
| 267 | } | ||
| 253 | static int max98927_set_clock(struct max98927_priv *max98927, | 268 | static int max98927_set_clock(struct max98927_priv *max98927, |
| 254 | struct snd_pcm_hw_params *params) | 269 | struct snd_pcm_hw_params *params) |
| 255 | { | 270 | { |
| @@ -275,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927, | |||
| 275 | i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); | 290 | i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); |
| 276 | } | 291 | } |
| 277 | 292 | ||
| 278 | switch (blr_clk_ratio) { | 293 | if (!max98927->tdm_mode) { |
| 279 | case 32: | 294 | /* BCLK configuration */ |
| 280 | value = 2; | 295 | value = max98927_get_bclk_sel(blr_clk_ratio); |
| 281 | break; | 296 | if (!value) { |
| 282 | case 48: | 297 | dev_err(codec->dev, "format unsupported %d\n", |
| 283 | value = 3; | 298 | params_format(params)); |
| 284 | break; | 299 | return -EINVAL; |
| 285 | case 64: | 300 | } |
| 286 | value = 4; | 301 | |
| 287 | break; | 302 | regmap_update_bits(max98927->regmap, |
| 288 | default: | 303 | MAX98927_R0022_PCM_CLK_SETUP, |
| 289 | return -EINVAL; | 304 | MAX98927_PCM_CLK_SETUP_BSEL_MASK, |
| 305 | value); | ||
| 290 | } | 306 | } |
| 291 | regmap_update_bits(max98927->regmap, | ||
| 292 | MAX98927_R0022_PCM_CLK_SETUP, | ||
| 293 | MAX98927_PCM_CLK_SETUP_BSEL_MASK, | ||
| 294 | value); | ||
| 295 | return 0; | 307 | return 0; |
| 296 | } | 308 | } |
| 297 | 309 | ||
| @@ -391,6 +403,78 @@ err: | |||
| 391 | return -EINVAL; | 403 | return -EINVAL; |
| 392 | } | 404 | } |
| 393 | 405 | ||
| 406 | static int max98927_dai_tdm_slot(struct snd_soc_dai *dai, | ||
| 407 | unsigned int tx_mask, unsigned int rx_mask, | ||
| 408 | int slots, int slot_width) | ||
| 409 | { | ||
| 410 | struct snd_soc_codec *codec = dai->codec; | ||
| 411 | struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); | ||
| 412 | int bsel = 0; | ||
| 413 | unsigned int chan_sz = 0; | ||
| 414 | |||
| 415 | max98927->tdm_mode = true; | ||
| 416 | |||
| 417 | /* BCLK configuration */ | ||
| 418 | bsel = max98927_get_bclk_sel(slots * slot_width); | ||
| 419 | if (bsel == 0) { | ||
| 420 | dev_err(codec->dev, "BCLK %d not supported\n", | ||
| 421 | slots * slot_width); | ||
| 422 | return -EINVAL; | ||
| 423 | } | ||
| 424 | |||
| 425 | regmap_update_bits(max98927->regmap, | ||
| 426 | MAX98927_R0022_PCM_CLK_SETUP, | ||
| 427 | MAX98927_PCM_CLK_SETUP_BSEL_MASK, | ||
| 428 | bsel); | ||
| 429 | |||
| 430 | /* Channel size configuration */ | ||
| 431 | switch (slot_width) { | ||
| 432 | case 16: | ||
| 433 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; | ||
| 434 | break; | ||
| 435 | case 24: | ||
| 436 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; | ||
| 437 | break; | ||
| 438 | case 32: | ||
| 439 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; | ||
| 440 | break; | ||
| 441 | default: | ||
| 442 | dev_err(codec->dev, "format unsupported %d\n", | ||
| 443 | slot_width); | ||
| 444 | return -EINVAL; | ||
| 445 | } | ||
| 446 | |||
| 447 | regmap_update_bits(max98927->regmap, | ||
| 448 | MAX98927_R0020_PCM_MODE_CFG, | ||
| 449 | MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); | ||
| 450 | |||
| 451 | /* Rx slot configuration */ | ||
| 452 | regmap_write(max98927->regmap, | ||
| 453 | MAX98927_R0018_PCM_RX_EN_A, | ||
| 454 | rx_mask & 0xFF); | ||
| 455 | regmap_write(max98927->regmap, | ||
| 456 | MAX98927_R0019_PCM_RX_EN_B, | ||
| 457 | (rx_mask & 0xFF00) >> 8); | ||
| 458 | |||
| 459 | /* Tx slot configuration */ | ||
| 460 | regmap_write(max98927->regmap, | ||
| 461 | MAX98927_R001A_PCM_TX_EN_A, | ||
| 462 | tx_mask & 0xFF); | ||
| 463 | regmap_write(max98927->regmap, | ||
| 464 | MAX98927_R001B_PCM_TX_EN_B, | ||
| 465 | (tx_mask & 0xFF00) >> 8); | ||
| 466 | |||
| 467 | /* Tx slot Hi-Z configuration */ | ||
| 468 | regmap_write(max98927->regmap, | ||
| 469 | MAX98927_R001C_PCM_TX_HIZ_CTRL_A, | ||
| 470 | ~tx_mask & 0xFF); | ||
| 471 | regmap_write(max98927->regmap, | ||
| 472 | MAX98927_R001D_PCM_TX_HIZ_CTRL_B, | ||
| 473 | (~tx_mask & 0xFF00) >> 8); | ||
| 474 | |||
| 475 | return 0; | ||
| 476 | } | ||
| 477 | |||
| 394 | #define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 | 478 | #define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 |
| 395 | 479 | ||
| 396 | #define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 480 | #define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| @@ -410,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = { | |||
| 410 | .set_sysclk = max98927_dai_set_sysclk, | 494 | .set_sysclk = max98927_dai_set_sysclk, |
| 411 | .set_fmt = max98927_dai_set_fmt, | 495 | .set_fmt = max98927_dai_set_fmt, |
| 412 | .hw_params = max98927_dai_hw_params, | 496 | .hw_params = max98927_dai_hw_params, |
| 497 | .set_tdm_slot = max98927_dai_tdm_slot, | ||
| 413 | }; | 498 | }; |
| 414 | 499 | ||
| 415 | static int max98927_dac_event(struct snd_soc_dapm_widget *w, | 500 | 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 | struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); | 504 | struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); |
| 420 | 505 | ||
| 421 | switch (event) { | 506 | switch (event) { |
| 507 | case SND_SOC_DAPM_PRE_PMU: | ||
| 508 | max98927->tdm_mode = 0; | ||
| 509 | break; | ||
| 422 | case SND_SOC_DAPM_POST_PMU: | 510 | case SND_SOC_DAPM_POST_PMU: |
| 423 | regmap_update_bits(max98927->regmap, | 511 | regmap_update_bits(max98927->regmap, |
| 424 | MAX98927_R003A_AMP_EN, | 512 | MAX98927_R003A_AMP_EN, |
diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h index bf7a6f92562a..9ea839735433 100644 --- a/sound/soc/codecs/max98927.h +++ b/sound/soc/codecs/max98927.h | |||
| @@ -270,5 +270,6 @@ struct max98927_priv { | |||
| 270 | unsigned int iface; | 270 | unsigned int iface; |
| 271 | unsigned int master; | 271 | unsigned int master; |
| 272 | unsigned int digital_gain; | 272 | unsigned int digital_gain; |
| 273 | bool tdm_mode; | ||
| 273 | }; | 274 | }; |
| 274 | #endif | 275 | #endif |
