On Sun, Feb 15, 2015 at 03:49:30PM +0800, Wan Zongshun wrote:
- /* SP Class-D mute control */
- SOC_DOUBLE("HP Playback Switch", NAU8824_HP_MUTE, NAU8824_L_MUTE_SFT,
NAU8824_R_MUTE_SFT, 1, 1),
- SOC_SINGLE_TLV("HP Left Volume", NAU8824_HP_VOL, NAU8824_L_VOL_SFT,
NAU8824_VOL_RSCL_RANGE, 1, out_hp_vol_tlv),
- SOC_SINGLE_TLV("HP Right Volume", NAU8824_HP_VOL, NAU8824_R_VOL_SFT,
NAU8824_VOL_RSCL_RANGE, 1, out_hp_vol_tlv),
I would have expected the headphone volume control to be a stereo (double) control - same for speakers.
- /* DMIC control */
- SOC_DOUBLE("DMIC L R Switch", NAU8824_ENA_CTRL, NAU8824_DMIC_CH0_SFT,
NAU8824_DMIC_CH1_SFT, 1, 0),
- SOC_SINGLE("DMIC Enable", NAU8824_BIAS_ADJ, NAU8824_DMIC1_SFT, 1, 0),
- SOC_SINGLE("VMID Switch", NAU8824_BIAS_ADJ, NAU8824_VMID_SFT, 1, 0),
- SOC_SINGLE("BIAS Switch", NAU8824_BOOST, NAU8824_G_BIAS_SFT, 1, 0),
This all looks like stuff that should be done with DAPM...
- SOC_DOUBLE_R_TLV("MIC L R Gain", NAU8824_ADC_CH0_DGAIN_CTRL,
NAU8824_ADC_CH1_DGAIN_CTRL, 0,
NAU8824_ADC_VOL_RSCL_RANGE, 0, adc_vol_tlv),
All volume controls should be called Volume.
+static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
+{
- struct snd_soc_codec *codec = w->codec;
w->codec is going away, use snd_soc_dapm_to_codec(). You should always submit against current code.
+static const struct snd_kcontrol_new nau8824_rec_l_mix[] = {
SOC_DAPM_SINGLE("BST1 Switch", SND_SOC_NOPM,
0, 0, 0),
+};
Please use normal indentation, a single tab is enough.
+static int nau8824_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
+{
- return 0;
+}
Remove empty functions.
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
reg_val_2 |= NAU8824_I2S_MS_M;
break;
- case SND_SOC_DAIFMT_CBS_CFS:
break;
- case SND_SOC_DAIFMT_CBS_CFM:
break;
These two clocking configurations appear not to differ in terms of what we do to the device - this suggests that only one of them is actually supported.
+static int nau8824_FLL_freerun_mode(struct snd_soc_codec *codec, int IsEnable) +{
- if (IsEnable == true) {
This doesn't look like Linux coding style...
+void set_sys_clk(struct snd_soc_codec *codec, int sys_clk) +{
- pr_debug("%s sys_clk=%x\n", __func__, sys_clk);
- switch (sys_clk) {
- case NAU8824_INTERNALCLOCK:
nau8824_FLL_freerun_mode(codec, true);
break;
- case NAU8824_MCLK:
- default:
nau8824_FLL_freerun_mode(codec, false);
break;
- }
+}
...and I don't entirely see why it's a separate function to this (which is itself an internal wrapper function which possibly shouldn't exist)>
+static int nau8824_set_sysclk(struct snd_soc_codec *codec,
int clk_id, int source, unsigned int freq, int dir)
+{
- int divider = 1;
- if (clk_id == NAU8824_MCLK) {
set_sys_clk(codec, NAU8824_MCLK);
dev_dbg(codec->dev, "%s: input freq = %d divider = %d",
__func__, freq, divider);
- } else if (clk_id == NAU8824_INTERNALCLOCK) {
set_sys_clk(codec, NAU8824_INTERNALCLOCK);
- } else {
dev_err(codec->dev, "Wrong clock src\n");
return -EINVAL;
- }
Use switch statements rather than if trees like other drivers. It looks like clk_id should actually be source since we're selecting the clock to use rather than selecting which clock to configure.
+static int nau8824_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
+{
- dev_dbg(codec->dev, "## nau8824_set_bias_level %d\n", level);
- if (level == codec->dapm.bias_level) {
dev_dbg(codec->dev, "##set_bias_level: level returning...\r\n");
return -EINVAL;
- }
Why is this here - other drivers don't do this and it doesn't look device specific?
- switch (level) {
- case SND_SOC_BIAS_ON:
/* All power is driven by DAPM system*/
dev_dbg(codec->dev, "###nau8824_set_bias_level BIAS_ON\n");
snd_soc_update_bits(codec, NAU8824_BIAS_ADJ,
NAU8824_VMID_MASK, NAU8824_VMID_EN);
snd_soc_update_bits(codec, NAU8824_BOOST,
NAU8824_G_BIAS_MASK, NAU8824_G_BIAS_EN);
We turn on VMID last? That's a strange thing to do...
+static int nau8824_suspend(struct snd_soc_codec *codec) +{
- dev_dbg(codec->dev, "%s: Entered\n", __func__);
- nau8824_set_bias_level(codec, SND_SOC_BIAS_OFF);
- dev_dbg(codec->dev, "%s: Exiting\n", __func__);
- return 0;
+}
Set idle_bias_off (which it looks like you should be doing) and this becomes redundant. If you're *not* using idle_bias_off for some reason then the set_bias_level() work done in _ON should be undone in at least _SUSPEND rather than _OFF so we save power on idle.
+struct nau8824_init_reg {
- u8 reg;
- u16 val;
+};
This looks like you're reimplementing regmap's register sequence stuff... It's also a *very* large sequence you have, are you sure it's all required? It seems like this may be doing a bunch of machine specific configuration but since it's all magic numbers it's hard to tell.
+#define NAU8824_INIT_REG_LEN ARRAY_SIZE(init_list)
Just use ARRAY_SIZE().
+static int nau8824_reg_init(struct snd_soc_codec *codec) +{
- int i;
- mdelay(1);
- for (i = 0; i < NAU8824_INIT_REG_LEN; i++) {
if (init_list[i].reg == 0xFFFF)
mdelay(1);
else
snd_soc_write(codec, init_list[i].reg,
init_list[i].val);
- }
Use the standard regmap patch stuff. If you need the delays in the sequence implement that in the core, though I guess you don't since reg is a u8 and you're looking for 0xffff in it...
- /* Dynamic Headset detection enabled */
- snd_soc_update_bits(codec, 0x01, 0x400, 0x400);
- snd_soc_update_bits(codec, 0x02, 0x0008, 0x0008);
- snd_soc_update_bits(codec, 0x0f, 0x0300, 0x0100);
- snd_soc_write(codec, 0x09, 0xE000);
- snd_soc_write(codec, NAU8824_IRQ_SETTING, 0x1006);
- snd_soc_write(codec, 0x13, 0x1615);
- snd_soc_write(codec, 0x15, 0x0414);
- snd_soc_update_bits(codec, 0x16, 0xFF00, 0x5900);
- snd_soc_update_bits(codec, 0x66, 0x0070, 0x0060);
Too many magic numbers here I think and this looks like it should be configured using platform data and/or the machine driver (what if the headphone detection/IRQ aren't wired up?). I'd also expect to see reporting via the standard interfaces for jack reporting.
+static const struct i2c_device_id nau8824_i2c_id[] = {
- { "nau8824", 0},
- {"10508824:00", 0},
- {"10508824", 0},
- { }
+};
It looks like you've put some ACPI IDs in the I2C ID table here. At least I hope that's what the last two entries are... if they are ACPI IDs they should be registered as such. If they're something else then what are they?