1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Generic routines and proc interface for ELD(EDID Like Data) information 4 * 5 * Copyright(c) 2008 Intel Corporation. 6 * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi> 7 * 8 * Authors: 9 * Wu Fengguang <wfg@linux.intel.com> 10 */ 11 12 #include <linux/init.h> 13 #include <linux/slab.h> 14 #include <sound/core.h> 15 #include <sound/hda_chmap.h> 16 #include <sound/hda_codec.h> 17 #include "hda_local.h" 18 19 enum cea_edid_versions { 20 CEA_EDID_VER_NONE = 0, 21 CEA_EDID_VER_CEA861 = 1, 22 CEA_EDID_VER_CEA861A = 2, 23 CEA_EDID_VER_CEA861BCD = 3, 24 CEA_EDID_VER_RESERVED = 4, 25 }; 26 27 /* 28 * The following two lists are shared between 29 * - HDMI audio InfoFrame (source to sink) 30 * - CEA E-EDID Extension (sink to source) 31 */ 32 33 static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, 34 int byte_index) 35 { 36 unsigned int val; 37 38 val = snd_hda_codec_read(codec, nid, 0, 39 AC_VERB_GET_HDMI_ELDD, byte_index); 40 #ifdef BE_PARANOID 41 codec_info(codec, "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); 42 #endif 43 return val; 44 } 45 46 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) 47 { 48 return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, 49 AC_DIPSIZE_ELD_BUF); 50 } 51 52 int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, 53 unsigned char *buf, int *eld_size) 54 { 55 int i; 56 int ret = 0; 57 int size; 58 59 /* 60 * ELD size is initialized to zero in caller function. If no errors and 61 * ELD is valid, actual eld_size is assigned. 62 */ 63 64 size = snd_hdmi_get_eld_size(codec, nid); 65 if (size == 0) { 66 /* wfg: workaround for ASUS P5E-VM HDMI board */ 67 codec_info(codec, "HDMI: ELD buf size is 0, force 128\n"); 68 size = 128; 69 } 70 if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) { 71 codec_info(codec, "HDMI: invalid ELD buf size %d\n", size); 72 return -ERANGE; 73 } 74 75 /* set ELD buffer */ 76 for (i = 0; i < size; i++) { 77 unsigned int val = hdmi_get_eld_data(codec, nid, i); 78 /* 79 * Graphics driver might be writing to ELD buffer right now. 80 * Just abort. The caller will repoll after a while. 81 */ 82 if (!(val & AC_ELDD_ELD_VALID)) { 83 codec_info(codec, "HDMI: invalid ELD data byte %d\n", i); 84 ret = -EINVAL; 85 goto error; 86 } 87 val &= AC_ELDD_ELD_DATA; 88 /* 89 * The first byte cannot be zero. This can happen on some DVI 90 * connections. Some Intel chips may also need some 250ms delay 91 * to return non-zero ELD data, even when the graphics driver 92 * correctly writes ELD content before setting ELD_valid bit. 93 */ 94 if (!val && !i) { 95 codec_dbg(codec, "HDMI: 0 ELD data\n"); 96 ret = -EINVAL; 97 goto error; 98 } 99 buf[i] = val; 100 } 101 102 *eld_size = size; 103 error: 104 return ret; 105 } 106 107 #ifdef CONFIG_SND_PROC_FS 108 void snd_hdmi_print_eld_info(struct hdmi_eld *eld, 109 struct snd_info_buffer *buffer, 110 hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid) 111 { 112 snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present); 113 snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid); 114 snd_iprintf(buffer, "codec_pin_nid\t\t0x%x\n", pin_nid); 115 snd_iprintf(buffer, "codec_dev_id\t\t0x%x\n", dev_id); 116 snd_iprintf(buffer, "codec_cvt_nid\t\t0x%x\n", cvt_nid); 117 118 if (!eld->eld_valid) 119 return; 120 121 snd_print_eld_info(&eld->info, buffer); 122 } 123 124 void snd_hdmi_write_eld_info(struct hdmi_eld *eld, 125 struct snd_info_buffer *buffer) 126 { 127 struct snd_parsed_hdmi_eld *e = &eld->info; 128 char line[64]; 129 char name[64]; 130 char *sname; 131 long long val; 132 unsigned int n; 133 134 while (!snd_info_get_line(buffer, line, sizeof(line))) { 135 if (sscanf(line, "%s %llx", name, &val) != 2) 136 continue; 137 /* 138 * We don't allow modification to these fields: 139 * monitor_name manufacture_id product_id 140 * eld_version edid_version 141 */ 142 if (!strcmp(name, "monitor_present")) 143 eld->monitor_present = val; 144 else if (!strcmp(name, "eld_valid")) 145 eld->eld_valid = val; 146 else if (!strcmp(name, "connection_type")) 147 e->conn_type = val; 148 else if (!strcmp(name, "port_id")) 149 e->port_id = val; 150 else if (!strcmp(name, "support_hdcp")) 151 e->support_hdcp = val; 152 else if (!strcmp(name, "support_ai")) 153 e->support_ai = val; 154 else if (!strcmp(name, "audio_sync_delay")) 155 e->aud_synch_delay = val; 156 else if (!strcmp(name, "speakers")) 157 e->spk_alloc = val; 158 else if (!strcmp(name, "sad_count")) 159 e->sad_count = val; 160 else if (!strncmp(name, "sad", 3)) { 161 sname = name + 4; 162 n = name[3] - '0'; 163 if (name[4] >= '0' && name[4] <= '9') { 164 sname++; 165 n = 10 * n + name[4] - '0'; 166 } 167 if (n >= ELD_MAX_SAD) 168 continue; 169 if (!strcmp(sname, "_coding_type")) 170 e->sad[n].format = val; 171 else if (!strcmp(sname, "_channels")) 172 e->sad[n].channels = val; 173 else if (!strcmp(sname, "_rates")) 174 e->sad[n].rates = val; 175 else if (!strcmp(sname, "_bits")) 176 e->sad[n].sample_bits = val; 177 else if (!strcmp(sname, "_max_bitrate")) 178 e->sad[n].max_bitrate = val; 179 else if (!strcmp(sname, "_profile")) 180 e->sad[n].profile = val; 181 if (n >= e->sad_count) 182 e->sad_count = n + 1; 183 } 184 } 185 } 186 #endif /* CONFIG_SND_PROC_FS */ 187 188 /* update PCM info based on ELD */ 189 void snd_hdmi_eld_update_pcm_info(struct snd_parsed_hdmi_eld *e, 190 struct hda_pcm_stream *hinfo) 191 { 192 u32 rates; 193 u64 formats; 194 unsigned int maxbps; 195 unsigned int channels_max; 196 int i; 197 198 /* assume basic audio support (the basic audio flag is not in ELD; 199 * however, all audio capable sinks are required to support basic 200 * audio) */ 201 rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 202 SNDRV_PCM_RATE_48000; 203 formats = SNDRV_PCM_FMTBIT_S16_LE; 204 maxbps = 16; 205 channels_max = 2; 206 for (i = 0; i < e->sad_count; i++) { 207 struct snd_cea_sad *a = &e->sad[i]; 208 rates |= a->rates; 209 if (a->channels > channels_max) 210 channels_max = a->channels; 211 if (a->format == AUDIO_CODING_TYPE_LPCM) { 212 if (a->sample_bits & ELD_PCM_BITS_20) { 213 formats |= SNDRV_PCM_FMTBIT_S32_LE; 214 if (maxbps < 20) 215 maxbps = 20; 216 } 217 if (a->sample_bits & ELD_PCM_BITS_24) { 218 formats |= SNDRV_PCM_FMTBIT_S32_LE; 219 if (maxbps < 24) 220 maxbps = 24; 221 } 222 } 223 } 224 225 /* restrict the parameters by the values the codec provides */ 226 hinfo->rates &= rates; 227 hinfo->formats &= formats; 228 hinfo->maxbps = min(hinfo->maxbps, maxbps); 229 hinfo->channels_max = min(hinfo->channels_max, channels_max); 230 } 231