From 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 02:46:07 +0000
Subject: [PATCH] add audio

---
 kernel/sound/soc/codecs/tlv320aic32x4.c |  595 ++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 329 insertions(+), 266 deletions(-)

diff --git a/kernel/sound/soc/codecs/tlv320aic32x4.c b/kernel/sound/soc/codecs/tlv320aic32x4.c
index 45d9f4a..b895075 100644
--- a/kernel/sound/soc/codecs/tlv320aic32x4.c
+++ b/kernel/sound/soc/codecs/tlv320aic32x4.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * linux/sound/soc/codecs/tlv320aic32x4.c
  *
@@ -6,21 +7,6 @@
  * Author: Javier Martin <javier.martin@vista-silicon.com>
  *
  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
  */
 
 #include <linux/module.h>
@@ -33,6 +19,7 @@
 #include <linux/cdev.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/of_clk.h>
 #include <linux/regulator/consumer.h>
 
 #include <sound/tlv320aic32x4.h>
@@ -46,29 +33,13 @@
 
 #include "tlv320aic32x4.h"
 
-struct aic32x4_rate_divs {
-	u32 mclk;
-	u32 rate;
-	u8 p_val;
-	u8 pll_j;
-	u16 pll_d;
-	u16 dosr;
-	u8 ndac;
-	u8 mdac;
-	u8 aosr;
-	u8 nadc;
-	u8 madc;
-	u8 blck_N;
-};
-
 struct aic32x4_priv {
 	struct regmap *regmap;
-	u32 sysclk;
 	u32 power_cfg;
 	u32 micpga_routing;
 	bool swapdacs;
 	int rstn_gpio;
-	struct clk *mclk;
+	const char *mclk_name;
 
 	struct regulator *supply_ldo;
 	struct regulator *supply_iov;
@@ -79,13 +50,61 @@
 	struct device *dev;
 };
 
+static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	u32 adc_reg;
+
+	/*
+	 * Workaround: the datasheet does not mention a required programming
+	 * sequence but experiments show the ADC needs to be reset after each
+	 * capture to avoid audible artifacts.
+	 */
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMD:
+		adc_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP);
+		snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg |
+					AIC32X4_LADC_EN | AIC32X4_RADC_EN);
+		snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg);
+		break;
+	}
+	return 0;
+};
+
+static int mic_bias_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* Change Mic Bias Registor */
+		snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
+				AIC32x4_MICBIAS_MASK,
+				AIC32X4_MICBIAS_LDOIN |
+				AIC32X4_MICBIAS_2075V);
+		printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
+				AIC32x4_MICBIAS_MASK, 0);
+		printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
+				__func__);
+		break;
+	}
+
+	return 0;
+}
+
+
 static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	u8 val;
 
-	val = snd_soc_component_read32(component, AIC32X4_DINCTL);
+	val = snd_soc_component_read(component, AIC32X4_DINCTL);
 
 	ucontrol->value.integer.value[0] = (val & 0x01);
 
@@ -99,7 +118,7 @@
 	u8 val;
 	u8 gpio_check;
 
