1 From: Jaroslav Kysela <perex@perex.cz>
2 Subject: [ALSA] hda_intel: fix unexpected ring buffer positions
3 Patch-mainline: 2.6.30-rc3
6 I found two issues with ICH7-M (it should be related to other HDA chipsets
9 - the ring buffer position is not reset when stream restarts (after xrun) -
10 solved by moving azx_stream_reset() call from open() to prepare() callback
11 and reset posbuf to zero (it might be filled with hw later than position()
13 - irq_ignore flag should be set also when ring buffer memory area is not
14 changed in prepare() callback - this patch replaces irq_ignore with
15 more universal check based on jiffies clock
17 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
18 Signed-off-by: Takashi Iwai <tiwai@suse.de>
21 sound/pci/hda/hda_intel.c | 39 +++++++++++++++++++++++++--------------
22 1 file changed, 25 insertions(+), 14 deletions(-)
24 --- a/sound/pci/hda/hda_intel.c
25 +++ b/sound/pci/hda/hda_intel.c
26 @@ -304,6 +304,9 @@ struct azx_dev {
27 unsigned int period_bytes; /* size of the period in bytes */
28 unsigned int frags; /* number for period in the play buffer */
29 unsigned int fifo_size; /* FIFO size */
30 + unsigned int start_flag: 1; /* stream full start flag */
31 + unsigned long start_jiffies; /* start + minimum jiffies */
32 + unsigned long min_jiffies; /* minimum jiffies before position is valid */
34 void __iomem *sd_addr; /* stream descriptor pointer */
36 @@ -322,7 +325,6 @@ struct azx_dev {
37 unsigned int opened :1;
38 unsigned int running :1;
39 unsigned int irq_pending :1;
40 - unsigned int irq_ignore :1;
43 * A flag to ensure DMA position is 0
44 @@ -964,7 +966,7 @@ static irqreturn_t azx_interrupt(int irq
45 struct azx *chip = dev_id;
46 struct azx_dev *azx_dev;
51 spin_lock(&chip->reg_lock);
53 @@ -980,18 +982,14 @@ static irqreturn_t azx_interrupt(int irq
54 azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
55 if (!azx_dev->substream || !azx_dev->running)
57 - /* ignore the first dummy IRQ (due to pos_adj) */
58 - if (azx_dev->irq_ignore) {
59 - azx_dev->irq_ignore = 0;
62 /* check whether this IRQ is really acceptable */
63 - if (azx_position_ok(chip, azx_dev)) {
64 + ok = azx_position_ok(chip, azx_dev);
66 azx_dev->irq_pending = 0;
67 spin_unlock(&chip->reg_lock);
68 snd_pcm_period_elapsed(azx_dev->substream);
69 spin_lock(&chip->reg_lock);
70 - } else if (chip->bus && chip->bus->workq) {
71 + } else if (ok == 0 && chip->bus && chip->bus->workq) {
72 /* bogus IRQ, process it later */
73 azx_dev->irq_pending = 1;
74 queue_work(chip->bus->workq,
75 @@ -1080,7 +1078,6 @@ static int azx_setup_periods(struct azx
76 bdl = (u32 *)azx_dev->bdl.area;
79 - azx_dev->irq_ignore = 0;
80 pos_adj = bdl_pos_adj[chip->dev_index];
82 struct snd_pcm_runtime *runtime = substream->runtime;
83 @@ -1101,7 +1098,6 @@ static int azx_setup_periods(struct azx
84 &bdl, ofs, pos_adj, 1);
87 - azx_dev->irq_ignore = 1;
91 @@ -1147,6 +1143,9 @@ static void azx_stream_reset(struct azx
92 while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
96 + /* reset first position - may not be synced with hw at this time */
97 + *azx_dev->posbuf = 0;
101 @@ -1396,7 +1395,6 @@ static int azx_pcm_open(struct snd_pcm_s
102 snd_pcm_set_sync(substream);
103 mutex_unlock(&chip->open_mutex);
105 - azx_stream_reset(chip, azx_dev);
109 @@ -1461,6 +1459,7 @@ static int azx_pcm_prepare(struct snd_pc
110 unsigned int bufsize, period_bytes, format_val;
113 + azx_stream_reset(chip, azx_dev);
114 format_val = snd_hda_calc_stream_format(runtime->rate,
117 @@ -1489,6 +1488,8 @@ static int azx_pcm_prepare(struct snd_pc
121 + azx_dev->min_jiffies = (runtime->period_size * HZ) /
122 + (runtime->rate * 2);
123 azx_setup_controller(chip, azx_dev);
124 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
125 azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
126 @@ -1505,13 +1506,14 @@ static int azx_pcm_trigger(struct snd_pc
127 struct azx *chip = apcm->chip;
128 struct azx_dev *azx_dev;
129 struct snd_pcm_substream *s;
130 - int start, nsync = 0, sbits = 0;
131 + int rstart = 0, start, nsync = 0, sbits = 0;
135 + case SNDRV_PCM_TRIGGER_START:
137 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
138 case SNDRV_PCM_TRIGGER_RESUME:
139 - case SNDRV_PCM_TRIGGER_START:
142 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
143 @@ -1541,6 +1543,10 @@ static int azx_pcm_trigger(struct snd_pc
144 if (s->pcm->card != substream->pcm->card)
146 azx_dev = get_azx_dev(s);
148 + azx_dev->start_flag = 1;
149 + azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies;
152 azx_stream_start(chip, azx_dev);
154 @@ -1690,6 +1696,11 @@ static int azx_position_ok(struct azx *c
158 + if (azx_dev->start_flag &&
159 + time_before_eq(jiffies, azx_dev->start_jiffies))
160 + return -1; /* bogus (too early) interrupt */
161 + azx_dev->start_flag = 0;
163 pos = azx_get_position(chip, azx_dev);
164 if (chip->position_fix == POS_FIX_AUTO) {