aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_intel.c124
1 files changed, 106 insertions, 18 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index b3a618eb42cd..6ba7ac01d9f6 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -285,6 +285,7 @@ struct azx_dev {
285 u32 *posbuf; /* position buffer pointer */ 285 u32 *posbuf; /* position buffer pointer */
286 286
287 unsigned int bufsize; /* size of the play buffer in bytes */ 287 unsigned int bufsize; /* size of the play buffer in bytes */
288 unsigned int period_bytes; /* size of the period in bytes */
288 unsigned int frags; /* number for period in the play buffer */ 289 unsigned int frags; /* number for period in the play buffer */
289 unsigned int fifo_size; /* FIFO size */ 290 unsigned int fifo_size; /* FIFO size */
290 291
@@ -301,11 +302,10 @@ struct azx_dev {
301 */ 302 */
302 unsigned char stream_tag; /* assigned stream */ 303 unsigned char stream_tag; /* assigned stream */
303 unsigned char index; /* stream index */ 304 unsigned char index; /* stream index */
304 /* for sanity check of position buffer */
305 unsigned int period_intr;
306 305
307 unsigned int opened :1; 306 unsigned int opened :1;
308 unsigned int running :1; 307 unsigned int running :1;
308 unsigned int irq_pending: 1;
309}; 309};
310 310
311/* CORB/RIRB */ 311/* CORB/RIRB */
@@ -369,6 +369,9 @@ struct azx {
369 369
370 /* for debugging */ 370 /* for debugging */
371 unsigned int last_cmd; /* last issued command (to sync) */ 371 unsigned int last_cmd; /* last issued command (to sync) */
372
373 /* for pending irqs */
374 struct work_struct irq_pending_work;
372}; 375};
373 376
374/* driver types */ 377/* driver types */
@@ -908,6 +911,8 @@ static void azx_init_pci(struct azx *chip)
908} 911}
909 912
910 913
914static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
915
911/* 916/*
912 * interrupt handler 917 * interrupt handler
913 */ 918 */
@@ -930,11 +935,18 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
930 azx_dev = &chip->azx_dev[i]; 935 azx_dev = &chip->azx_dev[i];
931 if (status & azx_dev->sd_int_sta_mask) { 936 if (status & azx_dev->sd_int_sta_mask) {
932 azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); 937 azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
933 if (azx_dev->substream && azx_dev->running) { 938 if (!azx_dev->substream || !azx_dev->running)
934 azx_dev->period_intr++; 939 continue;
940 /* check whether this IRQ is really acceptable */
941 if (azx_position_ok(chip, azx_dev)) {
942 azx_dev->irq_pending = 0;
935 spin_unlock(&chip->reg_lock); 943 spin_unlock(&chip->reg_lock);
936 snd_pcm_period_elapsed(azx_dev->substream); 944 snd_pcm_period_elapsed(azx_dev->substream);
937 spin_lock(&chip->reg_lock); 945 spin_lock(&chip->reg_lock);
946 } else {
947 /* bogus IRQ, process it later */
948 azx_dev->irq_pending = 1;
949 schedule_work(&chip->irq_pending_work);
938 } 950 }
939 } 951 }
940 } 952 }
@@ -973,6 +985,7 @@ static int azx_setup_periods(struct snd_pcm_substream *substream,
973 azx_sd_writel(azx_dev, SD_BDLPU, 0); 985 azx_sd_writel(azx_dev, SD_BDLPU, 0);
974 986
975 period_bytes = snd_pcm_lib_period_bytes(substream); 987 period_bytes = snd_pcm_lib_period_bytes(substream);
988 azx_dev->period_bytes = period_bytes;
976 periods = azx_dev->bufsize / period_bytes; 989 periods = azx_dev->bufsize / period_bytes;
977 990
978 /* program the initial BDL entries */ 991 /* program the initial BDL entries */
@@ -1421,27 +1434,16 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
1421 return 0; 1434 return 0;
1422} 1435}
1423 1436
1424static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) 1437static unsigned int azx_get_position(struct azx *chip,
1438 struct azx_dev *azx_dev)
1425{ 1439{
1426 struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
1427 struct azx *chip = apcm->chip;
1428 struct azx_dev *azx_dev = get_azx_dev(substream);
1429 unsigned int pos; 1440 unsigned int pos;
1430 1441
1431 if (chip->position_fix == POS_FIX_POSBUF || 1442 if (chip->position_fix == POS_FIX_POSBUF ||
1432 chip->position_fix == POS_FIX_AUTO) { 1443 chip->position_fix == POS_FIX_AUTO) {
1433 /* use the position buffer */ 1444 /* use the position buffer */
1434 pos = le32_to_cpu(*azx_dev->posbuf); 1445 pos = le32_to_cpu(*azx_dev->posbuf);
1435 if (chip->position_fix == POS_FIX_AUTO &&
1436 azx_dev->period_intr == 1 && !pos) {
1437 printk(KERN_WARNING
1438 "hda-intel: Invalid position buffer, "
1439 "using LPIB read method instead.\n");
1440 chip->position_fix = POS_FIX_NONE;
1441 goto read_lpib;
1442 }
1443 } else { 1446 } else {
1444 read_lpib:
1445 /* read LPIB */ 1447 /* read LPIB */
1446 pos = azx_sd_readl(azx_dev, SD_LPIB); 1448 pos = azx_sd_readl(azx_dev, SD_LPIB);
1447 if (chip->position_fix == POS_FIX_FIFO) 1449 if (chip->position_fix == POS_FIX_FIFO)
@@ -1449,7 +1451,90 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
1449 } 1451 }
1450 if (pos >= azx_dev->bufsize) 1452 if (pos >= azx_dev->bufsize)
1451 pos = 0; 1453 pos = 0;
1452 return bytes_to_frames(substream->runtime, pos); 1454 return pos;
1455}
1456
1457static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
1458{
1459 struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
1460 struct azx *chip = apcm->chip;
1461 struct azx_dev *azx_dev = get_azx_dev(substream);
1462 return bytes_to_frames(substream->runtime,
1463 azx_get_position(chip, azx_dev));
1464}
1465
1466/*
1467 * Check whether the current DMA position is acceptable for updating
1468 * periods. Returns non-zero if it's OK.
1469 *
1470 * Many HD-audio controllers appear pretty inaccurate about
1471 * the update-IRQ timing. The IRQ is issued before actually the
1472 * data is processed. So, we need to process it afterwords in a
1473 * workqueue.
1474 */
1475static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
1476{
1477 unsigned int pos;
1478
1479 pos = azx_get_position(chip, azx_dev);
1480 if (chip->position_fix == POS_FIX_AUTO) {
1481 if (!pos) {
1482 printk(KERN_WARNING
1483 "hda-intel: Invalid position buffer, "
1484 "using LPIB read method instead.\n");
1485 chip->position_fix = POS_FIX_NONE;
1486 pos = azx_get_position(chip, azx_dev);
1487 } else
1488 chip->position_fix = POS_FIX_POSBUF;
1489 }
1490
1491 if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
1492 return 0; /* NG - it's below the period boundary */
1493 return 1; /* OK, it's fine */
1494}
1495
1496/*
1497 * The work for pending PCM period updates.
1498 */
1499static void azx_irq_pending_work(struct work_struct *work)
1500{
1501 struct azx *chip = container_of(work, struct azx, irq_pending_work);
1502 int i, pending;
1503
1504 for (;;) {
1505 pending = 0;
1506 spin_lock_irq(&chip->reg_lock);
1507 for (i = 0; i < chip->num_streams; i++) {
1508 struct azx_dev *azx_dev = &chip->azx_dev[i];
1509 if (!azx_dev->irq_pending ||
1510 !azx_dev->substream ||
1511 !azx_dev->running)
1512 continue;
1513 if (azx_position_ok(chip, azx_dev)) {
1514 azx_dev->irq_pending = 0;
1515 spin_unlock(&chip->reg_lock);
1516 snd_pcm_period_elapsed(azx_dev->substream);
1517 spin_lock(&chip->reg_lock);
1518 } else
1519 pending++;
1520 }
1521 spin_unlock_irq(&chip->reg_lock);
1522 if (!pending)
1523 return;
1524 cond_resched();
1525 }
1526}
1527
1528/* clear irq_pending flags and assure no on-going workq */
1529static void azx_clear_irq_pending(struct azx *chip)
1530{
1531 int i;
1532
1533 spin_lock_irq(&chip->reg_lock);
1534 for (i = 0; i < chip->num_streams; i++)
1535 chip->azx_dev[i].irq_pending = 0;
1536 spin_unlock_irq(&chip->reg_lock);
1537 flush_scheduled_work();
1453} 1538}
1454 1539
1455static struct snd_pcm_ops azx_pcm_ops = { 1540static struct snd_pcm_ops azx_pcm_ops = {
@@ -1676,6 +1761,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
1676 int i; 1761 int i;
1677 1762
1678 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 1763 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1764 azx_clear_irq_pending(chip);
1679 for (i = 0; i < AZX_MAX_PCMS; i++) 1765 for (i = 0; i < AZX_MAX_PCMS; i++)
1680 snd_pcm_suspend_all(chip->pcm[i]); 1766 snd_pcm_suspend_all(chip->pcm[i]);
1681 if (chip->initialized) 1767 if (chip->initialized)
@@ -1732,6 +1818,7 @@ static int azx_free(struct azx *chip)
1732 int i; 1818 int i;
1733 1819
1734 if (chip->initialized) { 1820 if (chip->initialized) {
1821 azx_clear_irq_pending(chip);
1735 for (i = 0; i < chip->num_streams; i++) 1822 for (i = 0; i < chip->num_streams; i++)
1736 azx_stream_stop(chip, &chip->azx_dev[i]); 1823 azx_stream_stop(chip, &chip->azx_dev[i]);
1737 azx_stop_chip(chip); 1824 azx_stop_chip(chip);
@@ -1857,6 +1944,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
1857 chip->irq = -1; 1944 chip->irq = -1;
1858 chip->driver_type = driver_type; 1945 chip->driver_type = driver_type;
1859 chip->msi = enable_msi; 1946 chip->msi = enable_msi;
1947 INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
1860 1948
1861 chip->position_fix = check_position_fix(chip, position_fix[dev]); 1949 chip->position_fix = check_position_fix(chip, position_fix[dev]);
1862 check_probe_mask(chip, dev); 1950 check_probe_mask(chip, dev);