-	val = snd_soc_component_read32(component, AIC32X4_DOUTCTL);
+	val = snd_soc_component_read(component, AIC32X4_DOUTCTL);
 	gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
 	if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
 		printk(KERN_ERR "%s: MFP2 is not configure as a GPIO output\n",
@@ -126,7 +145,7 @@
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	u8 val;
 
-	val = snd_soc_component_read32(component, AIC32X4_SCLKCTL);
+	val = snd_soc_component_read(component, AIC32X4_SCLKCTL);
 
 	ucontrol->value.integer.value[0] = (val & 0x01);
 
@@ -140,7 +159,7 @@
 	u8 val;
 	u8 gpio_check;
 
-	val = snd_soc_component_read32(component, AIC32X4_MISOCTL);
+	val = snd_soc_component_read(component, AIC32X4_MISOCTL);
 	gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
 	if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
 		printk(KERN_ERR "%s: MFP4 is not configure as a GPIO output\n",
@@ -167,7 +186,7 @@
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	u8 val;
 
-	val = snd_soc_component_read32(component, AIC32X4_GPIOCTL);
+	val = snd_soc_component_read(component, AIC32X4_GPIOCTL);
 	ucontrol->value.integer.value[0] = ((val & 0x2) >> 1);
 
 	return 0;
@@ -180,7 +199,7 @@
 	u8 val;
 	u8 gpio_check;
 
-	val = snd_soc_component_read32(component, AIC32X4_GPIOCTL);
+	val = snd_soc_component_read(component, AIC32X4_GPIOCTL);
 	gpio_check = (val & AIC32X4_MFP5_GPIO_OUTPUT);
 	if (gpio_check != AIC32X4_MFP5_GPIO_OUTPUT) {
 		printk(KERN_ERR "%s: MFP5 is not configure as a GPIO output\n",
@@ -231,9 +250,24 @@
 /* -12dB min, 0.5dB steps */
 static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
 
+static const char * const lo_cm_text[] = {
+	"Full Chip", "1.65V",
+};
+
+static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
+
+static const char * const ptm_text[] = {
+	"P3", "P2", "P1",
+};
+
+static SOC_ENUM_SINGLE_DECL(l_ptm_enum, AIC32X4_LPLAYBACK, 2, ptm_text);
+static SOC_ENUM_SINGLE_DECL(r_ptm_enum, AIC32X4_RPLAYBACK, 2, ptm_text);
+
 static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
 	SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
 			AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
+	SOC_ENUM("DAC Left Playback PowerTune Switch", l_ptm_enum),
+	SOC_ENUM("DAC Right Playback PowerTune Switch", r_ptm_enum),
 	SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
 			AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0,
 			tlv_driver_gain),
@@ -244,6 +278,7 @@
 			AIC32X4_HPRGAIN, 6, 0x01, 1),
 	SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN,
 			AIC32X4_LORGAIN, 6, 0x01, 1),
+	SOC_ENUM("LO Playback Common Mode Switch", lo_cm_enum),
 	SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL,
 			AIC32X4_RMICPGAVOL, 7, 0x01, 1),
 
@@ -277,38 +312,6 @@
 			0, 0x1F, 0),
 	SOC_DOUBLE_R("AGC Signal Debounce", AIC32X4_LAGC7, AIC32X4_RAGC7,
 			0, 0x0F, 0),
