diff options
-rw-r--r-- | sound/soc/codecs/hdac_hdmi.c | 83 |
1 files changed, 38 insertions, 45 deletions
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index da3432c9f64d..aaa038ffc8a5 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c | |||
@@ -1420,32 +1420,39 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec) | |||
1420 | } | 1420 | } |
1421 | 1421 | ||
1422 | #ifdef CONFIG_PM | 1422 | #ifdef CONFIG_PM |
1423 | static int hdmi_codec_prepare(struct device *dev) | ||
1424 | { | ||
1425 | struct hdac_ext_device *edev = to_hda_ext_device(dev); | ||
1426 | struct hdac_device *hdac = &edev->hdac; | ||
1427 | |||
1428 | pm_runtime_get_sync(&edev->hdac.dev); | ||
1429 | |||
1430 | /* | ||
1431 | * Power down afg. | ||
1432 | * codec_read is preferred over codec_write to set the power state. | ||
1433 | * This way verb is send to set the power state and response | ||
1434 | * is received. So setting power state is ensured without using loop | ||
1435 | * to read the state. | ||
1436 | */ | ||
1437 | snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE, | ||
1438 | AC_PWRST_D3); | ||
1439 | |||
1440 | return 0; | ||
1441 | } | ||
1442 | |||
1423 | static void hdmi_codec_complete(struct device *dev) | 1443 | static void hdmi_codec_complete(struct device *dev) |
1424 | { | 1444 | { |
1425 | struct hdac_ext_device *edev = to_hda_ext_device(dev); | 1445 | struct hdac_ext_device *edev = to_hda_ext_device(dev); |
1426 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1446 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1427 | struct hdac_hdmi_pin *pin; | 1447 | struct hdac_hdmi_pin *pin; |
1428 | struct hdac_device *hdac = &edev->hdac; | 1448 | struct hdac_device *hdac = &edev->hdac; |
1429 | struct hdac_bus *bus = hdac->bus; | ||
1430 | int err; | ||
1431 | unsigned long timeout; | ||
1432 | |||
1433 | hdac_hdmi_skl_enable_all_pins(&edev->hdac); | ||
1434 | hdac_hdmi_skl_enable_dp12(&edev->hdac); | ||
1435 | 1449 | ||
1436 | /* Power up afg */ | 1450 | /* Power up afg */ |
1437 | if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)) { | 1451 | snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE, |
1438 | 1452 | AC_PWRST_D0); | |
1439 | snd_hdac_codec_write(hdac, hdac->afg, 0, | ||
1440 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
1441 | 1453 | ||
1442 | /* Wait till power state is set to D0 */ | 1454 | hdac_hdmi_skl_enable_all_pins(&edev->hdac); |
1443 | timeout = jiffies + msecs_to_jiffies(1000); | 1455 | hdac_hdmi_skl_enable_dp12(&edev->hdac); |
1444 | while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0) | ||
1445 | && time_before(jiffies, timeout)) { | ||
1446 | msleep(50); | ||
1447 | } | ||
1448 | } | ||
1449 | 1456 | ||
1450 | /* | 1457 | /* |
1451 | * As the ELD notify callback request is not entertained while the | 1458 | * As the ELD notify callback request is not entertained while the |
@@ -1455,18 +1462,10 @@ static void hdmi_codec_complete(struct device *dev) | |||
1455 | list_for_each_entry(pin, &hdmi->pin_list, head) | 1462 | list_for_each_entry(pin, &hdmi->pin_list, head) |
1456 | hdac_hdmi_present_sense(pin, 1); | 1463 | hdac_hdmi_present_sense(pin, 1); |
1457 | 1464 | ||
1458 | /* | 1465 | pm_runtime_put_sync(&edev->hdac.dev); |
1459 | * Codec power is turned ON during controller resume. | ||
1460 | * Turn it OFF here | ||
1461 | */ | ||
1462 | err = snd_hdac_display_power(bus, false); | ||
1463 | if (err < 0) { | ||
1464 | dev_err(bus->dev, | ||
1465 | "Cannot turn OFF display power on i915, err: %d\n", | ||
1466 | err); | ||
1467 | } | ||
1468 | } | 1466 | } |
1469 | #else | 1467 | #else |
1468 | #define hdmi_codec_prepare NULL | ||
1470 | #define hdmi_codec_complete NULL | 1469 | #define hdmi_codec_complete NULL |
1471 | #endif | 1470 | #endif |
1472 | 1471 | ||
@@ -1557,7 +1556,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) | |||
1557 | struct hdac_ext_device *edev = to_hda_ext_device(dev); | 1556 | struct hdac_ext_device *edev = to_hda_ext_device(dev); |
1558 | struct hdac_device *hdac = &edev->hdac; | 1557 | struct hdac_device *hdac = &edev->hdac; |
1559 | struct hdac_bus *bus = hdac->bus; | 1558 | struct hdac_bus *bus = hdac->bus; |
1560 | unsigned long timeout; | ||
1561 | int err; | 1559 | int err; |
1562 | 1560 | ||
1563 | dev_dbg(dev, "Enter: %s\n", __func__); | 1561 | dev_dbg(dev, "Enter: %s\n", __func__); |
@@ -1566,20 +1564,15 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) | |||
1566 | if (!bus) | 1564 | if (!bus) |
1567 | return 0; | 1565 | return 0; |
1568 | 1566 | ||
1569 | /* Power down afg */ | 1567 | /* |
1570 | if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3)) { | 1568 | * Power down afg. |
1571 | snd_hdac_codec_write(hdac, hdac->afg, 0, | 1569 | * codec_read is preferred over codec_write to set the power state. |
1572 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 1570 | * This way verb is send to set the power state and response |
1573 | 1571 | * is received. So setting power state is ensured without using loop | |
1574 | /* Wait till power state is set to D3 */ | 1572 | * to read the state. |
1575 | timeout = jiffies + msecs_to_jiffies(1000); | 1573 | */ |
1576 | while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3) | 1574 | snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE, |
1577 | && time_before(jiffies, timeout)) { | 1575 | AC_PWRST_D3); |
1578 | |||
1579 | msleep(50); | ||
1580 | } | ||
1581 | } | ||
1582 | |||
1583 | err = snd_hdac_display_power(bus, false); | 1576 | err = snd_hdac_display_power(bus, false); |
1584 | if (err < 0) { | 1577 | if (err < 0) { |
1585 | dev_err(bus->dev, "Cannot turn on display power on i915\n"); | 1578 | dev_err(bus->dev, "Cannot turn on display power on i915\n"); |
@@ -1612,9 +1605,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev) | |||
1612 | hdac_hdmi_skl_enable_dp12(&edev->hdac); | 1605 | hdac_hdmi_skl_enable_dp12(&edev->hdac); |
1613 | 1606 | ||
1614 | /* Power up afg */ | 1607 | /* Power up afg */ |
1615 | if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)) | 1608 | snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE, |
1616 | snd_hdac_codec_write(hdac, hdac->afg, 0, | 1609 | AC_PWRST_D0); |
1617 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
1618 | 1610 | ||
1619 | return 0; | 1611 | return 0; |
1620 | } | 1612 | } |
@@ -1625,6 +1617,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev) | |||
1625 | 1617 | ||
1626 | static const struct dev_pm_ops hdac_hdmi_pm = { | 1618 | static const struct dev_pm_ops hdac_hdmi_pm = { |
1627 | SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) | 1619 | SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) |
1620 | .prepare = hdmi_codec_prepare, | ||
1628 | .complete = hdmi_codec_complete, | 1621 | .complete = hdmi_codec_complete, |
1629 | }; | 1622 | }; |
1630 | 1623 | ||