[STLinux Kernel] [PATCH v2 4/4] ASoC: hdmi-codec: add channel mapping control
Arnaud Pouliquen
arnaud.pouliquen at st.com
Mon Dec 19 11:07:03 UTC 2016
I detected 2 issues in this version, details below.
V3 is following.
Sorry for the inconvenience...
Regards
Arnaud
On 12/14/2016 04:16 PM, Arnaud Pouliquen wrote:
> +static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc)
> +{
> + int i;
> + const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {
> + [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR,
> + [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC,
> + };
> + unsigned long spk_mask;
Missing initialization that generates warning during compilation
> +
> + for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) {
> + if (spk_alloc & (1 << i))
> + spk_mask |= hdmi_codec_eld_spk_alloc_bits[i];
> + }
> +
> + return spk_mask;
> +}
> +
> +/* From speaker bit mask to ALSA API channel position */
> +static int snd_hdac_spk_to_chmap(int spk)
> +{
> + const struct hdmi_codec_channel_map_table *t = hdmi_codec_map_table;
> +
> + for (; t->map; t++) {
> + if (t->spk_mask == spk)
> + return t->map;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * hdmi_codec_cea_init_channel_alloc:
> + * Compute derived values in hdmi_codec_channel_alloc[].
> + * spk_na_mask is used to store unused channels in mid of the channel
> + * allocations. These particular channels are then considered as active channels
> + * For instance:
> + * CA_ID 0x02: CA = (FL, FR, 0, FC) => spk_na_mask = 0x04, channels = 4
> + * CA_ID 0x04: CA = (FL, FR, 0, 0, RC) => spk_na_mask = 0x03C, channels = 5
> + */
> +static void hdmi_codec_cea_init_channel_alloc(void)
> +{
> + int i, j, k, last;
> + struct hdmi_codec_cea_spk_alloc *p;
> +
> + /* Test if not already done by another instance */
> + if (hdmi_codec_channel_alloc[0].channels)
> + return;
> +
> + for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++) {
> + p = hdmi_codec_channel_alloc + i;
> + p->spks_mask = 0;
> + p->spk_na_mask = 0;
> + last = HDMI_MAX_SPEAKERS;
> + for (j = 0, k = 7; j < HDMI_MAX_SPEAKERS; j++, k--) {
> + if (p->speakers[j]) {
> + p->spks_mask |= p->speakers[j];
> + if (last == HDMI_MAX_SPEAKERS)
> + last = j;
> + } else if (last != HDMI_MAX_SPEAKERS) {
> + p->spk_na_mask |= 1 << k;
> + }
> + }
> + p->channels = 8 - last;
> + }
> +}
> +
> +static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp,
> + unsigned char channels)
> +{
> + int i;
> + u8 spk_alloc;
> + unsigned long spk_mask;
> + struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc;
> +
> + spk_alloc = drm_eld_get_spk_alloc(hcp->eld);
> + spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
> +
> + for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) {
> + if (cap->channels != channels)
> + continue;
> + if (!(cap->spks_mask == (spk_mask & cap->spks_mask)))
> + continue;
> + return i;
> + }
> +
If HDMI cable not plugged, ELD is empty. In this case this function
returns an error. For backward compatible, it should not return an error
but a default allocation that should be stereo.
> + return -EINVAL;
> +}
> +
> +static void hdmi_cea_alloc_to_tlv_spks(struct hdmi_codec_cea_spk_alloc *cap,
> + unsigned char *chmap)
> +{
> + int count = 0;
> + int c, spk;
> +
> + /* Detect unused channels in cea caps, tag them as N/A channel in TLV */
> + for (c = 0; c < HDMI_MAX_SPEAKERS; c++) {
> + spk = cap->speakers[7 - c];
> + if (cap->spk_na_mask & BIT(c))
> + chmap[count++] = SNDRV_CHMAP_NA;
> + else
> + chmap[count++] = snd_hdac_spk_to_chmap(spk);
> + }
> +}
> +
> +static void hdmi_cea_alloc_to_tlv_chmap(struct hdmi_codec_priv *hcp,
> + struct hdmi_codec_cea_spk_alloc *cap)
> +{
> + unsigned int chs, count = 0;
> + struct snd_pcm_chmap *info = hcp->chmap_info;
> + struct snd_pcm_chmap_elem *chmap = info->chmap;
> + unsigned long max_chs = info->max_channels;
> + int num_ca = ARRAY_SIZE(hdmi_codec_channel_alloc);
> + int spk_alloc, spk_mask;
> +
> + spk_alloc = drm_eld_get_spk_alloc(hcp->eld);
> + spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
> +
> + for (chs = 2; chs <= max_chs; chs++) {
> + int i;
> + struct hdmi_codec_cea_spk_alloc *cap;
> +
> + cap = hdmi_codec_channel_alloc;
> + for (i = 0; i < num_ca; i++, cap++) {
> + if (cap->channels != chs)
> + continue;
> +
> + if (!(cap->spks_mask == (spk_mask & cap->spks_mask)))
> + continue;
> +
> + chmap[count].channels = cap->channels;
> + hdmi_cea_alloc_to_tlv_spks(cap, chmap[count].map);
> + count++;
> + }
> + }
> +
> + /* Force last one to 0 to indicate end of available allocations */
> + chmap[count].channels = 0;
> +}
> +
More information about the dri-devel
mailing list