-};
-
-static const struct aic32x4_rate_divs aic32x4_divs[] = {
-	/* 8k rate */
-	{12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
-	{24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
-	{25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
-	/* 11.025k rate */
-	{12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
-	{24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
-	/* 16k rate */
-	{12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
-	{24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
-	{25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
-	/* 22.05k rate */
-	{12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
-	{24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
-	{25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
-	/* 32k rate */
-	{12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
-	{24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
-	/* 44.1k rate */
-	{12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
-	{24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
-	{25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
-	/* 48k rate */
-	{12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
-	{24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
-	{25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},
-
-	/* 96k rate */
-	{25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1},
 };
 
 static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
@@ -365,7 +368,7 @@
 	SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum),
 };
 
-/*  Right mixer pins */
+/*	Right mixer pins */
 static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
 static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
 static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
@@ -450,7 +453,10 @@
 	SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
 			in3r_to_lmixer_controls),
 
-	SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
+	SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_POST("ADC Reset", aic32x4_reset_adc),
 
 	SND_SOC_DAPM_OUTPUT("HPL"),
 	SND_SOC_DAPM_OUTPUT("HPR"),
@@ -567,50 +573,35 @@
 static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
 	{
 		.selector_reg = 0,
-		.selector_mask  = 0xff,
+		.selector_mask	= 0xff,
 		.window_start = 0,
 		.window_len = 128,
 		.range_min = 0,
-		.range_max = AIC32X4_RMICPGAVOL,
+		.range_max = AIC32X4_REFPOWERUP,
 	},
 };
 
 const struct regmap_config aic32x4_regmap_config = {
-	.max_register = AIC32X4_RMICPGAVOL,
+	.max_register = AIC32X4_REFPOWERUP,
 	.ranges = aic32x4_regmap_pages,
 	.num_ranges = ARRAY_SIZE(aic32x4_regmap_pages),
 };
 EXPORT_SYMBOL(aic32x4_regmap_config);
 
-static inline int aic32x4_get_divs(int mclk, int rate)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
-		if ((aic32x4_divs[i].rate == rate)
-		    && (aic32x4_divs[i].mclk == mclk)) {
-			return i;
-		}
-	}
-	printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n");
-	return -EINVAL;
-}
-
 static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 				  int clk_id, unsigned int freq, int dir)
 {
 	struct snd_soc_component *component = codec_dai->component;
-	struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+	struct clk *mclk;
+	struct clk *pll;
 
-	switch (freq) {
-	case 12000000:
-	case 24000000:
-	case 25000000:
-		aic32x4->sysclk = freq;
-		return 0;
-	}
-	printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n");
-	return -EINVAL;
+	pll = devm_clk_get(component->dev, "pll");
+	if (IS_ERR(pll))
+		return PTR_ERR(pll);
+
+	mclk = clk_get_parent(pll);
+
+	return clk_set_rate(mclk, freq);
 }
 
 static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
@@ -660,103 +651,180 @@
 	}
 
 	snd_soc_component_update_bits(component, AIC32X4_IFACE1,
-			    AIC32X4_IFACE1_DATATYPE_MASK |
-			    AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
+				AIC32X4_IFACE1_DATATYPE_MASK |
+				AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
 	snd_soc_component_update_bits(component, AIC32X4_IFACE2,
-			    AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
+				AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
 	snd_soc_component_update_bits(component, AIC32X4_IFACE3,
-			    AIC32X4_BCLKINV_MASK, iface_reg_3);
+				AIC32X4_BCLKINV_MASK, iface_reg_3);
 
 	return 0;
 }
 
+static int aic32x4_set_aosr(struct snd_soc_component *component, u8 aosr)
+{
+	return snd_soc_component_write(component, AIC32X4_AOSR, aosr);
+}
+
+static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
+{
+	snd_soc_component_write(component, AIC32X4_DOSRMSB, dosr >> 8);
+	snd_soc_component_write(component, AIC32X4_DOSRLSB,
+		      (dosr & 0xff));
+
+	return 0;
+}
+
+static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
+						u8 r_block, u8 p_block)
+{
+	if (r_block > 18 || p_block > 25)
+		return -EINVAL;
+
+	snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
+	snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
+
+	return 0;
+}
+
+static int aic32x4_setup_clocks(struct snd_soc_component *component,
+				unsigned int sample_rate, unsigned int channels,
+				unsigned int bit_depth)
+{
+	u8 aosr;
+	u16 dosr;
+	u8 adc_resource_class, dac_resource_class;
+	u8 madc, nadc, mdac, ndac, max_nadc, min_mdac, max_ndac;
+	u8 dosr_increment;
+	u16 max_dosr, min_dosr;
+	unsigned long adc_clock_rate, dac_clock_rate;
+	int ret;
+
+	struct clk_bulk_data clocks[] = {
+		{ .id = "pll" },
+		{ .id = "nadc" },
+		{ .id = "madc" },
+		{ .id = "ndac" },
+		{ .id = "mdac" },
+		{ .id = "bdiv" },
+	};
+	ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+	if (ret)
+		return ret;
+
+	if (sample_rate <= 48000) {
+		aosr = 128;
+		adc_resource_class = 6;
+		dac_resource_class = 8;
+		dosr_increment = 8;
+		aic32x4_set_processing_blocks(component, 1, 1);
+	} else if (sample_rate <= 96000) {
+		aosr = 64;
+		adc_resource_class = 6;
+		dac_resource_class = 8;
+		dosr_increment = 4;
+		aic32x4_set_processing_blocks(component, 1, 9);
+	} else if (sample_rate == 192000) {
+		aosr = 32;
+		adc_resource_class = 3;
+		dac_resource_class = 4;
+		dosr_increment = 2;
+		aic32x4_set_processing_blocks(component, 13, 19);
+	} else {
+		dev_err(component->dev, "Sampling rate not supported\n");
+		return -EINVAL;
+	}
+
+	madc = DIV_ROUND_UP((32 * adc_resource_class), aosr);
+	max_dosr = (AIC32X4_MAX_DOSR_FREQ / sample_rate / dosr_increment) *
+			dosr_increment;
+	min_dosr = (AIC32X4_MIN_DOSR_FREQ / sample_rate / dosr_increment) *
+			dosr_increment;
+	max_nadc = AIC32X4_MAX_CODEC_CLKIN_FREQ / (madc * aosr * sample_rate);
+
+	for (nadc = max_nadc; nadc > 0; --nadc) {
+		adc_clock_rate = nadc * madc * aosr * sample_rate;
+		for (dosr = max_dosr; dosr >= min_dosr;
+				dosr -= dosr_increment) {
+			min_mdac = DIV_ROUND_UP((32 * dac_resource_class), dosr);
+			max_ndac = AIC32X4_MAX_CODEC_CLKIN_FREQ /
+					(min_mdac * dosr * sample_rate);
+			for (mdac = min_mdac; mdac <= 128; ++mdac) {
+				for (ndac = max_ndac; ndac > 0; --ndac) {
+					dac_clock_rate = ndac * mdac * dosr *
+							sample_rate;
+					if (dac_clock_rate == adc_clock_rate) {
+						if (clk_round_rate(clocks[0].clk, dac_clock_rate) == 0)
+							continue;
+
+						clk_set_rate(clocks[0].clk,
+							dac_clock_rate);
+
+						clk_set_rate(clocks[1].clk,
+							sample_rate * aosr *
+							madc);
+						clk_set_rate(clocks[2].clk,
+							sample_rate * aosr);
+						aic32x4_set_aosr(component,
+							aosr);
+
+						clk_set_rate(clocks[3].clk,
+							sample_rate * dosr *
+							mdac);
+						clk_set_rate(clocks[4].clk,
+							sample_rate * dosr);
+						aic32x4_set_dosr(component,
+							dosr);
+
+						clk_set_rate(clocks[5].clk,
+							sample_rate * channels *
+							bit_depth);
+
+						return 0;
+					}
+				}
+			}
+		}
+	}
+
+	dev_err(component->dev,
+		"Could not set clocks to support sample rate.\n");
+	return -EINVAL;
+}
+
 static int aic32x4_hw_params(struct snd_pcm_substream *substream,
-			     struct snd_pcm_hw_params *params,
-			     struct snd_soc_dai *dai)
+				 struct snd_pcm_hw_params *params,
+				 struct snd_soc_dai *dai)
 {
 	struct snd_soc_component *component = dai->component;
 	struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
 	u8 iface1_reg = 0;
 	u8 dacsetup_reg = 0;
-	int i;
 
-	i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params));
-	if (i < 0) {
-		printk(KERN_ERR "aic32x4: sampling rate not supported\n");
-		return i;
-	}
+	aic32x4_setup_clocks(component, params_rate(params),
+			     params_channels(params),
+			     params_physical_width(params));
 
-	/* MCLK as PLL_CLKIN */
-	snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
-			    AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
-	/* PLL as CODEC_CLKIN */
-	snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_CODEC_CLKIN_MASK,
-			    AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
-	/* DAC_MOD_CLK as BDIV_CLKIN */
-	snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
-			    AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
-
-	/* We will fix R value to 1 and will make P & J=K.D as variable */
-	snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_R_MASK, 0x01);
-
-	/* PLL P value */
-	snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_P_MASK,
-			    aic32x4_divs[i].p_val << AIC32X4_PLL_P_SHIFT);
-
-	/* PLL J value */
-	snd_soc_component_write(component, AIC32X4_PLLJ, aic32x4_divs[i].pll_j);
-
-	/* PLL D value */
-	snd_soc_component_write(component, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8));
-	snd_soc_component_write(component, AIC32X4_PLLDLSB, (aic32x4_divs[i].pll_d & 0xff));
-
-	/* NDAC divider value */
-	snd_soc_component_update_bits(component, AIC32X4_NDAC,
-			    AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
-
-	/* MDAC divider value */
-	snd_soc_component_update_bits(component, AIC32X4_MDAC,
-			    AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
-
-	/* DOSR MSB & LSB values */
-	snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
-	snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
-
-	/* NADC divider value */
-	snd_soc_component_update_bits(component, AIC32X4_NADC,
-			    AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
-
-	/* MADC divider value */
-	snd_soc_component_update_bits(component, AIC32X4_MADC,
-			    AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
-
-	/* AOSR value */
-	snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-
-	/* BCLK N divider */
-	snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-			    AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
-
-	switch (params_width(params)) {
+	switch (params_physical_width(params)) {
 	case 16:
 		iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
-			       AIC32X4_IFACE1_DATALEN_SHIFT);
+				   AIC32X4_IFACE1_DATALEN_SHIFT);
 		break;
 	case 20:
 		iface1_reg |= (AIC32X4_WORD_LEN_20BITS <<
-			       AIC32X4_IFACE1_DATALEN_SHIFT);
+				   AIC32X4_IFACE1_DATALEN_SHIFT);
 		break;
 	case 24:
 		iface1_reg |= (AIC32X4_WORD_LEN_24BITS <<
-			       AIC32X4_IFACE1_DATALEN_SHIFT);
+				   AIC32X4_IFACE1_DATALEN_SHIFT);
 		break;
 	case 32:
 		iface1_reg |= (AIC32X4_WORD_LEN_32BITS <<
-			       AIC32X4_IFACE1_DATALEN_SHIFT);
+				   AIC32X4_IFACE1_DATALEN_SHIFT);
 		break;
 	}
 	snd_soc_component_update_bits(component, AIC32X4_IFACE1,
-			    AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
+				AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
 
 	if (params_channels(params) == 1) {
 		dacsetup_reg = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN;
@@ -767,17 +835,17 @@
 			dacsetup_reg = AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN;
 	}
 	snd_soc_component_update_bits(component, AIC32X4_DACSETUP,
-			    AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
+				AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
 
 	return 0;
 }
 
-static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
+static int aic32x4_mute(struct snd_soc_dai *dai, int mute, int direction)
 {
 	struct snd_soc_component *component = dai->component;
 
 	snd_soc_component_update_bits(component, AIC32X4_DACMUTE,
-			    AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
+				AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
 
 	return 0;
 }
@@ -785,41 +853,25 @@
 static int aic32x4_set_bias_level(struct snd_soc_component *component,
 				  enum snd_soc_bias_level level)
 {
-	struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
 	int ret;
+
+	struct clk_bulk_data clocks[] = {
+		{ .id = "madc" },
+		{ .id = "mdac" },
+		{ .id = "bdiv" },
+	};
+
+	ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+	if (ret)
+		return ret;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		/* Switch on master clock */
-		ret = clk_prepare_enable(aic32x4->mclk);
+		ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks);
 		if (ret) {
-			dev_err(component->dev, "Failed to enable master clock\n");
+			dev_err(component->dev, "Failed to enable clocks\n");
 			return ret;
 		}
-
-		/* Switch on PLL */
-		snd_soc_component_update_bits(component, AIC32X4_PLLPR,
-				    AIC32X4_PLLEN, AIC32X4_PLLEN);
-
-		/* Switch on NDAC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_NDAC,
-				    AIC32X4_NDACEN, AIC32X4_NDACEN);
-
-		/* Switch on MDAC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_MDAC,
-				    AIC32X4_MDACEN, AIC32X4_MDACEN);
-
-		/* Switch on NADC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_NADC,
-				    AIC32X4_NADCEN, AIC32X4_NADCEN);
-
-		/* Switch on MADC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_MADC,
-				    AIC32X4_MADCEN, AIC32X4_MADCEN);
-
-		/* Switch on BCLK_N Divider */
-		snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-				    AIC32X4_BCLKEN, AIC32X4_BCLKEN);
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
@@ -828,32 +880,7 @@
 		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
 			break;
 
-		/* Switch off BCLK_N Divider */
-		snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-				    AIC32X4_BCLKEN, 0);
-
-		/* Switch off MADC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_MADC,
-				    AIC32X4_MADCEN, 0);
-
-		/* Switch off NADC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_NADC,
-				    AIC32X4_NADCEN, 0);
-
-		/* Switch off MDAC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_MDAC,
-				    AIC32X4_MDACEN, 0);
-
-		/* Switch off NDAC Divider */
-		snd_soc_component_update_bits(component, AIC32X4_NDAC,
-				    AIC32X4_NDACEN, 0);
-
-		/* Switch off PLL */
-		snd_soc_component_update_bits(component, AIC32X4_PLLPR,
-				    AIC32X4_PLLEN, 0);
-
-		/* Switch off master clock */
-		clk_disable_unprepare(aic32x4->mclk);
+		clk_bulk_disable_unprepare(ARRAY_SIZE(clocks), clocks);
 		break;
 	case SND_SOC_BIAS_OFF:
 		break;
@@ -861,31 +888,33 @@
 	return 0;
 }
 
-#define AIC32X4_RATES	SNDRV_PCM_RATE_8000_96000
-#define AIC32X4_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
-			 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+#define AIC32X4_RATES	SNDRV_PCM_RATE_8000_192000
+#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+			 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE \
+			 | SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dai_ops aic32x4_ops = {
 	.hw_params = aic32x4_hw_params,
-	.digital_mute = aic32x4_mute,
+	.mute_stream = aic32x4_mute,
 	.set_fmt = aic32x4_set_dai_fmt,
 	.set_sysclk = aic32x4_set_dai_sysclk,
+	.no_capture_mute = 1,
 };
 
 static struct snd_soc_dai_driver aic32x4_dai = {
 	.name = "tlv320aic32x4-hifi",
 	.playback = {
-		     .stream_name = "Playback",
-		     .channels_min = 1,
-		     .channels_max = 2,
-		     .rates = AIC32X4_RATES,
-		     .formats = AIC32X4_FORMATS,},
+			 .stream_name = "Playback",
+			 .channels_min = 1,
+			 .channels_max = 2,
+			 .rates = AIC32X4_RATES,
+			 .formats = AIC32X4_FORMATS,},
 	.capture = {
-		    .stream_name = "Capture",
-		    .channels_min = 1,
-		    .channels_max = 2,
-		    .rates = AIC32X4_RATES,
-		    .formats = AIC32X4_FORMATS,},
+			.stream_name = "Capture",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = AIC32X4_RATES,
+			.formats = AIC32X4_FORMATS,},
 	.ops = &aic32x4_ops,
 	.symmetric_rates = 1,
 };
@@ -898,7 +927,7 @@
 	/* MFP1 */
 	if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) {
 		snd_soc_component_write(component, AIC32X4_DINCTL,
-		      aic32x4->setup->gpio_func[0]);
+			  aic32x4->setup->gpio_func[0]);
 		snd_soc_add_component_controls(component, aic32x4_mfp1,
 			ARRAY_SIZE(aic32x4_mfp1));
 	}
