summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/arizona.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-14 11:14:28 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-14 11:14:28 -0800
commitce38207f161513ee3d2bd3860489f07ebe65bc78 (patch)
treeb3ad9e8a5e087b91d9f30a314c55df5fa70c142e /sound/soc/codecs/arizona.c
parenta9042defa29a01cc538b742eab047848e9b5ae14 (diff)
parent995c6a7fd9b9212abdf01160f6ce3193176be503 (diff)
Merge tag 'sound-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "No dramatic changes are found in this development cycle, but as usual, many commits are applied in a wide range of drivers. Most of big changes are in ASoC, where a few bits of framework work and quite a lot of cleanups and improvements to existing code have been done. The rest are usual stuff, a few HD-audio and USB-audio quirks and fixes, as well as the drop of kthread usages in the whole subsystem. Below are some highlights: ASoC: - support for stereo DAPM controls - some initial work on the of-graph sound card - regmap conversions of the remaining AC'97 drivers - a new version of the topology ABI; this should be backward compatible - updates / cleanups of rsnd, sunxi, sti, nau8825, samsung, arizona, Intel skylake, atom-sst - new drivers for Cirrus Logic CS42L42, Qualcomm MSM8916-WCD, and Realtek RT5665 USB-audio: - yet another race fix at disconnection - tolerated packet size calculation for some Android devices - quirks for Axe-Fx II, QuickCam, TEAC 501/503 HD-audio: - improvement of Dell pin fixup mapping - quirks for HP Z1 Gen3, Alienware 15 R2 2016 and ALC622 headset mic Misc: - replace all kthread usages with simple works" * tag 'sound-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (296 commits) ALSA: hiface: Fix M2Tech hiFace driver sampling rate change ALSA: usb-audio: Eliminate noise at the start of DSD playback. ALSA: usb-audio: Add native DSD support for TEAC 501/503 DAC ASoC: wm_adsp: wm_adsp_buf_alloc should use kfree in error path ASoC: topology: avoid uninitialized kcontrol_type ALSA: usb-audio: Add QuickCam Communicate Deluxe/S7500 to volume_control_quirks ALSA: usb-audio: add implicit fb quirk for Axe-Fx II ASoC: zte: spdif: correct ZX_SPDIF_CLK_RAT define ASoC: zte: spdif and i2s drivers are not zx296702 specific ASoC: rsnd: setup BRGCKR/BRRA/BRRB when starting ASoC: rsnd: enable/disable ADG when suspend/resume timing ASoC: rsnd: tidyup ssi->usrcnt counter check in hw_params ALSA: cs46xx: add a new line ASoC: Intel: update bxt_da7219_max98357a to support quad ch dmic capture ASoC: nau8825: disable sinc filter for high THD of ADC ALSA: usb-audio: more tolerant packetsize ALSA: usb-audio: avoid setting of sample rate multiple times on bus ASoC: cs35l34: Simplify the logic to set CS35L34_MCLK_CTL setting ALSA: hda - Gate the mic jack on HP Z1 Gen3 AiO ALSA: hda: when comparing pin configurations, ignore assoc in addition to seq ...
Diffstat (limited to 'sound/soc/codecs/arizona.c')
-rw-r--r--sound/soc/codecs/arizona.c153
1 files changed, 113 insertions, 40 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 846ca079845f..0a734d910850 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -191,6 +191,14 @@ int arizona_init_spk(struct snd_soc_codec *codec)
break;
}
+ return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_spk);
+
+int arizona_init_spk_irqs(struct arizona *arizona)
+{
+ int ret;
+
ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN,
"Thermal warning", arizona_thermal_warn,
arizona);
@@ -209,19 +217,16 @@ int arizona_init_spk(struct snd_soc_codec *codec)
return 0;
}
-EXPORT_SYMBOL_GPL(arizona_init_spk);
+EXPORT_SYMBOL_GPL(arizona_init_spk_irqs);
-int arizona_free_spk(struct snd_soc_codec *codec)
+int arizona_free_spk_irqs(struct arizona *arizona)
{
- struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
- struct arizona *arizona = priv->arizona;
-
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT, arizona);
return 0;
}
-EXPORT_SYMBOL_GPL(arizona_free_spk);
+EXPORT_SYMBOL_GPL(arizona_free_spk_irqs);
static const struct snd_soc_dapm_route arizona_mono_routes[] = {
{ "OUT1R", NULL, "OUT1L" },
@@ -252,6 +257,7 @@ EXPORT_SYMBOL_GPL(arizona_init_mono);
int arizona_init_gpio(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+ struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
int i;
@@ -259,21 +265,24 @@ int arizona_init_gpio(struct snd_soc_codec *codec)
switch (arizona->type) {
case WM5110:
case WM8280:
- snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity");
+ snd_soc_component_disable_pin(component,
+ "DRC2 Signal Activity");
break;
default:
break;
}
- snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity");
+ snd_soc_component_disable_pin(component, "DRC1 Signal Activity");
for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
- snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity");
+ snd_soc_component_enable_pin(component,
+ "DRC1 Signal Activity");
break;
case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
- snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity");
+ snd_soc_component_enable_pin(component,
+ "DRC2 Signal Activity");
break;
default:
break;
@@ -1233,6 +1242,46 @@ static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
return -EINVAL;
}
+int arizona_clk_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);
+ unsigned int val;
+ int clk_idx;
+ int ret;
+
+ ret = regmap_read(arizona->regmap, w->reg, &val);
+ if (ret) {
+ dev_err(codec->dev, "Failed to check clock source: %d\n", ret);
+ return ret;
+ }
+
+ val = (val & ARIZONA_SYSCLK_SRC_MASK) >> ARIZONA_SYSCLK_SRC_SHIFT;
+
+ switch (val) {
+ case ARIZONA_CLK_SRC_MCLK1:
+ clk_idx = ARIZONA_MCLK1;
+ break;
+ case ARIZONA_CLK_SRC_MCLK2:
+ clk_idx = ARIZONA_MCLK2;
+ break;
+ default:
+ return 0;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return clk_prepare_enable(arizona->mclk[clk_idx]);
+ case SND_SOC_DAPM_POST_PMD:
+ clk_disable_unprepare(arizona->mclk[clk_idx]);
+ return 0;
+ default:
+ return 0;
+ }
+}
+EXPORT_SYMBOL_GPL(arizona_clk_ev);
+
int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir)
{
@@ -2242,6 +2291,42 @@ static int arizona_is_enabled_fll(struct arizona_fll *fll, int base)
return reg & ARIZONA_FLL1_ENA;
}
+static int arizona_set_fll_clks(struct arizona_fll *fll, int base, bool ena)
+{
+ struct arizona *arizona = fll->arizona;
+ unsigned int val;
+ struct clk *clk;
+ int ret;
+
+ ret = regmap_read(arizona->regmap, base + 6, &val);
+ if (ret != 0) {
+ arizona_fll_err(fll, "Failed to read current source: %d\n",
+ ret);
+ return ret;
+ }
+
+ val &= ARIZONA_FLL1_CLK_REF_SRC_MASK;
+ val >>= ARIZONA_FLL1_CLK_REF_SRC_SHIFT;
+
+ switch (val) {
+ case ARIZONA_FLL_SRC_MCLK1:
+ clk = arizona->mclk[ARIZONA_MCLK1];
+ break;
+ case ARIZONA_FLL_SRC_MCLK2:
+ clk = arizona->mclk[ARIZONA_MCLK2];
+ break;
+ default:
+ return 0;
+ }
+
+ if (ena) {
+ return clk_prepare_enable(clk);
+ } else {
+ clk_disable_unprepare(clk);
+ return 0;
+ }
+}
+
static int arizona_enable_fll(struct arizona_fll *fll)
{
struct arizona *arizona = fll->arizona;
@@ -2264,6 +2349,10 @@ static int arizona_enable_fll(struct arizona_fll *fll)
udelay(32);
regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
ARIZONA_FLL1_GAIN_MASK, 0);
+
+ if (arizona_is_enabled_fll(fll, fll->base + 0x10) > 0)
+ arizona_set_fll_clks(fll, fll->base + 0x10, false);
+ arizona_set_fll_clks(fll, fll->base, false);
}
/*
@@ -2318,10 +2407,13 @@ static int arizona_enable_fll(struct arizona_fll *fll)
if (!already_enabled)
pm_runtime_get_sync(arizona->dev);
- if (use_sync)
+ if (use_sync) {
+ arizona_set_fll_clks(fll, fll->base + 0x10, true);
regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA,
ARIZONA_FLL1_SYNC_ENA);
+ }
+ arizona_set_fll_clks(fll, fll->base, true);
regmap_update_bits_async(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
@@ -2354,19 +2446,24 @@ static int arizona_enable_fll(struct arizona_fll *fll)
static void arizona_disable_fll(struct arizona_fll *fll)
{
struct arizona *arizona = fll->arizona;
- bool change;
+ bool ref_change, sync_change;
regmap_update_bits_async(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
regmap_update_bits_check(arizona->regmap, fll->base + 1,
- ARIZONA_FLL1_ENA, 0, &change);
- regmap_update_bits(arizona->regmap, fll->base + 0x11,
- ARIZONA_FLL1_SYNC_ENA, 0);
+ ARIZONA_FLL1_ENA, 0, &ref_change);
+ regmap_update_bits_check(arizona->regmap, fll->base + 0x11,
+ ARIZONA_FLL1_SYNC_ENA, 0, &sync_change);
regmap_update_bits_async(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_FREERUN, 0);
- if (change)
+ if (sync_change)
+ arizona_set_fll_clks(fll, fll->base + 0x10, false);
+
+ if (ref_change) {
+ arizona_set_fll_clks(fll, fll->base, false);
pm_runtime_put_autosuspend(arizona->dev);
+ }
}
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
@@ -2598,30 +2695,6 @@ int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
-int arizona_register_notifier(struct snd_soc_codec *codec,
- struct notifier_block *nb,
- int (*notify)(struct notifier_block *nb,
- unsigned long action, void *data))
-{
- struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
- struct arizona *arizona = priv->arizona;
-
- nb->notifier_call = notify;
-
- return blocking_notifier_chain_register(&arizona->notifier, nb);
-}
-EXPORT_SYMBOL_GPL(arizona_register_notifier);
-
-int arizona_unregister_notifier(struct snd_soc_codec *codec,
- struct notifier_block *nb)
-{
- struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
- struct arizona *arizona = priv->arizona;
-
- return blocking_notifier_chain_unregister(&arizona->notifier, nb);
-}
-EXPORT_SYMBOL_GPL(arizona_unregister_notifier);
-
MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");