[igt-dev] [PATCH i-g-t 3/3] lib/igt_kms: introduce igt_kms_get_hdmi_audio_edid

Martin Peres martin.peres at linux.intel.com
Mon Jun 3 13:18:06 UTC 2019


On 27/05/2019 15:03, Simon Ser wrote:
> 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);
> +}

Looks pretty neat!

Reviewed-by: Martin Peres <martin.peres at linux.intel.com>

> +
> +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
> 


More information about the igt-dev mailing list