diff options
author | Mark Brown <broonie@kernel.org> | 2016-05-13 14:26:22 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-05-13 14:26:22 +0100 |
commit | c988e26130132813e3550a7b97ab2ed2ae0455eb (patch) | |
tree | 9259bd3e05c9a3f607051501ece7c252785f2e22 /sound/hda | |
parent | 35302156ea791f96bdc7e0ca3c44cb25341fbcb1 (diff) | |
parent | b2047e996cd88d36eb0f4e84fe6aedab831a4b31 (diff) | |
download | op-kernel-dev-c988e26130132813e3550a7b97ab2ed2ae0455eb.zip op-kernel-dev-c988e26130132813e3550a7b97ab2ed2ae0455eb.tar.gz |
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
Diffstat (limited to 'sound/hda')
-rw-r--r-- | sound/hda/ext/hdac_ext_bus.c | 3 | ||||
-rw-r--r-- | sound/hda/ext/hdac_ext_controller.c | 66 |
2 files changed, 69 insertions, 0 deletions
diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 2433f7c..3b7ae24 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -105,6 +105,9 @@ int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev, INIT_LIST_HEAD(&ebus->hlink_list); ebus->idx = idx++; + mutex_init(&ebus->lock); + ebus->cmd_dma_state = true; + return 0; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init); diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 548cc1e..860f8ca 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -186,6 +186,9 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) hlink->lcaps = readl(hlink->ml_addr + AZX_REG_ML_LCAP); hlink->lsdiid = readw(hlink->ml_addr + AZX_REG_ML_LSDIID); + /* since link in On, update the ref */ + hlink->ref_count = 1; + list_add_tail(&hlink->list, &ebus->hlink_list); } @@ -327,3 +330,66 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus) return 0; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all); + +int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus, + struct hdac_ext_link *link) +{ + int ret = 0; + + mutex_lock(&ebus->lock); + + /* + * if we move from 0 to 1, count will be 1 so power up this link + * as well, also check the dma status and trigger that + */ + if (++link->ref_count == 1) { + if (!ebus->cmd_dma_state) { + snd_hdac_bus_init_cmd_io(&ebus->bus); + ebus->cmd_dma_state = true; + } + + ret = snd_hdac_ext_bus_link_power_up(link); + } + + mutex_unlock(&ebus->lock); + return ret; +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_get); + +int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, + struct hdac_ext_link *link) +{ + int ret = 0; + struct hdac_ext_link *hlink; + bool link_up = false; + + mutex_lock(&ebus->lock); + + /* + * if we move from 1 to 0, count will be 0 + * so power down this link as well + */ + if (--link->ref_count == 0) { + ret = snd_hdac_ext_bus_link_power_down(link); + + /* + * now check if all links are off, if so turn off + * cmd dma as well + */ + list_for_each_entry(hlink, &ebus->hlink_list, list) { + if (hlink->ref_count) { + link_up = true; + break; + } + } + + if (!link_up) { + snd_hdac_bus_stop_cmd_io(&ebus->bus); + ebus->cmd_dma_state = false; + } + } + + mutex_unlock(&ebus->lock); + return ret; +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put); |