The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data
@ 2026-06-12  4:53 Cássio Gabriel
  2026-06-12  4:53 ` [PATCH RFC 1/4] ALSA: pcm: Add common CEA channel allocation helpers Cássio Gabriel
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Cássio Gabriel @ 2026-06-12  4:53 UTC (permalink / raw)
  To: Takashi Iwai, Thierry Reding, Jonathan Hunter, Jaroslav Kysela
  Cc: linux-sound, linux-kernel, linux-tegra, notify,
	Cássio Gabriel

HDA HDMI and Intel HDMI LPE maintain separate copies of the ordered
CEA-861 channel allocation descriptors, ELD speaker expansion, and
allocation selection logic. The Intel implementation originated from
the HDA code, but the copies now differ in supported allocation ranges
and fallback behavior.

Move the common data and transformations alongside the PCM DRM ELD
helpers, then migrate both users while preserving their established
behavior. HDA retains the complete CA range and channel-count fallback.
Intel HDMI LPE retains its CA 0x1f limit, ELD speaker bits 0 through 6,
and lack of fallback for incompatible ELD data.

The descriptors and their derived channel counts and speaker masks
become compile-time constants. This removes duplicated mutable
initialization and provides one authoritative allocation table without
changing the existing allocation-selection policy.

No hardware was available to test this patch series.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
---
Cássio Gabriel (4):
      ALSA: pcm: Add common CEA channel allocation helpers
      ALSA: hda: Make CEA channel allocation interfaces const
      ALSA: hda: Use common CEA channel allocations
      ALSA: x86: Use common CEA channel allocations

 include/sound/hda_chmap.h         |  15 +--
 include/sound/pcm_drm_eld.h       |  16 +++
 sound/core/pcm_drm_eld.c          | 181 +++++++++++++++++++++++++++
 sound/hda/codecs/hdmi/atihdmi.c   |   6 +-
 sound/hda/codecs/hdmi/nvhdmi.c    |   2 +-
 sound/hda/codecs/hdmi/tegrahdmi.c |   2 +-
 sound/hda/core/Kconfig            |   1 +
 sound/hda/core/hdmi_chmap.c       | 252 +++++++-------------------------------
 sound/x86/Kconfig                 |   1 +
 sound/x86/intel_hdmi_audio.c      | 158 +++---------------------
 sound/x86/intel_hdmi_audio.h      |   9 --
 11 files changed, 271 insertions(+), 372 deletions(-)
---
base-commit: 0f6f60115bfc536c1935d3d0da66cf1d5c7d6055


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH RFC 1/4] ALSA: pcm: Add common CEA channel allocation helpers
  2026-06-12  4:53 [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Cássio Gabriel
@ 2026-06-12  4:53 ` Cássio Gabriel
  2026-06-12  4:53 ` [PATCH RFC 2/4] ALSA: hda: Make CEA channel allocation interfaces const Cássio Gabriel
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Cássio Gabriel @ 2026-06-12  4:53 UTC (permalink / raw)
  To: Takashi Iwai, Thierry Reding, Jonathan Hunter, Jaroslav Kysela
  Cc: linux-sound, linux-kernel, linux-tegra, notify,
	Cássio Gabriel

HDA HDMI and Intel HDMI LPE carry independent copies of the ordered
CEA-861 channel allocation table, ELD speaker expansion, and allocation
selection loop. The copies originated from the same implementation but
already differ in table coverage and fallback policy.

Move the immutable descriptors and common transformations next to the
other PCM DRM ELD helpers. Build the derived channel count and speaker
mask at compile time, and make table range and fallback policy explicit
arguments so consumers can preserve their existing contracts.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
---
 include/sound/pcm_drm_eld.h |  16 ++++
 sound/core/pcm_drm_eld.c    | 181 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 197 insertions(+)

diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
index 5a38413ada91..917228e97375 100644
--- a/include/sound/pcm_drm_eld.h
+++ b/include/sound/pcm_drm_eld.h
@@ -2,6 +2,8 @@
 #ifndef __SOUND_PCM_DRM_ELD_H
 #define __SOUND_PCM_DRM_ELD_H
 
+struct snd_info_buffer;
+
 enum eld_versions {
 	ELD_VER_CEA_861D	= 2,
 	ELD_VER_PARTIAL		= 31,
@@ -84,6 +86,20 @@ struct snd_parsed_hdmi_eld {
 	struct snd_cea_sad sad[ELD_MAX_SAD];
 };
 
+struct snd_cea_channel_speaker_allocation {
+	unsigned int ca_index;
+	unsigned int speakers[8];
+	unsigned int channels;
+	unsigned int spk_mask;
+};
+
+extern const struct snd_cea_channel_speaker_allocation
+	snd_cea_channel_allocations[];
+extern const unsigned int snd_cea_channel_allocations_count;
+unsigned int snd_cea_spk_mask_from_alloc(unsigned int spk_alloc);
+int snd_cea_channel_allocation(unsigned int spk_alloc, unsigned int channels,
+			       unsigned int max_ca, bool fallback);
+
 int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
 
 int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index 1941ee520063..20156a9e3ed9 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -24,6 +24,187 @@
 #define SAD1_RATE_176400_MASK	BIT(5)
 #define SAD1_RATE_192000_MASK	BIT(6)
 
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel notions LS/RS in SMPTE 320M correspond to
+ * CEA RL/RR; the SMPTE channel assignment C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+	FL  = BIT(0),	/* Front Left */
+	FC  = BIT(1),	/* Front Center */
+	FR  = BIT(2),	/* Front Right */
+	FLC = BIT(3),	/* Front Left Center */
+	FRC = BIT(4),	/* Front Right Center */
+	RL  = BIT(5),	/* Rear Left */
+	RC  = BIT(6),	/* Rear Center */
+	RR  = BIT(7),	/* Rear Right */
+	RLC = BIT(8),	/* Rear Left Center */
+	RRC = BIT(9),	/* Rear Right Center */
+	LFE = BIT(10),	/* Low Frequency Effect */
+	FLW = BIT(11),	/* Front Left Wide */
+	FRW = BIT(12),	/* Front Right Wide */
+	FLH = BIT(13),	/* Front Left High */
+	FCH = BIT(14),	/* Front Center High */
+	FRH = BIT(15),	/* Front Right High */
+	TC  = BIT(16),	/* Top Center */
+};
+
+#define CEA_CHANNEL_ALLOCATION(_ca, _s7, _s6, _s5, _s4, _s3, _s2, _s1, _s0) \
+	{ .ca_index = (_ca), .speakers = { (_s7), (_s6), (_s5), (_s4), \
+		(_s3), (_s2), (_s1), (_s0) }, \
+	  .channels = !!(_s7) + !!(_s6) + !!(_s5) + !!(_s4) + \
+		!!(_s3) + !!(_s2) + !!(_s1) + !!(_s0), \
+	  .spk_mask = (_s7) | (_s6) | (_s5) | (_s4) | (_s3) | (_s2) | \
+		(_s1) | (_s0) }
+
+/*
+ * This is an ordered list. Earlier entries have a better chance of being
+ * selected by snd_cea_channel_allocation().
+ */
+const struct snd_cea_channel_speaker_allocation snd_cea_channel_allocations[] = {
+	/*                         channel:  7    6    5    4    3    2    1    0 */
+	CEA_CHANNEL_ALLOCATION(0x00,   0,   0,   0,   0,   0,   0,  FR,  FL),
+	/* 2.1 */
+	CEA_CHANNEL_ALLOCATION(0x01,   0,   0,   0,   0,   0, LFE,  FR,  FL),
+	/* Dolby Surround */
+	CEA_CHANNEL_ALLOCATION(0x02,   0,   0,   0,   0,  FC,   0,  FR,  FL),
+	/* surround40 */
+	CEA_CHANNEL_ALLOCATION(0x08,   0,   0,  RR,  RL,   0,   0,  FR,  FL),
+	/* surround41 */
+	CEA_CHANNEL_ALLOCATION(0x09,   0,   0,  RR,  RL,   0, LFE,  FR,  FL),
+	/* surround50 */
+	CEA_CHANNEL_ALLOCATION(0x0a,   0,   0,  RR,  RL,  FC,   0,  FR,  FL),
+	/* surround51 */
+	CEA_CHANNEL_ALLOCATION(0x0b,   0,   0,  RR,  RL,  FC, LFE,  FR,  FL),
+	/* 6.1 */
+	CEA_CHANNEL_ALLOCATION(0x0f,   0,  RC,  RR,  RL,  FC, LFE,  FR,  FL),
+	/* surround71 */
+	CEA_CHANNEL_ALLOCATION(0x13, RRC, RLC,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x03,   0,   0,   0,   0,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x04,   0,   0,   0,  RC,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x05,   0,   0,   0,  RC,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x06,   0,   0,   0,  RC,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x07,   0,   0,   0,  RC,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x0c,   0,  RC,  RR,  RL,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x0d,   0,  RC,  RR,  RL,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x0e,   0,  RC,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x10, RRC, RLC,  RR,  RL,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x11, RRC, RLC,  RR,  RL,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x12, RRC, RLC,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x14, FRC, FLC,   0,   0,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x15, FRC, FLC,   0,   0,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x16, FRC, FLC,   0,   0,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x17, FRC, FLC,   0,   0,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x18, FRC, FLC,   0,  RC,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x19, FRC, FLC,   0,  RC,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x1a, FRC, FLC,   0,  RC,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x1b, FRC, FLC,   0,  RC,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x1c, FRC, FLC,  RR,  RL,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x1d, FRC, FLC,  RR,  RL,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x1e, FRC, FLC,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x1f, FRC, FLC,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x20,   0, FCH,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x21,   0, FCH,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x22,  TC,   0,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x23,  TC,   0,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x24, FRH, FLH,  RR,  RL,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x25, FRH, FLH,  RR,  RL,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x26, FRW, FLW,  RR,  RL,   0,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x27, FRW, FLW,  RR,  RL,   0, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x28,  TC,  RC,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x29,  TC,  RC,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x2a, FCH,  RC,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x2b, FCH,  RC,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x2c,  TC, FCH,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x2d,  TC, FCH,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x2e, FRH, FLH,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x2f, FRH, FLH,  RR,  RL,  FC, LFE,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x30, FRW, FLW,  RR,  RL,  FC,   0,  FR,  FL),
+	CEA_CHANNEL_ALLOCATION(0x31, FRW, FLW,  RR,  RL,  FC, LFE,  FR,  FL),
+};
+EXPORT_SYMBOL_GPL(snd_cea_channel_allocations);
+
+const unsigned int snd_cea_channel_allocations_count =
+	ARRAY_SIZE(snd_cea_channel_allocations);
+EXPORT_SYMBOL_GPL(snd_cea_channel_allocations_count);
+
+/* ELD SA bits in the CEA Speaker Allocation data block. */
+static const unsigned int eld_speaker_allocation_bits[] = {
+	[0] = FL | FR,
+	[1] = LFE,
+	[2] = FC,
+	[3] = RL | RR,
+	[4] = RC,
+	[5] = FLC | FRC,
+	[6] = RLC | RRC,
+	/* Not represented by the baseline ELD speaker allocation byte. */
+	[7] = FLW | FRW,
+	[8] = FLH | FRH,
+	[9] = TC,
+	[10] = FCH,
+};
+
+unsigned int snd_cea_spk_mask_from_alloc(unsigned int spk_alloc)
+{
+	unsigned int spk_mask = 0;
+	int i;
+
+	/* Expand ELD's compact, paired speaker allocation into a full mask. */
+	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++)
+		if (spk_alloc & BIT(i))
+			spk_mask |= eld_speaker_allocation_bits[i];
+
+	return spk_mask;
+}
+EXPORT_SYMBOL_GPL(snd_cea_spk_mask_from_alloc);
+
+/*
+ * The transformation takes two steps:
+ *
+ *      spk_alloc => eld_speaker_allocation_bits[] => spk_mask
+ *       spk_mask => snd_cea_channel_allocations[] => CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+ */
+int snd_cea_channel_allocation(unsigned int spk_alloc, unsigned int channels,
+			       unsigned int max_ca, bool fallback)
+{
+	unsigned int spk_mask, i;
+
+	/* CA 0 is the basic stereo allocation. */
+	if (channels <= 2)
+		return 0;
+
+	spk_mask = snd_cea_spk_mask_from_alloc(spk_alloc);
+	for (i = 0; i < snd_cea_channel_allocations_count; i++) {
+		const struct snd_cea_channel_speaker_allocation *ca;
+
+		ca = &snd_cea_channel_allocations[i];
+		if (ca->ca_index <= max_ca && ca->channels == channels &&
+		    (spk_mask & ca->spk_mask) == ca->spk_mask)
+			return ca->ca_index;
+	}
+
+	/* Fall back to the preferred allocation with the requested channels. */
+	if (fallback)
+		for (i = 0; i < snd_cea_channel_allocations_count; i++)
+			if (snd_cea_channel_allocations[i].ca_index <= max_ca &&
+			    snd_cea_channel_allocations[i].channels == channels)
+				return snd_cea_channel_allocations[i].ca_index;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_cea_channel_allocation);
+
 static const unsigned int eld_rates[] = {
 	32000,
 	44100,

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH RFC 2/4] ALSA: hda: Make CEA channel allocation interfaces const
  2026-06-12  4:53 [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Cássio Gabriel
  2026-06-12  4:53 ` [PATCH RFC 1/4] ALSA: pcm: Add common CEA channel allocation helpers Cássio Gabriel
