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

AQT1000 codec supports multiple micbias voltage settings. Add an
API to client modules to adjust the micbias voltage based on their
desire voltage requirements.

Change-Id: If89b836ab60b66e9ec1000fe6d07f4b1a8484b01
Signed-off-by: Sudheer Papothi <spapothi@codeaurora.org>
This commit is contained in:
Sudheer Papothi 2017-12-29 02:12:47 +05:30
parent db20f92cb3
commit 7c53cb5010
2 changed files with 105 additions and 0 deletions

View file

@ -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 */

View file

@ -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 *