include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / sound / pci / hda / hda_eld.c
index da08dda..d8da18a 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <sound/core.h>
 #include <asm/unaligned.h>
 #include "hda_codec.h"
@@ -32,14 +33,6 @@ enum eld_versions {
        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,
@@ -48,14 +41,6 @@ enum cea_edid_versions {
        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",
@@ -72,7 +57,7 @@ static char *cea_speaker_allocation_names[] = {
 
 static char *eld_connection_type_names[4] = {
        "HDMI",
-       "Display Port",
+       "DisplayPort",
        "2-reserved",
        "3-reserved"
 };
@@ -118,7 +103,7 @@ static char *cea_audio_coding_type_names[] = {
        /*  6 */ "AAC-LC",
        /*  7 */ "DTS",
        /*  8 */ "ATRAC",
-       /*  9 */ "DSD (1-bit audio)",
+       /*  9 */ "DSD (One Bit Audio)",
        /* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)",
        /* 11 */ "DTS-HD",
        /* 12 */ "MLP (Dolby TrueHD)",
@@ -168,11 +153,11 @@ static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
                                        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;
        }
@@ -208,7 +193,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
        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:
@@ -254,7 +239,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
                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
@@ -267,8 +252,8 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 /*
  * Be careful, ELD buf could be totally rubbish!
  */
-static int hdmi_update_sink_eld(struct sink_eld *e,
-                               const unsigned char *buf, int size)
+static int hdmi_update_eld(struct hdmi_eld *e,
+                          const unsigned char *buf, int size)
 {
        int mnl;
        int i;
@@ -276,7 +261,8 @@ static int hdmi_update_sink_eld(struct sink_eld *e,
        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;
        }
 
@@ -300,17 +286,17 @@ static int hdmi_update_sink_eld(struct sink_eld *e,
        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,
@@ -324,22 +310,18 @@ out_fail:
        return -EINVAL;
 }
 
-static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid)
-{
-       return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0);
-}
-
 static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
 {
        int eldv;
        int present;
 
-       present = hdmi_present_sense(codec, nid);
+       present = snd_hda_pin_sense(codec, nid);
        eldv    = (present & AC_PINSENSE_ELDV);
        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;
@@ -350,8 +332,9 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
        return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
                                                 AC_DIPSIZE_ELD_BUF);
 }
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size);
 
-int snd_hdmi_get_eld(struct sink_eld *eld,
+int snd_hdmi_get_eld(struct hdmi_eld *eld,
                     struct hda_codec *codec, hda_nid_t nid)
 {
        int i;
@@ -365,11 +348,11 @@ int snd_hdmi_get_eld(struct sink_eld *eld,
        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;
        }
 
@@ -380,31 +363,37 @@ int snd_hdmi_get_eld(struct sink_eld *eld,
        for (i = 0; i < size; i++)
                buf[i] = hdmi_get_eld_byte(codec, nid, i);
 
-       ret = hdmi_update_sink_eld(eld, buf, size);
+       ret = hdmi_update_eld(eld, buf, size);
 
        kfree(buf);
        return ret;
 }
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld);
 
 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 frequencies: %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)
@@ -413,63 +402,51 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
 
        for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
                if (spk_alloc & (1 << i))
-                       j += snprintf(buf + j, buflen - j,  "%s ",
+                       j += snprintf(buf + j, buflen - j,  " %s",
                                        cea_speaker_allocation_names[i]);
        }
-       if (j)
-               j--;    /* skip last space */
        buf[j] = '\0';  /* necessary when j == 0 */
 }
+EXPORT_SYMBOL_HDA(snd_print_channel_allocation);
 
-void snd_hdmi_show_eld(struct sink_eld *e)
+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);
 }
+EXPORT_SYMBOL_HDA(snd_hdmi_show_eld);
 
 #ifdef CONFIG_PROC_FS
 
 static void hdmi_print_sad_info(int i, struct cea_sad *a,
                                struct snd_info_buffer *buffer)
 {
-       char buf[80];
+       char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
 
        snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
                        i, a->format, cea_audio_coding_type_names[a->format]);
        snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
 
        snd_print_pcm_rates(a->rates, buf, sizeof(buf));
-       snd_iprintf(buffer, "sad%d_sampling_rates\t[0x%x] %s\n",
-                       i, a->rates, buf);
+       snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
 
-       if (a->format == AUDIO_CODING_TYPE_LPCM)
-               snd_iprintf(buffer, "sad%d_sample_bits\t0x%x\n",
-                                                       i, a->sample_bits);
+       if (a->format == AUDIO_CODING_TYPE_LPCM) {
+               snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf));
+               snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n",
+                                                       i, a->sample_bits, buf);
+       }
 
        if (a->max_bitrate)
                snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
@@ -482,11 +459,27 @@ static void hdmi_print_sad_info(int i, struct cea_sad *a,
 static void hdmi_print_eld_info(struct snd_info_entry *entry,
                                struct snd_info_buffer *buffer)
 {
-       struct sink_eld *e = entry->private_data;
+       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_present\t\t%d\n", e->monitor_present);
+       snd_iprintf(buffer, "eld_valid\t\t%d\n", e->eld_valid);
+       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,
@@ -501,7 +494,7 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry,
        snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
 
        snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
-       snd_iprintf(buffer, "speakers\t\t[0x%x] %s\n", e->spk_alloc, buf);
+       snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf);
 
        snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
 
@@ -509,19 +502,98 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry,
                hdmi_print_sad_info(i, e->sad + i, buffer);
 }
 
-int snd_hda_eld_proc_new(struct hda_codec *codec, struct sink_eld *eld)
+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;
+       unsigned 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, "monitor_present"))
+                       e->monitor_present = val;
+               else if (!strcmp(name, "eld_valid"))
+                       e->eld_valid = val;
+               else 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 >= ELD_MAX_SAD)
+                               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,
+                        int index)
 {
        char name[32];
        struct snd_info_entry *entry;
        int err;
 
-       snprintf(name, sizeof(name), "eld#%d", codec->addr);
+       snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index);
        err = snd_card_proc_new(codec->bus->card, name, &entry);
        if (err < 0)
                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;
 }
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new);
 
-#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;
+       }
+}
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
+
+#endif /* CONFIG_PROC_FS */