@ 2026-06-12  4:53 ` Cássio Gabriel
  2026-06-12  4:53 ` [PATCH RFC 3/4] ALSA: hda: Use common CEA channel allocations Cássio Gabriel
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Cássio Gabriel @ 2026-06-12  4:53 UTC (permalink / raw)
  To: Takashi Iwai, Thierry Reding, Jonathan Hunter, Jaroslav Kysela
  Cc: linux-sound, linux-kernel, linux-tegra, notify,
	Cássio Gabriel

The CEA channel allocation descriptors are initialized once and only
read by the HDA channel-map helpers and codec-specific callbacks.

Qualify the pointers passed through these interfaces as const. This
makes their read-only contract explicit and prepares the interfaces for
using an immutable common allocation table.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
---
 include/sound/hda_chmap.h         |  8 +++++---
 sound/hda/codecs/hdmi/atihdmi.c   |  6 +++---
 sound/hda/codecs/hdmi/nvhdmi.c    |  3 ++-
 sound/hda/codecs/hdmi/tegrahdmi.c |  3 ++-
 sound/hda/core/hdmi_chmap.c       | 12 +++++++-----
 5 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/include/sound/hda_chmap.h b/include/sound/hda_chmap.h
index e508f3192294..b539595fd5cd 100644
--- a/include/sound/hda_chmap.h
+++ b/include/sound/hda_chmap.h
@@ -28,9 +28,10 @@ struct hdac_chmap_ops {
 	 * for devices that have non-standard mapping requirements.
 	 */
 	int (*chmap_cea_alloc_validate_get_type)(struct hdac_chmap *chmap,
-		struct hdac_cea_channel_speaker_allocation *cap, int channels);
+		const struct hdac_cea_channel_speaker_allocation *cap,
+		int channels);
 	void (*cea_alloc_to_tlv_chmap)(struct hdac_chmap *hchmap,
-		struct hdac_cea_channel_speaker_allocation *cap,
+		const struct hdac_cea_channel_speaker_allocation *cap,
 		unsigned int *chmap, int channels);
 
 	/* check that the user-given chmap is supported */
