diff options
author | Dylan Reid <dgreid@chromium.org> | 2014-03-01 03:41:28 +0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-03-01 14:23:16 +0400 |
commit | 7ca954a86b1f2e42af9299eb2ac142bcb5c9bd67 (patch) | |
tree | fd987d727b454bfe4ec6c90dbd05cceffe0a1e7e /sound/pci | |
parent | f43923ff2c97c2ecad668c5133a36c2a9821b5df (diff) | |
download | linux-7ca954a86b1f2e42af9299eb2ac142bcb5c9bd67.tar.xz |
ALSA: hda - Add position_check op
This op will be used by hda_intel to do the position check. Takashi
wisely suggested adding this before moving the interrupt handler to
common HDA code. Having this callback prevents the need to move the
hda_intel specific delayed interrupt handling with the irq.
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 30 | ||||
-rw-r--r-- | sound/pci/hda/hda_priv.h | 2 |
2 files changed, 23 insertions, 9 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 4f693eff531a..53e4b40a72af 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -416,6 +416,23 @@ static void azx_init_pci(struct azx *chip) static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); +/* called from IRQ */ +static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) +{ + int ok; + + ok = azx_position_ok(chip, azx_dev); + if (ok == 1) { + azx_dev->irq_pending = 0; + return ok; + } else if (ok == 0 && chip->bus && chip->bus->workq) { + /* bogus IRQ, process it later */ + azx_dev->irq_pending = 1; + queue_work(chip->bus->workq, &chip->irq_pending_work); + } + return 0; +} + /* * interrupt handler */ @@ -425,7 +442,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) struct azx_dev *azx_dev; u32 status; u8 sd_status; - int i, ok; + int i; #ifdef CONFIG_PM_RUNTIME if (chip->driver_caps & AZX_DCAPS_PM_RUNTIME) @@ -455,17 +472,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) !(sd_status & SD_INT_COMPLETE)) continue; /* check whether this IRQ is really acceptable */ - ok = azx_position_ok(chip, azx_dev); - if (ok == 1) { - azx_dev->irq_pending = 0; + if (!chip->ops->position_check || + chip->ops->position_check(chip, azx_dev)) { spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); - } else if (ok == 0 && chip->bus && chip->bus->workq) { - /* bogus IRQ, process it later */ - azx_dev->irq_pending = 1; - queue_work(chip->bus->workq, - &chip->irq_pending_work); } } } @@ -1821,6 +1832,7 @@ static const struct hda_controller_ops pci_hda_ops = { .substream_alloc_pages = substream_alloc_pages, .substream_free_pages = substream_free_pages, .pcm_mmap_prepare = pcm_mmap_prepare, + .position_check = azx_position_check, }; static int azx_probe(struct pci_dev *pci, diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h index edbe2ebac025..bf3cb33e0dd3 100644 --- a/sound/pci/hda/hda_priv.h +++ b/sound/pci/hda/hda_priv.h @@ -311,6 +311,8 @@ struct hda_controller_ops { struct snd_pcm_substream *substream); void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream, struct vm_area_struct *area); + /* Check if current position is acceptable */ + int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); }; struct azx_pcm { |