Skip to contentSkip to conversation

ASoC: Add support for NAU8825 codec to ASoC

PATCH Superseded Chih-Chiang Chang 2 participants 3 messages Apr 10, 2015 – Apr 15, 2015

Subsystems (2)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ASoC: Add support for NAU8825 codec to ASoC

The NAU88L25 is an ultra-low power high performance audio codec designed for smartphone, tablet PC, and other portable devices by Nuvoton, now add linux driver support for it.

---
 include/sound/nau8825_plat.h |  22 ++
 sound/soc/codecs/Kconfig     |   5 +
 sound/soc/codecs/Makefile    |   2 +
 sound/soc/codecs/nau8825.c   | 593 +++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/nau8825.h   | 150 +++++++++++
 5 files changed, 772 insertions(+)
 create mode 100644 include/sound/nau8825_plat.h
 create mode 100644 sound/soc/codecs/nau8825.c
 create mode 100644 sound/soc/codecs/nau8825.h
include/sound/nau8825_plat.h new file +22 -0
new file mode 100644
index 0000000..87afcd3
@@ -0,0 +1,22 @@
+/*
+ * linux/sound/snd_nau8825.h -- Platform data for NAU8825
+ *
+ * Copyright 2015 Nuvoton Technology Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_NAU8825_H
+#define __LINUX_SND_NAU8825_H
+
+struct nau8825_platform_data {
+	unsigned int audio_mclk1;
+	unsigned int gpio_irq;
+	int naudint_irq;
+	int headset_detect;
+	int button_press_detect;
+};
+
+#endif
sound/soc/codecs/Kconfig +5 -0
index 0bddd92..8807c57 100644
@@ -75,6 +75,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_MC13783 if MFD_MC13XXX
 	select SND_SOC_ML26124 if I2C
+	select SND_SOC_NAU8825 if I2C
 	select SND_SOC_HDMI_CODEC
 	select SND_SOC_PCM1681 if I2C
 	select SND_SOC_PCM1792A if SPI_MASTER
@@ -464,6 +465,10 @@ config SND_SOC_MAX98357A
 config SND_SOC_MAX9850
 	tristate
 
+config SND_SOC_NAU8825
+	tristate "Nuvoton NAU8825 CODEC"
+	depends on I2C
+
 config SND_SOC_PCM1681
 	tristate "Texas Instruments PCM1681 CODEC"
 	depends on I2C
sound/soc/codecs/Makefile +2 -0
index 7acb6c1..acf594e 100644
@@ -68,6 +68,7 @@ snd-soc-max98357a-objs := max98357a.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
+snd-soc-nau8825-objs := nau8825.o
 snd-soc-hdmi-codec-objs := hdmi.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm1792a-codec-objs := pcm1792a.o
@@ -252,6 +253,7 @@ obj-$(CONFIG_SND_SOC_MAX98357A)	+= snd-soc-max98357a.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
+obj-$(CONFIG_SND_SOC_NAU8825)	+= snd-soc-nau8825.o
 obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
 obj-$(CONFIG_SND_SOC_PCM1681)	+= snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM1792A)	+= snd-soc-pcm1792a-codec.o
sound/soc/codecs/nau8825.c new file +593 -0

593 lines not on this page · raw message

sound/soc/codecs/nau8825.h new file +150 -0

150 lines not on this page · raw message

Signature · 6 lines
1.9.3


---
Avast 防毒軟體已檢查此封電子郵件的病毒。
http://www.avast.com
#1 lore raw

include/sound/nau8825_plat.h

Quoted 21 lines · Chih-Chiang Chang

The NAU88L25 is an ultra-low power high performance audio codec designed for smartphone, tablet PC, and other portable devices by Nuvoton, now add linux driver support for it.

---
  include/sound/nau8825_plat.h |  22 ++
  sound/soc/codecs/Kconfig     |   5 +
  sound/soc/codecs/Makefile    |   2 +
  sound/soc/codecs/nau8825.c   | 593 +++++++++++++++++++++++++++++++++++++++++++
  sound/soc/codecs/nau8825.h   | 150 +++++++++++
  5 files changed, 772 insertions(+)

create mode 100644 include/sound/nau8825_plat.h
create mode 100644 sound/soc/codecs/nau8825.c
create mode 100644 sound/soc/codecs/nau8825.h

include/sound/nau8825_plat.h new file +0 -0
new file mode 100644
index 0000000..87afcd3

the preferred place for platform_data files is include/linux/platform_data/, but the driver doesn't seem to use the platform data anyway, so maybe drop it?

[...]

sound/soc/codecs/nau8825.c line 2

Quoted 8 lines
sound/soc/codecs/nau8825.c new file +2 -0
new file mode 100644
index 0000000..a8c8f59
@@ -0,0 +1,593 @@
+/*
+ * linux/sound/soc/codecs/nau8825.c

No need to include the file path in the header of the file, this will just become outdated if the file is ever moved.

[...]

sound/soc/codecs/nau8825.c line 43

Quoted 9 lines
sound/soc/codecs/nau8825.c new file +9 -0
+static int nau8825_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai);
+static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai,
+				unsigned int fmt);
+static int nau8825_set_bias_level(struct snd_soc_codec *codec,
+				enum snd_soc_bias_level level);
+static int nau8825_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+				unsigned int freq, int dir);

These forward declarations don't seem to be necessary.

[...]

sound/soc/codecs/nau8825.c line 59

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +4 -0
+static const struct snd_kcontrol_new nau8825_snd_controls[] = {
+
 
+	SOC_SINGLE("HP Class OP", NAU8825_CLASS_G_CTRL, NAU8825_CLASS_G_SHIFT,
+				 1, 0),

What is "Class OP"?

sound/soc/codecs/nau8825.c line 61

Quoted 2 lines
sound/soc/codecs/nau8825.c new file +2 -0
+	SOC_SINGLE("DAC Right", NAU8825_DAC_CTRL, NAU8825_DAC_R_SFT, 1, 0),
+	SOC_SINGLE("DAC Left", NAU8825_DAC_CTRL, NAU8825_DAC_L_SFT, 1, 0),

The same bits are controlled by the DAC DAPM widgets, there shouldn't be any controls for them.

sound/soc/codecs/nau8825.c line 65

Quoted 4 lines
sound/soc/codecs/nau8825.c new file +4 -0
+	SOC_SINGLE("DAC Right Clock", NAU8825_DAC_CTRL, NAU8825_DAC_CLK_R_SFT,
+				1, 0),
+	SOC_SINGLE("DAC Left Clock", NAU8825_DAC_CTRL, NAU8825_DAC_CLK_L_SFT,
+				1, 0),

The clock controls should probably not be user controllable but rather be DAPM supply widgets.

sound/soc/codecs/nau8825.c line 77

Quoted 12 lines
sound/soc/codecs/nau8825.c new file +12 -0
+};
+
+static const struct snd_kcontrol_new nau8825_hpo_mix[] = {
+	SOC_DAPM_SINGLE("HP L Switch", NAU8825_HSVOL_CTRL,
+	NAU8825_L_MUTE_SFT, 1, 1),
+	SOC_DAPM_SINGLE("HP R Switch", NAU8825_HSVOL_CTRL,
+	NAU8825_R_MUTE_SFT, 1, 1),
+};
+
+static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
+
+	SND_SOC_DAPM_INPUT("Mic Jack"),

Input and output widgets should have the same name as the matching pin of the CODEC.

sound/soc/codecs/nau8825.c line 78

Quoted 1 line
sound/soc/codecs/nau8825.c new file +1 -0
+	SND_SOC_DAPM_MICBIAS("MIC BIAS", NAU8825_BOOST, NAU8825_G_BIAS_SFT, 0),

New drivers shouldn't use DAPM_MICBIAS widgets as they are known to be broken. Use a DAPM_SUPPLY widget instead.

sound/soc/codecs/nau8825.c line 83

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	SND_SOC_DAPM_SUPPLY("micbias", SND_SOC_NOPM, 0, 0,
+				NULL, SND_SOC_DAPM_PRE_PMU
+				| SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("vmid", SND_SOC_NOPM, 0, 0, NULL,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),

Both the vmid and micbias supply seem to be unused and don't do anything either.

sound/soc/codecs/nau8825.c line 88

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
+	/* ADC IF1  */
+	SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),

