Switch usage to regmap field for bits handled by the g12a_toacodec_mux_put_enum() function to avoid uselesss code duplication when adding SM1 variant support. Signed-off-by: Neil Armstrong <narmstrong@xxxxxxxxxxxx> --- sound/soc/meson/g12a-toacodec.c | 80 +++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c index 9339fabccb79..2084c9542c9c 100644 --- a/sound/soc/meson/g12a-toacodec.c +++ b/sound/soc/meson/g12a-toacodec.c @@ -21,17 +21,31 @@ #define TOACODEC_CTRL0 0x0 #define CTRL0_ENABLE_SHIFT 31 -#define CTRL0_DAT_SEL_SHIFT 14 -#define CTRL0_DAT_SEL (0x3 << CTRL0_DAT_SEL_SHIFT) +#define CTRL0_DAT_SEL_MSB 15 +#define CTRL0_DAT_SEL_LSB 14 #define CTRL0_LANE_SEL 12 -#define CTRL0_LRCLK_SEL GENMASK(9, 8) +#define CTRL0_LRCLK_SEL_MSB 9 +#define CTRL0_LRCLK_SEL_LSB 8 #define CTRL0_BLK_CAP_INV BIT(7) #define CTRL0_BCLK_O_INV BIT(6) -#define CTRL0_BCLK_SEL GENMASK(5, 4) +#define CTRL0_BCLK_SEL_MSB 5 +#define CTRL0_BCLK_SEL_LSB 4 #define CTRL0_MCLK_SEL GENMASK(2, 0) #define TOACODEC_OUT_CHMAX 2 +struct g12a_toacodec { + struct regmap_field *field_dat_sel; + struct regmap_field *field_lrclk_sel; + struct regmap_field *field_bclk_sel; +}; + +struct g12a_toacodec_match_data { + struct reg_field field_dat_sel; + struct reg_field field_lrclk_sel; + struct reg_field field_bclk_sel; +}; + static const char * const g12a_toacodec_mux_texts[] = { "I2S A", "I2S B", "I2S C", }; @@ -41,29 +55,24 @@ static int g12a_toacodec_mux_put_enum(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); + struct g12a_toacodec *priv = snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int mux, changed; + unsigned int mux, reg; mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); - changed = snd_soc_component_test_bits(component, e->reg, - CTRL0_DAT_SEL, - FIELD_PREP(CTRL0_DAT_SEL, mux)); + regmap_field_read(priv->field_dat_sel, ®); - if (!changed) + if (mux == reg) return 0; /* Force disconnect of the mux while updating */ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); - snd_soc_component_update_bits(component, e->reg, - CTRL0_DAT_SEL | - CTRL0_LRCLK_SEL | - CTRL0_BCLK_SEL, - FIELD_PREP(CTRL0_DAT_SEL, mux) | - FIELD_PREP(CTRL0_LRCLK_SEL, mux) | - FIELD_PREP(CTRL0_BCLK_SEL, mux)); + regmap_field_write(priv->field_dat_sel, mux); + regmap_field_write(priv->field_lrclk_sel, mux); + regmap_field_write(priv->field_bclk_sel, mux); /* * FIXME: @@ -86,7 +95,7 @@ static int g12a_toacodec_mux_put_enum(struct snd_kcontrol *kcontrol, } static SOC_ENUM_SINGLE_DECL(g12a_toacodec_mux_enum, TOACODEC_CTRL0, - CTRL0_DAT_SEL_SHIFT, + CTRL0_DAT_SEL_LSB, g12a_toacodec_mux_texts); static const struct snd_kcontrol_new g12a_toacodec_mux = @@ -205,19 +214,42 @@ static const struct regmap_config g12a_toacodec_regmap_cfg = { .reg_stride = 4, }; +static const struct g12a_toacodec_match_data g12a_toacodec_match_data = { + .field_dat_sel = REG_FIELD(TOACODEC_CTRL0, CTRL0_DAT_SEL_LSB, CTRL0_DAT_SEL_MSB), + .field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, CTRL0_LRCLK_SEL_LSB, CTRL0_LRCLK_SEL_MSB), + .field_bclk_sel = REG_FIELD(TOACODEC_CTRL0, CTRL0_BCLK_SEL_LSB, CTRL0_BCLK_SEL_MSB), +}; + static const struct of_device_id g12a_toacodec_of_match[] = { - { .compatible = "amlogic,g12a-toacodec", }, + { + .compatible = "amlogic,g12a-toacodec", + .data = &g12a_toacodec_match_data, + }, {} }; MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match); static int g12a_toacodec_probe(struct platform_device *pdev) { + const struct g12a_toacodec_match_data *data; struct device *dev = &pdev->dev; + struct g12a_toacodec *priv; void __iomem *regs; struct regmap *map; int ret; + data = device_get_match_data(dev); + if (!data) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + ret = device_reset(dev); if (ret) return ret; @@ -233,6 +265,18 @@ static int g12a_toacodec_probe(struct platform_device *pdev) return PTR_ERR(map); } + priv->field_dat_sel = devm_regmap_field_alloc(dev, map, data->field_dat_sel); + if (IS_ERR(priv->field_dat_sel)) + return PTR_ERR(priv->field_dat_sel); + + priv->field_lrclk_sel = devm_regmap_field_alloc(dev, map, data->field_lrclk_sel); + if (IS_ERR(priv->field_lrclk_sel)) + return PTR_ERR(priv->field_lrclk_sel); + + priv->field_bclk_sel = devm_regmap_field_alloc(dev, map, data->field_bclk_sel); + if (IS_ERR(priv->field_bclk_sel)) + return PTR_ERR(priv->field_bclk_sel); + return devm_snd_soc_register_component(dev, &g12a_toacodec_component_drv, g12a_toacodec_dai_drv, ARRAY_SIZE(g12a_toacodec_dai_drv)); -- 2.25.1