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 |