Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: pcm3168a: Use fixup instead of constraint for channels and formats

The snd_pcm_hw_constraint_minmax() works fine when a single codec is
connected to a single CPU DAI, but in multicodec or DPCM setup the
constraints placed by the driver will apply to the whole PCM stream (FE
included) and thus prevents more than 8 playback channels for example.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Link: https://lore.kernel.org/r/20191008115720.7135-1-peter.ujfalusi@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Peter Ujfalusi and committed by
Mark Brown
cfc28ac1 1466327e

+40 -58
+40 -58
sound/soc/codecs/pcm3168a.c
··· 62 62 unsigned long sysclk; 63 63 64 64 struct pcm3168a_io_params io_params[2]; 65 + struct snd_soc_dai_driver dai_drv[2]; 65 66 }; 66 67 67 68 static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; ··· 315 314 return 0; 316 315 } 317 316 317 + static void pcm3168a_update_fixup_pcm_stream(struct snd_soc_dai *dai) 318 + { 319 + struct snd_soc_component *component = dai->component; 320 + struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); 321 + u64 formats = SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE; 322 + unsigned int channel_max = dai->id == PCM3168A_DAI_DAC ? 8 : 6; 323 + 324 + if (!pcm3168a->io_params[dai->id].fmt) 325 + return; 326 + 327 + if (pcm3168a->io_params[dai->id].fmt == PCM3168A_FMT_RIGHT_J) { 328 + /* S16_LE is only supported in RIGHT_J mode */ 329 + formats |= SNDRV_PCM_FMTBIT_S16_LE; 330 + 331 + /* 332 + * If multi DIN/DOUT is not selected, RIGHT_J can only support 333 + * two channels (no TDM support) 334 + */ 335 + if (pcm3168a->io_params[dai->id].tdm_slots != 2) 336 + channel_max = 2; 337 + } 338 + 339 + if (dai->id == PCM3168A_DAI_DAC) { 340 + dai->driver->playback.channels_max = channel_max; 341 + dai->driver->playback.formats = formats; 342 + } else { 343 + dai->driver->capture.channels_max = channel_max; 344 + dai->driver->capture.formats = formats; 345 + } 346 + } 347 + 318 348 static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format) 319 349 { 320 350 struct snd_soc_component *component = dai->component; ··· 408 376 409 377 regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); 410 378 379 + pcm3168a_update_fixup_pcm_stream(dai); 380 + 411 381 return 0; 412 382 } 413 383 ··· 442 408 io_params->tdm_mask = tx_mask; 443 409 else 444 410 io_params->tdm_mask = rx_mask; 411 + 412 + pcm3168a_update_fixup_pcm_stream(dai); 445 413 446 414 return 0; 447 415 } ··· 566 530 return 0; 567 531 } 568 532 569 - static int pcm3168a_startup(struct snd_pcm_substream *substream, 570 - struct snd_soc_dai *dai) 571 - { 572 - struct snd_soc_component *component = dai->component; 573 - struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); 574 - unsigned int sample_min; 575 - unsigned int channel_max; 576 - unsigned int channel_maxs[] = { 577 - 8, /* DAC */ 578 - 6 /* ADC */ 579 - }; 580 - 581 - /* 582 - * Available Data Bits 583 - * 584 - * RIGHT_J : 24 / 16 585 - * LEFT_J : 24 586 - * I2S : 24 587 - * 588 - * TDM available 589 - * 590 - * I2S 591 - * LEFT_J 592 - */ 593 - switch (pcm3168a->io_params[dai->id].fmt) { 594 - case PCM3168A_FMT_RIGHT_J: 595 - sample_min = 16; 596 - channel_max = 2; 597 - break; 598 - case PCM3168A_FMT_LEFT_J: 599 - case PCM3168A_FMT_I2S: 600 - case PCM3168A_FMT_DSP_A: 601 - case PCM3168A_FMT_DSP_B: 602 - sample_min = 24; 603 - channel_max = channel_maxs[dai->id]; 604 - break; 605 - default: 606 - sample_min = 24; 607 - channel_max = 2; 608 - } 609 - 610 - snd_pcm_hw_constraint_minmax(substream->runtime, 611 - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 612 - sample_min, 32); 613 - 614 - /* Allow all channels in multi DIN/DOUT mode */ 615 - if (pcm3168a->io_params[dai->id].tdm_slots == 2) 616 - channel_max = channel_maxs[dai->id]; 617 - 618 - snd_pcm_hw_constraint_minmax(substream->runtime, 619 - SNDRV_PCM_HW_PARAM_CHANNELS, 620 - 2, channel_max); 621 - 622 - return 0; 623 - } 624 533 static const struct snd_soc_dai_ops pcm3168a_dai_ops = { 625 - .startup = pcm3168a_startup, 626 534 .set_fmt = pcm3168a_set_dai_fmt, 627 535 .set_sysclk = pcm3168a_set_dai_sysclk, 628 536 .hw_params = pcm3168a_hw_params, ··· 756 776 pm_runtime_enable(dev); 757 777 pm_runtime_idle(dev); 758 778 759 - ret = devm_snd_soc_register_component(dev, &pcm3168a_driver, pcm3168a_dais, 760 - ARRAY_SIZE(pcm3168a_dais)); 779 + memcpy(pcm3168a->dai_drv, pcm3168a_dais, sizeof(pcm3168a->dai_drv)); 780 + ret = devm_snd_soc_register_component(dev, &pcm3168a_driver, 781 + pcm3168a->dai_drv, 782 + ARRAY_SIZE(pcm3168a->dai_drv)); 761 783 if (ret) { 762 784 dev_err(dev, "failed to register component: %d\n", ret); 763 785 goto err_regulator;