@@ -71,7 +72,8 @@ void snd_hdac_setup_channel_mapping(struct hdac_chmap *chmap,
 		       int channels, unsigned char *map,
 		       bool chmap_set);
 void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen);
-struct hdac_cea_channel_speaker_allocation *snd_hdac_get_ch_alloc_from_ca(int ca);
+const struct hdac_cea_channel_speaker_allocation *
+snd_hdac_get_ch_alloc_from_ca(int ca);
 int snd_hdac_chmap_to_spk_mask(unsigned char c);
 int snd_hdac_spk_to_chmap(int spk);
 int snd_hdac_add_chmap_ctls(struct snd_pcm *pcm, int pcm_idx,
diff --git a/sound/hda/codecs/hdmi/atihdmi.c b/sound/hda/codecs/hdmi/atihdmi.c
index 44366f75de33..9afdbf44b6f0 100644
--- a/sound/hda/codecs/hdmi/atihdmi.c
+++ b/sound/hda/codecs/hdmi/atihdmi.c
@@ -262,7 +262,7 @@ static int atihdmi_paired_swap_fc_lfe(int pos)
 static int atihdmi_paired_chmap_validate(struct hdac_chmap *chmap,
 			int ca, int chs, unsigned char *map)
 {
-	struct hdac_cea_channel_speaker_allocation *cap;
+	const struct hdac_cea_channel_speaker_allocation *cap;
 	int i, j;
 
 	/* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */
@@ -377,7 +377,7 @@ static int atihdmi_pin_get_slot_channel(struct hdac_device *hdac,
 
 static int atihdmi_paired_chmap_cea_alloc_validate_get_type(
 		struct hdac_chmap *chmap,
-		struct hdac_cea_channel_speaker_allocation *cap,
+		const struct hdac_cea_channel_speaker_allocation *cap,
 		int channels)
 {
 	int c;
@@ -406,7 +406,7 @@ static int atihdmi_paired_chmap_cea_alloc_validate_get_type(
 }
 
 static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
-		struct hdac_cea_channel_speaker_allocation *cap,
+		const struct hdac_cea_channel_speaker_allocation *cap,
 		unsigned int *chmap, int channels)
 {
 	/* produce paired maps for pre-rev3 ATI/AMD codecs */
diff --git a/sound/hda/codecs/hdmi/nvhdmi.c b/sound/hda/codecs/hdmi/nvhdmi.c
index 94671ad24b5e..eaefa016cdec 100644
--- a/sound/hda/codecs/hdmi/nvhdmi.c
+++ b/sound/hda/codecs/hdmi/nvhdmi.c
@@ -24,7 +24,8 @@ enum {
  * - 0x10de0040
  */
 static int nvhdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
-		struct hdac_cea_channel_speaker_allocation *cap, int channels)
+		const struct hdac_cea_channel_speaker_allocation *cap,
+		int channels)
 {
 	if (cap->ca_index == 0x00 && channels == 2)
 		return SNDRV_CTL_TLVT_CHMAP_FIXED;
diff --git a/sound/hda/codecs/hdmi/tegrahdmi.c b/sound/hda/codecs/hdmi/tegrahdmi.c
index ebb6410a4831..751a50cd4b7d 100644
--- a/sound/hda/codecs/hdmi/tegrahdmi.c
+++ b/sound/hda/codecs/hdmi/tegrahdmi.c
@@ -205,7 +205,8 @@ static int tegra_hdmi_build_pcms(struct hda_codec *codec)
  * - 0x10de0040
  */
 static int nvhdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
-		struct hdac_cea_channel_speaker_allocation *cap, int channels)
+		const struct hdac_cea_channel_speaker_allocation *cap,
+		int channels)
 {
 	if (cap->ca_index == 0x00 && channels == 2)
 		return SNDRV_CTL_TLVT_CHMAP_FIXED;
diff --git a/sound/hda/core/hdmi_chmap.c b/sound/hda/core/hdmi_chmap.c
index c897fc443467..f76b5dcc6433 100644
--- a/sound/hda/core/hdmi_chmap.c
+++ b/sound/hda/core/hdmi_chmap.c
@@ -341,7 +341,7 @@ static void hdmi_std_setup_channel_mapping(struct hdac_chmap *chmap,
 				       bool non_pcm,
 				       int ca)
 {
-	struct hdac_cea_channel_speaker_allocation *ch_alloc;
+	const struct hdac_cea_channel_speaker_allocation *ch_alloc;
 	int i;
 	int err;
 	int order;
@@ -581,7 +581,8 @@ int snd_hdac_get_active_channels(int ca)
 }
 EXPORT_SYMBOL_GPL(snd_hdac_get_active_channels);
 
-struct hdac_cea_channel_speaker_allocation *snd_hdac_get_ch_alloc_from_ca(int ca)
+const struct hdac_cea_channel_speaker_allocation *
+snd_hdac_get_ch_alloc_from_ca(int ca)
 {
 	return &channel_allocations[get_channel_allocation_order(ca)];
 }
@@ -622,7 +623,8 @@ static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol,
 }
 
 static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
-		struct hdac_cea_channel_speaker_allocation *cap, int channels)
+		const struct hdac_cea_channel_speaker_allocation *cap,
+		int channels)
 {
 	/* If the speaker allocation matches the channel count, it is OK.*/
 	if (cap->channels != channels)
@@ -633,7 +635,7 @@ static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
 }
 
 static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