@@ -906,7 +935,7 @@
 	/* MFP2 */
 	if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) {
 		snd_soc_component_write(component, AIC32X4_DOUTCTL,
-		      aic32x4->setup->gpio_func[1]);
+			  aic32x4->setup->gpio_func[1]);
 		snd_soc_add_component_controls(component, aic32x4_mfp2,
 			ARRAY_SIZE(aic32x4_mfp2));
 	}
@@ -914,7 +943,7 @@
 	/* MFP3 */
 	if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) {
 		snd_soc_component_write(component, AIC32X4_SCLKCTL,
-		      aic32x4->setup->gpio_func[2]);
+			  aic32x4->setup->gpio_func[2]);
 		snd_soc_add_component_controls(component, aic32x4_mfp3,
 			ARRAY_SIZE(aic32x4_mfp3));
 	}
@@ -922,7 +951,7 @@
 	/* MFP4 */
 	if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) {
 		snd_soc_component_write(component, AIC32X4_MISOCTL,
-		      aic32x4->setup->gpio_func[3]);
+			  aic32x4->setup->gpio_func[3]);
 		snd_soc_add_component_controls(component, aic32x4_mfp4,
 			ARRAY_SIZE(aic32x4_mfp4));
 	}
@@ -930,7 +959,7 @@
 	/* MFP5 */
 	if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) {
 		snd_soc_component_write(component, AIC32X4_GPIOCTL,
-		      aic32x4->setup->gpio_func[4]);
+			  aic32x4->setup->gpio_func[4]);
 		snd_soc_add_component_controls(component, aic32x4_mfp5,
 			ARRAY_SIZE(aic32x4_mfp5));
 	}
