From 135d405d2e68183ad64c2a5b48ea63683a3819f2 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Mon, 18 Jun 2018 20:28:53 +0530 Subject: [PATCH] asoc: bolero: Update dmic sample rate config for VA macro Add support for DMICs of different sampling rates with respective clk_div config update in VA macro register. Change-Id: I8faa46774cf1fe561af3bd7a284bc7d37f85cb9d Signed-off-by: Laxminath Kasam --- asoc/codecs/bolero/va-macro.c | 91 +++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 5 deletions(-) diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 5e9e096275cb..554ed90415d5 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -39,7 +39,11 @@ #define CF_MIN_3DB_75HZ 0x1 #define CF_MIN_3DB_150HZ 0x2 +#define VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0 +#define VA_MACRO_MCLK_FREQ 9600000 #define VA_MACRO_TX_PATH_OFFSET 0x80 +#define VA_MACRO_TX_DMIC_CLK_DIV_MASK 0x0E +#define VA_MACRO_TX_DMIC_CLK_DIV_SHFT 0x01 #define BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS 40 @@ -66,6 +70,15 @@ enum { VA_MACRO_DEC_MAX, }; +enum { + VA_MACRO_CLK_DIV_2, + VA_MACRO_CLK_DIV_3, + VA_MACRO_CLK_DIV_4, + VA_MACRO_CLK_DIV_6, + VA_MACRO_CLK_DIV_8, + VA_MACRO_CLK_DIV_16, +}; + struct va_mute_work { struct va_macro_priv *va_priv; u32 decimator; @@ -94,6 +107,7 @@ struct va_macro_priv { s32 dmic_2_3_clk_cnt; s32 dmic_4_5_clk_cnt; s32 dmic_6_7_clk_cnt; + u16 dmic_clk_div; u16 va_mclk_users; char __iomem *va_io_base; struct regulator *micb_supply; @@ -415,22 +429,22 @@ static int va_macro_enable_dmic(struct snd_soc_dapm_widget *w, case 0: case 1: dmic_clk_cnt = &(va_priv->dmic_0_1_clk_cnt); - dmic_clk_reg = BOLERO_CDC_VA_TX0_TX_PATH_CTL; + dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL; break; case 2: case 3: dmic_clk_cnt = &(va_priv->dmic_2_3_clk_cnt); - dmic_clk_reg = BOLERO_CDC_VA_TX1_TX_PATH_CTL; + dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL; break; case 4: case 5: dmic_clk_cnt = &(va_priv->dmic_4_5_clk_cnt); - dmic_clk_reg = BOLERO_CDC_VA_TX2_TX_PATH_CTL; + dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL; break; case 6: case 7: dmic_clk_cnt = &(va_priv->dmic_6_7_clk_cnt); - dmic_clk_reg = BOLERO_CDC_VA_TX3_TX_PATH_CTL; + dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL; break; default: dev_err(va_dev, "%s: Invalid DMIC Selection\n", @@ -446,6 +460,10 @@ static int va_macro_enable_dmic(struct snd_soc_dapm_widget *w, if (*dmic_clk_cnt == 1) { snd_soc_update_bits(codec, dmic_clk_reg, dmic_clk_en, dmic_clk_en); + snd_soc_update_bits(codec, dmic_clk_reg, + VA_MACRO_TX_DMIC_CLK_DIV_MASK, + va_priv->dmic_clk_div << + VA_MACRO_TX_DMIC_CLK_DIV_SHFT); } break; case SND_SOC_DAPM_POST_PMD: @@ -1255,6 +1273,56 @@ static const struct snd_kcontrol_new va_macro_snd_controls[] = { 0, -84, 40, digital_gain), }; +static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, + struct va_macro_priv *va_priv) +{ + u32 div_factor; + u32 mclk_rate = VA_MACRO_MCLK_FREQ; + + if (dmic_sample_rate == VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED || + mclk_rate % dmic_sample_rate != 0) + goto undefined_rate; + + div_factor = mclk_rate / dmic_sample_rate; + + switch (div_factor) { + case 2: + va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_2; + break; + case 3: + va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_3; + break; + case 4: + va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_4; + break; + case 6: + va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_6; + break; + case 8: + va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_8; + break; + case 16: + va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_16; + break; + default: + /* Any other DIV factor is invalid */ + goto undefined_rate; + } + + /* Valid dmic DIV factors */ + dev_dbg(va_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n", + __func__, div_factor, mclk_rate); + + return dmic_sample_rate; + +undefined_rate: + dev_dbg(va_priv->dev, "%s: Invalid rate %d, for mclk %d\n", + __func__, dmic_sample_rate, mclk_rate); + dmic_sample_rate = VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED; + + return dmic_sample_rate; +} + static int va_macro_init(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); @@ -1355,7 +1423,7 @@ static int va_macro_probe(struct platform_device *pdev) { struct macro_ops ops; struct va_macro_priv *va_priv; - u32 va_base_addr; + u32 va_base_addr, sample_rate = 0; char __iomem *va_io_base; struct clk *va_core_clk; bool va_without_decimation = false; @@ -1363,6 +1431,7 @@ static int va_macro_probe(struct platform_device *pdev) const char *micb_voltage_str = "qcom,va-vdd-micb-voltage"; const char *micb_current_str = "qcom,va-vdd-micb-current"; int ret = 0; + const char *dmic_sample_rate = "qcom,va-dmic-sample-rate"; va_priv = devm_kzalloc(&pdev->dev, sizeof(struct va_macro_priv), GFP_KERNEL); @@ -1381,6 +1450,18 @@ static int va_macro_probe(struct platform_device *pdev) "qcom,va-without-decimation"); va_priv->va_without_decimation = va_without_decimation; + ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate, + &sample_rate); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, sample_rate); + va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_2; + } else { + if (va_macro_validate_dmic_sample_rate( + sample_rate, va_priv) == VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED) + return -EINVAL; + } + va_io_base = devm_ioremap(&pdev->dev, va_base_addr, VA_MAX_OFFSET); if (!va_io_base) {