[igt-dev] [PATCH i-g-t 3/3] lib/igt_kms: introduce igt_kms_get_hdmi_audio_edid
Simon Ser
simon.ser at intel.com
Mon May 27 12:03:07 UTC 2019
This new function uses igt_edid to generate an EDID suitable for testing HDMI
audio. It's imported from kms_chamelium with minor edits, it's used there and
in kms_hdmi_inject. A (unexported for now) generate_hdmi_audio_edid function
enables generation of EDIDs with arbitrary SAD and speaker blocks.
This obsoletes kmstest_edid_add_audio.
The sanity check for the HDMI audio EDID has been moved from
lib/tests/igt_hdmi_inject.c to lib/tests/igt_edid.c.
Signed-off-by: Simon Ser <simon.ser at intel.com>
---
lib/igt_kms.c | 133 ++++++++++++++++++++----------------
lib/igt_kms.h | 10 ++-
lib/tests/igt_edid.c | 1 +
lib/tests/igt_hdmi_inject.c | 1 -
tests/kms_chamelium.c | 62 +----------------
tests/kms_hdmi_inject.c | 9 ++-
6 files changed, 88 insertions(+), 128 deletions(-)
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index a7dc3ac3fb66..d7d711a72d27 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -26,6 +26,8 @@
*/
#include "config.h"
+
+#include <assert.h>
#include <inttypes.h>
#include <unistd.h>
#include <stdio.h>
@@ -180,6 +182,79 @@ const unsigned char *igt_kms_get_alt_edid(void)
return (unsigned char *) &edid;
}
+static void
+generate_hdmi_audio_edid(unsigned char raw_edid[static HDMI_AUDIO_EDID_LENGTH],
+ struct cea_sad *sad,
+ struct cea_speaker_alloc *speaker_alloc)
+{
+ struct edid *edid;
+ struct edid_ext *edid_ext;
+ struct edid_cea *edid_cea;
+ char *cea_data;
+ struct edid_cea_data_block *block;
+ const struct cea_vsd *vsd;
+ size_t cea_data_size, vsd_size;
+
+ /* Create a new EDID from the base IGT EDID, and add an
+ * extension that advertises audio support. */
+ edid = (struct edid *) raw_edid;
+ memcpy(edid, igt_kms_get_base_edid(), sizeof(struct edid));
+ edid->extensions_len = 1;
+ edid_ext = &edid->extensions[0];
+ edid_cea = &edid_ext->data.cea;
+ cea_data = edid_cea->data;
+ cea_data_size = 0;
+
+ /* Short Audio Descriptor block */
+ block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+ cea_data_size += edid_cea_data_block_set_sad(block, sad, 1);
+
+ /* A Vendor Specific Data block is needed for HDMI audio */
+ block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+ vsd = cea_vsd_get_hdmi_default(&vsd_size);
+ cea_data_size += edid_cea_data_block_set_vsd(block, vsd,
+ vsd_size);
+
+ /* Speaker Allocation Data block */
+ block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+ cea_data_size += edid_cea_data_block_set_speaker_alloc(block,
+ speaker_alloc);
+
+ assert(cea_data_size <= sizeof(edid_cea->data));
+
+ edid_ext_set_cea(edid_ext, cea_data_size,
+ EDID_CEA_BASIC_AUDIO);
+
+ edid_update_checksum(edid);
+ edid_ext_update_cea_checksum(edid_ext);
+}
+
+const unsigned char *igt_kms_get_hdmi_audio_edid(void)
+{
+ int channels;
+ uint8_t sampling_rates, sample_sizes;
+ static unsigned char raw_edid[HDMI_AUDIO_EDID_LENGTH] = {0};
+ struct cea_sad sad = {0};
+ struct cea_speaker_alloc speaker_alloc = {0};
+
+ /* Initialize the Short Audio Descriptor for PCM */
+ channels = 2;
+ sampling_rates = CEA_SAD_SAMPLING_RATE_32KHZ |
+ CEA_SAD_SAMPLING_RATE_44KHZ |
+ CEA_SAD_SAMPLING_RATE_48KHZ;
+ sample_sizes = CEA_SAD_SAMPLE_SIZE_16 |
+ CEA_SAD_SAMPLE_SIZE_20 |
+ CEA_SAD_SAMPLE_SIZE_24;
+ cea_sad_init_pcm(&sad, channels, sampling_rates, sample_sizes);
+
+ /* Initialize the Speaker Allocation Data */
+ speaker_alloc.speakers = CEA_SPEAKER_FRONT_LEFT_RIGHT_CENTER;
+
+ generate_hdmi_audio_edid(raw_edid, &sad, &speaker_alloc);
+
+ return raw_edid;
+}
+
const char * const igt_plane_prop_names[IGT_NUM_PLANE_PROPS] = {
[IGT_PLANE_SRC_X] = "SRC_X",
[IGT_PLANE_SRC_Y] = "SRC_Y",
@@ -1356,64 +1431,6 @@ void kmstest_edid_add_4k(const unsigned char *edid, size_t length,
update_edid_csum(new_edid.data, length);
}
-/**
- * kmstest_edid_add_audio:
- * @edid: an existing valid edid block
- * @length: length of @edid
- * @new_edid_ptr: pointer to where the new edid will be placed
- * @new_length: pointer to the size of the new edid
- *
- * Makes a copy of an existing edid block and adds an extension indicating
- * basic audio support and speaker data block.
- *
- */
-void kmstest_edid_add_audio(const unsigned char *edid, size_t length,
- unsigned char *new_edid_ptr[], size_t *new_length)
-{
- char vsdb_block_len = 10, audio_block_len = 4, spkr_block_len = 4;
- struct edid_block new_edid = init_cea_block(edid, length, new_edid_ptr,
- new_length,
- vsdb_block_len +
- audio_block_len +
- spkr_block_len,
- DTD_SUPPORTS_AUDIO);
- int pos = new_edid.pos;
-
- /* audio block, short audio block descriptors */
- new_edid.data[pos++] = (1 << 5) | (audio_block_len - 1);
- new_edid.data[pos++] = 0x09; /* Audio Format, PCM */
- new_edid.data[pos++] = 0x07; /* Frequency, 32, 44.1, 48kHz */
- new_edid.data[pos++] = 0x07; /* Bit Rate 16, 20, 24 bit */
-
-
- /* vsdb block ( id | length ) -- need vsdb as well
- * otherwise the kernel will fallback to lower clock modes */
- new_edid.data[pos++] = 3 << 5 | (vsdb_block_len - 1);
- /* registration id */
- new_edid.data[pos++] = 0x3;
- new_edid.data[pos++] = 0xc;
- new_edid.data[pos++] = 0x0;
- /* source physical address */
- new_edid.data[pos++] = 0x10;
- new_edid.data[pos++] = 0x00;
- /* Supports_AI ... etc */
- new_edid.data[pos++] = 0x00;
- /* Max TMDS Clock */
- new_edid.data[pos++] = 0x00;
- /* Latency present, HDMI Video Present */
- new_edid.data[pos++] = 0x20;
- /* HDMI Video */
- new_edid.data[pos++] = 0x00; /* 3D present */
-
- /* speaker data block */
- new_edid.data[pos++] = (4 << 5) | (spkr_block_len - 1);
- new_edid.data[pos++] = (1 << 5);
- new_edid.data[pos++] = 0x00;
- new_edid.data[pos++] = 0x00;
-
- update_edid_csum(new_edid.data, length);
-}
-
/**
* kmstest_unset_all_crtcs:
* @drm_fd: the DRM fd
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 38bdc08f3d50..4ac28131b6d9 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -196,7 +196,6 @@ bool kmstest_force_connector(int fd, drmModeConnector *connector,
enum kmstest_force_connector_state state);
void kmstest_edid_add_3d(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
void kmstest_edid_add_4k(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
-void kmstest_edid_add_audio(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
void kmstest_force_edid(int drm_fd, drmModeConnector *connector,
const unsigned char *edid, size_t length);
@@ -754,9 +753,14 @@ void igt_reset_connectors(void);
uint32_t kmstest_get_vbl_flag(uint32_t pipe_id);
+struct cea_sad;
+struct cea_speaker_alloc;
+
#define EDID_LENGTH 128
-const unsigned char* igt_kms_get_base_edid(void);
-const unsigned char* igt_kms_get_alt_edid(void);
+#define HDMI_AUDIO_EDID_LENGTH (2 * EDID_LENGTH)
+const unsigned char *igt_kms_get_base_edid(void);
+const unsigned char *igt_kms_get_alt_edid(void);
+const unsigned char *igt_kms_get_hdmi_audio_edid(void);
struct udev_monitor *igt_watch_hotplug(void);
bool igt_hotplug_detected(struct udev_monitor *mon,
diff --git a/lib/tests/igt_edid.c b/lib/tests/igt_edid.c
index 6cf6b5c14b53..a847df272525 100644
--- a/lib/tests/igt_edid.c
+++ b/lib/tests/igt_edid.c
@@ -75,6 +75,7 @@ igt_simple_main
} funcs[] = {
{ "base", igt_kms_get_base_edid, 0 },
{ "alt", igt_kms_get_alt_edid, 0 },
+ { "hdmi_audio", igt_kms_get_hdmi_audio_edid, 1 },
{0},
}, *f;
const unsigned char *edid;
diff --git a/lib/tests/igt_hdmi_inject.c b/lib/tests/igt_hdmi_inject.c
index 9b6780a14aa6..2534b1a23acb 100644
--- a/lib/tests/igt_hdmi_inject.c
+++ b/lib/tests/igt_hdmi_inject.c
@@ -73,7 +73,6 @@ igt_simple_main
} funcs[] = {
{ "3D", kmstest_edid_add_3d },
{ "4k", kmstest_edid_add_4k },
- { "audio", kmstest_edid_add_audio },
{ NULL, NULL },
}, *f;
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 8da6ec20759e..e75786d33765 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -1740,66 +1740,6 @@ test_hpd_storm_disable(data_t *data, struct chamelium_port *port, int width)
igt_hpd_storm_reset(data->drm_fd);
}
-#define HDMI_AUDIO_EDID_SIZE (sizeof(struct edid) + sizeof(struct edid_ext))
-
-static unsigned const char *get_hdmi_audio_edid(void)
-{
- int channels;
- uint8_t sampling_rates, sample_sizes;
- static unsigned char raw_edid[HDMI_AUDIO_EDID_SIZE] = {0};
- struct edid *edid;
- struct edid_ext *edid_ext;
- struct edid_cea *edid_cea;
- char *cea_data;
- struct edid_cea_data_block *block;
- struct cea_sad sad = {0};
- const struct cea_vsd *vsd;
- size_t cea_data_size, vsd_size;
-
- /* Initialize the Short Audio Descriptor for PCM */
- channels = 2; /* TODO: speaker alloc blocks for > 2 channels */
- sampling_rates = CEA_SAD_SAMPLING_RATE_32KHZ |
- CEA_SAD_SAMPLING_RATE_44KHZ |
- CEA_SAD_SAMPLING_RATE_48KHZ |
- CEA_SAD_SAMPLING_RATE_88KHZ |
- CEA_SAD_SAMPLING_RATE_96KHZ |
- CEA_SAD_SAMPLING_RATE_176KHZ |
- CEA_SAD_SAMPLING_RATE_192KHZ;
- sample_sizes = CEA_SAD_SAMPLE_SIZE_16 |
- CEA_SAD_SAMPLE_SIZE_20 |
- CEA_SAD_SAMPLE_SIZE_24;
- cea_sad_init_pcm(&sad, channels, sampling_rates, sample_sizes);
-
- /* Create a new EDID from the base IGT EDID, and add an
- * extension that advertises audio support. */
- edid = (struct edid *) raw_edid;
- memcpy(edid, igt_kms_get_base_edid(), sizeof(struct edid));
- edid->extensions_len = 1;
- edid_ext = &edid->extensions[0];
- edid_cea = &edid_ext->data.cea;
- cea_data = edid_cea->data;
- cea_data_size = 0;
-
- block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
- cea_data_size += edid_cea_data_block_set_sad(block, &sad, 1);
-
- /* A Vendor Specific Data block is needed for HDMI audio */
- block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
- vsd = cea_vsd_get_hdmi_default(&vsd_size);
- cea_data_size += edid_cea_data_block_set_vsd(block, vsd,
- vsd_size);
-
- igt_assert(cea_data_size <= sizeof(edid_cea->data));
-
- edid_ext_set_cea(edid_ext, cea_data_size,
- EDID_CEA_BASIC_AUDIO);
-
- edid_update_checksum(edid);
- edid_ext_update_cea_checksum(edid_ext);
-
- return raw_edid;
-}
-
static const unsigned char *get_edid(enum test_edid edid)
{
switch (edid) {
@@ -1811,7 +1751,7 @@ static const unsigned char *get_edid(enum test_edid edid)
case TEST_EDID_ALT:
return igt_kms_get_alt_edid();
case TEST_EDID_HDMI_AUDIO:
- return get_hdmi_audio_edid();
+ return igt_kms_get_hdmi_audio_edid();
}
assert(0); /* unreachable */
}
diff --git a/tests/kms_hdmi_inject.c b/tests/kms_hdmi_inject.c
index a24061042c20..47f5ef2c558a 100644
--- a/tests/kms_hdmi_inject.c
+++ b/tests/kms_hdmi_inject.c
@@ -24,6 +24,7 @@
#include <dirent.h>
#include "igt.h"
+#include "igt_edid.h"
#define HDISPLAY_4K 3840
#define VDISPLAY_4K 2160
@@ -211,14 +212,14 @@ eld_is_valid(void)
static void
hdmi_inject_audio(int drm_fd, drmModeConnector *connector)
{
- unsigned char *edid;
+ const unsigned char *edid;
size_t length;
int fb_id, cid, ret, crtc_mask = -1;
struct igt_fb fb;
struct kmstest_connector_config config;
- kmstest_edid_add_audio(igt_kms_get_base_edid(), EDID_LENGTH, &edid,
- &length);
+ edid = igt_kms_get_hdmi_audio_edid();
+ length = HDMI_AUDIO_EDID_LENGTH;
kmstest_force_edid(drm_fd, connector, edid, length);
@@ -261,8 +262,6 @@ hdmi_inject_audio(int drm_fd, drmModeConnector *connector)
kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_UNSPECIFIED);
kmstest_force_edid(drm_fd, connector, NULL, 0);
-
- free(edid);
}
igt_main
--
2.21.0
More information about the igt-dev
mailing list