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

ASoC: codecs: max98090: Allow dsp_a mode

TDM mode for max98090 is dsp_a compatible with such limitations:
1) Up to four timeslots supported.
2) Only 16 bits timeslots supported.
3) Only 2 active timeslots (L/R) supported.

We want to setup TDM mode only when dsp_a mode is selected. So move
M98090_REG_TDM_FORMAT/M98090_REG_TDM_CONTROL registers setup from
max98090_set_tdm_slot() to the max98090_dai_set_fmt(). Also extend
max98090_set_tdm_slot() with all TDM limitations check.

Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
Link: https://lore.kernel.org/r/Message-Id: <20230622142038.63388-1-fido_max@inbox.ru>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Maxim Kochetkov and committed by
Mark Brown
fb180283 82f76ac2

+30 -26
+28 -25
sound/soc/codecs/max98090.c
··· 1581 1581 struct snd_soc_component *component = codec_dai->component; 1582 1582 struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); 1583 1583 struct max98090_cdata *cdata; 1584 - u8 regval; 1584 + u8 regval, tdm_regval; 1585 1585 1586 1586 max98090->dai_fmt = fmt; 1587 1587 cdata = &max98090->dai[0]; ··· 1590 1590 cdata->fmt = fmt; 1591 1591 1592 1592 regval = 0; 1593 + tdm_regval = 0; 1593 1594 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 1594 1595 case SND_SOC_DAIFMT_CBC_CFC: 1595 1596 /* Set to consumer mode PLL - MAS mode off */ ··· 1636 1635 regval |= M98090_RJ_MASK; 1637 1636 break; 1638 1637 case SND_SOC_DAIFMT_DSP_A: 1639 - /* Not supported mode */ 1638 + tdm_regval |= M98090_TDM_MASK; 1639 + break; 1640 1640 default: 1641 1641 dev_err(component->dev, "DAI format unsupported"); 1642 1642 return -EINVAL; ··· 1666 1664 * seen for the case of TDM mode. The remaining cases have 1667 1665 * normal logic. 1668 1666 */ 1669 - if (max98090->tdm_slots > 1) 1667 + if (tdm_regval) 1670 1668 regval ^= M98090_BCI_MASK; 1671 1669 1672 1670 snd_soc_component_write(component, 1673 1671 M98090_REG_INTERFACE_FORMAT, regval); 1672 + 1673 + regval = 0; 1674 + if (tdm_regval) 1675 + regval = max98090->tdm_lslot << M98090_TDM_SLOTL_SHIFT | 1676 + max98090->tdm_rslot << M98090_TDM_SLOTR_SHIFT | 1677 + 0 << M98090_TDM_SLOTDLY_SHIFT; 1678 + 1679 + snd_soc_component_write(component, M98090_REG_TDM_FORMAT, regval); 1680 + snd_soc_component_write(component, M98090_REG_TDM_CONTROL, tdm_regval); 1674 1681 } 1675 1682 1676 1683 return 0; ··· 1690 1679 { 1691 1680 struct snd_soc_component *component = codec_dai->component; 1692 1681 struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); 1693 - struct max98090_cdata *cdata; 1694 - cdata = &max98090->dai[0]; 1695 1682 1696 1683 if (slots < 0 || slots > 4) 1697 1684 return -EINVAL; 1698 1685 1686 + if (slot_width != 16) 1687 + return -EINVAL; 1688 + 1689 + if (rx_mask != tx_mask) 1690 + return -EINVAL; 1691 + 1692 + if (!rx_mask) 1693 + return -EINVAL; 1694 + 1699 1695 max98090->tdm_slots = slots; 1700 - max98090->tdm_width = slot_width; 1701 - 1702 - if (max98090->tdm_slots > 1) { 1703 - /* SLOTL SLOTR SLOTDLY */ 1704 - snd_soc_component_write(component, M98090_REG_TDM_FORMAT, 1705 - 0 << M98090_TDM_SLOTL_SHIFT | 1706 - 1 << M98090_TDM_SLOTR_SHIFT | 1707 - 0 << M98090_TDM_SLOTDLY_SHIFT); 1708 - 1709 - /* FSW TDM */ 1710 - snd_soc_component_update_bits(component, M98090_REG_TDM_CONTROL, 1711 - M98090_TDM_MASK, 1712 - M98090_TDM_MASK); 1713 - } 1714 - 1715 - /* 1716 - * Normally advisable to set TDM first, but this permits either order 1717 - */ 1718 - cdata->fmt = 0; 1719 - max98090_dai_set_fmt(codec_dai, max98090->dai_fmt); 1696 + max98090->tdm_lslot = ffs(rx_mask) - 1; 1697 + max98090->tdm_rslot = fls(rx_mask) - 1; 1720 1698 1721 1699 return 0; 1722 1700 } ··· 2407 2407 max98090->lin_state = 0; 2408 2408 max98090->pa1en = 0; 2409 2409 max98090->pa2en = 0; 2410 + 2411 + max98090->tdm_lslot = 0; 2412 + max98090->tdm_rslot = 1; 2410 2413 2411 2414 ret = snd_soc_component_read(component, M98090_REG_REVISION_ID); 2412 2415 if (ret < 0) {
+2 -1
sound/soc/codecs/max98090.h
··· 1533 1533 struct snd_soc_jack *jack; 1534 1534 unsigned int dai_fmt; 1535 1535 int tdm_slots; 1536 - int tdm_width; 1536 + int tdm_lslot; 1537 + int tdm_rslot; 1537 1538 u8 lin_state; 1538 1539 unsigned int pa1en; 1539 1540 unsigned int pa2en;