Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8bb6f409 authored by Sudheer Papothi's avatar Sudheer Papothi
Browse files

ASoC: AQT1000: Fix hardware sequence for AQT1000



Fix hardware sequence for AQT1000 as per hardware
requirements to bring codec out of reset for playback
and capture usecases on headset.

Change-Id: I7419aec36aefc2887583308a60d1ea246d000469
Signed-off-by: default avatarSudheer Papothi <spapothi@codeaurora.org>
parent 8ed1b0eb
Loading
Loading
Loading
Loading
+52 −2
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <linux/mfd/core.h>
@@ -21,6 +23,9 @@
#include <linux/debugfs.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include "../msm-cdc-pinctrl.h"
#include "../msm-cdc-supply.h"
@@ -93,8 +98,22 @@ static int aqt1000_bringup(struct aqt1000 *aqt)
	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_MCLK2_I2S_HS_CLK_PRG,
			   0x01, 0x01);

	regmap_update_bits(aqt->regmap, AQT1000_CHIP_CFG0_CLK_CFG_MCLK,
			   0x04, 0x00);

	/* Add 100usec delay as per HW requirement */
	usleep_range(100, 110);
	regmap_update_bits(aqt->regmap, AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL,
			   0x01, 0x01);
	regmap_update_bits(aqt->regmap, AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
			   0x01, 0x01);
	regmap_update_bits(aqt->regmap, AQT1000_CHIP_CFG0_CLK_CTL_CDC_DIG,
			   0x01, 0x01);

	/* Codec digital reset */
	regmap_update_bits(aqt->regmap, AQT1000_CHIP_CFG0_RST_CTL, 0x01, 0x01);
	/* Add 100usec delay as per HW requirement */
	usleep_range(100, 110);

	return 0;
}
@@ -378,6 +397,13 @@ static struct aqt1000_pdata *aqt1000_populate_dt_data(struct device *dev)
		goto err_parse_dt_prop;
	}

	pdata->irq_gpio = of_get_named_gpio(dev->of_node,
					    "qcom,gpio-connect", 0);
	if (!gpio_is_valid(pdata->irq_gpio)) {
		dev_err(dev, "%s: TLMM connect gpio not found\n", __func__);
		goto err_parse_dt_prop;
	}

	return pdata;

