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

This commit is contained in:
Linux Build Service Account 2018-02-16 16:05:51 -08:00 committed by Gerrit - the friendly Code Review server
commit b7da83b2b8
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 *