diff options
Diffstat (limited to 'sound/soc/sunxi/sun4i-i2s.c')
-rw-r--r-- | sound/soc/sunxi/sun4i-i2s.c | 91 |
1 files changed, 67 insertions, 24 deletions
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 1e9116cd365e..6028871825ba 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -115,9 +115,9 @@ #define SUN8I_I2S_FIFO_TX_REG 0x20 #define SUN8I_I2S_CHAN_CFG_REG 0x30 -#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4) +#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(7, 4) #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) ((chan - 1) << 4) -#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) +#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(3, 0) #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1) #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 @@ -138,13 +138,19 @@ #define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0) #define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1)) -#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44 -#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48 +#define SUN50I_H6_I2S_TX_CHAN_SEL_REG(pin) (0x34 + 4 * (pin)) +#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG(pin) (0x44 + 8 * (pin)) +#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG(pin) (0x48 + 8 * (pin)) #define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64 #define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68 #define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6C +#define SUN50I_R329_I2S_RX_CHAN_MAP0_REG 0x68 +#define SUN50I_R329_I2S_RX_CHAN_MAP1_REG 0x6c +#define SUN50I_R329_I2S_RX_CHAN_MAP2_REG 0x70 +#define SUN50I_R329_I2S_RX_CHAN_MAP3_REG 0x74 + struct sun4i_i2s; /** @@ -155,6 +161,8 @@ 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. + * @num_din_pins: input pins + * @num_dout_pins: output pins (currently set but unused) * @bclk_dividers: bit clock dividers array * @num_bclk_dividers: number of bit clock dividers * @mclk_dividers: mclk dividers array @@ -175,6 +183,9 @@ struct sun4i_i2s_quirks { struct reg_field field_fmt_wss; struct reg_field field_fmt_sr; + unsigned int num_din_pins; + unsigned int num_dout_pins; + const struct sun4i_i2s_clk_div *bclk_dividers; unsigned int num_bclk_dividers; const struct sun4i_i2s_clk_div *mclk_dividers; @@ -523,13 +534,20 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, unsigned int lrck_period; /* Map the channels for playback and capture */ - regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98); - regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210); - regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); - regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); + regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG(0), 0xFEDCBA98); + regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG(0), 0x76543210); + if (i2s->variant->num_din_pins > 1) { + regmap_write(i2s->regmap, SUN50I_R329_I2S_RX_CHAN_MAP0_REG, 0x0F0E0D0C); + regmap_write(i2s->regmap, SUN50I_R329_I2S_RX_CHAN_MAP1_REG, 0x0B0A0908); + regmap_write(i2s->regmap, SUN50I_R329_I2S_RX_CHAN_MAP2_REG, 0x07060504); + regmap_write(i2s->regmap, SUN50I_R329_I2S_RX_CHAN_MAP3_REG, 0x03020100); + } else { + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); + } /* Configure the channels */ - regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, + regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_SEL_REG(0), SUN50I_H6_I2S_TX_CHAN_SEL_MASK, SUN50I_H6_I2S_TX_CHAN_SEL(channels)); regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, @@ -563,7 +581,7 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); - regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, + regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_SEL_REG(0), SUN50I_H6_I2S_TX_CHAN_EN_MASK, SUN50I_H6_I2S_TX_CHAN_EN(channels)); @@ -686,13 +704,13 @@ static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, SUN4I_I2S_FMT0_FMT_MASK, val); /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* BCLK and LRCLK master */ val = SUN4I_I2S_CTRL_MODE_MASTER; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* BCLK and LRCLK slave */ val = SUN4I_I2S_CTRL_MODE_SLAVE; break; @@ -786,13 +804,13 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, SUN8I_I2S_TX_CHAN_OFFSET(offset)); /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* BCLK and LRCLK master */ val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* BCLK and LRCLK slave */ val = 0; break; @@ -893,13 +911,13 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* BCLK and LRCLK master */ val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* BCLK and LRCLK slave */ val = 0; break; @@ -1107,7 +1125,8 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = { }; static const struct snd_soc_component_driver sun4i_i2s_component = { - .name = "sun4i-dai", + .name = "sun4i-dai", + .legacy_dai_naming = 1, }; static bool sun4i_i2s_rd_reg(struct device *dev, unsigned int reg) @@ -1210,9 +1229,9 @@ static const struct reg_default sun50i_h6_i2s_reg_defaults[] = { { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, - { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, - { SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0x00000000 }, - { SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x00000000 }, + { SUN50I_H6_I2S_TX_CHAN_SEL_REG(0), 0x00000000 }, + { SUN50I_H6_I2S_TX_CHAN_MAP0_REG(0), 0x00000000 }, + { SUN50I_H6_I2S_TX_CHAN_MAP1_REG(0), 0x00000000 }, { SUN50I_H6_I2S_RX_CHAN_SEL_REG, 0x00000000 }, { SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x00000000 }, { SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x00000000 }, @@ -1249,7 +1268,7 @@ static const struct regmap_config sun50i_h6_i2s_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = SUN50I_H6_I2S_RX_CHAN_MAP1_REG, + .max_register = SUN50I_R329_I2S_RX_CHAN_MAP3_REG, .cache_type = REGCACHE_FLAT, .reg_defaults = sun50i_h6_i2s_reg_defaults, .num_reg_defaults = ARRAY_SIZE(sun50i_h6_i2s_reg_defaults), @@ -1434,6 +1453,26 @@ static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = { .set_fmt = sun50i_h6_i2s_set_soc_fmt, }; +static const struct sun4i_i2s_quirks sun50i_r329_i2s_quirks = { + .has_reset = true, + .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, + .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config, + .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), + .num_din_pins = 4, + .num_dout_pins = 4, + .bclk_dividers = sun8i_i2s_clk_div, + .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), + .mclk_dividers = sun8i_i2s_clk_div, + .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), + .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate, + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, + .set_chan_cfg = sun50i_h6_i2s_set_chan_cfg, + .set_fmt = sun50i_h6_i2s_set_soc_fmt, +}; + static int sun4i_i2s_init_regmap_fields(struct device *dev, struct sun4i_i2s *i2s) { @@ -1606,6 +1645,10 @@ static const struct of_device_id sun4i_i2s_match[] = { .compatible = "allwinner,sun50i-h6-i2s", .data = &sun50i_h6_i2s_quirks, }, + { + .compatible = "allwinner,sun50i-r329-i2s", + .data = &sun50i_r329_i2s_quirks, + }, {} }; MODULE_DEVICE_TABLE(of, sun4i_i2s_match); |