This one seems to be unused, and doesn't do anything either.

sound/soc/codecs/nau8825.c line 95

Quoted 7 lines
sound/soc/codecs/nau8825.c new file +7 -0
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	/* DACs */
+	SND_SOC_DAPM_DAC_E("DAC L1", NULL, NAU8825_DAC_CTRL,
+				NAU8825_DAC_L_SFT, 0, NULL,
+				SND_SOC_DAPM_PRE_PMD),

Just use DAC instead of DAC_E if you don't have to implement a callback

sound/soc/codecs/nau8825.c line 98

Quoted 3 lines
sound/soc/codecs/nau8825.c new file +3 -0
+	SND_SOC_DAPM_DAC_E("DAC R1", NULL, NAU8825_DAC_CTRL,
+				NAU8825_DAC_R_SFT, 0, NULL,
+				SND_SOC_DAPM_PRE_PMD),

Same here.

sound/soc/codecs/nau8825.c line 103

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	/* SPO/HPO/LOUT/Mono Mixer */
+	SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0, nau8825_hpo_mix,
+				ARRAY_SIZE(nau8825_hpo_mix)),
+	SND_SOC_DAPM_PGA_S("HP amp", 1, NAU8825_CLASS_G_CTRL,
+				NAU8825_CLASS_G_SHIFT, 0, NULL, 0),

