]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.2-i810_audio.patch
- [2.4.2x, 2.6.x] don't recursively crash in die() on CHRP/PReP machines
[packages/kernel.git] / linux-2.4.2-i810_audio.patch
CommitLineData
95e83f51
JR
1--- Linux/drivers/sound/i810_audio.c Tue Apr 17 18:06:46 2001
2+++ linux/drivers/sound/i810_audio.c Tue Apr 17 18:14:17 2001
3@@ -323,6 +323,10 @@
4 struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *);
5 struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *);
6 void (*free_pcm_channel)(struct i810_card *, int chan);
7+
8+ /* We have a *very* long init time possibly, so use this to block */
9+ /* attempts to open our devices before we are ready (stops oops'es) */
10+ int initializing;
11 };
12
13 static struct i810_card *devs = NULL;
14@@ -1738,7 +1742,9 @@
15
16 /* find an avaiable virtual channel (instance of /dev/dsp) */
17 while (card != NULL) {
18- for (i = 0; i < NR_HW_CH; i++) {
19+ for (i = 0; i < 50 && card->initializing; i++)
20+ schedule_timeout(HZ/20);
21+ for (i = 0; i < NR_HW_CH && !card->initializing; i++) {
22 if (card->states[i] == NULL) {
23 state = card->states[i] = (struct i810_state *)
24 kmalloc(sizeof(struct i810_state), GFP_KERNEL);
25@@ -1885,13 +1887,16 @@
26 int minor = MINOR(inode->i_rdev);
27 struct i810_card *card = devs;
28
29- for (card = devs; card != NULL; card = card->next)
30- for (i = 0; i < NR_AC97; i++)
31+ for (card = devs; card != NULL; card = card->next) {
32+ for (i = 0; i < 50 && card->initializing; i++)
33+ schedule_timeout(HZ/20);
34+ for (i = 0; i < NR_AC97 && !card->initializing; i++)
35 if (card->ac97_codec[i] != NULL &&
36 card->ac97_codec[i]->dev_mixer == minor) {
37 file->private_data = card->ac97_codec[i];
38 return 0;
39 }
40+ }
41 return -ENODEV;
42 }
43
44@@ -2023,6 +2028,75 @@
45 return num_ac97;
46 }
47
48+static void __init i810_configure_clocking (void)
49+{
50+ struct i810_card *card;
51+ struct i810_state *state;
52+ struct dmabuf *dmabuf;
53+ unsigned int i, offset, new_offset;
54+ unsigned long flags;
55+
56+ card = devs;
57+ /* We could try to set the clocking for multiple cards, but can you even have
58+ * more than one i810 in a machine? Besides, clocking is global, so unless
59+ * someone actually thinks more than one i810 in a machine is possible and
60+ * decides to rewrite that little bit, setting the rate for more than one card
61+ * is a waste of time.
62+ */
63+ if(card != NULL) {
64+ state = card->states[0] = (struct i810_state *)
65+ kmalloc(sizeof(struct i810_state), GFP_KERNEL);
66+ if (state == NULL)
67+ return;
68+ memset(state, 0, sizeof(struct i810_state));
69+ dmabuf = &state->dmabuf;
70+
71+ dmabuf->write_channel = card->alloc_pcm_channel(card);
72+ state->virt = 0;
73+ state->card = card;
74+ state->magic = I810_STATE_MAGIC;
75+ init_waitqueue_head(&dmabuf->wait);
76+ init_MUTEX(&state->open_sem);
77+ dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT;
78+ dmabuf->trigger = PCM_ENABLE_OUTPUT;
79+ i810_set_dac_rate(state, 48000);
80+ if(prog_dmabuf(state, 0) != 0) {
81+ goto config_out_nodmabuf;
82+ }
83+ if(dmabuf->dmasize < 16384) {
84+ goto config_out;
85+ }
86+ dmabuf->count = dmabuf->dmasize;
87+ outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI);
88+ save_flags(flags);
89+ cli();
90+ start_dac(state);
91+ offset = i810_get_dma_addr(state, 0);
92+ mdelay(50);
93+ new_offset = i810_get_dma_addr(state, 0);
94+ stop_dac(state);
95+ outb(2,card->iobase+dmabuf->write_channel->port+OFF_CR);
96+ restore_flags(flags);
97+ i = new_offset - offset;
98+#ifdef DEBUG
99+ printk("i810_audio: %d bytes in 50 milliseconds\n", i);
100+#endif
101+ if(i == 0)
102+ goto config_out;
103+ i = i / 4 * 20;
104+ if (i > 48500 || i < 47500) {
105+ clocking = clocking * clocking / i;
106+ printk("i810_audio: setting clocking to %d\n", clocking);
107+ }
108+config_out:
109+ dealloc_dmabuf(state);
110+config_out_nodmabuf:
111+ state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num);
112+ kfree(state);
113+ card->states[0] = NULL;
114+ }
115+}
116+
117 /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
118 until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
119
120@@ -2030,21 +2104,21 @@
121 {
122 struct i810_card *card;
123
124- if (pci_enable_device(pci_dev))
125- return -EIO;
126-
127- if (pci_set_dma_mask(pci_dev, I810_DMA_MASK)) {
128+ if (!pci_dma_supported(pci_dev, I810_DMA_MASK)) {
129 printk(KERN_ERR "intel810: architecture does not support"
130 " 32bit PCI busmaster DMA\n");
131 return -ENODEV;
132 }
133
134+ if (pci_enable_device(pci_dev))
135+ return -EIO;
136 if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
137 printk(KERN_ERR "i810_audio: out of memory\n");
138 return -ENOMEM;
139 }
140 memset(card, 0, sizeof(*card));
141
142+ card->initializing = 1;
143 card->iobase = pci_resource_start (pci_dev, 1);
144 card->ac97base = pci_resource_start (pci_dev, 0);
145 card->pci_dev = pci_dev;
146@@ -2108,6 +2182,11 @@
147 return -ENODEV;
148 }
149 pci_dev->driver_data = card;
150+ pci_dev->dma_mask = I810_DMA_MASK;
151+ if(clocking == 48000) {
152+ i810_configure_clocking();
153+ }
154+ card->initializing = 0;
155 return 0;
156 }
157
158@@ -2146,75 +2225,6 @@
159 remove: i810_remove,
160 };
161
162-static void __init i810_configure_clocking (void)
163-{
164- struct i810_card *card;
165- struct i810_state *state;
166- struct dmabuf *dmabuf;
167- unsigned int i, offset, new_offset;
168- unsigned long flags;
169-
170- card = devs;
171- /* We could try to set the clocking for multiple cards, but can you even have
172- * more than one i810 in a machine? Besides, clocking is global, so unless
173- * someone actually thinks more than one i810 in a machine is possible and
174- * decides to rewrite that little bit, setting the rate for more than one card
175- * is a waste of time.
176- */
177- if(card != NULL) {
178- state = card->states[0] = (struct i810_state *)
179- kmalloc(sizeof(struct i810_state), GFP_KERNEL);
180- if (state == NULL)
181- return;
182- memset(state, 0, sizeof(struct i810_state));
183- dmabuf = &state->dmabuf;
184-
185- dmabuf->write_channel = card->alloc_pcm_channel(card);
186- state->virt = 0;
187- state->card = card;
188- state->magic = I810_STATE_MAGIC;
189- init_waitqueue_head(&dmabuf->wait);
190- init_MUTEX(&state->open_sem);
191- dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT;
192- dmabuf->trigger = PCM_ENABLE_OUTPUT;
193- i810_set_dac_rate(state, 48000);
194- if(prog_dmabuf(state, 0) != 0) {
195- goto config_out_nodmabuf;
196- }
197- if(dmabuf->dmasize < 16384) {
198- goto config_out;
199- }
200- dmabuf->count = dmabuf->dmasize;
201- outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI);
202- save_flags(flags);
203- cli();
204- start_dac(state);
205- offset = i810_get_dma_addr(state, 0);
206- mdelay(50);
207- new_offset = i810_get_dma_addr(state, 0);
208- stop_dac(state);
209- outb(2,card->iobase+dmabuf->write_channel->port+OFF_CR);
210- restore_flags(flags);
211- i = new_offset - offset;
212-#ifdef DEBUG
213- printk("i810_audio: %d bytes in 50 milliseconds\n", i);
214-#endif
215- if(i == 0)
216- goto config_out;
217- i = i / 4 * 20;
218- if (i > 48500 || i < 47500) {
219- clocking = clocking * clocking / i;
220- printk("i810_audio: setting clocking to %d\n", clocking);
221- }
222-config_out:
223- dealloc_dmabuf(state);
224-config_out_nodmabuf:
225- state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num);
226- kfree(state);
227- card->states[0] = NULL;
228- }
229-}
230-
231 static int __init i810_init_module (void)
232 {
233 if (!pci_present()) /* No PCI bus in this machine! */
234@@ -2229,9 +2239,6 @@
235 }
236 if(ftsodell != 0) {
237 printk("i810_audio: ftsodell is now a deprecated option.\n");
238- }
239- if(clocking == 48000) {
240- i810_configure_clocking();
241 }
242 return 0;
243 }
This page took 0.249435 seconds and 4 git commands to generate.