diff options
Diffstat (limited to 'sound/hda')
-rw-r--r-- | sound/hda/ext/hdac_ext_controller.c | 37 | ||||
-rw-r--r-- | sound/hda/hdac_bus.c | 23 | ||||
-rw-r--r-- | sound/hda/hdac_controller.c | 14 |
3 files changed, 74 insertions, 0 deletions
diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index b0c0ef824d7d..a9bd39b93697 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -332,3 +332,40 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put); + +static void hdac_ext_codec_link_up(struct hdac_device *codec) +{ + const char *devname = dev_name(&codec->dev); + struct hdac_ext_link *hlink = + snd_hdac_ext_bus_get_link(codec->bus, devname); + + if (hlink) + snd_hdac_ext_bus_link_get(codec->bus, hlink); +} + +static void hdac_ext_codec_link_down(struct hdac_device *codec) +{ + const char *devname = dev_name(&codec->dev); + struct hdac_ext_link *hlink = + snd_hdac_ext_bus_get_link(codec->bus, devname); + + if (hlink) + snd_hdac_ext_bus_link_put(codec->bus, hlink); +} + +void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable) +{ + struct hdac_bus *bus = codec->bus; + bool oldstate = test_bit(codec->addr, &bus->codec_powered); + + if (enable == oldstate) + return; + + snd_hdac_bus_link_power(codec, enable); + + if (enable) + hdac_ext_codec_link_up(codec); + else + hdac_ext_codec_link_down(codec); +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power); diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 9766f6af8743..71db8592b33d 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -17,6 +17,7 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work); static const struct hdac_bus_ops default_ops = { .command = snd_hdac_bus_send_cmd, .get_response = snd_hdac_bus_get_response, + .link_power = snd_hdac_bus_link_power, }; /** @@ -264,3 +265,25 @@ void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, } EXPORT_SYMBOL_GPL(snd_hdac_aligned_write); #endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ + +void snd_hdac_codec_link_up(struct hdac_device *codec) +{ + struct hdac_bus *bus = codec->bus; + + if (bus->ops->link_power) + bus->ops->link_power(codec, true); + else + snd_hdac_bus_link_power(codec, true); +} +EXPORT_SYMBOL_GPL(snd_hdac_codec_link_up); + +void snd_hdac_codec_link_down(struct hdac_device *codec) +{ + struct hdac_bus *bus = codec->bus; + + if (bus->ops->link_power) + bus->ops->link_power(codec, false); + else + snd_hdac_bus_link_power(codec, false); +} +EXPORT_SYMBOL_GPL(snd_hdac_codec_link_down); diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index b98449fd92f3..062da7a7a586 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -648,3 +648,17 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus) snd_dma_free_pages(&bus->posbuf); } EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); + +/** + * snd_hdac_bus_link_power - power up/down codec link + * @codec: HD-audio device + * @enable: whether to power-up the link + */ +void snd_hdac_bus_link_power(struct hdac_device *codec, bool enable) +{ + if (enable) + set_bit(codec->addr, &codec->bus->codec_powered); + else + clear_bit(codec->addr, &codec->bus->codec_powered); +} +EXPORT_SYMBOL_GPL(snd_hdac_bus_link_power); |