Commit adf615a6 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda/hdmi: Move ELD parse and jack reporting into update_eld()



This is a final step of the cleanup series: move the HDMI ELD parser
call into update_eld() function so that we can unify the calls.
The ELD validity check is unified in update_eld(), too.

Along with it, the repoll scheduling is moved to update_eld() as well,
where sync_eld_via_acomp() just passes 0 for skipping it.

Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: default avatarNikhil Mahale <nmahale@nvidia.com>
Link: https://lore.kernel.org/r/20200206162804.4734-5-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent ae47e2ec
Loading
Loading
Loading
Loading
+48 −62
Original line number Diff line number Diff line
@@ -1466,21 +1466,60 @@ static void hdmi_pcm_reset_pin(struct hdmi_spec *spec,
	per_pin->channels = 0;
}

static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
					    struct hdmi_spec_per_pin *per_pin)
{
	struct hdmi_spec *spec = codec->spec;

	if (per_pin->pcm_idx >= 0)
		return spec->pcm_rec[per_pin->pcm_idx].jack;
	else
		return NULL;
}

/* update per_pin ELD from the given new ELD;
 * setup info frame and notification accordingly
 * also notify ELD kctl and report jack status changes
 */
static bool update_eld(struct hda_codec *codec,
static void update_eld(struct hda_codec *codec,
		       struct hdmi_spec_per_pin *per_pin,
		       struct hdmi_eld *eld)
		       struct hdmi_eld *eld,
		       int repoll)
{
	struct hdmi_eld *pin_eld = &per_pin->sink_eld;
	struct hdmi_spec *spec = codec->spec;
	struct snd_jack *pcm_jack;
	bool old_eld_valid = pin_eld->eld_valid;
	bool eld_changed;
	int pcm_idx;

	if (eld->eld_valid) {
		if (eld->eld_size <= 0 ||
		    snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
				       eld->eld_size) < 0) {
			eld->eld_valid = false;
			if (repoll) {
				schedule_delayed_work(&per_pin->work,
						      msecs_to_jiffies(300));
				return;
			}
		}
	}

	if (!eld->eld_valid || eld->eld_size <= 0) {
		eld->eld_valid = false;
		eld->eld_size = 0;
	}

	/* for monitor disconnection, save pcm_idx firstly */
	pcm_idx = per_pin->pcm_idx;

	/*
	 * pcm_idx >=0 before update_eld() means it is in monitor
	 * disconnected event. Jack must be fetched before update_eld().
	 */
	pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);

	if (spec->dyn_pcm_assign) {
		if (eld->eld_valid) {
			hdmi_attach_hda_pcm(spec, per_pin);
@@ -1495,6 +1534,8 @@ static bool update_eld(struct hda_codec *codec,
	 */
	if (pcm_idx == -1)
		pcm_idx = per_pin->pcm_idx;
	if (!pcm_jack)
		pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);

	if (eld->eld_valid)
		snd_hdmi_show_eld(codec, &eld->info);
@@ -1533,36 +1574,8 @@ static bool update_eld(struct hda_codec *codec,
			       SNDRV_CTL_EVENT_MASK_VALUE |
			       SNDRV_CTL_EVENT_MASK_INFO,
			       &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
	return eld_changed;
}

static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
					    struct hdmi_spec_per_pin *per_pin)
{
	struct hdmi_spec *spec = codec->spec;

	if (per_pin->pcm_idx >= 0)
		return spec->pcm_rec[per_pin->pcm_idx].jack;
	else
		return NULL;
}

static void do_update_eld(struct hda_codec *codec,
			  struct hdmi_spec_per_pin *per_pin,
			  struct hdmi_eld *eld)
{
	struct snd_jack *pcm_jack;
	bool changed;

	/*
	 * pcm_idx >=0 before update_eld() means it is in monitor
	 * disconnected event. Jack must be fetched before update_eld().
	 */
	pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
	changed = update_eld(codec, per_pin, eld);
	if (!pcm_jack)
		pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
	if (changed && pcm_jack)
	if (eld_changed && pcm_jack)
		snd_jack_report(pcm_jack,
				(eld->monitor_present && eld->eld_valid) ?
				SND_JACK_AVOUT : 0);
@@ -1586,7 +1599,6 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
	 * the unsolicited response to avoid custom WARs.
	 */
	int present;
	bool do_repoll = false;
	int ret;

	ret = snd_hda_power_up_pm(codec);
@@ -1610,20 +1622,9 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
		if (spec->ops.pin_get_eld(codec, pin_nid, dev_id,
					  eld->eld_buffer, &eld->eld_size) < 0)
			eld->eld_valid = false;
		else {
			if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
						    eld->eld_size) < 0)
				eld->eld_valid = false;
		}
		if (!eld->eld_valid && repoll)
			do_repoll = true;
	}

	if (do_repoll)
		schedule_delayed_work(&per_pin->work, msecs_to_jiffies(300));
	else
		do_update_eld(codec, per_pin, eld);

	update_eld(codec, per_pin, eld, repoll);
	mutex_unlock(&per_pin->lock);
 out:
	snd_hda_power_down_pm(codec);
@@ -1635,29 +1636,14 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
{
	struct hdmi_spec *spec = codec->spec;
	struct hdmi_eld *eld = &spec->temp_eld;
	int size;

	mutex_lock(&per_pin->lock);
	eld->monitor_present = false;
	size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
	eld->eld_size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
				      per_pin->dev_id, &eld->monitor_present,
				      eld->eld_buffer, ELD_MAX_SIZE);
	if (size > 0) {
		size = min(size, ELD_MAX_SIZE);
		if (snd_hdmi_parse_eld(codec, &eld->info,
				       eld->eld_buffer, size) < 0)
			size = -EINVAL;
	}

	if (size > 0) {
		eld->eld_valid = true;
		eld->eld_size = size;
	} else {
		eld->eld_valid = false;
		eld->eld_size = 0;
	}

	do_update_eld(codec, per_pin, eld);
	eld->eld_valid = (eld->eld_size > 0);
	update_eld(codec, per_pin, eld, 0);
	mutex_unlock(&per_pin->lock);
}