Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Generic routines and proc interface for ELD(EDID Like Data) information
0004  *
0005  * Copyright(c) 2008 Intel Corporation.
0006  * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi>
0007  *
0008  * Authors:
0009  *      Wu Fengguang <wfg@linux.intel.com>
0010  */
0011 
0012 #include <linux/init.h>
0013 #include <linux/slab.h>
0014 #include <sound/core.h>
0015 #include <asm/unaligned.h>
0016 #include <sound/hda_chmap.h>
0017 #include <sound/hda_codec.h>
0018 #include "hda_local.h"
0019 
0020 enum eld_versions {
0021     ELD_VER_CEA_861D    = 2,
0022     ELD_VER_PARTIAL     = 31,
0023 };
0024 
0025 enum cea_edid_versions {
0026     CEA_EDID_VER_NONE   = 0,
0027     CEA_EDID_VER_CEA861 = 1,
0028     CEA_EDID_VER_CEA861A    = 2,
0029     CEA_EDID_VER_CEA861BCD  = 3,
0030     CEA_EDID_VER_RESERVED   = 4,
0031 };
0032 
0033 static const char * const eld_connection_type_names[4] = {
0034     "HDMI",
0035     "DisplayPort",
0036     "2-reserved",
0037     "3-reserved"
0038 };
0039 
0040 enum cea_audio_coding_types {
0041     AUDIO_CODING_TYPE_REF_STREAM_HEADER =  0,
0042     AUDIO_CODING_TYPE_LPCM          =  1,
0043     AUDIO_CODING_TYPE_AC3           =  2,
0044     AUDIO_CODING_TYPE_MPEG1         =  3,
0045     AUDIO_CODING_TYPE_MP3           =  4,
0046     AUDIO_CODING_TYPE_MPEG2         =  5,
0047     AUDIO_CODING_TYPE_AACLC         =  6,
0048     AUDIO_CODING_TYPE_DTS           =  7,
0049     AUDIO_CODING_TYPE_ATRAC         =  8,
0050     AUDIO_CODING_TYPE_SACD          =  9,
0051     AUDIO_CODING_TYPE_EAC3          = 10,
0052     AUDIO_CODING_TYPE_DTS_HD        = 11,
0053     AUDIO_CODING_TYPE_MLP           = 12,
0054     AUDIO_CODING_TYPE_DST           = 13,
0055     AUDIO_CODING_TYPE_WMAPRO        = 14,
0056     AUDIO_CODING_TYPE_REF_CXT       = 15,
0057     /* also include valid xtypes below */
0058     AUDIO_CODING_TYPE_HE_AAC        = 15,
0059     AUDIO_CODING_TYPE_HE_AAC2       = 16,
0060     AUDIO_CODING_TYPE_MPEG_SURROUND     = 17,
0061 };
0062 
0063 enum cea_audio_coding_xtypes {
0064     AUDIO_CODING_XTYPE_HE_REF_CT        = 0,
0065     AUDIO_CODING_XTYPE_HE_AAC       = 1,
0066     AUDIO_CODING_XTYPE_HE_AAC2      = 2,
0067     AUDIO_CODING_XTYPE_MPEG_SURROUND    = 3,
0068     AUDIO_CODING_XTYPE_FIRST_RESERVED   = 4,
0069 };
0070 
0071 static const char * const cea_audio_coding_type_names[] = {
0072     /*  0 */ "undefined",
0073     /*  1 */ "LPCM",
0074     /*  2 */ "AC-3",
0075     /*  3 */ "MPEG1",
0076     /*  4 */ "MP3",
0077     /*  5 */ "MPEG2",
0078     /*  6 */ "AAC-LC",
0079     /*  7 */ "DTS",
0080     /*  8 */ "ATRAC",
0081     /*  9 */ "DSD (One Bit Audio)",
0082     /* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)",
0083     /* 11 */ "DTS-HD",
0084     /* 12 */ "MLP (Dolby TrueHD)",
0085     /* 13 */ "DST",
0086     /* 14 */ "WMAPro",
0087     /* 15 */ "HE-AAC",
0088     /* 16 */ "HE-AACv2",
0089     /* 17 */ "MPEG Surround",
0090 };
0091 
0092 /*
0093  * The following two lists are shared between
0094  *  - HDMI audio InfoFrame (source to sink)
0095  *  - CEA E-EDID Extension (sink to source)
0096  */
0097 
0098 /*
0099  * SS1:SS0 index => sample size
0100  */
0101 static const int cea_sample_sizes[4] = {
0102     0,          /* 0: Refer to Stream Header */
0103     AC_SUPPCM_BITS_16,  /* 1: 16 bits */
0104     AC_SUPPCM_BITS_20,  /* 2: 20 bits */
0105     AC_SUPPCM_BITS_24,  /* 3: 24 bits */
0106 };
0107 
0108 /*
0109  * SF2:SF1:SF0 index => sampling frequency
0110  */
0111 static const int cea_sampling_frequencies[8] = {
0112     0,          /* 0: Refer to Stream Header */
0113     SNDRV_PCM_RATE_32000,   /* 1:  32000Hz */
0114     SNDRV_PCM_RATE_44100,   /* 2:  44100Hz */
0115     SNDRV_PCM_RATE_48000,   /* 3:  48000Hz */
0116     SNDRV_PCM_RATE_88200,   /* 4:  88200Hz */
0117     SNDRV_PCM_RATE_96000,   /* 5:  96000Hz */
0118     SNDRV_PCM_RATE_176400,  /* 6: 176400Hz */
0119     SNDRV_PCM_RATE_192000,  /* 7: 192000Hz */
0120 };
0121 
0122 static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
0123                     int byte_index)
0124 {
0125     unsigned int val;
0126 
0127     val = snd_hda_codec_read(codec, nid, 0,
0128                     AC_VERB_GET_HDMI_ELDD, byte_index);
0129 #ifdef BE_PARANOID
0130     codec_info(codec, "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
0131 #endif
0132     return val;
0133 }
0134 
0135 #define GRAB_BITS(buf, byte, lowbit, bits)      \
0136 ({                          \
0137     BUILD_BUG_ON(lowbit > 7);           \
0138     BUILD_BUG_ON(bits > 8);             \
0139     BUILD_BUG_ON(bits <= 0);            \
0140                             \
0141     (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1);  \
0142 })
0143 
0144 static void hdmi_update_short_audio_desc(struct hda_codec *codec,
0145                      struct cea_sad *a,
0146                      const unsigned char *buf)
0147 {
0148     int i;
0149     int val;
0150 
0151     val = GRAB_BITS(buf, 1, 0, 7);
0152     a->rates = 0;
0153     for (i = 0; i < 7; i++)
0154         if (val & (1 << i))
0155             a->rates |= cea_sampling_frequencies[i + 1];
0156 
0157     a->channels = GRAB_BITS(buf, 0, 0, 3);
0158     a->channels++;
0159 
0160     a->sample_bits = 0;
0161     a->max_bitrate = 0;
0162 
0163     a->format = GRAB_BITS(buf, 0, 3, 4);
0164     switch (a->format) {
0165     case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
0166         codec_info(codec, "HDMI: audio coding type 0 not expected\n");
0167         break;
0168 
0169     case AUDIO_CODING_TYPE_LPCM:
0170         val = GRAB_BITS(buf, 2, 0, 3);
0171         for (i = 0; i < 3; i++)
0172             if (val & (1 << i))
0173                 a->sample_bits |= cea_sample_sizes[i + 1];
0174         break;
0175 
0176     case AUDIO_CODING_TYPE_AC3:
0177     case AUDIO_CODING_TYPE_MPEG1:
0178     case AUDIO_CODING_TYPE_MP3:
0179     case AUDIO_CODING_TYPE_MPEG2:
0180     case AUDIO_CODING_TYPE_AACLC:
0181     case AUDIO_CODING_TYPE_DTS:
0182     case AUDIO_CODING_TYPE_ATRAC:
0183         a->max_bitrate = GRAB_BITS(buf, 2, 0, 8);
0184         a->max_bitrate *= 8000;
0185         break;
0186 
0187     case AUDIO_CODING_TYPE_SACD:
0188         break;
0189 
0190     case AUDIO_CODING_TYPE_EAC3:
0191         break;
0192 
0193     case AUDIO_CODING_TYPE_DTS_HD:
0194         break;
0195 
0196     case AUDIO_CODING_TYPE_MLP:
0197         break;
0198 
0199     case AUDIO_CODING_TYPE_DST:
0200         break;
0201 
0202     case AUDIO_CODING_TYPE_WMAPRO:
0203         a->profile = GRAB_BITS(buf, 2, 0, 3);
0204         break;
0205 
0206     case AUDIO_CODING_TYPE_REF_CXT:
0207         a->format = GRAB_BITS(buf, 2, 3, 5);
0208         if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
0209             a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
0210             codec_info(codec,
0211                    "HDMI: audio coding xtype %d not expected\n",
0212                    a->format);
0213             a->format = 0;
0214         } else
0215             a->format += AUDIO_CODING_TYPE_HE_AAC -
0216                      AUDIO_CODING_XTYPE_HE_AAC;
0217         break;
0218     }
0219 }
0220 
0221 /*
0222  * Be careful, ELD buf could be totally rubbish!
0223  */
0224 int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
0225               const unsigned char *buf, int size)
0226 {
0227     int mnl;
0228     int i;
0229 
0230     memset(e, 0, sizeof(*e));
0231     e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
0232     if (e->eld_ver != ELD_VER_CEA_861D &&
0233         e->eld_ver != ELD_VER_PARTIAL) {
0234         codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver);
0235         goto out_fail;
0236     }
0237 
0238     e->baseline_len = GRAB_BITS(buf, 2, 0, 8);
0239     mnl     = GRAB_BITS(buf, 4, 0, 5);
0240     e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3);
0241 
0242     e->support_hdcp = GRAB_BITS(buf, 5, 0, 1);
0243     e->support_ai   = GRAB_BITS(buf, 5, 1, 1);
0244     e->conn_type    = GRAB_BITS(buf, 5, 2, 2);
0245     e->sad_count    = GRAB_BITS(buf, 5, 4, 4);
0246 
0247     e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2;
0248     e->spk_alloc    = GRAB_BITS(buf, 7, 0, 7);
0249 
0250     e->port_id    = get_unaligned_le64(buf + 8);
0251 
0252     /* not specified, but the spec's tendency is little endian */
0253     e->manufacture_id = get_unaligned_le16(buf + 16);
0254     e->product_id     = get_unaligned_le16(buf + 18);
0255 
0256     if (mnl > ELD_MAX_MNL) {
0257         codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl);
0258         goto out_fail;
0259     } else if (ELD_FIXED_BYTES + mnl > size) {
0260         codec_info(codec, "HDMI: out of range MNL %d\n", mnl);
0261         goto out_fail;
0262     } else
0263         strscpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
0264 
0265     for (i = 0; i < e->sad_count; i++) {
0266         if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
0267             codec_info(codec, "HDMI: out of range SAD %d\n", i);
0268             goto out_fail;
0269         }
0270         hdmi_update_short_audio_desc(codec, e->sad + i,
0271                     buf + ELD_FIXED_BYTES + mnl + 3 * i);
0272     }
0273 
0274     /*
0275      * HDMI sink's ELD info cannot always be retrieved for now, e.g.
0276      * in console or for audio devices. Assume the highest speakers
0277      * configuration, to _not_ prohibit multi-channel audio playback.
0278      */
0279     if (!e->spk_alloc)
0280         e->spk_alloc = 0xffff;
0281 
0282     return 0;
0283 
0284 out_fail:
0285     return -EINVAL;
0286 }
0287 
0288 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
0289 {
0290     return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
0291                          AC_DIPSIZE_ELD_BUF);
0292 }
0293 
0294 int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
0295              unsigned char *buf, int *eld_size)
0296 {
0297     int i;
0298     int ret = 0;
0299     int size;
0300 
0301     /*
0302      * ELD size is initialized to zero in caller function. If no errors and
0303      * ELD is valid, actual eld_size is assigned.
0304      */
0305 
0306     size = snd_hdmi_get_eld_size(codec, nid);
0307     if (size == 0) {
0308         /* wfg: workaround for ASUS P5E-VM HDMI board */
0309         codec_info(codec, "HDMI: ELD buf size is 0, force 128\n");
0310         size = 128;
0311     }
0312     if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
0313         codec_info(codec, "HDMI: invalid ELD buf size %d\n", size);
0314         return -ERANGE;
0315     }
0316 
0317     /* set ELD buffer */
0318     for (i = 0; i < size; i++) {
0319         unsigned int val = hdmi_get_eld_data(codec, nid, i);
0320         /*
0321          * Graphics driver might be writing to ELD buffer right now.
0322          * Just abort. The caller will repoll after a while.
0323          */
0324         if (!(val & AC_ELDD_ELD_VALID)) {
0325             codec_info(codec, "HDMI: invalid ELD data byte %d\n", i);
0326             ret = -EINVAL;
0327             goto error;
0328         }
0329         val &= AC_ELDD_ELD_DATA;
0330         /*
0331          * The first byte cannot be zero. This can happen on some DVI
0332          * connections. Some Intel chips may also need some 250ms delay
0333          * to return non-zero ELD data, even when the graphics driver
0334          * correctly writes ELD content before setting ELD_valid bit.
0335          */
0336         if (!val && !i) {
0337             codec_dbg(codec, "HDMI: 0 ELD data\n");
0338             ret = -EINVAL;
0339             goto error;
0340         }
0341         buf[i] = val;
0342     }
0343 
0344     *eld_size = size;
0345 error:
0346     return ret;
0347 }
0348 
0349 /*
0350  * SNDRV_PCM_RATE_* and AC_PAR_PCM values don't match, print correct rates with
0351  * hdmi-specific routine.
0352  */
0353 static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
0354 {
0355     static const unsigned int alsa_rates[] = {
0356         5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
0357         88200, 96000, 176400, 192000, 384000
0358     };
0359     int i, j;
0360 
0361     for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
0362         if (pcm & (1 << i))
0363             j += scnprintf(buf + j, buflen - j,  " %d",
0364                 alsa_rates[i]);
0365 
0366     buf[j] = '\0'; /* necessary when j == 0 */
0367 }
0368 
0369 #define SND_PRINT_RATES_ADVISED_BUFSIZE 80
0370 
0371 static void hdmi_show_short_audio_desc(struct hda_codec *codec,
0372                        struct cea_sad *a)
0373 {
0374     char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
0375     char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
0376 
0377     if (!a->format)
0378         return;
0379 
0380     hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
0381 
0382     if (a->format == AUDIO_CODING_TYPE_LPCM)
0383         snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8);
0384     else if (a->max_bitrate)
0385         snprintf(buf2, sizeof(buf2),
0386                 ", max bitrate = %d", a->max_bitrate);
0387     else
0388         buf2[0] = '\0';
0389 
0390     codec_dbg(codec,
0391           "HDMI: supports coding type %s: channels = %d, rates =%s%s\n",
0392           cea_audio_coding_type_names[a->format],
0393           a->channels, buf, buf2);
0394 }
0395 
0396 void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e)
0397 {
0398     int i;
0399 
0400     codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n",
0401             e->monitor_name,
0402             eld_connection_type_names[e->conn_type]);
0403 
0404     if (e->spk_alloc) {
0405         char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
0406         snd_hdac_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
0407         codec_dbg(codec, "HDMI: available speakers:%s\n", buf);
0408     }
0409 
0410     for (i = 0; i < e->sad_count; i++)
0411         hdmi_show_short_audio_desc(codec, e->sad + i);
0412 }
0413 
0414 #ifdef CONFIG_SND_PROC_FS
0415 
0416 static void hdmi_print_sad_info(int i, struct cea_sad *a,
0417                 struct snd_info_buffer *buffer)
0418 {
0419     char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
0420 
0421     snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
0422             i, a->format, cea_audio_coding_type_names[a->format]);
0423     snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
0424 
0425     hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
0426     snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
0427 
0428     if (a->format == AUDIO_CODING_TYPE_LPCM) {
0429         snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf));
0430         snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n",
0431                             i, a->sample_bits, buf);
0432     }
0433 
0434     if (a->max_bitrate)
0435         snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
0436                             i, a->max_bitrate);
0437 
0438     if (a->profile)
0439         snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
0440 }
0441 
0442 void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
0443                  struct snd_info_buffer *buffer)
0444 {
0445     struct parsed_hdmi_eld *e = &eld->info;
0446     char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
0447     int i;
0448     static const char * const eld_version_names[32] = {
0449         "reserved",
0450         "reserved",
0451         "CEA-861D or below",
0452         [3 ... 30] = "reserved",
0453         [31] = "partial"
0454     };
0455     static const char * const cea_edid_version_names[8] = {
0456         "no CEA EDID Timing Extension block present",
0457         "CEA-861",
0458         "CEA-861-A",
0459         "CEA-861-B, C or D",
0460         [4 ... 7] = "reserved"
0461     };
0462 
0463     snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present);
0464     snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid);
0465     if (!eld->eld_valid)
0466         return;
0467     snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
0468     snd_iprintf(buffer, "connection_type\t\t%s\n",
0469                 eld_connection_type_names[e->conn_type]);
0470     snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
0471                     eld_version_names[e->eld_ver]);
0472     snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver,
0473                 cea_edid_version_names[e->cea_edid_ver]);
0474     snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id);
0475     snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id);
0476     snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id);
0477     snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp);
0478     snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai);
0479     snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
0480 
0481     snd_hdac_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
0482     snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf);
0483 
0484     snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
0485 
0486     for (i = 0; i < e->sad_count; i++)
0487         hdmi_print_sad_info(i, e->sad + i, buffer);
0488 }
0489 
0490 void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
0491                  struct snd_info_buffer *buffer)
0492 {
0493     struct parsed_hdmi_eld *e = &eld->info;
0494     char line[64];
0495     char name[64];
0496     char *sname;
0497     long long val;
0498     unsigned int n;
0499 
0500     while (!snd_info_get_line(buffer, line, sizeof(line))) {
0501         if (sscanf(line, "%s %llx", name, &val) != 2)
0502             continue;
0503         /*
0504          * We don't allow modification to these fields:
0505          *  monitor_name manufacture_id product_id
0506          *  eld_version edid_version
0507          */
0508         if (!strcmp(name, "monitor_present"))
0509             eld->monitor_present = val;
0510         else if (!strcmp(name, "eld_valid"))
0511             eld->eld_valid = val;
0512         else if (!strcmp(name, "connection_type"))
0513             e->conn_type = val;
0514         else if (!strcmp(name, "port_id"))
0515             e->port_id = val;
0516         else if (!strcmp(name, "support_hdcp"))
0517             e->support_hdcp = val;
0518         else if (!strcmp(name, "support_ai"))
0519             e->support_ai = val;
0520         else if (!strcmp(name, "audio_sync_delay"))
0521             e->aud_synch_delay = val;
0522         else if (!strcmp(name, "speakers"))
0523             e->spk_alloc = val;
0524         else if (!strcmp(name, "sad_count"))
0525             e->sad_count = val;
0526         else if (!strncmp(name, "sad", 3)) {
0527             sname = name + 4;
0528             n = name[3] - '0';
0529             if (name[4] >= '0' && name[4] <= '9') {
0530                 sname++;
0531                 n = 10 * n + name[4] - '0';
0532             }
0533             if (n >= ELD_MAX_SAD)
0534                 continue;
0535             if (!strcmp(sname, "_coding_type"))
0536                 e->sad[n].format = val;
0537             else if (!strcmp(sname, "_channels"))
0538                 e->sad[n].channels = val;
0539             else if (!strcmp(sname, "_rates"))
0540                 e->sad[n].rates = val;
0541             else if (!strcmp(sname, "_bits"))
0542                 e->sad[n].sample_bits = val;
0543             else if (!strcmp(sname, "_max_bitrate"))
0544                 e->sad[n].max_bitrate = val;
0545             else if (!strcmp(sname, "_profile"))
0546                 e->sad[n].profile = val;
0547             if (n >= e->sad_count)
0548                 e->sad_count = n + 1;
0549         }
0550     }
0551 }
0552 #endif /* CONFIG_SND_PROC_FS */
0553 
0554 /* update PCM info based on ELD */
0555 void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
0556                   struct hda_pcm_stream *hinfo)
0557 {
0558     u32 rates;
0559     u64 formats;
0560     unsigned int maxbps;
0561     unsigned int channels_max;
0562     int i;
0563 
0564     /* assume basic audio support (the basic audio flag is not in ELD;
0565      * however, all audio capable sinks are required to support basic
0566      * audio) */
0567     rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
0568         SNDRV_PCM_RATE_48000;
0569     formats = SNDRV_PCM_FMTBIT_S16_LE;
0570     maxbps = 16;
0571     channels_max = 2;
0572     for (i = 0; i < e->sad_count; i++) {
0573         struct cea_sad *a = &e->sad[i];
0574         rates |= a->rates;
0575         if (a->channels > channels_max)
0576             channels_max = a->channels;
0577         if (a->format == AUDIO_CODING_TYPE_LPCM) {
0578             if (a->sample_bits & AC_SUPPCM_BITS_20) {
0579                 formats |= SNDRV_PCM_FMTBIT_S32_LE;
0580                 if (maxbps < 20)
0581                     maxbps = 20;
0582             }
0583             if (a->sample_bits & AC_SUPPCM_BITS_24) {
0584                 formats |= SNDRV_PCM_FMTBIT_S32_LE;
0585                 if (maxbps < 24)
0586                     maxbps = 24;
0587             }
0588         }
0589     }
0590 
0591     /* restrict the parameters by the values the codec provides */
0592     hinfo->rates &= rates;
0593     hinfo->formats &= formats;
0594     hinfo->maxbps = min(hinfo->maxbps, maxbps);
0595     hinfo->channels_max = min(hinfo->channels_max, channels_max);
0596 }
0597 
0598 
0599 /* ATI/AMD specific stuff (ELD emulation) */
0600 
0601 #define ATI_VERB_SET_AUDIO_DESCRIPTOR   0x776
0602 #define ATI_VERB_SET_SINK_INFO_INDEX    0x780
0603 #define ATI_VERB_GET_SPEAKER_ALLOCATION 0xf70
0604 #define ATI_VERB_GET_AUDIO_DESCRIPTOR   0xf76
0605 #define ATI_VERB_GET_AUDIO_VIDEO_DELAY  0xf7b
0606 #define ATI_VERB_GET_SINK_INFO_INDEX    0xf80
0607 #define ATI_VERB_GET_SINK_INFO_DATA 0xf81
0608 
0609 #define ATI_SPKALLOC_SPKALLOC       0x007f
0610 #define ATI_SPKALLOC_TYPE_HDMI      0x0100
0611 #define ATI_SPKALLOC_TYPE_DISPLAYPORT   0x0200
0612 
0613 /* first three bytes are just standard SAD */
0614 #define ATI_AUDIODESC_CHANNELS      0x00000007
0615 #define ATI_AUDIODESC_RATES     0x0000ff00
0616 #define ATI_AUDIODESC_LPCM_STEREO_RATES 0xff000000
0617 
0618 /* in standard HDMI VSDB format */
0619 #define ATI_DELAY_VIDEO_LATENCY     0x000000ff
0620 #define ATI_DELAY_AUDIO_LATENCY     0x0000ff00
0621 
0622 enum ati_sink_info_idx {
0623     ATI_INFO_IDX_MANUFACTURER_ID    = 0,
0624     ATI_INFO_IDX_PRODUCT_ID     = 1,
0625     ATI_INFO_IDX_SINK_DESC_LEN  = 2,
0626     ATI_INFO_IDX_PORT_ID_LOW    = 3,
0627     ATI_INFO_IDX_PORT_ID_HIGH   = 4,
0628     ATI_INFO_IDX_SINK_DESC_FIRST    = 5,
0629     ATI_INFO_IDX_SINK_DESC_LAST = 22, /* max len 18 bytes */
0630 };
0631 
0632 int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
0633              unsigned char *buf, int *eld_size, bool rev3_or_later)
0634 {
0635     int spkalloc, ati_sad, aud_synch;
0636     int sink_desc_len = 0;
0637     int pos, i;
0638 
0639     /* ATI/AMD does not have ELD, emulate it */
0640 
0641     spkalloc = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SPEAKER_ALLOCATION, 0);
0642 
0643     if (spkalloc <= 0) {
0644         codec_info(codec, "HDMI ATI/AMD: no speaker allocation for ELD\n");
0645         return -EINVAL;
0646     }
0647 
0648     memset(buf, 0, ELD_FIXED_BYTES + ELD_MAX_MNL + ELD_MAX_SAD * 3);
0649 
0650     /* version */
0651     buf[0] = ELD_VER_CEA_861D << 3;
0652 
0653     /* speaker allocation from EDID */
0654     buf[7] = spkalloc & ATI_SPKALLOC_SPKALLOC;
0655 
0656     /* is DisplayPort? */
0657     if (spkalloc & ATI_SPKALLOC_TYPE_DISPLAYPORT)
0658         buf[5] |= 0x04;
0659 
0660     pos = ELD_FIXED_BYTES;
0661 
0662     if (rev3_or_later) {
0663         int sink_info;
0664 
0665         snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_LOW);
0666         sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
0667         put_unaligned_le32(sink_info, buf + 8);
0668 
0669         snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_HIGH);
0670         sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
0671         put_unaligned_le32(sink_info, buf + 12);
0672 
0673         snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_MANUFACTURER_ID);
0674         sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
0675         put_unaligned_le16(sink_info, buf + 16);
0676 
0677         snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PRODUCT_ID);
0678         sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
0679         put_unaligned_le16(sink_info, buf + 18);
0680 
0681         snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_LEN);
0682         sink_desc_len = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
0683 
0684         if (sink_desc_len > ELD_MAX_MNL) {
0685             codec_info(codec, "HDMI ATI/AMD: Truncating HDMI sink description with length %d\n",
0686                    sink_desc_len);
0687             sink_desc_len = ELD_MAX_MNL;
0688         }
0689 
0690         buf[4] |= sink_desc_len;
0691 
0692         for (i = 0; i < sink_desc_len; i++) {
0693             snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_FIRST + i);
0694             buf[pos++] = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
0695         }
0696     }
0697 
0698     for (i = AUDIO_CODING_TYPE_LPCM; i <= AUDIO_CODING_TYPE_WMAPRO; i++) {
0699         if (i == AUDIO_CODING_TYPE_SACD || i == AUDIO_CODING_TYPE_DST)
0700             continue; /* not handled by ATI/AMD */
0701 
0702         snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_AUDIO_DESCRIPTOR, i << 3);
0703         ati_sad = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_DESCRIPTOR, 0);
0704 
0705         if (ati_sad <= 0)
0706             continue;
0707 
0708         if (ati_sad & ATI_AUDIODESC_RATES) {
0709             /* format is supported, copy SAD as-is */
0710             buf[pos++] = (ati_sad & 0x0000ff) >> 0;
0711             buf[pos++] = (ati_sad & 0x00ff00) >> 8;
0712             buf[pos++] = (ati_sad & 0xff0000) >> 16;
0713         }
0714 
0715         if (i == AUDIO_CODING_TYPE_LPCM
0716             && (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES)
0717             && (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES) >> 16 != (ati_sad & ATI_AUDIODESC_RATES)) {
0718             /* for PCM there is a separate stereo rate mask */
0719             buf[pos++] = ((ati_sad & 0x000000ff) & ~ATI_AUDIODESC_CHANNELS) | 0x1;
0720             /* rates from the extra byte */
0721             buf[pos++] = (ati_sad & 0xff000000) >> 24;
0722             buf[pos++] = (ati_sad & 0x00ff0000) >> 16;
0723         }
0724     }
0725 
0726     if (pos == ELD_FIXED_BYTES + sink_desc_len) {
0727         codec_info(codec, "HDMI ATI/AMD: no audio descriptors for ELD\n");
0728         return -EINVAL;
0729     }
0730 
0731     /*
0732      * HDMI VSDB latency format:
0733      * separately for both audio and video:
0734      *  0          field not valid or unknown latency
0735      *  [1..251]   msecs = (x-1)*2  (max 500ms with x = 251 = 0xfb)
0736      *  255        audio/video not supported
0737      *
0738      * HDA latency format:
0739      * single value indicating video latency relative to audio:
0740      *  0          unknown or 0ms
0741      *  [1..250]   msecs = x*2  (max 500ms with x = 250 = 0xfa)
0742      *  [251..255] reserved
0743      */
0744     aud_synch = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_VIDEO_DELAY, 0);
0745     if ((aud_synch & ATI_DELAY_VIDEO_LATENCY) && (aud_synch & ATI_DELAY_AUDIO_LATENCY)) {
0746         int video_latency_hdmi = (aud_synch & ATI_DELAY_VIDEO_LATENCY);
0747         int audio_latency_hdmi = (aud_synch & ATI_DELAY_AUDIO_LATENCY) >> 8;
0748 
0749         if (video_latency_hdmi <= 0xfb && audio_latency_hdmi <= 0xfb &&
0750             video_latency_hdmi > audio_latency_hdmi)
0751             buf[6] = video_latency_hdmi - audio_latency_hdmi;
0752         /* else unknown/invalid or 0ms or video ahead of audio, so use zero */
0753     }
0754 
0755     /* SAD count */
0756     buf[5] |= ((pos - ELD_FIXED_BYTES - sink_desc_len) / 3) << 4;
0757 
0758     /* Baseline ELD block length is 4-byte aligned */
0759     pos = round_up(pos, 4);
0760 
0761     /* Baseline ELD length (4-byte header is not counted in) */
0762     buf[2] = (pos - 4) / 4;
0763 
0764     *eld_size = pos;
0765 
0766     return 0;
0767 }