-		struct hdac_cea_channel_speaker_allocation *cap,
+		const struct hdac_cea_channel_speaker_allocation *cap,
 		unsigned int *chmap, int channels)
 {
 	int count = 0;
@@ -690,7 +692,7 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 
 	for (chs = 2; chs <= max_chs; chs++) {
 		int i;
-		struct hdac_cea_channel_speaker_allocation *cap;
+		const struct hdac_cea_channel_speaker_allocation *cap;
 
 		cap = channel_allocations;
 		for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) {

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH RFC 3/4] ALSA: hda: Use common CEA channel allocations
  2026-06-12  4:53 [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Cássio Gabriel
  2026-06-12  4:53 ` [PATCH RFC 1/4] ALSA: pcm: Add common CEA channel allocation helpers Cássio Gabriel
  2026-06-12  4:53 ` [PATCH RFC 2/4] ALSA: hda: Make CEA channel allocation interfaces const Cássio Gabriel
@ 2026-06-12  4:53 ` Cássio Gabriel
  2026-06-12  4:53 ` [PATCH RFC 4/4] ALSA: x86: " Cássio Gabriel
  2026-06-12  9:13 ` [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Takashi Iwai
  4 siblings, 0 replies; 7+ messages in thread
From: Cássio Gabriel @ 2026-06-12  4:53 UTC (permalink / raw)
  To: Takashi Iwai, Thierry Reding, Jonathan Hunter, Jaroslav Kysela
  Cc: linux-sound, linux-kernel, linux-tegra, notify,
	Cássio Gabriel

Replace the HDA-local CEA allocation table and selection implementation
with the common PCM ELD data and helpers. Keep the complete CA range and
the existing channel-count fallback when the ELD speaker allocation does
not contain a compatible layout.

The HDA core now directly references helpers built under SND_PCM_ELD, so
select that option from SND_HDA_CORE.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
---
 include/sound/hda_chmap.h         |  17 +--
 sound/hda/codecs/hdmi/atihdmi.c   |   6 +-
 sound/hda/codecs/hdmi/nvhdmi.c    |   3 +-
 sound/hda/codecs/hdmi/tegrahdmi.c |   3 +-
 sound/hda/core/Kconfig            |   1 +
 sound/hda/core/hdmi_chmap.c       | 254 +++++++-------------------------------
 6 files changed, 54 insertions(+), 230 deletions(-)

diff --git a/include/sound/hda_chmap.h b/include/sound/hda_chmap.h
index b539595fd5cd..27e52b40a2a8 100644
--- a/include/sound/hda_chmap.h
+++ b/include/sound/hda_chmap.h
@@ -7,19 +7,12 @@
 #define __SOUND_HDA_CHMAP_H
 
 #include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
 #include <sound/hdaudio.h>
 
 
 #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
 
-struct hdac_cea_channel_speaker_allocation {
-	int ca_index;
-	int speakers[8];
-
-	/* derived values, just for convenience */
-	int channels;
-	int spk_mask;
-};
 struct hdac_chmap;
 
 struct hdac_chmap_ops {
@@ -28,10 +21,9 @@ struct hdac_chmap_ops {
 	 * for devices that have non-standard mapping requirements.
 	 */
 	int (*chmap_cea_alloc_validate_get_type)(struct hdac_chmap *chmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
-		int channels);
+		const struct snd_cea_channel_speaker_allocation *cap, int channels);
 	void (*cea_alloc_to_tlv_chmap)(struct hdac_chmap *hchmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
+		const struct snd_cea_channel_speaker_allocation *cap,
 		unsigned int *chmap, int channels);
 
 	/* check that the user-given chmap is supported */
@@ -72,8 +64,7 @@ void snd_hdac_setup_channel_mapping(struct hdac_chmap *chmap,
 		       int channels, unsigned char *map,
 		       bool chmap_set);
 void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen);
-const struct hdac_cea_channel_speaker_allocation *
-snd_hdac_get_ch_alloc_from_ca(int ca);
+const struct snd_cea_channel_speaker_allocation *snd_hdac_get_ch_alloc_from_ca(int ca);
 int snd_hdac_chmap_to_spk_mask(unsigned char c);
 int snd_hdac_spk_to_chmap(int spk);
 int snd_hdac_add_chmap_ctls(struct snd_pcm *pcm, int pcm_idx,
diff --git a/sound/hda/codecs/hdmi/atihdmi.c b/sound/hda/codecs/hdmi/atihdmi.c
index 9afdbf44b6f0..b1ac997dcce0 100644
--- a/sound/hda/codecs/hdmi/atihdmi.c
+++ b/sound/hda/codecs/hdmi/atihdmi.c
@@ -262,7 +262,7 @@ static int atihdmi_paired_swap_fc_lfe(int pos)
 static int atihdmi_paired_chmap_validate(struct hdac_chmap *chmap,
 			int ca, int chs, unsigned char *map)
 {
-	const struct hdac_cea_channel_speaker_allocation *cap;
+	const struct snd_cea_channel_speaker_allocation *cap;
 	int i, j;
 
 	/* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */
@@ -377,7 +377,7 @@ static int atihdmi_pin_get_slot_channel(struct hdac_device *hdac,
 
 static int atihdmi_paired_chmap_cea_alloc_validate_get_type(
 		struct hdac_chmap *chmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
+		const struct snd_cea_channel_speaker_allocation *cap,
 		int channels)
 {
 	int c;
@@ -406,7 +406,7 @@ static int atihdmi_paired_chmap_cea_alloc_validate_get_type(
 }
 
 static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
+		const struct snd_cea_channel_speaker_allocation *cap,
 		unsigned int *chmap, int channels)
 {
 	/* produce paired maps for pre-rev3 ATI/AMD codecs */
diff --git a/sound/hda/codecs/hdmi/nvhdmi.c b/sound/hda/codecs/hdmi/nvhdmi.c
index eaefa016cdec..91a4d66b88a7 100644
--- a/sound/hda/codecs/hdmi/nvhdmi.c
+++ b/sound/hda/codecs/hdmi/nvhdmi.c
@@ -24,8 +24,7 @@ enum {
  * - 0x10de0040
  */
 static int nvhdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
-		int channels)
+		const struct snd_cea_channel_speaker_allocation *cap, int channels)
 {
 	if (cap->ca_index == 0x00 && channels == 2)
 		return SNDRV_CTL_TLVT_CHMAP_FIXED;
diff --git a/sound/hda/codecs/hdmi/tegrahdmi.c b/sound/hda/codecs/hdmi/tegrahdmi.c
index 751a50cd4b7d..d8d34faad0c5 100644
--- a/sound/hda/codecs/hdmi/tegrahdmi.c
+++ b/sound/hda/codecs/hdmi/tegrahdmi.c
@@ -205,8 +205,7 @@ static int tegra_hdmi_build_pcms(struct hda_codec *codec)
  * - 0x10de0040
  */
 static int nvhdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
-		int channels)
+		const struct snd_cea_channel_speaker_allocation *cap, int channels)
 {
 	if (cap->ca_index == 0x00 && channels == 2)
 		return SNDRV_CTL_TLVT_CHMAP_FIXED;
diff --git a/sound/hda/core/Kconfig b/sound/hda/core/Kconfig
index bfdcf6384c52..b5158a44a183 100644
--- a/sound/hda/core/Kconfig
+++ b/sound/hda/core/Kconfig
@@ -2,6 +2,7 @@
 config SND_HDA_CORE
 	tristate
 	select REGMAP
+	select SND_PCM_ELD
 
 config SND_HDA_DSP_LOADER
 	bool
diff --git a/sound/hda/core/hdmi_chmap.c b/sound/hda/core/hdmi_chmap.c
index f76b5dcc6433..033e0dda9ac3 100644
--- a/sound/hda/core/hdmi_chmap.c
+++ b/sound/hda/core/hdmi_chmap.c
@@ -23,23 +23,23 @@
  * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
  */
 enum cea_speaker_placement {
-	FL  = (1 <<  0),	/* Front Left           */
-	FC  = (1 <<  1),	/* Front Center         */
-	FR  = (1 <<  2),	/* Front Right          */
-	FLC = (1 <<  3),	/* Front Left Center    */
-	FRC = (1 <<  4),	/* Front Right Center   */
-	RL  = (1 <<  5),	/* Rear Left            */
-	RC  = (1 <<  6),	/* Rear Center          */
-	RR  = (1 <<  7),	/* Rear Right           */
-	RLC = (1 <<  8),	/* Rear Left Center     */
-	RRC = (1 <<  9),	/* Rear Right Center    */
-	LFE = (1 << 10),	/* Low Frequency Effect */
-	FLW = (1 << 11),	/* Front Left Wide      */
-	FRW = (1 << 12),	/* Front Right Wide     */
-	FLH = (1 << 13),	/* Front Left High      */
-	FCH = (1 << 14),	/* Front Center High    */
-	FRH = (1 << 15),	/* Front Right High     */
-	TC  = (1 << 16),	/* Top Center           */
+	FL  = BIT(0),	/* Front Left */
+	FC  = BIT(1),	/* Front Center */
+	FR  = BIT(2),	/* Front Right */
+	FLC = BIT(3),	/* Front Left Center */
+	FRC = BIT(4),	/* Front Right Center */
+	RL  = BIT(5),	/* Rear Left */
+	RC  = BIT(6),	/* Rear Center */
+	RR  = BIT(7),	/* Rear Right */
+	RLC = BIT(8),	/* Rear Left Center */
+	RRC = BIT(9),	/* Rear Right Center */
+	LFE = BIT(10),	/* Low Frequency Effect */
+	FLW = BIT(11),	/* Front Left Wide */
+	FRW = BIT(12),	/* Front Right Wide */
+	FLH = BIT(13),	/* Front Left High */
+	FCH = BIT(14),	/* Front Center High */
+	FRH = BIT(15),	/* Front Right High */
+	TC  = BIT(16),	/* Top Center */
 };
 
 static const char * const cea_speaker_allocation_names[] = {
@@ -56,24 +56,6 @@ static const char * const cea_speaker_allocation_names[] = {
 	/* 10 */ "FCH",
 };
 
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static const int eld_speaker_allocation_bits[] = {
-	[0] = FL | FR,
-	[1] = LFE,
-	[2] = FC,
-	[3] = RL | RR,
-	[4] = RC,
-	[5] = FLC | FRC,
-	[6] = RLC | RRC,
-	/* the following are not defined in ELD yet */
-	[7] = FLW | FRW,
-	[8] = FLH | FRH,
-	[9] = TC,
-	[10] = FCH,
-};
-
 /*
  * ALSA sequence is:
  *
@@ -110,75 +92,6 @@ static int hdmi_channel_mapping[0x32][8] = {
 	[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
 };
 
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_channel_allocation().
- */
-static struct hdac_cea_channel_speaker_allocation channel_allocations[] = {
-/*			  channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-				 /* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-				 /* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-				 /* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-				 /* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-				 /* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-				 /* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
 static int hdmi_pin_set_slot_channel(struct hdac_device *codec,
 		hda_nid_t pin_nid, int asp_slot, int channel)
 {
@@ -213,32 +126,12 @@ static void hdmi_set_channel_count(struct hdac_device *codec,
  * Channel mapping routines
  */
 
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-	int i, j;
-	struct hdac_cea_channel_speaker_allocation *p;
-
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		p = channel_allocations + i;
-		p->channels = 0;
-		p->spk_mask = 0;
-		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-			if (p->speakers[j]) {
-				p->channels++;
-				p->spk_mask |= p->speakers[j];
-			}
-	}
-}
-
 static int get_channel_allocation_order(int ca)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channel_allocations[i].ca_index == ca)
+	for (i = 0; i < snd_cea_channel_allocations_count; i++) {
+		if (snd_cea_channel_allocations[i].ca_index == ca)
 			break;
 	}
 	return i;
@@ -257,61 +150,13 @@ void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen)
 }
 EXPORT_SYMBOL_GPL(snd_hdac_print_channel_allocation);
 
-/*
- * The transformation takes two steps:
- *
- *	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- *	      spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
 static int hdmi_channel_allocation_spk_alloc_blk(struct hdac_device *codec,
 				   int spk_alloc, int channels)
 {
-	int i;
-	int ca = 0;
-	int spk_mask = 0;
+	int ca;
 	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
 
-	/*
-	 * CA defaults to 0 for basic stereo audio
-	 */
-	if (channels <= 2)
-		return 0;
-
-	/*
-	 * expand ELD's speaker allocation mask
-	 *
-	 * ELD tells the speaker mask in a compact(paired) form,
-	 * expand ELD's notions to match the ones used by Audio InfoFrame.
-	 */
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (spk_alloc & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
-
-	/* search for the first working match in the CA table */
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channels == channel_allocations[i].channels &&
-		    (spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask) {
-			ca = channel_allocations[i].ca_index;
-			break;
-		}
-	}
-
-	if (!ca) {
-		/*
-		 * if there was no match, select the regular ALSA channel
-		 * allocation with the matching number of channels
-		 */
-		for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-			if (channels == channel_allocations[i].channels) {
-				ca = channel_allocations[i].ca_index;
-				break;
-			}
-		}
-	}
+	ca = snd_cea_channel_allocation(spk_alloc, channels, 0x31, true);
 
 	snd_hdac_print_channel_allocation(spk_alloc, buf, sizeof(buf));
 	dev_dbg(&codec->dev, "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
@@ -341,14 +186,14 @@ static void hdmi_std_setup_channel_mapping(struct hdac_chmap *chmap,
 				       bool non_pcm,
 				       int ca)
 {
-	const struct hdac_cea_channel_speaker_allocation *ch_alloc;
+	const struct snd_cea_channel_speaker_allocation *ch_alloc;
 	int i;
 	int err;
 	int order;
 	int non_pcm_mapping[8];
 
 	order = get_channel_allocation_order(ca);
-	ch_alloc = &channel_allocations[order];
+	ch_alloc = &snd_cea_channel_allocations[order];
 
 	if (hdmi_channel_mapping[ca][1] == 0) {
 		int hdmi_slot = 0;
@@ -438,12 +283,12 @@ static int to_cea_slot(int ordered_ca, unsigned char pos)
 	/* Add sanity check to pass klockwork check.
 	 * This should never happen.
 	 */
-	if (ordered_ca >= ARRAY_SIZE(channel_allocations))
+	if (ordered_ca >= snd_cea_channel_allocations_count)
 		return -1;
 
 	if (mask) {
 		for (i = 0; i < 8; i++) {
-			if (channel_allocations[ordered_ca].speakers[7 - i] == mask)
+			if (snd_cea_channel_allocations[ordered_ca].speakers[7 - i] == mask)
 				return i;
 		}
 	}
@@ -475,7 +320,7 @@ static int from_cea_slot(int ordered_ca, unsigned char slot)
 	if (slot >= 8)
 		return 0;
 
-	mask = channel_allocations[ordered_ca].speakers[7 - slot];
+	mask = snd_cea_channel_allocations[ordered_ca].speakers[7 - slot];
 
 	return snd_hdac_spk_to_chmap(mask);
 }
@@ -494,12 +339,12 @@ static int hdmi_manual_channel_allocation(int chs, unsigned char *map)
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if ((chs == channel_allocations[i].channels ||
-		     spks == channel_allocations[i].channels) &&
-		    (spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask)
-			return channel_allocations[i].ca_index;
+	for (i = 0; i < snd_cea_channel_allocations_count; i++) {
+		if ((chs == snd_cea_channel_allocations[i].channels ||
+		     spks == snd_cea_channel_allocations[i].channels) &&
+		    (spk_mask & snd_cea_channel_allocations[i].spk_mask) ==
+				snd_cea_channel_allocations[i].spk_mask)
+			return snd_cea_channel_allocations[i].ca_index;
 	}
 	return -1;
 }
@@ -542,8 +387,8 @@ static void hdmi_setup_fake_chmap(unsigned char *map, int ca)
 	int ordered_ca = get_channel_allocation_order(ca);
 
 	for (i = 0; i < 8; i++) {
-		if (ordered_ca < ARRAY_SIZE(channel_allocations) &&
-		    i < channel_allocations[ordered_ca].channels)
+		if (ordered_ca < snd_cea_channel_allocations_count &&
+		    i < snd_cea_channel_allocations[ordered_ca].channels)
 			map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f);
 		else
 			map[i] = 0;
@@ -574,17 +419,16 @@ int snd_hdac_get_active_channels(int ca)
 	/* Add sanity check to pass klockwork check.
 	 * This should never happen.
 	 */
-	if (ordered_ca >= ARRAY_SIZE(channel_allocations))
+	if (ordered_ca >= snd_cea_channel_allocations_count)
 		ordered_ca = 0;
 
-	return channel_allocations[ordered_ca].channels;
+	return snd_cea_channel_allocations[ordered_ca].channels;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_get_active_channels);
 
-const struct hdac_cea_channel_speaker_allocation *
-snd_hdac_get_ch_alloc_from_ca(int ca)
+const struct snd_cea_channel_speaker_allocation *snd_hdac_get_ch_alloc_from_ca(int ca)
 {
-	return &channel_allocations[get_channel_allocation_order(ca)];
+	return &snd_cea_channel_allocations[get_channel_allocation_order(ca)];
 }
 EXPORT_SYMBOL_GPL(snd_hdac_get_ch_alloc_from_ca);
 
@@ -623,8 +467,7 @@ static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol,
 }
 
 static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
-		int channels)
+		const struct snd_cea_channel_speaker_allocation *cap, int channels)
 {
 	/* If the speaker allocation matches the channel count, it is OK.*/
 	if (cap->channels != channels)
@@ -635,7 +478,7 @@ static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
 }
 
 static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
-		const struct hdac_cea_channel_speaker_allocation *cap,
+		const struct snd_cea_channel_speaker_allocation *cap,
 		unsigned int *chmap, int channels)
 {
 	int count = 0;
@@ -655,15 +498,7 @@ static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
 
 static int spk_mask_from_spk_alloc(int spk_alloc)
 {
-	int i;
-	int spk_mask = eld_speaker_allocation_bits[0];
-
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (spk_alloc & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
-
-	return spk_mask;
+	return snd_cea_spk_mask_from_alloc(spk_alloc | BIT(0));
 }
 
 static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
@@ -692,10 +527,10 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 
 	for (chs = 2; chs <= max_chs; chs++) {
 		int i;
-		const struct hdac_cea_channel_speaker_allocation *cap;
+		const struct snd_cea_channel_speaker_allocation *cap;
 
-		cap = channel_allocations;
-		for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) {
+		cap = snd_cea_channel_allocations;
+		for (i = 0; i < snd_cea_channel_allocations_count; i++, cap++) {
 			int chs_bytes = chs * 4;
 			unsigned int tlv_chmap[8];
 
@@ -842,7 +677,6 @@ void snd_hdac_register_chmap_ops(struct hdac_device *hdac,
 {
 	chmap->ops = chmap_ops;
 	chmap->hdac = hdac;
-	init_channel_allocations();
 }
 EXPORT_SYMBOL_GPL(snd_hdac_register_chmap_ops);
 

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH RFC 4/4] ALSA: x86: Use common CEA channel allocations
  2026-06-12  4:53 [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Cássio Gabriel
                   ` (2 preceding siblings ...)
  2026-06-12  4:53 ` [PATCH RFC 3/4] ALSA: hda: Use common CEA channel allocations Cássio Gabriel
@ 2026-06-12  4:53 ` Cássio Gabriel
  2026-06-12  9:13 ` [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Takashi Iwai
  4 siblings, 0 replies; 7+ messages in thread
From: Cássio Gabriel @ 2026-06-12  4:53 UTC (permalink / raw)
  To: Takashi Iwai, Thierry Reding, Jonathan Hunter, Jaroslav Kysela
  Cc: linux-sound, linux-kernel, linux-tegra, notify,
	Cássio Gabriel

Replace the Intel HDMI LPE copy of the CEA allocation table and selector
with the common PCM ELD helpers. Preserve the driver's existing limits:
only ELD speaker bits 0 through 6 participate, only CA values through
0x1f are considered, and an incompatible ELD does not use HDA's fallback.

Select SND_PCM_ELD for the new helper dependency.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
---
 sound/x86/Kconfig            |   1 +
 sound/x86/intel_hdmi_audio.c | 158 ++++++-------------------------------------
 sound/x86/intel_hdmi_audio.h |   9 ---
 3 files changed, 20 insertions(+), 148 deletions(-)

diff --git a/sound/x86/Kconfig b/sound/x86/Kconfig
index 4ffcc5e623c2..a990989a12b9 100644
--- a/sound/x86/Kconfig
+++ b/sound/x86/Kconfig
@@ -12,6 +12,7 @@ config HDMI_LPE_AUDIO
 	tristate "HDMI audio without HDAudio on Intel Atom platforms"
 	depends on DRM_I915
 	select SND_PCM
+	select SND_PCM_ELD
 	help
 	 Choose this option to support HDMI LPE Audio mode
 
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index 91dfcf47e979..4ea29c3ea6c5 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -26,6 +26,7 @@
 #include <sound/core.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/control.h>
@@ -57,72 +58,6 @@ module_param(single_port, bool, 0444);
 MODULE_PARM_DESC(single_port,
 		"Single-port mode (for compatibility)");
 
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static const int eld_speaker_allocation_bits[] = {
-	[0] = FL | FR,
-	[1] = LFE,
-	[2] = FC,
-	[3] = RL | RR,
-	[4] = RC,
-	[5] = FLC | FRC,
-	[6] = RLC | RRC,
-	/* the following are not defined in ELD yet */
-	[7] = 0,
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/*                        channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-				/* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-				/* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-				/* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-				/* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-				/* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-				/* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				/* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				/* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
 static const struct channel_map_table map_tables[] = {
 	{ SNDRV_CHMAP_FL,       0x00,   FL },
 	{ SNDRV_CHMAP_FR,       0x01,   FR },
@@ -384,68 +319,13 @@ static int had_init_audio_ctrl(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-	int i, j;
-	struct cea_channel_speaker_allocation *p;
-
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		p = channel_allocations + i;
-		p->channels = 0;
-		p->spk_mask = 0;
-		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-			if (p->speakers[j]) {
-				p->channels++;
-				p->spk_mask |= p->speakers[j];
-			}
-	}
-}
-
-/*
- * The transformation takes two steps:
- *
- *      eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- *            spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
- */
 static int had_channel_allocation(struct snd_intelhad *intelhaddata,
 				  int channels)
 {
-	int i;
-	int ca = 0;
-	int spk_mask = 0;
-
-	/*
-	 * CA defaults to 0 for basic stereo audio
-	 */
-	if (channels <= 2)
-		return 0;
-
-	/*
-	 * expand ELD's speaker allocation mask
-	 *
-	 * ELD tells the speaker mask in a compact(paired) form,
-	 * expand ELD's notions to match the ones used by Audio InfoFrame.
-	 */
-
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
+	int ca;
 
-	/* search for the first working match in the CA table */
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channels == channel_allocations[i].channels &&
-		(spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask) {
-			ca = channel_allocations[i].ca_index;
-			break;
-		}
-	}
+	ca = snd_cea_channel_allocation(intelhaddata->eld[DRM_ELD_SPEAKER] & 0x7f,
+					channels, 0x1f, false);
 
 	dev_dbg(intelhaddata->dev, "select CA 0x%x for %d\n", ca, channels);
 
@@ -487,7 +367,7 @@ static void had_build_channel_allocation_map(struct snd_intelhad *intelhaddata)
 	/*
 	 * Sink may support more than 8 channels, if eld_high has more than
 	 * one bit set. SOC supports max 8 channels.
-	 * Refer eld_speaker_allocation_bits, for sink speaker allocation
+	 * Refer the CEA ELD speaker allocation mapping for sink allocation.
 	 */
 
 	/* if 0x2F < eld < 0x4F fall back to 0x2f, else fall back to 0x4F */
@@ -505,24 +385,25 @@ static void had_build_channel_allocation_map(struct snd_intelhad *intelhaddata)
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
+	spk_mask = snd_cea_spk_mask_from_alloc(intelhaddata->eld[DRM_ELD_SPEAKER] &
+						 0x7f);
 
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (spk_mask == channel_allocations[i].spk_mask) {
-			for (c = 0; c < channel_allocations[i].channels; c++) {
-				chmap->map[c] = spk_to_chmap(
-					channel_allocations[i].speakers[
-						(MAX_SPEAKERS - 1) - c]);
-			}
-			chmap->channels = channel_allocations[i].channels;
+	for (i = 0; i < snd_cea_channel_allocations_count; i++) {
+		const struct snd_cea_channel_speaker_allocation *ca;
+
+		ca = &snd_cea_channel_allocations[i];
+		if (ca->ca_index > 0x1f)
+			continue;
+		if (spk_mask == ca->spk_mask) {
+			for (c = 0; c < ca->channels; c++)
+				chmap->map[c] =
+					spk_to_chmap(ca->speakers[MAX_SPEAKERS - 1 - c]);
+			chmap->channels = ca->channels;
 			intelhaddata->chmap->chmap = chmap;
 			break;
 		}
 	}
-	if (i >= ARRAY_SIZE(channel_allocations))
+	if (i >= snd_cea_channel_allocations_count)
 		kfree(chmap);
 }
 
@@ -1723,7 +1604,6 @@ static int __hdmi_lpe_audio_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	init_channel_allocations();
 
 	card_ctx->num_pipes = pdata->num_pipes;
 	card_ctx->num_ports = single_port ? 1 : pdata->num_ports;
diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h
index 88bf9ef2c491..21cec605a879 100644
--- a/sound/x86/intel_hdmi_audio.h
+++ b/sound/x86/intel_hdmi_audio.h
@@ -44,15 +44,6 @@ enum cea_speaker_placement {
 	LFE = (1 << 10),        /* Low Frequency Effect */
 };
 
-struct cea_channel_speaker_allocation {
-	int ca_index;
-	int speakers[8];
-
-	/* derived values, just for convenience */
-	int channels;
-	int spk_mask;
-};
-
 struct channel_map_table {
 	unsigned char map;              /* ALSA API channel map position */
 	unsigned char cea_slot;         /* CEA slot value */

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data
  2026-06-12  4:53 [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Cássio Gabriel
                   ` (3 preceding siblings ...)
  2026-06-12  4:53 ` [PATCH RFC 4/4] ALSA: x86: " Cássio Gabriel
@ 2026-06-12  9:13 ` Takashi Iwai
  2026-06-12 11:44   ` Cássio Gabriel
  4 siblings, 1 reply; 7+ messages in thread
From: Takashi Iwai @ 2026-06-12  9:13 UTC (permalink / raw)
  To: Cássio Gabriel
  Cc: Takashi Iwai, Thierry Reding, Jonathan Hunter, Jaroslav Kysela,
	linux-sound, linux-kernel, linux-tegra, notify

On Fri, 12 Jun 2026 06:53:22 +0200,
Cássio Gabriel wrote:
> 
> HDA HDMI and Intel HDMI LPE maintain separate copies of the ordered
> CEA-861 channel allocation descriptors, ELD speaker expansion, and
> allocation selection logic. The Intel implementation originated from
> the HDA code, but the copies now differ in supported allocation ranges
> and fallback behavior.
> 
> Move the common data and transformations alongside the PCM DRM ELD
> helpers, then migrate both users while preserving their established
> behavior. HDA retains the complete CA range and channel-count fallback.
> Intel HDMI LPE retains its CA 0x1f limit, ELD speaker bits 0 through 6,
> and lack of fallback for incompatible ELD data.
> 
> The descriptors and their derived channel counts and speaker masks
> become compile-time constants. This removes duplicated mutable
> initialization and provides one authoritative allocation table without
> changing the existing allocation-selection policy.
> 
> No hardware was available to test this patch series.
> 
> Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
> ---
> Cássio Gabriel (4):
>       ALSA: pcm: Add common CEA channel allocation helpers
>       ALSA: hda: Make CEA channel allocation interfaces const
>       ALSA: hda: Use common CEA channel allocations
>       ALSA: x86: Use common CEA channel allocations

This looks like a nice cleanup.  There is similar code in
sound/soc/codecs/hdmi-codec.c, too.  Can we integrate it further in
future?


thanks,

Takashi

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data
  2026-06-12  9:13 ` [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Takashi Iwai
@ 2026-06-12 11:44   ` Cássio Gabriel
  0 siblings, 0 replies; 7+ messages in thread
From: Cássio Gabriel @ 2026-06-12 11:44 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Takashi Iwai, Thierry Reding, Jonathan Hunter, Jaroslav Kysela,
	linux-sound, linux-kernel, linux-tegra, notify


[-- Attachment #1.1: Type: text/plain, Size: 1721 bytes --]

Hi, Iwai-san

On 6/12/26 06:13, Takashi Iwai wrote:
> On Fri, 12 Jun 2026 06:53:22 +0200,
> Cássio Gabriel wrote:
>>
>> HDA HDMI and Intel HDMI LPE maintain separate copies of the ordered
>> CEA-861 channel allocation descriptors, ELD speaker expansion, and
>> allocation selection logic. The Intel implementation originated from
>> the HDA code, but the copies now differ in supported allocation ranges
>> and fallback behavior.
>>
>> Move the common data and transformations alongside the PCM DRM ELD
>> helpers, then migrate both users while preserving their established
>> behavior. HDA retains the complete CA range and channel-count fallback.
>> Intel HDMI LPE retains its CA 0x1f limit, ELD speaker bits 0 through 6,
>> and lack of fallback for incompatible ELD data.
>>
>> The descriptors and their derived channel counts and speaker masks
>> become compile-time constants. This removes duplicated mutable
>> initialization and provides one authoritative allocation table without
>> changing the existing allocation-selection policy.
>>
>> No hardware was available to test this patch series.
>>
>> Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
>> ---
>> Cássio Gabriel (4):
>>       ALSA: pcm: Add common CEA channel allocation helpers
>>       ALSA: hda: Make CEA channel allocation interfaces const
>>       ALSA: hda: Use common CEA channel allocations
>>       ALSA: x86: Use common CEA channel allocations
> 
> This looks like a nice cleanup.  There is similar code in
> sound/soc/codecs/hdmi-codec.c, too.  Can we integrate it further in
> future?

Yes, absolutely, and thanks for pointing that file.
I'll work on that.

-- 
Thanks,
Cássio


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 236 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-06-12 11:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-12  4:53 [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Cássio Gabriel
2026-06-12  4:53 ` [PATCH RFC 1/4] ALSA: pcm: Add common CEA channel allocation helpers Cássio Gabriel
2026-06-12  4:53 ` [PATCH RFC 2/4] ALSA: hda: Make CEA channel allocation interfaces const Cássio Gabriel
2026-06-12  4:53 ` [PATCH RFC 3/4] ALSA: hda: Use common CEA channel allocations Cássio Gabriel
2026-06-12  4:53 ` [PATCH RFC 4/4] ALSA: x86: " Cássio Gabriel
2026-06-12  9:13 ` [PATCH RFC 0/4] ALSA: Consolidate CEA channel allocation data Takashi Iwai
2026-06-12 11:44   ` Cássio Gabriel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox