Skip to content

Commit 3e83957

Browse files
mattmart3broonie
authored andcommitted
ASoC: sunxi: sun4i-i2s: fix LRCLK polarity in i2s mode
This fixes the LRCLK polarity for sun8i-h3 and sun50i-h6 in i2s mode which was wrongly inverted. The LRCLK was being set in reversed logic compared to the DAI format: inverted LRCLK for SND_SOC_DAIFMT_IB_NF and SND_SOC_DAIFMT_NB_NF; normal LRCLK for SND_SOC_DAIFMT_IB_IF and SND_SOC_DAIFMT_NB_IF. Such reversed logic applies properly for DSP_A, DSP_B, LEFT_J and RIGHT_J modes but not for I2S mode, for which the LRCLK signal results reversed to what expected on the bus. The issue is due to a misinterpretation of the LRCLK polarity bit of the H3 and H6 i2s controllers. Such bit in this case does not mean "0 => normal" or "1 => inverted" according to the expected bus operation, but it means "0 => frame starts on low edge" and "1 => frame starts on high edge" (from the User Manuals). This commit fixes the LRCLK polarity by setting the LRCLK polarity bit according to the selected bus mode and renames the LRCLK polarity bit definition to avoid further confusion. Fixes: dd657ea ("ASoC: sun4i-i2s: Fix the LRCK polarity") Fixes: 73adf87 ("ASoC: sun4i-i2s: Add support for H6 I2S") Signed-off-by: Matteo Martelli <matteomartelli3@gmail.com> Link: https://patch.msgid.link/20240801-asoc-fix-sun4i-i2s-v2-1-a8e4e9daa363@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 283844c commit 3e83957

File tree

1 file changed

+73
-70
lines changed

1 file changed

+73
-70
lines changed

sound/soc/sunxi/sun4i-i2s.c

Lines changed: 73 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@
100100
#define SUN8I_I2S_CTRL_MODE_PCM (0 << 4)
101101

102102
#define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(19)
103-
#define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19)
104-
#define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19)
103+
#define SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH (1 << 19)
104+
#define SUN8I_I2S_FMT0_LRCLK_POLARITY_START_LOW (0 << 19)
105105
#define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8)
106106
#define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8)
107107
#define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK BIT(7)
@@ -729,65 +729,37 @@ static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
729729
static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
730730
unsigned int fmt)
731731
{
732-
u32 mode, val;
732+
u32 mode, lrclk_pol, bclk_pol, val;
733733
u8 offset;
734734

735-
/*
736-
* DAI clock polarity
737-
*
738-
* The setup for LRCK contradicts the datasheet, but under a
739-
* scope it's clear that the LRCK polarity is reversed
740-
* compared to the expected polarity on the bus.
741-
*/
742-
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
743-
case SND_SOC_DAIFMT_IB_IF:
744-
/* Invert both clocks */
745-
val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
746-
break;
747-
case SND_SOC_DAIFMT_IB_NF:
748-
/* Invert bit clock */
749-
val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED |
750-
SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
751-
break;
752-
case SND_SOC_DAIFMT_NB_IF:
753-
/* Invert frame clock */
754-
val = 0;
755-
break;
756-
case SND_SOC_DAIFMT_NB_NF:
757-
val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
758-
break;
759-
default:
760-
return -EINVAL;
761-
}
762-
763-
regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
764-
SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK |
765-
SUN8I_I2S_FMT0_BCLK_POLARITY_MASK,
766-
val);
767-
768735
/* DAI Mode */
769736
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
770737
case SND_SOC_DAIFMT_DSP_A:
738+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
771739
mode = SUN8I_I2S_CTRL_MODE_PCM;
772740
offset = 1;
773741
break;
774742

775743
case SND_SOC_DAIFMT_DSP_B:
744+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
776745
mode = SUN8I_I2S_CTRL_MODE_PCM;
777746
offset = 0;
778747
break;
779748

780749
case SND_SOC_DAIFMT_I2S:
750+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_LOW;
781751
mode = SUN8I_I2S_CTRL_MODE_LEFT;
782752
offset = 1;
783753
break;
784754

785755
case SND_SOC_DAIFMT_LEFT_J:
756+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
786757
mode = SUN8I_I2S_CTRL_MODE_LEFT;
787758
offset = 0;
788759
break;
789760

790761
case SND_SOC_DAIFMT_RIGHT_J:
762+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
791763
mode = SUN8I_I2S_CTRL_MODE_RIGHT;
792764
offset = 0;
793765
break;
@@ -805,6 +777,35 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
805777
SUN8I_I2S_TX_CHAN_OFFSET_MASK,
806778
SUN8I_I2S_TX_CHAN_OFFSET(offset));
807779

