aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-02-16 13:51:10 -0500
committerJaroslav Kysela <perex@suse.cz>2006-03-22 04:30:14 -0500
commit1a56f8d662ec7fc86f2c408d289fa07cdb781746 (patch)
tree98093268b0feacbb9d69492113a688dfedacaf4f
parent111d3af5f5fbf0e28570f1c01e83444d73c68a25 (diff)
[ALSA] hda-intel - Auto-correction of the DMA position mode
Modules: HDA Intel driver Switch the method to measure the current DMA position automatically from position-buffer mode to LPIB-read mode with a sanity check. Some hardwares seems to have problem with the position buffer. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_intel.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 016fbc263e55..c096606970ff 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -250,7 +250,6 @@ struct azx_dev {
250 unsigned int fragsize; /* size of each period in bytes */ 250 unsigned int fragsize; /* size of each period in bytes */
251 unsigned int frags; /* number for period in the play buffer */ 251 unsigned int frags; /* number for period in the play buffer */
252 unsigned int fifo_size; /* FIFO size */ 252 unsigned int fifo_size; /* FIFO size */
253 unsigned int last_pos; /* last updated period position */
254 253
255 void __iomem *sd_addr; /* stream descriptor pointer */ 254 void __iomem *sd_addr; /* stream descriptor pointer */
256 255
@@ -261,10 +260,11 @@ struct azx_dev {
261 unsigned int format_val; /* format value to be set in the controller and the codec */ 260 unsigned int format_val; /* format value to be set in the controller and the codec */
262 unsigned char stream_tag; /* assigned stream */ 261 unsigned char stream_tag; /* assigned stream */
263 unsigned char index; /* stream index */ 262 unsigned char index; /* stream index */
263 /* for sanity check of position buffer */
264 unsigned int period_intr;
264 265
265 unsigned int opened: 1; 266 unsigned int opened: 1;
266 unsigned int running: 1; 267 unsigned int running: 1;
267 unsigned int period_updating: 1;
268}; 268};
269 269
270/* CORB/RIRB */ 270/* CORB/RIRB */
@@ -804,11 +804,10 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
804 if (status & azx_dev->sd_int_sta_mask) { 804 if (status & azx_dev->sd_int_sta_mask) {
805 azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); 805 azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
806 if (azx_dev->substream && azx_dev->running) { 806 if (azx_dev->substream && azx_dev->running) {
807 azx_dev->period_updating = 1; 807 azx_dev->period_intr++;
808 spin_unlock(&chip->reg_lock); 808 spin_unlock(&chip->reg_lock);
809 snd_pcm_period_elapsed(azx_dev->substream); 809 snd_pcm_period_elapsed(azx_dev->substream);
810 spin_lock(&chip->reg_lock); 810 spin_lock(&chip->reg_lock);
811 azx_dev->period_updating = 0;
812 } 811 }
813 } 812 }
814 } 813 }
@@ -1119,7 +1118,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
1119 azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; 1118 azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
1120 else 1119 else
1121 azx_dev->fifo_size = 0; 1120 azx_dev->fifo_size = 0;
1122 azx_dev->last_pos = 0;
1123 1121
1124 return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, 1122 return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
1125 azx_dev->format_val, substream); 1123 azx_dev->format_val, substream);
@@ -1167,10 +1165,20 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
1167 struct azx_dev *azx_dev = get_azx_dev(substream); 1165 struct azx_dev *azx_dev = get_azx_dev(substream);
1168 unsigned int pos; 1166 unsigned int pos;
1169 1167
1170 if (chip->position_fix == POS_FIX_POSBUF) { 1168 if (chip->position_fix == POS_FIX_POSBUF ||
1169 chip->position_fix == POS_FIX_AUTO) {
1171 /* use the position buffer */ 1170 /* use the position buffer */
1172 pos = *azx_dev->posbuf; 1171 pos = *azx_dev->posbuf;
1172 if (chip->position_fix == POS_FIX_AUTO &&
1173 azx_dev->period_intr == 1 && ! pos) {
1174 printk(KERN_WARNING
1175 "hda-intel: Invalid position buffer, "
1176 "using LPIB read method instead.\n");
1177 chip->position_fix = POS_FIX_NONE;
1178 goto read_lpib;
1179 }
1173 } else { 1180 } else {
1181 read_lpib:
1174 /* read LPIB */ 1182 /* read LPIB */
1175 pos = azx_sd_readl(azx_dev, SD_LPIB); 1183 pos = azx_sd_readl(azx_dev, SD_LPIB);
1176 if (chip->position_fix == POS_FIX_FIFO) 1184 if (chip->position_fix == POS_FIX_FIFO)
@@ -1441,7 +1449,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
1441 chip->irq = -1; 1449 chip->irq = -1;
1442 chip->driver_type = driver_type; 1450 chip->driver_type = driver_type;
1443 1451
1444 chip->position_fix = position_fix ? position_fix : POS_FIX_POSBUF; 1452 chip->position_fix = position_fix;
1445 chip->single_cmd = single_cmd; 1453 chip->single_cmd = single_cmd;
1446 1454
1447#if BITS_PER_LONG != 64 1455#if BITS_PER_LONG != 64