diff options
Diffstat (limited to 'sound/soc/codecs/wm2200.c')
| -rw-r--r-- | sound/soc/codecs/wm2200.c | 326 |
1 files changed, 154 insertions, 172 deletions
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index d83dab57a1d1..87418c838ca0 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * wm2200.c -- WM2200 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> @@ -17,7 +14,7 @@ #include <linux/pm.h> #include <linux/firmware.h> #include <linux/gcd.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> @@ -33,7 +30,6 @@ #include <sound/wm2200.h> #include "wm2200.h" -#include "wmfw.h" #include "wm_adsp.h" #define WM2200_DSP_CONTROL_1 0x00 @@ -75,21 +71,16 @@ static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = { "LDOVDD", }; -struct wm2200_fll { - int fref; - int fout; - int src; - struct completion lock; -}; - /* codec private data */ struct wm2200_priv { struct wm_adsp dsp[2]; struct regmap *regmap; struct device *dev; - struct snd_soc_codec *codec; + struct snd_soc_component *component; struct wm2200_pdata pdata; struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES]; + struct gpio_desc *ldo_ena; + struct gpio_desc *reset; struct completion fll_lock; int fll_fout; @@ -98,6 +89,8 @@ struct wm2200_priv { int rev; int sysclk; + + unsigned int symmetric_rates:1; }; #define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1) @@ -154,13 +147,13 @@ static const struct regmap_range_cfg wm2200_ranges[] = { .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, }, }; -static const struct wm_adsp_region wm2200_dsp1_regions[] = { +static const struct cs_dsp_region wm2200_dsp1_regions[] = { { .type = WMFW_ADSP1_PM, .base = WM2200_DSP1_PM_BASE }, { .type = WMFW_ADSP1_DM, .base = WM2200_DSP1_DM_BASE }, { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP1_ZM_BASE }, }; -static const struct wm_adsp_region wm2200_dsp2_regions[] = { +static const struct cs_dsp_region wm2200_dsp2_regions[] = { { .type = WMFW_ADSP1_PM, .base = WM2200_DSP2_PM_BASE }, { .type = WMFW_ADSP1_DM, .base = WM2200_DSP2_DM_BASE }, { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE }, @@ -984,9 +977,10 @@ static const struct reg_sequence wm2200_reva_patch[] = { static int wm2200_reset(struct wm2200_priv *wm2200) { - if (wm2200->pdata.reset) { - gpio_set_value_cansleep(wm2200->pdata.reset, 0); - gpio_set_value_cansleep(wm2200->pdata.reset, 1); + if (wm2200->reset) { + /* Descriptor flagged active low, so this will be inverted */ + gpiod_set_value_cansleep(wm2200->reset, 1); + gpiod_set_value_cansleep(wm2200->reset, 0); return 0; } else { @@ -1153,8 +1147,8 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L, SND_SOC_BYTES_MASK("EQL Coefficients", WM2200_EQL_1, 20, WM2200_EQL_ENA), SND_SOC_BYTES_MASK("EQR Coefficients", WM2200_EQR_1, 20, WM2200_EQR_ENA), -SND_SOC_BYTES("LHPF1 Coefficeints", WM2200_HPLPF1_2, 1), -SND_SOC_BYTES("LHPF2 Coefficeints", WM2200_HPLPF2_2, 1), +SND_SOC_BYTES("LHPF1 Coefficients", WM2200_HPLPF1_2, 1), +SND_SOC_BYTES("LHPF2 Coefficients", WM2200_HPLPF2_2, 1), SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L, WM2200_OUT1_OSR_SHIFT, 1, 0), @@ -1178,6 +1172,9 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, WM2200_SPK1R_MUTE_SHIFT, 1, 1), SOC_ENUM("RxANC Src", wm2200_rxanc_input_sel), + +WM_ADSP_FW_CONTROL("DSP1", 0), +WM_ADSP_FW_CONTROL("DSP2", 1), }; WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); @@ -1548,23 +1545,18 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = { WM2200_MIXER_ROUTES("LHPF2", "LHPF2"), }; -static int wm2200_probe(struct snd_soc_codec *codec) +static int wm2200_probe(struct snd_soc_component *component) { - struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev); - int ret; - - wm2200->codec = codec; + struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); - ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 2); - if (ret != 0) - return ret; + wm2200->component = component; - return ret; + return 0; } static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; int lrclk, bclk, fmt_val; lrclk = 0; @@ -1578,26 +1570,26 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) fmt_val = 2; break; default: - dev_err(codec->dev, "Unsupported DAI format %d\n", + dev_err(component->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: lrclk |= WM2200_AIF1TX_LRCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: bclk |= WM2200_AIF1_BCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: lrclk |= WM2200_AIF1TX_LRCLK_MSTR; bclk |= WM2200_AIF1_BCLK_MSTR; break; default: - dev_err(codec->dev, "Unsupported master mode %d\n", + dev_err(component->dev, "Unsupported master mode %d\n", fmt & SND_SOC_DAIFMT_MASTER_MASK); return -EINVAL; } @@ -1619,15 +1611,15 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR | + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR | WM2200_AIF1_BCLK_INV, bclk); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2, + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_2, WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, lrclk); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3, + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_3, WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, lrclk); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_5, WM2200_AIF1_FMT_MASK, fmt_val); return 0; @@ -1696,8 +1688,8 @@ static int wm2200_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 wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); int i, bclk, lrclk, wl, fl, sr_code; int *bclk_rates; @@ -1709,7 +1701,7 @@ static int wm2200_hw_params(struct snd_pcm_substream *substream, if (fl < 0) return fl; - dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n", + dev_dbg(component->dev, "Word length %d bits, frame length %d bits\n", wl, fl); /* Target BCLK rate */ @@ -1718,7 +1710,7 @@ static int wm2200_hw_params(struct snd_pcm_substream *substream, return bclk; if (!wm2200->sysclk) { - dev_err(codec->dev, "SYSCLK has no rate set\n"); + dev_err(component->dev, "SYSCLK has no rate set\n"); return -EINVAL; } @@ -1726,13 +1718,13 @@ static int wm2200_hw_params(struct snd_pcm_substream *substream, if (wm2200_sr_code[i] == params_rate(params)) break; if (i == ARRAY_SIZE(wm2200_sr_code)) { - dev_err(codec->dev, "Unsupported sample rate: %dHz\n", + dev_err(component->dev, "Unsupported sample rate: %dHz\n", params_rate(params)); return -EINVAL; } sr_code = i; - dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n", + dev_dbg(component->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n", bclk, wm2200->sysclk); if (wm2200->sysclk % 4000) @@ -1744,52 +1736,47 @@ static int wm2200_hw_params(struct snd_pcm_substream *substream, if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0)) break; if (i == WM2200_NUM_BCLK_RATES) { - dev_err(codec->dev, + dev_err(component->dev, "No valid BCLK for %dHz found from %dHz SYSCLK\n", bclk, wm2200->sysclk); return -EINVAL; } bclk = i; - dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, + dev_dbg(component->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]); + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_DIV_MASK, bclk); lrclk = bclk_rates[bclk] / params_rate(params); - dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); + dev_dbg(component->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - dai->symmetric_rates) - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7, + wm2200->symmetric_rates) + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_7, WM2200_AIF1RX_BCPF_MASK, lrclk); else - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6, + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_6, WM2200_AIF1TX_BCPF_MASK, lrclk); i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9, + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_9, WM2200_AIF1RX_WL_MASK | WM2200_AIF1RX_SLOT_LEN_MASK, i); else - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8, + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_8, WM2200_AIF1TX_WL_MASK | WM2200_AIF1TX_SLOT_LEN_MASK, i); - snd_soc_update_bits(codec, WM2200_CLOCKING_4, + snd_soc_component_update_bits(component, WM2200_CLOCKING_4, WM2200_SAMPLE_RATE_1_MASK, sr_code); return 0; } -static const struct snd_soc_dai_ops wm2200_dai_ops = { - .set_fmt = wm2200_set_fmt, - .hw_params = wm2200_hw_params, -}; - -static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id, +static int wm2200_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsigned int freq, int dir) { - struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); + struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); int fval; switch (clk_id) { @@ -1797,7 +1784,7 @@ static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id, break; default: - dev_err(codec->dev, "Unknown clock %d\n", clk_id); + dev_err(component->dev, "Unknown clock %d\n", clk_id); return -EINVAL; } @@ -1808,7 +1795,7 @@ static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id, case WM2200_CLKSRC_BCLK1: break; default: - dev_err(codec->dev, "Invalid source %d\n", source); + dev_err(component->dev, "Invalid source %d\n", source); return -EINVAL; } @@ -1818,7 +1805,7 @@ static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id, fval = 2; break; default: - dev_err(codec->dev, "Invalid clock rate: %d\n", freq); + dev_err(component->dev, "Invalid clock rate: %d\n", freq); return -EINVAL; } @@ -1826,7 +1813,7 @@ static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id, * match. */ - snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK | + snd_soc_component_update_bits(component, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK | WM2200_SYSCLK_SRC_MASK, fval << WM2200_SYSCLK_FREQ_SHIFT | source); @@ -1934,23 +1921,23 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, return 0; } -static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, +static int wm2200_set_fll(struct snd_soc_component *component, int fll_id, int source, unsigned int Fref, unsigned int Fout) { - struct i2c_client *i2c = to_i2c_client(codec->dev); - struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); + struct i2c_client *i2c = to_i2c_client(component->dev); + struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); struct _fll_div factors; int ret, i, timeout; unsigned long time_left; if (!Fout) { - dev_dbg(codec->dev, "FLL disabled"); + dev_dbg(component->dev, "FLL disabled"); if (wm2200->fll_fout) - pm_runtime_put(codec->dev); + pm_runtime_put(component->dev); wm2200->fll_fout = 0; - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0); return 0; } @@ -1961,7 +1948,7 @@ static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, case WM2200_FLL_SRC_BCLK: break; default: - dev_err(codec->dev, "Invalid FLL source %d\n", source); + dev_err(component->dev, "Invalid FLL source %d\n", source); return -EINVAL; } @@ -1970,44 +1957,44 @@ static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, return ret; /* Disable the FLL while we reconfigure */ - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0); + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0); - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_2, WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK, (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) | factors.fll_fratio); if (factors.theta) { - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_3, WM2200_FLL_FRACN_ENA, WM2200_FLL_FRACN_ENA); - snd_soc_update_bits(codec, WM2200_FLL_EFS_2, + snd_soc_component_update_bits(component, WM2200_FLL_EFS_2, WM2200_FLL_EFS_ENA, WM2200_FLL_EFS_ENA); } else { - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_3, WM2200_FLL_FRACN_ENA, 0); - snd_soc_update_bits(codec, WM2200_FLL_EFS_2, + snd_soc_component_update_bits(component, WM2200_FLL_EFS_2, WM2200_FLL_EFS_ENA, 0); } - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK, factors.theta); - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK, factors.n); - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_7, WM2200_FLL_CLK_REF_DIV_MASK | WM2200_FLL_CLK_REF_SRC_MASK, (factors.fll_refclk_div << WM2200_FLL_CLK_REF_DIV_SHIFT) | source); - snd_soc_update_bits(codec, WM2200_FLL_EFS_1, + snd_soc_component_update_bits(component, WM2200_FLL_EFS_1, WM2200_FLL_LAMBDA_MASK, factors.lambda); /* Clear any pending completions */ try_wait_for_completion(&wm2200->fll_lock); - pm_runtime_get_sync(codec->dev); + pm_runtime_get_sync(component->dev); - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, + snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, WM2200_FLL_ENA); if (i2c->irq) @@ -2015,7 +2002,7 @@ static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, else timeout = 50; - snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA, + snd_soc_component_update_bits(component, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA, WM2200_SYSCLK_ENA); /* Poll for the lock; will use the interrupt to exit quickly */ @@ -2030,10 +2017,10 @@ static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, msleep(1); } - ret = snd_soc_read(codec, + ret = snd_soc_component_read(component, WM2200_INTERRUPT_RAW_STATUS_2); if (ret < 0) { - dev_err(codec->dev, + dev_err(component->dev, "Failed to read FLL status: %d\n", ret); continue; @@ -2042,8 +2029,8 @@ static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, break; } if (i == timeout) { - dev_err(codec->dev, "FLL lock timed out\n"); - pm_runtime_put(codec->dev); + dev_err(component->dev, "FLL lock timed out\n"); + pm_runtime_put(component->dev); return -ETIMEDOUT; } @@ -2051,33 +2038,40 @@ static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, wm2200->fll_fref = Fref; wm2200->fll_fout = Fout; - dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout); + dev_dbg(component->dev, "FLL running %dHz->%dHz\n", Fref, Fout); return 0; } static int wm2200_dai_probe(struct snd_soc_dai *dai) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; + struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); unsigned int val = 0; int ret; - ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1); + ret = snd_soc_component_read(component, WM2200_GPIO_CTRL_1); if (ret >= 0) { if ((ret & WM2200_GP1_FN_MASK) != 0) { - dai->symmetric_rates = true; + wm2200->symmetric_rates = true; val = WM2200_AIF1TX_LRCLK_SRC; } } else { - dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret); + dev_err(component->dev, "Failed to read GPIO 1 config: %d\n", ret); } - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2, + snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_2, WM2200_AIF1TX_LRCLK_SRC, val); return 0; } +static const struct snd_soc_dai_ops wm2200_dai_ops = { + .probe = wm2200_dai_probe, + .set_fmt = wm2200_set_fmt, + .hw_params = wm2200_hw_params, +}; + #define WM2200_RATES SNDRV_PCM_RATE_8000_48000 #define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ @@ -2085,7 +2079,6 @@ static int wm2200_dai_probe(struct snd_soc_dai *dai) static struct snd_soc_dai_driver wm2200_dai = { .name = "wm2200", - .probe = wm2200_dai_probe, .playback = { .stream_name = "Playback", .channels_min = 2, @@ -2103,22 +2096,17 @@ static struct snd_soc_dai_driver wm2200_dai = { .ops = &wm2200_dai_ops, }; -static const struct snd_soc_codec_driver soc_codec_wm2200 = { - .probe = wm2200_probe, - - .idle_bias_off = true, - .ignore_pmdown_time = true, - .set_sysclk = wm2200_set_sysclk, - .set_pll = wm2200_set_fll, - - .component_driver = { - .controls = wm2200_snd_controls, - .num_controls = ARRAY_SIZE(wm2200_snd_controls), - .dapm_widgets = wm2200_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), - .dapm_routes = wm2200_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), - }, +static const struct snd_soc_component_driver soc_component_wm2200 = { + .probe = wm2200_probe, + .set_sysclk = wm2200_set_sysclk, + .set_pll = wm2200_set_fll, + .controls = wm2200_snd_controls, + .num_controls = ARRAY_SIZE(wm2200_snd_controls), + .dapm_widgets = wm2200_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), + .dapm_routes = wm2200_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), + .endianness = 1, }; static irqreturn_t wm2200_irq(int irq, void *data) @@ -2166,7 +2154,7 @@ static const struct regmap_config wm2200_regmap = { .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults), .volatile_reg = wm2200_volatile_register, .readable_reg = wm2200_readable_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .ranges = wm2200_ranges, .num_ranges = ARRAY_SIZE(wm2200_ranges), }; @@ -2190,8 +2178,7 @@ static const unsigned int wm2200_mic_ctrl_reg[] = { WM2200_IN3L_CONTROL, }; -static int wm2200_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int wm2200_i2c_probe(struct i2c_client *i2c) { struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev); struct wm2200_priv *wm2200; @@ -2216,23 +2203,23 @@ static int wm2200_i2c_probe(struct i2c_client *i2c, } for (i = 0; i < 2; i++) { - wm2200->dsp[i].type = WMFW_ADSP1; + wm2200->dsp[i].cs_dsp.type = WMFW_ADSP1; wm2200->dsp[i].part = "wm2200"; - wm2200->dsp[i].num = i + 1; - wm2200->dsp[i].dev = &i2c->dev; - wm2200->dsp[i].regmap = wm2200->regmap; - wm2200->dsp[i].sysclk_reg = WM2200_CLOCKING_3; - wm2200->dsp[i].sysclk_mask = WM2200_SYSCLK_FREQ_MASK; - wm2200->dsp[i].sysclk_shift = WM2200_SYSCLK_FREQ_SHIFT; + wm2200->dsp[i].cs_dsp.num = i + 1; + wm2200->dsp[i].cs_dsp.dev = &i2c->dev; + wm2200->dsp[i].cs_dsp.regmap = wm2200->regmap; + wm2200->dsp[i].cs_dsp.sysclk_reg = WM2200_CLOCKING_3; + wm2200->dsp[i].cs_dsp.sysclk_mask = WM2200_SYSCLK_FREQ_MASK; + wm2200->dsp[i].cs_dsp.sysclk_shift = WM2200_SYSCLK_FREQ_SHIFT; } - wm2200->dsp[0].base = WM2200_DSP1_CONTROL_1; - wm2200->dsp[0].mem = wm2200_dsp1_regions; - wm2200->dsp[0].num_mems = ARRAY_SIZE(wm2200_dsp1_regions); + wm2200->dsp[0].cs_dsp.base = WM2200_DSP1_CONTROL_1; + wm2200->dsp[0].cs_dsp.mem = wm2200_dsp1_regions; + wm2200->dsp[0].cs_dsp.num_mems = ARRAY_SIZE(wm2200_dsp1_regions); - wm2200->dsp[1].base = WM2200_DSP2_CONTROL_1; - wm2200->dsp[1].mem = wm2200_dsp2_regions; - wm2200->dsp[1].num_mems = ARRAY_SIZE(wm2200_dsp2_regions); + wm2200->dsp[1].cs_dsp.base = WM2200_DSP2_CONTROL_1; + wm2200->dsp[1].cs_dsp.mem = wm2200_dsp2_regions; + wm2200->dsp[1].cs_dsp.num_mems = ARRAY_SIZE(wm2200_dsp2_regions); for (i = 0; i < ARRAY_SIZE(wm2200->dsp); i++) wm_adsp1_init(&wm2200->dsp[i]); @@ -2262,28 +2249,28 @@ static int wm2200_i2c_probe(struct i2c_client *i2c, return ret; } - if (wm2200->pdata.ldo_ena) { - ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena, - GPIOF_OUT_INIT_HIGH, - "WM2200 LDOENA"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", - wm2200->pdata.ldo_ena, ret); - goto err_enable; - } + wm2200->ldo_ena = devm_gpiod_get_optional(&i2c->dev, "wlf,ldo1ena", + GPIOD_OUT_HIGH); + if (IS_ERR(wm2200->ldo_ena)) { + ret = PTR_ERR(wm2200->ldo_ena); + dev_err(&i2c->dev, "Failed to request LDOENA GPIO %d\n", + ret); + goto err_enable; + } + if (wm2200->ldo_ena) { + gpiod_set_consumer_name(wm2200->ldo_ena, "WM2200 LDOENA"); msleep(2); } - if (wm2200->pdata.reset) { - ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset, - GPIOF_OUT_INIT_HIGH, - "WM2200 /RESET"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", - wm2200->pdata.reset, ret); - goto err_ldo; - } + wm2200->reset = devm_gpiod_get_optional(&i2c->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(wm2200->reset)) { + ret = PTR_ERR(wm2200->reset); + dev_err(&i2c->dev, "Failed to request RESET GPIO %d\n", + ret); + goto err_ldo; } + gpiod_set_consumer_name(wm2200->reset, "WM2200 /RESET"); ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, ®); if (ret < 0) { @@ -2405,7 +2392,7 @@ static int wm2200_i2c_probe(struct i2c_client *i2c, pm_runtime_enable(&i2c->dev); pm_request_idle(&i2c->dev); - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200, + ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_wm2200, &wm2200_dai, 1); if (ret != 0) { dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); @@ -2416,42 +2403,39 @@ static int wm2200_i2c_probe(struct i2c_client *i2c, err_pm_runtime: pm_runtime_disable(&i2c->dev); + if (i2c->irq) + free_irq(i2c->irq, wm2200); err_reset: - if (wm2200->pdata.reset) - gpio_set_value_cansleep(wm2200->pdata.reset, 0); + gpiod_set_value_cansleep(wm2200->reset, 1); err_ldo: - if (wm2200->pdata.ldo_ena) - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); + gpiod_set_value_cansleep(wm2200->ldo_ena, 0); err_enable: regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), wm2200->core_supplies); return ret; } -static int wm2200_i2c_remove(struct i2c_client *i2c) +static void wm2200_i2c_remove(struct i2c_client *i2c) { struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c); - snd_soc_unregister_codec(&i2c->dev); + pm_runtime_disable(&i2c->dev); if (i2c->irq) free_irq(i2c->irq, wm2200); - if (wm2200->pdata.reset) - gpio_set_value_cansleep(wm2200->pdata.reset, 0); - if (wm2200->pdata.ldo_ena) - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); - - return 0; + /* Assert RESET, disable LDO */ + gpiod_set_value_cansleep(wm2200->reset, 1); + gpiod_set_value_cansleep(wm2200->ldo_ena, 0); + regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), + wm2200->core_supplies); } -#ifdef CONFIG_PM static int wm2200_runtime_suspend(struct device *dev) { struct wm2200_priv *wm2200 = dev_get_drvdata(dev); regcache_cache_only(wm2200->regmap, true); regcache_mark_dirty(wm2200->regmap); - if (wm2200->pdata.ldo_ena) - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); + gpiod_set_value_cansleep(wm2200->ldo_ena, 0); regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), wm2200->core_supplies); @@ -2471,8 +2455,8 @@ static int wm2200_runtime_resume(struct device *dev) return ret; } - if (wm2200->pdata.ldo_ena) { - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1); + if (wm2200->ldo_ena) { + gpiod_set_value_cansleep(wm2200->ldo_ena, 1); msleep(2); } @@ -2481,15 +2465,13 @@ static int wm2200_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops wm2200_pm = { - SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, - NULL) + RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, NULL) }; static const struct i2c_device_id wm2200_i2c_id[] = { - { "wm2200", 0 }, + { "wm2200" }, { } }; MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); @@ -2497,7 +2479,7 @@ MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); static struct i2c_driver wm2200_i2c_driver = { .driver = { .name = "wm2200", - .pm = &wm2200_pm, + .pm = pm_ptr(&wm2200_pm), }, .probe = wm2200_i2c_probe, .remove = wm2200_i2c_remove, |
