[alsa-devel] [PATCH] ALSA: hda/hdmi - Don't report Jack event if no need to do that
Hui Wang
hui.wang at canonical.com
Fri May 3 06:05:09 CEST 2019
On 2019/5/2 下午11:49, Takashi Iwai wrote:
> On Thu, 02 May 2019 04:52:46 +0200,
> Hui Wang wrote:
>>
>> On 2019/4/30 下午5:02, Takashi Iwai wrote:
>>> On Tue, 30 Apr 2019 10:42:55 +0200,
>>> Hui Wang wrote:
>>>> On 2019/4/30 下午3:35, Takashi Iwai wrote:
>>>>> On Tue, 30 Apr 2019 08:57:11 +0200,
>>>>> Hui Wang wrote:
>>>>>> On the machines with AMD GPU or Nvidia GPU, we often meet this issues:
>>>>>> after s3, there are 4 HDMI/DP audio devices in the gnome-sound-setting
>>>>>> even there is no any monitors plugged.
>>>>>>
>>>>>> When this problem happens, we check the /proc/asound/cardX/eld#N.M, we
>>>>>> will find the monitor_present=1, eld_valid=0.
>>>>>>
>>>>>>
>>>>>> So the fix is putting your change and my change together like below?
> Well, removing "!repoll" should be treated as a separate patch, and
> I'm not sure whether we want to get rid of it.
>
> The "!repoll" check is a bit misleading. This condition indicates
> that the jack status sync is required, e.g. it's the case where
> polling goes to timeout or at the beginning of the probe. For
> example, in the case of resume, it starts with repoll=1. If an
> incomplete state (monitor=1, eld_valid=0) is seen at this point, the
> code schedules for the retry at a later point. And if it reaches to
> the max count, it clears to repoll=0 and try the last attempt, which
> won't schedule any longer.
>
> So, at this point, we *have to* notify the result no matter whether
> it's satisfying or not.
>
>
> thanks,
>
> Takashi
So let us do sth in the hda_jack.c, adding two members check_eld and
eld_valid in the struct hda_jack_tbl{},
When building new jacks, since there is no eld_data yet, just follow old
rules (only checking AC_PINSENSE_PRESENCE)
After building new jacks, if it is not a phantom one, set check_eld to 1
every time we get eld (via verbs or acomp), we will sync jack->eld_valid
to eld->eld_valid.
in the report_sync(), we will check check_eld and eld_valid, not depends
on AC_PINSENSE_PRESENCE only.
No matter interrupt, s3 or poll, the jack->eld_valid will be synced and
the report_sync() will report jack state depeneds on both
AC_PINSENSE_PRESENCE and eld_valid
Does it sound good?
Thanks,
Hui.
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 74b46952fc98..4bdf842bd915 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -341,7 +341,8 @@ void snd_hda_jack_report_sync(struct hda_codec *codec)
continue;
state = jack->button_state;
if (get_jack_plug_state(jack->pin_sense))
- state |= jack->type;
+ if (!jack->check_eld || jack->eld_valid)
+ state |= jack->type;
snd_jack_report(jack->jack, state);
if (jack->button_state) {
snd_jack_report(jack->jack,
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index 1d713201c160..57d7245b8961 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -40,6 +40,8 @@ struct hda_jack_tbl {
unsigned int jack_dirty:1; /* needs to update? */
unsigned int phantom_jack:1; /* a fixed, always present port? */
unsigned int block_report:1; /* in a transitional state - do
not report to userspace */
+ unsigned int check_eld:1; /* check eld flag when deciding
pin presence */
+ unsigned int eld_valid:1; /* eld data valid or not */
hda_nid_t gating_jack; /* valid when gating jack
plugged */
hda_nid_t gated_jack; /* gated is dependent on this
jack */
int type;
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 8b3ac690efa3..56357e17d17d 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1551,8 +1551,10 @@ static bool hdmi_present_sense_via_verbs(struct
hdmi_spec_per_pin *per_pin,
ret = !repoll || !eld->monitor_present || eld->eld_valid;
jack = snd_hda_jack_tbl_get(codec, pin_nid);
- if (jack)
+ if (jack) {
jack->block_report = !ret;
+ jack->eld_valid = eld->eld_valid;
+ }
mutex_unlock(&per_pin->lock);
return ret;
@@ -1593,6 +1595,7 @@ static void sync_eld_via_acomp(struct hda_codec
*codec,
struct hdmi_spec *spec = codec->spec;
struct hdmi_eld *eld = &spec->temp_eld;
struct snd_jack *jack = NULL;
+ struct hda_jack_tbl *jack_tbl;
int size;
mutex_lock(&per_pin->lock);
@@ -1615,6 +1618,10 @@ static void sync_eld_via_acomp(struct hda_codec
*codec,
eld->eld_size = 0;
}
+ jack_tbl = snd_hda_jack_tbl_get(codec, per_pin->pin_nid);
+ if (jack_tbl)
+ jack_tbl->eld_valid = eld->eld_valid;
+
/* pcm_idx >=0 before update_eld() means it is in monitor
* disconnected event. Jack must be fetched before update_eld()
*/
@@ -1625,7 +1632,7 @@ static void sync_eld_via_acomp(struct hda_codec
*codec,
if (jack == NULL)
goto unlock;
snd_jack_report(jack,
- eld->monitor_present ? SND_JACK_AVOUT : 0);
+ (eld->monitor_present && eld->eld_valid) ?
SND_JACK_AVOUT : 0);
unlock:
mutex_unlock(&per_pin->lock);
}
@@ -2163,6 +2170,8 @@ static int generic_hdmi_build_jack(struct
hda_codec *codec, int pcm_idx)
* align with dyn_pcm_assign mode
*/
spec->pcm_rec[pcm_idx].jack = jack->jack;
+ if (!jack->phantom_jack)
+ jack->check_eld = 1;
return 0;
}
>
>> diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
>> index 8b3ac690efa3..14b799a85873 100644
>> --- a/sound/pci/hda/patch_hdmi.c
>> +++ b/sound/pci/hda/patch_hdmi.c
>>
>>
>>> thanks,
>>>
>>> Takashi
>>> _______________________________________________
>>> Alsa-devel mailing list
>>> Alsa-devel at alsa-project.org
>>> https://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> https://mailman.alsa-project.org/mailman/listinfo/alsa-devel
More information about the Alsa-devel
mailing list