]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
tegra-alt: rt565x: Add control to set codec rate
authorViswanath L <viswanathl@nvidia.com>
Wed, 19 Aug 2015 06:44:08 +0000 (12:14 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Fri, 4 Sep 2015 13:35:07 +0000 (06:35 -0700)
Add control to set codec rate. This is used to force codec
rate when SFC is used.

Increase xbar clock to support 44.1kHz to 48kHz SRC.

Bug 200127533

Change-Id: Ie53660697d8506fdae203d9911ff13e2721fc049
Signed-off-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-on: http://git-master/r/787161
(cherry picked from commit 0ca8375f298aa2047cecc016ff89b5d11ef695ae)
Reviewed-on: http://git-master/r/792948
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
sound/soc/tegra-alt/tegra_t210ref_mobile_rt565x_alt.c

index 0fd3ad95269ffa729454d11e6c23bc353f23d903..3fb3feb16f3930056ea4020386009c66bfde68d2 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "tegra_asoc_utils_alt.h"
 #include "tegra_asoc_machine_alt.h"
+#include "tegra210_xbar_alt.h"
 
 #define DRV_NAME "tegra-snd-t210ref-mobile-rt565x"
 
@@ -68,6 +69,23 @@ struct tegra_t210ref {
        struct regulator *dmic_reg;
        struct snd_soc_card *pcard;
        int is_codec_dummy;
+       int rate_via_kcontrol;
+};
+
+static const int tegra_t210ref_srate_values[] = {
+       0,
+       8000,
+       16000,
+       44100,
+       48000,
+       11025,
+       22050,
+       24000,
+       32000,
+       88200,
+       96000,
+       176000,
+       192000,
 };
 
 static struct snd_soc_jack tegra_t210ref_hp_jack;
@@ -183,19 +201,22 @@ static int tegra_t210ref_dai_init(struct snd_soc_pcm_runtime *rtd,
        struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
        struct snd_soc_pcm_stream *dai_params;
        unsigned int idx, mclk, clk_out_rate;
-       int err;
+       int err, codec_rate, clk_rate;
 
        if (machine->is_codec_dummy)
                return 0;
 
-       switch (rate) {
+       codec_rate = tegra_t210ref_srate_values[machine->rate_via_kcontrol];
+       clk_rate = (machine->rate_via_kcontrol) ? codec_rate : rate;
+
+       switch (clk_rate) {
        case 11025:
        case 22050:
        case 44100:
        case 88200:
        case 176000:
                clk_out_rate = 11289600; /* Codec rate */
-               mclk = 11289600 * 2; /* PLL_A rate */
+               mclk = 11289600 * 4; /* PLL_A rate */
                break;
        case 8000:
        case 16000:
@@ -206,12 +227,14 @@ static int tegra_t210ref_dai_init(struct snd_soc_pcm_runtime *rtd,
        case 192000:
        default:
                clk_out_rate = 12288000;
-               mclk = 12288000 * 2;
+               mclk = 12288000 * 3;
                break;
        }
 
+       pr_info("Setting pll_a = %d Hz clk_out = %d Hz\n",
+                       mclk, clk_out_rate);
        err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock,
-                               rate, mclk, clk_out_rate);
+                               clk_rate, mclk, clk_out_rate);
        if (err < 0) {
                dev_err(card->dev,
                "Can't configure clocks pll_a = %d Hz clk_out = %d Hz\n",
@@ -219,6 +242,13 @@ static int tegra_t210ref_dai_init(struct snd_soc_pcm_runtime *rtd,
                return err;
        }
 
+       err = tegra210_xbar_set_clock(mclk);
+       if (err < 0) {
+               dev_err(card->dev,
+                       "Can't configure xbar clock = %d Hz\n", mclk);
+               return err;
+       }
+
        idx = tegra_machine_get_codec_dai_link_idx("rt565x-playback");
        /* check if idx has valid number */
        if (idx != -EINVAL) {
@@ -232,7 +262,8 @@ static int tegra_t210ref_dai_init(struct snd_soc_pcm_runtime *rtd,
                }
 
                /* update link_param to update hw_param for DAPM */
-               dai_params->rate_min = rate;
+               dai_params->rate_min = (machine->rate_via_kcontrol) ?
+                       codec_rate : rate;
                dai_params->channels_min = channels;
                dai_params->formats = formats;
 
@@ -269,6 +300,16 @@ static int tegra_t210ref_dai_init(struct snd_soc_pcm_runtime *rtd,
                }
        }
 
+       idx = tegra_machine_get_codec_dai_link_idx("spdif-dit-3");
+       if (idx != -EINVAL) {
+               dai_params =
+               (struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;
+
+               /* update link_param to update hw_param for DAPM */
+               dai_params->rate_min = (machine->rate_via_kcontrol) ?
+                       codec_rate : rate;
+       }
+
        return 0;
 }
 
@@ -516,14 +557,56 @@ static int tegra_t210ref_resume_pre(struct snd_soc_card *card)
        return 0;
 }
 
-static const struct snd_soc_dapm_route tegra_t210ref_audio_map[] = {
+static const char * const tegra_t210ref_srate_text[] = {
+       "None",
+       "8kHz",
+       "16kHz",
+       "44kHz",
+       "48kHz",
+       "11kHz",
+       "22kHz",
+       "24kHz",
+       "32kHz",
+       "88kHz",
+       "96kHz",
+       "176kHz",
+       "192kHz",
 };
 
+static int tegra_t210ref_codec_get_rate(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+       struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
+
+       ucontrol->value.integer.value[0] = machine->rate_via_kcontrol;
+
+       return 0;
+}
+
+static int tegra_t210ref_codec_put_rate(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+       struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
+
+       /* set the rate control flag */
+       machine->rate_via_kcontrol = ucontrol->value.integer.value[0];
+
+       return 0;
+}
+
+static const struct soc_enum tegra_t210ref_codec_rate =
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_t210ref_srate_text),
+               tegra_t210ref_srate_text);
+
 static const struct snd_kcontrol_new tegra_t210ref_controls[] = {
        SOC_DAPM_PIN_SWITCH("x Int Spk"),
        SOC_DAPM_PIN_SWITCH("x Headphone Jack"),
        SOC_DAPM_PIN_SWITCH("x Mic Jack"),
        SOC_DAPM_PIN_SWITCH("x Int Mic"),
+       SOC_ENUM_EXT("codec-x rate", tegra_t210ref_codec_rate,
+               tegra_t210ref_codec_get_rate, tegra_t210ref_codec_put_rate),
 };
 
 static int tegra_t210ref_remove(struct snd_soc_card *card)