aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-09-05 11:11:40 -0400
committerJaroslav Kysela <perex@suse.cz>2005-09-12 04:41:37 -0400
commit0be3b5d3fb94c36c517655d18a936681d7108667 (patch)
tree6ce1556cfac492f4a9957c5d73d8b116d87e19cb
parenta76af199dc025e8f5cf6b9542efadc3de5163a7a (diff)
[ALSA] hda-intel - Check validity of DMA position
HDA Intel driver Check the validity of the current DMA position when position_fix=0 (auto) is set. If the DMA position overcomes the threshold, the driver changes the fix behavior automatically to use POSBUF. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_intel.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 15107df1f490..96f9e8729192 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -62,7 +62,7 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
62module_param_array(model, charp, NULL, 0444); 62module_param_array(model, charp, NULL, 0444);
63MODULE_PARM_DESC(model, "Use the given board model."); 63MODULE_PARM_DESC(model, "Use the given board model.");
64module_param_array(position_fix, int, NULL, 0444); 64module_param_array(position_fix, int, NULL, 0444);
65MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)."); 65MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
66 66
67MODULE_LICENSE("GPL"); 67MODULE_LICENSE("GPL");
68MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," 68MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
@@ -211,9 +211,10 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
211 211
212/* position fix mode */ 212/* position fix mode */
213enum { 213enum {
214 POS_FIX_FIFO, 214 POS_FIX_AUTO,
215 POS_FIX_NONE, 215 POS_FIX_NONE,
216 POS_FIX_POSBUF 216 POS_FIX_POSBUF,
217 POS_FIX_FIFO,
217}; 218};
218 219
219/* Defines for ATI HD Audio support in SB450 south bridge */ 220/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -243,6 +244,7 @@ struct snd_azx_dev {
243 unsigned int fragsize; /* size of each period in bytes */ 244 unsigned int fragsize; /* size of each period in bytes */
244 unsigned int frags; /* number for period in the play buffer */ 245 unsigned int frags; /* number for period in the play buffer */
245 unsigned int fifo_size; /* FIFO size */ 246 unsigned int fifo_size; /* FIFO size */
247 unsigned int last_pos; /* last updated period position */
246 248
247 void __iomem *sd_addr; /* stream descriptor pointer */ 249 void __iomem *sd_addr; /* stream descriptor pointer */
248 250
@@ -256,6 +258,7 @@ struct snd_azx_dev {
256 258
257 unsigned int opened: 1; 259 unsigned int opened: 1;
258 unsigned int running: 1; 260 unsigned int running: 1;
261 unsigned int period_updating: 1;
259}; 262};
260 263
261/* CORB/RIRB */ 264/* CORB/RIRB */
@@ -724,11 +727,9 @@ static void azx_init_chip(azx_t *chip)
724 /* initialize the codec command I/O */ 727 /* initialize the codec command I/O */
725 azx_init_cmd_io(chip); 728 azx_init_cmd_io(chip);
726 729
727 if (chip->position_fix == POS_FIX_POSBUF) { 730 /* program the position buffer */
728 /* program the position buffer */ 731 azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
729 azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); 732 azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
730 azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
731 }
732 733
733 /* For ATI SB450 azalia HD audio, we need to enable snoop */ 734 /* For ATI SB450 azalia HD audio, we need to enable snoop */
734 if (chip->driver_type == AZX_DRIVER_ATI) { 735 if (chip->driver_type == AZX_DRIVER_ATI) {
@@ -763,9 +764,11 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
763 if (status & azx_dev->sd_int_sta_mask) { 764 if (status & azx_dev->sd_int_sta_mask) {
764 azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); 765 azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
765 if (azx_dev->substream && azx_dev->running) { 766 if (azx_dev->substream && azx_dev->running) {
767 azx_dev->period_updating = 1;
766 spin_unlock(&chip->reg_lock); 768 spin_unlock(&chip->reg_lock);
767 snd_pcm_period_elapsed(azx_dev->substream); 769 snd_pcm_period_elapsed(azx_dev->substream);
768 spin_lock(&chip->reg_lock); 770 spin_lock(&chip->reg_lock);
771 azx_dev->period_updating = 0;
769 } 772 }
770 } 773 }
771 } 774 }
@@ -866,11 +869,9 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
866 /* upper BDL address */ 869 /* upper BDL address */
867 azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); 870 azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
868 871
869 if (chip->position_fix == POS_FIX_POSBUF) { 872 /* enable the position buffer */
870 /* enable the position buffer */ 873 if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
871 if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) 874 azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
872 azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
873 }
874 875
875 /* set the interrupt enable bits in the descriptor control register */ 876 /* set the interrupt enable bits in the descriptor control register */
876 azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); 877 azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
@@ -1078,6 +1079,7 @@ static int azx_pcm_prepare(snd_pcm_substream_t *substream)
1078 azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; 1079 azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
1079 else 1080 else
1080 azx_dev->fifo_size = 0; 1081 azx_dev->fifo_size = 0;
1082 azx_dev->last_pos = 0;
1081 1083
1082 return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, 1084 return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
1083 azx_dev->format_val, substream); 1085 azx_dev->format_val, substream);
@@ -1133,6 +1135,26 @@ static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
1133 pos = azx_sd_readl(azx_dev, SD_LPIB); 1135 pos = azx_sd_readl(azx_dev, SD_LPIB);
1134 if (chip->position_fix == POS_FIX_FIFO) 1136 if (chip->position_fix == POS_FIX_FIFO)
1135 pos += azx_dev->fifo_size; 1137 pos += azx_dev->fifo_size;
1138 else if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_updating) {
1139 /* check the validity of DMA position */
1140 unsigned int diff = 0;
1141 azx_dev->last_pos += azx_dev->fragsize;
1142 if (azx_dev->last_pos > pos)
1143 diff = azx_dev->last_pos - pos;
1144 if (azx_dev->last_pos >= azx_dev->bufsize) {
1145 if (pos < azx_dev->fragsize)
1146 diff = 0;
1147 azx_dev->last_pos = 0;
1148 }
1149 if (diff > 0 && diff <= azx_dev->fifo_size)
1150 pos += azx_dev->fifo_size;
1151 else {
1152 snd_printdd(KERN_INFO "hda_intel: DMA position fix %d, switching to posbuf\n", diff);
1153 chip->position_fix = POS_FIX_POSBUF;
1154 pos = *azx_dev->posbuf;
1155 }
1156 azx_dev->period_updating = 0;
1157 }
1136 } 1158 }
1137 if (pos >= azx_dev->bufsize) 1159 if (pos >= azx_dev->bufsize)
1138 pos = 0; 1160 pos = 0;
@@ -1244,8 +1266,7 @@ static int __devinit azx_init_stream(azx_t *chip)
1244 azx_dev_t *azx_dev = &chip->azx_dev[i]; 1266 azx_dev_t *azx_dev = &chip->azx_dev[i];
1245 azx_dev->bdl = (u32 *)(chip->bdl.area + off); 1267 azx_dev->bdl = (u32 *)(chip->bdl.area + off);
1246 azx_dev->bdl_addr = chip->bdl.addr + off; 1268 azx_dev->bdl_addr = chip->bdl.addr + off;
1247 if (chip->position_fix == POS_FIX_POSBUF) 1269 azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
1248 azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
1249 /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ 1270 /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
1250 azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); 1271 azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
1251 /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ 1272 /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1437,13 +1458,11 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
1437 snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); 1458 snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
1438 goto errout; 1459 goto errout;
1439 } 1460 }
1440 if (chip->position_fix == POS_FIX_POSBUF) { 1461 /* allocate memory for the position buffer */
1441 /* allocate memory for the position buffer */ 1462 if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
1442 if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 1463 chip->num_streams * 8, &chip->posbuf)) < 0) {
1443 chip->num_streams * 8, &chip->posbuf)) < 0) { 1464 snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
1444 snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); 1465 goto errout;
1445 goto errout;
1446 }
1447 } 1466 }
1448 /* allocate CORB/RIRB */ 1467 /* allocate CORB/RIRB */
1449 if ((err = azx_alloc_cmd_io(chip)) < 0) 1468 if ((err = azx_alloc_cmd_io(chip)) < 0)