]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - sound/soc/sunxi/sun4i-i2s.c
ASoC: sun4i-i2s: Fix LRCK and BCLK polarity offsets on newer SoCs
[linux.git] / sound / soc / sunxi / sun4i-i2s.c
index 53c95e5289f549ac9b3fb618a2ee47d445da52e0..e3eadfe38aaf5c166b239c5bb0d61dacfe399cc2 100644 (file)
@@ -46,8 +46,6 @@
 #define SUN4I_I2S_FMT0_FMT_RIGHT_J                     (2 << 0)
 #define SUN4I_I2S_FMT0_FMT_LEFT_J                      (1 << 0)
 #define SUN4I_I2S_FMT0_FMT_I2S                         (0 << 0)
-#define SUN4I_I2S_FMT0_POLARITY_INVERTED               (1)
-#define SUN4I_I2S_FMT0_POLARITY_NORMAL                 (0)
 
 #define SUN4I_I2S_FMT1_REG             0x08
 #define SUN4I_I2S_FIFO_TX_REG          0x0c
 #define SUN8I_I2S_CTRL_MODE_LEFT               (1 << 4)
 #define SUN8I_I2S_CTRL_MODE_PCM                        (0 << 4)
 
+#define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK     BIT(19)
+#define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED         (1 << 19)
+#define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL           (0 << 19)
 #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK                GENMASK(17, 8)
 #define SUN8I_I2S_FMT0_LRCK_PERIOD(period)     ((period - 1) << 8)
+#define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK      BIT(7)
+#define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED          (1 << 7)
+#define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL            (0 << 7)
 
 #define SUN8I_I2S_INT_STA_REG          0x0c
 #define SUN8I_I2S_FIFO_TX_REG          0x20
@@ -132,8 +136,6 @@ struct sun4i_i2s;
  * @field_clkdiv_mclk_en: regmap field to enable mclk output.
  * @field_fmt_wss: regmap field to set word select size.
  * @field_fmt_sr: regmap field to set sample resolution.
