aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRene Herman <rene.herman@keyaccess.nl>2008-05-14 19:05:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-05-14 22:11:13 -0400
commit3b73a223661ed137c5d3d2635f954382e94f5a43 (patch)
tree71a6d01c5b98a8ffb7ee8273fc4f086e09bbf5df
parentbc033c9b5fd261855278f4ed82c3713cc549afbe (diff)
pnp: add ISAPnP MPU option quirks
The AD181x and AZT230 chips don't support an IRQ-less MPU401 option but work fine without one. This adds (priority functional) IRQ-less options for each port option to help systems with few available IRQs. The AD1815 quirk can't use pnp_register_irq_resource() due to doubly penalizing the IRQ. Also, while not a practical issue due to no IRQ option being present for the dependents, this needs to add in front, not back. Doesn't use pnp_register_port_resource() for symetry with above. This does not delete the AD1815 independent option even though it should be empty after the IRQ transfer due to AD1816 coming with an empty but still present independent option by default. Was tested on AD1815, AD1816 and AZT2320. The ALSA snd-ad1818a driver also support the AZT2002 ID for MPU401 but this doesn't as I was unable to test it. Signed-off-by: Rene Herman <rene.herman@gmail.com> Tested-by: Uwe Bugla <uwe.bugla@gmx.de> Acked-by: Uwe Bugla <uwe.bugla@gmx.de> Acked-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Cc: Takashi Iwai <tiwai@suse.de> Cc: Len Brown <len.brown@intel.com Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/pnp/quirks.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index a1af2f989482..ffdb12a59c40 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -111,6 +111,113 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
111 dev_info(&dev->dev, "SB audio device quirk - increased port range\n"); 111 dev_info(&dev->dev, "SB audio device quirk - increased port range\n");
112} 112}
113 113
114static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev)
115{
116 struct pnp_option *head = NULL;
117 struct pnp_option *prev = NULL;
118 struct pnp_option *res;
119
120 /*
121 * Build a functional IRQ-less variant of each MPU option.
122 */
123
124 for (res = dev->dependent; res; res = res->next) {
125 struct pnp_option *curr;
126 struct pnp_port *port;
127 struct pnp_port *copy;
128
129 port = res->port;
130 if (!port || !res->irq)
131 continue;
132
133 copy = pnp_alloc(sizeof *copy);
134 if (!copy)
135 break;
136
137 copy->min = port->min;
138 copy->max = port->max;
139 copy->align = port->align;
140 copy->size = port->size;
141 copy->flags = port->flags;
142
143 curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL);
144 if (!curr) {
145 kfree(copy);
146 break;
147 }
148 curr->port = copy;
149
150 if (prev)
151 prev->next = curr;
152 else
153 head = curr;
154 prev = curr;
155 }
156 if (head)
157 dev_info(&dev->dev, "adding IRQ-less MPU options\n");
158
159 return head;
160}
161
162static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
163{
164 struct pnp_option *res;
165 struct pnp_irq *irq;
166
167 /*
168 * Distribute the independent IRQ over the dependent options
169 */
170
171 res = dev->independent;
172 if (!res)
173 return;
174
175 irq = res->irq;
176 if (!irq || irq->next)
177 return;
178
179 res = dev->dependent;
180 if (!res)
181 return;
182
183 while (1) {
184 struct pnp_irq *copy;
185
186 copy = pnp_alloc(sizeof *copy);
187 if (!copy)
188 break;
189
190 memcpy(copy->map, irq->map, sizeof copy->map);
191 copy->flags = irq->flags;
192
193 copy->next = res->irq; /* Yes, this is NULL */
194 res->irq = copy;
195
196 if (!res->next)
197 break;
198 res = res->next;
199 }
200 kfree(irq);
201
202 res->next = quirk_isapnp_mpu_options(dev);
203
204 res = dev->independent;
205 res->irq = NULL;
206}
207
208static void quirk_isapnp_mpu_resources(struct pnp_dev *dev)
209{
210 struct pnp_option *res;
211
212 res = dev->dependent;
213 if (!res)
214 return;
215
216 while (res->next)
217 res = res->next;
218
219 res->next = quirk_isapnp_mpu_options(dev);
220}
114 221
115#include <linux/pci.h> 222#include <linux/pci.h>
116 223
@@ -205,6 +312,11 @@ static struct pnp_fixup pnp_fixups[] = {
205 {"CTL0043", quirk_sb16audio_resources}, 312 {"CTL0043", quirk_sb16audio_resources},
206 {"CTL0044", quirk_sb16audio_resources}, 313 {"CTL0044", quirk_sb16audio_resources},
207 {"CTL0045", quirk_sb16audio_resources}, 314 {"CTL0045", quirk_sb16audio_resources},
315 /* Add IRQ-less MPU options */
316 {"ADS7151", quirk_ad1815_mpu_resources},
317 {"ADS7181", quirk_isapnp_mpu_resources},
318 {"AZT0002", quirk_isapnp_mpu_resources},
319 /* PnP resources that might overlap PCI BARs */
208 {"PNP0c01", quirk_system_pci_resources}, 320 {"PNP0c01", quirk_system_pci_resources},
209 {"PNP0c02", quirk_system_pci_resources}, 321 {"PNP0c02", quirk_system_pci_resources},
210 {""} 322 {""}