xref: /linux/sound/hda/codecs/hdmi/eld.c (revision 73cd0490819d2a693928c5977280dd31b756cb42)
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 
hdmi_get_eld_data(struct hda_codec * codec,hda_nid_t nid,int byte_index)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 
snd_hdmi_get_eld_size(struct hda_codec * codec,hda_nid_t nid)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 
snd_hdmi_get_eld(struct hda_codec * codec,hda_nid_t nid,unsigned char * buf,int * eld_size)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
snd_hdmi_print_eld_info(struct hdmi_eld * eld,struct snd_info_buffer * buffer,hda_nid_t pin_nid,int dev_id,hda_nid_t cvt_nid)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 
snd_hdmi_write_eld_info(struct hdmi_eld * eld,struct snd_info_buffer * buffer)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 */
snd_hdmi_eld_update_pcm_info(struct snd_parsed_hdmi_eld * e,struct hda_pcm_stream * hinfo)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