@@ -940,21 +969,29 @@
 {
 	struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
 	u32 tmp_reg;
+	int ret;
 
-	if (gpio_is_valid(aic32x4->rstn_gpio)) {
-		ndelay(10);
-		gpio_set_value(aic32x4->rstn_gpio, 1);
-	}
+	struct clk_bulk_data clocks[] = {
+		{ .id = "codec_clkin" },
+		{ .id = "pll" },
+		{ .id = "bdiv" },
+		{ .id = "mdac" },
+	};
 
-	snd_soc_component_write(component, AIC32X4_RESET, 0x01);
+	ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+	if (ret)
+		return ret;
 
 	if (aic32x4->setup)
 		aic32x4_setup_gpios(component);
 
+	clk_set_parent(clocks[0].clk, clocks[1].clk);
+	clk_set_parent(clocks[2].clk, clocks[3].clk);
+
 	/* Power platform configuration */
 	if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
-		snd_soc_component_write(component, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
-						      AIC32X4_MICBIAS_2075V);
+		snd_soc_component_write(component, AIC32X4_MICBIAS,
+				AIC32X4_MICBIAS_LDOIN | AIC32X4_MICBIAS_2075V);
 	}
 	if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
 		snd_soc_component_write(component, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
@@ -963,7 +1000,7 @@
 			AIC32X4_LDOCTLEN : 0;
 	snd_soc_component_write(component, AIC32X4_LDOCTL, tmp_reg);
 
-	tmp_reg = snd_soc_component_read32(component, AIC32X4_CMMODE);
+	tmp_reg = snd_soc_component_read(component, AIC32X4_CMMODE);
 	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36)
 		tmp_reg |= AIC32X4_LDOIN_18_36;
 	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED)
