audio: add tdm and spdif clk fine tuning interface [1/1]
authorZhe Wang <Zhe.Wang@amlogic.com>
Mon, 25 Mar 2019 11:53:30 +0000 (19:53 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Tue, 26 Mar 2019 08:33:35 +0000 (01:33 -0700)
PD#SWPL-5518

Problem:
In DTV passthrough, the output clk drifts from input

Solution:
add clk fine tuning interface

Verify:
verify by X301

Change-Id: I969d3eb865fb1aba90f155965548454cc3040c99
Signed-off-by: Zhe Wang <Zhe.Wang@amlogic.com>
sound/soc/amlogic/auge/audio_utils.c
sound/soc/amlogic/auge/spdif.c
sound/soc/amlogic/auge/tdm.c

index c710d16..2301428 100644 (file)
@@ -165,6 +165,7 @@ static int loopback_tdminlb_set_enum(
        return 0;
 }
 
+#if 0
 static int snd_int_info(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_info *uinfo)
 {
@@ -279,6 +280,7 @@ static int snd_byte_set(struct snd_kcontrol *kcontrol,
 
        return 0;
 }
+#endif
 
 #define SND_BYTE(xname, type, func, xshift, xmask)   \
 {                                      \
@@ -742,7 +744,7 @@ static const struct snd_kcontrol_new snd_auge_controls[] = {
                     loopback_tdminlb_enum,
                     loopback_tdminlb_get_enum,
                     loopback_tdminlb_set_enum),
-
+#if 0
        /*TDMIN_A swap*/
        SND_SWAP("TDMIN_A Ch0 Swap", TDMIN_A, in_swap_channel_enum, 0, 0x7),
        SND_SWAP("TDMIN_A Ch1 Swap", TDMIN_A, in_swap_channel_enum, 4, 0x7),
@@ -983,6 +985,7 @@ static const struct snd_kcontrol_new snd_auge_controls[] = {
                TDMOUT_C, lane2_mixer_enum, 22, 0x1),
        SND_MIX("TDMOUT_C Lane3 Mixer Channel",
                TDMOUT_C, lane3_mixer_enum, 23, 0x1),
+#endif
 
        /* SPDIFIN Channel Status */
        SPDIFIN_CHSTATUS("SPDIFIN Channel Status",
index 0205867..31757ef 100644 (file)
@@ -53,6 +53,9 @@
 
 /*#define __SPDIFIN_AUDIO_TYPE_HW__*/
 
+static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai,
+                               int clk_id, unsigned int freq, int dir);
+
 struct spdif_chipinfo {
        unsigned int id;
 
@@ -345,16 +348,49 @@ int spdifin_source_set_enum(
        return 0;
 }
 
+static int spdif_clk_get(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+       struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
+
+       ucontrol->value.enumerated.item[0] =
+                       clk_get_rate(p_spdif->clk_spdifout);
+       return 0;
+}
+
+static int spdif_clk_set(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+       struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
+
+       int sysclk = p_spdif->sysclk_freq;
+       int value = ucontrol->value.enumerated.item[0];
+
+       if (value > 2000000 || value < 0) {
+               pr_err("Fine spdif sysclk setting range(0~2000000), %d\n",
+                               value);
+               return 0;
+       }
+       sysclk += (value - 1000000);
+
+       aml_dai_set_spdif_sysclk(cpu_dai, 0, sysclk, 0);
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new snd_spdif_controls[] = {
 
-       SOC_ENUM_EXT("SPDIFIN audio samplerate", spdifin_sample_rate_enum,
+       SOC_ENUM_EXT("SPDIFIN audio samplerate",
+                               spdifin_sample_rate_enum,
                                spdifin_samplerate_get_enum,
                                NULL),
 
        SOC_ENUM_EXT("SPDIFIN Audio Type",
-                        spdif_audio_type_enum,
-                        spdifin_audio_type_get_enum,
-                        NULL),
+                               spdif_audio_type_enum,
+                               spdifin_audio_type_get_enum,
+                               NULL),
 
        SOC_ENUM_EXT("Audio spdif format",
                                spdif_format_enum,
@@ -364,15 +400,22 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = {
        SOC_SINGLE_BOOL_EXT("Audio spdif mute",
                                0, aml_audio_get_spdif_mute,
                                aml_audio_set_spdif_mute),
+
        SOC_ENUM_EXT("Audio spdifin source",
                                spdifin_src_enum,
                                spdifin_source_get_enum,
                                spdifin_source_set_enum),
+
 #ifdef CONFIG_AMLOGIC_HDMITX
        SOC_SINGLE_BOOL_EXT("Audio hdmi-out mute",
                                0, aml_get_hdmi_out_audio,
                                aml_set_hdmi_out_audio),
 #endif
+
+       SOC_SINGLE_EXT("SPDIF CLK Fine Setting",
+                               0, 0, 2000000, 0,
+                               spdif_clk_get,
+                               spdif_clk_set),
 };
 
 static bool spdifin_check_audiotype_by_sw(struct aml_spdif *p_spdif)
index 4ed034b..1a27094 100644 (file)
@@ -52,6 +52,9 @@
 #define TDM_C  2
 #define LANE_MAX 4
 
+static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai,
+                               int clk_id, unsigned int freq, int dir);
+
 static void dump_pcm_setting(struct pcm_setting *setting)
 {
        if (setting == NULL)
@@ -152,6 +155,36 @@ static const struct snd_pcm_hardware aml_tdm_hardware = {
        .channels_max = 32,
 };
 
+static int tdm_clk_get(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+       struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
+
+       ucontrol->value.enumerated.item[0] = clk_get_rate(p_tdm->mclk);
+       return 0;
+}
+
+static int tdm_clk_set(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+       struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
+
+       int mclk_rate = p_tdm->last_mclk_freq;
+       int value = ucontrol->value.enumerated.item[0];
+
+       if (value > 2000000 || value < 0) {
+               pr_err("Fine tdm clk setting range (0~2000000), %d\n", value);
+               return 0;
+       }
+       mclk_rate += (value - 1000000);
+
+       aml_dai_set_tdm_sysclk(cpu_dai, 0, mclk_rate, 0);
+
+       return 0;
+}
+
 static int tdmin_clk_get(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
@@ -182,8 +215,6 @@ static const char *const i2sin_clk[] = {
        "12000000"
 };
 
-
-
 static const struct soc_enum i2sin_clk_enum[] = {
        SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(i2sin_clk),
                        i2sin_clk),
@@ -194,7 +225,12 @@ static const struct soc_enum i2sin_clk_enum[] = {
 static const struct snd_kcontrol_new snd_tdm_controls[] = {
        SOC_ENUM_EXT("I2SIn CLK", i2sin_clk_enum,
                                tdmin_clk_get,
-                               NULL)
+                               NULL),
+
+       SOC_SINGLE_EXT("TDM MCLK Fine Setting",
+                               0, 0, 2000000, 0,
+                               tdm_clk_get,
+                               tdm_clk_set),
 };