- * @field_fmt_bclk: regmap field to set clk polarity.
- * @field_fmt_lrclk: regmap field to set frame polarity.
  */
 struct sun4i_i2s_quirks {
        bool                            has_reset;
@@ -145,8 +147,6 @@ struct sun4i_i2s_quirks {
        struct reg_field                field_clkdiv_mclk_en;
        struct reg_field                field_fmt_wss;
        struct reg_field                field_fmt_sr;
-       struct reg_field                field_fmt_bclk;
-       struct reg_field                field_fmt_lrclk;
 
        const struct sun4i_i2s_clk_div  *bclk_dividers;
        unsigned int                    num_bclk_dividers;
@@ -176,8 +176,6 @@ struct sun4i_i2s {
        struct regmap_field     *field_clkdiv_mclk_en;
        struct regmap_field     *field_fmt_wss;
        struct regmap_field     *field_fmt_sr;
-       struct regmap_field     *field_fmt_bclk;
-       struct regmap_field     *field_fmt_lrclk;
 
        const struct sun4i_i2s_quirks   *variant;
 };
@@ -498,6 +496,33 @@ static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
 {
        u32 val;
 
+       /* DAI clock polarity */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_IF:
+               /* Invert both clocks */
+               val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED |
+                     SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               /* Invert bit clock */
+               val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               /* Invert frame clock */
+               val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
+                          SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK |
+                          SUN4I_I2S_FMT0_BCLK_POLARITY_MASK,
+                          val);
+
        /* DAI Mode */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
@@ -545,6 +570,33 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
        u32 mode, val;
        u8 offset;
 
+       /* DAI clock polarity */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_IF:
+               /* Invert both clocks */
+               val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED |
+                     SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               /* Invert bit clock */
+               val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               /* Invert frame clock */
+               val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
+                          SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK |
+                          SUN8I_I2S_FMT0_BCLK_POLARITY_MASK,
+                          val);
+
        /* DAI Mode */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
@@ -601,36 +653,8 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
 static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       u32 bclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL;
-       u32 lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL;
        int ret;
 
-       /* DAI clock polarity */
-       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-       case SND_SOC_DAIFMT_IB_IF:
-               /* Invert both clocks */
-               bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
-               lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
-               break;
-       case SND_SOC_DAIFMT_IB_NF:
-               /* Invert bit clock */
-               bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
-               break;
-       case SND_SOC_DAIFMT_NB_IF:
-               /* Invert frame clock */
-               lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
-               break;
-       case SND_SOC_DAIFMT_NB_NF:
-               break;
-       default:
-               dev_err(dai->dev, "Unsupported clock polarity: %d\n",
-                       fmt & SND_SOC_DAIFMT_INV_MASK);
-               return -EINVAL;
-       }
-
-       regmap_field_write(i2s->field_fmt_bclk, bclk_polarity);
-       regmap_field_write(i2s->field_fmt_lrclk, lrclk_polarity);
-
        ret = i2s->variant->set_fmt(i2s, fmt);
        if (ret) {
                dev_err(dai->dev, "Unsupported format configuration\n");
@@ -984,8 +1008,6 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
        .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
        .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
        .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
-       .field_fmt_bclk         = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
-       .field_fmt_lrclk        = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
        .bclk_dividers          = sun4i_i2s_bclk_div,
        .num_bclk_dividers      = ARRAY_SIZE(sun4i_i2s_bclk_div),
        .mclk_dividers          = sun4i_i2s_mclk_div,
@@ -1004,8 +1026,6 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
        .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
        .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
        .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
-       .field_fmt_bclk         = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
-       .field_fmt_lrclk        = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
        .bclk_dividers          = sun4i_i2s_bclk_div,
        .num_bclk_dividers      = ARRAY_SIZE(sun4i_i2s_bclk_div),
        .mclk_dividers          = sun4i_i2s_mclk_div,
@@ -1024,8 +1044,6 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
        .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
        .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
        .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
-       .field_fmt_bclk         = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
-       .field_fmt_lrclk        = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
        .bclk_dividers          = sun8i_i2s_clk_div,
        .num_bclk_dividers      = ARRAY_SIZE(sun8i_i2s_clk_div),
        .mclk_dividers          = sun8i_i2s_clk_div,
@@ -1045,8 +1063,6 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
        .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
        .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2),
        .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
-       .field_fmt_bclk         = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
-       .field_fmt_lrclk        = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19),
        .bclk_dividers          = sun8i_i2s_clk_div,
        .num_bclk_dividers      = ARRAY_SIZE(sun8i_i2s_clk_div),
        .mclk_dividers          = sun8i_i2s_clk_div,
@@ -1065,8 +1081,6 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
        .field_clkdiv_mclk_en   = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
        .field_fmt_wss          = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
        .field_fmt_sr           = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
-       .field_fmt_bclk         = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
-       .field_fmt_lrclk        = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
        .bclk_dividers          = sun4i_i2s_bclk_div,
        .num_bclk_dividers      = ARRAY_SIZE(sun4i_i2s_bclk_div),
        .mclk_dividers          = sun4i_i2s_mclk_div,
@@ -1099,18 +1113,6 @@ static int sun4i_i2s_init_regmap_fields(struct device *dev,
        if (IS_ERR(i2s->field_fmt_sr))
                return PTR_ERR(i2s->field_fmt_sr);
 
-       i2s->field_fmt_bclk =
-                       devm_regmap_field_alloc(dev, i2s->regmap,
-                                               i2s->variant->field_fmt_bclk);
-       if (IS_ERR(i2s->field_fmt_bclk))
-               return PTR_ERR(i2s->field_fmt_bclk);
-
-       i2s->field_fmt_lrclk =
-                       devm_regmap_field_alloc(dev, i2s->regmap,
-                                               i2s->variant->field_fmt_lrclk);
-       if (IS_ERR(i2s->field_fmt_lrclk))
-               return PTR_ERR(i2s->field_fmt_lrclk);
-
        return 0;
 }