No need for _S if there is no sub-sequencing involved.

sound/soc/codecs/nau8825.c line 108

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+};
+

[...

sound/soc/codecs/nau8825.c line 129

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +6 -0
+static int nau8825_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *tmp)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;

rtd->codec does not necessarily point to your CODEC device, use dai->codec instead. As rule of thumb you should never have to look at the snd_soc_pcm_runtime in a CODEC driver.

[...]

sound/soc/codecs/nau8825.c line 218

Quoted 10 lines
sound/soc/codecs/nau8825.c new file +10 -0
+
+static void config_fll_clk_12m(struct snd_soc_codec *codec)
+{
+	snd_soc_update_bits(codec, NAU8825_CLK_DIVIDER, 0x000F, 0x0003);
+	snd_soc_update_bits(codec, NAU8825_FL_1, 0x007F, 0x0001);
+	snd_soc_write(codec, NAU8825_FL_2, 0xC49B);
+	snd_soc_update_bits(codec, NAU8825_FL_3, 0x03FF, 0x0020);
+	snd_soc_update_bits(codec, NAU8825_FL_4, 0x0C00, 0x0800);
+	snd_soc_update_bits(codec, NAU8825_FL_5, 0x2000, 0x0000);
+	snd_soc_update_bits(codec, NAU8825_FL_6, 0x4000, 0x4000);

So what do these magic values do?

sound/soc/codecs/nau8825.c line 221

Quoted 3 lines
sound/soc/codecs/nau8825.c new file +3 -0
+}
+
+void set_sys_clk(struct snd_soc_codec *codec, int sys_clk)

static

sound/soc/codecs/nau8825.c

Quoted 2 lines
sound/soc/codecs/nau8825.c new file +2 -0
+{
+	pr_debug("%s :: sys_clk=%x\n", __func__, sys_clk);

[...

sound/soc/codecs/nau8825.c line 291

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+static int nau8825_codec_suspend(struct snd_soc_codec *codec)
+{
+	nau8825_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}

set the suspend_bias_off flag in your codec driver to let the core take care of this.

sound/soc/codecs/nau8825.c line 297

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +6 -0
+
+static int nau8825_resume(struct snd_soc_codec *codec)
+{
+	nau8825_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}

This is not necessary the core already takes care of it.

Quoted 1 line

+

[...]

sound/soc/codecs/nau8825.c line 361

Quoted 10 lines
sound/soc/codecs/nau8825.c new file +10 -0
+static int nau8825_codec_probe(struct snd_soc_codec *codec)
+{
+	int i;
+	struct nau8825_priv *nau8825;
+
+	nau8825 = snd_soc_codec_get_drvdata(codec);
+	nau8825->codec = codec;
+	/*writing initial register values to the codec*/
+	for (i = 0; i < ARRAY_SIZE(nau8825_reg); i++)
+		snd_soc_write(codec, nau8825_reg[i].reg, nau8825_reg[i].def);

If that is really necessary use regmap_sync() and preferably in the i2c probe function. But I'd expect that a soft reset should put the device in the default register configuration?

Quoted 3 lines
sound/soc/codecs/nau8825.c new file +3 -0
+	return 0;
+}
+

[...]

Quoted 1 line

+static struct snd_soc_codec_driver soc_codec_driver_nau8825 = {

const

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	.probe = nau8825_codec_probe,
+	.remove	= nau8825_codec_remove,
+	.suspend = nau8825_codec_suspend,
+	.resume	= nau8825_resume,
+	.set_bias_level	= nau8825_set_bias_level,

sound/soc/codecs/nau8825.c

Quoted 10 lines
sound/soc/codecs/nau8825.c new file +9 -0
+	.controls = nau8825_snd_controls,
+	.num_controls = ARRAY_SIZE(nau8825_snd_controls),
+	.dapm_widgets = nau8825_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets),
+	.dapm_routes = nau8825_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes),
+};
+
 
