diff options
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 99 |
1 files changed, 92 insertions, 7 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 19cb72db9c3..342540128fb 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -324,6 +324,66 @@ static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid) | |||
324 | return -EINVAL; | 324 | return -EINVAL; |
325 | } | 325 | } |
326 | 326 | ||
327 | static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, | ||
328 | struct snd_ctl_elem_info *uinfo) | ||
329 | { | ||
330 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
331 | struct hdmi_spec *spec; | ||
332 | int pin_idx; | ||
333 | |||
334 | spec = codec->spec; | ||
335 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
336 | |||
337 | pin_idx = kcontrol->private_value; | ||
338 | uinfo->count = spec->pins[pin_idx].sink_eld.eld_size; | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, | ||
344 | struct snd_ctl_elem_value *ucontrol) | ||
345 | { | ||
346 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
347 | struct hdmi_spec *spec; | ||
348 | int pin_idx; | ||
349 | |||
350 | spec = codec->spec; | ||
351 | pin_idx = kcontrol->private_value; | ||
352 | |||
353 | memcpy(ucontrol->value.bytes.data, | ||
354 | spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE); | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static struct snd_kcontrol_new eld_bytes_ctl = { | ||
360 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
361 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
362 | .name = "ELD", | ||
363 | .info = hdmi_eld_ctl_info, | ||
364 | .get = hdmi_eld_ctl_get, | ||
365 | }; | ||
366 | |||
367 | static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, | ||
368 | int device) | ||
369 | { | ||
370 | struct snd_kcontrol *kctl; | ||
371 | struct hdmi_spec *spec = codec->spec; | ||
372 | int err; | ||
373 | |||
374 | kctl = snd_ctl_new1(&eld_bytes_ctl, codec); | ||
375 | if (!kctl) | ||
376 | return -ENOMEM; | ||
377 | kctl->private_value = pin_idx; | ||
378 | kctl->id.device = device; | ||
379 | |||
380 | err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl); | ||
381 | if (err < 0) | ||
382 | return err; | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
327 | #ifdef BE_PARANOID | 387 | #ifdef BE_PARANOID |
328 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | 388 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, |
329 | int *packet_index, int *byte_index) | 389 | int *packet_index, int *byte_index) |
@@ -967,19 +1027,12 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
967 | 1027 | ||
968 | per_pin->pin_nid = pin_nid; | 1028 | per_pin->pin_nid = pin_nid; |
969 | 1029 | ||
970 | err = snd_hda_input_jack_add(codec, pin_nid, | ||
971 | SND_JACK_VIDEOOUT, NULL); | ||
972 | if (err < 0) | ||
973 | return err; | ||
974 | |||
975 | err = hdmi_read_pin_conn(codec, pin_idx); | 1030 | err = hdmi_read_pin_conn(codec, pin_idx); |
976 | if (err < 0) | 1031 | if (err < 0) |
977 | return err; | 1032 | return err; |
978 | 1033 | ||
979 | spec->num_pins++; | 1034 | spec->num_pins++; |
980 | 1035 | ||
981 | hdmi_present_sense(codec, pin_nid, eld); | ||
982 | |||
983 | return 0; | 1036 | return 0; |
984 | } | 1037 | } |
985 | 1038 | ||
@@ -1162,6 +1215,25 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) | |||
1162 | return 0; | 1215 | return 0; |
1163 | } | 1216 | } |
1164 | 1217 | ||
1218 | static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) | ||
1219 | { | ||
1220 | int err; | ||
1221 | char hdmi_str[32]; | ||
1222 | struct hdmi_spec *spec = codec->spec; | ||
1223 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | ||
1224 | int pcmdev = spec->pcm_rec[pin_idx].device; | ||
1225 | |||
1226 | snprintf(hdmi_str, sizeof(hdmi_str), "HDMI/DP,pcm=%d", pcmdev); | ||
1227 | |||
1228 | err = snd_hda_input_jack_add(codec, per_pin->pin_nid, | ||
1229 | SND_JACK_VIDEOOUT, pcmdev > 0 ? hdmi_str : NULL); | ||
1230 | if (err < 0) | ||
1231 | return err; | ||
1232 | |||
1233 | hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld); | ||
1234 | return 0; | ||
1235 | } | ||
1236 | |||
1165 | static int generic_hdmi_build_controls(struct hda_codec *codec) | 1237 | static int generic_hdmi_build_controls(struct hda_codec *codec) |
1166 | { | 1238 | { |
1167 | struct hdmi_spec *spec = codec->spec; | 1239 | struct hdmi_spec *spec = codec->spec; |
@@ -1170,12 +1242,25 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
1170 | 1242 | ||
1171 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1243 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1172 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1244 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1245 | |||
1246 | err = generic_hdmi_build_jack(codec, pin_idx); | ||
1247 | if (err < 0) | ||
1248 | return err; | ||
1249 | |||
1173 | err = snd_hda_create_spdif_out_ctls(codec, | 1250 | err = snd_hda_create_spdif_out_ctls(codec, |
1174 | per_pin->pin_nid, | 1251 | per_pin->pin_nid, |
1175 | per_pin->mux_nids[0]); | 1252 | per_pin->mux_nids[0]); |
1176 | if (err < 0) | 1253 | if (err < 0) |
1177 | return err; | 1254 | return err; |
1178 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1255 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1256 | |||
1257 | /* add control for ELD Bytes */ | ||
1258 | err = hdmi_create_eld_ctl(codec, | ||
1259 | pin_idx, | ||
1260 | spec->pcm_rec[pin_idx].device); | ||
1261 | |||
1262 | if (err < 0) | ||
1263 | return err; | ||
1179 | } | 1264 | } |
1180 | 1265 | ||
1181 | return 0; | 1266 | return 0; |