Skip to contentSkip to conversation

ASoC for moorestown

PATCH Superseded Lu Guanqun 5 participants 60 messages May 4, 2011 – May 6, 2011

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Lu Guanqun

author
#0 lore raw

cover ASoC for moorestown

This series of patches provides the ASoC implementation of moorestown audio.

This series adds a new codec called upd9976 and a new machine driver called mrst_machine. The platform driver is mostly re-used.

With this patchset, it can do:
- playback via headphone
- playback via internal speaker
- capture via DMIC
- capture via headset microphone
- jack detection

However, other functionalities such as voice support in uPD9976 codec is not implemented yet. This patchset mainly focuses on the audio support in uPD9976 codec.

Any comments are welcome.

---

Lu Guanqun (17):
ASoC: upd9976: Add Renesas uPD9976 codec driver
ASoC: sst_platform: add cpu dai driver for moorestown platform
ASoC: mrst_machine: add moorestown machine driver
ASoC: mrst_machine: add speaker widget to moorestown machine driver
ASoC: mrst_machine: enable user to select different output
ASoC: upd9976: add DMIC support
ASoC: upd9976: add Analog MIC support
ASoC: upd9976: add microphone bias support
ASoC: upd9976: add jack detection function
ASoC: mrst_machine: add capture functionality
ASoC: mrst_machine: add jack detection support
ASoC: upd9976: add mute switch for DMIC
ASoC: upd9976: add mute switch for analog
ASoC: mrst_machine: make DMIC's output to PCM2 mono
ASoC: mrst_machine: make MIC2 pseudo-differential
ASoC: upd9976: add capture volume for analog inputs
ASoC: upd9976: add capture volume for DMIC

Wang Xingchao (2):
ASoC: upd9976: add capture ability for dai driver
ASoC: sst_platform: add capture capability for cpu dai driver

 sound/soc/codecs/Kconfig         |    4 
 sound/soc/codecs/Makefile        |    2 
 sound/soc/codecs/upd9976.c       |  569 ++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/upd9976.h       |   85 ++++++
 sound/soc/mid-x86/Kconfig        |   12 +
 sound/soc/mid-x86/Makefile       |    2 
 sound/soc/mid-x86/mrst_machine.c |  365 ++++++++++++++++++++++++
 sound/soc/mid-x86/sst_platform.c |   20 +
 8 files changed, 1059 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/codecs/upd9976.c
 create mode 100644 sound/soc/codecs/upd9976.h
 create mode 100644 sound/soc/mid-x86/mrst_machine.c
Signature · 1 line
guanqun
author
#1 lore raw

PATCH 1/19 ASoC: upd9976: Add Renesas uPD9976 codec driver

uPD9976 is a complex codec, however this patch only provides basic playback functionality for headphone. More functionality will be added bit by bit in the following patches.

---
 sound/soc/codecs/Kconfig   |    4 
 sound/soc/codecs/Makefile  |    2 
 sound/soc/codecs/upd9976.c |  407 ++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/upd9976.h |   83 +++++++++
 4 files changed, 496 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/codecs/upd9976.c
 create mode 100644 sound/soc/codecs/upd9976.h
sound/soc/codecs/Kconfig +4 -0
index 2a69718..b914bc6 100644
@@ -52,6 +52,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_TWL6040 if TWL4030_CORE
 	select SND_SOC_UDA134X
 	select SND_SOC_UDA1380 if I2C
+	select SND_SOC_UPD9976 if INTEL_SCU_IPC
 	select SND_SOC_WL1273 if MFD_WL1273_CORE
 	select SND_SOC_WM1250_EV1 if I2C
 	select SND_SOC_WM2000 if I2C
@@ -244,6 +245,9 @@ config SND_SOC_UDA134X
 config SND_SOC_UDA1380
         tristate
 
+config SND_SOC_UPD9976
+	tristate
+
 config SND_SOC_WL1273
 	tristate
 
sound/soc/codecs/Makefile +2 -0
index 4cb2f42..163c623 100644
@@ -37,6 +37,7 @@ snd-soc-twl4030-objs := twl4030.o
 snd-soc-twl6040-objs := twl6040.o
 snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
+snd-soc-upd9976-objs := upd9976.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm8350-objs := wm8350.o
@@ -128,6 +129,7 @@ obj-$(CONFIG_SND_SOC_TWL4030)	+= snd-soc-twl4030.o
 obj-$(CONFIG_SND_SOC_TWL6040)	+= snd-soc-twl6040.o
 obj-$(CONFIG_SND_SOC_UDA134X)	+= snd-soc-uda134x.o
 obj-$(CONFIG_SND_SOC_UDA1380)	+= snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_UPD9976)	+= snd-soc-upd9976.o
 obj-$(CONFIG_SND_SOC_WL1273)	+= snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
 obj-$(CONFIG_SND_SOC_WM8350)	+= snd-soc-wm8350.o
sound/soc/codecs/upd9976.c new file +407 -0

407 lines not on this page · raw message

sound/soc/codecs/upd9976.h new file +83 -0

83 lines not on this page · raw message

#2 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

On Wed, May 04, 2011 at 09:44:58PM +0800, Lu Guanqun wrote:

Overall this looks very good, a few minor points below.

sound/soc/codecs/upd9976.c line 42