780+
/* DAI clock polarity */
781+
bclk_pol = SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL;
782+
783+
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
784+
case SND_SOC_DAIFMT_IB_IF:
785+
/* Invert both clocks */
786+
lrclk_pol ^= SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK;
787+
bclk_pol = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
788+
break;
789+
case SND_SOC_DAIFMT_IB_NF:
790+
/* Invert bit clock */
791+
bclk_pol = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
792+
break;
793+
case SND_SOC_DAIFMT_NB_IF:
794+
/* Invert frame clock */
795+
lrclk_pol ^= SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK;
796+
break;
797+
case SND_SOC_DAIFMT_NB_NF:
798+
/* No inversion */
799+
break;
800+
default:
801+
return -EINVAL;
802+
}
803+
804+
regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
805+
SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK |
806+
SUN8I_I2S_FMT0_BCLK_POLARITY_MASK,
807+
lrclk_pol | bclk_pol);
808+
808809
/* DAI clock master masks */
809810
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
810811
case SND_SOC_DAIFMT_BP_FP:
@@ -836,65 +837,37 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
836837
static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
837838
unsigned int fmt)
838839
{
839-
u32 mode, val;
840+
u32 mode, lrclk_pol, bclk_pol, val;
840841
u8 offset;
841842

842-
/*
843-
* DAI clock polarity
844-
*
845-
* The setup for LRCK contradicts the datasheet, but under a
846-
* scope it's clear that the LRCK polarity is reversed
847-
* compared to the expected polarity on the bus.
848-
*/
849-
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
850-
case SND_SOC_DAIFMT_IB_IF:
851-
/* Invert both clocks */
852-
val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
853-
break;
854-
case SND_SOC_DAIFMT_IB_NF:
855-
/* Invert bit clock */
856-
val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED |
857-
SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
858-
break;
859-
case SND_SOC_DAIFMT_NB_IF:
860-
/* Invert frame clock */
861-
val = 0;
862-
break;
863-
case SND_SOC_DAIFMT_NB_NF:
864-
val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
865-
break;
866-
default:
867-
return -EINVAL;
868-
}
869-
870-
regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
871-
SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK |
872-
SUN8I_I2S_FMT0_BCLK_POLARITY_MASK,
873-
val);
874-
875843
/* DAI Mode */
876844
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
877845
case SND_SOC_DAIFMT_DSP_A:
846+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
878847
mode = SUN8I_I2S_CTRL_MODE_PCM;
879848
offset = 1;
880849
break;
881850

882851
case SND_SOC_DAIFMT_DSP_B:
852+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
883853
mode = SUN8I_I2S_CTRL_MODE_PCM;
884854
offset = 0;
885855
break;
886856

887857
case SND_SOC_DAIFMT_I2S:
858+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_LOW;
888859
mode = SUN8I_I2S_CTRL_MODE_LEFT;
889860
offset = 1;
890861
break;
891862

892863
case SND_SOC_DAIFMT_LEFT_J:
864+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
893865
mode = SUN8I_I2S_CTRL_MODE_LEFT;
894866
offset = 0;
895867
break;
896868

897869
case SND_SOC_DAIFMT_RIGHT_J:
870+
lrclk_pol = SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH;
898871
mode = SUN8I_I2S_CTRL_MODE_RIGHT;
899872
offset = 0;
900873
break;
@@ -912,6 +885,36 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
912885
SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK,
913886
SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset));
914887

888+
/* DAI clock polarity */
889+
bclk_pol = SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL;
890+
891+
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
892+
case SND_SOC_DAIFMT_IB_IF:
893+
/* Invert both clocks */
894+
lrclk_pol ^= SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK;
895+
bclk_pol = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
896+
break;
897+
case SND_SOC_DAIFMT_IB_NF:
898+
/* Invert bit clock */
899+
bclk_pol = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
900+
break;
901+
case SND_SOC_DAIFMT_NB_IF:
902+
/* Invert frame clock */
903+
lrclk_pol ^= SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK;
904+
break;
905+
case SND_SOC_DAIFMT_NB_NF:
906+
/* No inversion */
907+
break;
908+
default:
909+
return -EINVAL;
910+
}
911+
912+
regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
913+
SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK |
914+
SUN8I_I2S_FMT0_BCLK_POLARITY_MASK,
915+
lrclk_pol | bclk_pol);
916+
917+
915918
/* DAI clock master masks */
916919
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
917920
case SND_SOC_DAIFMT_BP_FP:

0 commit comments

Comments
 (0)