ELD_VER_PARTIAL = 31,
};
-static char *eld_versoin_names[32] = {
- "reserved",
- "reserved",
- "CEA-861D or below",
- [3 ... 30] = "reserved",
- [31] = "partial"
-};
-
enum cea_edid_versions {
CEA_EDID_VER_NONE = 0,
CEA_EDID_VER_CEA861 = 1,
CEA_EDID_VER_RESERVED = 4,
};
-static char *cea_edid_version_names[8] = {
- "no CEA EDID Timing Extension block present",
- "CEA-861",
- "CEA-861-A",
- "CEA-861-B, C or D",
- [4 ... 7] = "reserved"
-};
-
static char *cea_speaker_allocation_names[] = {
/* 0 */ "FL/FR",
/* 1 */ "LFE",
static char *eld_connection_type_names[4] = {
"HDMI",
- "Display Port",
+ "DisplayPort",
"2-reserved",
"3-reserved"
};
AC_VERB_GET_HDMI_ELDD, byte_index);
#ifdef BE_PARANOID
- printk(KERN_INFO "ELD data byte %d: 0x%x\n", byte_index, val);
+ printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
#endif
if ((val & AC_ELDD_ELD_VALID) == 0) {
- snd_printd(KERN_INFO "Invalid ELD data byte %d\n",
+ snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
byte_index);
val = 0;
}
switch (a->format) {
case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
snd_printd(KERN_INFO
- "audio coding type 0 not expected in ELD\n");
+ "HDMI: audio coding type 0 not expected\n");
break;
case AUDIO_CODING_TYPE_LPCM:
if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
snd_printd(KERN_INFO
- "audio coding xtype %d not expected in ELD\n",
+ "HDMI: audio coding xtype %d not expected\n",
a->format);
a->format = 0;
} else
e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
if (e->eld_ver != ELD_VER_CEA_861D &&
e->eld_ver != ELD_VER_PARTIAL) {
- snd_printd(KERN_INFO "Unknown ELD version %d\n", e->eld_ver);
+ snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n",
+ e->eld_ver);
goto out_fail;
}
e->product_id = get_unaligned_le16(buf + 18);
if (mnl > ELD_MAX_MNL) {
- snd_printd(KERN_INFO "MNL is reserved value %d\n", mnl);
+ snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl);
goto out_fail;
} else if (ELD_FIXED_BYTES + mnl > size) {
- snd_printd(KERN_INFO "out of range MNL %d\n", mnl);
+ snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl);
goto out_fail;
} else
strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl);
for (i = 0; i < e->sad_count; i++) {
if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
- snd_printd(KERN_INFO "out of range SAD %d\n", i);
+ snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i);
goto out_fail;
}
hdmi_update_short_audio_desc(e->sad + i,
present = (present & AC_PINSENSE_PRESENCE);
#ifdef CONFIG_SND_DEBUG_VERBOSE
- printk(KERN_INFO "pinp = %d, eldv = %d\n", !!present, !!eldv);
+ printk(KERN_INFO "HDMI: sink_present = %d, eld_valid = %d\n",
+ !!present, !!eldv);
#endif
return eldv && present;
size = snd_hdmi_get_eld_size(codec, nid);
if (size == 0) {
/* wfg: workaround for ASUS P5E-VM HDMI board */
- snd_printd(KERN_INFO "ELD buf size is 0, force 128\n");
+ snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
size = 128;
}
if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) {
- snd_printd(KERN_INFO "Invalid ELD buf size %d\n", size);
+ snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
return -ERANGE;
}
static void hdmi_show_short_audio_desc(struct cea_sad *a)
{
char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
+ char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
- printk(KERN_INFO "coding type: %s\n",
- cea_audio_coding_type_names[a->format]);
- printk(KERN_INFO "channels: %d\n", a->channels);
+ if (!a->format)
+ return;
snd_print_pcm_rates(a->rates, buf, sizeof(buf));
- printk(KERN_INFO "sampling rates: %s\n", buf);
if (a->format == AUDIO_CODING_TYPE_LPCM)
- printk(KERN_INFO "sample bits: 0x%x\n", a->sample_bits);
-
- if (a->max_bitrate)
- printk(KERN_INFO "max bitrate: %d\n", a->max_bitrate);
-
- if (a->profile)
- printk(KERN_INFO "profile: %d\n", a->profile);
+ snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8));
+ else if (a->max_bitrate)
+ snprintf(buf2, sizeof(buf2),
+ ", max bitrate = %d", a->max_bitrate);
+ else
+ buf2[0] = '\0';
+
+ printk(KERN_INFO "HDMI: supports coding type %s:"
+ " channels = %d, rates =%s%s\n",
+ cea_audio_coding_type_names[a->format],
+ a->channels,
+ buf,
+ buf2);
}
void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
void snd_hdmi_show_eld(struct hdmi_eld *e)
{
int i;
- char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
- printk(KERN_INFO "ELD buffer size is %d\n", e->eld_size);
- printk(KERN_INFO "ELD baseline len is %d*4\n", e->baseline_len);
- printk(KERN_INFO "vendor block len is %d\n",
- e->eld_size - e->baseline_len * 4 - 4);
- printk(KERN_INFO "ELD version is %s\n",
- eld_versoin_names[e->eld_ver]);
- printk(KERN_INFO "CEA EDID version is %s\n",
- cea_edid_version_names[e->cea_edid_ver]);
- printk(KERN_INFO "manufacture id is 0x%x\n", e->manufacture_id);
- printk(KERN_INFO "product id is 0x%x\n", e->product_id);
- printk(KERN_INFO "port id is 0x%llx\n", (long long)e->port_id);
- printk(KERN_INFO "HDCP support is %d\n", e->support_hdcp);
- printk(KERN_INFO "AI support is %d\n", e->support_ai);
- printk(KERN_INFO "SAD count is %d\n", e->sad_count);
- printk(KERN_INFO "audio sync delay is %x\n", e->aud_synch_delay);
- printk(KERN_INFO "connection type is %s\n",
- eld_connection_type_names[e->conn_type]);
- printk(KERN_INFO "monitor name is %s\n", e->monitor_name);
+ printk(KERN_INFO "HDMI: detected monitor %s at connection type %s\n",
+ e->monitor_name,
+ eld_connection_type_names[e->conn_type]);
- snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
- printk(KERN_INFO "speaker allocations: (0x%x)%s\n", e->spk_alloc, buf);
+ if (e->spk_alloc) {
+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+ snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
+ printk(KERN_INFO "HDMI: available speakers:%s\n", buf);
+ }
for (i = 0; i < e->sad_count; i++)
hdmi_show_short_audio_desc(e->sad + i);
struct hdmi_eld *e = entry->private_data;
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
int i;
-
- snd_iprintf(buffer, "monitor name\t\t%s\n", e->monitor_name);
+ static char *eld_versoin_names[32] = {
+ "reserved",
+ "reserved",
+ "CEA-861D or below",
+ [3 ... 30] = "reserved",
+ [31] = "partial"
+ };
+ static char *cea_edid_version_names[8] = {
+ "no CEA EDID Timing Extension block present",
+ "CEA-861",
+ "CEA-861-A",
+ "CEA-861-B, C or D",
+ [4 ... 7] = "reserved"
+ };
+
+ snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
snd_iprintf(buffer, "connection_type\t\t%s\n",
eld_connection_type_names[e->conn_type]);
snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
hdmi_print_sad_info(i, e->sad + i, buffer);
}
+static void hdmi_write_eld_info(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct hdmi_eld *e = entry->private_data;
+ char line[64];
+ char name[64];
+ char *sname;
+ long long val;
+ int n;
+
+ while (!snd_info_get_line(buffer, line, sizeof(line))) {
+ if (sscanf(line, "%s %llx", name, &val) != 2)
+ continue;
+ /*
+ * We don't allow modification to these fields:
+ * monitor_name manufacture_id product_id
+ * eld_version edid_version
+ */
+ if (!strcmp(name, "connection_type"))
+ e->conn_type = val;
+ else if (!strcmp(name, "port_id"))
+ e->port_id = val;
+ else if (!strcmp(name, "support_hdcp"))
+ e->support_hdcp = val;
+ else if (!strcmp(name, "support_ai"))
+ e->support_ai = val;
+ else if (!strcmp(name, "audio_sync_delay"))
+ e->aud_synch_delay = val;
+ else if (!strcmp(name, "speakers"))
+ e->spk_alloc = val;
+ else if (!strcmp(name, "sad_count"))
+ e->sad_count = val;
+ else if (!strncmp(name, "sad", 3)) {
+ sname = name + 4;
+ n = name[3] - '0';
+ if (name[4] >= '0' && name[4] <= '9') {
+ sname++;
+ n = 10 * n + name[4] - '0';
+ }
+ if (n < 0 || n > 31) /* double the CEA limit */
+ continue;
+ if (!strcmp(sname, "_coding_type"))
+ e->sad[n].format = val;
+ else if (!strcmp(sname, "_channels"))
+ e->sad[n].channels = val;
+ else if (!strcmp(sname, "_rates"))
+ e->sad[n].rates = val;
+ else if (!strcmp(sname, "_bits"))
+ e->sad[n].sample_bits = val;
+ else if (!strcmp(sname, "_max_bitrate"))
+ e->sad[n].max_bitrate = val;
+ else if (!strcmp(sname, "_profile"))
+ e->sad[n].profile = val;
+ if (n >= e->sad_count)
+ e->sad_count = n + 1;
+ }
+ }
+}
+
+
int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld)
{
char name[32];
return err;
snd_info_set_text_ops(entry, eld, hdmi_print_eld_info);
+ entry->c.text.write = hdmi_write_eld_info;
+ entry->mode |= S_IWUSR;
+ eld->proc_entry = entry;
+
return 0;
}
-#endif
+void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
+{
+ if (!codec->bus->shutdown && eld->proc_entry) {
+ snd_device_free(codec->bus->card, eld->proc_entry);
+ eld->proc_entry = NULL;
+ }
+}
+
+#endif /* CONFIG_PROC_FS */