Quoted 3 lines
sound/soc/codecs/upd9976.c new file +3 -0
+static inline unsigned int upd9976_read(struct snd_soc_codec *codec,
+					unsigned int reg)
+{

I guess these SCU write functions are going to be shared with other CODECs for this CPU - we should probably push this into the soc-cache for them.

sound/soc/codecs/upd9976.c line 69

Quoted 2 lines
sound/soc/codecs/upd9976.c new file +2 -0
+static const struct snd_kcontrol_new upd9976_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",

Master Volume would be a better name.

sound/soc/codecs/upd9976.c line 76

Quoted 3 lines
sound/soc/codecs/upd9976.c new file +3 -0
+static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_left_controls[] = {
+	SOC_DAPM_SINGLE("Audio DAC Left", UPD9976_HPLMIXSEL, 4, 1, 1),
+	SOC_DAPM_SINGLE("Audio DAC Right", UPD9976_HPLMIXSEL, 3, 1, 1),

These need Switch at the end of the name.

sound/soc/codecs/upd9976.c line 297

Quoted 4 lines
sound/soc/codecs/upd9976.c new file +4 -0
+static struct snd_soc_dai_driver upd9976_dais[] = {
+{
+	.name = "upd9976-audio",
+	.playback = {

Just drop the audio from the name, it's a CODEC so it's obviously audio.

author
#3 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 11 lines · Mark Brown

On Wed, May 04, 2011 at 09:44:58PM +0800, Lu Guanqun wrote:

Overall this looks very good, a few minor points below.

sound/soc/codecs/upd9976.c line 42

Quoted 3 lines
sound/soc/codecs/upd9976.c new file +3 -0
+static inline unsigned int upd9976_read(struct snd_soc_codec *codec,
+					unsigned int reg)
+{

I guess these SCU write functions are going to be shared with other CODECs for this CPU - we should probably push this into the soc-cache for them.

Yes, currently it's the same read/write operation as in sn95031 codec.

Quoted 5 lines

sound/soc/codecs/upd9976.c line 69

Quoted 3 lines
sound/soc/codecs/upd9976.c new file +2 -0
+static const struct snd_kcontrol_new upd9976_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",

Master Volume would be a better name.

OK. I was trying to be more clear on what this volume represents.

Quoted 6 lines

sound/soc/codecs/upd9976.c line 76

Quoted 4 lines
sound/soc/codecs/upd9976.c new file +3 -0
+static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_left_controls[] = {
+	SOC_DAPM_SINGLE("Audio DAC Left", UPD9976_HPLMIXSEL, 4, 1, 1),
+	SOC_DAPM_SINGLE("Audio DAC Right", UPD9976_HPLMIXSEL, 3, 1, 1),

These need Switch at the end of the name.

OK.

Quoted 7 lines

sound/soc/codecs/upd9976.c line 297

Quoted 5 lines
sound/soc/codecs/upd9976.c new file +4 -0
+static struct snd_soc_dai_driver upd9976_dais[] = {
+{
+	.name = "upd9976-audio",
+	.playback = {

Just drop the audio from the name, it's a CODEC so it's obviously audio.

OK. Thanks for the review.

Signature · 1 line
guanqun
#4 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 13 lines · Guanqun
Quoted 11 lines · Mark Brown

On Wed, May 04, 2011 at 09:44:58PM +0800, Lu Guanqun wrote:

Overall this looks very good, a few minor points below.

sound/soc/codecs/upd9976.c line 42

Quoted 3 lines
sound/soc/codecs/upd9976.c new file +3 -0
+static inline unsigned int upd9976_read(struct snd_soc_codec *codec,
+					unsigned int reg)
+{

I guess these SCU write functions are going to be shared with other CODECs for this CPU - we should probably push this into the soc-cache for them.

Quoted 1 line

Yes, currently it's the same read/write operation as in sn95031 codec.

I would not do that yet, as I don't see any more codecs using this interface today or in near future :)

Signature · 1 line
~Vinod
author
#5 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 14 lines · Vinod
Quoted 13 lines · Guanqun
Quoted 11 lines · Mark Brown

On Wed, May 04, 2011 at 09:44:58PM +0800, Lu Guanqun wrote:

Overall this looks very good, a few minor points below.

sound/soc/codecs/upd9976.c line 42

Quoted 3 lines
sound/soc/codecs/upd9976.c new file +3 -0
+static inline unsigned int upd9976_read(struct snd_soc_codec *codec,
+					unsigned int reg)
+{

I guess these SCU write functions are going to be shared with other CODECs for this CPU - we should probably push this into the soc-cache for them.

Quoted 3 lines
Quoted 1 line

Yes, currently it's the same read/write operation as in sn95031 codec.

I would not do that yet, as I don't see any more codecs using this interface today or in near future :)

In this series of patches, I'll not refactor them out and turn them into some common code. We can do it later when it's necessary.

Signature · 1 line
guanqun
#6 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

In reply to Mark Brown

At Wed, 4 May 2011 15:34:51 +0100,

Quoted 7 lines · Mark Brown

sound/soc/codecs/upd9976.c line 69

Quoted 2 lines · Lu Guanqun
sound/soc/codecs/upd9976.c new file +2 -0
+static const struct snd_kcontrol_new upd9976_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",

Master Volume would be a better name.

Yes, also in general, try to avoid special letters like "&".

Takashi

author
#7 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 11 lines · Takashi Iwai

At Wed, 4 May 2011 15:34:51 +0100,

Quoted 7 lines · Mark Brown

sound/soc/codecs/upd9976.c line 69

Quoted 2 lines · Lu Guanqun
sound/soc/codecs/upd9976.c new file +2 -0
+static const struct snd_kcontrol_new upd9976_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",

Master Volume would be a better name.

Yes, also in general, try to avoid special letters like "&".

I once used letter "/", but then it failed to create the corresponding debugfs directory... :)

Oh, btw: There are another register that's related to volume control, it's before DAC (not added in this patchset yet, for simplicity, will add it later). so the connection looks something like this:

[volume gain A] --> [DAC] --> [Mixer Volume] -> [Output Pins]

Which volume control should be the master volume? I'm a bit unclear on this one.

Signature · 1 line
guanqun
#8 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

At Wed, 4 May 2011 23:18:27 +0800,

Quoted 12 lines · Lu Guanqun
Quoted 10 lines · Takashi Iwai

At Wed, 4 May 2011 15:34:51 +0100,

Quoted 7 lines · Mark Brown

sound/soc/codecs/upd9976.c line 69

Quoted 2 lines · Lu Guanqun
sound/soc/codecs/upd9976.c new file +2 -0
+static const struct snd_kcontrol_new upd9976_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",

Master Volume would be a better name.

Quoted 4 lines
Quoted 1 line

Yes, also in general, try to avoid special letters like "&".

I once used letter "/", but then it failed to create the corresponding debugfs directory... :)

Yeah, "/" can be used for control names for now because they aren't exposed in fs, but better to avoid if possible, too.

Quoted 8 lines

Oh, btw: There are another register that's related to volume control, it's before DAC (not added in this patchset yet, for simplicity, will add it later). so the connection looks something like this:

[volume gain A] --> [DAC] --> [Mixer Volume] -> [Output Pins]

Which volume control should be the master volume? I'm a bit unclear on this one.

If it's the only output, any of them can be a "Master" volume. But if there are other outputs, it shouldn't be named as "Master" at all.

Master volume is like Highlander(*), there can be only one :)

Takashi

(*) doesn't mean guys in Edinburgh

#9 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 3 lines · Takashi Iwai

If it's the only output, any of them can be a "Master" volume. But if there are other outputs, it shouldn't be named as "Master" at all.

If you've got a choice you probably want to pick an analogue control over a digital one as this will give better performance.

Quoted 3 lines

Master volume is like Highlander(*), there can be only one :)

(*) doesn't mean guys in Edinburgh

Definitely not, Edinburgh is in the lowlands not the highlands!

author
#10 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 8 lines · Mark Brown
Quoted 3 lines · Takashi Iwai

If it's the only output, any of them can be a "Master" volume. But if there are other outputs, it shouldn't be named as "Master" at all.

If you've got a choice you probably want to pick an analogue control over a digital one as this will give better performance.

Good to know that.
But there's no single volume control after DAC that can control all the outputs. poor about that...

Quoted 6 lines
Quoted 4 lines

Master volume is like Highlander(*), there can be only one :)

(*) doesn't mean guys in Edinburgh

Definitely not, Edinburgh is in the lowlands not the highlands!

Signature · 1 line
guanqun
author
#11 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

In reply to Takashi Iwai
Quoted 26 lines · Takashi Iwai

At Wed, 4 May 2011 23:18:27 +0800,

Quoted 12 lines · Lu Guanqun
Quoted 10 lines · Takashi Iwai

At Wed, 4 May 2011 15:34:51 +0100,

Quoted 7 lines · Mark Brown

sound/soc/codecs/upd9976.c line 69

Quoted 2 lines · Lu Guanqun
sound/soc/codecs/upd9976.c new file +2 -0
+static const struct snd_kcontrol_new upd9976_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",

Master Volume would be a better name.

Quoted 4 lines
Quoted 1 line

Yes, also in general, try to avoid special letters like "&".

I once used letter "/", but then it failed to create the corresponding debugfs directory... :)

Yeah, "/" can be used for control names for now because they aren't exposed in fs, but better to avoid if possible, too.

Quoted 4 lines

Oh, btw: There are another register that's related to volume control, it's before DAC (not added in this patchset yet, for simplicity, will add it later). so the connection looks something like this:

Quoted 8 lines
Quoted 4 lines

[volume gain A] --> [DAC] --> [Mixer Volume] -> [Output Pins]

Which volume control should be the master volume? I'm a bit unclear on this one.

If it's the only output, any of them can be a "Master" volume. But if there are other outputs, it shouldn't be named as "Master" at all.

Thanks for the info.
There are other outputs in this codec.

                            .-> [Mixer Volume for Earpiece] -> [output pins]
                           /
[volume gain A] --> [DAC] --> [Mixer Volume for HP/Spkr] -> [Output Pins]
                           \
                            `-> [Mixer Volume for LineOut] -> [LineOut Pins]

So in this case, I'll make the [volume gain A] as the master volume.

Quoted 7 lines

Master volume is like Highlander(*), there can be only one :)

Takashi

(*) doesn't mean guys in Edinburgh

Signature · 1 line
guanqun
#12 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

In reply to Lu Guanqun
Quoted 8 lines · Lu Guanqun

Oh, btw: There are another register that's related to volume control, it's before DAC (not added in this patchset yet, for simplicity, will add it later). so the connection looks something like this:

[volume gain A] --> [DAC] --> [Mixer Volume] -> [Output Pins]

Which volume control should be the master volume? I'm a bit unclear on this one.

Probably the mixer if that's the only path out.

author
#13 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

In reply to Mark Brown
Quoted 6 lines · Mark Brown

sound/soc/codecs/upd9976.c line 297

Quoted 4 lines
sound/soc/codecs/upd9976.c new file +4 -0
+static struct snd_soc_dai_driver upd9976_dais[] = {
+{
+	.name = "upd9976-audio",
+	.playback = {

Just drop the audio from the name, it's a CODEC so it's obviously audio.

Giving it a second look, I recall why I added this "-audio", because there is another interface on the codec driver called "voice port", so in the future, I would expect to add a new dai driver called "upd9976-voice". So that's the differentiation. :)

I'm finished with all the changes according to you guys' comments. After I do a thorough test, I'll resend this patchset. Thanks.

Signature · 1 line
guanqun
#14 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 4 lines · Lu Guanqun

Giving it a second look, I recall why I added this "-audio", because there is another interface on the codec driver called "voice port", so in the future, I would expect to add a new dai driver called "upd9976-voice". So that's the differentiation. :)

Something like -hifi would make more sense, -audio is completely non-descriptive.

#15 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

In reply to Lu Guanqun
Quoted 8 lines · Lu Guanqun

uPD9976 is a complex codec, however this patch only provides basic playback functionality for headphone. More functionality will be added bit by bit in the following patches.

sound/soc/codecs/upd9976.c new file +1 -0
+static inline unsigned int upd9976_read(struct snd_soc_codec *codec,

sound/soc/codecs/upd9976.c line 50

Quoted 10 lines
sound/soc/codecs/upd9976.c new file +10 -0
+					unsigned int reg)
+{
+	u8 value = 0;
+	int ret;
+
+	ret = intel_scu_ipc_ioread8(reg, &value);
+	if (ret)
+		pr_err("upd9976 read of 0x%x failed, error: %d\n", reg, ret);
+	return value;
+}

dev_err() would be more preferable.

Quoted 21 lines
sound/soc/codecs/upd9976.c new file +21 -0
+static int upd9976_audio_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	unsigned int mode, mask;
+
+	mask = BIT(5) | BIT(4);
+	mode = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		mode |= BIT(4);
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		mode |= BIT(5);
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		mode |= BIT(5) | BIT(4);
+		break;
+	}
+
+	mask |= BIT(7) | BIT(3);

sound/soc/codecs/upd9976.c line 213

Quoted 10 lines
sound/soc/codecs/upd9976.c new file +10 -0
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+		mode |= BIT(7) | BIT(3);
+		break;
+	}
+
+	return snd_soc_update_bits(codec, UPD9976_AUDIOPORT1, mask, mode);
+}

I am not sure whether the BIT() macro is more confusing than helpful.

Quoted 47 lines
sound/soc/codecs/upd9976.c new file +47 -0
+static int upd9976_audio_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;
+	unsigned int tmp;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		tmp = 0x00;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		tmp = 0x03;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		tmp = 0x01;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		tmp = 0x02;
+		break;
+	default:
+		return -EINVAL;
+	}
+	snd_soc_update_bits(codec, UPD9976_AUDIOPORT1,
+			    BIT(2)|BIT(1)|BIT(0), tmp);
+
+	switch (params_rate(params)) {
+	case 8000:
+		tmp = 0x00;
+		break;
+	case 11025:
+		tmp = 0x01;
+		break;
+	case 12000:
+		tmp = 0x02;
+		break;
+	case 16000:
+		tmp = 0x03;
+		break;
+	case 22050:
+		tmp = 0x04;
+		break;
+	case 24000:
+		tmp = 0x05;
+		break;
+	case 32000:
+		tmp = 0x07;

sound/soc/codecs/upd9976.c line 271

Quoted 10 lines
sound/soc/codecs/upd9976.c new file +10 -0
+		break;
+	case 44100:
+		tmp = 0x08;
+		break;
+	case 48000:
+		tmp = 0x09;
+		break;
+	default:
+		return -EINVAL;
+	}

Looks fine, I'd rather use an array though.

Quoted 16 lines
sound/soc/codecs/upd9976.c new file +16 -0
+static int upd9976_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+			snd_soc_update_bits(codec, UPD9976_VAUDIOCNT,
+					    0x27, 0x27);
+			snd_soc_update_bits(codec, UPD9976_VREFPLL,
+					    0x35, 0x35);
+		}
+		break;
+

sound/soc/codecs/upd9976.c line 337

Quoted 10 lines
sound/soc/codecs/upd9976.c new file +10 -0
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_write(codec, UPD9976_VAUDIOCNT, 0x25);
+		snd_soc_write(codec, UPD9976_VREFPLL, 0x10);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		snd_soc_write(codec, UPD9976_VREFPLL, 0);
+		snd_soc_write(codec, UPD9976_VAUDIOCNT, 0x24);
+		break;
+	}

Why not snd_soc_update_bits()? These should normally be DAPM widgets.

sound/soc/codecs/upd9976.c line 348

Quoted 6 lines
sound/soc/codecs/upd9976.c new file +6 -0
+static int upd9976_codec_probe(struct snd_soc_codec *codec)
+{
+	upd9976_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}

Why SND_SOC_BIAS_OFF and not SND_SOC_BIAS_STANDBY?

sound/soc/codecs/upd9976.c line 353

Quoted 4 lines
sound/soc/codecs/upd9976.c new file +4 -0
+static int upd9976_codec_remove(struct snd_soc_codec *codec)
+{
+	return 0;
+}

You can call upd9976_set_bias_level(codec, SND_SOC_BIAS_OFF) here.

Thanks,
Dimitris

author
#16 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 7 lines · Dimitris Papastamos

sound/soc/codecs/upd9976.c line 50

Quoted 4 lines · Lu Guanqun
sound/soc/codecs/upd9976.c new file +4 -0
+	if (ret)
+		pr_err("upd9976 read of 0x%x failed, error: %d\n", reg, ret);
+	return value;
+}

dev_err() would be more preferable.

OK.

Quoted 11 lines

sound/soc/codecs/upd9976.c line 213

Quoted 9 lines
sound/soc/codecs/upd9976.c new file +9 -0
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+		mode |= BIT(7) | BIT(3);
+		break;
+	}
+
+	return snd_soc_update_bits(codec, UPD9976_AUDIOPORT1, mask, mode);
+}

I am not sure whether the BIT() macro is more confusing than helpful.

I was trying to be helpful. :) but if that confuses you.,I'm OK to use hex number.

Quoted 25 lines
Quoted 25 lines
sound/soc/codecs/upd9976.c new file +25 -0
+	switch (params_rate(params)) {
+	case 8000:
+		tmp = 0x00;
+		break;
+	case 11025:
+		tmp = 0x01;
+		break;
+	case 12000:
+		tmp = 0x02;
+		break;
+	case 16000:
+		tmp = 0x03;
+		break;
+	case 22050:
+		tmp = 0x04;
+		break;
+	case 24000:
+		tmp = 0x05;
+		break;
+	case 32000:
+		tmp = 0x07;
+		break;
+	case 44100:
+		tmp = 0x08;
+		break;
Quoted 8 lines

sound/soc/codecs/upd9976.c line 271

Quoted 6 lines
sound/soc/codecs/upd9976.c new file +6 -0
+	case 48000:
+		tmp = 0x09;
+		break;
+	default:
+		return -EINVAL;
+	}

Looks fine, I'd rather use an array though.

OK. Array makes it less code.

Quoted 21 lines
Quoted 21 lines
sound/soc/codecs/upd9976.c new file +20 -0
+static int upd9976_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+			snd_soc_update_bits(codec, UPD9976_VAUDIOCNT,
+					    0x27, 0x27);
+			snd_soc_update_bits(codec, UPD9976_VREFPLL,
+					    0x35, 0x35);
+		}
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_write(codec, UPD9976_VAUDIOCNT, 0x25);
+		snd_soc_write(codec, UPD9976_VREFPLL, 0x10);
+		break;
Quoted 8 lines

sound/soc/codecs/upd9976.c line 337

Quoted 6 lines
sound/soc/codecs/upd9976.c new file +6 -0
+
+	case SND_SOC_BIAS_OFF:
+		snd_soc_write(codec, UPD9976_VREFPLL, 0);
+		snd_soc_write(codec, UPD9976_VAUDIOCNT, 0x24);
+		break;
+	}

Why not snd_soc_update_bits()? These should normally be DAPM widgets.

There's no DAPM widgets bound to these two registers. So I'm afraid it's OK to use snd_soc_write when it's been powered off totally.

Quoted 9 lines

sound/soc/codecs/upd9976.c line 348

Quoted 7 lines
sound/soc/codecs/upd9976.c new file +6 -0
+static int upd9976_codec_probe(struct snd_soc_codec *codec)
+{
+	upd9976_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}

Why SND_SOC_BIAS_OFF and not SND_SOC_BIAS_STANDBY?

Try to use as little power as possible.

Quoted 7 lines

sound/soc/codecs/upd9976.c line 353

Quoted 5 lines
sound/soc/codecs/upd9976.c new file +4 -0
+static int upd9976_codec_remove(struct snd_soc_codec *codec)
+{
+	return 0;
+}

You can call upd9976_set_bias_level(codec, SND_SOC_BIAS_OFF) here.

Thanks for reminding this.

Signature · 1 line
guanqun
#17 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 11 lines · Lu Guanqun
Quoted 9 lines · Dimitris Papastamos

sound/soc/codecs/upd9976.c line 337

Quoted 5 lines · Lu Guanqun
sound/soc/codecs/upd9976.c new file +5 -0
+	case SND_SOC_BIAS_OFF:
+		snd_soc_write(codec, UPD9976_VREFPLL, 0);
+		snd_soc_write(codec, UPD9976_VAUDIOCNT, 0x24);
+		break;
+	}

Why not snd_soc_update_bits()? These should normally be DAPM widgets.

Quoted 2 lines

There's no DAPM widgets bound to these two registers. So I'm afraid it's OK to use snd_soc_write when it's been powered off totally.

That's an orthogonal thing, the usual reason for pushing back on this stuff is that people have open coded a read/modify/write cycle which only updates a subset of bits. In this case I think the writes are fine as you're setting the full register to a specific value.

Quoted 10 lines
Quoted 8 lines

sound/soc/codecs/upd9976.c line 348

Quoted 6 lines
sound/soc/codecs/upd9976.c new file +6 -0
+static int upd9976_codec_probe(struct snd_soc_codec *codec)
+{
+	upd9976_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}

Why SND_SOC_BIAS_OFF and not SND_SOC_BIAS_STANDBY?

Try to use as little power as possible.

You should set idle_bias_off in the CODEC driver if you're doing this otherwise DAPM will just bring the CODEC up to _STANDBY at runtime.

#18 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

In reply to Lu Guanqun
Quoted 8 lines · Guanqun
Quoted 7 lines · Dimitris Papastamos

sound/soc/codecs/upd9976.c line 50

Quoted 4 lines · Lu Guanqun
sound/soc/codecs/upd9976.c new file +4 -0
+	if (ret)
+		pr_err("upd9976 read of 0x%x failed, error: %d\n", reg, ret);
+	return value;
+}

dev_err() would be more preferable.

any specific reasons for that?

Signature · 1 line
~Vinod
#19 lore raw

Re: [PATCH 01/19] ASoC: upd9976: Add Renesas uPD9976 codec driver

Quoted 5 lines · Vinod
Quoted 1 line · Guanqun
Quoted 1 line

dev_err() would be more preferable.

any specific reasons for that?

It'll cause the logging to include the device name.

author
#20 lore raw

PATCH 2/19 ASoC: sst_platform: add cpu dai driver for moorestown platform

In reply to Lu Guanqun
---
 sound/soc/mid-x86/sst_platform.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
sound/soc/mid-x86/sst_platform.c +14 -0
index 139db15..ce0ac3c 100644
@@ -110,6 +110,20 @@ struct snd_soc_dai_driver sst_platform_dai[] = {
 		.formats = SNDRV_PCM_FMTBIT_S24_LE,
 	},
 },
+{
+	.name = "mrst-cpu-pcm2",
+	.id = 4,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = (SNDRV_PCM_RATE_48000 |
+			  SNDRV_PCM_RATE_44100 |
+			  SNDRV_PCM_RATE_8000),
+		.formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+			    SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
+			    SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
+	},
+},
 };
 
 /* helper functions */
#21 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 17 lines · Guanqun
---
 sound/soc/mid-x86/sst_platform.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
sound/soc/mid-x86/sst_platform.c +4 -0
index 139db15..ce0ac3c 100644
@@ -110,6 +110,20 @@ struct snd_soc_dai_driver sst_platform_dai[] = {
 		.formats = SNDRV_PCM_FMTBIT_S24_LE,
 	},
 },
+{
+	.name = "mrst-cpu-pcm2",
+	.id = 4,
+	.playback = {

sound/soc/mid-x86/sst_platform.c struct snd_soc_dai_driver sst_platform_dai[] = { · line 126

Quoted 10 lines
sound/soc/mid-x86/sst_platform.c +10 -0
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = (SNDRV_PCM_RATE_48000 |
+			  SNDRV_PCM_RATE_44100 |
+			  SNDRV_PCM_RATE_8000),
+		.formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+			    SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
+			    SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
+	},
+},

Nope, We cant keep on adding these DAIs for every new platform :( Even the current way is not best as it just creates 4 instance of DAI where we could have done with two (as they have same properties) I would use the current headset DAI and change the ops there, or create a new one for each type so that it can be reused.

Signature · 1 line
~Vinod
author
#22 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 25 lines · Vinod
Quoted 24 lines · Guanqun
---
 sound/soc/mid-x86/sst_platform.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
sound/soc/mid-x86/sst_platform.c +11 -0
index 139db15..ce0ac3c 100644
@@ -110,6 +110,20 @@ struct snd_soc_dai_driver sst_platform_dai[] = {
 		.formats = SNDRV_PCM_FMTBIT_S24_LE,
 	},
 },
+{
+	.name = "mrst-cpu-pcm2",
+	.id = 4,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = (SNDRV_PCM_RATE_48000 |
+			  SNDRV_PCM_RATE_44100 |
+			  SNDRV_PCM_RATE_8000),
+		.formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+			    SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
Quoted 8 lines

sound/soc/mid-x86/sst_platform.c struct snd_soc_dai_driver sst_platform_dai[] = { · line 126

Quoted 3 lines
sound/soc/mid-x86/sst_platform.c +3 -0
+			    SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
+	},
+},

Nope, We cant keep on adding these DAIs for every new platform :( Even the current way is not best as it just creates 4 instance of DAI where we could have done with two (as they have same properties) I would use the current headset DAI and change the ops there, or create a new one for each type so that it can be reused.

So how about this one (not tested yet):

sound/soc/mid-x86/sst_platform.c +9 -4
index 7985cfe..78660e4 100644
@@ -68,16 +68,21 @@ struct snd_soc_dai_driver sst_platform_dai[] = {
        .name = "Headset-cpu-dai",
        .id = 0,
        .playback = {
-               .channels_min = SST_STEREO,
+               .channels_min = SST_MONO,
                .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S24_LE,
+               .rates = (SNDRV_PCM_RATE_48000 |
+                         SNDRV_PCM_RATE_44100 |
+                         SNDRV_PCM_RATE_8000),
+               .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+                           SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
+                           SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 5,
                .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S24_LE,
+               .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+                           SNDRV_PCM_FMTBIT_S24_LE),
        },
 },
 {
Signature · 1 line
guanqun
#23 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 32 lines · Guanqun
Quoted 11 lines · Vinod
Quoted 5 lines · Guanqun
---
 sound/soc/mid-x86/sst_platform.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

Nope, We cant keep on adding these DAIs for every new platform :( Even the current way is not best as it just creates 4 instance of DAI where we could have done with two (as they have same properties) I would use the current headset DAI and change the ops there, or create a new one for each type so that it can be reused.

So how about this one (not tested yet):

sound/soc/mid-x86/sst_platform.c +5 -3
index 7985cfe..78660e4 100644
@@ -68,16 +68,21 @@ struct snd_soc_dai_driver sst_platform_dai[] = {
        .name = "Headset-cpu-dai",
        .id = 0,
        .playback = {
-               .channels_min = SST_STEREO,
+               .channels_min = SST_MONO,
                .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S24_LE,
+               .rates = (SNDRV_PCM_RATE_48000 |
+                         SNDRV_PCM_RATE_44100 |
+                         SNDRV_PCM_RATE_8000),
+               .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |

sound/soc/mid-x86/sst_platform.c struct snd_soc_dai_driver sst_platform_dai[] = { · line 85

Quoted 10 lines
sound/soc/mid-x86/sst_platform.c +4 -1
+                           SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
+                           SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 5,
                .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S24_LE,
+               .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+                           SNDRV_PCM_FMTBIT_S24_LE),

You will have my Ack on this

Signature · 1 line
~Vinod
#24 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

In reply to Koul, Vinod
Quoted 5 lines · Vinod

Nope, We cant keep on adding these DAIs for every new platform :( Even the current way is not best as it just creates 4 instance of DAI where we could have done with two (as they have same properties) I would use the current headset DAI and change the ops there, or create a new one for each type so that it can be reused.

What does this DAI actually represent? I'd assume from the description that it's another interface on the same CPU?

#25 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 10 lines · Mark Brown
Quoted 5 lines · Vinod

Nope, We cant keep on adding these DAIs for every new platform :( Even the current way is not best as it just creates 4 instance of DAI where we could have done with two (as they have same properties) I would use the current headset DAI and change the ops there, or create a new one for each type so that it can be reused.

What does this DAI actually represent? I'd assume from the description that it's another interface on the same CPU?

The sst-platfrom driver sends the DAI ops to SST driver which sends to FW running on DSP.
So it essentially represent the DSP side
Note here DSP does DMA and sending data to PCM port.

Signature · 1 line
~Vinod
#26 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 9 lines · Vinod
Quoted 2 lines · Mark Brown

What does this DAI actually represent? I'd assume from the description that it's another interface on the same CPU?

The sst-platfrom driver sends the DAI ops to SST driver which sends to FW running on DSP.
So it essentially represent the DSP side
Note here DSP does DMA and sending data to PCM port.

Are there a fixed number of channels to the DSP or are these virtual?

#27 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 6 lines · Mark Brown
Quoted 4 lines · Vinod
Quoted 2 lines · Mark Brown

What does this DAI actually represent? I'd assume from the description that it's another interface on the same CPU?

Quoted 6 lines
Quoted 4 lines

The sst-platfrom driver sends the DAI ops to SST driver which sends to FW running on DSP.
So it essentially represent the DSP side
Note here DSP does DMA and sending data to PCM port.

Are there a fixed number of channels to the DSP or are these virtual?

Channels are fixed...

Signature · 1 line
~Vinod
#28 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 5 lines · Vinod
Quoted 1 line · Mark Brown

Are there a fixed number of channels to the DSP or are these virtual?

Channels are fixed...

OK, DAIs make sense then - I'd been concerned that these weren't fixed and might need to be virtualised.

#29 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 9 lines · Mark Brown
Quoted 5 lines · Vinod
Quoted 1 line · Mark Brown

Are there a fixed number of channels to the DSP or are these virtual?

Channels are fixed...

OK, DAIs make sense then - I'd been concerned that these weren't fixed and might need to be virtualised.

So how do we go about making them virtual? Thaat might be useful for some other things I had in mind...

Signature · 1 line
~Vinod
#30 lore raw

Re: [PATCH 02/19] ASoC: sst_platform: add cpu dai driver for moorestown platform

Quoted 7 lines · Vinod
Quoted 2 lines · Mark Brown

OK, DAIs make sense then - I'd been concerned that these weren't fixed and might need to be virtualised.

So how do we go about making them virtual? Thaat might be useful for some other things I had in mind...

You don't currently. The long term plan is to add support for this for DSPs and so on but it requires a bunch of framework work.

author
#31 lore raw

PATCH 3/19 ASoC: mrst_machine: add moorestown machine driver

In reply to Lu Guanqun

This machine driver glues upd9976 codec driver and sst_platform driver.

---
 sound/soc/mid-x86/Kconfig        |   12 +++
 sound/soc/mid-x86/Makefile       |    2 
 sound/soc/mid-x86/mrst_machine.c |  163 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 177 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/mid-x86/mrst_machine.c
sound/soc/mid-x86/Kconfig +12 -0
index 2935042..f76acba 100644
@@ -10,5 +10,17 @@ config SND_MFLD_MACHINE
           Say Y if you have such a device
           If unsure select "N".
 
+config SND_MRST_MACHINE
+	tristate "SoC Machine Audio Driver for Intel Moorestown Platform"
+	depends on INTEL_SCU_IPC
+	depends on SND_INTEL_SST
+	select SND_SOC_UPD9976
+	select SND_SST_PLATFORM
+	help
+	  This adds support for ASoC machine driver for Intel(R) MID Moorestown platform.
+	  It is used as ALSA device in audio substream in Intel(R) MID devices.
+	  Say Y if you have such a device.
+	  If unsure, select 'N'.
+
 config SND_SST_PLATFORM
 	tristate
sound/soc/mid-x86/Makefile +2 -0
index 6398833..d0f2c29 100644
@@ -1,5 +1,7 @@
 snd-soc-sst-platform-objs := sst_platform.o
 snd-soc-mfld-machine-objs := mfld_machine.o
+snd-soc-mrst-machine-objs := mrst_machine.o
 
 obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o
 obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o
+obj-$(CONFIG_SND_MRST_MACHINE) += snd-soc-mrst-machine.o
sound/soc/mid-x86/mrst_machine.c new file +163 -0

163 lines not on this page · raw message

#32 lore raw

Re: [PATCH 03/19] ASoC: mrst_machine: add moorestown machine driver

Quoted 7 lines · Lu Guanqun

This machine driver glues upd9976 codec driver and sst_platform driver.

sound/soc/mid-x86/mrst_machine.c new file +2 -0
+static int mrst_hw_params(struct snd_pcm_substream *substream,
+			  struct snd_pcm_hw_params *params)

sound/soc/mid-x86/mrst_machine.c line 92

Quoted 10 lines
sound/soc/mid-x86/mrst_machine.c new file +10 -0
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	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_CBM_CFM);
+
+	return ret;
+}

Should we not be letting know the CPU that the CODEC is master? Or is it by default slave?

Thanks,
Dimitris

author
#33 lore raw

Re: [PATCH 03/19] ASoC: mrst_machine: add moorestown machine driver

Quoted 6 lines · Dimitris Papastamos
Quoted 4 lines · Lu Guanqun

This machine driver glues upd9976 codec driver and sst_platform driver.

Quoted 15 lines

sound/soc/mid-x86/mrst_machine.c line 92

Quoted 12 lines
sound/soc/mid-x86/mrst_machine.c new file +12 -0
+static int mrst_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 *codec_dai = rtd->codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_fmt(codec_dai,
+				  SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM);
+
+	return ret;
+}

Should we not be letting know the CPU that the CODEC is master? Or is it by default slave?

by default, the corresponding bit is 0 and it's slave mode. we should change it to master somewhere. no sure about your first question...

Quoted 7 lines

Thanks,
Dimitris
_______________________________________________
Alsa-devel mailing list
[email protected]
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

Signature · 1 line
guanqun
author
#34 lore raw

PATCH 4/19 ASoC: mrst_machine: add speaker widget to moorestown machine driver

In reply to Lu Guanqun

This internal speaker needs an extra GPIO to control its power.

---
 sound/soc/mid-x86/mrst_machine.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)
sound/soc/mid-x86/mrst_machine.c +31 -0
index 11163e7..0bce388 100644
@@ -36,8 +36,24 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
+/*
+ * GPIO pin to power on/off Internal Speaker
+ */
+static int mrst_gpio_amp;
+
+static int mrst_speaker_event(struct snd_soc_dapm_widget *widget,
+			      struct snd_kcontrol *control, int event)
+{
+	if (mrst_gpio_amp)
+		gpio_set_value_cansleep(mrst_gpio_amp,
+					SND_SOC_DAPM_EVENT_ON(event));
+
+	return 0;
+}
+
 static const struct snd_soc_dapm_widget mrst_audio_widgets[] = {
 	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_SPK("Speaker", mrst_speaker_event),
 };
 
 static const struct snd_soc_dapm_route mrst_audio_map[] = {
@@ -46,6 +62,9 @@ static const struct snd_soc_dapm_route mrst_audio_map[] = {
 
 	{"Headphone", NULL, "HPOUTL"},
 	{"Headphone", NULL, "HPOUTR"},
+
+	{"Speaker", NULL, "PREOUTL"},
+	{"Speaker", NULL, "PREOUTR"},
 };
 
 static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
@@ -72,6 +91,7 @@ static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
 	snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
 
 	snd_soc_dapm_enable_pin(dapm, "Headphone");
+	snd_soc_dapm_disable_pin(dapm, "Speaker");
 
 	snd_soc_dapm_sync(dapm);
 
@@ -118,6 +138,13 @@ static int __devinit snd_mrst_audio_probe(struct platform_device *pdev)
 {
 	int ret;
 
+	if (pdev->dev.platform_data) {
+		mrst_gpio_amp = *(int *)pdev->dev.platform_data;
+		if (gpio_request_one(mrst_gpio_amp,
+				     GPIOF_OUT_INIT_LOW, "amp power"))
+			mrst_gpio_amp = 0;
+	}
+
 	snd_soc_card_mrst.dev = &pdev->dev;
 	ret = snd_soc_register_card(&snd_soc_card_mrst);
 	if (ret)
@@ -126,11 +153,15 @@ static int __devinit snd_mrst_audio_probe(struct platform_device *pdev)
 	return 0;
 
 fail_register_card:
+	if (mrst_gpio_amp)
+		gpio_free(mrst_gpio_amp);
 	return ret;
 }
 
 static int __devexit snd_mrst_audio_remove(struct platform_device *pdev)
 {
+	if (mrst_gpio_amp)
+		gpio_free(mrst_gpio_amp);
 	snd_soc_unregister_card(&snd_soc_card_mrst);
 	return 0;
 }
#35 lore raw

Re: [PATCH 04/19] ASoC: mrst_machine: add speaker widget to moorestown machine driver

sound/soc/mid-x86/mrst_machine.c static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime) · line 96

Quoted 7 lines · Lu Guanqun
sound/soc/mid-x86/mrst_machine.c +1 -0
@@ -72,6 +91,7 @@ static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
 	snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
 
 	snd_soc_dapm_enable_pin(dapm, "Headphone");
+	snd_soc_dapm_disable_pin(dapm, "Speaker");
 
 	snd_soc_dapm_sync(dapm);

There's nothing in this patch that ever enables the speaker...

author
#36 lore raw

PATCH 5/19 ASoC: mrst_machine: enable user to select different output

In reply to Lu Guanqun

All these two output device can be enabled and disabled independently.

---
 sound/soc/mid-x86/mrst_machine.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)
sound/soc/mid-x86/mrst_machine.c +13 -2
index 0bce388..b4d542e 100644
@@ -36,6 +36,11 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
+static const struct snd_kcontrol_new mrst_snd_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Speaker"),
+};
+
 /*
  * GPIO pin to power on/off Internal Speaker
  */
@@ -85,13 +90,19 @@ static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
 	if (ret)
 		return ret;
 
+	ret = snd_soc_add_controls(codec,
+				   mrst_snd_controls,
+				   ARRAY_SIZE(mrst_snd_controls));
+	if (ret)
+		return ret;
+
 	snd_soc_dapm_nc_pin(dapm, "LINEINL");
 	snd_soc_dapm_nc_pin(dapm, "LINEINR");
 	snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
 	snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
 
-	snd_soc_dapm_enable_pin(dapm, "Headphone");
-	snd_soc_dapm_disable_pin(dapm, "Speaker");
+	snd_soc_dapm_disable_pin(dapm, "Headphone");
+	snd_soc_dapm_enable_pin(dapm, "Speaker");
 
 	snd_soc_dapm_sync(dapm);
 
#37 lore raw

Re: [PATCH 05/19] ASoC: mrst_machine: enable user to select different output

sound/soc/mid-x86/mrst_machine.c static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime) · line 98

Quoted 6 lines · Lu Guanqun
sound/soc/mid-x86/mrst_machine.c +6 -0
+	ret = snd_soc_add_controls(codec,
+				   mrst_snd_controls,
+				   ARRAY_SIZE(mrst_snd_controls));
+	if (ret)
+		return ret;
+

It'd be better to use the data based init stuff to add the controls.

author
#38 lore raw

Re: [PATCH 05/19] ASoC: mrst_machine: enable user to select different output

Quoted 10 lines · Mark Brown

sound/soc/mid-x86/mrst_machine.c static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime) · line 98

Quoted 6 lines · Lu Guanqun
sound/soc/mid-x86/mrst_machine.c +6 -0
+	ret = snd_soc_add_controls(codec,
+				   mrst_snd_controls,
+				   ARRAY_SIZE(mrst_snd_controls));
+	if (ret)
+		return ret;
+

It'd be better to use the data based init stuff to add the controls.

OK. Will change that.

Signature · 1 line
guanqun
author
#39 lore raw

PATCH 6/19 ASoC: upd9976: add capture ability for dai driver

In reply to Lu Guanqun

From: Wang Xingchao <[email protected]>

---
 sound/soc/codecs/upd9976.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +7 -0
index cd68633..dc7920c 100644
@@ -305,6 +305,13 @@ static struct snd_soc_dai_driver upd9976_dais[] = {
 			    SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
 			    SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
 	},
+	.capture = {
+		.stream_name = "Audio Capture",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16),
+	},
 	.ops = &upd9976_audio_dai_ops,
 },
 };
author
#41 lore raw

PATCH 7/19 ASoC: sst_platform: add capture capability for cpu dai driver

In reply to Lu Guanqun

From: Wang Xingchao <[email protected]>

---
 sound/soc/mid-x86/sst_platform.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
sound/soc/mid-x86/sst_platform.c +6 -0
index ce0ac3c..7985cfe 100644
@@ -123,6 +123,12 @@ struct snd_soc_dai_driver sst_platform_dai[] = {
 			    SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
 			    SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
 	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16),
+	},
 },
 };
 
author
#42 lore raw

PATCH 8/19 ASoC: upd9976: add DMIC support

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |   67 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 67 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +67 -0
index dc7920c..fb3a4fc 100644
@@ -81,6 +81,29 @@ static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_right_controls[] = {
 	SOC_DAPM_SINGLE("Audio DAC Right", UPD9976_HPRMIXSEL, 3, 1, 1),
 };
 
+/* PCM2 Left Mux */
+static const char *upd9976_pcm2_left_mux_texts[] = {"AADC Left", "DMIC"};
+static const struct soc_enum upd9976_pcm2_left_mux_enum =
+	SOC_ENUM_SINGLE(UPD9976_ADCSAMPLERATE, 5, 2,
+			upd9976_pcm2_left_mux_texts);
+static const struct snd_kcontrol_new upd9976_pcm2_left_mux_control =
+	SOC_DAPM_ENUM("PCM2 Left Mux", upd9976_pcm2_left_mux_enum);
+
+/* PCM2 Right Mux */
+static const char *upd9976_pcm2_right_mux_texts[] = {"AADC Right", "DMIC"};
+static const struct soc_enum upd9976_pcm2_right_mux_enum =
+	SOC_ENUM_SINGLE(UPD9976_ADCSAMPLERATE, 4, 2,
+			upd9976_pcm2_right_mux_texts);
+static const struct snd_kcontrol_new upd9976_pcm2_right_mux_control =
+	SOC_DAPM_ENUM("PCM2 Right Mux", upd9976_pcm2_right_mux_enum);
+
+/* PCM2 Mux */
+static const char *upd9976_pcm2_mux_texts[] = {"No Mix", "Mix"};
+static const struct soc_enum upd9976_pcm2_mux_enum =
+	SOC_ENUM_SINGLE(UPD9976_ADCSAMPLERATE, 3, 2, upd9976_pcm2_mux_texts);
+static const struct snd_kcontrol_new upd9976_pcm2_mux_control =
+	SOC_DAPM_ENUM("PCM2 Mux", upd9976_pcm2_mux_enum);
+
 static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = {
 	/* Input */
 	SND_SOC_DAPM_INPUT("LINEINL"),
@@ -117,12 +140,34 @@ static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = {
 			   upd9976_hp_spkr_mixer_right_controls,
 			   ARRAY_SIZE(upd9976_hp_spkr_mixer_right_controls)),
 
+	SND_SOC_DAPM_MIXER("PCM2 IN Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("PCM2 IN No Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Mux */
+	SND_SOC_DAPM_MUX("PCM2 Left", SND_SOC_NOPM, 0, 0,
+			 &upd9976_pcm2_left_mux_control),
+	SND_SOC_DAPM_MUX("PCM2 Right", SND_SOC_NOPM, 0, 0,
+			 &upd9976_pcm2_right_mux_control),
+	SND_SOC_DAPM_MUX("PCM2 Mux", SND_SOC_NOPM, 0, 0,
+			 &upd9976_pcm2_mux_control),
+
 	/* PGA */
 	SND_SOC_DAPM_PGA("HP Playback Left", UPD9976_DRVPOWERCTRL,
 			 2, 0, NULL, 0),
 	SND_SOC_DAPM_PGA("HP Playback Right", UPD9976_DRVPOWERCTRL,
 			 1, 0, NULL, 0),
 
+	SND_SOC_DAPM_PGA("AADC Left", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("AADC Right", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("DMIC Gain", UPD9976_DMICCTRL1, 7, 0, NULL, 0),
+
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_OUT("PCM2 Out", "Audio Capture", 0, SND_SOC_NOPM, 0,
+			     0),
+
+	/* Supply */
+	SND_SOC_DAPM_SUPPLY("DMIC Supply", UPD9976_POWERCTRL2, 1, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route upd9976_dapm_routes[] = {
@@ -141,6 +186,28 @@ static const struct snd_soc_dapm_route upd9976_dapm_routes[] = {
 	{"HPOUTL", NULL, "HP Playback Left"},
 	{"HPOUTR", NULL, "HP Playback Right"},
 
+	{"DMICDAT", NULL, "DMIC Supply"},
+	{"DMIC Gain", NULL, "DMICDAT"},
+
+	{"AADC Left", NULL, "AADC"},
+	{"AADC Right", NULL, "AADC"},
+
+	{"PCM2 Left", "DMIC", "DMIC Gain"},
+	{"PCM2 Left", "AADC Left", "AADC Left"},
+
+	{"PCM2 Right", "DMIC", "DMIC Gain"},
+	{"PCM2 Right", "AADC Right", "AADC Right"},
+
+	{"PCM2 IN Mix", NULL, "PCM2 Left"},
+	{"PCM2 IN No Mix", NULL, "PCM2 Left"},
+
+	{"PCM2 IN No Mix", NULL, "PCM2 Right"},
+	{"PCM2 IN Mix", NULL, "PCM2 Right"},
+
+	{"PCM2 Mux", "No Mix", "PCM2 IN No Mix"},
+	{"PCM2 Mux", "Mix", "PCM2 IN Mix"},
+
+	{"PCM2 Out", NULL, "PCM2 Mux"},
 };
 
 static int upd9976_audio_digital_mute(struct snd_soc_dai *dai, int mute)
#43 lore raw

Re: [PATCH 08/19] ASoC: upd9976: add DMIC support

sound/soc/codecs/upd9976.c static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = { · line 144

Quoted 4 lines · Lu Guanqun
sound/soc/codecs/upd9976.c +2 -0
+	SND_SOC_DAPM_MIXER("PCM2 IN Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("PCM2 IN No Mix", SND_SOC_NOPM, 0, 0, NULL, 0),

Mixer instead of Mix?

sound/soc/codecs/upd9976.c static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = { · line 150

Quoted 5 lines
sound/soc/codecs/upd9976.c +5 -0
+	/* Mux */
+	SND_SOC_DAPM_MUX("PCM2 Left", SND_SOC_NOPM, 0, 0,
+			 &upd9976_pcm2_left_mux_control),
+	SND_SOC_DAPM_MUX("PCM2 Right", SND_SOC_NOPM, 0, 0,
+			 &upd9976_pcm2_right_mux_control),

Append Mux.

sound/soc/codecs/upd9976.c static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = { · line 163

Quoted 10 lines
sound/soc/codecs/upd9976.c +4 -0
 	/* PGA */
 	SND_SOC_DAPM_PGA("HP Playback Left", UPD9976_DRVPOWERCTRL,
 			 2, 0, NULL, 0),
 	SND_SOC_DAPM_PGA("HP Playback Right", UPD9976_DRVPOWERCTRL,
 			 1, 0, NULL, 0),
 
+	SND_SOC_DAPM_PGA("AADC Left", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("AADC Right", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("DMIC Gain", UPD9976_DMICCTRL1, 7, 0, NULL, 0),

Append PGA.

Thanks,
Dimitris

author
#44 lore raw

Re: [PATCH 08/19] ASoC: upd9976: add DMIC support

Quoted 22 lines · Dimitris Papastamos

sound/soc/codecs/upd9976.c static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = { · line 144

Quoted 4 lines · Lu Guanqun
sound/soc/codecs/upd9976.c +2 -0
+	SND_SOC_DAPM_MIXER("PCM2 IN Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("PCM2 IN No Mix", SND_SOC_NOPM, 0, 0, NULL, 0),

Mixer instead of Mix?

sound/soc/codecs/upd9976.c static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = { · line 150

Quoted 5 lines
sound/soc/codecs/upd9976.c +5 -0
+	/* Mux */
+	SND_SOC_DAPM_MUX("PCM2 Left", SND_SOC_NOPM, 0, 0,
+			 &upd9976_pcm2_left_mux_control),
+	SND_SOC_DAPM_MUX("PCM2 Right", SND_SOC_NOPM, 0, 0,
+			 &upd9976_pcm2_right_mux_control),

Append Mux.

Quoted 6 lines
sound/soc/codecs/upd9976.c +0 -0
 	/* PGA */
 	SND_SOC_DAPM_PGA("HP Playback Left", UPD9976_DRVPOWERCTRL,
 			 2, 0, NULL, 0),
 	SND_SOC_DAPM_PGA("HP Playback Right", UPD9976_DRVPOWERCTRL,
 			 1, 0, NULL, 0),
Quoted 6 lines

sound/soc/codecs/upd9976.c static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = { · line 163

Quoted 4 lines
sound/soc/codecs/upd9976.c +4 -0
+	SND_SOC_DAPM_PGA("AADC Left", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("AADC Right", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("DMIC Gain", UPD9976_DMICCTRL1, 7, 0, NULL, 0),

Append PGA.

Seems I'm not clear on the naming :) Thanks for correction. I'll change these names.

Signature · 1 line
guanqun
author
#45 lore raw

PATCH 9/19 ASoC: upd9976: add Analog MIC support

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +19 -0
index fb3a4fc..8b2fff7 100644
@@ -81,6 +81,13 @@ static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_right_controls[] = {
 	SOC_DAPM_SINGLE("Audio DAC Right", UPD9976_HPRMIXSEL, 3, 1, 1),
 };
 
+/* Analog Right Mux */
+static const char *upd9976_analog_mux_texts[] = {"MIC", "LineIn"};
+static const struct soc_enum upd9976_ar_mux_enum =
+	SOC_ENUM_SINGLE(UPD9976_LIRSEL, 7, 2, upd9976_analog_mux_texts);
+static const struct snd_kcontrol_new upd9976_ar_mux_control =
+	SOC_DAPM_ENUM("Route", upd9976_ar_mux_enum);
+
 /* PCM2 Left Mux */
 static const char *upd9976_pcm2_left_mux_texts[] = {"AADC Left", "DMIC"};
 static const struct soc_enum upd9976_pcm2_left_mux_enum =
@@ -144,6 +151,9 @@ static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = {
 	SND_SOC_DAPM_MIXER("PCM2 IN No Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
 
 	/* Mux */
+	SND_SOC_DAPM_MUX("Analog Right", UPD9976_POWERCTRL1, 4, 0,
+			 &upd9976_ar_mux_control),
+
 	SND_SOC_DAPM_MUX("PCM2 Left", SND_SOC_NOPM, 0, 0,
 			 &upd9976_pcm2_left_mux_control),
 	SND_SOC_DAPM_MUX("PCM2 Right", SND_SOC_NOPM, 0, 0,
@@ -162,6 +172,8 @@ static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = {
 
 	SND_SOC_DAPM_PGA("DMIC Gain", UPD9976_DMICCTRL1, 7, 0, NULL, 0),
 
+	SND_SOC_DAPM_PGA("MIC2 In", UPD9976_POWERCTRL1, 2, 0, NULL, 0),
+
 	/* Audio Interface */
 	SND_SOC_DAPM_AIF_OUT("PCM2 Out", "Audio Capture", 0, SND_SOC_NOPM, 0,
 			     0),
@@ -186,6 +198,13 @@ static const struct snd_soc_dapm_route upd9976_dapm_routes[] = {
 	{"HPOUTL", NULL, "HP Playback Left"},
 	{"HPOUTR", NULL, "HP Playback Right"},
 
+	{"MIC2 In", NULL, "MIC2"},
+
+	{"Analog Right", "MIC", "MIC2 In"},
+	{"Analog Right", "LineIn", "LINEINR"},
+
+	{"AADC", NULL, "Analog Right"},
+
 	{"DMICDAT", NULL, "DMIC Supply"},
 	{"DMIC Gain", NULL, "DMICDAT"},
 
author
#46 lore raw

PATCH 10/19 ASoC: upd9976: add microphone bias support

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +23 -0
index 8b2fff7..69d83ea 100644
@@ -60,6 +60,23 @@ static inline int upd9976_write(struct snd_soc_codec *codec,
 	return ret;
 }
 
+static int upd9976_mic2_bias_event(struct snd_soc_dapm_widget *widget,
+				   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = widget->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_write(codec, UPD9976_AUXDBNC, 0xff);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_write(codec, UPD9976_AUXDBNC, 0x0);
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * Mixing Volume: from -25 dB to 6 dB in 1 dB steps.
  */
@@ -161,6 +178,12 @@ static const struct snd_soc_dapm_widget upd9976_dapm_widgets[] = {
 	SND_SOC_DAPM_MUX("PCM2 Mux", SND_SOC_NOPM, 0, 0,
 			 &upd9976_pcm2_mux_control),
 
+	/* Microphose Bias */
+	SND_SOC_DAPM_MICBIAS("MIC1 Bias", UPD9976_MICCTRL, 6, 0),
+	SND_SOC_DAPM_MICBIAS_E("MIC2 Bias", UPD9976_MICCTRL, 4, 0,
+			       upd9976_mic2_bias_event,
+			       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
 	/* PGA */
 	SND_SOC_DAPM_PGA("HP Playback Left", UPD9976_DRVPOWERCTRL,
 			 2, 0, NULL, 0),
#47 lore raw

Re: [PATCH 10/19] ASoC: upd9976: add microphone bias support

Quoted 1 line · Lu Guanqun

In general for most of these things just squash them into the original driver for submission, no point in splitting them out if you're not actually doing initial submission.

author
#48 lore raw

Re: [PATCH 10/19] ASoC: upd9976: add microphone bias support

Quoted 6 lines · Mark Brown
Quoted 1 line · Lu Guanqun

In general for most of these things just squash them into the original driver for submission, no point in splitting them out if you're not actually doing initial submission.

OK. I was trying to split things into smaller patches so that you maintainers have a easier time to review them.

So in the next version, there will be less number of patches. :)

Signature · 1 line
guanqun
author
#49 lore raw

PATCH 11/19 ASoC: upd9976: add jack detection function

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |   28 ++++++++++++++++++++++++++++
 sound/soc/codecs/upd9976.h |    2 ++
 2 files changed, 30 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +28 -0
index 69d83ea..9231cee 100644
@@ -60,6 +60,34 @@ static inline int upd9976_write(struct snd_soc_codec *codec,
 	return ret;
 }
 
+void upd9976_jack_detection(struct snd_soc_jack *jack, u8 interrupt_status)
+{
+	int status = 0;
+	unsigned int value = 0;
+	struct snd_soc_codec *codec = jack->codec;
+	int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET;
+
+	if (interrupt_status & 0x3)
+		value = snd_soc_read(codec, UPD9976_SAUXINT);
+
+	if (interrupt_status & 0x1 && value == 0x1)
+		status |= SND_JACK_HEADSET;
+
+	if (interrupt_status & 0x2 && value == 0x2)
+		status |= SND_JACK_HEADPHONE;
+
+	if (interrupt_status & 0x4)
+		status |= SND_JACK_HEADSET | SND_JACK_BTN_0;
+
+	if (interrupt_status & 0x8)
+		status |= SND_JACK_HEADSET | SND_JACK_BTN_1;
+
+	snd_soc_jack_report(jack, status, mask);
+	if (status & (SND_JACK_BTN_0 | SND_JACK_BTN_1))
+		snd_soc_jack_report(jack, SND_JACK_HEADSET, mask);
+}
+EXPORT_SYMBOL_GPL(upd9976_jack_detection);
+
 static int upd9976_mic2_bias_event(struct snd_soc_dapm_widget *widget,
 				   struct snd_kcontrol *kcontrol, int event)
 {
sound/soc/codecs/upd9976.h +2 -0
index ab2ea15..090dd0b 100644
@@ -80,4 +80,6 @@
 
 #define UPD9976_SAUXINT		0x132
 
+void upd9976_jack_detection(struct snd_soc_jack *jack, u8 interrupt_status);
+
 #endif
#50 lore raw

Re: [PATCH 11/19] ASoC: upd9976: add jack detection function

sound/soc/codecs/upd9976.c static inline int upd9976_write(struct snd_soc_codec *codec, · line 90

Quoted 12 lines · Lu Guanqun
sound/soc/codecs/upd9976.c +11 -0
+void upd9976_jack_detection(struct snd_soc_jack *jack, u8 interrupt_status)
+{
+	int status = 0;
+	unsigned int value = 0;
+	struct snd_soc_codec *codec = jack->codec;
+	int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET;
+
+	if (interrupt_status & 0x3)
+		value = snd_soc_read(codec, UPD9976_SAUXINT);
 
+EXPORT_SYMBOL_GPL(upd9976_jack_detection);
+

I'd expect that the driver would also manage the work to do with handling the interrupt as well.

author
#51 lore raw

Re: [PATCH 11/19] ASoC: upd9976: add jack detection function

Quoted 12 lines · Mark Brown
Quoted 9 lines · Lu Guanqun
sound/soc/codecs/upd9976.c +9 -0
+void upd9976_jack_detection(struct snd_soc_jack *jack, u8 interrupt_status)
+{
+	int status = 0;
+	unsigned int value = 0;
+	struct snd_soc_codec *codec = jack->codec;
+	int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET;
+
+	if (interrupt_status & 0x3)
+		value = snd_soc_read(codec, UPD9976_SAUXINT);
Quoted 5 lines

sound/soc/codecs/upd9976.c static inline int upd9976_write(struct snd_soc_codec *codec, · line 90

Quoted 2 lines
sound/soc/codecs/upd9976.c +2 -0
+EXPORT_SYMBOL_GPL(upd9976_jack_detection);
+

I'd expect that the driver would also manage the work to do with handling the interrupt as well.

Yes, I see some wm* codec driver handles the interrupt directly in CODEC. I'm not sure whether it's better handled in codec driver or machine driver. Now it's confirmed by you, I'll change it correspondingly.

Signature · 1 line
guanqun
author
#52 lore raw

PATCH 12/19 ASoC: mrst_machine: add capture functionality

In reply to Lu Guanqun
---
 sound/soc/mid-x86/mrst_machine.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)
sound/soc/mid-x86/mrst_machine.c +12 -0
index b4d542e..d70b26e 100644
@@ -39,6 +39,9 @@
 static const struct snd_kcontrol_new mrst_snd_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Headphone"),
 	SOC_DAPM_PIN_SWITCH("Speaker"),
+
+	SOC_DAPM_PIN_SWITCH("Headset MIC"),
+	SOC_DAPM_PIN_SWITCH("Internal MIC"),
 };
 
 /*
@@ -59,6 +62,9 @@ static int mrst_speaker_event(struct snd_soc_dapm_widget *widget,
 static const struct snd_soc_dapm_widget mrst_audio_widgets[] = {
 	SND_SOC_DAPM_HP("Headphone", NULL),
 	SND_SOC_DAPM_SPK("Speaker", mrst_speaker_event),
+
+	SND_SOC_DAPM_MIC("Headset MIC", NULL),
+	SND_SOC_DAPM_MIC("Internal MIC", NULL),
 };
 
 static const struct snd_soc_dapm_route mrst_audio_map[] = {
@@ -70,6 +76,9 @@ static const struct snd_soc_dapm_route mrst_audio_map[] = {
 
 	{"Speaker", NULL, "PREOUTL"},
 	{"Speaker", NULL, "PREOUTR"},
+
+	{"MIC2", NULL, "Headset MIC"},
+	{"DMICDAT", NULL, "Internal MIC"},
 };
 
 static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
@@ -104,6 +113,9 @@ static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
 	snd_soc_dapm_disable_pin(dapm, "Headphone");
 	snd_soc_dapm_enable_pin(dapm, "Speaker");
 
+	snd_soc_dapm_disable_pin(dapm, "Headset MIC");
+	snd_soc_dapm_enable_pin(dapm, "Internal MIC");
+
 	snd_soc_dapm_sync(dapm);
 
 	return 0;
author
#53 lore raw

PATCH 13/19 ASoC: mrst_machine: add jack detection support

In reply to Lu Guanqun
---
 sound/soc/mid-x86/mrst_machine.c |  142 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 142 insertions(+), 0 deletions(-)
sound/soc/mid-x86/mrst_machine.c +142 -0
index d70b26e..96df9a1 100644
@@ -31,10 +31,83 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/list.h>
 #include <linux/io.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/jack.h>
+#include <../codecs/upd9976.h>
+
+/* Jack Detection */
+static struct snd_soc_jack mrst_jack;
+struct mrst_jack_context {
+	struct list_head head;
+	spinlock_t lock;
+	void __iomem *interrupt_base;
+};
+
+struct mrst_jack_node {
+	struct list_head list;
+	u8 interrupt_status;
+};
+
+static struct snd_soc_jack_pin mrst_jack_pins = {
+	.pin = "Headphone",
+	.mask = SND_JACK_HEADSET,
+};
+
+static irqreturn_t mrst_jack_intr_handler(int irq, void *dev)
+{
+	struct mrst_jack_context *context = dev;
+	u8 interrupt_status;
+	struct mrst_jack_node *node;
+	unsigned long flags;
+
+	memcpy_fromio(&interrupt_status,
+		      context->interrupt_base,
+		      sizeof(u8));
+
+	/* check if it's valid */
+	if (!(interrupt_status & 0xf))
+		return IRQ_NONE;
+
+	node = kmalloc(sizeof(*node), GFP_ATOMIC);
+	if (!node)
+		return IRQ_NONE;
+
+	INIT_LIST_HEAD(&node->list);
+	node->interrupt_status = interrupt_status;
+
+	spin_lock_irqsave(&context->lock, flags);
+	list_add_tail(&node->list, &context->head);
+	spin_unlock_irqrestore(&context->lock, flags);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t mrst_jack_detection(int irq, void *data)
+{
+	struct mrst_jack_context *context = data;
+	u8 interrupt_status;
+	unsigned long flags;
+	struct mrst_jack_node *node;
+
+	spin_lock_irqsave(&context->lock, flags);
+	if (list_empty(&context->head)) {
+		spin_unlock_irqrestore(&context->lock, flags);
+		return IRQ_HANDLED;
+	}
+	node = list_first_entry(&context->head, struct mrst_jack_node, list);
+	interrupt_status = node->interrupt_status;
+	list_del(&node->list);
+	kfree(node);
+	spin_unlock_irqrestore(&context->lock, flags);
+
+	upd9976_jack_detection(&mrst_jack, interrupt_status);
+
+	return IRQ_HANDLED;
+}
 
 static const struct snd_kcontrol_new mrst_snd_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Headphone"),
@@ -116,8 +189,22 @@ static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
 	snd_soc_dapm_disable_pin(dapm, "Headset MIC");
 	snd_soc_dapm_enable_pin(dapm, "Internal MIC");
 
+	snd_soc_dapm_force_enable_pin(dapm, "MIC2 Bias");
+
 	snd_soc_dapm_sync(dapm);
 
+	ret = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
+			       (SND_JACK_HEADSET |
+				SND_JACK_BTN_0 |
+				SND_JACK_BTN_1),
+			       &mrst_jack);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_jack_add_pins(&mrst_jack, 1, &mrst_jack_pins);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -159,6 +246,9 @@ static struct snd_soc_card snd_soc_card_mrst = {
 
 static int __devinit snd_mrst_audio_probe(struct platform_device *pdev)
 {
+	int irq;
+	struct resource *irq_mem;
+	struct mrst_jack_context *jack_context = NULL;
 	int ret;
 
 	if (pdev->dev.platform_data) {
@@ -168,14 +258,59 @@ static int __devinit snd_mrst_audio_probe(struct platform_device *pdev)
 			mrst_gpio_amp = 0;
 	}
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto fail_get_irq;
+	}
+
+	jack_context = kzalloc(sizeof(*jack_context), GFP_KERNEL);
+	if (!jack_context) {
+		ret = -ENOMEM;
+		goto fail_get_irq;
+	}
+	spin_lock_init(&jack_context->lock);
+	INIT_LIST_HEAD(&jack_context->head);
+
+	irq_mem = platform_get_resource_byname(pdev,
+					       IORESOURCE_MEM, "IRQ_BASE");
+	if (!irq_mem) {
+		ret = -ENODEV;
+		goto fail_alloc_context;
+	}
+
+	jack_context->interrupt_base = ioremap_nocache(irq_mem->start,
+						       resource_size(irq_mem));
+	if (!jack_context->interrupt_base) {
+		ret = -ENOMEM;
+		goto fail_alloc_context;
+	}
+
+	ret = request_threaded_irq(irq,
+				   mrst_jack_intr_handler,
+				   mrst_jack_detection,
+				   IRQF_SHARED,
+				   pdev->dev.driver->name,
+				   jack_context);
+	if (ret)
+		goto fail_request_irq;
+
 	snd_soc_card_mrst.dev = &pdev->dev;
 	ret = snd_soc_register_card(&snd_soc_card_mrst);
 	if (ret)
 		goto fail_register_card;
 
+	platform_set_drvdata(pdev, jack_context);
+
 	return 0;
 
 fail_register_card:
+	free_irq(irq, jack_context);
+fail_request_irq:
+	iounmap(jack_context->interrupt_base);
+fail_alloc_context:
+	kfree(jack_context);
+fail_get_irq:
 	if (mrst_gpio_amp)
 		gpio_free(mrst_gpio_amp);
 	return ret;
@@ -183,9 +318,16 @@ fail_register_card:
 
 static int __devexit snd_mrst_audio_remove(struct platform_device *pdev)
 {
+	struct mrst_jack_context *jack_context = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	free_irq(irq, jack_context);
+	iounmap(jack_context->interrupt_base);
+	kfree(jack_context);
 	if (mrst_gpio_amp)
 		gpio_free(mrst_gpio_amp);
 	snd_soc_unregister_card(&snd_soc_card_mrst);
+
 	return 0;
 }
 
author
#54 lore raw

PATCH 14/19 ASoC: upd9976: add mute switch for DMIC

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +1 -0
index 9231cee..a8f9e4a 100644
@@ -114,6 +114,7 @@ static const struct snd_kcontrol_new upd9976_snd_controls[] = {
 	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",
 			 UPD9976_HPSPRLVOL, UPD9976_HPSPRRVOL,
 			 0, 0x1f, 1, mixer_tlv),
+	SOC_SINGLE("Internal Mic Switch", UPD9976_DMICCTRL1, 6, 1, 0),
 };
 
 static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_left_controls[] = {
author
#55 lore raw

PATCH 15/19 ASoC: upd9976: add mute switch for analog

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +2 -0
index a8f9e4a..f345db1 100644
@@ -115,6 +115,8 @@ static const struct snd_kcontrol_new upd9976_snd_controls[] = {
 			 UPD9976_HPSPRLVOL, UPD9976_HPSPRRVOL,
 			 0, 0x1f, 1, mixer_tlv),
 	SOC_SINGLE("Internal Mic Switch", UPD9976_DMICCTRL1, 6, 1, 0),
+	SOC_DOUBLE_R("Analog Mic Switch", UPD9976_LILSEL, UPD9976_LIRSEL,
+		     6, 1, 0),
 };
 
 static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_left_controls[] = {
author
#56 lore raw

PATCH 16/19 ASoC: mrst_machine: make DMIC's output to PCM2 mono

In reply to Lu Guanqun

On Moorestown, DMIC's output is set to PCM2 mono.

---
 sound/soc/mid-x86/mrst_machine.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
sound/soc/mid-x86/mrst_machine.c +3 -0
index 96df9a1..5f19df5 100644
@@ -160,6 +160,9 @@ static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret;
 
+	/* DMIC configuration: mono output to PCM2 */
+	snd_soc_update_bits(codec, UPD9976_MICCTRL, BIT(1)|BIT(0), 0x1);
+
 	ret = snd_soc_dapm_new_controls(dapm,
 					mrst_audio_widgets,
 					ARRAY_SIZE(mrst_audio_widgets));
author
#57 lore raw

PATCH 17/19 ASoC: mrst_machine: make MIC2 pseudo-differential

In reply to Lu Guanqun

The Moorestown uses MIC2 pseudo-differential configuration.

---
 sound/soc/mid-x86/mrst_machine.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
sound/soc/mid-x86/mrst_machine.c +3 -0
index 5f19df5..7ea5bc5 100644
@@ -163,6 +163,9 @@ static int mrst_audio_init(struct snd_soc_pcm_runtime *runtime)
 	/* DMIC configuration: mono output to PCM2 */
 	snd_soc_update_bits(codec, UPD9976_MICCTRL, BIT(1)|BIT(0), 0x1);
 
+	/* Set MIC2 to pseudo-differential */
+	snd_soc_update_bits(codec, UPD9976_MICSELVOL, BIT(4), BIT(4));
+
 	ret = snd_soc_dapm_new_controls(dapm,
 					mrst_audio_widgets,
 					ARRAY_SIZE(mrst_audio_widgets));
author
#58 lore raw

PATCH 18/19 ASoC: upd9976: add capture volume for analog inputs

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +8 -0
index f345db1..6fc9902 100644
@@ -110,6 +110,11 @@ static int upd9976_mic2_bias_event(struct snd_soc_dapm_widget *widget,
  */
 static DECLARE_TLV_DB_SCALE(mixer_tlv, -2500, 100, 0);
 
+/*
+ * Analog Volume: from -25 dB to 6 dB in 1 dB steps.
+ */
+static DECLARE_TLV_DB_SCALE(analog_tlv, -2500, 100, 0);
+
 static const struct snd_kcontrol_new upd9976_snd_controls[] = {
 	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",
 			 UPD9976_HPSPRLVOL, UPD9976_HPSPRRVOL,
@@ -117,6 +122,9 @@ static const struct snd_kcontrol_new upd9976_snd_controls[] = {
 	SOC_SINGLE("Internal Mic Switch", UPD9976_DMICCTRL1, 6, 1, 0),
 	SOC_DOUBLE_R("Analog Mic Switch", UPD9976_LILSEL, UPD9976_LIRSEL,
 		     6, 1, 0),
+	SOC_DOUBLE_R_TLV("Analog Capture Volume",
+			 UPD9976_LILSEL, UPD9976_LILSEL,
+			 0, 0x1f, 1, analog_tlv),
 };
 
 static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_left_controls[] = {
author
#59 lore raw

PATCH 19/19 ASoC: upd9976: add capture volume for DMIC

In reply to Lu Guanqun
---
 sound/soc/codecs/upd9976.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
sound/soc/codecs/upd9976.c +7 -0
index 6fc9902..a35b891 100644
@@ -115,6 +115,11 @@ static DECLARE_TLV_DB_SCALE(mixer_tlv, -2500, 100, 0);
  */
 static DECLARE_TLV_DB_SCALE(analog_tlv, -2500, 100, 0);
 
+/*
+ * DMIC Volume: from -63 dB to 1 dB in 1 db steps.
+ */
+static DECLARE_TLV_DB_SCALE(dmic_tlv, -6300, 100, 1);
+
 static const struct snd_kcontrol_new upd9976_snd_controls[] = {
 	SOC_DOUBLE_R_TLV("Headphone & Speaker Volume",
 			 UPD9976_HPSPRLVOL, UPD9976_HPSPRRVOL,
@@ -125,6 +130,8 @@ static const struct snd_kcontrol_new upd9976_snd_controls[] = {
 	SOC_DOUBLE_R_TLV("Analog Capture Volume",
 			 UPD9976_LILSEL, UPD9976_LILSEL,
 			 0, 0x1f, 1, analog_tlv),
+	SOC_SINGLE_TLV("Internal Mic Capture Volume",
+		       UPD9976_DMICCTRL1, 0, 0x3f, 1, dmic_tlv),
 };
 
 static const struct snd_kcontrol_new upd9976_hp_spkr_mixer_left_controls[] = {