@@ -989,10 +1026,18 @@
 	 * and down for the first capture to work properly. It seems related to
 	 * a HW BUG or some kind of behavior not documented in the datasheet.
 	 */
-	tmp_reg = snd_soc_component_read32(component, AIC32X4_ADCSETUP);
+	tmp_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP);
 	snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg |
 				AIC32X4_LADC_EN | AIC32X4_RADC_EN);
 	snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg);
+
+	/*
+	 * Enable the fast charging feature and ensure the needed 40ms ellapsed
+	 * before using the analog circuits.
+	 */
+	snd_soc_component_write(component, AIC32X4_REFPOWERUP,
+				AIC32X4_REFPOWERUP_40MS);
+	msleep(40);
 
 	return 0;
 }
@@ -1017,11 +1062,17 @@
 		struct device_node *np)
 {
 	struct aic32x4_setup_data *aic32x4_setup;
+	int ret;
 
 	aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup),
 							GFP_KERNEL);
 	if (!aic32x4_setup)
 		return -ENOMEM;
+
+	ret = of_property_match_string(np, "clock-names", "mclk");
+	if (ret < 0)
+		return -EINVAL;
+	aic32x4->mclk_name = of_clk_get_parent_name(np, ret);
 
 	aic32x4->swapdacs = false;
 	aic32x4->micpga_routing = 0;
