aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorSandeep Tayal <sandeepx.tayal@intel.com>2016-09-20 09:46:05 -0400
committerMark Brown <broonie@kernel.org>2016-09-24 14:53:28 -0400
commitfe27f4e0545d3fc1b0518fafb4fe0460d757651d (patch)
tree248964908f30643fc0f4a40663e8e82f51f84211 /sound
parent1635c694124fe66933ae3db0d39dacb44c53f4b9 (diff)
ASoC: hdac_hdmi: use audio component framework to read ELD
With codec read sometimes the pin_sense shows invalid monitor present and eld_valid. Currently driver polls for few times to get the valid ELD data. To avoid the latency, Instead of reading ELD from codec, read it directly from the display driver using audio component framework. Removed the direct codec helper functions. Signed-off-by: Sandeep Tayal <sandeepx.tayal@intel.com> Signed-off-by: Jeeja KP <jeeja.kp@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/hdac_hdmi.c201
1 files changed, 56 insertions, 145 deletions
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 4e181b270d95..537f61aa27fa 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -46,6 +46,10 @@
46#define ELD_MAX_SIZE 256 46#define ELD_MAX_SIZE 256
47#define ELD_FIXED_BYTES 20 47#define ELD_FIXED_BYTES 20
48 48
49#define ELD_VER_CEA_861D 2
50#define ELD_VER_PARTIAL 31
51#define ELD_MAX_MNL 16
52
49struct hdac_hdmi_cvt_params { 53struct hdac_hdmi_cvt_params {
50 unsigned int channels_min; 54 unsigned int channels_min;
51 unsigned int channels_max; 55 unsigned int channels_max;
@@ -81,8 +85,6 @@ struct hdac_hdmi_pin {
81 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; 85 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
82 struct hdac_hdmi_eld eld; 86 struct hdac_hdmi_eld eld;
83 struct hdac_ext_device *edev; 87 struct hdac_ext_device *edev;
84 int repoll_count;
85 struct delayed_work work;
86 struct mutex lock; 88 struct mutex lock;
87 bool chmap_set; 89 bool chmap_set;
88 unsigned char chmap[8]; /* ALSA API channel-map */ 90 unsigned char chmap[8]; /* ALSA API channel-map */
@@ -173,80 +175,6 @@ format_constraint:
173 175
174} 176}
175 177
176 /* HDMI ELD routines */
177static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec,
178 hda_nid_t nid, int byte_index)
179{
180 unsigned int val;
181
182 val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD,
183 byte_index);
184
185 dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n",
186 byte_index, val);
187
188 return val;
189}
190
191static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid)
192{
193 return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
194 AC_DIPSIZE_ELD_BUF);
195}
196
197/*
198 * This function queries the ELD size and ELD data and fills in the buffer
199 * passed by user
200 */
201static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid,
202 unsigned char *buf, int *eld_size)
203{
204 int i, size, ret = 0;
205
206 /*
207 * ELD size is initialized to zero in caller function. If no errors and
208 * ELD is valid, actual eld_size is assigned.
209 */
210
211 size = hdac_hdmi_get_eld_size(codec, nid);
212 if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
213 dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size);
214 return -ERANGE;
215 }
216
217 /* set ELD buffer */
218 for (i = 0; i < size; i++) {
219 unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i);
220 /*
221 * Graphics driver might be writing to ELD buffer right now.
222 * Just abort. The caller will repoll after a while.
223 */
224 if (!(val & AC_ELDD_ELD_VALID)) {
225 dev_err(&codec->dev,
226 "HDMI: invalid ELD data byte %d\n", i);
227 ret = -EINVAL;
228 goto error;
229 }
230 val &= AC_ELDD_ELD_DATA;
231 /*
232 * The first byte cannot be zero. This can happen on some DVI
233 * connections. Some Intel chips may also need some 250ms delay
234 * to return non-zero ELD data, even when the graphics driver
235 * correctly writes ELD content before setting ELD_valid bit.
236 */
237 if (!val && !i) {
238 dev_err(&codec->dev, "HDMI: 0 ELD data\n");
239 ret = -EINVAL;
240 goto error;
241 }
242 buf[i] = val;
243 }
244
245 *eld_size = size;
246error:
247 return ret;
248}
249
250static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac, 178static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac,
251 hda_nid_t cvt_nid, hda_nid_t pin_nid, 179 hda_nid_t cvt_nid, hda_nid_t pin_nid,
252 u32 stream_tag, int format) 180 u32 stream_tag, int format)
@@ -1059,32 +987,59 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
1059 return hdac_hdmi_query_cvt_params(&edev->hdac, cvt); 987 return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
1060} 988}
1061 989
1062static void hdac_hdmi_parse_eld(struct hdac_ext_device *edev, 990static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
1063 struct hdac_hdmi_pin *pin) 991 struct hdac_hdmi_pin *pin)
1064{ 992{
993 unsigned int ver, mnl;
994
995 ver = (pin->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
996 >> DRM_ELD_VER_SHIFT;
997
998 if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
999 dev_dbg(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver);
1000 return -EINVAL;
1001 }
1002
1003 mnl = (pin->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
1004 DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
1005
1006 if (mnl > ELD_MAX_MNL) {
1007 dev_dbg(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl);
1008 return -EINVAL;
1009 }
1010
1065 pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER]; 1011 pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER];
1012
1013 return 0;
1066} 1014}
1067 1015
1068static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) 1016static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin)
1069{ 1017{
1070 struct hdac_ext_device *edev = pin->edev; 1018 struct hdac_ext_device *edev = pin->edev;
1071 struct hdac_hdmi_priv *hdmi = edev->private_data; 1019 struct hdac_hdmi_priv *hdmi = edev->private_data;
1072 struct hdac_hdmi_pcm *pcm; 1020 struct hdac_hdmi_pcm *pcm;
1073 int val; 1021 int size;
1074
1075 pin->repoll_count = repoll;
1076 1022
1077 pm_runtime_get_sync(&edev->hdac.dev); 1023 mutex_lock(&hdmi->pin_mutex);
1078 val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0, 1024 pin->eld.monitor_present = false;
1079 AC_VERB_GET_PIN_SENSE, 0);
1080 1025
1081 dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n", 1026 size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1,
1082 val, pin->nid); 1027 &pin->eld.monitor_present, pin->eld.eld_buffer,
1028 ELD_MAX_SIZE);
1083 1029
1030 if (size > 0) {
1031 size = min(size, ELD_MAX_SIZE);
1032 if (hdac_hdmi_parse_eld(edev, pin) < 0)
1033 size = -EINVAL;
1034 }
1084 1035
1085 mutex_lock(&hdmi->pin_mutex); 1036 if (size > 0) {
1086 pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE); 1037 pin->eld.eld_valid = true;
1087 pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV); 1038 pin->eld.eld_size = size;
1039 } else {
1040 pin->eld.eld_valid = false;
1041 pin->eld.eld_size = 0;
1042 }
1088 1043
1089 pcm = hdac_hdmi_get_pcm(edev, pin); 1044 pcm = hdac_hdmi_get_pcm(edev, pin);
1090 1045
@@ -1106,66 +1061,23 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
1106 } 1061 }
1107 1062
1108 mutex_unlock(&hdmi->pin_mutex); 1063 mutex_unlock(&hdmi->pin_mutex);
1109 goto put_hdac_device; 1064 return;
1110 } 1065 }
1111 1066
1112 if (pin->eld.monitor_present && pin->eld.eld_valid) { 1067 if (pin->eld.monitor_present && pin->eld.eld_valid) {
1113 /* TODO: use i915 component for reading ELD later */ 1068 if (pcm) {
1114 if (hdac_hdmi_get_eld(&edev->hdac, pin->nid, 1069 dev_dbg(&edev->hdac.dev,
1115 pin->eld.eld_buffer, 1070 "jack report for pcm=%d\n",
1116 &pin->eld.eld_size) == 0) { 1071 pcm->pcm_id);
1117
1118 if (pcm) {
1119 dev_dbg(&edev->hdac.dev,
1120 "jack report for pcm=%d\n",
1121 pcm->pcm_id);
1122
1123 snd_jack_report(pcm->jack, SND_JACK_AVOUT);
1124 }
1125 hdac_hdmi_parse_eld(edev, pin);
1126
1127 print_hex_dump_debug("ELD: ",
1128 DUMP_PREFIX_OFFSET, 16, 1,
1129 pin->eld.eld_buffer, pin->eld.eld_size,
1130 true);
1131 } else {
1132 pin->eld.monitor_present = false;
1133 pin->eld.eld_valid = false;
1134
1135 if (pcm) {
1136 dev_dbg(&edev->hdac.dev,
1137 "jack report for pcm=%d\n",
1138 pcm->pcm_id);
1139 1072
1140 snd_jack_report(pcm->jack, 0); 1073 snd_jack_report(pcm->jack, SND_JACK_AVOUT);
1141 }
1142 } 1074 }
1075
1076 print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
1077 pin->eld.eld_buffer, pin->eld.eld_size, false);
1143 } 1078 }
1144 1079
1145 mutex_unlock(&hdmi->pin_mutex); 1080 mutex_unlock(&hdmi->pin_mutex);
1146
1147 /*
1148 * Sometimes the pin_sense may present invalid monitor
1149 * present and eld_valid. If ELD data is not valid, loop few
1150 * more times to get correct pin sense and valid ELD.
1151 */
1152 if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll)
1153 schedule_delayed_work(&pin->work, msecs_to_jiffies(300));
1154
1155put_hdac_device:
1156 pm_runtime_put_sync(&edev->hdac.dev);
1157}
1158
1159static void hdac_hdmi_repoll_eld(struct work_struct *work)
1160{
1161 struct hdac_hdmi_pin *pin =
1162 container_of(to_delayed_work(work), struct hdac_hdmi_pin, work);
1163
1164 /* picked from legacy HDA driver */
1165 if (pin->repoll_count++ > 6)
1166 pin->repoll_count = 0;
1167
1168 hdac_hdmi_present_sense(pin, pin->repoll_count);
1169} 1081}
1170 1082
1171static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) 1083static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
@@ -1184,7 +1096,6 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
1184 1096
1185 pin->edev = edev; 1097 pin->edev = edev;
1186 mutex_init(&pin->lock); 1098 mutex_init(&pin->lock);
1187 INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld);
1188 1099
1189 return 0; 1100 return 0;
1190} 1101}
@@ -1395,7 +1306,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port)
1395 1306
1396 list_for_each_entry(pin, &hdmi->pin_list, head) { 1307 list_for_each_entry(pin, &hdmi->pin_list, head) {
1397 if (pin->nid == pin_nid) 1308 if (pin->nid == pin_nid)
1398 hdac_hdmi_present_sense(pin, 1); 1309 hdac_hdmi_present_sense(pin);
1399 } 1310 }
1400} 1311}
1401 1312
@@ -1496,7 +1407,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
1496 } 1407 }
1497 1408
1498 list_for_each_entry(pin, &hdmi->pin_list, head) 1409 list_for_each_entry(pin, &hdmi->pin_list, head)
1499 hdac_hdmi_present_sense(pin, 1); 1410 hdac_hdmi_present_sense(pin);
1500 1411
1501 /* Imp: Store the card pointer in hda_codec */ 1412 /* Imp: Store the card pointer in hda_codec */
1502 edev->card = dapm->card->snd_card; 1413 edev->card = dapm->card->snd_card;
@@ -1561,7 +1472,7 @@ static void hdmi_codec_complete(struct device *dev)
1561 * all pins here. 1472 * all pins here.
1562 */ 1473 */
1563 list_for_each_entry(pin, &hdmi->pin_list, head) 1474 list_for_each_entry(pin, &hdmi->pin_list, head)
1564 hdac_hdmi_present_sense(pin, 1); 1475 hdac_hdmi_present_sense(pin);
1565 1476
1566 pm_runtime_put_sync(&edev->hdac.dev); 1477 pm_runtime_put_sync(&edev->hdac.dev);
1567} 1478}