* [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches
@ 2011-06-08 13:50 Mark Brown
2011-06-08 13:50 ` [PATCH 2/6] ASoC: Factor out I2C usage in WM8962 driver Mark Brown
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Mark Brown @ 2011-06-08 13:50 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel, patches, Mark Brown
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm8962.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index f90ae42..5e05eed 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1999,12 +1999,12 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
return 0;
/* If the left PGA is enabled hit that VU bit... */
- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA)
+ if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA)
return snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
reg_cache[WM8962_HPOUTL_VOLUME]);
/* ...otherwise the right. The VU is stereo. */
- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA)
+ if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA)
return snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
reg_cache[WM8962_HPOUTR_VOLUME]);
--
1.7.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/6] ASoC: Factor out I2C usage in WM8962 driver
2011-06-08 13:50 [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Mark Brown
@ 2011-06-08 13:50 ` Mark Brown
2011-06-08 13:50 ` [PATCH 3/6] ASoC: Report errors when we have a WM8962 IRQ and don't get FLL lock Mark Brown
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2011-06-08 13:50 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel, patches, Mark Brown
The chip can actually support SPI so we shouldn't assume we've got an I2C
device even though that's the most common configuration.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm8962.c | 19 ++++++++++---------
1 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 5e05eed..a159453 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -78,6 +78,8 @@ struct wm8962_priv {
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
#endif
+
+ int irq;
};
/* We can't use the same notifier block for more than one supply and
@@ -3731,8 +3733,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
int ret;
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
- struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
- dev);
u16 *reg_cache = codec->reg_cache;
int i, trigger, irq_pol;
bool dmicclk, dmicdat;
@@ -3899,7 +3899,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
wm8962_init_beep(codec);
wm8962_init_gpio(codec);
- if (i2c->irq) {
+ if (wm8962->irq) {
if (pdata && pdata->irq_active_low) {
trigger = IRQF_TRIGGER_LOW;
irq_pol = WM8962_IRQ_POL;
@@ -3911,12 +3911,13 @@ static int wm8962_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
WM8962_IRQ_POL, irq_pol);
- ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq,
+ ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
trigger | IRQF_ONESHOT,
"wm8962", codec);
if (ret != 0) {
dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
- i2c->irq, ret);
+ wm8962->irq, ret);
+ wm8962->irq = 0;
/* Non-fatal */
} else {
/* Enable some IRQs by default */
@@ -3941,12 +3942,10 @@ err:
static int wm8962_remove(struct snd_soc_codec *codec)
{
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
- dev);
int i;
- if (i2c->irq)
- free_irq(i2c->irq, codec);
+ if (wm8962->irq)
+ free_irq(wm8962->irq, codec);
cancel_delayed_work_sync(&wm8962->mic_work);
@@ -3986,6 +3985,8 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8962);
+ wm8962->irq = i2c->irq;
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8962, &wm8962_dai, 1);
if (ret < 0)
--
1.7.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/6] ASoC: Report errors when we have a WM8962 IRQ and don't get FLL lock
2011-06-08 13:50 [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Mark Brown
2011-06-08 13:50 ` [PATCH 2/6] ASoC: Factor out I2C usage in WM8962 driver Mark Brown
@ 2011-06-08 13:50 ` Mark Brown
2011-06-08 13:50 ` [PATCH 4/6] ASoC: Implement base 5 band EQ control for WM8962 Mark Brown
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2011-06-08 13:50 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel, patches, Mark Brown
We really should be getting the interrupt - if we don't get one it's very
likely that the configuration is incorrect and audio will fail. Also
increase the timeout substantially in this case for safety.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm8962.c | 37 ++++++++++++++++++++++++++++++++-----
1 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index a159453..859e699 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2186,6 +2186,8 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ unsigned long timeout;
int src;
int fll;
@@ -2205,9 +2207,19 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- if (fll)
+ if (fll) {
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_ENA, WM8962_FLL_ENA);
+ if (wm8962->irq) {
+ timeout = msecs_to_jiffies(5);
+ timeout = wait_for_completion_timeout(&wm8962->fll_lock,
+ timeout);
+
+ if (timeout == 0)
+ dev_err(codec->dev,
+ "Timed out starting FLL\n");
+ }
+ }
break;
case SND_SOC_DAPM_POST_PMD:
@@ -3263,16 +3275,31 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
- /* This should be a massive overestimate */
- timeout = msecs_to_jiffies(1);
+ ret = 0;
+
+ if (fll1 & WM8962_FLL_ENA) {
+ /* This should be a massive overestimate but go even
+ * higher if we'll error out
+ */
+ if (wm8962->irq)
+ timeout = msecs_to_jiffies(5);
+ else
+ timeout = msecs_to_jiffies(1);
+
+ timeout = wait_for_completion_timeout(&wm8962->fll_lock,
+ timeout);
- wait_for_completion_timeout(&wm8962->fll_lock, timeout);
+ if (timeout == 0 && wm8962->irq) {
+ dev_err(codec->dev, "FLL lock timed out");
+ ret = -ETIMEDOUT;
+ }
+ }
wm8962->fll_fref = Fref;
wm8962->fll_fout = Fout;
wm8962->fll_src = source;
- return 0;
+ return ret;
}
static int wm8962_mute(struct snd_soc_dai *dai, int mute)
--
1.7.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/6] ASoC: Implement base 5 band EQ control for WM8962
2011-06-08 13:50 [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Mark Brown
2011-06-08 13:50 ` [PATCH 2/6] ASoC: Factor out I2C usage in WM8962 driver Mark Brown
2011-06-08 13:50 ` [PATCH 3/6] ASoC: Report errors when we have a WM8962 IRQ and don't get FLL lock Mark Brown
@ 2011-06-08 13:50 ` Mark Brown
2011-06-08 13:50 ` [PATCH 5/6] ASoC: Defer all WM8962 clocking configuration until power up Mark Brown
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2011-06-08 13:50 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel, patches, Mark Brown
ReTune Mobile modes are not currently supported.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm8962.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 859e699..56934d3 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1984,6 +1984,7 @@ static const unsigned int classd_tlv[] = {
0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
};
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
/* The VU bits for the headphones are in a different register to the mute
* bits and only take effect on the PGA if it is actually powered.
@@ -2121,6 +2122,18 @@ SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4,
SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0,
classd_tlv),
+
+SOC_SINGLE("EQ Switch", WM8962_EQ1, WM8962_EQ_ENA_SHIFT, 1, 0),
+SOC_DOUBLE_R_TLV("EQ1 Volume", WM8962_EQ2, WM8962_EQ22,
+ WM8962_EQL_B1_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ2 Volume", WM8962_EQ2, WM8962_EQ22,
+ WM8962_EQL_B2_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ3 Volume", WM8962_EQ2, WM8962_EQ22,
+ WM8962_EQL_B3_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23,
+ WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
+ WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),
};
static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@@ -3898,6 +3911,9 @@ static int wm8962_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
WM8962_HPOUT_VU, WM8962_HPOUT_VU);
+ /* Stereo control for EQ */
+ snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0);
+
wm8962_add_widgets(codec);
/* Save boards having to disable DMIC when not in use */
--
1.7.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/6] ASoC: Defer all WM8962 clocking configuration until power up
2011-06-08 13:50 [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Mark Brown
` (2 preceding siblings ...)
2011-06-08 13:50 ` [PATCH 4/6] ASoC: Implement base 5 band EQ control for WM8962 Mark Brown
@ 2011-06-08 13:50 ` Mark Brown
2011-06-08 13:50 ` [PATCH 6/6] ASoC: Support Speyside build variants with WM8962 fitted Mark Brown
2011-06-08 14:15 ` [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Liam Girdwood
5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2011-06-08 13:50 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel, patches, Mark Brown
Don't require an audio rate SYSCLK in hw_params() in order to better
support microphone detection use cases.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm8962.c | 60 ++++++++++++++++++++++++--------------------
1 files changed, 33 insertions(+), 27 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 56934d3..8499c56 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2790,18 +2790,44 @@ static const int bclk_divs[] = {
1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
};
+static const int sysclk_rates[] = {
+ 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+};
+
static void wm8962_configure_bclk(struct snd_soc_codec *codec)
{
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
int dspclk, i;
int clocking2 = 0;
+ int clocking4 = 0;
int aif2 = 0;
- if (!wm8962->bclk) {
- dev_dbg(codec->dev, "No BCLK rate configured\n");
+ if (!wm8962->sysclk_rate) {
+ dev_dbg(codec->dev, "No SYSCLK configured\n");
return;
}
+ if (!wm8962->bclk || !wm8962->lrclk) {
+ dev_dbg(codec->dev, "No audio clocks configured\n");
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
+ if (sysclk_rates[i] == wm8962->sysclk_rate / wm8962->lrclk) {
+ clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(sysclk_rates)) {
+ dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
+ wm8962->sysclk_rate / wm8962->lrclk);
+ return;
+ }
+
+ snd_soc_update_bits(codec, WM8962_CLOCKING_4,
+ WM8962_SYSCLK_RATE_MASK, clocking4);
+
dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
if (dspclk < 0) {
dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
@@ -2871,6 +2897,8 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
/* VMID 2*50k */
snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
WM8962_VMID_SEL_MASK, 0x80);
+
+ wm8962_configure_bclk(codec);
break;
case SND_SOC_BIAS_STANDBY:
@@ -2903,8 +2931,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, WM8962_CLOCKING2,
WM8962_CLKREG_OVD,
WM8962_CLKREG_OVD);
-
- wm8962_configure_bclk(codec);
}
/* VMID 2*250k */
@@ -2945,10 +2971,6 @@ static const struct {
{ 96000, 6 },
};
-static const int sysclk_rates[] = {
- 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
-};
-
static int wm8962_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -2956,41 +2978,27 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- int rate = params_rate(params);
int i;
int aif0 = 0;
int adctl3 = 0;
- int clocking4 = 0;
wm8962->bclk = snd_soc_params_to_bclk(params);
wm8962->lrclk = params_rate(params);
for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
- if (sr_vals[i].rate == rate) {
+ if (sr_vals[i].rate == wm8962->lrclk) {
adctl3 |= sr_vals[i].reg;
break;
}
}
if (i == ARRAY_SIZE(sr_vals)) {
- dev_err(codec->dev, "Unsupported rate %dHz\n", rate);
+ dev_err(codec->dev, "Unsupported rate %dHz\n", wm8962->lrclk);
return -EINVAL;
}
- if (rate % 8000 == 0)
+ if (wm8962->lrclk % 8000 == 0)
adctl3 |= WM8962_SAMPLE_RATE_INT_MODE;
- for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
- if (sysclk_rates[i] == wm8962->sysclk_rate / rate) {
- clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
- break;
- }
- }
- if (i == ARRAY_SIZE(sysclk_rates)) {
- dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
- wm8962->sysclk_rate / rate);
- return -EINVAL;
- }
-
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
break;
@@ -3012,8 +3020,6 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3,
WM8962_SAMPLE_RATE_INT_MODE |
WM8962_SAMPLE_RATE_MASK, adctl3);
- snd_soc_update_bits(codec, WM8962_CLOCKING_4,
- WM8962_SYSCLK_RATE_MASK, clocking4);
wm8962_configure_bclk(codec);
--
1.7.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/6] ASoC: Support Speyside build variants with WM8962 fitted
2011-06-08 13:50 [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Mark Brown
` (3 preceding siblings ...)
2011-06-08 13:50 ` [PATCH 5/6] ASoC: Defer all WM8962 clocking configuration until power up Mark Brown
@ 2011-06-08 13:50 ` Mark Brown
2011-06-08 14:15 ` [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Liam Girdwood
5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2011-06-08 13:50 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel, patches, Mark Brown
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
sound/soc/samsung/Kconfig | 6 +
sound/soc/samsung/Makefile | 2 +
sound/soc/samsung/speyside_wm8962.c | 260 +++++++++++++++++++++++++++++++++++
3 files changed, 268 insertions(+), 0 deletions(-)
create mode 100644 sound/soc/samsung/speyside_wm8962.c
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index d155cbb..b5d7c0d 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -177,3 +177,9 @@ config SND_SOC_SPEYSIDE
select SND_SAMSUNG_I2S
select SND_SOC_WM8915
select SND_SOC_WM9081
+
+config SND_SOC_SPEYSIDE_WM8962
+ tristate "Audio support for Wolfson Speyside with WM8962"
+ depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+ select SND_SAMSUNG_I2S
+ select SND_SOC_WM8962
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 683843a..e04df65 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -36,6 +36,7 @@ snd-soc-goni-wm8994-objs := goni_wm8994.o
snd-soc-smdk-spdif-objs := smdk_spdif.o
snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
snd-soc-speyside-objs := speyside.o
+snd-soc-speyside-wm8962-objs := speyside_wm8962.o
obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -55,3 +56,4 @@ obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o
obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o
obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o
obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o
+obj-$(CONFIG_SND_SOC_SPEYSIDE_WM8962) += snd-soc-speyside-wm8962.o
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/speyside_wm8962.c
new file mode 100644
index 0000000..c0ba0bf
--- /dev/null
+++ b/sound/soc/samsung/speyside_wm8962.c
@@ -0,0 +1,260 @@
+/*
+ * Speyside with WM8962 audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+
+#include "../codecs/wm8962.h"
+
+static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
+ enum snd_soc_bias_level level)
+{
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_PREPARE:
+ if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+ ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
+ WM8962_FLL_MCLK, 32768,
+ 44100 * 256);
+ if (ret < 0)
+ pr_err("Failed to start FLL\n");
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ WM8962_SYSCLK_FLL,
+ 44100 * 256,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
+ enum snd_soc_bias_level level)
+{
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
+ 32768, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
+ 0, 0, 0);
+ if (ret < 0) {
+ pr_err("Failed to stop FLL\n");
+ return ret;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ dapm->bias_level = level;
+
+ return 0;
+}
+
+static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops speyside_wm8962_ops = {
+ .hw_params = speyside_wm8962_hw_params,
+};
+
+static struct snd_soc_dai_link speyside_wm8962_dai[] = {
+ {
+ .name = "CPU",
+ .stream_name = "CPU",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "wm8962",
+ .platform_name = "samsung-audio",
+ .codec_name = "wm8962.1-001a",
+ .ops = &speyside_wm8962_ops,
+ },
+};
+
+static const struct snd_kcontrol_new controls[] = {
+ SOC_DAPM_PIN_SWITCH("Main Speaker"),
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+
+ SND_SOC_DAPM_MIC("DMIC", NULL),
+
+ SND_SOC_DAPM_SPK("Main Speaker", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+ { "Headphone", NULL, "HPOUTL" },
+ { "Headphone", NULL, "HPOUTR" },
+
+ { "Main Speaker", NULL, "SPKOUTL" },
+ { "Main Speaker", NULL, "SPKOUTR" },
+
+ { "MICBIAS", NULL, "Headset Mic" },
+ { "IN4L", NULL, "MICBIAS" },
+ { "IN4R", NULL, "MICBIAS" },
+
+ { "MICBIAS", NULL, "DMIC" },
+ { "DMICDAT", NULL, "MICBIAS" },
+};
+
+static struct snd_soc_jack speyside_wm8962_headset;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin speyside_wm8962_headset_pins[] = {
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+ {
+ .pin = "Headphone",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+
+static int speyside_wm8962_late_probe(struct snd_soc_card *card)
+{
+ struct snd_soc_codec *codec = card->rtd[0].codec;
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
+ 32768, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_jack_new(codec, "Headset",
+ SND_JACK_HEADSET | SND_JACK_BTN_0,
+ &speyside_wm8962_headset);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_jack_add_pins(&speyside_wm8962_headset,
+ ARRAY_SIZE(speyside_wm8962_headset_pins),
+ speyside_wm8962_headset_pins);
+ if (ret)
+ return ret;
+
+ wm8962_mic_detect(codec, &speyside_wm8962_headset);
+
+ return 0;
+}
+
+static struct snd_soc_card speyside_wm8962 = {
+ .name = "Speyside WM8962",
+ .dai_link = speyside_wm8962_dai,
+ .num_links = ARRAY_SIZE(speyside_wm8962_dai),
+
+ .set_bias_level = speyside_wm8962_set_bias_level,
+ .set_bias_level_post = speyside_wm8962_set_bias_level_post,
+
+ .controls = controls,
+ .num_controls = ARRAY_SIZE(controls),
+ .dapm_widgets = widgets,
+ .num_dapm_widgets = ARRAY_SIZE(widgets),
+ .dapm_routes = audio_paths,
+ .num_dapm_routes = ARRAY_SIZE(audio_paths),
+
+ .late_probe = speyside_wm8962_late_probe,
+};
+
+static __devinit int speyside_wm8962_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &speyside_wm8962;
+ int ret;
+
+ card->dev = &pdev->dev;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devexit speyside_wm8962_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver speyside_wm8962_driver = {
+ .driver = {
+ .name = "speyside-wm8962",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = speyside_wm8962_probe,
+ .remove = __devexit_p(speyside_wm8962_remove),
+};
+
+static int __init speyside_wm8962_audio_init(void)
+{
+ return platform_driver_register(&speyside_wm8962_driver);
+}
+module_init(speyside_wm8962_audio_init);
+
+static void __exit speyside_wm8962_audio_exit(void)
+{
+ platform_driver_unregister(&speyside_wm8962_driver);
+}
+module_exit(speyside_wm8962_audio_exit);
+
+MODULE_DESCRIPTION("Speyside WM8962 audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:speyside-wm8962");
--
1.7.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches
2011-06-08 13:50 [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Mark Brown
` (4 preceding siblings ...)
2011-06-08 13:50 ` [PATCH 6/6] ASoC: Support Speyside build variants with WM8962 fitted Mark Brown
@ 2011-06-08 14:15 ` Liam Girdwood
5 siblings, 0 replies; 7+ messages in thread
From: Liam Girdwood @ 2011-06-08 14:15 UTC (permalink / raw)
To: Mark Brown
Cc: alsa-devel@alsa-project.org, patches@opensource.wolfsonmicro.com
On 08/06/11 14:50, Mark Brown wrote:
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> ---
All
Acked-by: Liam Girdwood <lrg@ti.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-06-08 14:15 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-08 13:50 [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Mark Brown
2011-06-08 13:50 ` [PATCH 2/6] ASoC: Factor out I2C usage in WM8962 driver Mark Brown
2011-06-08 13:50 ` [PATCH 3/6] ASoC: Report errors when we have a WM8962 IRQ and don't get FLL lock Mark Brown
2011-06-08 13:50 ` [PATCH 4/6] ASoC: Implement base 5 band EQ control for WM8962 Mark Brown
2011-06-08 13:50 ` [PATCH 5/6] ASoC: Defer all WM8962 clocking configuration until power up Mark Brown
2011-06-08 13:50 ` [PATCH 6/6] ASoC: Support Speyside build variants with WM8962 fitted Mark Brown
2011-06-08 14:15 ` [PATCH 1/6] ASoC: Fix WM8962 headphone volume update for use of advanced caches Liam Girdwood
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).