MLK-12607: ASoC: fsl-asrc: Add the support of 12kHz and 24kHz
authorShengjiu Wang <shengjiu.wang@freescale.com>
Tue, 29 Mar 2016 08:11:51 +0000 (16:11 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:51:46 +0000 (14:51 -0500)
Remove the pre-processing and post-processing table. use proc_autosel()
to select proper parameters.
Unify the supported input and output rate.

Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
sound/soc/fsl/fsl_asrc.c

index 50562aa..e47aee7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
  *
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
  *
  * Author: Nicolin Chen <nicoleotsuka@gmail.com>
  *
 #define pair_dbg(fmt, ...) \
        dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
 
-/* Sample rates are aligned with that defined in pcm.h file */
-static const u8 process_option[][12][2] = {
-       /* 8kHz 11.025kHz 16kHz 22.05kHz 32kHz 44.1kHz 48kHz   64kHz   88.2kHz 96kHz   176kHz  192kHz */
-       {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 5512Hz */
-       {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 8kHz */
-       {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 11025Hz */
-       {{1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 16kHz */
-       {{1, 2}, {1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 22050Hz */
-       {{1, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},},      /* 32kHz */
-       {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},      /* 44.1kHz */
-       {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},      /* 48kHz */
-       {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},},      /* 64kHz */
-       {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},      /* 88.2kHz */
-       {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},      /* 96kHz */
-       {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},      /* 176kHz */
-       {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},      /* 192kHz */
-};
-
 /* Corresponding to process_option */
-static int supported_input_rate[] = {
-       5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
-       96000, 176400, 192000,
+static unsigned int supported_asrc_rate[] = {
+       5512, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
+       64000, 88200, 96000, 128000, 176400, 192000,
 };
 
-static int supported_asrc_rate[] = {
-       8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
+static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = {
+       .count = ARRAY_SIZE(supported_asrc_rate),
+       .list = supported_asrc_rate,
 };
 
 /**
@@ -129,6 +112,47 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
        return ret;
 }
 
+static int proc_autosel(int Fsin, int Fsout, int *pre_proc, int *post_proc)
+{
+       bool det_out_op2_cond;
+       bool det_out_op0_cond;
+       det_out_op2_cond = (((Fsin * 15 > Fsout * 16) & (Fsout < 56000)) |
+                                       ((Fsin > 56000) & (Fsout < 56000)));
+       det_out_op0_cond = (Fsin * 23 < Fsout * 8);
+
+       /*
+        * Not supported case: Tsout>16.125*Tsin, and Tsout>8.125*Tsin.
+        */
+       if (Fsin * 8 > 129 * Fsout)
+               *pre_proc = 5;
+       else if (Fsin * 8 > 65 * Fsout)
+               *pre_proc = 4;
+       else if (Fsin * 8 > 33 * Fsout)
+               *pre_proc = 2;
+       else if (Fsin * 8 > 15 * Fsout) {
+               if (Fsin > 152000)
+                       *pre_proc = 2;
+               else
+                       *pre_proc = 1;
+       } else if (Fsin < 76000)
+               *pre_proc = 0;
+       else if (Fsin > 152000)
+               *pre_proc = 2;
+       else
+               *pre_proc = 1;
+
+       if (det_out_op2_cond)
+               *post_proc = 2;
+       else if (det_out_op0_cond)
+               *post_proc = 0;
+       else
+               *post_proc = 1;
+
+       if (*pre_proc == 4 || *pre_proc == 5)
+               return -EINVAL;
+       return 0;
+}
+
 /**
  * Release ASRC pair
  *
@@ -244,8 +268,10 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2
        u32 inrate, outrate, indiv, outdiv;
        u32 clk_index[2], div[2];
        int in, out, channels;
+       int pre_proc, post_proc;
        struct clk *clk;
        bool ideal;
+       int ret;
 
        if (!config) {
                pair_err("invalid pair config\n");
@@ -269,11 +295,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2
        ideal = config->inclk == INCLK_NONE;
 
        /* Validate input and output sample rates */
-       for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
-               if (inrate == supported_input_rate[in])
+       for (in = 0; in < ARRAY_SIZE(supported_asrc_rate); in++)
+               if (inrate == supported_asrc_rate[in])
                        break;
 
-       if (in == ARRAY_SIZE(supported_input_rate)) {
+       if (in == ARRAY_SIZE(supported_asrc_rate)) {
                pair_err("unsupported input sample rate: %dHz\n", inrate);
                return -EINVAL;
        }
@@ -388,11 +414,17 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2
                           ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
                           ASRCTR_IDR(index) | ASRCTR_USR(index));
 
+       ret = proc_autosel(inrate, outrate, &pre_proc, &post_proc);
+       if (ret) {
+               pair_err("No supported pre-processing options\n");
+               return ret;
+       }
+
        /* Apply configurations for pre- and post-processing */
        regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
                           ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index),
-                          ASRCFG_PREMOD(index, process_option[in][out][0]) |
-                          ASRCFG_POSTMOD(index, process_option[in][out][1]));
+                          ASRCFG_PREMOD(index, pre_proc) |
+                          ASRCFG_POSTMOD(index, post_proc));
 
        return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
 }
@@ -564,7 +596,9 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream,
        struct fsl_asrc *asrc_priv   = snd_soc_dai_get_drvdata(cpu_dai);
 
        asrc_priv->substream[substream->stream] = substream;
-       return 0;
+
+       return snd_pcm_hw_constraint_list(substream->runtime, 0,
+                       SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints);
 }
 
 static void fsl_asrc_dai_shutdown(struct snd_pcm_substream *substream,
@@ -604,14 +638,18 @@ static struct snd_soc_dai_driver fsl_asrc_dai = {
                .stream_name = "ASRC-Playback",
                .channels_min = 1,
                .channels_max = 10,
-               .rates = FSL_ASRC_RATES,
+               .rate_min = 5512,
+               .rate_max = 192000,
+               .rates = SNDRV_PCM_RATE_KNOT,
                .formats = FSL_ASRC_FORMATS,
        },
        .capture = {
                .stream_name = "ASRC-Capture",
                .channels_min = 1,
                .channels_max = 10,
-               .rates = FSL_ASRC_RATES,
+               .rate_min = 5512,
+               .rate_max = 192000,
+               .rates = SNDRV_PCM_RATE_KNOT,
                .formats = FSL_ASRC_FORMATS,
        },
        .ops = &fsl_asrc_dai_ops,