diff options
Diffstat (limited to 'sound/soc/codecs/wm5102.c')
| -rw-r--r-- | sound/soc/codecs/wm5102.c | 338 |
1 files changed, 181 insertions, 157 deletions
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 1fe358e6be61..b4d4137c05b4 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * wm5102.c -- WM5102 ALSA SoC Audio driver * * Copyright 2012 Wolfson Microelectronics plc * * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> @@ -28,12 +25,14 @@ #include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/registers.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "arizona.h" #include "wm5102.h" #include "wm_adsp.h" +#define DRV_NAME "wm5102-codec" + struct wm5102_priv { struct arizona_priv core; struct arizona_fll fll[2]; @@ -45,7 +44,7 @@ static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); -static const struct wm_adsp_region wm5102_dsp1_regions[] = { +static const struct cs_dsp_region wm5102_dsp1_regions[] = { { .type = WMFW_ADSP2_PM, .base = 0x100000 }, { .type = WMFW_ADSP2_ZM, .base = 0x180000 }, { .type = WMFW_ADSP2_XM, .base = 0x190000 }, @@ -581,8 +580,8 @@ static const struct reg_default wm5102_sysclk_revb_patch[] = { static int wm5102_sysclk_ev(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 arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct arizona *arizona = dev_get_drvdata(component->dev->parent); struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; @@ -618,10 +617,10 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, } static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); - struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct arizona *arizona = dev_get_drvdata(component->dev->parent); unsigned int v = 0; int ret; @@ -629,7 +628,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMU: ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v); if (ret != 0) { - dev_err(codec->dev, + dev_err(component->dev, "Failed to read SYSCLK state: %d\n", ret); return -EIO; } @@ -637,19 +636,21 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT; if (v >= 3) { - ret = arizona_dvfs_up(codec, ARIZONA_DVFS_ADSP1_RQ); + ret = arizona_dvfs_up(component, ARIZONA_DVFS_ADSP1_RQ); if (ret) { - dev_err(codec->dev, + dev_err(component->dev, "Failed to raise DVFS: %d\n", ret); return ret; } } + + wm_adsp2_set_dspclk(w, v); break; case SND_SOC_DAPM_POST_PMD: - ret = arizona_dvfs_down(codec, ARIZONA_DVFS_ADSP1_RQ); + ret = arizona_dvfs_down(component, ARIZONA_DVFS_ADSP1_RQ); if (ret) - dev_warn(codec->dev, + dev_warn(component->dev, "Failed to lower DVFS: %d\n", ret); break; @@ -657,14 +658,14 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, break; } - return wm_adsp2_early_event(w, kcontrol, event, v); + return wm_adsp_early_event(w, kcontrol, event); } static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct arizona *arizona = dev_get_drvdata(component->dev->parent); mutex_lock(&arizona->dac_comp_lock); put_unaligned_be16(arizona->dac_comp_coeff, @@ -677,23 +678,26 @@ static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, static int wm5102_out_comp_coeff_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct arizona *arizona = dev_get_drvdata(component->dev->parent); + uint16_t dac_comp_coeff = get_unaligned_be16(ucontrol->value.bytes.data); + int ret = 0; mutex_lock(&arizona->dac_comp_lock); - memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data, - sizeof(arizona->dac_comp_coeff)); - arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff); + if (arizona->dac_comp_coeff != dac_comp_coeff) { + arizona->dac_comp_coeff = dac_comp_coeff; + ret = 1; + } mutex_unlock(&arizona->dac_comp_lock); - return 0; + return ret; } static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct arizona *arizona = dev_get_drvdata(component->dev->parent); mutex_lock(&arizona->dac_comp_lock); ucontrol->value.integer.value[0] = arizona->dac_comp_enabled; @@ -705,17 +709,25 @@ static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol, static int wm5102_out_comp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct arizona *arizona = dev_get_drvdata(component->dev->parent); + struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; + int ret = 0; + + if (ucontrol->value.integer.value[0] > mc->max) + return -EINVAL; mutex_lock(&arizona->dac_comp_lock); - arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; + if (arizona->dac_comp_enabled != ucontrol->value.integer.value[0]) { + arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; + ret = 1; + } mutex_unlock(&arizona->dac_comp_lock); - return 0; + return ret; } -static const char *wm5102_osr_text[] = { +static const char * const wm5102_osr_text[] = { "Low power", "Normal", "High performance", }; @@ -983,6 +995,8 @@ ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), }; ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); @@ -1060,7 +1074,7 @@ ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE); ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE); -static const char *wm5102_aec_loopback_texts[] = { +static const char * const wm5102_aec_loopback_texts[] = { "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", }; @@ -1210,113 +1224,112 @@ SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7, ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7, ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, ARIZONA_SLIMTX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7, ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, ARIZONA_SLIMRX8_ENA_SHIFT, 0), ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, - ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, - &wm5102_aec_loopback_mux), + ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, &wm5102_aec_loopback_mux), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, @@ -1734,10 +1747,10 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "DRC1 Signal Activity", NULL, "DRC1R" }, }; -static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, - unsigned int Fref, unsigned int Fout) +static int wm5102_set_fll(struct snd_soc_component *component, int fll_id, + int source, unsigned int Fref, unsigned int Fout) { - struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec); + struct wm5102_priv *wm5102 = snd_soc_component_get_drvdata(component); switch (fll_id) { case WM5102_FLL1: @@ -1760,6 +1773,10 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, #define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) +static const struct snd_soc_dai_ops wm5102_dai_ops = { + .compress_new = snd_soc_new_compress, +}; + static struct snd_soc_dai_driver wm5102_dai[] = { { .name = "wm5102-aif1", @@ -1780,8 +1797,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = { .formats = WM5102_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5102-aif2", @@ -1802,8 +1819,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = { .formats = WM5102_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5102-aif3", @@ -1824,8 +1841,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = { .formats = WM5102_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5102-slim1", @@ -1893,7 +1910,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = { .rates = WM5102_RATES, .formats = WM5102_FORMATS, }, - .compress_new = snd_soc_new_compress, + .ops = &wm5102_dai_ops, }, { .name = "wm5102-dsp-trace", @@ -1907,10 +1924,10 @@ static struct snd_soc_dai_driver wm5102_dai[] = { }, }; -static int wm5102_open(struct snd_compr_stream *stream) +static int wm5102_open(struct snd_soc_component *component, + struct snd_compr_stream *stream) { - struct snd_soc_pcm_runtime *rtd = stream->private_data; - struct wm5102_priv *priv = snd_soc_platform_get_drvdata(rtd->platform); + struct wm5102_priv *priv = snd_soc_component_get_drvdata(component); return wm_adsp_compr_open(&priv->core.adsp[0], stream); } @@ -1930,50 +1947,49 @@ static irqreturn_t wm5102_adsp2_irq(int irq, void *data) return IRQ_HANDLED; } -static int wm5102_codec_probe(struct snd_soc_codec *codec) +static int wm5102_component_probe(struct snd_soc_component *component) { - struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); - struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); - struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + struct wm5102_priv *priv = snd_soc_component_get_drvdata(component); + struct arizona *arizona = priv->core.arizona; int ret; - ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec); + snd_soc_component_init_regmap(component, arizona->regmap); + + ret = wm_adsp2_component_probe(&priv->core.adsp[0], component); if (ret) return ret; - ret = snd_soc_add_codec_controls(codec, - arizona_adsp2_rate_controls, 1); + ret = snd_soc_add_component_controls(component, + arizona_adsp2_rate_controls, 1); if (ret) goto err_adsp2_codec_probe; - ret = arizona_init_spk(codec); + ret = arizona_init_spk(component); if (ret < 0) return ret; - arizona_init_gpio(codec); - arizona_init_notifiers(codec); + arizona_init_gpio(component); - snd_soc_component_disable_pin(component, "HAPTICS"); + snd_soc_dapm_disable_pin(dapm, "HAPTICS"); priv->core.arizona->dapm = dapm; return 0; err_adsp2_codec_probe: - wm_adsp2_codec_remove(&priv->core.adsp[0], codec); + wm_adsp2_component_remove(&priv->core.adsp[0], component); return ret; } -static int wm5102_codec_remove(struct snd_soc_codec *codec) +static void wm5102_component_remove(struct snd_soc_component *component) { - struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); + struct wm5102_priv *priv = snd_soc_component_get_drvdata(component); - wm_adsp2_codec_remove(&priv->core.adsp[0], codec); + wm_adsp2_component_remove(&priv->core.adsp[0], component); priv->core.arizona->dapm = NULL; - - return 0; } #define WM5102_DIG_VU 0x0200 @@ -1990,45 +2006,32 @@ static unsigned int wm5102_digital_vu[] = { ARIZONA_DAC_DIGITAL_VOLUME_5R, }; -static struct regmap *wm5102_get_regmap(struct device *dev) -{ - struct wm5102_priv *priv = dev_get_drvdata(dev); - - return priv->core.arizona->regmap; -} - -static const struct snd_soc_codec_driver soc_codec_dev_wm5102 = { - .probe = wm5102_codec_probe, - .remove = wm5102_codec_remove, - .get_regmap = wm5102_get_regmap, - - .idle_bias_off = true, - - .set_sysclk = arizona_set_sysclk, - .set_pll = wm5102_set_fll, - - .component_driver = { - .controls = wm5102_snd_controls, - .num_controls = ARRAY_SIZE(wm5102_snd_controls), - .dapm_widgets = wm5102_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), - .dapm_routes = wm5102_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), - }, -}; - -static struct snd_compr_ops wm5102_compr_ops = { - .open = wm5102_open, - .free = wm_adsp_compr_free, - .set_params = wm_adsp_compr_set_params, - .get_caps = wm_adsp_compr_get_caps, - .trigger = wm_adsp_compr_trigger, - .pointer = wm_adsp_compr_pointer, - .copy = wm_adsp_compr_copy, +static const struct snd_compress_ops wm5102_compress_ops = { + .open = wm5102_open, + .free = wm_adsp_compr_free, + .set_params = wm_adsp_compr_set_params, + .get_caps = wm_adsp_compr_get_caps, + .trigger = wm_adsp_compr_trigger, + .pointer = wm_adsp_compr_pointer, + .copy = wm_adsp_compr_copy, }; -static struct snd_soc_platform_driver wm5102_compr_platform = { - .compr_ops = &wm5102_compr_ops, +static const struct snd_soc_component_driver soc_component_dev_wm5102 = { + .probe = wm5102_component_probe, + .remove = wm5102_component_remove, + .set_sysclk = arizona_set_sysclk, + .set_pll = wm5102_set_fll, + .set_jack = arizona_jack_set_jack, + .name = DRV_NAME, + .compress_ops = &wm5102_compress_ops, + .controls = wm5102_snd_controls, + .num_controls = ARRAY_SIZE(wm5102_snd_controls), + .dapm_widgets = wm5102_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), + .dapm_routes = wm5102_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), + .use_pmdown_time = 1, + .endianness = 1, }; static int wm5102_probe(struct platform_device *pdev) @@ -2043,6 +2046,14 @@ static int wm5102_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, wm5102); + if (IS_ENABLED(CONFIG_OF)) { + if (!dev_get_platdata(arizona->dev)) { + ret = arizona_of_get_audio_pdata(arizona); + if (ret < 0) + return ret; + } + } + mutex_init(&arizona->dac_comp_lock); wm5102->core.arizona = arizona; @@ -2051,18 +2062,23 @@ static int wm5102_probe(struct platform_device *pdev) arizona_init_dvfs(&wm5102->core); wm5102->core.adsp[0].part = "wm5102"; - wm5102->core.adsp[0].num = 1; - wm5102->core.adsp[0].type = WMFW_ADSP2; - wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1; - wm5102->core.adsp[0].dev = arizona->dev; - wm5102->core.adsp[0].regmap = arizona->regmap; - wm5102->core.adsp[0].mem = wm5102_dsp1_regions; - wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions); + wm5102->core.adsp[0].cs_dsp.num = 1; + wm5102->core.adsp[0].cs_dsp.type = WMFW_ADSP2; + wm5102->core.adsp[0].cs_dsp.base = ARIZONA_DSP1_CONTROL_1; + wm5102->core.adsp[0].cs_dsp.dev = arizona->dev; + wm5102->core.adsp[0].cs_dsp.regmap = arizona->regmap; + wm5102->core.adsp[0].cs_dsp.mem = wm5102_dsp1_regions; + wm5102->core.adsp[0].cs_dsp.num_mems = ARRAY_SIZE(wm5102_dsp1_regions); ret = wm_adsp2_init(&wm5102->core.adsp[0]); if (ret != 0) return ret; + /* This may return -EPROBE_DEFER, so do this early on */ + ret = arizona_jack_codec_dev_probe(&wm5102->core, &pdev->dev); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++) wm5102->fll[i].vco_mult = 1; @@ -2095,54 +2111,62 @@ static int wm5102_probe(struct platform_device *pdev) wm5102); if (ret != 0) { dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); - return ret; + goto err_jack_codec_dev; } + ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1); + if (ret != 0) + dev_warn(&pdev->dev, + "Failed to set compressed IRQ as a wake source: %d\n", + ret); + + arizona_init_common(arizona); + + ret = arizona_init_vol_limit(arizona); + if (ret < 0) + goto err_dsp_irq; ret = arizona_init_spk_irqs(arizona); if (ret < 0) goto err_dsp_irq; - ret = snd_soc_register_platform(&pdev->dev, &wm5102_compr_platform); + ret = devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_wm5102, + wm5102_dai, + ARRAY_SIZE(wm5102_dai)); if (ret < 0) { - dev_err(&pdev->dev, "Failed to register platform: %d\n", ret); + dev_err(&pdev->dev, "Failed to register component: %d\n", ret); goto err_spk_irqs; } - ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102, - wm5102_dai, ARRAY_SIZE(wm5102_dai)); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); - goto err_platform; - } - return ret; -err_platform: - snd_soc_unregister_platform(&pdev->dev); err_spk_irqs: arizona_free_spk_irqs(arizona); err_dsp_irq: + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); +err_jack_codec_dev: + pm_runtime_disable(&pdev->dev); + arizona_jack_codec_dev_remove(&wm5102->core); return ret; } -static int wm5102_remove(struct platform_device *pdev) +static void wm5102_remove(struct platform_device *pdev) { struct wm5102_priv *wm5102 = platform_get_drvdata(pdev); struct arizona *arizona = wm5102->core.arizona; - snd_soc_unregister_platform(&pdev->dev); - snd_soc_unregister_codec(&pdev->dev); pm_runtime_disable(&pdev->dev); wm_adsp2_remove(&wm5102->core.adsp[0]); arizona_free_spk_irqs(arizona); + arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); - return 0; + arizona_jack_codec_dev_remove(&wm5102->core); } static struct platform_driver wm5102_codec_driver = { |
