ALSA: hda - Add position_check op
authorDylan Reid <dgreid@chromium.org>
Fri, 28 Feb 2014 23:41:28 +0000 (15:41 -0800)
committerTakashi Iwai <tiwai@suse.de>
Sat, 1 Mar 2014 10:23:16 +0000 (11:23 +0100)
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>
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_priv.h

index 4f693eff531abd26d67a4face09996efd7c51252..53e4b40a72af5e6d6a89bac4a9ea77bdba0ca401 100644 (file)
@@ -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,
index edbe2ebac025830fcca050fcac7c343f83c9056f..bf3cb33e0dd3393653e7cd374064064339591846 100644 (file)
@@ -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 {