aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sunxi/sun4i-i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sunxi/sun4i-i2s.c')
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c91
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);