|
@@ -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) {
|