audio: when audio hdmirx is unstable, mute all input buffer [1/2]
authorZhe Wang <Zhe.Wang@amlogic.com>
Wed, 31 Jul 2019 02:13:26 +0000 (10:13 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Mon, 5 Aug 2019 05:28:54 +0000 (22:28 -0700)
PD#SWPL-12104

Problem:
when hdmirx timing switching, pop noise.

Solution:
when audio hdmirx is unstable, mute all input buffer

Verify:
T962x2 x301

Change-Id: I594b5bf9c1f4af45bb3653a7bfef5e0c7dab2825
Signed-off-by: Zhe Wang <Zhe.Wang@amlogic.com>
include/linux/amlogic/media/sound/misc.h
sound/soc/amlogic/auge/extn.c
sound/soc/amlogic/common/misc.c

index c9e9fbd..866644e 100644 (file)
@@ -75,6 +75,9 @@ extern int aml_get_hdmiin_audio_packet(
        struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 
+extern int get_hdmiin_audio_stable(void);
+extern int get_hdmi_sample_rate_index(void);
+
 #endif
 
 #endif
index 31a208a..c8db16f 100644 (file)
@@ -343,6 +343,38 @@ static int extn_mmap(struct snd_pcm_substream *substream,
        return snd_pcm_lib_default_mmap(substream, vma);
 }
 
+static int extn_copy(struct snd_pcm_substream *substream, int channel,
+                       snd_pcm_uframes_t pos,
+                       void __user *buf, snd_pcm_uframes_t count)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos);
+       int bytes = frames_to_bytes(runtime, count);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (copy_from_user(hwbuf, buf, bytes))
+                       return -EFAULT;
+       }  else {
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+               enum toddr_src src = toddr_src_get();
+
+               /*if hdmirx or N&CTS is unstable, clear all buffer data.*/
+               if (src == FRHDMIRX && (!get_hdmiin_audio_stable() ||
+                               get_hdmi_sample_rate_index() == 0)) {
+                       char *buffer = runtime->dma_area;
+                       int buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+                       memset(buffer, 0, buffer_size);
+               }
+#endif
+               if (copy_to_user(buf, hwbuf, bytes))
+                       return -EFAULT;
+
+               memset(hwbuf, 0, bytes);
+       }
+       return 0;
+}
+
 static struct snd_pcm_ops extn_ops = {
        .open      = extn_open,
        .close     = extn_close,
@@ -354,6 +386,7 @@ static struct snd_pcm_ops extn_ops = {
        .pointer   = extn_pointer,
        .silence   = extn_silence,
        .mmap      = extn_mmap,
+       .copy      = extn_copy,
 };
 
 static int extn_new(struct snd_soc_pcm_runtime *rtd)
index 1b46705..10c10a9 100644 (file)
@@ -199,15 +199,21 @@ const struct soc_enum hdmi_in_status_enum[] = {
                        hdmi_in_audio_packet)
 };
 
-int aml_get_hdmiin_audio_stable(
-       struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
+int get_hdmiin_audio_stable(void)
 {
        struct rx_audio_stat_s aud_sts;
 
        rx_get_audio_status(&aud_sts);
+
+       return (aud_sts.aud_rcv_packet == 0) ? 0 : 1;
+}
+
+int aml_get_hdmiin_audio_stable(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
        ucontrol->value.integer.value[0] =
-               (aud_sts.aud_rcv_packet == 0) ? 0 : 1;
+               get_hdmiin_audio_stable();
 
        return 0;
 }