.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * hdac_hdmi.c - ASoc HDA-HDMI codec driver for Intel platforms |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * Subhransu S. Prusty <subhransu.s.prusty@intel.com> |
---|
7 | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
8 | 9 | * |
---|
9 | | - * This program is free software; you can redistribute it and/or modify |
---|
10 | | - * it under the terms of the GNU General Public License as published by |
---|
11 | | - * the Free Software Foundation; version 2 of the License. |
---|
12 | | - * |
---|
13 | | - * This program is distributed in the hope that it will be useful, but |
---|
14 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
16 | | - * General Public License for more details. |
---|
17 | | - * |
---|
18 | 10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
19 | 11 | */ |
---|
| 12 | + |
---|
20 | 13 | #include <linux/init.h> |
---|
21 | 14 | #include <linux/delay.h> |
---|
22 | 15 | #include <linux/module.h> |
---|
.. | .. |
---|
96 | 89 | hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; |
---|
97 | 90 | struct hdac_hdmi_eld eld; |
---|
98 | 91 | const char *jack_pin; |
---|
| 92 | + bool is_connect; |
---|
99 | 93 | struct snd_soc_dapm_context *dapm; |
---|
100 | 94 | const char *output_pin; |
---|
| 95 | + struct work_struct dapm_work; |
---|
101 | 96 | }; |
---|
102 | 97 | |
---|
103 | 98 | struct hdac_hdmi_pcm { |
---|
.. | .. |
---|
113 | 108 | unsigned char chmap[8]; /* ALSA API channel-map */ |
---|
114 | 109 | struct mutex lock; |
---|
115 | 110 | int jack_event; |
---|
| 111 | + struct snd_kcontrol *eld_ctl; |
---|
116 | 112 | }; |
---|
117 | 113 | |
---|
118 | 114 | struct hdac_hdmi_dai_port_map { |
---|
.. | .. |
---|
163 | 159 | { |
---|
164 | 160 | struct hdac_device *hdev = port->pin->hdev; |
---|
165 | 161 | |
---|
166 | | - if (is_connect) |
---|
167 | | - snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); |
---|
168 | | - else |
---|
169 | | - snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); |
---|
170 | | - |
---|
| 162 | + port->is_connect = is_connect; |
---|
171 | 163 | if (is_connect) { |
---|
172 | 164 | /* |
---|
173 | 165 | * Report Jack connect event when a device is connected |
---|
.. | .. |
---|
193 | 185 | if (pcm->jack_event > 0) |
---|
194 | 186 | pcm->jack_event--; |
---|
195 | 187 | } |
---|
| 188 | +} |
---|
196 | 189 | |
---|
| 190 | +static void hdac_hdmi_port_dapm_update(struct hdac_hdmi_port *port) |
---|
| 191 | +{ |
---|
| 192 | + if (port->is_connect) |
---|
| 193 | + snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); |
---|
| 194 | + else |
---|
| 195 | + snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); |
---|
197 | 196 | snd_soc_dapm_sync(port->dapm); |
---|
| 197 | +} |
---|
| 198 | + |
---|
| 199 | +static void hdac_hdmi_jack_dapm_work(struct work_struct *work) |
---|
| 200 | +{ |
---|
| 201 | + struct hdac_hdmi_port *port; |
---|
| 202 | + |
---|
| 203 | + port = container_of(work, struct hdac_hdmi_port, dapm_work); |
---|
| 204 | + hdac_hdmi_port_dapm_update(port); |
---|
| 205 | +} |
---|
| 206 | + |
---|
| 207 | +static void hdac_hdmi_jack_report_sync(struct hdac_hdmi_pcm *pcm, |
---|
| 208 | + struct hdac_hdmi_port *port, bool is_connect) |
---|
| 209 | +{ |
---|
| 210 | + hdac_hdmi_jack_report(pcm, port, is_connect); |
---|
| 211 | + hdac_hdmi_port_dapm_update(port); |
---|
198 | 212 | } |
---|
199 | 213 | |
---|
200 | 214 | /* MST supported verbs */ |
---|
.. | .. |
---|
447 | 461 | struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai) |
---|
448 | 462 | { |
---|
449 | 463 | struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai); |
---|
450 | | - struct hdac_device *hdev = hdmi->hdev; |
---|
451 | 464 | struct hdac_hdmi_dai_port_map *dai_map; |
---|
452 | | - struct hdac_hdmi_port *port; |
---|
453 | 465 | struct hdac_hdmi_pcm *pcm; |
---|
454 | 466 | int format; |
---|
455 | 467 | |
---|
456 | 468 | dai_map = &hdmi->dai_map[dai->id]; |
---|
457 | | - port = dai_map->port; |
---|
458 | | - |
---|
459 | | - if (!port) |
---|
460 | | - return -ENODEV; |
---|
461 | | - |
---|
462 | | - if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) { |
---|
463 | | - dev_err(&hdev->dev, |
---|
464 | | - "device is not configured for this pin:port%d:%d\n", |
---|
465 | | - port->pin->nid, port->id); |
---|
466 | | - return -ENODEV; |
---|
467 | | - } |
---|
468 | 469 | |
---|
469 | 470 | format = snd_hdac_calc_stream_format(params_rate(hparams), |
---|
470 | 471 | params_channels(hparams), params_format(hparams), |
---|
.. | .. |
---|
549 | 550 | } |
---|
550 | 551 | |
---|
551 | 552 | return NULL; |
---|
| 553 | +} |
---|
| 554 | + |
---|
| 555 | +/* |
---|
| 556 | + * Go through all converters and ensure connection is set to |
---|
| 557 | + * the correct pin as set via kcontrols. |
---|
| 558 | + */ |
---|
| 559 | +static void hdac_hdmi_verify_connect_sel_all_pins(struct hdac_device *hdev) |
---|
| 560 | +{ |
---|
| 561 | + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); |
---|
| 562 | + struct hdac_hdmi_port *port; |
---|
| 563 | + struct hdac_hdmi_cvt *cvt; |
---|
| 564 | + int cvt_idx = 0; |
---|
| 565 | + |
---|
| 566 | + list_for_each_entry(cvt, &hdmi->cvt_list, head) { |
---|
| 567 | + port = hdac_hdmi_get_port_from_cvt(hdev, hdmi, cvt); |
---|
| 568 | + if (port && port->pin) { |
---|
| 569 | + snd_hdac_codec_write(hdev, port->pin->nid, 0, |
---|
| 570 | + AC_VERB_SET_CONNECT_SEL, cvt_idx); |
---|
| 571 | + dev_dbg(&hdev->dev, "%s: %s set connect %d -> %d\n", |
---|
| 572 | + __func__, cvt->name, port->pin->nid, cvt_idx); |
---|
| 573 | + } |
---|
| 574 | + ++cvt_idx; |
---|
| 575 | + } |
---|
552 | 576 | } |
---|
553 | 577 | |
---|
554 | 578 | /* |
---|
.. | .. |
---|
811 | 835 | AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag); |
---|
812 | 836 | snd_hdac_codec_write(hdev, cvt->nid, 0, |
---|
813 | 837 | AC_VERB_SET_STREAM_FORMAT, pcm->format); |
---|
| 838 | + |
---|
| 839 | + /* |
---|
| 840 | + * The connection indices are shared by all converters and |
---|
| 841 | + * may interfere with each other. Ensure correct |
---|
| 842 | + * routing for all converters at stream start. |
---|
| 843 | + */ |
---|
| 844 | + hdac_hdmi_verify_connect_sel_all_pins(hdev); |
---|
| 845 | + |
---|
814 | 846 | break; |
---|
815 | 847 | |
---|
816 | 848 | case SND_SOC_DAPM_POST_PMD: |
---|
.. | .. |
---|
886 | 918 | list_for_each_entry_safe(p, p_next, &pcm->port_list, head) { |
---|
887 | 919 | if (p == port && p->id == port->id && |
---|
888 | 920 | p->pin == port->pin) { |
---|
889 | | - hdac_hdmi_jack_report(pcm, port, false); |
---|
| 921 | + hdac_hdmi_jack_report_sync(pcm, port, false); |
---|
890 | 922 | list_del(&p->head); |
---|
891 | 923 | } |
---|
892 | 924 | } |
---|
.. | .. |
---|
900 | 932 | if (!strcmp(cvt_name, pcm->cvt->name)) { |
---|
901 | 933 | list_add_tail(&port->head, &pcm->port_list); |
---|
902 | 934 | if (port->eld.monitor_present && port->eld.eld_valid) { |
---|
903 | | - hdac_hdmi_jack_report(pcm, port, true); |
---|
| 935 | + hdac_hdmi_jack_report_sync(pcm, port, true); |
---|
904 | 936 | mutex_unlock(&hdmi->pin_mutex); |
---|
905 | 937 | return ret; |
---|
906 | 938 | } |
---|
.. | .. |
---|
1168 | 1200 | struct hdac_hdmi_cvt *cvt; |
---|
1169 | 1201 | char name[NAME_SIZE]; |
---|
1170 | 1202 | |
---|
1171 | | - cvt = kzalloc(sizeof(*cvt), GFP_KERNEL); |
---|
| 1203 | + cvt = devm_kzalloc(&hdev->dev, sizeof(*cvt), GFP_KERNEL); |
---|
1172 | 1204 | if (!cvt) |
---|
1173 | 1205 | return -ENOMEM; |
---|
1174 | 1206 | |
---|
1175 | 1207 | cvt->nid = nid; |
---|
1176 | 1208 | sprintf(name, "cvt %d", cvt->nid); |
---|
1177 | | - cvt->name = kstrdup(name, GFP_KERNEL); |
---|
| 1209 | + cvt->name = devm_kstrdup(&hdev->dev, name, GFP_KERNEL); |
---|
| 1210 | + if (!cvt->name) |
---|
| 1211 | + return -ENOMEM; |
---|
1178 | 1212 | |
---|
1179 | 1213 | list_add_tail(&cvt->head, &hdmi->cvt_list); |
---|
1180 | 1214 | hdmi->num_cvt++; |
---|
.. | .. |
---|
1216 | 1250 | struct hdac_hdmi_pcm *pcm; |
---|
1217 | 1251 | int size = 0; |
---|
1218 | 1252 | int port_id = -1; |
---|
| 1253 | + bool eld_valid, eld_changed; |
---|
1219 | 1254 | |
---|
1220 | 1255 | if (!hdmi) |
---|
1221 | 1256 | return; |
---|
.. | .. |
---|
1241 | 1276 | size = -EINVAL; |
---|
1242 | 1277 | } |
---|
1243 | 1278 | |
---|
| 1279 | + eld_valid = port->eld.eld_valid; |
---|
| 1280 | + |
---|
1244 | 1281 | if (size > 0) { |
---|
1245 | 1282 | port->eld.eld_valid = true; |
---|
1246 | 1283 | port->eld.eld_size = size; |
---|
.. | .. |
---|
1248 | 1285 | port->eld.eld_valid = false; |
---|
1249 | 1286 | port->eld.eld_size = 0; |
---|
1250 | 1287 | } |
---|
| 1288 | + |
---|
| 1289 | + eld_changed = (eld_valid != port->eld.eld_valid); |
---|
1251 | 1290 | |
---|
1252 | 1291 | pcm = hdac_hdmi_get_pcm(hdev, port); |
---|
1253 | 1292 | |
---|
.. | .. |
---|
1261 | 1300 | * report jack here. It will be done in usermode mux |
---|
1262 | 1301 | * control select. |
---|
1263 | 1302 | */ |
---|
1264 | | - if (pcm) |
---|
| 1303 | + if (pcm) { |
---|
1265 | 1304 | hdac_hdmi_jack_report(pcm, port, false); |
---|
| 1305 | + schedule_work(&port->dapm_work); |
---|
| 1306 | + } |
---|
1266 | 1307 | |
---|
1267 | 1308 | mutex_unlock(&hdmi->pin_mutex); |
---|
1268 | 1309 | return; |
---|
1269 | 1310 | } |
---|
1270 | 1311 | |
---|
1271 | 1312 | if (port->eld.monitor_present && port->eld.eld_valid) { |
---|
1272 | | - if (pcm) |
---|
| 1313 | + if (pcm) { |
---|
1273 | 1314 | hdac_hdmi_jack_report(pcm, port, true); |
---|
| 1315 | + schedule_work(&port->dapm_work); |
---|
| 1316 | + } |
---|
1274 | 1317 | |
---|
1275 | 1318 | print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1, |
---|
1276 | 1319 | port->eld.eld_buffer, port->eld.eld_size, false); |
---|
1277 | 1320 | |
---|
1278 | 1321 | } |
---|
1279 | 1322 | mutex_unlock(&hdmi->pin_mutex); |
---|
| 1323 | + |
---|
| 1324 | + if (eld_changed && pcm) |
---|
| 1325 | + snd_ctl_notify(hdmi->card, |
---|
| 1326 | + SNDRV_CTL_EVENT_MASK_VALUE | |
---|
| 1327 | + SNDRV_CTL_EVENT_MASK_INFO, |
---|
| 1328 | + &pcm->eld_ctl->id); |
---|
1280 | 1329 | } |
---|
1281 | 1330 | |
---|
1282 | | -static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi, |
---|
1283 | | - struct hdac_hdmi_pin *pin) |
---|
| 1331 | +static int hdac_hdmi_add_ports(struct hdac_device *hdev, |
---|
| 1332 | + struct hdac_hdmi_pin *pin) |
---|
1284 | 1333 | { |
---|
1285 | 1334 | struct hdac_hdmi_port *ports; |
---|
1286 | 1335 | int max_ports = HDA_MAX_PORTS; |
---|
.. | .. |
---|
1292 | 1341 | * implemented. |
---|
1293 | 1342 | */ |
---|
1294 | 1343 | |
---|
1295 | | - ports = kcalloc(max_ports, sizeof(*ports), GFP_KERNEL); |
---|
| 1344 | + ports = devm_kcalloc(&hdev->dev, max_ports, sizeof(*ports), GFP_KERNEL); |
---|
1296 | 1345 | if (!ports) |
---|
1297 | 1346 | return -ENOMEM; |
---|
1298 | 1347 | |
---|
1299 | 1348 | for (i = 0; i < max_ports; i++) { |
---|
1300 | 1349 | ports[i].id = i; |
---|
1301 | 1350 | ports[i].pin = pin; |
---|
| 1351 | + INIT_WORK(&ports[i].dapm_work, hdac_hdmi_jack_dapm_work); |
---|
1302 | 1352 | } |
---|
1303 | 1353 | pin->ports = ports; |
---|
1304 | 1354 | pin->num_ports = max_ports; |
---|
.. | .. |
---|
1311 | 1361 | struct hdac_hdmi_pin *pin; |
---|
1312 | 1362 | int ret; |
---|
1313 | 1363 | |
---|
1314 | | - pin = kzalloc(sizeof(*pin), GFP_KERNEL); |
---|
| 1364 | + pin = devm_kzalloc(&hdev->dev, sizeof(*pin), GFP_KERNEL); |
---|
1315 | 1365 | if (!pin) |
---|
1316 | 1366 | return -ENOMEM; |
---|
1317 | 1367 | |
---|
1318 | 1368 | pin->nid = nid; |
---|
1319 | 1369 | pin->mst_capable = false; |
---|
1320 | 1370 | pin->hdev = hdev; |
---|
1321 | | - ret = hdac_hdmi_add_ports(hdmi, pin); |
---|
| 1371 | + ret = hdac_hdmi_add_ports(hdev, pin); |
---|
1322 | 1372 | if (ret < 0) |
---|
1323 | 1373 | return ret; |
---|
1324 | 1374 | |
---|
.. | .. |
---|
1372 | 1422 | if (vendor_param == -1) |
---|
1373 | 1423 | return; |
---|
1374 | 1424 | |
---|
| 1425 | +} |
---|
| 1426 | + |
---|
| 1427 | +static int hdac_hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, |
---|
| 1428 | + struct snd_ctl_elem_info *uinfo) |
---|
| 1429 | +{ |
---|
| 1430 | + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
---|
| 1431 | + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); |
---|
| 1432 | + struct hdac_hdmi_pcm *pcm; |
---|
| 1433 | + struct hdac_hdmi_port *port; |
---|
| 1434 | + struct hdac_hdmi_eld *eld; |
---|
| 1435 | + |
---|
| 1436 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
---|
| 1437 | + uinfo->count = 0; |
---|
| 1438 | + |
---|
| 1439 | + pcm = get_hdmi_pcm_from_id(hdmi, kcontrol->id.device); |
---|
| 1440 | + if (!pcm) { |
---|
| 1441 | + dev_dbg(component->dev, "%s: no pcm, device %d\n", __func__, |
---|
| 1442 | + kcontrol->id.device); |
---|
| 1443 | + return 0; |
---|
| 1444 | + } |
---|
| 1445 | + |
---|
| 1446 | + if (list_empty(&pcm->port_list)) { |
---|
| 1447 | + dev_dbg(component->dev, "%s: empty port list, device %d\n", |
---|
| 1448 | + __func__, kcontrol->id.device); |
---|
| 1449 | + return 0; |
---|
| 1450 | + } |
---|
| 1451 | + |
---|
| 1452 | + mutex_lock(&hdmi->pin_mutex); |
---|
| 1453 | + |
---|
| 1454 | + list_for_each_entry(port, &pcm->port_list, head) { |
---|
| 1455 | + eld = &port->eld; |
---|
| 1456 | + |
---|
| 1457 | + if (eld->eld_valid) { |
---|
| 1458 | + uinfo->count = eld->eld_size; |
---|
| 1459 | + break; |
---|
| 1460 | + } |
---|
| 1461 | + } |
---|
| 1462 | + |
---|
| 1463 | + mutex_unlock(&hdmi->pin_mutex); |
---|
| 1464 | + |
---|
| 1465 | + return 0; |
---|
| 1466 | +} |
---|
| 1467 | + |
---|
| 1468 | +static int hdac_hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, |
---|
| 1469 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 1470 | +{ |
---|
| 1471 | + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
---|
| 1472 | + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); |
---|
| 1473 | + struct hdac_hdmi_pcm *pcm; |
---|
| 1474 | + struct hdac_hdmi_port *port; |
---|
| 1475 | + struct hdac_hdmi_eld *eld; |
---|
| 1476 | + |
---|
| 1477 | + memset(ucontrol->value.bytes.data, 0, sizeof(ucontrol->value.bytes.data)); |
---|
| 1478 | + |
---|
| 1479 | + pcm = get_hdmi_pcm_from_id(hdmi, kcontrol->id.device); |
---|
| 1480 | + if (!pcm) { |
---|
| 1481 | + dev_dbg(component->dev, "%s: no pcm, device %d\n", __func__, |
---|
| 1482 | + kcontrol->id.device); |
---|
| 1483 | + return 0; |
---|
| 1484 | + } |
---|
| 1485 | + |
---|
| 1486 | + if (list_empty(&pcm->port_list)) { |
---|
| 1487 | + dev_dbg(component->dev, "%s: empty port list, device %d\n", |
---|
| 1488 | + __func__, kcontrol->id.device); |
---|
| 1489 | + return 0; |
---|
| 1490 | + } |
---|
| 1491 | + |
---|
| 1492 | + mutex_lock(&hdmi->pin_mutex); |
---|
| 1493 | + |
---|
| 1494 | + list_for_each_entry(port, &pcm->port_list, head) { |
---|
| 1495 | + eld = &port->eld; |
---|
| 1496 | + |
---|
| 1497 | + if (!eld->eld_valid) |
---|
| 1498 | + continue; |
---|
| 1499 | + |
---|
| 1500 | + if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || |
---|
| 1501 | + eld->eld_size > ELD_MAX_SIZE) { |
---|
| 1502 | + mutex_unlock(&hdmi->pin_mutex); |
---|
| 1503 | + |
---|
| 1504 | + dev_err(component->dev, "%s: buffer too small, device %d eld_size %d\n", |
---|
| 1505 | + __func__, kcontrol->id.device, eld->eld_size); |
---|
| 1506 | + snd_BUG(); |
---|
| 1507 | + return -EINVAL; |
---|
| 1508 | + } |
---|
| 1509 | + |
---|
| 1510 | + memcpy(ucontrol->value.bytes.data, eld->eld_buffer, |
---|
| 1511 | + eld->eld_size); |
---|
| 1512 | + break; |
---|
| 1513 | + } |
---|
| 1514 | + |
---|
| 1515 | + mutex_unlock(&hdmi->pin_mutex); |
---|
| 1516 | + |
---|
| 1517 | + return 0; |
---|
| 1518 | +} |
---|
| 1519 | + |
---|
| 1520 | +static int hdac_hdmi_create_eld_ctl(struct snd_soc_component *component, struct hdac_hdmi_pcm *pcm) |
---|
| 1521 | +{ |
---|
| 1522 | + struct snd_kcontrol *kctl; |
---|
| 1523 | + struct snd_kcontrol_new hdmi_eld_ctl = { |
---|
| 1524 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | |
---|
| 1525 | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 1526 | + .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
---|
| 1527 | + .name = "ELD", |
---|
| 1528 | + .info = hdac_hdmi_eld_ctl_info, |
---|
| 1529 | + .get = hdac_hdmi_eld_ctl_get, |
---|
| 1530 | + .device = pcm->pcm_id, |
---|
| 1531 | + }; |
---|
| 1532 | + |
---|
| 1533 | + /* add ELD ctl with the device number corresponding to the PCM stream */ |
---|
| 1534 | + kctl = snd_ctl_new1(&hdmi_eld_ctl, component); |
---|
| 1535 | + if (!kctl) |
---|
| 1536 | + return -ENOMEM; |
---|
| 1537 | + |
---|
| 1538 | + pcm->eld_ctl = kctl; |
---|
| 1539 | + |
---|
| 1540 | + return snd_ctl_add(component->card->snd_card, kctl); |
---|
1375 | 1541 | } |
---|
1376 | 1542 | |
---|
1377 | 1543 | static const struct snd_soc_dai_ops hdmi_dai_ops = { |
---|
.. | .. |
---|
1459 | 1625 | { |
---|
1460 | 1626 | hda_nid_t nid; |
---|
1461 | 1627 | int i, num_nodes; |
---|
1462 | | - struct hdac_hdmi_cvt *temp_cvt, *cvt_next; |
---|
1463 | | - struct hdac_hdmi_pin *temp_pin, *pin_next; |
---|
1464 | 1628 | struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); |
---|
1465 | 1629 | int ret; |
---|
1466 | 1630 | |
---|
.. | .. |
---|
1488 | 1652 | case AC_WID_AUD_OUT: |
---|
1489 | 1653 | ret = hdac_hdmi_add_cvt(hdev, nid); |
---|
1490 | 1654 | if (ret < 0) |
---|
1491 | | - goto free_widgets; |
---|
| 1655 | + return ret; |
---|
1492 | 1656 | break; |
---|
1493 | 1657 | |
---|
1494 | 1658 | case AC_WID_PIN: |
---|
1495 | 1659 | ret = hdac_hdmi_add_pin(hdev, nid); |
---|
1496 | 1660 | if (ret < 0) |
---|
1497 | | - goto free_widgets; |
---|
| 1661 | + return ret; |
---|
1498 | 1662 | break; |
---|
1499 | 1663 | } |
---|
1500 | 1664 | } |
---|
1501 | 1665 | |
---|
1502 | 1666 | if (!hdmi->num_pin || !hdmi->num_cvt) { |
---|
1503 | 1667 | ret = -EIO; |
---|
1504 | | - goto free_widgets; |
---|
| 1668 | + dev_err(&hdev->dev, "Bad pin/cvt setup in %s\n", __func__); |
---|
| 1669 | + return ret; |
---|
1505 | 1670 | } |
---|
1506 | 1671 | |
---|
1507 | 1672 | ret = hdac_hdmi_create_dais(hdev, dais, hdmi, hdmi->num_cvt); |
---|
1508 | 1673 | if (ret) { |
---|
1509 | 1674 | dev_err(&hdev->dev, "Failed to create dais with err: %d\n", |
---|
1510 | | - ret); |
---|
1511 | | - goto free_widgets; |
---|
| 1675 | + ret); |
---|
| 1676 | + return ret; |
---|
1512 | 1677 | } |
---|
1513 | 1678 | |
---|
1514 | 1679 | *num_dais = hdmi->num_cvt; |
---|
1515 | 1680 | ret = hdac_hdmi_init_dai_map(hdev); |
---|
1516 | 1681 | if (ret < 0) |
---|
1517 | | - goto free_widgets; |
---|
1518 | | - |
---|
1519 | | - return ret; |
---|
1520 | | - |
---|
1521 | | -free_widgets: |
---|
1522 | | - list_for_each_entry_safe(temp_cvt, cvt_next, &hdmi->cvt_list, head) { |
---|
1523 | | - list_del(&temp_cvt->head); |
---|
1524 | | - kfree(temp_cvt->name); |
---|
1525 | | - kfree(temp_cvt); |
---|
1526 | | - } |
---|
1527 | | - |
---|
1528 | | - list_for_each_entry_safe(temp_pin, pin_next, &hdmi->pin_list, head) { |
---|
1529 | | - for (i = 0; i < temp_pin->num_ports; i++) |
---|
1530 | | - temp_pin->ports[i].pin = NULL; |
---|
1531 | | - kfree(temp_pin->ports); |
---|
1532 | | - list_del(&temp_pin->head); |
---|
1533 | | - kfree(temp_pin); |
---|
1534 | | - } |
---|
1535 | | - |
---|
| 1682 | + dev_err(&hdev->dev, "Failed to init DAI map with err: %d\n", |
---|
| 1683 | + ret); |
---|
1536 | 1684 | return ret; |
---|
1537 | 1685 | } |
---|
1538 | 1686 | |
---|
.. | .. |
---|
1604 | 1752 | { |
---|
1605 | 1753 | struct snd_soc_pcm_runtime *rtd; |
---|
1606 | 1754 | |
---|
1607 | | - list_for_each_entry(rtd, &card->rtd_list, list) { |
---|
| 1755 | + for_each_card_rtds(card, rtd) { |
---|
1608 | 1756 | if (rtd->pcm && (rtd->pcm->device == device)) |
---|
1609 | 1757 | return rtd->pcm; |
---|
1610 | 1758 | } |
---|
.. | .. |
---|
1745 | 1893 | * this is a new PCM device, create new pcm and |
---|
1746 | 1894 | * add to the pcm list |
---|
1747 | 1895 | */ |
---|
1748 | | - pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
---|
| 1896 | + pcm = devm_kzalloc(&hdev->dev, sizeof(*pcm), GFP_KERNEL); |
---|
1749 | 1897 | if (!pcm) |
---|
1750 | 1898 | return -ENOMEM; |
---|
1751 | 1899 | pcm->pcm_id = device; |
---|
.. | .. |
---|
1761 | 1909 | dev_err(&hdev->dev, |
---|
1762 | 1910 | "chmap control add failed with err: %d for pcm: %d\n", |
---|
1763 | 1911 | err, device); |
---|
1764 | | - kfree(pcm); |
---|
1765 | 1912 | return err; |
---|
1766 | 1913 | } |
---|
| 1914 | + } |
---|
| 1915 | + |
---|
| 1916 | + /* add control for ELD Bytes */ |
---|
| 1917 | + err = hdac_hdmi_create_eld_ctl(component, pcm); |
---|
| 1918 | + if (err < 0) { |
---|
| 1919 | + dev_err(&hdev->dev, |
---|
| 1920 | + "eld control add failed with err: %d for pcm: %d\n", |
---|
| 1921 | + err, device); |
---|
| 1922 | + return err; |
---|
1767 | 1923 | } |
---|
1768 | 1924 | |
---|
1769 | 1925 | list_add_tail(&pcm->head, &hdmi->pcm_list); |
---|
.. | .. |
---|
1870 | 2026 | pm_runtime_disable(&hdev->dev); |
---|
1871 | 2027 | } |
---|
1872 | 2028 | |
---|
1873 | | -#ifdef CONFIG_PM |
---|
1874 | | -static int hdmi_codec_prepare(struct device *dev) |
---|
1875 | | -{ |
---|
1876 | | - struct hdac_device *hdev = dev_to_hdac_dev(dev); |
---|
1877 | | - |
---|
1878 | | - pm_runtime_get_sync(&hdev->dev); |
---|
1879 | | - |
---|
1880 | | - /* |
---|
1881 | | - * Power down afg. |
---|
1882 | | - * codec_read is preferred over codec_write to set the power state. |
---|
1883 | | - * This way verb is send to set the power state and response |
---|
1884 | | - * is received. So setting power state is ensured without using loop |
---|
1885 | | - * to read the state. |
---|
1886 | | - */ |
---|
1887 | | - snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE, |
---|
1888 | | - AC_PWRST_D3); |
---|
1889 | | - |
---|
1890 | | - return 0; |
---|
1891 | | -} |
---|
1892 | | - |
---|
1893 | | -static void hdmi_codec_complete(struct device *dev) |
---|
| 2029 | +#ifdef CONFIG_PM_SLEEP |
---|
| 2030 | +static int hdmi_codec_resume(struct device *dev) |
---|
1894 | 2031 | { |
---|
1895 | 2032 | struct hdac_device *hdev = dev_to_hdac_dev(dev); |
---|
1896 | 2033 | struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); |
---|
| 2034 | + int ret; |
---|
1897 | 2035 | |
---|
1898 | | - /* Power up afg */ |
---|
1899 | | - snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE, |
---|
1900 | | - AC_PWRST_D0); |
---|
1901 | | - |
---|
1902 | | - hdac_hdmi_skl_enable_all_pins(hdev); |
---|
1903 | | - hdac_hdmi_skl_enable_dp12(hdev); |
---|
1904 | | - |
---|
| 2036 | + ret = pm_runtime_force_resume(dev); |
---|
| 2037 | + if (ret < 0) |
---|
| 2038 | + return ret; |
---|
1905 | 2039 | /* |
---|
1906 | 2040 | * As the ELD notify callback request is not entertained while the |
---|
1907 | 2041 | * device is in suspend state. Need to manually check detection of |
---|
1908 | 2042 | * all pins here. pin capablity change is not support, so use the |
---|
1909 | 2043 | * already set pin caps. |
---|
| 2044 | + * |
---|
| 2045 | + * NOTE: this is safe to call even if the codec doesn't actually resume. |
---|
| 2046 | + * The pin check involves only with DRM audio component hooks, so it |
---|
| 2047 | + * works even if the HD-audio side is still dreaming peacefully. |
---|
1910 | 2048 | */ |
---|
1911 | 2049 | hdac_hdmi_present_sense_all_pins(hdev, hdmi, false); |
---|
1912 | | - |
---|
1913 | | - pm_runtime_put_sync(&hdev->dev); |
---|
| 2050 | + return 0; |
---|
1914 | 2051 | } |
---|
1915 | 2052 | #else |
---|
1916 | | -#define hdmi_codec_prepare NULL |
---|
1917 | | -#define hdmi_codec_complete NULL |
---|
| 2053 | +#define hdmi_codec_resume NULL |
---|
1918 | 2054 | #endif |
---|
1919 | 2055 | |
---|
1920 | 2056 | static const struct snd_soc_component_driver hdmi_hda_codec = { |
---|
.. | .. |
---|
1984 | 2120 | |
---|
1985 | 2121 | port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head); |
---|
1986 | 2122 | |
---|
1987 | | - if (!port) |
---|
1988 | | - return 0; |
---|
1989 | | - |
---|
1990 | 2123 | if (!port || !port->eld.eld_valid) |
---|
1991 | 2124 | return 0; |
---|
1992 | 2125 | |
---|
.. | .. |
---|
2003 | 2136 | |
---|
2004 | 2137 | static int hdac_hdmi_dev_probe(struct hdac_device *hdev) |
---|
2005 | 2138 | { |
---|
2006 | | - struct hdac_hdmi_priv *hdmi_priv = NULL; |
---|
| 2139 | + struct hdac_hdmi_priv *hdmi_priv; |
---|
2007 | 2140 | struct snd_soc_dai_driver *hdmi_dais = NULL; |
---|
2008 | | - struct hdac_ext_link *hlink = NULL; |
---|
| 2141 | + struct hdac_ext_link *hlink; |
---|
2009 | 2142 | int num_dais = 0; |
---|
2010 | | - int ret = 0; |
---|
| 2143 | + int ret; |
---|
2011 | 2144 | struct hdac_driver *hdrv = drv_to_hdac_driver(hdev->dev.driver); |
---|
2012 | 2145 | const struct hda_device_id *hdac_id = hdac_get_device_id(hdev, hdrv); |
---|
2013 | 2146 | |
---|
.. | .. |
---|
2051 | 2184 | * Turned off in the runtime_suspend during the first explicit |
---|
2052 | 2185 | * pm_runtime_suspend call. |
---|
2053 | 2186 | */ |
---|
2054 | | - ret = snd_hdac_display_power(hdev->bus, true); |
---|
2055 | | - if (ret < 0) { |
---|
2056 | | - dev_err(&hdev->dev, |
---|
2057 | | - "Cannot turn on display power on i915 err: %d\n", |
---|
2058 | | - ret); |
---|
2059 | | - return ret; |
---|
2060 | | - } |
---|
| 2187 | + snd_hdac_display_power(hdev->bus, hdev->addr, true); |
---|
2061 | 2188 | |
---|
2062 | 2189 | ret = hdac_hdmi_parse_and_map_nid(hdev, &hdmi_dais, &num_dais); |
---|
2063 | 2190 | if (ret < 0) { |
---|
.. | .. |
---|
2065 | 2192 | "Failed in parse and map nid with err: %d\n", ret); |
---|
2066 | 2193 | return ret; |
---|
2067 | 2194 | } |
---|
2068 | | - snd_hdac_refresh_widgets(hdev, true); |
---|
| 2195 | + snd_hdac_refresh_widgets(hdev); |
---|
2069 | 2196 | |
---|
2070 | 2197 | /* ASoC specific initialization */ |
---|
2071 | 2198 | ret = devm_snd_soc_register_component(&hdev->dev, &hdmi_hda_codec, |
---|
.. | .. |
---|
2076 | 2203 | return ret; |
---|
2077 | 2204 | } |
---|
2078 | 2205 | |
---|
2079 | | -static int hdac_hdmi_dev_remove(struct hdac_device *hdev) |
---|
| 2206 | +static void clear_dapm_works(struct hdac_device *hdev) |
---|
2080 | 2207 | { |
---|
2081 | 2208 | struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); |
---|
2082 | | - struct hdac_hdmi_pin *pin, *pin_next; |
---|
2083 | | - struct hdac_hdmi_cvt *cvt, *cvt_next; |
---|
2084 | | - struct hdac_hdmi_pcm *pcm, *pcm_next; |
---|
2085 | | - struct hdac_hdmi_port *port, *port_next; |
---|
| 2209 | + struct hdac_hdmi_pin *pin; |
---|
2086 | 2210 | int i; |
---|
2087 | 2211 | |
---|
2088 | | - list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) { |
---|
2089 | | - pcm->cvt = NULL; |
---|
2090 | | - if (list_empty(&pcm->port_list)) |
---|
2091 | | - continue; |
---|
2092 | | - |
---|
2093 | | - list_for_each_entry_safe(port, port_next, |
---|
2094 | | - &pcm->port_list, head) |
---|
2095 | | - list_del(&port->head); |
---|
2096 | | - |
---|
2097 | | - list_del(&pcm->head); |
---|
2098 | | - kfree(pcm); |
---|
2099 | | - } |
---|
2100 | | - |
---|
2101 | | - list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) { |
---|
2102 | | - list_del(&cvt->head); |
---|
2103 | | - kfree(cvt->name); |
---|
2104 | | - kfree(cvt); |
---|
2105 | | - } |
---|
2106 | | - |
---|
2107 | | - list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) { |
---|
| 2212 | + list_for_each_entry(pin, &hdmi->pin_list, head) |
---|
2108 | 2213 | for (i = 0; i < pin->num_ports; i++) |
---|
2109 | | - pin->ports[i].pin = NULL; |
---|
2110 | | - kfree(pin->ports); |
---|
2111 | | - list_del(&pin->head); |
---|
2112 | | - kfree(pin); |
---|
2113 | | - } |
---|
| 2214 | + cancel_work_sync(&pin->ports[i].dapm_work); |
---|
| 2215 | +} |
---|
| 2216 | + |
---|
| 2217 | +static int hdac_hdmi_dev_remove(struct hdac_device *hdev) |
---|
| 2218 | +{ |
---|
| 2219 | + clear_dapm_works(hdev); |
---|
| 2220 | + snd_hdac_display_power(hdev->bus, hdev->addr, false); |
---|
2114 | 2221 | |
---|
2115 | 2222 | return 0; |
---|
2116 | 2223 | } |
---|
2117 | 2224 | |
---|
2118 | 2225 | #ifdef CONFIG_PM |
---|
2119 | | -/* |
---|
2120 | | - * Power management sequences |
---|
2121 | | - * ========================== |
---|
2122 | | - * |
---|
2123 | | - * The following explains the PM handling of HDAC HDMI with its parent |
---|
2124 | | - * device SKL and display power usage |
---|
2125 | | - * |
---|
2126 | | - * Probe |
---|
2127 | | - * ----- |
---|
2128 | | - * In SKL probe, |
---|
2129 | | - * 1. skl_probe_work() powers up the display (refcount++ -> 1) |
---|
2130 | | - * 2. enumerates the codecs on the link |
---|
2131 | | - * 3. powers down the display (refcount-- -> 0) |
---|
2132 | | - * |
---|
2133 | | - * In HDAC HDMI probe, |
---|
2134 | | - * 1. hdac_hdmi_dev_probe() powers up the display (refcount++ -> 1) |
---|
2135 | | - * 2. probe the codec |
---|
2136 | | - * 3. put the HDAC HDMI device to runtime suspend |
---|
2137 | | - * 4. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) |
---|
2138 | | - * |
---|
2139 | | - * Once children are runtime suspended, SKL device also goes to runtime |
---|
2140 | | - * suspend |
---|
2141 | | - * |
---|
2142 | | - * HDMI Playback |
---|
2143 | | - * ------------- |
---|
2144 | | - * Open HDMI device, |
---|
2145 | | - * 1. skl_runtime_resume() invoked |
---|
2146 | | - * 2. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1) |
---|
2147 | | - * |
---|
2148 | | - * Close HDMI device, |
---|
2149 | | - * 1. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) |
---|
2150 | | - * 2. skl_runtime_suspend() invoked |
---|
2151 | | - * |
---|
2152 | | - * S0/S3 Cycle with playback in progress |
---|
2153 | | - * ------------------------------------- |
---|
2154 | | - * When the device is opened for playback, the device is runtime active |
---|
2155 | | - * already and the display refcount is 1 as explained above. |
---|
2156 | | - * |
---|
2157 | | - * Entering to S3, |
---|
2158 | | - * 1. hdmi_codec_prepare() invoke the runtime resume of codec which just |
---|
2159 | | - * increments the PM runtime usage count of the codec since the device |
---|
2160 | | - * is in use already |
---|
2161 | | - * 2. skl_suspend() powers down the display (refcount-- -> 0) |
---|
2162 | | - * |
---|
2163 | | - * Wakeup from S3, |
---|
2164 | | - * 1. skl_resume() powers up the display (refcount++ -> 1) |
---|
2165 | | - * 2. hdmi_codec_complete() invokes the runtime suspend of codec which just |
---|
2166 | | - * decrements the PM runtime usage count of the codec since the device |
---|
2167 | | - * is in use already |
---|
2168 | | - * |
---|
2169 | | - * Once playback is stopped, the display refcount is set to 0 as explained |
---|
2170 | | - * above in the HDMI playback sequence. The PM handlings are designed in |
---|
2171 | | - * such way that to balance the refcount of display power when the codec |
---|
2172 | | - * device put to S3 while playback is going on. |
---|
2173 | | - * |
---|
2174 | | - * S0/S3 Cycle without playback in progress |
---|
2175 | | - * ---------------------------------------- |
---|
2176 | | - * Entering to S3, |
---|
2177 | | - * 1. hdmi_codec_prepare() invoke the runtime resume of codec |
---|
2178 | | - * 2. skl_runtime_resume() invoked |
---|
2179 | | - * 3. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1) |
---|
2180 | | - * 4. skl_suspend() powers down the display (refcount-- -> 0) |
---|
2181 | | - * |
---|
2182 | | - * Wakeup from S3, |
---|
2183 | | - * 1. skl_resume() powers up the display (refcount++ -> 1) |
---|
2184 | | - * 2. hdmi_codec_complete() invokes the runtime suspend of codec |
---|
2185 | | - * 3. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) |
---|
2186 | | - * 4. skl_runtime_suspend() invoked |
---|
2187 | | - */ |
---|
2188 | 2226 | static int hdac_hdmi_runtime_suspend(struct device *dev) |
---|
2189 | 2227 | { |
---|
2190 | 2228 | struct hdac_device *hdev = dev_to_hdac_dev(dev); |
---|
2191 | 2229 | struct hdac_bus *bus = hdev->bus; |
---|
2192 | 2230 | struct hdac_ext_link *hlink = NULL; |
---|
2193 | | - int err; |
---|
2194 | 2231 | |
---|
2195 | 2232 | dev_dbg(dev, "Enter: %s\n", __func__); |
---|
2196 | 2233 | |
---|
.. | .. |
---|
2214 | 2251 | return -EIO; |
---|
2215 | 2252 | } |
---|
2216 | 2253 | |
---|
| 2254 | + snd_hdac_codec_link_down(hdev); |
---|
2217 | 2255 | snd_hdac_ext_bus_link_put(bus, hlink); |
---|
2218 | 2256 | |
---|
2219 | | - err = snd_hdac_display_power(bus, false); |
---|
2220 | | - if (err < 0) |
---|
2221 | | - dev_err(dev, "Cannot turn off display power on i915\n"); |
---|
| 2257 | + snd_hdac_display_power(bus, hdev->addr, false); |
---|
2222 | 2258 | |
---|
2223 | | - return err; |
---|
| 2259 | + return 0; |
---|
2224 | 2260 | } |
---|
2225 | 2261 | |
---|
2226 | 2262 | static int hdac_hdmi_runtime_resume(struct device *dev) |
---|
.. | .. |
---|
2228 | 2264 | struct hdac_device *hdev = dev_to_hdac_dev(dev); |
---|
2229 | 2265 | struct hdac_bus *bus = hdev->bus; |
---|
2230 | 2266 | struct hdac_ext_link *hlink = NULL; |
---|
2231 | | - int err; |
---|
2232 | 2267 | |
---|
2233 | 2268 | dev_dbg(dev, "Enter: %s\n", __func__); |
---|
2234 | 2269 | |
---|
.. | .. |
---|
2243 | 2278 | } |
---|
2244 | 2279 | |
---|
2245 | 2280 | snd_hdac_ext_bus_link_get(bus, hlink); |
---|
| 2281 | + snd_hdac_codec_link_up(hdev); |
---|
2246 | 2282 | |
---|
2247 | | - err = snd_hdac_display_power(bus, true); |
---|
2248 | | - if (err < 0) { |
---|
2249 | | - dev_err(dev, "Cannot turn on display power on i915\n"); |
---|
2250 | | - return err; |
---|
2251 | | - } |
---|
| 2283 | + snd_hdac_display_power(bus, hdev->addr, true); |
---|
2252 | 2284 | |
---|
2253 | 2285 | hdac_hdmi_skl_enable_all_pins(hdev); |
---|
2254 | 2286 | hdac_hdmi_skl_enable_dp12(hdev); |
---|
.. | .. |
---|
2266 | 2298 | |
---|
2267 | 2299 | static const struct dev_pm_ops hdac_hdmi_pm = { |
---|
2268 | 2300 | SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) |
---|
2269 | | - .prepare = hdmi_codec_prepare, |
---|
2270 | | - .complete = hdmi_codec_complete, |
---|
| 2301 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume) |
---|
2271 | 2302 | }; |
---|
2272 | 2303 | |
---|
2273 | 2304 | static const struct hda_device_id hdmi_list[] = { |
---|