Przeglądaj źródła

Merge "ASoC: AQT1000: Add API for adjusting the micbias voltage on AQT1000"

Linux Build Service Account 7 lat temu
rodzic
commit
b7da83b2b8
2 zmienionych plików z 105 dodań i 0 usunięć
  1. 28 0
      asoc/codecs/aqt1000/aqt1000-api.h
  2. 77 0
      asoc/codecs/aqt1000/aqt1000.c

+ 28 - 0
asoc/codecs/aqt1000/aqt1000-api.h

@@ -0,0 +1,28 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef AQT1000_API_H
+#define AQT1000_API_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <sound/soc.h>
+
+extern int aqt_mbhc_micb_adjust_voltage(struct snd_soc_codec *codec,
+					int volt, int micb_num);
+extern int aqt_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable);
+extern int aqt_get_micb_vout_ctl_val(u32 micb_mv);
+extern int aqt_micbias_control(struct snd_soc_codec *codec, int micb_num,
+			       int req, bool is_dapm);
+
+#endif /* AQT1000_API_H */

+ 77 - 0
asoc/codecs/aqt1000/aqt1000.c

@@ -35,6 +35,7 @@
 #include <sound/info.h>
 #include "aqt1000-registers.h"
 #include "aqt1000.h"
+#include "aqt1000-api.h"
 #include "aqt1000-routing.h"
 #include "../wcdcal-hwdep.h"
 #include "aqt1000-internal.h"
@@ -46,6 +47,7 @@
 #define  CF_MIN_3DB_150HZ   0x2
 
 #define AQT_VERSION_ENTRY_SIZE 17
+#define AQT_VOUT_CTL_TO_MICB(x) (1000 + x *50)
 
 static struct interp_sample_rate sr_val_tbl[] = {
 	{8000, 0x0}, {16000, 0x1}, {32000, 0x3}, {48000, 0x4}, {96000, 0x5},
@@ -682,6 +684,81 @@ static int aqt_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+/*
+ * aqt_mbhc_micb_adjust_voltage: adjust specific micbias voltage
+ * @codec: handle to snd_soc_codec *
+ * @req_volt: micbias voltage to be set
+ * @micb_num: micbias to be set, e.g. micbias1 or micbias2
+ *
+ * return 0 if adjustment is success or error code in case of failure
+ */
+int aqt_mbhc_micb_adjust_voltage(struct snd_soc_codec *codec,
+				   int req_volt, int micb_num)
+{
+	struct aqt1000 *aqt;
+	int cur_vout_ctl, req_vout_ctl;
+	int micb_reg, micb_val, micb_en;
+	int ret = 0;
+
+	if (!codec) {
+		pr_err("%s: Invalid codec pointer\n", __func__);
+		return -EINVAL;
+	}
+
+	if (micb_num != MIC_BIAS_1)
+		return -EINVAL;
+	else
+		micb_reg = AQT1000_ANA_MICB1;
+
+	aqt = snd_soc_codec_get_drvdata(codec);
+	mutex_lock(&aqt->micb_lock);
+
+	/*
+	 * If requested micbias voltage is same as current micbias
+	 * voltage, then just return. Otherwise, adjust voltage as
+	 * per requested value. If micbias is already enabled, then
+	 * to avoid slow micbias ramp-up or down enable pull-up
+	 * momentarily, change the micbias value and then re-enable
+	 * micbias.
+	 */
+	micb_val = snd_soc_read(codec, micb_reg);
+	micb_en = (micb_val & 0xC0) >> 6;
+	cur_vout_ctl = micb_val & 0x3F;
+
+	req_vout_ctl = aqt_get_micb_vout_ctl_val(req_volt);
+	if (req_vout_ctl < 0) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	if (cur_vout_ctl == req_vout_ctl) {
+		ret = 0;
+		goto exit;
+	}
+
+	dev_dbg(codec->dev, "%s: micb_num: %d, cur_mv: %d, req_mv: %d, micb_en: %d\n",
+		 __func__, micb_num, AQT_VOUT_CTL_TO_MICB(cur_vout_ctl),
+		 req_volt, micb_en);
+
+	if (micb_en == 0x1)
+		snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
+
+	snd_soc_update_bits(codec, micb_reg, 0x3F, req_vout_ctl);
+
+	if (micb_en == 0x1) {
+		snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
+		/*
+		 * Add 2ms delay as per HW requirement after enabling
+		 * micbias
+		 */
+		usleep_range(2000, 2100);
+	}
+exit:
+	mutex_unlock(&aqt->micb_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(aqt_mbhc_micb_adjust_voltage);
+
 /*
  * aqt_micbias_control: enable/disable micbias
  * @codec: handle to snd_soc_codec *