]> Pileus Git - ~andy/linux/blobdiff - sound/pci/hda/patch_hdmi.c
Merge branch 'next/cross-platform' of git://git.linaro.org/people/arnd/arm-soc
[~andy/linux] / sound / pci / hda / patch_hdmi.c
index 19cb72db9c38df1261f3ded1fe1c0471bd906aef..342540128fb8f2bc4c8ce18b9f53e9c859c1c5d7 100644 (file)
@@ -324,6 +324,66 @@ static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid)
        return -EINVAL;
 }
 
+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;
+       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;
+
+       return 0;
+}
+
+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;
+       int pin_idx;
+
+       spec = codec->spec;
+       pin_idx = kcontrol->private_value;
+
+       memcpy(ucontrol->value.bytes.data,
+               spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE);
+
+       return 0;
+}
+
+static struct snd_kcontrol_new eld_bytes_ctl = {
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+       .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+       .name = "ELD",
+       .info = hdmi_eld_ctl_info,
+       .get = hdmi_eld_ctl_get,
+};
+
+static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
+                       int device)
+{
+       struct snd_kcontrol *kctl;
+       struct hdmi_spec *spec = codec->spec;
+       int err;
+
+       kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
+       if (!kctl)
+               return -ENOMEM;
+       kctl->private_value = pin_idx;
+       kctl->id.device = device;
+
+       err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
 #ifdef BE_PARANOID
 static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
                                int *packet_index, int *byte_index)
@@ -967,19 +1027,12 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 
        per_pin->pin_nid = pin_nid;
 
-       err = snd_hda_input_jack_add(codec, pin_nid,
-                                    SND_JACK_VIDEOOUT, NULL);
-       if (err < 0)
-               return err;
-
        err = hdmi_read_pin_conn(codec, pin_idx);
        if (err < 0)
                return err;
 
        spec->num_pins++;
 
-       hdmi_present_sense(codec, pin_nid, eld);
-
        return 0;
 }
 
@@ -1162,6 +1215,25 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
        return 0;
 }
 
+static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
+{
+       int err;
+       char hdmi_str[32];
+       struct hdmi_spec *spec = codec->spec;
+       struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+       int pcmdev = spec->pcm_rec[pin_idx].device;
+
+       snprintf(hdmi_str, sizeof(hdmi_str), "HDMI/DP,pcm=%d", pcmdev);
+
+       err = snd_hda_input_jack_add(codec, per_pin->pin_nid,
+                            SND_JACK_VIDEOOUT, pcmdev > 0 ? hdmi_str : NULL);
+       if (err < 0)
+               return err;
+
+       hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld);
+       return 0;
+}
+
 static int generic_hdmi_build_controls(struct hda_codec *codec)
 {
        struct hdmi_spec *spec = codec->spec;
@@ -1170,12 +1242,25 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
 
        for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
                struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+
+               err = generic_hdmi_build_jack(codec, pin_idx);
+               if (err < 0)
+                       return err;
+
                err = snd_hda_create_spdif_out_ctls(codec,
                                                    per_pin->pin_nid,
                                                    per_pin->mux_nids[0]);
                if (err < 0)
                        return err;
                snd_hda_spdif_ctls_unassign(codec, pin_idx);
+
+               /* add control for ELD Bytes */
+               err = hdmi_create_eld_ctl(codec,
+                                       pin_idx,
+                                       spec->pcm_rec[pin_idx].device);
+
+               if (err < 0)
+                       return err;
        }
 
        return 0;