aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu Fengguang <wfg@linux.intel.com>2008-11-17 22:47:53 -0500
committerTakashi Iwai <tiwai@suse.de>2008-11-18 01:39:12 -0500
commit5f1e71b1cc2cc788c0f452772e2ce5e7430c40c2 (patch)
tree74c344fbdfdb12e7a02003fc3d8f6db9b7da0c83
parent7f4a9f43427793bfe4d42e71f42e2b551bcfe354 (diff)
ALSA: ELD proc interface for HDMI sinks
Create /proc/asound/card<card_no>/eld#<codec_no> to reflect the audio configurations and capabilities of the attached HDMI sink. Some notes: - Shall we show an empty file if the ELD content is not valid? Well it's not that simple. There could be partially populated ELD, and there may be malformed ELD provided by buggy drivers/monitors. So expose ELD as it is. - The ELD retrieval routines rely on the Intel HDA interface, others are/could be universal and independent ones. - How do we name the proc file? If there are going to be two HDMI pins per codec, then the current naming scheme (eld#<codec no>) will fail. Luckily the user space dependencies should be minimal, so it would be trivial to do the rename if that happens. - The ELD proc file content is designed to be easy for scripts and human reading. Its lines all have the pattern: <item_name>\t[\t]*<item_value> where <item_name> is a keyword in c language, while <item_value> could be any contents, including white spaces. <item_value> could also be a null value. Signed-off-by: Wu Fengguang <wfg@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_eld.c74
-rw-r--r--sound/pci/hda/hda_local.h9
-rw-r--r--sound/pci/hda/patch_intelhdmi.c2
3 files changed, 85 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index a69a7e87d26a..7fa065cd1d9c 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -452,3 +452,77 @@ void snd_hdmi_show_eld(struct sink_eld *e)
452 for (i = 0; i < e->sad_count; i++) 452 for (i = 0; i < e->sad_count; i++)
453 hdmi_show_short_audio_desc(e->sad + i); 453 hdmi_show_short_audio_desc(e->sad + i);
454} 454}
455
456#ifdef CONFIG_PROC_FS
457
458static void hdmi_print_sad_info(int i, struct cea_sad *a,
459 struct snd_info_buffer *buffer)
460{
461 char buf[80];
462
463 snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
464 i, a->format, cea_audio_coding_type_names[a->format]);
465 snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
466
467 snd_print_pcm_rates(a->rates, buf, sizeof(buf));
468 snd_iprintf(buffer, "sad%d_sampling_rates\t[0x%x] %s\n",
469 i, a->rates, buf);
470
471 if (a->format == AUDIO_CODING_TYPE_LPCM)
472 snd_iprintf(buffer, "sad%d_sample_bits\t0x%x\n",
473 i, a->sample_bits);
474
475 if (a->max_bitrate)
476 snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
477 i, a->max_bitrate);
478
479 if (a->profile)
480 snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
481}
482
483static void hdmi_print_eld_info(struct snd_info_entry *entry,
484 struct snd_info_buffer *buffer)
485{
486 struct sink_eld *e = entry->private_data;
487 char buf[HDMI_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
488 int i;
489
490 snd_iprintf(buffer, "monitor name\t\t%s\n", e->monitor_name);
491 snd_iprintf(buffer, "connection_type\t\t%s\n",
492 eld_connection_type_names[e->conn_type]);
493 snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
494 eld_versoin_names[e->eld_ver]);
495 snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver,
496 cea_edid_version_names[e->cea_edid_ver]);
497 snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id);
498 snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id);
499 snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id);
500 snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp);
501 snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai);
502 snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
503
504 hdmi_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
505 snd_iprintf(buffer, "speakers\t\t[0x%x] %s\n", e->spk_alloc, buf);
506
507 snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
508
509 for (i = 0; i < e->sad_count; i++)
510 hdmi_print_sad_info(i, e->sad + i, buffer);
511}
512
513int snd_hda_eld_proc_new(struct hda_codec *codec, struct sink_eld *eld)
514{
515 char name[32];
516 struct snd_info_entry *entry;
517 int err;
518
519 snprintf(name, sizeof(name), "eld#%d", codec->addr);
520 err = snd_card_proc_new(codec->bus->card, name, &entry);
521 if (err < 0)
522 return err;
523
524 snd_info_set_text_ops(entry, eld, hdmi_print_eld_info);
525 return 0;
526}
527
528#endif
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index e1b76686672a..02ac7321e5e4 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -484,4 +484,13 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
484int snd_hdmi_get_eld(struct sink_eld *, struct hda_codec *, hda_nid_t); 484int snd_hdmi_get_eld(struct sink_eld *, struct hda_codec *, hda_nid_t);
485void snd_hdmi_show_eld(struct sink_eld *eld); 485void snd_hdmi_show_eld(struct sink_eld *eld);
486 486
487#ifdef CONFIG_PROC_FS
488int snd_hda_eld_proc_new(struct hda_codec *codec, struct sink_eld *eld);
489#else
490inline int snd_hda_eld_proc_new(struct hda_codec *codec, struct sink_eld *eld)
491{
492 return 0;
493}
494#endif
495
487#endif /* __SOUND_HDA_LOCAL_H */ 496#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index 489278d3d773..c95abc47614f 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -446,6 +446,8 @@ static int patch_intel_hdmi(struct hda_codec *codec)
446 codec->spec = spec; 446 codec->spec = spec;
447 codec->patch_ops = intel_hdmi_patch_ops; 447 codec->patch_ops = intel_hdmi_patch_ops;
448 448
449 snd_hda_eld_proc_new(codec, &spec->sink);
450
449 return 0; 451 return 0;
450} 452}
451 453