diff options
Diffstat (limited to 'sound/soc/codecs/wm8903.c')
| -rw-r--r-- | sound/soc/codecs/wm8903.c | 509 |
1 files changed, 241 insertions, 268 deletions
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fa24cedee687..f73f6ad06b38 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * wm8903.c -- WM8903 ALSA SoC Audio driver * @@ -6,13 +7,8 @@ * * 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. - * * TODO: * - TDM mode configuration. - * - Digital microphone support. */ #include <linux/module.h> @@ -20,12 +16,14 @@ #include <linux/init.h> #include <linux/completion.h> #include <linux/delay.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/regmap.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/irq.h> +#include <linux/mutex.h> #include <sound/core.h> #include <sound/jack.h> #include <sound/pcm.h> @@ -114,15 +112,24 @@ static const struct reg_default wm8903_reg_defaults[] = { { 172, 0x0000 }, /* R172 - Analogue Output Bias 0 */ }; +#define WM8903_NUM_SUPPLIES 4 +static const char *wm8903_supply_names[WM8903_NUM_SUPPLIES] = { + "AVDD", + "CPVDD", + "DBVDD", + "DCVDD", +}; + struct wm8903_priv { struct wm8903_platform_data *pdata; struct device *dev; - struct snd_soc_codec *codec; struct regmap *regmap; + struct regulator_bulk_data supplies[WM8903_NUM_SUPPLIES]; int sysclk; int irq; + struct mutex lock; int fs; int deemph; @@ -240,10 +247,10 @@ static bool wm8903_volatile_register(struct device *dev, unsigned int reg) case WM8903_DC_SERVO_READBACK_2: case WM8903_DC_SERVO_READBACK_3: case WM8903_DC_SERVO_READBACK_4: - return 1; + return true; default: - return 0; + return false; } } @@ -259,15 +266,15 @@ static int wm8903_cp_event(struct snd_soc_dapm_widget *w, static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { - struct snd_soc_codec *codec = w->codec; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); switch (event) { case SND_SOC_DAPM_POST_PMU: wm8903->dcs_pending |= 1 << w->shift; break; case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, WM8903_DC_SERVO_0, + snd_soc_component_update_bits(component, WM8903_DC_SERVO_0, 1 << w->shift, 0); break; } @@ -278,18 +285,16 @@ static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, #define WM8903_DCS_MODE_WRITE_STOP 0 #define WM8903_DCS_MODE_START_STOP 2 -static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, +static void wm8903_seq_notifier(struct snd_soc_component *component, enum snd_soc_dapm_type event, int subseq) { - struct snd_soc_codec *codec = container_of(dapm, - struct snd_soc_codec, dapm); - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; int i, val; /* Complete any pending DC servo starts */ if (wm8903->dcs_pending) { - dev_dbg(codec->dev, "Starting DC servo for %x\n", + dev_dbg(component->dev, "Starting DC servo for %x\n", wm8903->dcs_pending); /* If we've no cached values then we need to do startup */ @@ -298,14 +303,14 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, continue; if (wm8903->dcs_cache[i]) { - dev_dbg(codec->dev, + dev_dbg(component->dev, "Restore DC servo %d value %x\n", 3 - i, wm8903->dcs_cache[i]); - snd_soc_write(codec, WM8903_DC_SERVO_4 + i, + snd_soc_component_write(component, WM8903_DC_SERVO_4 + i, wm8903->dcs_cache[i] & 0xff); } else { - dev_dbg(codec->dev, + dev_dbg(component->dev, "Calibrate DC servo %d\n", 3 - i); dcs_mode = WM8903_DCS_MODE_START_STOP; } @@ -315,10 +320,10 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, if (wm8903->class_w_users) dcs_mode = WM8903_DCS_MODE_START_STOP; - snd_soc_update_bits(codec, WM8903_DC_SERVO_2, + snd_soc_component_update_bits(component, WM8903_DC_SERVO_2, WM8903_DCS_MODE_MASK, dcs_mode); - snd_soc_update_bits(codec, WM8903_DC_SERVO_0, + snd_soc_component_update_bits(component, WM8903_DC_SERVO_0, WM8903_DCS_ENA_MASK, wm8903->dcs_pending); switch (dcs_mode) { @@ -336,9 +341,9 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, if (!(wm8903->dcs_pending & (1 << i))) continue; - val = snd_soc_read(codec, + val = snd_soc_component_read(component, WM8903_DC_SERVO_READBACK_1 + i); - dev_dbg(codec->dev, "DC servo %d: %x\n", + dev_dbg(component->dev, "DC servo %d: %x\n", 3 - i, val); wm8903->dcs_cache[i] = val; } @@ -364,20 +369,18 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = snd_soc_dapm_kcontrol_to_component(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); u16 reg; int ret; - reg = snd_soc_read(codec, WM8903_CLASS_W_0); + reg = snd_soc_component_read(component, WM8903_CLASS_W_0); /* Turn it off if we're about to enable bypass */ if (ucontrol->value.integer.value[0]) { if (wm8903->class_w_users == 0) { - dev_dbg(codec->dev, "Disabling Class W\n"); - snd_soc_write(codec, WM8903_CLASS_W_0, reg & + dev_dbg(component->dev, "Disabling Class W\n"); + snd_soc_component_write(component, WM8903_CLASS_W_0, reg & ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); } wm8903->class_w_users++; @@ -389,14 +392,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, /* If we've just disabled the last bypass path turn Class W on */ if (!ucontrol->value.integer.value[0]) { if (wm8903->class_w_users == 1) { - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_write(codec, WM8903_CLASS_W_0, reg | + dev_dbg(component->dev, "Enabling Class W\n"); + snd_soc_component_write(component, WM8903_CLASS_W_0, reg | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); } wm8903->class_w_users--; } - dev_dbg(codec->dev, "Bypass use count now %d\n", + dev_dbg(component->dev, "Bypass use count now %d\n", wm8903->class_w_users); return ret; @@ -409,9 +412,9 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, static int wm8903_deemph[] = { 0, 32000, 44100, 48000 }; -static int wm8903_set_deemph(struct snd_soc_codec *codec) +static int wm8903_set_deemph(struct snd_soc_component *component) { - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); int val, i, best; /* If we're using deemphasis select the nearest available sample @@ -431,20 +434,20 @@ static int wm8903_set_deemph(struct snd_soc_codec *codec) val = 0; } - dev_dbg(codec->dev, "Set deemphasis %d (%dHz)\n", + dev_dbg(component->dev, "Set deemphasis %d (%dHz)\n", best, wm8903_deemph[best]); - return snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, + return snd_soc_component_update_bits(component, WM8903_DAC_DIGITAL_1, WM8903_DEEMPH_MASK, val); } static int wm8903_get_deemph(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); - ucontrol->value.enumerated.item[0] = wm8903->deemph; + ucontrol->value.integer.value[0] = wm8903->deemph; return 0; } @@ -452,23 +455,23 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol, static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); + unsigned int deemph = ucontrol->value.integer.value[0]; int ret = 0; if (deemph > 1) return -EINVAL; - mutex_lock(&codec->mutex); + mutex_lock(&wm8903->lock); if (wm8903->deemph != deemph) { wm8903->deemph = deemph; - wm8903_set_deemph(codec); + wm8903_set_deemph(component); ret = 1; } - mutex_unlock(&codec->mutex); + mutex_unlock(&wm8903->lock); return ret; } @@ -491,28 +494,28 @@ static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8903_ADC_DIGITAL_0, 5, 4, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(hpf_mode, + WM8903_ADC_DIGITAL_0, 5, hpf_mode_text); static const char *osr_text[] = { "Low power", "High performance" }; -static const struct soc_enum adc_osr = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_ADC_0, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(adc_osr, + WM8903_ANALOGUE_ADC_0, 0, osr_text); -static const struct soc_enum dac_osr = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(dac_osr, + WM8903_DAC_DIGITAL_1, 0, osr_text); static const char *drc_slope_text[] = { "1", "1/2", "1/4", "1/8", "1/16", "0" }; -static const struct soc_enum drc_slope_r0 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r0, + WM8903_DRC_2, 3, drc_slope_text); -static const struct soc_enum drc_slope_r1 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r1, + WM8903_DRC_2, 0, drc_slope_text); static const char *drc_attack_text[] = { "instantaneous", @@ -520,125 +523,125 @@ static const char *drc_attack_text[] = { "46.4ms", "92.8ms", "185.6ms" }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8903_DRC_1, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", "23.87s", "47.56s" }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8903_DRC_1, 8, drc_decay_text); static const char *drc_ff_delay_text[] = { "5 samples", "9 samples" }; -static const struct soc_enum drc_ff_delay = - SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text); +static SOC_ENUM_SINGLE_DECL(drc_ff_delay, + WM8903_DRC_0, 5, drc_ff_delay_text); static const char *drc_qr_decay_text[] = { "0.725ms", "1.45ms", "5.8ms" }; -static const struct soc_enum drc_qr_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_decay, + WM8903_DRC_1, 4, drc_qr_decay_text); static const char *drc_smoothing_text[] = { "Low", "Medium", "High" }; -static const struct soc_enum drc_smoothing = - SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text); +static SOC_ENUM_SINGLE_DECL(drc_smoothing, + WM8903_DRC_0, 11, drc_smoothing_text); static const char *soft_mute_text[] = { "Fast (fs/2)", "Slow (fs/32)" }; -static const struct soc_enum soft_mute = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text); +static SOC_ENUM_SINGLE_DECL(soft_mute, + WM8903_DAC_DIGITAL_1, 10, soft_mute_text); static const char *mute_mode_text[] = { "Hard", "Soft" }; -static const struct soc_enum mute_mode = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text); +static SOC_ENUM_SINGLE_DECL(mute_mode, + WM8903_DAC_DIGITAL_1, 9, mute_mode_text); static const char *companding_text[] = { "ulaw", "alaw" }; -static const struct soc_enum dac_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(dac_companding, + WM8903_AUDIO_INTERFACE_0, 0, companding_text); -static const struct soc_enum adc_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(adc_companding, + WM8903_AUDIO_INTERFACE_0, 2, companding_text); static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; -static const struct soc_enum linput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(linput_mode_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 0, input_mode_text); -static const struct soc_enum rinput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(rinput_mode_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 0, input_mode_text); static const char *linput_mux_text[] = { "IN1L", "IN2L", "IN3L" }; -static const struct soc_enum linput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 2, linput_mux_text); -static const struct soc_enum linput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_inv_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 4, linput_mux_text); static const char *rinput_mux_text[] = { "IN1R", "IN2R", "IN3R" }; -static const struct soc_enum rinput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 2, rinput_mux_text); -static const struct soc_enum rinput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_inv_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 4, rinput_mux_text); static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum lsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(lsidetone_enum, + WM8903_DAC_DIGITAL_0, 2, sidetone_text); -static const struct soc_enum rsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(rsidetone_enum, + WM8903_DAC_DIGITAL_0, 0, sidetone_text); static const char *adcinput_text[] = { "ADC", "DMIC" }; -static const struct soc_enum adcinput_enum = - SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text); +static SOC_ENUM_SINGLE_DECL(adcinput_enum, + WM8903_CLOCK_RATE_TEST_4, 9, adcinput_text); static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum lcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lcapture_enum, + WM8903_AUDIO_INTERFACE_0, 7, aif_text); -static const struct soc_enum rcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rcapture_enum, + WM8903_AUDIO_INTERFACE_0, 6, aif_text); -static const struct soc_enum lplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lplay_enum, + WM8903_AUDIO_INTERFACE_0, 5, aif_text); -static const struct soc_enum rplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rplay_enum, + WM8903_AUDIO_INTERFACE_0, 4, aif_text); static const struct snd_kcontrol_new wm8903_snd_controls[] = { @@ -1093,22 +1096,24 @@ static const struct snd_soc_dapm_route wm8903_intercon[] = { { "Right Line Output PGA", NULL, "Charge Pump" }, }; -static int wm8903_set_bias_level(struct snd_soc_codec *codec, +static int wm8903_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_RES_MASK, WM8903_VMID_RES_50K); break; case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, + if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) { + snd_soc_component_update_bits(component, WM8903_BIAS_CONTROL_0, WM8903_POBCTRL | WM8903_ISEL_MASK | WM8903_STARTUP_BIAS_ENA | WM8903_BIAS_ENA, @@ -1116,22 +1121,22 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, (2 << WM8903_ISEL_SHIFT) | WM8903_STARTUP_BIAS_ENA); - snd_soc_update_bits(codec, + snd_soc_component_update_bits(component, WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, WM8903_SPK_DISCHARGE, WM8903_SPK_DISCHARGE); msleep(33); - snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, + snd_soc_component_update_bits(component, WM8903_POWER_MANAGEMENT_5, WM8903_SPKL_ENA | WM8903_SPKR_ENA, WM8903_SPKL_ENA | WM8903_SPKR_ENA); - snd_soc_update_bits(codec, + snd_soc_component_update_bits(component, WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, WM8903_SPK_DISCHARGE, 0); - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_TIE_ENA | WM8903_BUFIO_ENA | WM8903_VMID_IO_ENA | @@ -1147,71 +1152,69 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, msleep(129); - snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, + snd_soc_component_update_bits(component, WM8903_POWER_MANAGEMENT_5, WM8903_SPKL_ENA | WM8903_SPKR_ENA, 0); - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_SOFT_MASK, 0); - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_RES_MASK, WM8903_VMID_RES_50K); - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_BIAS_CONTROL_0, WM8903_BIAS_ENA | WM8903_POBCTRL, WM8903_BIAS_ENA); /* By default no bypass paths are enabled so * enable Class W support. */ - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_update_bits(codec, WM8903_CLASS_W_0, + dev_dbg(component->dev, "Enabling Class W\n"); + snd_soc_component_update_bits(component, WM8903_CLASS_W_0, WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V, WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); } - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_RES_MASK, WM8903_VMID_RES_250K); break; case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_BIAS_CONTROL_0, WM8903_BIAS_ENA, 0); - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_SOFT_MASK, 2 << WM8903_VMID_SOFT_SHIFT); - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_BUF_ENA, 0); msleep(290); - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_VMID_CONTROL_0, WM8903_VMID_TIE_ENA | WM8903_BUFIO_ENA | WM8903_VMID_IO_ENA | WM8903_VMID_RES_MASK | WM8903_VMID_SOFT_MASK | WM8903_VMID_BUF_ENA, 0); - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_BIAS_CONTROL_0, WM8903_STARTUP_BIAS_ENA, 0); break; } - codec->dapm.bias_level = level; - return 0; } static int wm8903_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 wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = codec_dai->component; + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); wm8903->sysclk = freq; @@ -1221,22 +1224,22 @@ static int wm8903_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; - u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1); + struct snd_soc_component *component = codec_dai->component; + u16 aif1 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_1); aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); 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: aif1 |= WM8903_LRCLK_DIR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif1 |= WM8903_LRCLK_DIR | WM8903_BCLK_DIR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: aif1 |= WM8903_BCLK_DIR; break; default: @@ -1300,24 +1303,24 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); + snd_soc_component_write(component, WM8903_AUDIO_INTERFACE_1, aif1); return 0; } -static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8903_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; u16 reg; - reg = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); + reg = snd_soc_component_read(component, WM8903_DAC_DIGITAL_1); if (mute) reg |= WM8903_DAC_MUTE; else reg &= ~WM8903_DAC_MUTE; - snd_soc_write(codec, WM8903_DAC_DIGITAL_1, reg); + snd_soc_component_write(component, WM8903_DAC_DIGITAL_1, reg); return 0; } @@ -1437,8 +1440,8 @@ static int wm8903_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 wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); int fs = params_rate(params); int bclk; int bclk_div; @@ -1449,12 +1452,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, int cur_val; int clk_sys; - u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1); - u16 aif2 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_2); - u16 aif3 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_3); - u16 clock0 = snd_soc_read(codec, WM8903_CLOCK_RATES_0); - u16 clock1 = snd_soc_read(codec, WM8903_CLOCK_RATES_1); - u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); + u16 aif1 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_1); + u16 aif2 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_2); + u16 aif3 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_3); + u16 clock0 = snd_soc_component_read(component, WM8903_CLOCK_RATES_0); + u16 clock1 = snd_soc_component_read(component, WM8903_CLOCK_RATES_1); + u16 dac_digital1 = snd_soc_component_read(component, WM8903_DAC_DIGITAL_1); /* Enable sloping stopband filter for low sample rates */ if (fs <= 24000) @@ -1473,25 +1476,25 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, } } - dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); + dev_dbg(component->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); clock1 &= ~WM8903_SAMPLE_RATE_MASK; clock1 |= sample_rates[dsp_config].value; aif1 &= ~WM8903_AIF_WL_MASK; bclk = 2 * fs; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: + switch (params_width(params)) { + case 16: bclk *= 16; break; - case SNDRV_PCM_FORMAT_S20_3LE: + case 20: bclk *= 20; aif1 |= 0x4; break; - case SNDRV_PCM_FORMAT_S24_LE: + case 24: bclk *= 24; aif1 |= 0x8; break; - case SNDRV_PCM_FORMAT_S32_LE: + case 32: bclk *= 32; aif1 |= 0xc; break; @@ -1499,7 +1502,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n", + dev_dbg(component->dev, "MCLK = %dHz, target sample rate = %dHz\n", wm8903->sysclk, fs); /* We may not have an MCLK which allows us to generate exactly @@ -1534,12 +1537,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; - dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", + dev_dbg(component->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", clk_sys_ratios[clk_config].rate, clk_sys_ratios[clk_config].mode, clk_sys_ratios[clk_config].div); - dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys); + dev_dbg(component->dev, "Actual CLK_SYS = %dHz\n", clk_sys); /* We may not get quite the right frequency if using * approximate clocks so look for the closest match that is @@ -1547,21 +1550,19 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, * BCLKs to clock out the samples). */ bclk_div = 0; - best_val = ((clk_sys * 10) / bclk_divs[0].ratio) - bclk; i = 1; while (i < ARRAY_SIZE(bclk_divs)) { cur_val = ((clk_sys * 10) / bclk_divs[i].ratio) - bclk; if (cur_val < 0) /* BCLK table is sorted */ break; bclk_div = i; - best_val = cur_val; i++; } aif2 &= ~WM8903_BCLK_DIV_MASK; aif3 &= ~WM8903_LRCLK_RATE_MASK; - dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", + dev_dbg(component->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", bclk_divs[bclk_div].ratio / 10, bclk, (clk_sys * 10) / bclk_divs[bclk_div].ratio); @@ -1569,14 +1570,14 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, aif3 |= bclk / fs; wm8903->fs = params_rate(params); - wm8903_set_deemph(codec); + wm8903_set_deemph(component); - snd_soc_write(codec, WM8903_CLOCK_RATES_0, clock0); - snd_soc_write(codec, WM8903_CLOCK_RATES_1, clock1); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); - snd_soc_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1); + snd_soc_component_write(component, WM8903_CLOCK_RATES_0, clock0); + snd_soc_component_write(component, WM8903_CLOCK_RATES_1, clock1); + snd_soc_component_write(component, WM8903_AUDIO_INTERFACE_1, aif1); + snd_soc_component_write(component, WM8903_AUDIO_INTERFACE_2, aif2); + snd_soc_component_write(component, WM8903_AUDIO_INTERFACE_3, aif3); + snd_soc_component_write(component, WM8903_DAC_DIGITAL_1, dac_digital1); return 0; } @@ -1584,7 +1585,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, /** * wm8903_mic_detect - Enable microphone detection via the WM8903 IRQ * - * @codec: WM8903 codec + * @component: WM8903 component * @jack: jack to report detection events on * @det: value to report for presence detection * @shrt: value to report for short detection @@ -1598,13 +1599,13 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, * micdet_cfg in the platform data. Using this function will force on * the microphone bias for the device. */ -int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, +int wm8903_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack, int det, int shrt) { - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); int irq_mask = WM8903_MICDET_EINT | WM8903_MICSHRT_EINT; - dev_dbg(codec->dev, "Enabling microphone detection: %x %x\n", + dev_dbg(component->dev, "Enabling microphone detection: %x %x\n", det, shrt); /* Store the configuration */ @@ -1618,19 +1619,19 @@ int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, if (shrt) irq_mask &= ~WM8903_MICSHRT_EINT; - snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, + snd_soc_component_update_bits(component, WM8903_INTERRUPT_STATUS_1_MASK, WM8903_MICDET_EINT | WM8903_MICSHRT_EINT, irq_mask); if (det || shrt) { /* Enable mic detection, this may not have been set through * platform data (eg, if the defaults are OK). */ - snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, + snd_soc_component_update_bits(component, WM8903_WRITE_SEQUENCER_0, WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); - snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_MIC_BIAS_CONTROL_0, WM8903_MICDET_ENA, WM8903_MICDET_ENA); } else { - snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0, + snd_soc_component_update_bits(component, WM8903_MIC_BIAS_CONTROL_0, WM8903_MICDET_ENA, 0); } @@ -1735,9 +1736,10 @@ static irqreturn_t wm8903_irq(int irq, void *data) static const struct snd_soc_dai_ops wm8903_dai_ops = { .hw_params = wm8903_hw_params, - .digital_mute = wm8903_digital_mute, + .mute_stream = wm8903_mute, .set_fmt = wm8903_set_dai_fmt, .set_sysclk = wm8903_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8903_dai = { @@ -1757,33 +1759,19 @@ static struct snd_soc_dai_driver wm8903_dai = { .formats = WM8903_FORMATS, }, .ops = &wm8903_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; -static int wm8903_suspend(struct snd_soc_codec *codec) +static int wm8903_resume(struct snd_soc_component *component) { - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8903_resume(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + struct wm8903_priv *wm8903 = snd_soc_component_get_drvdata(component); regcache_sync(wm8903->regmap); - wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } #ifdef CONFIG_GPIOLIB -static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8903_priv, gpio_chip); -} - static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) { if (offset >= WM8903_NUM_GPIO) @@ -1794,7 +1782,7 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int mask, val; int ret; @@ -1812,18 +1800,18 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int reg; regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, ®); - return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; + return !!((reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT); } static int wm8903_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int mask, val; int ret; @@ -1839,16 +1827,18 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, return 0; } -static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int wm8903_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); - regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, - WM8903_GP1_LVL_MASK, - !!value << WM8903_GP1_LVL_SHIFT); + return regmap_update_bits(wm8903->regmap, + WM8903_GPIO_CONTROL_1 + offset, + WM8903_GP1_LVL_MASK, + !!value << WM8903_GP1_LVL_SHIFT); } -static struct gpio_chip wm8903_template_chip = { +static const struct gpio_chip wm8903_template_chip = { .label = "wm8903", .owner = THIS_MODULE, .request = wm8903_gpio_request, @@ -1866,25 +1856,21 @@ static void wm8903_init_gpio(struct wm8903_priv *wm8903) wm8903->gpio_chip = wm8903_template_chip; wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; - wm8903->gpio_chip.dev = wm8903->dev; + wm8903->gpio_chip.parent = wm8903->dev; if (pdata->gpio_base) wm8903->gpio_chip.base = pdata->gpio_base; else wm8903->gpio_chip.base = -1; - ret = gpiochip_add(&wm8903->gpio_chip); + ret = gpiochip_add_data(&wm8903->gpio_chip, wm8903); if (ret != 0) dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret); } static void wm8903_free_gpio(struct wm8903_priv *wm8903) { - int ret; - - ret = gpiochip_remove(&wm8903->gpio_chip); - if (ret != 0) - dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret); + gpiochip_remove(&wm8903->gpio_chip); } #else static void wm8903_init_gpio(struct wm8903_priv *wm8903) @@ -1896,47 +1882,20 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) } #endif -static int wm8903_probe(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int ret; - - wm8903->codec = codec; - codec->control_data = wm8903->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* power on device */ - wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; -} - -/* power down chip */ -static int wm8903_remove(struct snd_soc_codec *codec) -{ - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { - .probe = wm8903_probe, - .remove = wm8903_remove, - .suspend = wm8903_suspend, - .resume = wm8903_resume, - .set_bias_level = wm8903_set_bias_level, - .seq_notifier = wm8903_seq_notifier, - .controls = wm8903_snd_controls, - .num_controls = ARRAY_SIZE(wm8903_snd_controls), - .dapm_widgets = wm8903_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), - .dapm_routes = wm8903_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), +static const struct snd_soc_component_driver soc_component_dev_wm8903 = { + .resume = wm8903_resume, + .set_bias_level = wm8903_set_bias_level, + .seq_notifier = wm8903_seq_notifier, + .controls = wm8903_snd_controls, + .num_controls = ARRAY_SIZE(wm8903_snd_controls), + .dapm_widgets = wm8903_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), + .dapm_routes = wm8903_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; static const struct regmap_config wm8903_regmap = { @@ -1947,7 +1906,7 @@ static const struct regmap_config wm8903_regmap = { .volatile_reg = wm8903_volatile_register, .readable_reg = wm8903_readable_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm8903_reg_defaults, .num_reg_defaults = ARRAY_SIZE(wm8903_reg_defaults), }; @@ -1969,7 +1928,7 @@ static int wm8903_set_pdata_irq_trigger(struct i2c_client *i2c, * We assume the controller imposes no restrictions, * so we are able to select active-high */ - /* Fall-through */ + fallthrough; case IRQ_TYPE_LEVEL_HIGH: pdata->irq_active_low = false; break; @@ -2024,8 +1983,7 @@ static int wm8903_set_pdata_from_of(struct i2c_client *i2c, return 0; } -static int wm8903_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int wm8903_i2c_probe(struct i2c_client *i2c) { struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); struct wm8903_priv *wm8903; @@ -2034,10 +1992,11 @@ static int wm8903_i2c_probe(struct i2c_client *i2c, unsigned int val, irq_pol; int ret, i; - wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), - GFP_KERNEL); + wm8903 = devm_kzalloc(&i2c->dev, sizeof(*wm8903), GFP_KERNEL); if (wm8903 == NULL) return -ENOMEM; + + mutex_init(&wm8903->lock); wm8903->dev = &i2c->dev; wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); @@ -2054,13 +2013,10 @@ static int wm8903_i2c_probe(struct i2c_client *i2c, if (pdata) { wm8903->pdata = pdata; } else { - wm8903->pdata = devm_kzalloc(&i2c->dev, - sizeof(struct wm8903_platform_data), - GFP_KERNEL); - if (wm8903->pdata == NULL) { - dev_err(&i2c->dev, "Failed to allocate pdata\n"); + wm8903->pdata = devm_kzalloc(&i2c->dev, sizeof(*wm8903->pdata), + GFP_KERNEL); + if (!wm8903->pdata) return -ENOMEM; - } if (i2c->irq) { ret = wm8903_set_pdata_irq_trigger(i2c, wm8903->pdata); @@ -2077,6 +2033,23 @@ static int wm8903_i2c_probe(struct i2c_client *i2c, pdata = wm8903->pdata; + for (i = 0; i < ARRAY_SIZE(wm8903->supplies); i++) + wm8903->supplies[i].supply = wm8903_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8903->supplies), + wm8903->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(wm8903->supplies), + wm8903->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val); if (ret != 0) { dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); @@ -2160,7 +2133,7 @@ static int wm8903_i2c_probe(struct i2c_client *i2c, if (ret != 0) { dev_err(wm8903->dev, "Failed to request IRQ: %d\n", ret); - return ret; + goto err; } /* Enable write sequencer interrupts */ @@ -2200,26 +2173,27 @@ static int wm8903_i2c_probe(struct i2c_client *i2c, WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8903, &wm8903_dai, 1); + ret = devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_wm8903, &wm8903_dai, 1); if (ret != 0) goto err; return 0; err: + regulator_bulk_disable(ARRAY_SIZE(wm8903->supplies), + wm8903->supplies); return ret; } -static int wm8903_i2c_remove(struct i2c_client *client) +static void wm8903_i2c_remove(struct i2c_client *client) { struct wm8903_priv *wm8903 = i2c_get_clientdata(client); + regulator_bulk_disable(ARRAY_SIZE(wm8903->supplies), + wm8903->supplies); if (client->irq) free_irq(client->irq, wm8903); wm8903_free_gpio(wm8903); - snd_soc_unregister_codec(&client->dev); - - return 0; } static const struct of_device_id wm8903_of_match[] = { @@ -2229,7 +2203,7 @@ static const struct of_device_id wm8903_of_match[] = { MODULE_DEVICE_TABLE(of, wm8903_of_match); static const struct i2c_device_id wm8903_i2c_id[] = { - { "wm8903", 0 }, + { "wm8903" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); @@ -2237,7 +2211,6 @@ MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); static struct i2c_driver wm8903_i2c_driver = { .driver = { .name = "wm8903", - .owner = THIS_MODULE, .of_match_table = wm8903_of_match, }, .probe = wm8903_i2c_probe, |