@@ -1077,11 +1128,9 @@
 			return PTR_ERR(aic32x4->supply_av);
 		}
 	} else {
-		if (IS_ERR(aic32x4->supply_dv) &&
-				PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
+		if (PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
-		if (IS_ERR(aic32x4->supply_av) &&
-				PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
+		if (PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
 	}
 
@@ -1144,7 +1193,7 @@
 		return PTR_ERR(regmap);
 
 	aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv),
-			       GFP_KERNEL);
+				   GFP_KERNEL);
 	if (aic32x4 == NULL)
 		return -ENOMEM;
 
@@ -1156,6 +1205,7 @@
 		aic32x4->swapdacs = pdata->swapdacs;
 		aic32x4->micpga_routing = pdata->micpga_routing;
 		aic32x4->rstn_gpio = pdata->rstn_gpio;
+		aic32x4->mclk_name = "mclk";
 	} else if (np) {
 		ret = aic32x4_parse_dt(aic32x4, np);
 		if (ret) {
@@ -1167,12 +1217,7 @@
 		aic32x4->swapdacs = false;
 		aic32x4->micpga_routing = 0;
 		aic32x4->rstn_gpio = -1;
-	}
-
-	aic32x4->mclk = devm_clk_get(dev, "mclk");
-	if (IS_ERR(aic32x4->mclk)) {
-		dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
-		return PTR_ERR(aic32x4->mclk);
+		aic32x4->mclk_name = "mclk";
 	}
 
 	if (gpio_is_valid(aic32x4->rstn_gpio)) {
@@ -1188,15 +1233,33 @@
 		return ret;
 	}
 
+	if (gpio_is_valid(aic32x4->rstn_gpio)) {
+		ndelay(10);
+		gpio_set_value_cansleep(aic32x4->rstn_gpio, 1);
+		mdelay(1);
+	}
+
+	ret = regmap_write(regmap, AIC32X4_RESET, 0x01);
+	if (ret)
+		goto err_disable_regulators;
+
+	ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
+	if (ret)
+		goto err_disable_regulators;
+
 	ret = devm_snd_soc_register_component(dev,
 			&soc_component_dev_aic32x4, &aic32x4_dai, 1);
 	if (ret) {
 		dev_err(dev, "Failed to register component\n");
-		aic32x4_disable_regulators(aic32x4);
-		return ret;
+		goto err_disable_regulators;
 	}
 
 	return 0;
+
+err_disable_regulators:
+	aic32x4_disable_regulators(aic32x4);
+
+	return ret;
 }
 EXPORT_SYMBOL(aic32x4_probe);
 

--
Gitblit v1.6.2