aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/emu10k1.h4
-rw-r--r--include/sound/hdaudio.h2
-rw-r--r--sound/core/init.c4
-rw-r--r--sound/hda/hdac_device.c35
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c71
-rw-r--r--sound/pci/emu10k1/emupcm.c10
-rw-r--r--sound/pci/emu10k1/memory.c101
-rw-r--r--sound/pci/hda/hda_beep.c17
-rw-r--r--sound/pci/hda/hda_beep.h17
-rw-r--r--sound/pci/hda/hda_codec.c28
-rw-r--r--sound/pci/hda/hda_local.h6
11 files changed, 192 insertions, 103 deletions
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 4f42affe777c..5ebcc51c0a6a 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1710,6 +1710,7 @@ struct snd_emu10k1 {
unsigned int ecard_ctrl; /* ecard control bits */
unsigned int address_mode; /* address mode */
unsigned long dma_mask; /* PCI DMA mask */
+ bool iommu_workaround; /* IOMMU workaround needed */
unsigned int delay_pcm_irq; /* in samples */
int max_cache_pages; /* max memory size / PAGE_SIZE */
struct snd_dma_buffer silent_page; /* silent page */
@@ -1718,7 +1719,6 @@ struct snd_emu10k1 {
struct snd_dma_buffer p16v_buffer;
struct snd_util_memhdr *memhdr; /* page allocation list */
- struct snd_emu10k1_memblk *reserved_page; /* reserved page */
struct list_head mapped_link_head;
struct list_head mapped_order_link_head;
@@ -1878,6 +1878,8 @@ void snd_p16v_resume(struct snd_emu10k1 *emu);
/* memory allocation */
struct snd_util_memblk *snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream);
int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk);
+int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size,
+ struct snd_dma_buffer *dmab);
struct snd_util_memblk *snd_emu10k1_synth_alloc(struct snd_emu10k1 *emu, unsigned int size);
int snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *blk);
int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size);
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 68169e3749de..4c93ff5301bd 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -146,6 +146,8 @@ int snd_hdac_codec_write(struct hdac_device *hdac, hda_nid_t nid,
int flags, unsigned int verb, unsigned int parm);
bool snd_hdac_check_power_state(struct hdac_device *hdac,
hda_nid_t nid, unsigned int target_state);
+unsigned int snd_hdac_sync_power_state(struct hdac_device *hdac,
+ hda_nid_t nid, unsigned int target_state);
/**
* snd_hdac_read_parm - read a codec parameter
* @codec: the codec object
diff --git a/sound/core/init.c b/sound/core/init.c
index 4fa5dd955740..79b4df1c1dc7 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -670,7 +670,7 @@ card_id_show_attr(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_card *card = container_of(dev, struct snd_card, card_dev);
- return snprintf(buf, PAGE_SIZE, "%s\n", card->id);
+ return scnprintf(buf, PAGE_SIZE, "%s\n", card->id);
}
static ssize_t
@@ -710,7 +710,7 @@ card_number_show_attr(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_card *card = container_of(dev, struct snd_card, card_dev);
- return snprintf(buf, PAGE_SIZE, "%i\n", card->number);
+ return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
}
static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL);
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index 06f845e293cb..7ba100bb1c3f 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -3,6 +3,7 @@
*/
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -1064,3 +1065,37 @@ bool snd_hdac_check_power_state(struct hdac_device *hdac,
return (state == target_state);
}
EXPORT_SYMBOL_GPL(snd_hdac_check_power_state);
+/**
+ * snd_hdac_sync_power_state - wait until actual power state matches
+ * with the target state
+ *
+ * @hdac: the HDAC device
+ * @nid: NID to send the command
+ * @target_state: target state to check for
+ *
+ * Return power state or PS_ERROR if codec rejects GET verb.
+ */
+unsigned int snd_hdac_sync_power_state(struct hdac_device *codec,
+ hda_nid_t nid, unsigned int power_state)
+{
+ unsigned long end_time = jiffies + msecs_to_jiffies(500);
+ unsigned int state, actual_state, count;
+
+ for (count = 0; count < 500; count++) {
+ state = snd_hdac_codec_read(codec, nid, 0,
+ AC_VERB_GET_POWER_STATE, 0);
+ if (state & AC_PWRST_ERROR) {
+ msleep(20);
+ break;
+ }
+ actual_state = (state >> 4) & 0x0f;
+ if (actual_state == power_state)
+ break;
+ if (time_after_eq(jiffies, end_time))
+ break;
+ /* wait until the codec reachs to the target state */
+ msleep(1);
+ }
+ return state;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_sync_power_state);
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index ccf4415a1c7b..18267de3a269 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/iommu.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
@@ -1272,12 +1273,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
release_firmware(emu->dock_fw);
if (emu->irq >= 0)
free_irq(emu->irq, emu);
- /* remove reserved page */
- if (emu->reserved_page) {
- snd_emu10k1_synth_free(emu,
- (struct snd_util_memblk *)emu->reserved_page);
- emu->reserved_page = NULL;
- }
snd_util_memhdr_free(emu->memhdr);
if (emu->silent_page.area)
snd_dma_free_pages(&emu->silent_page);
@@ -1764,6 +1759,38 @@ static struct snd_emu_chip_details emu_chip_details[] = {
{ } /* terminator */
};
+/*
+ * The chip (at least the Audigy 2 CA0102 chip, but most likely others, too)
+ * has a problem that from time to time it likes to do few DMA reads a bit
+ * beyond its normal allocation and gets very confused if these reads get
+ * blocked by a IOMMU.
+ *
+ * This behaviour has been observed for the first (reserved) page
+ * (for which it happens multiple times at every playback), often for various
+ * synth pages and sometimes for PCM playback buffers and the page table
+ * memory itself.
+ *
+ * As a workaround let's widen these DMA allocations by an extra page if we
+ * detect that the device is behind a non-passthrough IOMMU.
+ */
+static void snd_emu10k1_detect_iommu(struct snd_emu10k1 *emu)
+{
+ struct iommu_domain *domain;
+
+ emu->iommu_workaround = false;
+
+ if (!iommu_present(emu->card->dev->bus))
+ return;
+
+ domain = iommu_get_domain_for_dev(emu->card->dev);
+ if (domain && domain->type == IOMMU_DOMAIN_IDENTITY)
+ return;
+
+ dev_notice(emu->card->dev,
+ "non-passthrough IOMMU detected, widening DMA allocations");
+ emu->iommu_workaround = true;
+}
+
int snd_emu10k1_create(struct snd_card *card,
struct pci_dev *pci,
unsigned short extin_mask,
@@ -1776,6 +1803,7 @@ int snd_emu10k1_create(struct snd_card *card,
struct snd_emu10k1 *emu;
int idx, err;
int is_audigy;
+ size_t page_table_size;
unsigned int silent_page;
const struct snd_emu_chip_details *c;
static struct snd_device_ops ops = {
@@ -1873,12 +1901,13 @@ int snd_emu10k1_create(struct snd_card *card,
is_audigy = emu->audigy = c->emu10k2_chip;
+ snd_emu10k1_detect_iommu(emu);
+
/* set addressing mode */
emu->address_mode = is_audigy ? 0 : 1;
/* set the DMA transfer mask */
emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK;
- if (dma_set_mask(&pci->dev, emu->dma_mask) < 0 ||
- dma_set_coherent_mask(&pci->dev, emu->dma_mask) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, emu->dma_mask) < 0) {
dev_err(card->dev,
"architecture does not support PCI busmaster DMA with mask 0x%lx\n",
emu->dma_mask);
@@ -1900,11 +1929,17 @@ int snd_emu10k1_create(struct snd_card *card,
emu->port = pci_resource_start(pci, 0);
emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) {
+
+ page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 :
+ MAXPAGES0);
+ if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size,
+ &emu->ptb_pages) < 0) {
err = -ENOMEM;
goto error;
}
+ dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n",
+ (unsigned long)emu->ptb_pages.addr,
+ (unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes));
emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *));
emu->page_addr_table = vmalloc(emu->max_cache_pages *
@@ -1914,11 +1949,16 @@ int snd_emu10k1_create(struct snd_card *card,
goto error;
}
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- EMUPAGESIZE, &emu->silent_page) < 0) {
+ if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE,
+ &emu->silent_page) < 0) {
err = -ENOMEM;
goto error;
}
+ dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n",
+ (unsigned long)emu->silent_page.addr,
+ (unsigned long)(emu->silent_page.addr +
+ emu->silent_page.bytes));
+
emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
if (emu->memhdr == NULL) {
err = -ENOMEM;
@@ -1993,13 +2033,8 @@ int snd_emu10k1_create(struct snd_card *card,
SPCS_GENERATIONSTATUS | 0x00001200 |
0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
- emu->reserved_page = (struct snd_emu10k1_memblk *)
- snd_emu10k1_synth_alloc(emu, 4096);
- if (emu->reserved_page)
- emu->reserved_page->map_locked = 1;
-
/* Clear silent pages and set up pointers */
- memset(emu->silent_page.area, 0, PAGE_SIZE);
+ memset(emu->silent_page.area, 0, emu->silent_page.bytes);
silent_page = emu->silent_page.addr << emu->address_mode;
for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++)
((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 2683b9717215..cefe613ef7b7 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -411,12 +411,20 @@ static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_emu10k1_pcm *epcm = runtime->private_data;
+ size_t alloc_size;
int err;
if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
return err;
- if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
+
+ alloc_size = params_buffer_bytes(hw_params);
+ if (emu->iommu_workaround)
+ alloc_size += EMUPAGESIZE;
+ err = snd_pcm_lib_malloc_pages(substream, alloc_size);
+ if (err < 0)
return err;
+ if (emu->iommu_workaround && runtime->dma_bytes >= EMUPAGESIZE)
+ runtime->dma_bytes -= EMUPAGESIZE;
if (err > 0) { /* change */
int mapped;
if (epcm->memblk != NULL)
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index 4f1f69be1865..5865f3b90b34 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -34,7 +34,10 @@
* aligned pages in others
*/
#define __set_ptb_entry(emu,page,addr) \
- (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
+ (((__le32 *)(emu)->ptb_pages.area)[page] = \
+ cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
+#define __get_ptb_entry(emu, page) \
+ (le32_to_cpu(((__le32 *)(emu)->ptb_pages.area)[page]))
#define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE)
#define MAX_ALIGN_PAGES0 (MAXPAGES0 / UNIT_PAGES)
@@ -44,8 +47,7 @@
/* get offset address from aligned page */
#define aligned_page_offset(page) ((page) << PAGE_SHIFT)
-#if PAGE_SIZE == 4096
-/* page size == EMUPAGESIZE */
+#if PAGE_SIZE == EMUPAGESIZE && !IS_ENABLED(CONFIG_DYNAMIC_DEBUG)
/* fill PTB entrie(s) corresponding to page with addr */
#define set_ptb_entry(emu,page,addr) __set_ptb_entry(emu,page,addr)
/* fill PTB entrie(s) corresponding to page with silence pointer */
@@ -58,6 +60,8 @@ static inline void set_ptb_entry(struct snd_emu10k1 *emu, int page, dma_addr_t a
page *= UNIT_PAGES;
for (i = 0; i < UNIT_PAGES; i++, page++) {
__set_ptb_entry(emu, page, addr);
+ dev_dbg(emu->card->dev, "mapped page %d to entry %.8x\n", page,
+ (unsigned int)__get_ptb_entry(emu, page));
addr += EMUPAGESIZE;
}
}
@@ -65,9 +69,12 @@ static inline void set_silent_ptb(struct snd_emu10k1 *emu, int page)
{
int i;
page *= UNIT_PAGES;
- for (i = 0; i < UNIT_PAGES; i++, page++)
+ for (i = 0; i < UNIT_PAGES; i++, page++) {
/* do not increment ptr */
__set_ptb_entry(emu, page, emu->silent_page.addr);
+ dev_dbg(emu->card->dev, "mapped silent page %d to entry %.8x\n",
+ page, (unsigned int)__get_ptb_entry(emu, page));
+ }
}
#endif /* PAGE_SIZE */
@@ -102,7 +109,7 @@ static void emu10k1_memblk_init(struct snd_emu10k1_memblk *blk)
*/
static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct list_head **nextp)
{
- int page = 0, found_page = -ENOMEM;
+ int page = 1, found_page = -ENOMEM;
int max_size = npages;
int size;
struct list_head *candidate = &emu->mapped_link_head;
@@ -147,6 +154,10 @@ static int map_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
page = search_empty_map_area(emu, blk->pages, &next);
if (page < 0) /* not found */
return page;
+ if (page == 0) {
+ dev_err(emu->card->dev, "trying to map zero (reserved) page\n");
+ return -EINVAL;
+ }
/* insert this block in the proper position of mapped list */
list_add_tail(&blk->mapped_link, next);
/* append this as a newest block in order list */
@@ -177,7 +188,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
q = get_emu10k1_memblk(p, mapped_link);
start_page = q->mapped_page + q->pages;
} else
- start_page = 0;
+ start_page = 1;
if ((p = blk->mapped_link.next) != &emu->mapped_link_head) {
q = get_emu10k1_memblk(p, mapped_link);
end_page = q->mapped_page;
@@ -366,6 +377,33 @@ int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk)
return snd_emu10k1_synth_free(emu, blk);
}
+/*
+ * allocate DMA pages, widening the allocation if necessary
+ *
+ * See the comment above snd_emu10k1_detect_iommu() in emu10k1_main.c why
+ * this might be needed.
+ *
+ * If you modify this function check whether __synth_free_pages() also needs
+ * changes.
+ */
+int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size,
+ struct snd_dma_buffer *dmab)
+{
+ if (emu->iommu_workaround) {
+ size_t npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ size_t size_real = npages * PAGE_SIZE;
+
+ /*
+ * The device has been observed to accesses up to 256 extra
+ * bytes, but use 1k to be safe.
+ */
+ if (size_real < size + 1024)
+ size += PAGE_SIZE;
+ }
+
+ return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci), size, dmab);
+}
/*
* memory allocation using multiple pages (for synth)
@@ -450,10 +488,27 @@ static void get_single_page_range(struct snd_util_memhdr *hdr,
static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page,
int last_page)
{
+ struct snd_dma_buffer dmab;
int page;
+ dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+ dmab.dev.dev = snd_dma_pci_data(emu->pci);
+
for (page = first_page; page <= last_page; page++) {
- free_page((unsigned long)emu->page_ptr_table[page]);
+ if (emu->page_ptr_table[page] == NULL)
+ continue;
+ dmab.area = emu->page_ptr_table[page];
+ dmab.addr = emu->page_addr_table[page];
+
+ /*
+ * please keep me in sync with logic in
+ * snd_emu10k1_alloc_pages_maybe_wider()
+ */
+ dmab.bytes = PAGE_SIZE;
+ if (emu->iommu_workaround)
+ dmab.bytes *= 2;
+
+ snd_dma_free_pages(&dmab);
emu->page_addr_table[page] = 0;
emu->page_ptr_table[page] = NULL;
}
@@ -465,30 +520,30 @@ static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page,
static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int page, first_page, last_page;
+ struct snd_dma_buffer dmab;
emu10k1_memblk_init(blk);
get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
/* allocate kernel pages */
for (page = first_page; page <= last_page; page++) {
- /* first try to allocate from <4GB zone */
- struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 |
- __GFP_NOWARN);
- if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) {
- if (p)
- __free_page(p);
- /* try to allocate from <16MB zone */
- p = alloc_page(GFP_ATOMIC | GFP_DMA |
- __GFP_NORETRY | /* no OOM-killer */
- __GFP_NOWARN);
+ if (snd_emu10k1_alloc_pages_maybe_wider(emu, PAGE_SIZE,
+ &dmab) < 0)
+ goto __fail;
+ if (!is_valid_page(emu, dmab.addr)) {
+ snd_dma_free_pages(&dmab);
+ goto __fail;
}
- if (!p) {
- __synth_free_pages(emu, first_page, page - 1);
- return -ENOMEM;
- }
- emu->page_addr_table[page] = page_to_phys(p);
- emu->page_ptr_table[page] = page_address(p);
+ emu->page_addr_table[page] = dmab.addr;
+ emu->page_ptr_table[page] = dmab.area;
}
return 0;
+
+__fail:
+ /* release allocated pages */
+ last_page = page - 1;
+ __synth_free_pages(emu, first_page, last_page);
+
+ return -ENOMEM;
}
/*
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index c397e7da0eac..066b5b59c4d7 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Digital Beep Input Interface for HD-audio codec
*
- * Author: Matt Ranostay <[email protected]>
+ * Author: Matt Ranostay <[email protected]>
* Copyright (c) 2008 Embedded Alley Solutions Inc
- *
- * This driver is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/input.h>
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index 1052ad380e97..d1a6a9c1329a 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Digital Beep Input Interface for HD-audio codec
*
- * Author: Matt Ranostay <[email protected]>
+ * Author: Matt Ranostay <[email protected]>
* Copyright (c) 2008 Embedded Alley Solutions Inc
- *
- * This driver is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __SOUND_HDA_BEEP_H
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e018ecbf78a8..5bc3a7468e17 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2702,32 +2702,6 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
}
EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
-/*
- * wait until the state is reached, returns the current state
- */
-static unsigned int hda_sync_power_state(struct hda_codec *codec,
- hda_nid_t fg,
- unsigned int power_state)
-{
- unsigned long end_time = jiffies + msecs_to_jiffies(500);
- unsigned int state, actual_state;
-
- for (;;) {
- state = snd_hda_codec_read(codec, fg, 0,
- AC_VERB_GET_POWER_STATE, 0);
- if (state & AC_PWRST_ERROR)
- break;
- actual_state = (state >> 4) & 0x0f;
- if (actual_state == power_state)
- break;
- if (time_after_eq(jiffies, end_time))
- break;
- /* wait until the codec reachs to the target state */
- msleep(1);
- }
- return state;
-}
-
/**
* snd_hda_codec_eapd_power_filter - A power filter callback for EAPD
* @codec: the HDA codec
@@ -2790,7 +2764,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
state);
snd_hda_codec_set_power_to_all(codec, fg, power_state);
}
- state = hda_sync_power_state(codec, fg, power_state);
+ state = snd_hda_sync_power_state(codec, fg, power_state);
if (!(state & AC_PWRST_ERROR))
break;
}
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 5b5c324c99b9..321e78baa63c 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -622,7 +622,11 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
{
return snd_hdac_check_power_state(&codec->core, nid, target_state);
}
-
+static inline bool snd_hda_sync_power_state(struct hda_codec *codec,
+ hda_nid_t nid, unsigned int target_state)
+{
+ return snd_hdac_sync_power_state(&codec->core, nid, target_state);
+}
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state);