Browse Source

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>
Dylan Reid 11 years ago
parent
commit
7ca954a86b
2 changed files with 23 additions and 9 deletions
  1. 21 9
      sound/pci/hda/hda_intel.c
  2. 2 0
      sound/pci/hda/hda_priv.h

+ 21 - 9
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,

+ 2 - 0
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 {