diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-02-16 13:51:10 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-03-22 04:30:14 -0500 |
commit | 1a56f8d662ec7fc86f2c408d289fa07cdb781746 (patch) | |
tree | 98093268b0feacbb9d69492113a688dfedacaf4f /sound/pci | |
parent | 111d3af5f5fbf0e28570f1c01e83444d73c68a25 (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>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 22 |
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 |