err_parse_dt_prop:
@@ -457,6 +483,7 @@ static int aqt1000_i2c_probe(struct i2c_client *client,
	aqt1000->dev = &client->dev;
	aqt1000->dev_up = true;
	aqt1000->mclk_rate = pdata->mclk_rate;
	aqt1000->irq = client->irq;

	aqt1000->num_of_supplies = pdata->num_supplies;
	ret = msm_cdc_init_supplies(aqt1000->dev, &aqt1000->supplies,
@@ -496,6 +523,9 @@ static int aqt1000_i2c_probe(struct i2c_client *client,
		goto err_supplies;
	}

	pm_runtime_set_active(aqt1000->dev);
	pm_runtime_enable(aqt1000->dev);

	ret = aqt_register_codec(&client->dev);
	if (ret) {
		dev_err(aqt1000->dev, "%s: Codec registration failed\n",
@@ -506,6 +536,7 @@ static int aqt1000_i2c_probe(struct i2c_client *client,
	return ret;

err_cdc_register:
	pm_runtime_disable(aqt1000->dev);
	aqt1000_device_exit(aqt1000);
err_supplies:
	msm_cdc_release_supplies(aqt1000->dev, aqt1000->supplies,
@@ -527,6 +558,7 @@ static int aqt1000_i2c_remove(struct i2c_client *client)

	aqt = dev_get_drvdata(&client->dev);

	pm_runtime_disable(aqt->dev);
	msm_cdc_release_supplies(aqt->dev, aqt->supplies,
				 pdata->regulator,
				 pdata->num_supplies);
@@ -535,6 +567,22 @@ static int aqt1000_i2c_remove(struct i2c_client *client)
	return 0;
}

#ifdef CONFIG_PM
static int aqt1000_runtime_resume(struct device *dev)
{
	dev_dbg(dev, "%s system resume\n", __func__);

	return 0;
}

static int aqt1000_runtime_suspend(struct device *dev)
{
	dev_dbg(dev, "%s system suspend\n", __func__);

	return 0;
}
#endif

#ifdef CONFIG_PM_SLEEP
static int aqt1000_i2c_resume(struct device *dev)
{
@@ -556,8 +604,10 @@ static struct i2c_device_id aqt1000_id_table[] = {
MODULE_DEVICE_TABLE(i2c, aqt1000_id_table);

static const struct dev_pm_ops aqt1000_i2c_pm_ops = {
	.suspend = aqt1000_i2c_suspend,
	.resume = aqt1000_i2c_resume,
	SET_RUNTIME_PM_OPS(aqt1000_runtime_suspend,
			   aqt1000_runtime_resume, NULL)
	SET_SYSTEM_SLEEP_PM_OPS(aqt1000_i2c_suspend,
				aqt1000_i2c_resume)
};

static const struct of_device_id aqt_match_table[] = {
+7 −18
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ int aqt_request_irq(struct aqt1000 *aqt, int irq, const char *name,
	if (irq < 0)
		return irq;

	return request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT,
	return request_threaded_irq(irq, NULL, handler,
				    IRQF_ONESHOT | IRQF_TRIGGER_RISING,
				    name, data);
}
EXPORT_SYMBOL(aqt_request_irq);
@@ -160,6 +161,8 @@ static struct irq_chip aqt_irq_chip = {
	.irq_enable = aqt_irq_enable,
};

static struct lock_class_key aqt_irq_lock_class;

static int aqt_irq_map(struct irq_domain *irqd, unsigned int virq,
			irq_hw_number_t hw)
{
@@ -167,6 +170,7 @@ static int aqt_irq_map(struct irq_domain *irqd, unsigned int virq,

	irq_set_chip_data(virq, data);
	irq_set_chip_and_handler(virq, &aqt_irq_chip, handle_simple_irq);
	irq_set_lockdep_class(virq, &aqt_irq_lock_class);
	irq_set_nested_thread(virq, 1);
	irq_set_noprobe(virq);

@@ -196,12 +200,6 @@ int aqt_irq_init(struct aqt1000 *aqt)
		return -EINVAL;
	}

	if (!aqt->irq) {
		dev_dbg(aqt->dev, "%s: No interrupt specified\n", __func__);
		aqt->irq_base = 0;
		return 0;
	}

	pdata = dev_get_platdata(aqt->dev);
	if (!pdata) {
		dev_err(aqt->dev, "%s: Invalid platform data\n", __func__);
@@ -214,13 +212,7 @@ int aqt_irq_init(struct aqt1000 *aqt)
		flags = pdata->irq_flags;

	if (pdata->irq_gpio) {
		if (gpio_to_irq(pdata->irq_gpio) != aqt->irq) {
			dev_warn(aqt->dev, "%s: IRQ %d is not GPIO %d (%d)\n",
				 __func__, aqt->irq, pdata->irq_gpio,
				gpio_to_irq(pdata->irq_gpio));
		aqt->irq = gpio_to_irq(pdata->irq_gpio);
		}

		ret = devm_gpio_request_one(aqt->dev, pdata->irq_gpio,
					    GPIOF_IN, "AQT IRQ");
		if (ret) {
@@ -229,10 +221,6 @@ int aqt_irq_init(struct aqt1000 *aqt)
			pdata->irq_gpio = 0;
			return ret;
		}
	} else {
		dev_dbg(aqt->dev, "%s: irq_gpio is %d\n",
			__func__, pdata->irq_gpio);
		return 0;
	}

	irq_data = irq_get_irq_data(aqt->irq);
@@ -242,6 +230,7 @@ int aqt_irq_init(struct aqt1000 *aqt)
		return -EINVAL;
	}

	aqt->num_irq_regs = aqt_regmap_irq_chip.num_regs;
	for (i = 0; i < aqt->num_irq_regs; i++) {
		regmap_write(aqt->regmap,
			     (AQT1000_INTR_CTRL_INT_TYPE_2 + i), 0);
+17 −13
Original line number Diff line number Diff line
@@ -85,30 +85,30 @@ const struct snd_soc_dapm_route aqt_audio_map[] = {
	{"AQT ANC0 FB MUX", "ANC_IN_HPHL", "AQT RX INT1 MIX2"},
	{"AQT ANC1 FB MUX", "ANC_IN_HPHR", "AQT RX INT2 MIX2"},

	{"AQT I2S_L RX", "AIF1_PB", "AQT AIF1 PB"},
	{"AQT I2S_R RX", "AIF1_PB", "AQT AIF1 PB"},
	{"AQT I2S_L RX", NULL, "AQT AIF1 PB"},
	{"AQT I2S_R RX", NULL, "AQT AIF1 PB"},

	{"AQT RX INT1_1 MUX", "I2S_L", "AQT I2S_L RX"},
	{"AQT RX INT1_1 MUX", "I2S_R", "AQT I2S_R RX"},
	{"AQT RX INT1_1 MUX", "I2S0_L", "AQT I2S_L RX"},
	{"AQT RX INT1_1 MUX", "I2S0_R", "AQT I2S_R RX"},
	{"AQT RX INT1_1 MUX", "DEC_L", "AQT ADC0 MUX"},
	{"AQT RX INT1_1 MUX", "DEC_R", "AQT ADC1 MUX"},
	{"AQT RX INT1_1 MUX", "DEC_V", "AQT ADC2 MUX"},

	{"AQT RX INT2_1 MUX", "I2S_L", "AQT I2S_L RX"},
	{"AQT RX INT2_1 MUX", "I2S_R", "AQT I2S_R RX"},
	{"AQT RX INT2_1 MUX", "I2S0_L", "AQT I2S_L RX"},
	{"AQT RX INT2_1 MUX", "I2S0_R", "AQT I2S_R RX"},
	{"AQT RX INT2_1 MUX", "DEC_L", "AQT ADC0 MUX"},
	{"AQT RX INT2_1 MUX", "DEC_R", "AQT ADC1 MUX"},
	{"AQT RX INT2_1 MUX", "DEC_V", "AQT ADC2 MUX"},

	{"AQT RX INT1_2 MUX", "I2S_L", "AQT I2S_L RX"},
	{"AQT RX INT1_2 MUX", "I2S_R", "AQT I2S_R RX"},
	{"AQT RX INT1_2 MUX", "I2S0_L", "AQT I2S_L RX"},
	{"AQT RX INT1_2 MUX", "I2S0_R", "AQT I2S_R RX"},
	{"AQT RX INT1_2 MUX", "DEC_L", "AQT ADC0 MUX"},
	{"AQT RX INT1_2 MUX", "DEC_R", "AQT ADC1 MUX"},
	{"AQT RX INT1_2 MUX", "DEC_V", "AQT ADC2 MUX"},
	{"AQT RX INT1_2 MUX", "IIR0", "AQT IIR0"},

	{"AQT RX INT2_2 MUX", "I2S_L", "AQT I2S_L RX"},
	{"AQT RX INT2_2 MUX", "I2S_R", "AQT I2S_R RX"},
	{"AQT RX INT2_2 MUX", "I2S0_L", "AQT I2S_L RX"},
	{"AQT RX INT2_2 MUX", "I2S0_R", "AQT I2S_R RX"},
	{"AQT RX INT2_2 MUX", "DEC_L", "AQT ADC0 MUX"},
	{"AQT RX INT2_2 MUX", "DEC_R", "AQT ADC1 MUX"},
	{"AQT RX INT2_2 MUX", "DEC_V", "AQT ADC2 MUX"},
@@ -137,6 +137,8 @@ const struct snd_soc_dapm_route aqt_audio_map[] = {
	{"AQT RX INT1 DEM MUX", "CLSH_DSM_OUT", "AQT RX INT1 MIX2"},
	{"AQT RX INT1 DAC", NULL, "AQT RX INT1 DEM MUX"},
	{"AQT RX INT1 DAC", NULL, "AQT RX_BIAS"},
	{"AQT RX_BIAS", NULL, "AQT MCLK"},
	{"AQT MIC BIAS1", NULL, "AQT MCLK"},
	{"AQT HPHL PA", NULL, "AQT RX INT1 DAC"},
	{"AQT HPHL", NULL, "AQT HPHL PA"},

@@ -152,10 +154,12 @@ const struct snd_soc_dapm_route aqt_audio_map[] = {
	{"AQT ANC HPHR PA", NULL, "AQT RX INT2 DAC"},
	{"AQT ANC HPHR", NULL, "AQT ANC HPHR PA"},

	{"AQT IIR0", NULL, "AQT TX_PATH2"},
	{"AQT IIR0", NULL, "AQT ADC2 MUX"},
	{"AQT SRC0", NULL, "AQT IIR0"},
	{"AQT RX INT1 MIX2", "SRC0", "AQT SRC0"},
	{"AQT RX INT2 MIX2", "SRC0", "AQT SRC0"},
	{"AQT RX ST MUX", "SRC0", "AQT SRC0"},

	{"AQT RX INT1 MIX2", NULL, "AQT RX ST MUX"},
	{"AQT RX INT2 MIX2", NULL, "AQT RX ST MUX"},

	/* Native clk main path routing */
	{"AQT RX INT1_1 NATIVE MUX", "ON", "AQT RX INT1_1 MUX"},
+33 −4
Original line number Diff line number Diff line
@@ -2542,6 +2542,26 @@ static const char * const native_mux_text[] = {
AQT_DAPM_ENUM(int1_1_native, SND_SOC_NOPM, 0, native_mux_text);
AQT_DAPM_ENUM(int2_1_native, SND_SOC_NOPM, 0, native_mux_text);

static int aqt_mclk_event(struct snd_soc_dapm_widget *w,
			  struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
	int ret = 0;

	dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		ret = aqt_cdc_mclk_enable(codec, true);
		break;
	case SND_SOC_DAPM_POST_PMD:
		ret = aqt_cdc_mclk_enable(codec, false);
		break;
	}

	return ret;
}

static int aif_cap_mixer_get(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
@@ -2561,8 +2581,17 @@ static const struct snd_kcontrol_new aif1_cap_mixer[] = {
			aif_cap_mixer_get, aif_cap_mixer_put),
};

static const char * const rx_inp_st_mux_text[] = {
	"ZERO", "SRC0",
};
AQT_DAPM_ENUM(rx_inp_st, AQT1000_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
	      rx_inp_st_mux_text);

static const struct snd_soc_dapm_widget aqt_dapm_widgets[] = {

	SND_SOC_DAPM_SUPPLY("AQT MCLK", SND_SOC_NOPM, 0, 0, aqt_mclk_event,
			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),

	SND_SOC_DAPM_AIF_OUT_E("AQT AIF1 CAP", "AQT AIF1 Capture", 0,
		SND_SOC_NOPM, AIF1_CAP, 0, aqt_codec_enable_i2s_tx,
		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
@@ -2720,6 +2749,10 @@ static const struct snd_soc_dapm_widget aqt_dapm_widgets[] = {

	AQT_DAPM_MUX("AQT RX INT1_1 NATIVE MUX", 0, int1_1_native),
	AQT_DAPM_MUX("AQT RX INT2_1 NATIVE MUX", 0, int2_1_native),

	SND_SOC_DAPM_MUX("AQT RX ST MUX",
			 AQT1000_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2, 0,
			 &rx_inp_st_mux),
};

static int aqt_startup(struct snd_pcm_substream *substream,
@@ -3230,14 +3263,10 @@ int aqt_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
EXPORT_SYMBOL(aqt_codec_info_create_codec_entry);

static const struct aqt_reg_mask_val aqt_codec_reg_init[] = {
	{AQT1000_CHIP_CFG0_CLK_CFG_MCLK, 0x04, 0x00},
	{AQT1000_CHIP_CFG0_EFUSE_CTL, 0x01, 0x01},
};

static const struct aqt_reg_mask_val aqt_codec_reg_update[] = {
	{AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x01},
	{AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01},
	{AQT1000_CHIP_CFG0_CLK_CTL_CDC_DIG, 0x01, 0x01},
	{AQT1000_LDOH_MODE, 0x1F, 0x0B},
	{AQT1000_MICB1_TEST_CTL_2, 0x07, 0x01},
	{AQT1000_MICB1_MISC_MICB1_INM_RES_BIAS, 0x03, 0x02},