From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 07:24:11 +0000
Subject: [PATCH] add stmac read mac form eeprom
---
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