ALSA: hda - hdmi: Refactor hdmi_eld into parsed_hdmi_eld
[deliverable/linux.git] / sound / pci / hda / patch_hdmi.c
index b9af281b2ba45aa759a7150550e43f0ff3784ee8..1e381918eb826a89abf8192ac1b903830394b76b 100644 (file)
@@ -343,14 +343,16 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_info *uinfo)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hdmi_spec *spec;
+       struct hdmi_spec *spec = codec->spec;
+       struct hdmi_eld *eld;
        int pin_idx;
 
-       spec = codec->spec;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 
        pin_idx = kcontrol->private_value;
-       uinfo->count = spec->pins[pin_idx].sink_eld.eld_size;
+       eld = &spec->pins[pin_idx].sink_eld;
+
+       uinfo->count = eld->eld_valid ? eld->eld_size : 0;
 
        return 0;
 }
@@ -359,14 +361,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hdmi_spec *spec;
+       struct hdmi_spec *spec = codec->spec;
+       struct hdmi_eld *eld;
        int pin_idx;
 
-       spec = codec->spec;
        pin_idx = kcontrol->private_value;
+       eld = &spec->pins[pin_idx].sink_eld;
+
+       if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
+               snd_BUG();
+               return -EINVAL;
+       }
 
-       memcpy(ucontrol->value.bytes.data,
-               spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE);
+       memset(ucontrol->value.bytes.data, 0,
+              ARRAY_SIZE(ucontrol->value.bytes.data));
+       if (eld->eld_valid)
+               memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
+                      eld->eld_size);
 
        return 0;
 }
@@ -520,7 +531,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
         * expand ELD's notions to match the ones used by Audio InfoFrame.
         */
        for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-               if (eld->spk_alloc & (1 << i))
+               if (eld->info.spk_alloc & (1 << i))
                        spk_mask |= eld_speaker_allocation_bits[i];
        }
 
@@ -534,7 +545,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
                }
        }
 
-       snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+       snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
        snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
                    ca, channels, buf);
 
@@ -875,7 +886,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
                ca = 0;
 
        memset(&ai, 0, sizeof(ai));
-       if (eld->conn_type == 0) { /* HDMI */
+       if (eld->info.conn_type == 0) { /* HDMI */
                struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
 
                hdmi_ai->type           = 0x84;
@@ -884,7 +895,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
                hdmi_ai->CC02_CT47      = channels - 1;
                hdmi_ai->CA             = ca;
                hdmi_checksum_audio_infoframe(hdmi_ai);
-       } else if (eld->conn_type == 1) { /* DisplayPort */
+       } else if (eld->info.conn_type == 1) { /* DisplayPort */
                struct dp_audio_infoframe *dp_ai = &ai.dp;
 
                dp_ai->type             = 0x84;
@@ -1105,7 +1116,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
 
        /* Restrict capabilities by ELD if this isn't disabled */
        if (!static_hdmi_pcm && eld->eld_valid) {
-               snd_hdmi_eld_update_pcm_info(eld, hinfo);
+               snd_hdmi_eld_update_pcm_info(&eld->info, hinfo);
                if (hinfo->channels_min > hinfo->channels_max ||
                    !hinfo->rates || !hinfo->formats) {
                        per_cvt->assigned = 0;
@@ -1166,8 +1177,6 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
        int present = snd_hda_pin_sense(codec, pin_nid);
        bool eld_valid = false;
 
-       memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer));
-
        eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
        if (eld->monitor_present)
                eld_valid       = !!(present & AC_PINSENSE_ELDV);
@@ -1176,9 +1185,22 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
                "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
                codec->addr, pin_nid, eld->monitor_present, eld_valid);
 
+       eld->eld_valid = false;
        if (eld_valid) {
-               if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-                       snd_hdmi_show_eld(eld);
+               if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
+                                                    &eld->eld_size) < 0)
+                       eld_valid = false;
+               else {
+                       memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld));
+                       if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer,
+                                                   eld->eld_size) < 0)
+                               eld_valid = false;
+               }
+
+               if (eld_valid) {
+                       snd_hdmi_show_eld(&eld->info);
+                       eld->eld_valid = true;
+               }
                else if (repoll) {
                        queue_delayed_work(codec->bus->workq,
                                           &per_pin->work,
This page took 0.025739 seconds and 5 git commands to generate.