]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/alsa-post-ga-hda-hwptr-stabilize
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / alsa-post-ga-hda-hwptr-stabilize
1 From: Jaroslav Kysela <perex@perex.cz>
2 Subject: [ALSA] hda_intel: fix unexpected ring buffer positions
3 Patch-mainline: 2.6.30-rc3
4 References: bnc#502733
5
6 I found two issues with ICH7-M (it should be related to other HDA chipsets
7 as 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
17 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
18 Signed-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) {