From 9fc7c862e78ba8bec142935673227f2463aa05a5 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Thu, 14 Apr 2016 10:07:29 +0530 Subject: ALSA: hda - add helper to get channels from cap bits This helper is copied from legacy hda driver. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Acked-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/hda/local.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sound/hda') diff --git a/sound/hda/local.h b/sound/hda/local.h index d692f417ddc0..0d5bb159d538 100644 --- a/sound/hda/local.h +++ b/sound/hda/local.h @@ -16,6 +16,16 @@ static inline int get_wcaps_type(unsigned int wcaps) return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; } +static inline unsigned int get_wcaps_channels(u32 wcaps) +{ + unsigned int chans; + + chans = (wcaps & AC_WCAP_CHAN_CNT_EXT) >> 13; + chans = (chans + 1) * 2; + + return chans; +} + extern const struct attribute_group *hdac_dev_attr_groups[]; int hda_widget_sysfs_init(struct hdac_device *codec); void hda_widget_sysfs_exit(struct hdac_device *codec); -- cgit From 4446085d21e75dd6c0c45577f12db0bd7c7bf35f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 12 May 2016 08:58:53 +0530 Subject: ALSA: hdac: add link pm and ref counting The HDA links can be switched off when not is use, similarly command DMA can be stopped as well. This calls for a reference counting mechanism on the link by it's users to manage the link power. The DMA can be turned off when all links are off For this we add two APIs snd_hdac_ext_bus_link_get snd_hdac_ext_bus_link_put They help users to turn up/down link and manage the DMA as well Signed-off-by: Jeeja KP Signed-off-by: Vinod Koul Acked-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/hda/ext/hdac_ext_bus.c | 3 ++ sound/hda/ext/hdac_ext_controller.c | 66 +++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) (limited to 'sound/hda') diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 2433f7c81472..3b7ae24900fd 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 548cc1e4114b..860f8cad6602 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); -- cgit