+static struct snd_soc_dai_ops nau8825_dai_ops = {

const

Quoted 26 lines
sound/soc/codecs/nau8825.c new file +26 -0
+	.hw_params	= nau8825_hw_params,
+	.set_sysclk	= nau8825_dai_set_sysclk,
+	.set_fmt	= nau8825_set_dai_fmt,
+	.digital_mute	= nau8825_dac_mute,
+};
+
+static struct snd_soc_dai_driver nau8825_dai_driver[] = {
+	{
+		.name = "nau8825-aif1",
+			.playback = {
+				.stream_name	 = "AIF1 Playback",
+				.channels_min	 = 1,
+				.channels_max	 = 2,
+				.rates		 = NAU8825_RATES,
+				.formats	 = NAU8825_FORMATS,
+			},
+			.capture = {
+				.stream_name	 = "AIF1 Capture",
+				.channels_min	 = 1,
+				.channels_max	 = 2,
+				.rates		 = NAU8825_RATES,
+				.formats	 = NAU8825_FORMATS,
+			},
+		.ops = &nau8825_dai_ops,
+	}
+};

sound/soc/codecs/nau8825.c line 538

Quoted 10 lines
sound/soc/codecs/nau8825.c new file +10 -0
+
+
+static int nau8825_i2c_probe(struct i2c_client *i2c,
+				 const struct i2c_device_id *i2c_id)
+{
+	struct nau8825_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	struct nau8825_priv *nau8825;
+	int ret;
+
+	nau8825 = devm_kzalloc(&i2c->dev, sizeof(struct nau8825_priv),

preferred form for this is sizeof(*nau8825)

[...]

sound/soc/codecs/nau8825.c line 593

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+MODULE_DESCRIPTION("ASoC NAU8825 codec driver");
+MODULE_AUTHOR("Nuvoton");
+MODULE_LICENSE("GPL v2");
+
+

No need for the extra new lines at the end

Quoted 7 lines
sound/soc/codecs/nau8825.h new file +1 -0
new file mode 100644
index 0000000..b16d4d1
@@ -0,0 +1,150 @@
+/*

[...]

Quoted 7 lines
sound/soc/codecs/nau8825.h new file +7 -0
+
+struct nau8825_priv {
+	struct snd_soc_codec *codec;
+	struct nau8825_platform_data pdata;
+	struct regmap *regmap;
+	struct i2c_client *i2c;
+	struct snd_soc_jack *hp_jack;

sound/soc/codecs/nau8825.h line 149

Quoted 10 lines
sound/soc/codecs/nau8825.h new file +10 -0
+	struct snd_soc_jack *mic_jack;
+	struct delayed_work delayed_work;
+
+	struct workqueue_struct *workqueue;
+	struct mutex mutex;
+	unsigned int irq;
+	bool jd_status;
+	bool bp_status;
+	int	jack_type;
+};

It looks like pretty much all of the fields in the struct are not used by the driver.

Quoted 2 lines

+#endif /* _NAU8825_H */

#2 lore raw
Quoted 17 lines · Lars-Peter Clausen
Quoted 16 lines · Chih-Chiang Chang

The NAU88L25 is an ultra-low power high performance audio codec designed for smartphone, tablet PC, and other portable devices by Nuvoton, now add linux driver support for it.

---
  include/sound/nau8825_plat.h |  22 ++
  sound/soc/codecs/Kconfig     |   5 +
  sound/soc/codecs/Makefile    |   2 +
  sound/soc/codecs/nau8825.c   | 593 +++++++++++++++++++++++++++++++++++++++++++
  sound/soc/codecs/nau8825.h   | 150 +++++++++++
  5 files changed, 772 insertions(+)

create mode 100644 include/sound/nau8825_plat.h
create mode 100644 sound/soc/codecs/nau8825.c
create mode 100644 sound/soc/codecs/nau8825.h

Quoted 8 lines

include/sound/nau8825_plat.h

Quoted 5 lines
include/sound/nau8825_plat.h new file +0 -0
new file mode 100644
index 0000000..87afcd3

the preferred place for platform_data files is include/linux/platform_data/, but the driver doesn't seem to use the platform data anyway, so maybe drop it?

The data is reserved for future use, so drop it now.

For the preferred place for platform_data files, there are more than 300 files in the sound/soc/codecs folder. But I find only few files refer the platform_data files in include/linux/platform_data/ folder, most files put platform_data files in include/sound/ folder.

	cczhang@MS00-Linux:~/broonie_linux/sound/sound/soc/codecs$ grep -nr
"linux/platform_data/" *
	adau1761.c:20:#include <linux/platform_data/adau17x1.h>
	adau1781.c:20:#include <linux/platform_data/adau17x1.h>
	adau17x1.h:5:#include <linux/platform_data/adau17x1.h>
	adau1977.c:16:#include <linux/platform_data/adau1977.h>
	ssm2518.c:17:#include <linux/platform_data/ssm2518.h>
Quoted 13 lines

[...]

sound/soc/codecs/nau8825.c line 2

Quoted 8 lines
sound/soc/codecs/nau8825.c new file +2 -0
new file mode 100644
index 0000000..a8c8f59
@@ -0,0 +1,593 @@
+/*
+ * linux/sound/soc/codecs/nau8825.c

No need to include the file path in the header of the file, this will just become outdated if the file is ever moved.

Removed the file path in source.

Quoted 13 lines

[...]

sound/soc/codecs/nau8825.c line 43

Quoted 9 lines
sound/soc/codecs/nau8825.c new file +9 -0
+static int nau8825_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai);
+static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai,
+				unsigned int fmt);
+static int nau8825_set_bias_level(struct snd_soc_codec *codec,
+				enum snd_soc_bias_level level);
+static int nau8825_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+				unsigned int freq, int dir);

These forward declarations don't seem to be necessary.

Removed.

Quoted 9 lines

[...]

sound/soc/codecs/nau8825.c line 59

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +4 -0
+static const struct snd_kcontrol_new nau8825_snd_controls[] = {
+
 
+	SOC_SINGLE("HP Class OP", NAU8825_CLASS_G_CTRL, NAU8825_CLASS_G_SHIFT,
+				 1, 0),

What is "Class OP"?

"Class OP" means amplifier. The code is removed due to DAC DAPM widgets have the same bit control for NAU8825_CLASS_G_CTRL.

Quoted 6 lines

sound/soc/codecs/nau8825.c line 61

Quoted 3 lines
sound/soc/codecs/nau8825.c new file +2 -0
+	SOC_SINGLE("DAC Right", NAU8825_DAC_CTRL, NAU8825_DAC_R_SFT, 1, 0),
+	SOC_SINGLE("DAC Left", NAU8825_DAC_CTRL, NAU8825_DAC_L_SFT, 1, 0),

The same bits are controlled by the DAC DAPM widgets, there shouldn't be any controls for them.

Removed.

Quoted 8 lines

sound/soc/codecs/nau8825.c line 65

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +4 -0
+	SOC_SINGLE("DAC Right Clock", NAU8825_DAC_CTRL, NAU8825_DAC_CLK_R_SFT,
+				1, 0),
+	SOC_SINGLE("DAC Left Clock", NAU8825_DAC_CTRL, NAU8825_DAC_CLK_L_SFT,
+				1, 0),

The clock controls should probably not be user controllable but rather be DAPM supply widgets.

The code is not used, removed.

Quoted 16 lines

sound/soc/codecs/nau8825.c line 77

Quoted 13 lines
sound/soc/codecs/nau8825.c new file +12 -0
+};
+
+static const struct snd_kcontrol_new nau8825_hpo_mix[] = {
+	SOC_DAPM_SINGLE("HP L Switch", NAU8825_HSVOL_CTRL,
+	NAU8825_L_MUTE_SFT, 1, 1),
+	SOC_DAPM_SINGLE("HP R Switch", NAU8825_HSVOL_CTRL,
+	NAU8825_R_MUTE_SFT, 1, 1),
+};
+
+static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
+
+	SND_SOC_DAPM_INPUT("Mic Jack"),

Input and output widgets should have the same name as the matching pin of the CODEC.

Modified as below.

	SND_SOC_DAPM_INPUT("MIC"),
Quoted 5 lines

sound/soc/codecs/nau8825.c line 78

Quoted 2 lines
sound/soc/codecs/nau8825.c new file +1 -0
+	SND_SOC_DAPM_MICBIAS("MIC BIAS", NAU8825_BOOST, NAU8825_G_BIAS_SFT, 0),

New drivers shouldn't use DAPM_MICBIAS widgets as they are known to be broken. Use a DAPM_SUPPLY widget instead.

Modified as below.

	SND_SOC_DAPM_SUPPLY("MIC BIAS", NAU8825_BOOST, NAU8825_G_BIAS_SFT, 0,
				NULL, 0),
Quoted 8 lines

sound/soc/codecs/nau8825.c line 83

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	SND_SOC_DAPM_SUPPLY("micbias", SND_SOC_NOPM, 0, 0,
+				NULL, SND_SOC_DAPM_PRE_PMU
+				| SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("vmid", SND_SOC_NOPM, 0, 0, NULL,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),

Both the vmid and micbias supply seem to be unused and don't do anything either.

Removed.

Quoted 8 lines

sound/soc/codecs/nau8825.c line 88

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
+	/* ADC IF1  */
+	SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),

This one seems to be unused, and doesn't do anything either.

Removed.

Quoted 10 lines

sound/soc/codecs/nau8825.c line 95

Quoted 8 lines
sound/soc/codecs/nau8825.c new file +7 -0
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	/* DACs */
+	SND_SOC_DAPM_DAC_E("DAC L1", NULL, NAU8825_DAC_CTRL,
+				NAU8825_DAC_L_SFT, 0, NULL,
+				SND_SOC_DAPM_PRE_PMD),

Just use DAC instead of DAC_E if you don't have to implement a callback

Modified as below.

	SND_SOC_DAPM_DAC("DAC L1", NULL, NAU8825_DAC_CTRL,
				NAU8825_DAC_L_SFT, 0),
Quoted 6 lines

sound/soc/codecs/nau8825.c line 98

Quoted 4 lines
sound/soc/codecs/nau8825.c new file +3 -0
+	SND_SOC_DAPM_DAC_E("DAC R1", NULL, NAU8825_DAC_CTRL,
+				NAU8825_DAC_R_SFT, 0, NULL,
+				SND_SOC_DAPM_PRE_PMD),

Same here.

Modified as below.

	SND_SOC_DAPM_DAC("DAC R1", NULL, NAU8825_DAC_CTRL,
				NAU8825_DAC_R_SFT, 0),
Quoted 8 lines

sound/soc/codecs/nau8825.c line 103

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	/* SPO/HPO/LOUT/Mono Mixer */
+	SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0, nau8825_hpo_mix,
+				ARRAY_SIZE(nau8825_hpo_mix)),
+	SND_SOC_DAPM_PGA_S("HP amp", 1, NAU8825_CLASS_G_CTRL,
+				NAU8825_CLASS_G_SHIFT, 0, NULL, 0),

