From 12132de654bbcd16f6e4e9c0bf2947356756f773 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 29 Jan 2018 03:13:23 +0000 Subject: [PATCH 01/15] ASoC: ak5386: replace codec to component Now we can replace Codec to Component. Let's do it. Note: xxx_codec_xxx() -> xxx_component_xxx() .idle_bias_off = 0 -> .idle_bias_on = 1 .ignore_pmdown_time = 0 -> .use_pmdown_time = 1 - -> .endianness = 1 - -> .non_legacy_dai_naming = 1 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak5386.c | 62 ++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c index d0e16c03815c..d212960b4dda 100644 --- a/sound/soc/codecs/ak5386.c +++ b/sound/soc/codecs/ak5386.c @@ -38,30 +38,29 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = { { "Capture", NULL, "AINR" }, }; -static int ak5386_soc_probe(struct snd_soc_codec *codec) +static int ak5386_soc_probe(struct snd_soc_component *component) { - struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); + struct ak5386_priv *priv = snd_soc_component_get_drvdata(component); return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); } -static int ak5386_soc_remove(struct snd_soc_codec *codec) +static void ak5386_soc_remove(struct snd_soc_component *component) { - struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); + struct ak5386_priv *priv = snd_soc_component_get_drvdata(component); regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); - return 0; } #ifdef CONFIG_PM -static int ak5386_soc_suspend(struct snd_soc_codec *codec) +static int ak5386_soc_suspend(struct snd_soc_component *component) { - struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); + struct ak5386_priv *priv = snd_soc_component_get_drvdata(component); regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); return 0; } -static int ak5386_soc_resume(struct snd_soc_codec *codec) +static int ak5386_soc_resume(struct snd_soc_component *component) { - struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); + struct ak5386_priv *priv = snd_soc_component_get_drvdata(component); return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); } #else @@ -69,28 +68,30 @@ static int ak5386_soc_resume(struct snd_soc_codec *codec) #define ak5386_soc_resume NULL #endif /* CONFIG_PM */ -static const struct snd_soc_codec_driver soc_codec_ak5386 = { - .probe = ak5386_soc_probe, - .remove = ak5386_soc_remove, - .suspend = ak5386_soc_suspend, - .resume = ak5386_soc_resume, - .component_driver = { - .dapm_widgets = ak5386_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), - .dapm_routes = ak5386_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes), - }, +static const struct snd_soc_component_driver soc_component_ak5386 = { + .probe = ak5386_soc_probe, + .remove = ak5386_soc_remove, + .suspend = ak5386_soc_suspend, + .resume = ak5386_soc_resume, + .dapm_widgets = ak5386_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), + .dapm_routes = ak5386_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, }; static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int format) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; format &= SND_SOC_DAIFMT_FORMAT_MASK; if (format != SND_SOC_DAIFMT_LEFT_J && format != SND_SOC_DAIFMT_I2S) { - dev_err(codec->dev, "Invalid DAI format\n"); + dev_err(component->dev, "Invalid DAI format\n"); return -EINVAL; } @@ -101,8 +102,8 @@ static int ak5386_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_codec *codec = dai->codec; - struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct ak5386_priv *priv = snd_soc_component_get_drvdata(component); /* * From the datasheet: @@ -123,8 +124,8 @@ static int ak5386_hw_params(struct snd_pcm_substream *substream, static int ak5386_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_codec *codec = dai->codec; - struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct ak5386_priv *priv = snd_soc_component_get_drvdata(component); if (gpio_is_valid(priv->reset_gpio)) gpio_set_value(priv->reset_gpio, 0); @@ -192,19 +193,12 @@ static int ak5386_probe(struct platform_device *pdev) "AK5386 Reset")) priv->reset_gpio = -EINVAL; - return snd_soc_register_codec(dev, &soc_codec_ak5386, + return devm_snd_soc_register_component(dev, &soc_component_ak5386, &ak5386_dai, 1); } -static int ak5386_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - static struct platform_driver ak5386_driver = { .probe = ak5386_probe, - .remove = ak5386_remove, .driver = { .name = "ak5386", .of_match_table = of_match_ptr(ak5386_dt_ids), From c778b7715f66c97f6b41077c72a16ad3553817ff Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 29 Jan 2018 04:33:31 +0000 Subject: [PATCH 02/15] ASoC: alc5632: replace codec to component Now we can replace Codec to Component. Let's do it. Note: xxx_codec_xxx() -> xxx_component_xxx() .idle_bias_off = 0 -> .idle_bias_on = 1 .ignore_pmdown_time = 0 -> .use_pmdown_time = 1 - -> .endianness = 1 - -> .non_legacy_dai_naming = 1 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/alc5632.c | 138 ++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 72 deletions(-) diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index adb80d8719bd..08034a6d4c5a 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -116,20 +116,20 @@ static inline int alc5632_reset(struct regmap *map) static int amp_mixer_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); /* to power-on/off class-d amp generators/speaker */ /* need to write to 'index-46h' register : */ /* so write index num (here 0x46) to reg 0x6a */ /* and then 0xffff/0 to reg 0x6c */ - snd_soc_write(codec, ALC5632_HID_CTRL_INDEX, 0x46); + snd_soc_component_write(component, ALC5632_HID_CTRL_INDEX, 0x46); switch (event) { case SND_SOC_DAPM_PRE_PMU: - snd_soc_write(codec, ALC5632_HID_CTRL_DATA, 0xFFFF); + snd_soc_component_write(component, ALC5632_HID_CTRL_DATA, 0xFFFF); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_write(codec, ALC5632_HID_CTRL_DATA, 0); + snd_soc_component_write(component, ALC5632_HID_CTRL_DATA, 0); break; } @@ -681,7 +681,7 @@ static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { int i; - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; int gbl_clk = 0, pll_div = 0; u16 reg; @@ -689,15 +689,15 @@ static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, return -EINVAL; /* Disable PLL power */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_ADD2_PLL1, 0); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_ADD2_PLL2, 0); /* pll is not used in slave mode */ - reg = snd_soc_read(codec, ALC5632_DAI_CONTROL); + reg = snd_soc_component_read32(component, ALC5632_DAI_CONTROL); if (reg & ALC5632_DAI_SDP_SLAVE_MODE) return 0; @@ -745,19 +745,19 @@ static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, return -EINVAL; /* choose MCLK/BCLK/VBCLK */ - snd_soc_write(codec, ALC5632_GPCR2, gbl_clk); + snd_soc_component_write(component, ALC5632_GPCR2, gbl_clk); /* choose PLL1 clock rate */ - snd_soc_write(codec, ALC5632_PLL1_CTRL, pll_div); + snd_soc_component_write(component, ALC5632_PLL1_CTRL, pll_div); /* enable PLL1 */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_ADD2_PLL1, ALC5632_PWR_ADD2_PLL1); /* enable PLL2 */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_ADD2_PLL2, ALC5632_PWR_ADD2_PLL2); /* use PLL1 as main SYSCLK */ - snd_soc_update_bits(codec, ALC5632_GPCR1, + snd_soc_component_update_bits(component, ALC5632_GPCR1, ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1, ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1); @@ -775,9 +775,9 @@ static const struct _coeff_div coeff_div[] = { {512*1, 0x3075}, }; -static int get_coeff(struct snd_soc_codec *codec, int rate) +static int get_coeff(struct snd_soc_component *component, int rate) { - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); + struct alc5632_priv *alc5632 = snd_soc_component_get_drvdata(component); int i; for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { @@ -793,8 +793,8 @@ static int get_coeff(struct snd_soc_codec *codec, int rate) static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { - struct snd_soc_codec *codec = codec_dai->codec; - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = codec_dai->component; + struct alc5632_priv *alc5632 = snd_soc_component_get_drvdata(component); switch (freq) { case 4096000: @@ -815,7 +815,7 @@ static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int alc5632_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; u16 iface = 0; /* set master/slave audio interface */ @@ -864,17 +864,17 @@ static int alc5632_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - return snd_soc_write(codec, ALC5632_DAI_CONTROL, iface); + return snd_soc_component_write(component, ALC5632_DAI_CONTROL, iface); } static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; int coeff, rate; u16 iface; - iface = snd_soc_read(codec, ALC5632_DAI_CONTROL); + iface = snd_soc_component_read32(component, ALC5632_DAI_CONTROL); iface &= ~ALC5632_DAI_I2S_DL_MASK; /* bit size */ @@ -893,29 +893,29 @@ static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - snd_soc_write(codec, ALC5632_DAI_CONTROL, iface); + snd_soc_component_write(component, ALC5632_DAI_CONTROL, iface); rate = params_rate(params); - coeff = get_coeff(codec, rate); + coeff = get_coeff(component, rate); if (coeff < 0) return -EINVAL; coeff = coeff_div[coeff].regvalue; - snd_soc_write(codec, ALC5632_DAC_CLK_CTRL1, coeff); + snd_soc_component_write(component, ALC5632_DAC_CLK_CTRL1, coeff); return 0; } static int alc5632_mute(struct snd_soc_dai *dai, int mute) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; u16 hp_mute = ALC5632_MISC_HP_DEPOP_MUTE_L |ALC5632_MISC_HP_DEPOP_MUTE_R; - u16 mute_reg = snd_soc_read(codec, ALC5632_MISC_CTRL) & ~hp_mute; + u16 mute_reg = snd_soc_component_read32(component, ALC5632_MISC_CTRL) & ~hp_mute; if (mute) mute_reg |= hp_mute; - return snd_soc_write(codec, ALC5632_MISC_CTRL, mute_reg); + return snd_soc_component_write(component, ALC5632_MISC_CTRL, mute_reg); } #define ALC5632_ADD2_POWER_EN (ALC5632_PWR_ADD2_VREF) @@ -929,73 +929,73 @@ static int alc5632_mute(struct snd_soc_dai *dai, int mute) | ALC5632_PWR_ADD1_HP_OUT_ENH_AMP \ | ALC5632_PWR_ADD1_MAIN_BIAS) -static void enable_power_depop(struct snd_soc_codec *codec) +static void enable_power_depop(struct snd_soc_component *component) { - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD1, ALC5632_PWR_ADD1_SOFTGEN_EN, ALC5632_PWR_ADD1_SOFTGEN_EN); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD3, ALC5632_ADD3_POWER_EN, ALC5632_ADD3_POWER_EN); - snd_soc_update_bits(codec, ALC5632_MISC_CTRL, + snd_soc_component_update_bits(component, ALC5632_MISC_CTRL, ALC5632_MISC_HP_DEPOP_MODE2_EN, ALC5632_MISC_HP_DEPOP_MODE2_EN); /* "normal" mode: 0 @ 26 */ /* set all PR0-7 mixers to 0 */ - snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS, + snd_soc_component_update_bits(component, ALC5632_PWR_DOWN_CTRL_STATUS, ALC5632_PWR_DOWN_CTRL_STATUS_MASK, 0); msleep(500); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD2, ALC5632_ADD2_POWER_EN, ALC5632_ADD2_POWER_EN); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD1, ALC5632_ADD1_POWER_EN, ALC5632_ADD1_POWER_EN); /* disable HP Depop2 */ - snd_soc_update_bits(codec, ALC5632_MISC_CTRL, + snd_soc_component_update_bits(component, ALC5632_MISC_CTRL, ALC5632_MISC_HP_DEPOP_MODE2_EN, 0); } -static int alc5632_set_bias_level(struct snd_soc_codec *codec, +static int alc5632_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_ON: - enable_power_depop(codec); + enable_power_depop(component); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* everything off except vref/vmid, */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD1, ALC5632_PWR_MANAG_ADD1_MASK, ALC5632_PWR_ADD1_MAIN_BIAS); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_MANAG_ADD2_MASK, ALC5632_PWR_ADD2_VREF); /* "normal" mode: 0 @ 26 */ - snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS, + snd_soc_component_update_bits(component, ALC5632_PWR_DOWN_CTRL_STATUS, ALC5632_PWR_DOWN_CTRL_STATUS_MASK, 0xffff ^ (ALC5632_PWR_VREF_PR3 | ALC5632_PWR_VREF_PR2)); break; case SND_SOC_BIAS_OFF: /* everything off, dac mute, inactive */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_MANAG_ADD2_MASK, 0); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD3, ALC5632_PWR_MANAG_ADD3_MASK, 0); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, + snd_soc_component_update_bits(component, ALC5632_PWR_MANAG_ADD1, ALC5632_PWR_MANAG_ADD1_MASK, 0); break; } @@ -1038,9 +1038,9 @@ static struct snd_soc_dai_driver alc5632_dai = { }; #ifdef CONFIG_PM -static int alc5632_resume(struct snd_soc_codec *codec) +static int alc5632_resume(struct snd_soc_component *component) { - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); + struct alc5632_priv *alc5632 = snd_soc_component_get_drvdata(component); regcache_sync(alc5632->regmap); @@ -1050,13 +1050,13 @@ static int alc5632_resume(struct snd_soc_codec *codec) #define alc5632_resume NULL #endif -static int alc5632_probe(struct snd_soc_codec *codec) +static int alc5632_probe(struct snd_soc_component *component) { - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); + struct alc5632_priv *alc5632 = snd_soc_component_get_drvdata(component); switch (alc5632->id) { case 0x5c: - snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls, + snd_soc_add_component_controls(component, alc5632_vol_snd_controls, ARRAY_SIZE(alc5632_vol_snd_controls)); break; default: @@ -1066,20 +1066,21 @@ static int alc5632_probe(struct snd_soc_codec *codec) return 0; } -static const struct snd_soc_codec_driver soc_codec_device_alc5632 = { - .probe = alc5632_probe, - .resume = alc5632_resume, - .set_bias_level = alc5632_set_bias_level, - .suspend_bias_off = true, - - .component_driver = { - .controls = alc5632_snd_controls, - .num_controls = ARRAY_SIZE(alc5632_snd_controls), - .dapm_widgets = alc5632_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets), - .dapm_routes = alc5632_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), - }, +static const struct snd_soc_component_driver soc_component_device_alc5632 = { + .probe = alc5632_probe, + .resume = alc5632_resume, + .set_bias_level = alc5632_set_bias_level, + .controls = alc5632_snd_controls, + .num_controls = ARRAY_SIZE(alc5632_snd_controls), + .dapm_widgets = alc5632_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets), + .dapm_routes = alc5632_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, }; static const struct regmap_config alc5632_regmap = { @@ -1151,23 +1152,17 @@ static int alc5632_i2c_probe(struct i2c_client *client, return -EINVAL; } - ret = snd_soc_register_codec(&client->dev, - &soc_codec_device_alc5632, &alc5632_dai, 1); + ret = devm_snd_soc_register_component(&client->dev, + &soc_component_device_alc5632, &alc5632_dai, 1); if (ret < 0) { - dev_err(&client->dev, "Failed to register codec: %d\n", ret); + dev_err(&client->dev, "Failed to register component: %d\n", ret); return ret; } return ret; } -static int alc5632_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - static const struct i2c_device_id alc5632_i2c_table[] = { {"alc5632", 0x5c}, {} @@ -1187,7 +1182,6 @@ static struct i2c_driver alc5632_i2c_driver = { .of_match_table = of_match_ptr(alc5632_of_match), }, .probe = alc5632_i2c_probe, - .remove = alc5632_i2c_remove, .id_table = alc5632_i2c_table, }; From fd7c728de88eaea0d740b0d92ef73bbe8527a55d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 29 Jan 2018 04:34:01 +0000 Subject: [PATCH 03/15] ASoC: alc5623: replace codec to component Now we can replace Codec to Component. Let's do it. Note: xxx_codec_xxx() -> xxx_component_xxx() .idle_bias_off = 0 -> .idle_bias_on = 1 .ignore_pmdown_time = 0 -> .use_pmdown_time = 1 - -> .endianness = 1 - -> .non_legacy_dai_naming = 1 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/alc5623.c | 147 ++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 75 deletions(-) diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 1db965a93632..981a32973c08 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -47,28 +47,28 @@ struct alc5623_priv { unsigned int jack_det_ctrl; }; -static inline int alc5623_reset(struct snd_soc_codec *codec) +static inline int alc5623_reset(struct snd_soc_component *component) { - return snd_soc_write(codec, ALC5623_RESET, 0); + return snd_soc_component_write(component, ALC5623_RESET, 0); } static int amp_mixer_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); /* to power-on/off class-d amp generators/speaker */ /* need to write to 'index-46h' register : */ /* so write index num (here 0x46) to reg 0x6a */ /* and then 0xffff/0 to reg 0x6c */ - snd_soc_write(codec, ALC5623_HID_CTRL_INDEX, 0x46); + snd_soc_component_write(component, ALC5623_HID_CTRL_INDEX, 0x46); switch (event) { case SND_SOC_DAPM_PRE_PMU: - snd_soc_write(codec, ALC5623_HID_CTRL_DATA, 0xFFFF); + snd_soc_component_write(component, ALC5623_HID_CTRL_DATA, 0xFFFF); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_write(codec, ALC5623_HID_CTRL_DATA, 0); + snd_soc_component_write(component, ALC5623_HID_CTRL_DATA, 0); break; } @@ -526,7 +526,7 @@ static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { int i; - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; int gbl_clk = 0, pll_div = 0; u16 reg; @@ -534,12 +534,12 @@ static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, return -ENODEV; /* Disable PLL power */ - snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2, + snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD2, ALC5623_PWR_ADD2_PLL, 0); /* pll is not used in slave mode */ - reg = snd_soc_read(codec, ALC5623_DAI_CONTROL); + reg = snd_soc_component_read32(component, ALC5623_DAI_CONTROL); if (reg & ALC5623_DAI_SDP_SLAVE_MODE) return 0; @@ -575,13 +575,13 @@ static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (!pll_div) return -EINVAL; - snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk); - snd_soc_write(codec, ALC5623_PLL_CTRL, pll_div); - snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2, + snd_soc_component_write(component, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk); + snd_soc_component_write(component, ALC5623_PLL_CTRL, pll_div); + snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD2, ALC5623_PWR_ADD2_PLL, ALC5623_PWR_ADD2_PLL); gbl_clk |= ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL; - snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk); + snd_soc_component_write(component, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk); return 0; } @@ -604,9 +604,9 @@ static const struct _coeff_div coeff_div[] = { {384*1, 0x0c6b}, }; -static int get_coeff(struct snd_soc_codec *codec, int rate) +static int get_coeff(struct snd_soc_component *component, int rate) { - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component); int i; for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { @@ -622,8 +622,8 @@ static int get_coeff(struct snd_soc_codec *codec, int rate) static int alc5623_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { - struct snd_soc_codec *codec = codec_dai->codec; - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = codec_dai->component; + struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component); switch (freq) { case 8192000: @@ -643,7 +643,7 @@ static int alc5623_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; u16 iface = 0; /* set master/slave audio interface */ @@ -695,18 +695,18 @@ static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - return snd_soc_write(codec, ALC5623_DAI_CONTROL, iface); + return snd_soc_component_write(component, ALC5623_DAI_CONTROL, iface); } static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_codec *codec = dai->codec; - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component); int coeff, rate; u16 iface; - iface = snd_soc_read(codec, ALC5623_DAI_CONTROL); + iface = snd_soc_component_read32(component, ALC5623_DAI_CONTROL); iface &= ~ALC5623_DAI_I2S_DL_MASK; /* bit size */ @@ -728,30 +728,30 @@ static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - snd_soc_write(codec, ALC5623_DAI_CONTROL, iface); + snd_soc_component_write(component, ALC5623_DAI_CONTROL, iface); rate = params_rate(params); - coeff = get_coeff(codec, rate); + coeff = get_coeff(component, rate); if (coeff < 0) return -EINVAL; coeff = coeff_div[coeff].regvalue; - dev_dbg(codec->dev, "%s: sysclk=%d,rate=%d,coeff=0x%04x\n", + dev_dbg(component->dev, "%s: sysclk=%d,rate=%d,coeff=0x%04x\n", __func__, alc5623->sysclk, rate, coeff); - snd_soc_write(codec, ALC5623_STEREO_AD_DA_CLK_CTRL, coeff); + snd_soc_component_write(component, ALC5623_STEREO_AD_DA_CLK_CTRL, coeff); return 0; } static int alc5623_mute(struct snd_soc_dai *dai, int mute) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT; - u16 mute_reg = snd_soc_read(codec, ALC5623_MISC_CTRL) & ~hp_mute; + u16 mute_reg = snd_soc_component_read32(component, ALC5623_MISC_CTRL) & ~hp_mute; if (mute) mute_reg |= hp_mute; - return snd_soc_write(codec, ALC5623_MISC_CTRL, mute_reg); + return snd_soc_component_write(component, ALC5623_MISC_CTRL, mute_reg); } #define ALC5623_ADD2_POWER_EN (ALC5623_PWR_ADD2_VREF \ @@ -769,60 +769,60 @@ static int alc5623_mute(struct snd_soc_dai *dai, int mute) (ALC5623_PWR_ADD1_SHORT_CURR_DET_EN \ | ALC5623_PWR_ADD1_HP_OUT_AMP) -static void enable_power_depop(struct snd_soc_codec *codec) +static void enable_power_depop(struct snd_soc_component *component) { - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component); - snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD1, + snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD1, ALC5623_PWR_ADD1_SOFTGEN_EN, ALC5623_PWR_ADD1_SOFTGEN_EN); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, ALC5623_ADD3_POWER_EN); + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3, ALC5623_ADD3_POWER_EN); - snd_soc_update_bits(codec, ALC5623_MISC_CTRL, + snd_soc_component_update_bits(component, ALC5623_MISC_CTRL, ALC5623_MISC_HP_DEPOP_MODE2_EN, ALC5623_MISC_HP_DEPOP_MODE2_EN); msleep(500); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, ALC5623_ADD2_POWER_EN); + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2, ALC5623_ADD2_POWER_EN); /* avoid writing '1' into 5622 reserved bits */ if (alc5623->id == 0x22) - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1, ALC5623_ADD1_POWER_EN_5622); else - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1, ALC5623_ADD1_POWER_EN); /* disable HP Depop2 */ - snd_soc_update_bits(codec, ALC5623_MISC_CTRL, + snd_soc_component_update_bits(component, ALC5623_MISC_CTRL, ALC5623_MISC_HP_DEPOP_MODE2_EN, 0); } -static int alc5623_set_bias_level(struct snd_soc_codec *codec, +static int alc5623_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_ON: - enable_power_depop(codec); + enable_power_depop(component); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* everything off except vref/vmid, */ - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2, ALC5623_PWR_ADD2_VREF); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3, ALC5623_PWR_ADD3_MAIN_BIAS); break; case SND_SOC_BIAS_OFF: /* everything off, dac mute, inactive */ - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, 0); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, 0); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, 0); + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2, 0); + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3, 0); + snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1, 0); break; } return 0; @@ -862,25 +862,25 @@ static struct snd_soc_dai_driver alc5623_dai = { .ops = &alc5623_dai_ops, }; -static int alc5623_suspend(struct snd_soc_codec *codec) +static int alc5623_suspend(struct snd_soc_component *component) { - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component); regcache_cache_only(alc5623->regmap, true); return 0; } -static int alc5623_resume(struct snd_soc_codec *codec) +static int alc5623_resume(struct snd_soc_component *component) { - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component); int ret; /* Sync reg_cache with the hardware */ regcache_cache_only(alc5623->regmap, false); ret = regcache_sync(alc5623->regmap); if (ret != 0) { - dev_err(codec->dev, "Failed to sync register cache: %d\n", + dev_err(component->dev, "Failed to sync register cache: %d\n", ret); regcache_cache_only(alc5623->regmap, true); return ret; @@ -889,41 +889,41 @@ static int alc5623_resume(struct snd_soc_codec *codec) return 0; } -static int alc5623_probe(struct snd_soc_codec *codec) +static int alc5623_probe(struct snd_soc_component *component) { - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - alc5623_reset(codec); + alc5623_reset(component); if (alc5623->add_ctrl) { - snd_soc_write(codec, ALC5623_ADD_CTRL_REG, + snd_soc_component_write(component, ALC5623_ADD_CTRL_REG, alc5623->add_ctrl); } if (alc5623->jack_det_ctrl) { - snd_soc_write(codec, ALC5623_JACK_DET_CTRL, + snd_soc_component_write(component, ALC5623_JACK_DET_CTRL, alc5623->jack_det_ctrl); } switch (alc5623->id) { case 0x21: - snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls, + snd_soc_add_component_controls(component, alc5621_vol_snd_controls, ARRAY_SIZE(alc5621_vol_snd_controls)); break; case 0x22: - snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls, + snd_soc_add_component_controls(component, alc5622_vol_snd_controls, ARRAY_SIZE(alc5622_vol_snd_controls)); break; case 0x23: - snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls, + snd_soc_add_component_controls(component, alc5623_vol_snd_controls, ARRAY_SIZE(alc5623_vol_snd_controls)); break; default: return -EINVAL; } - snd_soc_add_codec_controls(codec, alc5623_snd_controls, + snd_soc_add_component_controls(component, alc5623_snd_controls, ARRAY_SIZE(alc5623_snd_controls)); snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets, @@ -951,12 +951,16 @@ static int alc5623_probe(struct snd_soc_codec *codec) return 0; } -static const struct snd_soc_codec_driver soc_codec_device_alc5623 = { - .probe = alc5623_probe, - .suspend = alc5623_suspend, - .resume = alc5623_resume, - .set_bias_level = alc5623_set_bias_level, - .suspend_bias_off = true, +static const struct snd_soc_component_driver soc_component_device_alc5623 = { + .probe = alc5623_probe, + .suspend = alc5623_suspend, + .resume = alc5623_resume, + .set_bias_level = alc5623_set_bias_level, + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, }; static const struct regmap_config alc5623_regmap = { @@ -1052,20 +1056,14 @@ static int alc5623_i2c_probe(struct i2c_client *client, i2c_set_clientdata(client, alc5623); - ret = snd_soc_register_codec(&client->dev, - &soc_codec_device_alc5623, &alc5623_dai, 1); + ret = devm_snd_soc_register_component(&client->dev, + &soc_component_device_alc5623, &alc5623_dai, 1); if (ret != 0) dev_err(&client->dev, "Failed to register codec: %d\n", ret); return ret; } -static int alc5623_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - static const struct i2c_device_id alc5623_i2c_table[] = { {"alc5621", 0x21}, {"alc5622", 0x22}, @@ -1087,7 +1085,6 @@ static struct i2c_driver alc5623_i2c_driver = { .of_match_table = of_match_ptr(alc5623_of_match), }, .probe = alc5623_i2c_probe, - .remove = alc5623_i2c_remove, .id_table = alc5623_i2c_table, }; From 920884777480739789bb94ce8aeab1bc1de30dc2 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 13 Feb 2018 16:29:33 +0200 Subject: [PATCH 04/15] ASoC: ak5558: Add support for AK5558 ADC driver AK5558 is a 32-bit, 768 kHZ sampling, differential input ADC for digital audio systems. Datasheet is available at: https://www.akm.com/akm/en/file/datasheet/AK5558VN.pdf Initial patch includes support for normal and TDM modes. Reviewed-by: Andy Shevchenko Reviewed-by: Fabio Estevam Signed-off-by: Junichi Wakasugi [initial coding for 3.18 kernel] Signed-off-by: Mihai Serban [cleanups and porting to 4.9 kernel] Signed-off-by: Shengjiu Wang [tdm support] Signed-off-by: Daniel Baluta [pm support, cleanups and porting to latest kernel] Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/ak5558.c | 417 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/ak5558.h | 52 +++++ 4 files changed, 477 insertions(+) create mode 100644 sound/soc/codecs/ak5558.c create mode 100644 sound/soc/codecs/ak5558.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2b331f7266ab..c29728c5f4e0 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -42,6 +42,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_AK4642 if I2C select SND_SOC_AK4671 if I2C select SND_SOC_AK5386 + select SND_SOC_AK5558 if I2C select SND_SOC_ALC5623 if I2C select SND_SOC_ALC5632 if I2C select SND_SOC_BT_SCO @@ -398,6 +399,11 @@ config SND_SOC_AK4671 config SND_SOC_AK5386 tristate "AKM AK5638 CODEC" +config SND_SOC_AK5558 + tristate "AKM AK5558 CODEC" + depends on I2C + select REGMAP_I2C + config SND_SOC_ALC5623 tristate "Realtek ALC5623 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index da1571336f1e..3e71d40cca19 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -34,6 +34,7 @@ snd-soc-ak4641-objs := ak4641.o snd-soc-ak4642-objs := ak4642.o snd-soc-ak4671-objs := ak4671.o snd-soc-ak5386-objs := ak5386.o +snd-soc-ak5558-objs := ak5558.o snd-soc-arizona-objs := arizona.o snd-soc-bt-sco-objs := bt-sco.o snd-soc-cq93vc-objs := cq93vc.o @@ -277,6 +278,7 @@ obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o obj-$(CONFIG_SND_SOC_AK5386) += snd-soc-ak5386.o +obj-$(CONFIG_SND_SOC_AK5558) += snd-soc-ak5558.o obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c new file mode 100644 index 000000000000..225173ff4efa --- /dev/null +++ b/sound/soc/codecs/ak5558.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Audio driver for AK5558 ADC + * + * Copyright (C) 2015 Asahi Kasei Microdevices Corporation + * Copyright 2018 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ak5558.h" + +/* AK5558 Codec Private Data */ +struct ak5558_priv { + struct snd_soc_codec codec; + struct regmap *regmap; + struct i2c_client *i2c; + struct gpio_desc *reset_gpiod; /* Reset & Power down GPIO */ + int slots; + int slot_width; +}; + +/* ak5558 register cache & default register settings */ +static const struct reg_default ak5558_reg[] = { + { 0x0, 0xFF }, /* 0x00 AK5558_00_POWER_MANAGEMENT1 */ + { 0x1, 0x01 }, /* 0x01 AK5558_01_POWER_MANAGEMENT2 */ + { 0x2, 0x01 }, /* 0x02 AK5558_02_CONTROL1 */ + { 0x3, 0x00 }, /* 0x03 AK5558_03_CONTROL2 */ + { 0x4, 0x00 }, /* 0x04 AK5558_04_CONTROL3 */ + { 0x5, 0x00 } /* 0x05 AK5558_05_DSD */ +}; + +static const char * const mono_texts[] = { + "8 Slot", "2 Slot", "4 Slot", "1 Slot", +}; + +static const struct soc_enum ak5558_mono_enum[] = { + SOC_ENUM_SINGLE(AK5558_01_POWER_MANAGEMENT2, 1, + ARRAY_SIZE(mono_texts), mono_texts), +}; + +static const char * const digfil_texts[] = { + "Sharp Roll-Off", "Show Roll-Off", + "Short Delay Sharp Roll-Off", "Short Delay Show Roll-Off", +}; + +static const struct soc_enum ak5558_adcset_enum[] = { + SOC_ENUM_SINGLE(AK5558_04_CONTROL3, 0, + ARRAY_SIZE(digfil_texts), digfil_texts), +}; + +static const struct snd_kcontrol_new ak5558_snd_controls[] = { + SOC_ENUM("AK5558 Monaural Mode", ak5558_mono_enum[0]), + SOC_ENUM("AK5558 Digital Filter", ak5558_adcset_enum[0]), +}; + +static const struct snd_soc_dapm_widget ak5558_dapm_widgets[] = { + /* Analog Input */ + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + SND_SOC_DAPM_INPUT("AIN3"), + SND_SOC_DAPM_INPUT("AIN4"), + SND_SOC_DAPM_INPUT("AIN5"), + SND_SOC_DAPM_INPUT("AIN6"), + SND_SOC_DAPM_INPUT("AIN7"), + SND_SOC_DAPM_INPUT("AIN8"), + + SND_SOC_DAPM_ADC("ADC Ch1", NULL, AK5558_00_POWER_MANAGEMENT1, 0, 0), + SND_SOC_DAPM_ADC("ADC Ch2", NULL, AK5558_00_POWER_MANAGEMENT1, 1, 0), + SND_SOC_DAPM_ADC("ADC Ch3", NULL, AK5558_00_POWER_MANAGEMENT1, 2, 0), + SND_SOC_DAPM_ADC("ADC Ch4", NULL, AK5558_00_POWER_MANAGEMENT1, 3, 0), + SND_SOC_DAPM_ADC("ADC Ch5", NULL, AK5558_00_POWER_MANAGEMENT1, 4, 0), + SND_SOC_DAPM_ADC("ADC Ch6", NULL, AK5558_00_POWER_MANAGEMENT1, 5, 0), + SND_SOC_DAPM_ADC("ADC Ch7", NULL, AK5558_00_POWER_MANAGEMENT1, 6, 0), + SND_SOC_DAPM_ADC("ADC Ch8", NULL, AK5558_00_POWER_MANAGEMENT1, 7, 0), + + SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route ak5558_intercon[] = { + {"ADC Ch1", NULL, "AIN1"}, + {"SDTO", NULL, "ADC Ch1"}, + + {"ADC Ch2", NULL, "AIN2"}, + {"SDTO", NULL, "ADC Ch2"}, + + {"ADC Ch3", NULL, "AIN3"}, + {"SDTO", NULL, "ADC Ch3"}, + + {"ADC Ch4", NULL, "AIN4"}, + {"SDTO", NULL, "ADC Ch4"}, + + {"ADC Ch5", NULL, "AIN5"}, + {"SDTO", NULL, "ADC Ch5"}, + + {"ADC Ch6", NULL, "AIN6"}, + {"SDTO", NULL, "ADC Ch6"}, + + {"ADC Ch7", NULL, "AIN7"}, + {"SDTO", NULL, "ADC Ch7"}, + + {"ADC Ch8", NULL, "AIN8"}, + {"SDTO", NULL, "ADC Ch8"}, +}; + +static int ak5558_set_mcki(struct snd_soc_codec *codec) +{ + return snd_soc_update_bits(codec, AK5558_02_CONTROL1, AK5558_CKS, + AK5558_CKS_AUTO); +} + +static int ak5558_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + u8 bits; + int pcm_width = max(params_physical_width(params), ak5558->slot_width); + + /* set master/slave audio interface */ + bits = snd_soc_read(codec, AK5558_02_CONTROL1); + bits &= ~AK5558_BITS; + + switch (pcm_width) { + case 16: + bits |= AK5558_DIF_24BIT_MODE; + break; + case 32: + bits |= AK5558_DIF_32BIT_MODE; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, AK5558_02_CONTROL1, AK5558_BITS, bits); + + return 0; +} + +static int ak5558_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + u8 format; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + case SND_SOC_DAIFMT_CBM_CFM: + break; + case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBM_CFS: + default: + dev_err(dai->dev, "Clock mode unsupported"); + return -EINVAL; + } + + /* set master/slave audio interface */ + format = snd_soc_read(codec, AK5558_02_CONTROL1); + format &= ~AK5558_DIF; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + format |= AK5558_DIF_I2S_MODE; + break; + case SND_SOC_DAIFMT_LEFT_J: + format |= AK5558_DIF_MSB_MODE; + break; + case SND_SOC_DAIFMT_DSP_B: + format |= AK5558_DIF_MSB_MODE; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, AK5558_02_CONTROL1, AK5558_DIF, format); + + return 0; +} + +static int ak5558_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, + int slot_width) +{ + struct snd_soc_codec *codec = dai->codec; + struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + int tdm_mode; + + ak5558->slots = slots; + ak5558->slot_width = slot_width; + + switch (slots * slot_width) { + case 128: + tdm_mode = AK5558_MODE_TDM128; + break; + case 256: + tdm_mode = AK5558_MODE_TDM256; + break; + case 512: + tdm_mode = AK5558_MODE_TDM512; + break; + default: + tdm_mode = AK5558_MODE_NORMAL; + break; + } + + snd_soc_update_bits(codec, AK5558_03_CONTROL2, AK5558_MODE_BITS, + tdm_mode); + return 0; +} + +#define AK5558_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static const unsigned int ak5558_rates[] = { + 8000, 11025, 16000, 22050, + 32000, 44100, 48000, 88200, + 96000, 176400, 192000, 352800, + 384000, 705600, 768000, 1411200, + 2822400, +}; + +static const struct snd_pcm_hw_constraint_list ak5558_rate_constraints = { + .count = ARRAY_SIZE(ak5558_rates), + .list = ak5558_rates, +}; + +static int ak5558_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &ak5558_rate_constraints); +} + +static struct snd_soc_dai_ops ak5558_dai_ops = { + .startup = ak5558_startup, + .hw_params = ak5558_hw_params, + + .set_fmt = ak5558_set_dai_fmt, + .set_tdm_slot = ak5558_set_tdm_slot, +}; + +static struct snd_soc_dai_driver ak5558_dai = { + .name = "ak5558-aif", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = AK5558_FORMATS, + }, + .ops = &ak5558_dai_ops, +}; + +static void ak5558_power_off(struct ak5558_priv *ak5558) +{ + if (!ak5558->reset_gpiod) + return; + + gpiod_set_value_cansleep(ak5558->reset_gpiod, 0); + usleep_range(1000, 2000); +} + +static void ak5558_power_on(struct ak5558_priv *ak5558) +{ + if (!ak5558->reset_gpiod) + return; + + gpiod_set_value_cansleep(ak5558->reset_gpiod, 1); + usleep_range(1000, 2000); +} + +static int ak5558_probe(struct snd_soc_codec *codec) +{ + struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + + ak5558_power_on(ak5558); + return ak5558_set_mcki(codec); +} + +static int ak5558_remove(struct snd_soc_codec *codec) +{ + struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + + ak5558_power_off(ak5558); + + return 0; +} + +static int __maybe_unused ak5558_runtime_suspend(struct device *dev) +{ + struct ak5558_priv *ak5558 = dev_get_drvdata(dev); + + regcache_cache_only(ak5558->regmap, true); + ak5558_power_off(ak5558); + + return 0; +} + +static int __maybe_unused ak5558_runtime_resume(struct device *dev) +{ + struct ak5558_priv *ak5558 = dev_get_drvdata(dev); + + ak5558_power_off(ak5558); + ak5558_power_on(ak5558); + + regcache_cache_only(ak5558->regmap, false); + regcache_mark_dirty(ak5558->regmap); + + return regcache_sync(ak5558->regmap); +} + +const struct dev_pm_ops ak5558_pm = { + SET_RUNTIME_PM_OPS(ak5558_runtime_suspend, ak5558_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +struct snd_soc_codec_driver soc_codec_dev_ak5558 = { + .probe = ak5558_probe, + .remove = ak5558_remove, + + .component_driver = { + .controls = ak5558_snd_controls, + .num_controls = ARRAY_SIZE(ak5558_snd_controls), + .dapm_widgets = ak5558_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak5558_dapm_widgets), + .dapm_routes = ak5558_intercon, + .num_dapm_routes = ARRAY_SIZE(ak5558_intercon), + }, +}; + +static const struct regmap_config ak5558_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = AK5558_05_DSD, + .reg_defaults = ak5558_reg, + .num_reg_defaults = ARRAY_SIZE(ak5558_reg), + .cache_type = REGCACHE_RBTREE, +}; + +static int ak5558_i2c_probe(struct i2c_client *i2c) +{ + struct ak5558_priv *ak5558; + int ret = 0; + + ak5558 = devm_kzalloc(&i2c->dev, sizeof(*ak5558), GFP_KERNEL); + if (!ak5558) + return -ENOMEM; + + ak5558->regmap = devm_regmap_init_i2c(i2c, &ak5558_regmap); + if (IS_ERR(ak5558->regmap)) + return PTR_ERR(ak5558->regmap); + + i2c_set_clientdata(i2c, ak5558); + ak5558->i2c = i2c; + + ak5558->reset_gpiod = devm_gpiod_get_optional(&i2c->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(ak5558->reset_gpiod)) + return PTR_ERR(ak5558->reset_gpiod); + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak5558, + &ak5558_dai, 1); + if (ret) + return ret; + + pm_runtime_enable(&i2c->dev); + + return 0; +} + +static int ak5558_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + pm_runtime_disable(&i2c->dev); + + return 0; +} + +static const struct of_device_id ak5558_i2c_dt_ids[] = { + { .compatible = "asahi-kasei,ak5558"}, + { } +}; + +static struct i2c_driver ak5558_i2c_driver = { + .driver = { + .name = "ak5558", + .of_match_table = of_match_ptr(ak5558_i2c_dt_ids), + .pm = &ak5558_pm, + }, + .probe_new = ak5558_i2c_probe, + .remove = ak5558_i2c_remove, +}; + +module_i2c_driver(ak5558_i2c_driver); + +MODULE_AUTHOR("Junichi Wakasugi "); +MODULE_AUTHOR("Mihai Serban "); +MODULE_DESCRIPTION("ASoC AK5558 ADC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/ak5558.h b/sound/soc/codecs/ak5558.h new file mode 100644 index 000000000000..7c9e37374f39 --- /dev/null +++ b/sound/soc/codecs/ak5558.h @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Audio driver header for AK5558 + * + * Copyright (C) 2016 Asahi Kasei Microdevices Corporation + * Copyright 2018 NXP + */ + +#ifndef _AK5558_H +#define _AK5558_H + +#define AK5558_00_POWER_MANAGEMENT1 0x00 +#define AK5558_01_POWER_MANAGEMENT2 0x01 +#define AK5558_02_CONTROL1 0x02 +#define AK5558_03_CONTROL2 0x03 +#define AK5558_04_CONTROL3 0x04 +#define AK5558_05_DSD 0x05 + +/* AK5558_02_CONTROL1 fields */ +#define AK5558_DIF GENMASK(1, 1) +#define AK5558_DIF_MSB_MODE (0 << 1) +#define AK5558_DIF_I2S_MODE (1 << 1) + +#define AK5558_BITS GENMASK(2, 2) +#define AK5558_DIF_24BIT_MODE (0 << 2) +#define AK5558_DIF_32BIT_MODE (1 << 2) + +#define AK5558_CKS GENMASK(6, 3) +#define AK5558_CKS_128FS_192KHZ (0 << 3) +#define AK5558_CKS_192FS_192KHZ (1 << 3) +#define AK5558_CKS_256FS_48KHZ (2 << 3) +#define AK5558_CKS_256FS_96KHZ (3 << 3) +#define AK5558_CKS_384FS_96KHZ (4 << 3) +#define AK5558_CKS_384FS_48KHZ (5 << 3) +#define AK5558_CKS_512FS_48KHZ (6 << 3) +#define AK5558_CKS_768FS_48KHZ (7 << 3) +#define AK5558_CKS_64FS_384KHZ (8 << 3) +#define AK5558_CKS_32FS_768KHZ (9 << 3) +#define AK5558_CKS_96FS_384KHZ (10 << 3) +#define AK5558_CKS_48FS_768KHZ (11 << 3) +#define AK5558_CKS_64FS_768KHZ (12 << 3) +#define AK5558_CKS_1024FS_16KHZ (13 << 3) +#define AK5558_CKS_AUTO (15 << 3) + +/* AK5558_03_CONTROL2 fields */ +#define AK5558_MODE_BITS GENMASK(6, 5) +#define AK5558_MODE_NORMAL (0 << 5) +#define AK5558_MODE_TDM128 (1 << 5) +#define AK5558_MODE_TDM256 (2 << 5) +#define AK5558_MODE_TDM512 (3 << 5) + +#endif From af0424e44c180d66c2ddfb0a99c52382de8f69f8 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 13 Feb 2018 16:29:34 +0200 Subject: [PATCH 05/15] ASoC: ak5558: Add bindings for AK5558 ADC Document the bindings for AK5558 ADC. Reviewed-by: Rob Herring Signed-off-by: Daniel Baluta Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/ak5558.txt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/ak5558.txt diff --git a/Documentation/devicetree/bindings/sound/ak5558.txt b/Documentation/devicetree/bindings/sound/ak5558.txt new file mode 100644 index 000000000000..7d67ca6ced80 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ak5558.txt @@ -0,0 +1,22 @@ +AK5558 8 channel differential 32-bit delta-sigma ADC + +This device supports I2C mode only. + +Required properties: + +- compatible : "asahi-kasei,ak5558" +- reg : The I2C address of the device. + +Optional properties: + +- reset-gpios: A GPIO specifier for the power down & reset pin. + +Example: + +&i2c { + ak5558: adc@10 { + compatible = "asahi-kasei,ak5558"; + reg = <0x10>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; +}; From 608a300fc1f0e088446cbef8e13ded686c5172b6 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Fri, 16 Feb 2018 13:11:13 +0530 Subject: [PATCH 06/15] ASoC: AMD: Add machine driver for ST DA7219 MAX98357 The driver is used for AMD board using DA7219 and MAX98357 codec. TEST=Build, apply grunt_mixer_settings: iotools mmio_write32 0xfed80e40 0x040c40c0 iotools mmio_write32 0xfed80e28 0x10000 iotools mmio_write8 0xfed816de 0xc0 aplay -D plughw:0,0 ./sample_48000.wav -vv aplay -D plughw:0,0 ./sample_44100.wav -vv Signed-off-by: Akshu Agrawal Signed-off-by: Daniel Kurtz Reviewed-by: Alex Deucher Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 9 + sound/soc/amd/Makefile | 2 + sound/soc/amd/acp-da7219-max98357a.c | 246 +++++++++++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 sound/soc/amd/acp-da7219-max98357a.c diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index d5838402f667..6cbf9cf4d1a4 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -3,6 +3,15 @@ config SND_SOC_AMD_ACP help This option enables ACP DMA support on AMD platform. +config SND_SOC_AMD_CZ_DA7219MX98357_MACH + tristate "AMD CZ support for DA7219 and MAX9835" + select SND_SOC_DA7219 + select SND_SOC_MAX98357A + select SND_SOC_ADAU7002 + depends on SND_SOC_AMD_ACP && I2C + help + This option enables machine driver for DA7219 and MAX9835. + config SND_SOC_AMD_CZ_RT5645_MACH tristate "AMD CZ support for RT5645" select SND_SOC_RT5645 diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile index f07fd2e2870a..79b0622fa5d3 100644 --- a/sound/soc/amd/Makefile +++ b/sound/soc/amd/Makefile @@ -1,5 +1,7 @@ acp_audio_dma-objs := acp-pcm-dma.o +snd-soc-acp-da7219mx98357-mach-objs := acp-da7219-max98357a.o snd-soc-acp-rt5645-mach-objs := acp-rt5645.o obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o +obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mach.o obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c new file mode 100644 index 000000000000..e51a878890ce --- /dev/null +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -0,0 +1,246 @@ +/* + * Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec + * + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../codecs/da7219.h" +#include "../codecs/da7219-aad.h" + +#define CZ_PLAT_CLK 24000000 +#define MCLK_RATE 24576000 +#define DUAL_CHANNEL 2 + +static struct snd_soc_jack cz_jack; + +static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card = rtd->card; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, + CZ_PLAT_CLK, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL, + CZ_PLAT_CLK, MCLK_RATE); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec pll: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(card, "Headset Jack", + SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &cz_jack, NULL, 0); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + da7219_aad_jack_det(codec, &cz_jack); + + return 0; +} + +static const unsigned int channels[] = { + DUAL_CHANNEL, +}; + +static const unsigned int rates[] = { + 48000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int cz_fe_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + return 0; +} + +static struct snd_soc_ops cz_da7219_cap_ops = { + .startup = cz_fe_startup, +}; + +static struct snd_soc_dai_link cz_dai_7219_98357[] = { + { + .name = "amd-da7219-play", + .stream_name = "Playback", + .platform_name = "acp_audio_dma.0.auto", + .cpu_dai_name = "designware-i2s.3.auto", + .codec_dai_name = "da7219-hifi", + .codec_name = "i2c-DLGS7219:00", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .init = cz_da7219_init, + .dpcm_playback = 1, + }, + { + .name = "amd-da7219-cap", + .stream_name = "Capture", + .platform_name = "acp_audio_dma.0.auto", + .cpu_dai_name = "designware-i2s.4.auto", + .codec_dai_name = "da7219-hifi", + .codec_name = "i2c-DLGS7219:00", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_capture = 1, + .ops = &cz_da7219_cap_ops, + }, + { + .name = "amd-max98357-play", + .stream_name = "HiFi Playback", + .platform_name = "acp_audio_dma.0.auto", + .cpu_dai_name = "designware-i2s.1.auto", + .codec_dai_name = "HiFi", + .codec_name = "MX98357A:00", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_playback = 1, + }, + { + .name = "dmic", + .stream_name = "DMIC Capture", + .platform_name = "acp_audio_dma.0.auto", + .cpu_dai_name = "designware-i2s.2.auto", + .codec_dai_name = "adau7002-hifi", + .codec_name = "ADAU7002:00", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_capture = 1, + }, +}; + +static const struct snd_soc_dapm_widget cz_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), +}; + +static const struct snd_soc_dapm_route cz_audio_route[] = { + {"Headphones", NULL, "HPL"}, + {"Headphones", NULL, "HPR"}, + {"MIC", NULL, "Headset Mic"}, + {"Speakers", NULL, "Speaker"}, + {"PDM_DAT", NULL, "Int Mic"}, +}; + +static const struct snd_kcontrol_new cz_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), +}; + +static struct snd_soc_card cz_card = { + .name = "acpd7219m98357", + .owner = THIS_MODULE, + .dai_link = cz_dai_7219_98357, + .num_links = ARRAY_SIZE(cz_dai_7219_98357), + .dapm_widgets = cz_widgets, + .num_dapm_widgets = ARRAY_SIZE(cz_widgets), + .dapm_routes = cz_audio_route, + .num_dapm_routes = ARRAY_SIZE(cz_audio_route), + .controls = cz_mc_controls, + .num_controls = ARRAY_SIZE(cz_mc_controls), +}; + +static int cz_probe(struct platform_device *pdev) +{ + int ret; + struct snd_soc_card *card; + + card = &cz_card; + cz_card.dev = &pdev->dev; + platform_set_drvdata(pdev, card); + ret = devm_snd_soc_register_card(&pdev->dev, &cz_card); + if (ret) { + dev_err(&pdev->dev, + "devm_snd_soc_register_card(%s) failed: %d\n", + cz_card.name, ret); + return ret; + } + return 0; +} + +static const struct acpi_device_id cz_audio_acpi_match[] = { + { "AMD7219", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); + +static struct platform_driver cz_pcm_driver = { + .driver = { + .name = "cz-da7219-max98357a", + .acpi_match_table = ACPI_PTR(cz_audio_acpi_match), + .pm = &snd_soc_pm_ops, + }, + .probe = cz_probe, +}; + +module_platform_driver(cz_pcm_driver); + +MODULE_AUTHOR("akshu.agrawal@amd.com"); +MODULE_DESCRIPTION("DA7219 & MAX98357A audio support"); +MODULE_LICENSE("GPL v2"); From 9a60cde2dd63e10b421e87e1397641304dd1ef13 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Feb 2018 04:16:06 +0000 Subject: [PATCH 07/15] ASoC: amd: acp-da7219-max98357: replace codec to component Now we can replace Codec to Component. Let's do it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index e51a878890ce..bbe0f103e6a8 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -47,8 +47,8 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) { int ret; struct snd_soc_card *card = rtd->card; - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_component *component = codec_dai->component; dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); @@ -76,7 +76,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) return ret; } - da7219_aad_jack_det(codec, &cz_jack); + da7219_aad_jack_det(component, &cz_jack); return 0; } From 3f15aa198fb88a6a0db8c7ba136637d566effb55 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Feb 2018 04:17:16 +0000 Subject: [PATCH 08/15] ASoC: ak5558: replace codec to component Now we can replace Codec to Component. Let's do it. Note: xxx_codec_xxx() -> xxx_component_xxx() .idle_bias_off = 0 -> .idle_bias_on = 1 .ignore_pmdown_time = 0 -> .use_pmdown_time = 1 - -> .endianness = 1 - -> .non_legacy_dai_naming = 1 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 67 +++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 225173ff4efa..f2248315677e 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -25,7 +25,7 @@ /* AK5558 Codec Private Data */ struct ak5558_priv { - struct snd_soc_codec codec; + struct snd_soc_component component; struct regmap *regmap; struct i2c_client *i2c; struct gpio_desc *reset_gpiod; /* Reset & Power down GPIO */ @@ -116,9 +116,9 @@ static const struct snd_soc_dapm_route ak5558_intercon[] = { {"SDTO", NULL, "ADC Ch8"}, }; -static int ak5558_set_mcki(struct snd_soc_codec *codec) +static int ak5558_set_mcki(struct snd_soc_component *component) { - return snd_soc_update_bits(codec, AK5558_02_CONTROL1, AK5558_CKS, + return snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_CKS, AK5558_CKS_AUTO); } @@ -126,13 +126,13 @@ static int ak5558_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_codec *codec = dai->codec; - struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); u8 bits; int pcm_width = max(params_physical_width(params), ak5558->slot_width); /* set master/slave audio interface */ - bits = snd_soc_read(codec, AK5558_02_CONTROL1); + bits = snd_soc_component_read32(component, AK5558_02_CONTROL1); bits &= ~AK5558_BITS; switch (pcm_width) { @@ -146,14 +146,14 @@ static int ak5558_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_soc_update_bits(codec, AK5558_02_CONTROL1, AK5558_BITS, bits); + snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_BITS, bits); return 0; } static int ak5558_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; u8 format; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -169,7 +169,7 @@ static int ak5558_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } /* set master/slave audio interface */ - format = snd_soc_read(codec, AK5558_02_CONTROL1); + format = snd_soc_component_read32(component, AK5558_02_CONTROL1); format &= ~AK5558_DIF; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -186,7 +186,7 @@ static int ak5558_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } - snd_soc_update_bits(codec, AK5558_02_CONTROL1, AK5558_DIF, format); + snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_DIF, format); return 0; } @@ -195,8 +195,8 @@ static int ak5558_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { - struct snd_soc_codec *codec = dai->codec; - struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); int tdm_mode; ak5558->slots = slots; @@ -217,7 +217,7 @@ static int ak5558_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, break; } - snd_soc_update_bits(codec, AK5558_03_CONTROL2, AK5558_MODE_BITS, + snd_soc_component_update_bits(component, AK5558_03_CONTROL2, AK5558_MODE_BITS, tdm_mode); return 0; } @@ -285,21 +285,19 @@ static void ak5558_power_on(struct ak5558_priv *ak5558) usleep_range(1000, 2000); } -static int ak5558_probe(struct snd_soc_codec *codec) +static int ak5558_probe(struct snd_soc_component *component) { - struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); ak5558_power_on(ak5558); - return ak5558_set_mcki(codec); + return ak5558_set_mcki(component); } -static int ak5558_remove(struct snd_soc_codec *codec) +static void ak5558_remove(struct snd_soc_component *component) { - struct ak5558_priv *ak5558 = snd_soc_codec_get_drvdata(codec); + struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); ak5558_power_off(ak5558); - - return 0; } static int __maybe_unused ak5558_runtime_suspend(struct device *dev) @@ -331,18 +329,19 @@ const struct dev_pm_ops ak5558_pm = { pm_runtime_force_resume) }; -struct snd_soc_codec_driver soc_codec_dev_ak5558 = { - .probe = ak5558_probe, - .remove = ak5558_remove, - - .component_driver = { - .controls = ak5558_snd_controls, - .num_controls = ARRAY_SIZE(ak5558_snd_controls), - .dapm_widgets = ak5558_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak5558_dapm_widgets), - .dapm_routes = ak5558_intercon, - .num_dapm_routes = ARRAY_SIZE(ak5558_intercon), - }, +struct snd_soc_component_driver soc_codec_dev_ak5558 = { + .probe = ak5558_probe, + .remove = ak5558_remove, + .controls = ak5558_snd_controls, + .num_controls = ARRAY_SIZE(ak5558_snd_controls), + .dapm_widgets = ak5558_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak5558_dapm_widgets), + .dapm_routes = ak5558_intercon, + .num_dapm_routes = ARRAY_SIZE(ak5558_intercon), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, }; static const struct regmap_config ak5558_regmap = { @@ -376,7 +375,8 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) if (IS_ERR(ak5558->reset_gpiod)) return PTR_ERR(ak5558->reset_gpiod); - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak5558, + ret = devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_ak5558, &ak5558_dai, 1); if (ret) return ret; @@ -388,7 +388,6 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) static int ak5558_i2c_remove(struct i2c_client *i2c) { - snd_soc_unregister_codec(&i2c->dev); pm_runtime_disable(&i2c->dev); return 0; From e21358c43b426301aefef27c498eee2e2525b3ce Mon Sep 17 00:00:00 2001 From: "Mukunda, Vijendar" Date: Fri, 16 Feb 2018 13:03:46 +0530 Subject: [PATCH 09/15] ASoC: amd: renaming pcm substream names and bytescount params With in ACP, There are three I2S controllers can be configured. (I2S SP ,I2S MICSP and I2S BT).These controllers can support both playback/capture scenarios. Default enabled i2s controller instance is i2s sp instance. Renamed stream names and bytescount params as i2ssp. These changes required to distinguish with other I2S controller instance pcm substreams and bytescount params. Signed-off-by: Vijendar Mukunda Reviewed-by: Alex Deucher Signed-off-by: Mark Brown --- sound/soc/amd/acp-pcm-dma.c | 49 +++++++++++++++++++------------------ sound/soc/amd/acp.h | 8 +++--- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index c33a512283a4..3c39a0d8125d 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -662,7 +662,7 @@ static irqreturn_t dma_irq_handler(int irq, void *arg) 1, 0); acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false); - snd_pcm_period_elapsed(irq_data->play_stream); + snd_pcm_period_elapsed(irq_data->play_i2ssp_stream); acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16, acp_mmio, mmACP_EXTERNAL_INTR_STAT); @@ -685,7 +685,7 @@ static irqreturn_t dma_irq_handler(int irq, void *arg) if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) { valid_irq = true; - snd_pcm_period_elapsed(irq_data->capture_stream); + snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream); acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16, acp_mmio, mmACP_EXTERNAL_INTR_STAT); } @@ -743,11 +743,11 @@ static int acp_dma_open(struct snd_pcm_substream *substream) * This enablement is not required for another stream, if current * stream is not closed */ - if (!intr_data->play_stream && !intr_data->capture_stream) + if (!intr_data->play_i2ssp_stream && !intr_data->capture_i2ssp_stream) acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - intr_data->play_stream = substream; + intr_data->play_i2ssp_stream = substream; /* For Stoney, Memory gating is disabled,i.e SRAM Banks * won't be turned off. The default state for SRAM banks is ON. * Setting SRAM bank state code skipped for STONEY platform. @@ -758,7 +758,7 @@ static int acp_dma_open(struct snd_pcm_substream *substream) bank, true); } } else { - intr_data->capture_stream = substream; + intr_data->capture_i2ssp_stream = substream; if (intr_data->asic_type != CHIP_STONEY) { for (bank = 5; bank <= 8; bank++) acp_set_sram_bank_state(intr_data->acp_mmio, @@ -857,11 +857,11 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) bytescount = acp_get_byte_count(rtd->acp_mmio, substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (bytescount > rtd->renderbytescount) - bytescount = bytescount - rtd->renderbytescount; + if (bytescount > rtd->i2ssp_renderbytescount) + bytescount = bytescount - rtd->i2ssp_renderbytescount; } else { - if (bytescount > rtd->capturebytescount) - bytescount = bytescount - rtd->capturebytescount; + if (bytescount > rtd->i2ssp_capturebytescount) + bytescount = bytescount - rtd->i2ssp_capturebytescount; } pos = do_div(bytescount, buffersize); return bytes_to_frames(runtime, pos); @@ -917,8 +917,8 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) bytescount = acp_get_byte_count(rtd->acp_mmio, substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (rtd->renderbytescount == 0) - rtd->renderbytescount = bytescount; + if (rtd->i2ssp_renderbytescount == 0) + rtd->i2ssp_renderbytescount = bytescount; acp_dma_start(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM, false); while (acp_reg_read(rtd->acp_mmio, mmACP_DMA_CH_STS) & @@ -935,8 +935,8 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) ACP_TO_I2S_DMA_CH_NUM, true); } else { - if (rtd->capturebytescount == 0) - rtd->capturebytescount = bytescount; + if (rtd->i2ssp_capturebytescount == 0) + rtd->i2ssp_capturebytescount = bytescount; acp_dma_start(rtd->acp_mmio, I2S_TO_ACP_DMA_CH_NUM, true); } @@ -953,11 +953,11 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = acp_dma_stop(rtd->acp_mmio, ACP_TO_I2S_DMA_CH_NUM); - rtd->renderbytescount = 0; + rtd->i2ssp_renderbytescount = 0; } else { ret = acp_dma_stop(rtd->acp_mmio, I2S_TO_ACP_DMA_CH_NUM); - rtd->capturebytescount = 0; + rtd->i2ssp_capturebytescount = 0; } break; default: @@ -1003,7 +1003,7 @@ static int acp_dma_close(struct snd_pcm_substream *substream) kfree(rtd); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - adata->play_stream = NULL; + adata->play_i2ssp_stream = NULL; /* For Stoney, Memory gating is disabled,i.e SRAM Banks * won't be turned off. The default state for SRAM banks is ON. * Setting SRAM bank state code skipped for STONEY platform. @@ -1015,7 +1015,7 @@ static int acp_dma_close(struct snd_pcm_substream *substream) false); } } else { - adata->capture_stream = NULL; + adata->capture_i2ssp_stream = NULL; if (adata->asic_type != CHIP_STONEY) { for (bank = 5; bank <= 8; bank++) acp_set_sram_bank_state(adata->acp_mmio, bank, @@ -1026,7 +1026,7 @@ static int acp_dma_close(struct snd_pcm_substream *substream) /* Disable ACP irq, when the current stream is being closed and * another stream is also not active. */ - if (!adata->play_stream && !adata->capture_stream) + if (!adata->play_i2ssp_stream && !adata->capture_i2ssp_stream) acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); return 0; @@ -1076,8 +1076,9 @@ static int acp_audio_probe(struct platform_device *pdev) * and device doesn't generate any interrupts. */ - audio_drv_data->play_stream = NULL; - audio_drv_data->capture_stream = NULL; + audio_drv_data->play_i2ssp_stream = NULL; + audio_drv_data->capture_i2ssp_stream = NULL; + audio_drv_data->asic_type = *pdata; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -1141,7 +1142,7 @@ static int acp_pcm_resume(struct device *dev) return status; } - if (adata->play_stream && adata->play_stream->runtime) { + if (adata->play_i2ssp_stream && adata->play_i2ssp_stream->runtime) { /* For Stoney, Memory gating is disabled,i.e SRAM Banks * won't be turned off. The default state for SRAM banks is ON. * Setting SRAM bank state code skipped for STONEY platform. @@ -1152,17 +1153,17 @@ static int acp_pcm_resume(struct device *dev) true); } config_acp_dma(adata->acp_mmio, - adata->play_stream->runtime->private_data, + adata->play_i2ssp_stream->runtime->private_data, adata->asic_type); } - if (adata->capture_stream && adata->capture_stream->runtime) { + if (adata->capture_i2ssp_stream && adata->capture_i2ssp_stream->runtime) { if (adata->asic_type != CHIP_STONEY) { for (bank = 5; bank <= 8; bank++) acp_set_sram_bank_state(adata->acp_mmio, bank, true); } config_acp_dma(adata->acp_mmio, - adata->capture_stream->runtime->private_data, + adata->capture_i2ssp_stream->runtime->private_data, adata->asic_type); } acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h index ecb458935d1e..27803b26fc35 100644 --- a/sound/soc/amd/acp.h +++ b/sound/soc/amd/acp.h @@ -84,14 +84,14 @@ struct audio_substream_data { u16 num_of_pages; u16 direction; uint64_t size; - u64 renderbytescount; - u64 capturebytescount; + u64 i2ssp_renderbytescount; + u64 i2ssp_capturebytescount; void __iomem *acp_mmio; }; struct audio_drv_data { - struct snd_pcm_substream *play_stream; - struct snd_pcm_substream *capture_stream; + struct snd_pcm_substream *play_i2ssp_stream; + struct snd_pcm_substream *capture_i2ssp_stream; void __iomem *acp_mmio; u32 asic_type; }; From 4376a86caa5f7011969801f41c4c2230c1685c23 Mon Sep 17 00:00:00 2001 From: "Mukunda, Vijendar" Date: Fri, 16 Feb 2018 13:03:47 +0530 Subject: [PATCH 10/15] ASoC: amd: Coding style changes for acp dma driver Removed hardcoding in dma descriptor programming api's. These changes are required to extend the logic to support dma descriptor programming for multiple i2s controller instances. Signed-off-by: Vijendar Mukunda Reviewed-by: Alex Deucher Signed-off-by: Mark Brown --- sound/soc/amd/acp-pcm-dma.c | 124 ++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 3c39a0d8125d..935c8fd42a7a 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -182,19 +182,18 @@ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio, * system memory <-> ACP SRAM */ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio, - u32 size, int direction, - u32 pte_offset, u32 asic_type) + u32 size, int direction, u32 pte_offset, + u16 ch, u32 sram_bank, + u16 dma_dscr_idx, u32 asic_type) { u16 i; - u16 dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12; acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL]; for (i = 0; i < NUM_DSCRS_PER_CHANNEL; i++) { dmadscr[i].xfer_val = 0; if (direction == SNDRV_PCM_STREAM_PLAYBACK) { - dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12 + i; - dmadscr[i].dest = ACP_SHARED_RAM_BANK_1_ADDRESS - + (i * (size/2)); + dma_dscr_idx = dma_dscr_idx + i; + dmadscr[i].dest = sram_bank + (i * (size/2)); dmadscr[i].src = ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS + (pte_offset * SZ_4K) + (i * (size/2)); switch (asic_type) { @@ -209,25 +208,19 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio, (size / 2); } } else { - dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14 + i; + dma_dscr_idx = dma_dscr_idx + i; + dmadscr[i].src = sram_bank + (i * (size/2)); + dmadscr[i].dest = + ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS + + (pte_offset * SZ_4K) + (i * (size/2)); switch (asic_type) { case CHIP_STONEY: - dmadscr[i].src = ACP_SHARED_RAM_BANK_3_ADDRESS + - (i * (size/2)); - dmadscr[i].dest = - ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS + - (pte_offset * SZ_4K) + (i * (size/2)); dmadscr[i].xfer_val |= BIT(22) | (ACP_DMA_ATTRIBUTES_SHARED_MEM_TO_DAGB_GARLIC << 16) | (size / 2); break; default: - dmadscr[i].src = ACP_SHARED_RAM_BANK_5_ADDRESS + - (i * (size/2)); - dmadscr[i].dest = - ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS + - (pte_offset * SZ_4K) + (i * (size/2)); dmadscr[i].xfer_val |= BIT(22) | (ACP_DMA_ATTRIBUTES_SHAREDMEM_TO_DAGB_ONION << 16) | @@ -237,72 +230,49 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio, config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, &dmadscr[i]); } - if (direction == SNDRV_PCM_STREAM_PLAYBACK) - config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM, - PLAYBACK_START_DMA_DESCR_CH12, - NUM_DSCRS_PER_CHANNEL, - ACP_DMA_PRIORITY_LEVEL_NORMAL); - else - config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, - CAPTURE_START_DMA_DESCR_CH14, - NUM_DSCRS_PER_CHANNEL, - ACP_DMA_PRIORITY_LEVEL_NORMAL); + config_acp_dma_channel(acp_mmio, ch, + dma_dscr_idx - 1, + NUM_DSCRS_PER_CHANNEL, + ACP_DMA_PRIORITY_LEVEL_NORMAL); } /* Initialize the DMA descriptor information for transfer between * ACP SRAM <-> I2S */ -static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, - u32 size, int direction, - u32 asic_type) +static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size, + int direction, u32 sram_bank, + u16 destination, u16 ch, + u16 dma_dscr_idx, u32 asic_type) { u16 i; - u16 dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13; acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL]; for (i = 0; i < NUM_DSCRS_PER_CHANNEL; i++) { dmadscr[i].xfer_val = 0; if (direction == SNDRV_PCM_STREAM_PLAYBACK) { - dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13 + i; - dmadscr[i].src = ACP_SHARED_RAM_BANK_1_ADDRESS + - (i * (size/2)); + dma_dscr_idx = dma_dscr_idx + i; + dmadscr[i].src = sram_bank + (i * (size/2)); /* dmadscr[i].dest is unused by hardware. */ dmadscr[i].dest = 0; - dmadscr[i].xfer_val |= BIT(22) | (TO_ACP_I2S_1 << 16) | + dmadscr[i].xfer_val |= BIT(22) | (destination << 16) | (size / 2); } else { - dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15 + i; + dma_dscr_idx = dma_dscr_idx + i; /* dmadscr[i].src is unused by hardware. */ dmadscr[i].src = 0; - switch (asic_type) { - case CHIP_STONEY: - dmadscr[i].dest = - ACP_SHARED_RAM_BANK_3_ADDRESS + - (i * (size / 2)); - break; - default: - dmadscr[i].dest = - ACP_SHARED_RAM_BANK_5_ADDRESS + - (i * (size / 2)); - } + dmadscr[i].dest = + sram_bank + (i * (size / 2)); dmadscr[i].xfer_val |= BIT(22) | - (FROM_ACP_I2S_1 << 16) | (size / 2); + (destination << 16) | (size / 2); } config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, &dmadscr[i]); } /* Configure the DMA channel with the above descriptore */ - if (direction == SNDRV_PCM_STREAM_PLAYBACK) - config_acp_dma_channel(acp_mmio, ACP_TO_I2S_DMA_CH_NUM, - PLAYBACK_START_DMA_DESCR_CH13, - NUM_DSCRS_PER_CHANNEL, - ACP_DMA_PRIORITY_LEVEL_NORMAL); - else - config_acp_dma_channel(acp_mmio, I2S_TO_ACP_DMA_CH_NUM, - CAPTURE_START_DMA_DESCR_CH15, - NUM_DSCRS_PER_CHANNEL, - ACP_DMA_PRIORITY_LEVEL_NORMAL); + config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1, + NUM_DSCRS_PER_CHANNEL, + ACP_DMA_PRIORITY_LEVEL_NORMAL); } /* Create page table entries in ACP SRAM for the allocated memory */ @@ -344,23 +314,51 @@ static void config_acp_dma(void __iomem *acp_mmio, struct audio_substream_data *audio_config, u32 asic_type) { - u32 pte_offset; + u32 pte_offset, sram_bank; + u16 ch1, ch2, destination, dma_dscr_idx; - if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK) + if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK) { pte_offset = ACP_PLAYBACK_PTE_OFFSET; - else + ch1 = SYSRAM_TO_ACP_CH_NUM; + ch2 = ACP_TO_I2S_DMA_CH_NUM; + sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS; + destination = TO_ACP_I2S_1; + + } else { pte_offset = ACP_CAPTURE_PTE_OFFSET; + ch1 = SYSRAM_TO_ACP_CH_NUM; + ch2 = ACP_TO_I2S_DMA_CH_NUM; + switch (asic_type) { + case CHIP_STONEY: + sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS; + break; + default: + sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS; + } + destination = FROM_ACP_I2S_1; + } acp_pte_config(acp_mmio, audio_config->pg, audio_config->num_of_pages, pte_offset); + if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK) + dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12; + else + dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14; /* Configure System memory <-> ACP SRAM DMA descriptors */ set_acp_sysmem_dma_descriptors(acp_mmio, audio_config->size, - audio_config->direction, pte_offset, asic_type); + audio_config->direction, pte_offset, + ch1, sram_bank, dma_dscr_idx, asic_type); + if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK) + dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13; + else + dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15; /* Configure ACP SRAM <-> I2S DMA descriptors */ set_acp_to_i2s_dma_descriptors(acp_mmio, audio_config->size, - audio_config->direction, asic_type); + audio_config->direction, sram_bank, + destination, ch2, dma_dscr_idx, + asic_type); } /* Start a given DMA channel transfer */ From af3acca3e35c01920fe476f730dca7345d0a48df Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 20 Feb 2018 14:53:10 +0200 Subject: [PATCH 11/15] ASoC: ak5558: Fix style for SPDX identifier Use // for .c and /* for .h files according to: Documentation/process/license-rules.rst file. Signed-off-by: Daniel Baluta Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 11 +++++------ sound/soc/codecs/ak5558.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index f2248315677e..f4ed5cc40661 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 -/* - * Audio driver for AK5558 ADC - * - * Copyright (C) 2015 Asahi Kasei Microdevices Corporation - * Copyright 2018 NXP - */ +// +// Audio driver for AK5558 ADC +// +// Copyright (C) 2015 Asahi Kasei Microdevices Corporation +// Copyright 2018 NXP #include #include diff --git a/sound/soc/codecs/ak5558.h b/sound/soc/codecs/ak5558.h index 7c9e37374f39..61059086f161 100644 --- a/sound/soc/codecs/ak5558.h +++ b/sound/soc/codecs/ak5558.h @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 -/* +/* SPDX-License-Identifier: GPL-2.0 + * * Audio driver header for AK5558 * * Copyright (C) 2016 Asahi Kasei Microdevices Corporation From 17aa9521d0c2856808c54ca1144d5c708e748928 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 9 Mar 2018 20:51:32 +0530 Subject: [PATCH 12/15] ASoC: amd: modifications in dma stop sequence As per design, non-circular dma also need to be stopped explicitly for both playback and capture scenarios. Signed-off-by: Vijendar Mukunda Signed-off-by: Mark Brown --- sound/soc/amd/acp-pcm-dma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 935c8fd42a7a..a1c6534455e6 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -949,12 +949,16 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) * completes : SYSRAM_TO_ACP_CH_NUM / ACP_TO_SYSRAM_CH_NUM */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = acp_dma_stop(rtd->acp_mmio, + SYSRAM_TO_ACP_CH_NUM); ret = acp_dma_stop(rtd->acp_mmio, ACP_TO_I2S_DMA_CH_NUM); rtd->i2ssp_renderbytescount = 0; } else { ret = acp_dma_stop(rtd->acp_mmio, I2S_TO_ACP_DMA_CH_NUM); + ret = acp_dma_stop(rtd->acp_mmio, + ACP_TO_SYSRAM_CH_NUM); rtd->i2ssp_capturebytescount = 0; } break; From f155181d23608acd3fb46d0d6b1507b68ffa436b Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Mon, 19 Mar 2018 11:07:41 +0530 Subject: [PATCH 13/15] ASoC: amd: Use single dai for da7219 playback and capture BT I2S is a bi-directional dai, we will use the same cpu dai for playback and capture. TEST=aplay -D hw:0,0 -vv arecord -D hw:0,0 -f dat -d 5 -vv Signed-off-by: Akshu Agrawal Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index bbe0f103e6a8..d07c2a1d5d9e 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -124,8 +124,8 @@ static struct snd_soc_ops cz_da7219_cap_ops = { static struct snd_soc_dai_link cz_dai_7219_98357[] = { { - .name = "amd-da7219-play", - .stream_name = "Playback", + .name = "amd-da7219-play-cap", + .stream_name = "Playback and Capture", .platform_name = "acp_audio_dma.0.auto", .cpu_dai_name = "designware-i2s.3.auto", .codec_dai_name = "da7219-hifi", @@ -134,16 +134,6 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { | SND_SOC_DAIFMT_CBM_CFM, .init = cz_da7219_init, .dpcm_playback = 1, - }, - { - .name = "amd-da7219-cap", - .stream_name = "Capture", - .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.4.auto", - .codec_dai_name = "da7219-hifi", - .codec_name = "i2c-DLGS7219:00", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, .dpcm_capture = 1, .ops = &cz_da7219_cap_ops, }, From c88d311533563e6dadc244930a36125d592f5ec5 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Mon, 19 Mar 2018 11:07:42 +0530 Subject: [PATCH 14/15] ASoC: amd: Enable da7219 master clock using common clock framework DA7219 is clock master for other codecs. DA7219 has exposed clock control by using common clock framework and same is used to enable and disable clock for all codecs in the system. TEST=aplay -D hw:0,0 -vv arecord -D hw:0,0 -f dat -d 5 -vv aplay -D hw:0,1 -vv Signed-off-by: Akshu Agrawal Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index d07c2a1d5d9e..99c6b5ce5c6c 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -42,11 +43,13 @@ #define DUAL_CHANNEL 2 static struct snd_soc_jack cz_jack; +struct clk *da7219_dai_clk; static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) { int ret; struct snd_soc_card *card = rtd->card; + struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_component *component = codec_dai->component; @@ -66,6 +69,8 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) return ret; } + da7219_dai_clk = clk_get(codec->dev, "da7219-dai-clks"); + ret = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | SND_JACK_BTN_0 | SND_JACK_BTN_1 | @@ -81,6 +86,28 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) return 0; } +static int cz_da7219_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + ret = clk_prepare_enable(da7219_dai_clk); + if (ret < 0) { + dev_err(rtd->dev, "can't enable master clock %d\n", ret); + return ret; + } + + return ret; +} + +static int cz_da7219_hw_free(struct snd_pcm_substream *substream) +{ + clk_disable_unprepare(da7219_dai_clk); + + return 0; +} + static const unsigned int channels[] = { DUAL_CHANNEL, }; @@ -119,9 +146,21 @@ static int cz_fe_startup(struct snd_pcm_substream *substream) } static struct snd_soc_ops cz_da7219_cap_ops = { + .hw_params = cz_da7219_hw_params, + .hw_free = cz_da7219_hw_free, .startup = cz_fe_startup, }; +static struct snd_soc_ops cz_max_play_ops = { + .hw_params = cz_da7219_hw_params, + .hw_free = cz_da7219_hw_free, +}; + +static struct snd_soc_ops cz_dmic_cap_ops = { + .hw_params = cz_da7219_hw_params, + .hw_free = cz_da7219_hw_free, +}; + static struct snd_soc_dai_link cz_dai_7219_98357[] = { { .name = "amd-da7219-play-cap", @@ -147,6 +186,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .dpcm_playback = 1, + .ops = &cz_max_play_ops, }, { .name = "dmic", @@ -158,6 +198,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .dpcm_capture = 1, + .ops = &cz_dmic_cap_ops, }, }; From 4c50e1e3e2c29899c0226f7ad56d7266e814f2b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 28 Mar 2018 01:48:07 +0000 Subject: [PATCH 15/15] ASoC: amd: don't use codec anymore commit c88d31153356 ("ASoC: amd: Enable da7219 master clock using common clock framework") is using rtd->codec, but codec is replaced to component. Let's use component Fixes: c88d31153356 ("ASoC: amd: Enable da7219 master clock using common clock framework") Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 99c6b5ce5c6c..b205c782e494 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -49,7 +49,6 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) { int ret; struct snd_soc_card *card = rtd->card; - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_component *component = codec_dai->component; @@ -69,7 +68,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) return ret; } - da7219_dai_clk = clk_get(codec->dev, "da7219-dai-clks"); + da7219_dai_clk = clk_get(component->dev, "da7219-dai-clks"); ret = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |