Unverified Commit d1a10f1b authored by Martin Povišer's avatar Martin Povišer Committed by Mark Brown
Browse files

ASoC: tas2764: Fix and extend FSYNC polarity handling



Fix setting of FSYNC polarity in case of LEFT_J and DSP_A/B formats.
Do NOT set the SCFG field as was previously done, because that is not
correct and is also in conflict with the "ASI1 Source" control which
sets the same SCFG field!

Also add support for explicit polarity inversion.

Fixes: 827ed8a0 ("ASoC: tas2764: Add the driver for the TAS2764")
Signed-off-by: default avatarMartin Povišer <povik+lin@cutebit.org>
Link: https://lore.kernel.org/r/20220630075135.2221-2-povik+lin@cutebit.org


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent cd10bb89
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -135,7 +135,8 @@ static const char * const tas2764_ASI1_src[] = {
};

static SOC_ENUM_SINGLE_DECL(
	tas2764_ASI1_src_enum, TAS2764_TDM_CFG2, 4, tas2764_ASI1_src);
	tas2764_ASI1_src_enum, TAS2764_TDM_CFG2, TAS2764_TDM_CFG2_SCFG_SHIFT,
	tas2764_ASI1_src);

static const struct snd_kcontrol_new tas2764_asi1_mux =
	SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum);
@@ -333,20 +334,22 @@ static int tas2764_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
	struct snd_soc_component *component = dai->component;
	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
	u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
	int iface;
	u8 tdm_rx_start_slot = 0, asi_cfg_0 = 0, asi_cfg_1 = 0;
	int ret;

	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_NB_IF:
		asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START;
		fallthrough;
	case SND_SOC_DAIFMT_NB_NF:
		asi_cfg_1 = TAS2764_TDM_CFG1_RX_RISING;
		break;
	case SND_SOC_DAIFMT_IB_IF:
		asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START;
		fallthrough;
	case SND_SOC_DAIFMT_IB_NF:
		asi_cfg_1 = TAS2764_TDM_CFG1_RX_FALLING;
		break;
	default:
		dev_err(tas2764->dev, "ASI format Inverse is not found\n");
		return -EINVAL;
	}

	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1,
@@ -357,13 +360,13 @@ static int tas2764_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)

	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START;
		fallthrough;
	case SND_SOC_DAIFMT_DSP_A:
		iface = TAS2764_TDM_CFG2_SCFG_I2S;
		tdm_rx_start_slot = 1;
		break;
	case SND_SOC_DAIFMT_DSP_B:
	case SND_SOC_DAIFMT_LEFT_J:
		iface = TAS2764_TDM_CFG2_SCFG_LEFT_J;
		tdm_rx_start_slot = 0;
		break;
	default:
@@ -372,14 +375,15 @@ static int tas2764_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
		return -EINVAL;
	}

	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1,
					    TAS2764_TDM_CFG1_MASK,
					    (tdm_rx_start_slot << TAS2764_TDM_CFG1_51_SHIFT));
	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG0,
					    TAS2764_TDM_CFG0_FRAME_START,
					    asi_cfg_0);
	if (ret < 0)
		return ret;

	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG2,
					    TAS2764_TDM_CFG2_SCFG_MASK, iface);
	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1,
					    TAS2764_TDM_CFG1_MASK,
					    (tdm_rx_start_slot << TAS2764_TDM_CFG1_51_SHIFT));
	if (ret < 0)
		return ret;

+2 −4
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#define TAS2764_TDM_CFG0_MASK		GENMASK(3, 1)
#define TAS2764_TDM_CFG0_44_1_48KHZ	BIT(3)
#define TAS2764_TDM_CFG0_88_2_96KHZ	(BIT(3) | BIT(1))
#define TAS2764_TDM_CFG0_FRAME_START	BIT(0)

/* TDM Configuration Reg1 */
#define TAS2764_TDM_CFG1		TAS2764_REG(0X0, 0x09)
@@ -66,10 +67,7 @@
#define TAS2764_TDM_CFG2_RXS_16BITS	0x0
#define TAS2764_TDM_CFG2_RXS_24BITS	BIT(0)
#define TAS2764_TDM_CFG2_RXS_32BITS	BIT(1)
#define TAS2764_TDM_CFG2_SCFG_MASK	GENMASK(5, 4)
#define TAS2764_TDM_CFG2_SCFG_I2S	0x0
#define TAS2764_TDM_CFG2_SCFG_LEFT_J	BIT(4)
#define TAS2764_TDM_CFG2_SCFG_RIGHT_J	BIT(5)
#define TAS2764_TDM_CFG2_SCFG_SHIFT	4

/* TDM Configuration Reg3 */
#define TAS2764_TDM_CFG3		TAS2764_REG(0X0, 0x0c)