No need for _S if there is no sub-sequencing involved.

Modified as below.

	SND_SOC_DAPM_SUPPLY("HP amp", NAU8825_CLASS_G_CTRL,
				NAU8825_CLASS_G_SHIFT, 0, NULL, 0),
Quoted 7 lines

sound/soc/codecs/nau8825.c line 108

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +5 -0
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+};
+

[...

Quoted 12 lines

sound/soc/codecs/nau8825.c line 129

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +6 -0
+static int nau8825_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *tmp)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;

rtd->codec does not necessarily point to your CODEC device, use dai->codec instead. As rule of thumb you should never have to look at the snd_soc_pcm_runtime in a CODEC driver.

Modified as below.

static int nau8825_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;
Quoted 14 lines

[...]

sound/soc/codecs/nau8825.c line 218

Quoted 10 lines
sound/soc/codecs/nau8825.c new file +10 -0
+
+static void config_fll_clk_12m(struct snd_soc_codec *codec)
+{
+	snd_soc_update_bits(codec, NAU8825_CLK_DIVIDER, 0x000F, 0x0003);
+	snd_soc_update_bits(codec, NAU8825_FL_1, 0x007F, 0x0001);
+	snd_soc_write(codec, NAU8825_FL_2, 0xC49B);
+	snd_soc_update_bits(codec, NAU8825_FL_3, 0x03FF, 0x0020);
+	snd_soc_update_bits(codec, NAU8825_FL_4, 0x0C00, 0x0800);
+	snd_soc_update_bits(codec, NAU8825_FL_5, 0x2000, 0x0000);
+	snd_soc_update_bits(codec, NAU8825_FL_6, 0x4000, 0x4000);

So what do these magic values do?

Modified as below, add definition and remark.

static void config_fll_clk_12m(struct snd_soc_codec *codec)

{
	struct nau8825_priv *nau8825 = snd_soc_codec_get_drvdata(codec);

	regmap_update_bits(nau8825->regmap, NAU8825_CLK_DIVIDER,
				NAU8825_CLK_MCLK_SRC_MASK, 0x0003);
	regmap_update_bits(nau8825->regmap, NAU8825_FLL_1,
				NAU8825_FLL_RATIO_MASK, 0x0001);
	/* FLL 16-bit fractional input */
	regmap_write(nau8825->regmap, NAU8825_FLL_2, 0xC49B);
	/* FLL 10-bit integer input */
	regmap_update_bits(nau8825->regmap, NAU8825_FLL_3,
				NAU8825_FLL_INTEGER_MASK, 0x0020);
	/* FLL pre-scaler */
	regmap_update_bits(nau8825->regmap, NAU8825_FLL_4,
				NAU8825_FLL_REF_DIV_MASK, 0x0800);
	/* select divied VCO input */
	regmap_update_bits(nau8825->regmap, NAU8825_FLL_5,
				NAU8825_FLL_FILTER_SW_MASK, 0x0000);
	/* FLL sigma delta modulator enable */
	regmap_update_bits(nau8825->regmap, NAU8825_FLL_6,
				NAU8825_SDM_EN_MASK, 0x4000);
Quoted 6 lines

sound/soc/codecs/nau8825.c line 221

Quoted 4 lines
sound/soc/codecs/nau8825.c new file +3 -0
+}
+
+void set_sys_clk(struct snd_soc_codec *codec, int sys_clk)

static

Modified as below.

static void set_sys_clk(struct snd_soc_codec *codec, int sys_clk)

Quoted 4 lines

sound/soc/codecs/nau8825.c

Quoted 3 lines
sound/soc/codecs/nau8825.c new file +2 -0
+{
+	pr_debug("%s :: sys_clk=%x\n", __func__, sys_clk);

[...

Quoted 8 lines

sound/soc/codecs/nau8825.c line 291

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+static int nau8825_codec_suspend(struct snd_soc_codec *codec)
+{
+	nau8825_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}

set the suspend_bias_off flag in your codec driver to let the core take care of this.

Removed nau8825_codec_suspend() and added suspend_bias_off flag in soc_codec_driver_nau8825.

        .remove = nau8825_codec_remove,
-       .suspend = nau8825_codec_suspend,
-       .resume = nau8825_resume,
+       .suspend_bias_off = true,
        .set_bias_level = nau8825_set_bias_level,
        .controls = nau8825_snd_controls,
        .num_controls = ARRAY_SIZE(nau8825_snd_controls),
Quoted 9 lines

sound/soc/codecs/nau8825.c line 297

Quoted 7 lines
sound/soc/codecs/nau8825.c new file +6 -0
+
+static int nau8825_resume(struct snd_soc_codec *codec)
+{
+	nau8825_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}

This is not necessary the core already takes care of it.

Removed.

Quoted 17 lines
Quoted 2 lines

+

[...]

sound/soc/codecs/nau8825.c line 361

Quoted 10 lines
sound/soc/codecs/nau8825.c new file +10 -0
+static int nau8825_codec_probe(struct snd_soc_codec *codec)
+{
+	int i;
+	struct nau8825_priv *nau8825;
+
+	nau8825 = snd_soc_codec_get_drvdata(codec);
+	nau8825->codec = codec;
+	/*writing initial register values to the codec*/
+	for (i = 0; i < ARRAY_SIZE(nau8825_reg); i++)
+		snd_soc_write(codec, nau8825_reg[i].reg, nau8825_reg[i].def);

If that is really necessary use regmap_sync() and preferably in the i2c probe function. But I'd expect that a soft reset should put the device in the default register configuration?

About the regmap_sync(), I cannot find it in Linux. Do you mean the regcache_sync()? But it is used to sync the register cache with the hardware, not set reg_defaults array to hardware.

Remove nau8825_codec_probe() and add below code in nau8825_i2c_probe().

                dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
                goto err_enable;
        }
+       /* software reset */
+       regmap_write(nau8825->regmap, NAU8825_RESET, 0x01);
+       regmap_write(nau8825->regmap, NAU8825_RESET, 0x02);
+       /*writing initial register values to the codec*/
+       for (i = 0; i < ARRAY_SIZE(nau8825_reg); i++)
+               regmap_write(nau8825->regmap, nau8825_reg[i].reg,
+               nau8825_reg[i].def);
+
        ret = snd_soc_register_codec(&i2c->dev, &soc_codec_driver_nau8825,
                                nau8825_dai_driver,
                                ARRAY_SIZE(nau8825_dai_driver));
Quoted 8 lines
Quoted 4 lines
sound/soc/codecs/nau8825.c new file +3 -0
+	return 0;
+}
+

[...]

Quoted 1 line

+static struct snd_soc_codec_driver soc_codec_driver_nau8825 = {

const

Modified as below.

static const struct snd_soc_codec_driver soc_codec_driver_nau8825 = {

Quoted 15 lines
Quoted 14 lines
sound/soc/codecs/nau8825.c new file +13 -0
+	.probe = nau8825_codec_probe,
+	.remove	= nau8825_codec_remove,
+	.suspend = nau8825_codec_suspend,
+	.resume	= nau8825_resume,
+	.set_bias_level	= nau8825_set_bias_level,
+	.controls = nau8825_snd_controls,
+	.num_controls = ARRAY_SIZE(nau8825_snd_controls),
+	.dapm_widgets = nau8825_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets),
+	.dapm_routes = nau8825_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes),
+};
+
Quoted 3 lines
Quoted 1 line

+static struct snd_soc_dai_ops nau8825_dai_ops = {

const

Modified as below.

static const struct snd_soc_dai_ops nau8825_dai_ops = {

Quoted 31 lines
Quoted 31 lines
sound/soc/codecs/nau8825.c new file +30 -0
+	.hw_params	= nau8825_hw_params,
+	.set_sysclk	= nau8825_dai_set_sysclk,
+	.set_fmt	= nau8825_set_dai_fmt,
+	.digital_mute	= nau8825_dac_mute,
+};
+
+static struct snd_soc_dai_driver nau8825_dai_driver[] = {
+	{
+		.name = "nau8825-aif1",
+			.playback = {
+				.stream_name	 = "AIF1 Playback",
+				.channels_min	 = 1,
+				.channels_max	 = 2,
+				.rates		 = NAU8825_RATES,
+				.formats	 = NAU8825_FORMATS,
+			},
+			.capture = {
+				.stream_name	 = "AIF1 Capture",
+				.channels_min	 = 1,
+				.channels_max	 = 2,
+				.rates		 = NAU8825_RATES,
+				.formats	 = NAU8825_FORMATS,
+			},
+		.ops = &nau8825_dai_ops,
+	}
+};
+
+
+static int nau8825_i2c_probe(struct i2c_client *i2c,
+				 const struct i2c_device_id *i2c_id)
Quoted 8 lines

sound/soc/codecs/nau8825.c line 538

Quoted 6 lines
sound/soc/codecs/nau8825.c new file +6 -0
+{
+	struct nau8825_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	struct nau8825_priv *nau8825;
+	int ret;
+
+	nau8825 = devm_kzalloc(&i2c->dev, sizeof(struct nau8825_priv),

preferred form for this is sizeof(*nau8825)

Modified as below.

	nau8825 = devm_kzalloc(&i2c->dev, sizeof(*nau8825),
Quoted 9 lines

[...]

sound/soc/codecs/nau8825.c line 593

Quoted 5 lines
sound/soc/codecs/nau8825.c new file +5 -0
+MODULE_DESCRIPTION("ASoC NAU8825 codec driver");
+MODULE_AUTHOR("Nuvoton");
+MODULE_LICENSE("GPL v2");
+
+

No need for the extra new lines at the end

Removed the new lines.

Quoted 21 lines
Quoted 8 lines
sound/soc/codecs/nau8825.h new file +1 -0
new file mode 100644
index 0000000..b16d4d1
@@ -0,0 +1,150 @@
+/*

[...]

Quoted 12 lines
sound/soc/codecs/nau8825.h new file +12 -0
+
+struct nau8825_priv {
+	struct snd_soc_codec *codec;
+	struct nau8825_platform_data pdata;
+	struct regmap *regmap;
+	struct i2c_client *i2c;
+	struct snd_soc_jack *hp_jack;
+	struct snd_soc_jack *mic_jack;
+	struct delayed_work delayed_work;
+
+	struct workqueue_struct *workqueue;
+	struct mutex mutex;
Quoted 8 lines

sound/soc/codecs/nau8825.h line 149

Quoted 5 lines
sound/soc/codecs/nau8825.h new file +5 -0
+	unsigned int irq;
+	bool jd_status;
+	bool bp_status;
+	int	jack_type;
+};

It looks like pretty much all of the fields in the struct are not used by the driver.

Removed some field and modified as below.

@@ -136,15 +163,7 @@ struct nau8825_priv {
        struct nau8825_platform_data pdata;
        struct regmap *regmap;
        struct i2c_client *i2c;
-       struct snd_soc_jack *hp_jack;
-       struct snd_soc_jack *mic_jack;
-       struct delayed_work delayed_work;
-
-       struct workqueue_struct *workqueue;
-       struct mutex mutex;
-       unsigned int irq;
-       bool jd_status;
-       bool bp_status;
-       int     jack_type;
+       struct snd_soc_jack *jack;
+       struct delayed_work jack_detect_work;

};

Quoted 4 lines
Quoted 3 lines

+#endif /* _NAU8825_H */