Browse Source

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: Sudheer Papothi <[email protected]>
Sudheer Papothi 7 years ago
parent
commit
8bb6f40917

+ 52 - 2
asoc/codecs/aqt1000/aqt1000-core.c

@@ -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
asoc/codecs/aqt1000/aqt1000-irq.c

@@ -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);
-		}
-
+		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
asoc/codecs/aqt1000/aqt1000-routing.h

@@ -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
asoc/codecs/aqt1000/aqt1000.c

@@ -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},