summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/wm2200.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm2200.c')
-rw-r--r--sound/soc/codecs/wm2200.c326
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, &reg);
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,