]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.drivers/alsa-post-ga-hda-hwptr-stabilize
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / alsa-post-ga-hda-hwptr-stabilize
CommitLineData
00e5a55c
BS
1From: Jaroslav Kysela <perex@perex.cz>
2Subject: [ALSA] hda_intel: fix unexpected ring buffer positions
3Patch-mainline: 2.6.30-rc3
4References: bnc#502733
5
6I found two issues with ICH7-M (it should be related to other HDA chipsets
7as well):
8
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()
12 callback is called)
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
16
17Signed-off-by: Jaroslav Kysela <perex@perex.cz>
18Signed-off-by: Takashi Iwai <tiwai@suse.de>
19
20---
21 sound/pci/hda/hda_intel.c | 39 +++++++++++++++++++++++++--------------
22 1 file changed, 25 insertions(+), 14 deletions(-)
23
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 */
33
34 void __iomem *sd_addr; /* stream descriptor pointer */
35
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;
41 /*
42 * For VIA:
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;
47 u32 status;
48- int i;
49+ int i, ok;
50
51 spin_lock(&chip->reg_lock);
52
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)
56 continue;
57- /* ignore the first dummy IRQ (due to pos_adj) */
58- if (azx_dev->irq_ignore) {
59- azx_dev->irq_ignore = 0;
60- continue;
61- }
62 /* check whether this IRQ is really acceptable */
63- if (azx_position_ok(chip, azx_dev)) {
64+ ok = azx_position_ok(chip, azx_dev);
65+ if (ok == 1) {
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;
77 ofs = 0;
78 azx_dev->frags = 0;
79- azx_dev->irq_ignore = 0;
80 pos_adj = bdl_pos_adj[chip->dev_index];
81 if (pos_adj > 0) {
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);
85 if (ofs < 0)
86 goto error;
87- azx_dev->irq_ignore = 1;
88 }
89 } else
90 pos_adj = 0;
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) &&
93 --timeout)
94 ;
95+
96+ /* reset first position - may not be synced with hw at this time */
97+ *azx_dev->posbuf = 0;
98 }
99
100 /*
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);
104
105- azx_stream_reset(chip, azx_dev);
106 return 0;
107 }
108
109@@ -1461,6 +1459,7 @@ static int azx_pcm_prepare(struct snd_pc
110 unsigned int bufsize, period_bytes, format_val;
111 int err;
112
113+ azx_stream_reset(chip, azx_dev);
114 format_val = snd_hda_calc_stream_format(runtime->rate,
115 runtime->channels,
116 runtime->format,
117@@ -1489,6 +1488,8 @@ static int azx_pcm_prepare(struct snd_pc
118 return err;
119 }
120
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;
132 int nwait, timeout;
133
134 switch (cmd) {
135+ case SNDRV_PCM_TRIGGER_START:
136+ rstart = 1;
137 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
138 case SNDRV_PCM_TRIGGER_RESUME:
139- case SNDRV_PCM_TRIGGER_START:
140 start = 1;
141 break;
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)
145 continue;
146 azx_dev = get_azx_dev(s);
147+ if (rstart) {
148+ azx_dev->start_flag = 1;
149+ azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies;
150+ }
151 if (start)
152 azx_stream_start(chip, azx_dev);
153 else
154@@ -1690,6 +1696,11 @@ static int azx_position_ok(struct azx *c
155 {
156 unsigned int pos;
157
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;
162+
163 pos = azx_get_position(chip, azx_dev);
164 if (chip->position_fix == POS_FIX_AUTO) {
165 if (!pos) {