diff options
author | Simon Ser <simon.ser@intel.com> | 2019-05-29 17:40:08 +0300 |
---|---|---|
committer | Simon Ser <simon.ser@intel.com> | 2019-06-04 16:18:44 +0300 |
commit | a98c9cd50aa48933217ca41055279ccb1680d25b (patch) | |
tree | f957055e4fb3156f05d28c312cb7d2bf3bd3b050 | |
parent | fa0086150a1651d66f80410857ecbe14696e8cdf (diff) |
lib/igt_eld: parse Short Audio Descriptors
Each valid ELD entry can contain zero, one or more Short Audio Descriptor
blocks. These are exposed in sadN_* fields (N being the index of the SAD).
We need to parse them to be able to check that ALSA has properly processed
them.
Signed-off-by: Simon Ser <simon.ser@intel.com>
Reviewed-by: Martin Peres <martin.peres@linux.intel.com>
-rw-r--r-- | lib/igt_eld.c | 90 | ||||
-rw-r--r-- | lib/igt_eld.h | 14 |
2 files changed, 103 insertions, 1 deletions
diff --git a/lib/igt_eld.c b/lib/igt_eld.c index 2f98b51e..1bb294e3 100644 --- a/lib/igt_eld.c +++ b/lib/igt_eld.c @@ -41,8 +41,84 @@ * DisplayPort connectors supporting audio. This includes the monitor name and * the supported audio parameters (formats, sampling rates, sample sizes and so * on). + * + * Audio parameters come from Short Audio Descriptors (SAD) blocks in the + * EDID. Enumerations from igt_edid are used since they are the same. */ +static enum cea_sad_format parse_sad_coding_type(const char *value) +{ + if (strcmp(value, "LPCM") == 0) + return CEA_SAD_FORMAT_PCM; + else + return 0; +} + +static enum cea_sad_sampling_rate parse_sad_rate(const char *value) +{ + switch (atoi(value)) { + case 32000: + return CEA_SAD_SAMPLING_RATE_32KHZ; + case 44100: + return CEA_SAD_SAMPLING_RATE_44KHZ; + case 48000: + return CEA_SAD_SAMPLING_RATE_48KHZ; + case 88000: + return CEA_SAD_SAMPLING_RATE_88KHZ; + case 96000: + return CEA_SAD_SAMPLING_RATE_96KHZ; + case 176000: + return CEA_SAD_SAMPLING_RATE_176KHZ; + case 192000: + return CEA_SAD_SAMPLING_RATE_192KHZ; + default: + return 0; + } +} + +static enum cea_sad_pcm_sample_size parse_sad_bit(const char *value) +{ + switch (atoi(value)) { + case 16: + return CEA_SAD_SAMPLE_SIZE_16; + case 20: + return CEA_SAD_SAMPLE_SIZE_20; + case 24: + return CEA_SAD_SAMPLE_SIZE_24; + default: + return 0; + } +} + +static void parse_sad_field(struct eld_sad *sad, const char *key, char *value) +{ + char *tok; + + /* Some fields are prefixed with the raw hex value, strip it */ + if (value[0] == '[') { + value = strchr(value, ' '); + igt_assert(value != NULL); + value++; /* skip the space */ + } + + /* Single-value fields */ + if (strcmp(key, "coding_type") == 0) + sad->coding_type = parse_sad_coding_type(value); + else if (strcmp(key, "channels") == 0) + sad->channels = atoi(value); + + /* Multiple-value fields */ + tok = strtok(value, " "); + while (tok) { + if (strcmp(key, "rates") == 0) + sad->rates |= parse_sad_rate(tok); + else if (strcmp(key, "bits") == 0) + sad->bits |= parse_sad_bit(tok); + + tok = strtok(NULL, " "); + } +} + /** eld_parse_entry: parse an ELD entry * * Here is an example of an ELD entry: @@ -66,14 +142,18 @@ * sad0_channels 2 * sad0_rates [0xe0] 32000 44100 48000 * sad0_bits [0xe0000] 16 20 24 + * + * Each entry contains one or more SAD blocks. Their contents is exposed in + * sadN_* fields. */ static bool eld_parse_entry(const char *path, struct eld_entry *eld) { FILE *f; char buf[1024]; - char *key, *value; + char *key, *value, *sad_key; size_t len; bool monitor_present; + int sad_index; memset(eld, 0, sizeof(*eld)); @@ -100,6 +180,14 @@ static bool eld_parse_entry(const char *path, struct eld_entry *eld) else if (strcmp(key, "monitor_name") == 0) snprintf(eld->monitor_name, sizeof(eld->monitor_name), "%s", value); + else if (strcmp(key, "sad_count") == 0) + eld->sads_len = atoi(value); + else if (sscanf(key, "sad%d_%ms", &sad_index, &sad_key) == 2) { + igt_assert(sad_index < ELD_SADS_CAP); + igt_assert(sad_index < eld->sads_len); + parse_sad_field(&eld->sads[sad_index], sad_key, value); + free(sad_key); + } } if (ferror(f) != 0) { diff --git a/lib/igt_eld.h b/lib/igt_eld.h index 21fe3537..e1618788 100644 --- a/lib/igt_eld.h +++ b/lib/igt_eld.h @@ -30,9 +30,23 @@ #include <stdbool.h> +#include "igt_edid.h" + +#define ELD_SADS_CAP 4 + +/** eld_sad: Short Audio Descriptor */ +struct eld_sad { + enum cea_sad_format coding_type; + int channels; + unsigned int rates; /* enum cea_sad_sampling_rate */ + unsigned int bits; /* enum cea_sad_pcm_sample_size */ +}; + struct eld_entry { bool valid; char monitor_name[16]; + size_t sads_len; + struct eld_sad sads[ELD_SADS_CAP]; }; bool eld_has_igt(void); |