blob: a4ca7569e700d81fa654e380bea7c3e24eab81c7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright 2001-2004 Randolph Chung <tausq@debian.org>
3 *
4 * Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * Notes:
21 * 1. Only flat DMA is supported; s-g is not supported right now
22 *
23 *
24<jsm> tausq: Anyway, to set up sample rates for D to A, you just use the sample rate on the codec. For A to D, you need to set the codec always to 48K (using the split sample rate feature on the codec) and then set the resampler on the AD1889 to the sample rate you want.
25<jsm> Also, when changing the sample rate on the codec you need to power it down and re power it up for the change to take effect!
26 *
27 * $Id: ad1889.c,v 1.3 2002/10/19 21:31:44 grundler Exp $
28 */
29#include <linux/config.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/ioport.h>
33#include <linux/pci.h>
34#include <linux/poll.h>
35#include <linux/proc_fs.h>
36#include <linux/slab.h>
37#include <linux/soundcard.h>
38#include <linux/ac97_codec.h>
39#include <linux/sound.h>
40#include <linux/interrupt.h>
Ingo Molnar910f5d22006-03-23 03:00:39 -080041#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#include <asm/delay.h>
44#include <asm/io.h>
45#include <asm/dma.h>
46#include <asm/uaccess.h>
47
48#include "ad1889.h"
49
50#define DBG(fmt, arg...) printk(fmt, ##arg)
51#define DEVNAME "ad1889"
52
53#define NR_HW_CH 4
54#define DAC_RUNNING 1
55#define ADC_RUNNING 2
56
57#define UNDERRUN(dev) (0)
58
59#define AD1889_READW(dev,reg) readw(dev->regbase + reg)
60#define AD1889_WRITEW(dev,reg,val) writew((val), dev->regbase + reg)
61#define AD1889_READL(dev,reg) readl(dev->regbase + reg)
62#define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
63
64//now 100ms
65/* #define WAIT_10MS() schedule_timeout(HZ/10) */
66#define WAIT_10MS() do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
67
68/* currently only support a single device */
69static ad1889_dev_t *ad1889_dev = NULL;
70
71/************************* helper routines ***************************** */
72static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
73{
74 struct ac97_codec *ac97_codec = dev->ac97_codec;
75
76 DBG("Setting WAV rate to %d\n", rate);
77 dev->state[AD_WAV_STATE].dmabuf.rate = rate;
Stuart Bradye74eb802005-03-01 23:00:56 +000078 AD1889_WRITEW(dev, AD_DS_WAS, rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80 /* Cycle the DAC to enable the new rate */
81 ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
82 WAIT_10MS();
83 ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
84}
85
86static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
87{
88 u16 tmp;
89
90 DBG("Setting WAV format to 0x%x\n", fmt);
91
Stuart Bradye74eb802005-03-01 23:00:56 +000092 tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 if (fmt & AFMT_S16_LE) {
94 //tmp |= 0x0100; /* set WA16 */
95 tmp |= 0x0300; /* set WA16 stereo */
96 } else if (fmt & AFMT_U8) {
97 tmp &= ~0x0100; /* clear WA16 */
98 }
Stuart Bradye74eb802005-03-01 23:00:56 +000099 AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100}
101
102static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
103{
104 u16 tmp;
105
106 DBG("Setting ADC format to 0x%x\n", fmt);
107
Stuart Bradye74eb802005-03-01 23:00:56 +0000108 tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 if (fmt & AFMT_S16_LE) {
110 tmp |= 0x0100; /* set WA16 */
111 } else if (fmt & AFMT_U8) {
112 tmp &= ~0x0100; /* clear WA16 */
113 }
Stuart Bradye74eb802005-03-01 23:00:56 +0000114 AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
117static void ad1889_start_wav(ad1889_state_t *state)
118{
119 unsigned long flags;
120 struct dmabuf *dmabuf = &state->dmabuf;
121 int cnt;
122 u16 tmp;
123
124 spin_lock_irqsave(&state->card->lock, flags);
125
126 if (dmabuf->dma_len) /* DMA already in flight */
127 goto skip_dma;
128
129 /* setup dma */
130 cnt = dmabuf->wr_ptr - dmabuf->rd_ptr;
131 if (cnt == 0) /* done - don't need to do anything */
132 goto skip_dma;
133
134 /* If the wr_ptr has wrapped, only map to the end */
135 if (cnt < 0)
136 cnt = DMA_SIZE - dmabuf->rd_ptr;
137
138 dmabuf->dma_handle = pci_map_single(ad1889_dev->pci,
139 dmabuf->rawbuf + dmabuf->rd_ptr,
140 cnt, PCI_DMA_TODEVICE);
141 dmabuf->dma_len = cnt;
142 dmabuf->ready = 1;
143
144 DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
145 dmabuf->rd_ptr, dmabuf->dma_len);
146
147 /* load up the current register set */
Stuart Bradye74eb802005-03-01 23:00:56 +0000148 AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
149 AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
150 AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
152 /* TODO: for now we load the base registers with the same thing */
Stuart Bradye74eb802005-03-01 23:00:56 +0000153 AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
154 AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
155 AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
157 /* and we're off to the races... */
Stuart Bradye74eb802005-03-01 23:00:56 +0000158 AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
159 tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 tmp |= 0x0400; /* set WAEN */
Stuart Bradye74eb802005-03-01 23:00:56 +0000161 AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
162 (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163
164 dmabuf->enable |= DAC_RUNNING;
165
166skip_dma:
167 spin_unlock_irqrestore(&state->card->lock, flags);
168}
169
170
171static void ad1889_stop_wav(ad1889_state_t *state)
172{
173 unsigned long flags;
174 struct dmabuf *dmabuf = &state->dmabuf;
175
176 spin_lock_irqsave(&state->card->lock, flags);
177
178 if (dmabuf->enable & DAC_RUNNING) {
179 u16 tmp;
180 unsigned long cnt = dmabuf->dma_len;
181
Stuart Bradye74eb802005-03-01 23:00:56 +0000182 tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 tmp &= ~0x0400; /* clear WAEN */
Stuart Bradye74eb802005-03-01 23:00:56 +0000184 AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
185 (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle,
187 cnt, PCI_DMA_TODEVICE);
188
189 dmabuf->enable &= ~DAC_RUNNING;
190
191 /* update dma pointers */
192 dmabuf->rd_ptr += cnt;
193 dmabuf->rd_ptr &= (DMA_SIZE - 1);
194
195 dmabuf->dma_handle = 0;
196 dmabuf->dma_len = 0;
197 dmabuf->ready = 0;
198
199 wake_up(&dmabuf->wait);
200 }
201
202 spin_unlock_irqrestore(&state->card->lock, flags);
203}
204
205
206#if 0
207static void ad1889_startstop_adc(ad1889_state_t *state, int start)
208{
209 u16 tmp;
210 unsigned long flags;
211
212 spin_lock_irqsave(&state->card->lock, flags);
213
Stuart Bradye74eb802005-03-01 23:00:56 +0000214 tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 if (start) {
216 state->dmabuf.enable |= ADC_RUNNING;
217 tmp |= 0x0004; /* set ADEN */
218 } else {
219 state->dmabuf.enable &= ~ADC_RUNNING;
220 tmp &= ~0x0004; /* clear ADEN */
221 }
Stuart Bradye74eb802005-03-01 23:00:56 +0000222 AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
224 spin_unlock_irqrestore(&state->card->lock, flags);
225}
226#endif
227
228static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
229{
230 ad1889_dev_t *dev;
231 struct dmabuf *dmabuf;
232 int i;
233
234 if ((dev = kmalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL)
235 return NULL;
236 memset(dev, 0, sizeof(ad1889_dev_t));
237 spin_lock_init(&dev->lock);
238 dev->pci = pci;
239
240 for (i = 0; i < AD_MAX_STATES; i++) {
241 dev->state[i].card = dev;
Ingo Molnar910f5d22006-03-23 03:00:39 -0800242 mutex_init(&dev->state[i].mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 init_waitqueue_head(&dev->state[i].dmabuf.wait);
244 }
245
246 /* allocate dma buffer */
247
248 for (i = 0; i < AD_MAX_STATES; i++) {
249 dmabuf = &dev->state[i].dmabuf;
250 dmabuf->rawbuf = kmalloc(DMA_SIZE, GFP_KERNEL|GFP_DMA);
251 if (!dmabuf->rawbuf)
252 goto err_free_dmabuf;
253 dmabuf->rawbuf_size = DMA_SIZE;
254 dmabuf->dma_handle = 0;
255 dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
256 dmabuf->ready = 0;
257 dmabuf->rate = 48000;
258 }
259 return dev;
260
261err_free_dmabuf:
262 while (--i >= 0)
263 kfree(dev->state[i].dmabuf.rawbuf);
264 kfree(dev);
265 return NULL;
266}
267
268static void ad1889_free_dev(ad1889_dev_t *dev)
269{
270 int j;
271 struct dmabuf *dmabuf;
272
273 if (dev == NULL)
274 return;
275
276 if (dev->ac97_codec)
277 ac97_release_codec(dev->ac97_codec);
278
279 for (j = 0; j < AD_MAX_STATES; j++) {
280 dmabuf = &dev->state[j].dmabuf;
Jesper Juhl09417372005-06-25 14:58:49 -0700281 kfree(dmabuf->rawbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
283
284 kfree(dev);
285}
286
287static inline void ad1889_trigger_playback(ad1889_dev_t *dev)
288{
289#if 0
290 u32 val;
291 struct dmabuf *dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
292#endif
293
294 ad1889_start_wav(&dev->state[AD_WAV_STATE]);
295}
296
297static int ad1889_read_proc (char *page, char **start, off_t off,
298 int count, int *eof, void *data)
299{
300 char *out = page;
301 int len, i;
302 ad1889_dev_t *dev = data;
303 ad1889_reg_t regs[] = {
Stuart Bradye74eb802005-03-01 23:00:56 +0000304 { "WSMC", AD_DS_WSMC, 16 },
305 { "RAMC", AD_DS_RAMC, 16 },
306 { "WADA", AD_DS_WADA, 16 },
307 { "SYDA", AD_DS_SYDA, 16 },
308 { "WAS", AD_DS_WAS, 16 },
309 { "RES", AD_DS_RES, 16 },
310 { "CCS", AD_DS_CCS, 16 },
311 { "ADCBA", AD_DMA_ADCBA, 32 },
312 { "ADCCA", AD_DMA_ADCCA, 32 },
313 { "ADCBC", AD_DMA_ADCBC, 32 },
314 { "ADCCC", AD_DMA_ADCCC, 32 },
315 { "ADCIBC", AD_DMA_ADCIBC, 32 },
316 { "ADCICC", AD_DMA_ADCICC, 32 },
317 { "ADCCTRL", AD_DMA_ADCCTRL, 16 },
318 { "WAVBA", AD_DMA_WAVBA, 32 },
319 { "WAVCA", AD_DMA_WAVCA, 32 },
320 { "WAVBC", AD_DMA_WAVBC, 32 },
321 { "WAVCC", AD_DMA_WAVCC, 32 },
322 { "WAVIBC", AD_DMA_WAVIBC, 32 },
323 { "WAVICC", AD_DMA_WAVICC, 32 },
324 { "WAVCTRL", AD_DMA_WAVCTRL, 16 },
325 { "DISR", AD_DMA_DISR, 32 },
326 { "CHSS", AD_DMA_CHSS, 32 },
327 { "IPC", AD_GPIO_IPC, 16 },
328 { "OP", AD_GPIO_OP, 16 },
329 { "IP", AD_GPIO_IP, 16 },
330 { "ACIC", AD_AC97_ACIC, 16 },
331 { "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
332 { "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
333 { "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
334 { "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
335 { "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
336 { "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
337 { "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
338 { "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
339 { "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
340 { "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
341 { "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
342 { "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
343 { "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
344 { "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
345 { "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
346 { "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
347 { "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
348 { "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
349 { "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
350 { "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 { NULL }
352 };
353
354 if (dev == NULL)
355 return -ENODEV;
356
357 for (i = 0; regs[i].name != 0; i++)
358 out += sprintf(out, "%s: 0x%0*x\n", regs[i].name,
359 regs[i].width >> 2,
360 (regs[i].width == 16
361 ? AD1889_READW(dev, regs[i].offset)
362 : AD1889_READL(dev, regs[i].offset)));
363
364 for (i = 0; i < AD_MAX_STATES; i++) {
365 out += sprintf(out, "DMA status for %s:\n",
366 (i == AD_WAV_STATE ? "WAV" : "ADC"));
367 out += sprintf(out, "\t\t0x%p (IOVA: 0x%llu)\n",
368 dev->state[i].dmabuf.rawbuf,
369 (unsigned long long)dev->state[i].dmabuf.dma_handle);
370
371 out += sprintf(out, "\tread ptr: offset %u\n",
372 (unsigned int)dev->state[i].dmabuf.rd_ptr);
373 out += sprintf(out, "\twrite ptr: offset %u\n",
374 (unsigned int)dev->state[i].dmabuf.wr_ptr);
375 out += sprintf(out, "\tdma len: offset %u\n",
376 (unsigned int)dev->state[i].dmabuf.dma_len);
377 }
378
379 len = out - page - off;
380 if (len < count) {
381 *eof = 1;
382 if (len <= 0) return 0;
383 } else {
384 len = count;
385 }
386 *start = page + off;
387 return len;
388}
389
390/***************************** DMA interfaces ************************** */
391#if 0
392static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
393{
394 struct dmabuf *dmabuf = &state->dmabuf;
395 u32 offset;
396
397 if (!(dmabuf->enable & (DAC_RUNNING | ADC_RUNNING))) {
398 printk(KERN_ERR DEVNAME ": get_dma_addr called without dma enabled\n");
399 return 0;
400 }
401
402 if (dmabuf->enable & DAC_RUNNING)
Stuart Bradye74eb802005-03-01 23:00:56 +0000403 offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 else
Stuart Bradye74eb802005-03-01 23:00:56 +0000405 offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407 return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
408}
409
410static void ad1889_update_ptr(ad1889_dev_t *dev, int wake)
411{
412 ad1889_state_t *state;
413 struct dmabuf *dmabuf;
414 unsigned long hwptr;
415 int diff;
416
417 /* check ADC first */
418 state = &dev->adc_state;
419 dmabuf = &state->dmabuf;
420 if (dmabuf->enable & ADC_RUNNING) {
421 hwptr = ad1889_get_dma_addr(state);
422 diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
423
424 dmabuf->hwptr = hwptr;
425 dmabuf->total_bytes += diff;
426 dmabuf->count += diff;
427 if (dmabuf->count > dmabuf->dmasize)
428 dmabuf->count = dmabuf->dmasize;
429
430 if (dmabuf->mapped) {
431 if (wake & dmabuf->count >= dmabuf->fragsize)
432 wake_up(&dmabuf->wait);
433 } else {
434 if (wake & dmabuf->count > 0)
435 wake_up(&dmabuf->wait);
436 }
437 }
438
439 /* check DAC */
440 state = &dev->wav_state;
441 dmabuf = &state->dmabuf;
442 if (dmabuf->enable & DAC_RUNNING) {
443XXX
444
445}
446#endif
447
448/************************* /dev/dsp interfaces ************************* */
449
450static ssize_t ad1889_read(struct file *file, char __user *buffer, size_t count,
451 loff_t *ppos)
452{
453 return 0;
454}
455
456static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t count,
457 loff_t *ppos)
458{
459 ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
460 ad1889_state_t *state = &dev->state[AD_WAV_STATE];
461 volatile struct dmabuf *dmabuf = &state->dmabuf;
462 ssize_t ret = 0;
463 DECLARE_WAITQUEUE(wait, current);
464
Ingo Molnar910f5d22006-03-23 03:00:39 -0800465 mutex_lock(&state->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466#if 0
467 if (dmabuf->mapped) {
468 ret = -ENXIO;
469 goto err1;
470 }
471#endif
472 if (!access_ok(VERIFY_READ, buffer, count)) {
473 ret = -EFAULT;
474 goto err1;
475 }
476
477 add_wait_queue(&state->dmabuf.wait, &wait);
478
479 /* start filling dma buffer.... */
480 while (count > 0) {
481 long rem;
482 long cnt = count;
483 unsigned long flags;
484
485 for (;;) {
486 long used_bytes;
487 long timeout; /* max time for DMA in jiffies */
488
489 /* buffer is full if wr catches up to rd */
490 spin_lock_irqsave(&state->card->lock, flags);
491 used_bytes = dmabuf->wr_ptr - dmabuf->rd_ptr;
492 timeout = (dmabuf->dma_len * HZ) / dmabuf->rate;
493 spin_unlock_irqrestore(&state->card->lock, flags);
494
495 /* adjust for buffer wrap around */
496 used_bytes = (used_bytes + DMA_SIZE) & (DMA_SIZE - 1);
497
498 /* If at least one page unused */
499 if (used_bytes < (DMA_SIZE - 0x1000))
500 break;
501
502 /* dma buffer full */
503
504 if (file->f_flags & O_NONBLOCK) {
505 ret = -EAGAIN;
506 goto err2;
507 }
508
509 set_current_state(TASK_INTERRUPTIBLE);
510 schedule_timeout(timeout + 1);
511 if (signal_pending(current)) {
512 ret = -ERESTARTSYS;
513 goto err2;
514 }
515 }
516
517 /* watch out for wrapping around static buffer */
518 spin_lock_irqsave(&state->card->lock, flags);
519 rem = DMA_SIZE - dmabuf->wr_ptr;
520 if (cnt > rem)
521 cnt = rem;
522
523 rem = dmabuf->wr_ptr;
524
525 /* update dma pointers */
526 dmabuf->wr_ptr += cnt;
527 dmabuf->wr_ptr &= DMA_SIZE - 1; /* wrap ptr if necessary */
528 spin_unlock_irqrestore(&state->card->lock, flags);
529
530 /* transfer unwrapped chunk */
531 if (copy_from_user(dmabuf->rawbuf + rem, buffer, cnt)) {
532 ret = -EFAULT;
533 goto err2;
534 }
535
536 DBG("Writing 0x%lx bytes to +0x%lx\n", cnt, rem);
537
538 /* update counters */
539 count -= cnt;
540 buffer += cnt;
541 ret += cnt;
542
543 /* we have something to play - go play it! */
544 ad1889_trigger_playback(dev);
545 }
546
547err2:
548 remove_wait_queue(&state->dmabuf.wait, &wait);
549err1:
Ingo Molnar910f5d22006-03-23 03:00:39 -0800550 mutex_unlock(&state->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 return ret;
552}
553
554static unsigned int ad1889_poll(struct file *file, struct poll_table_struct *wait)
555{
556 unsigned int mask = 0;
557#if 0
558 ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
559 ad1889_state_t *state = NULL;
560 struct dmabuf *dmabuf;
561 unsigned long flags;
562
563 if (!(file->f_mode & (FMODE_READ | FMODE_WRITE)))
564 return -EINVAL;
565
566 if (file->f_mode & FMODE_WRITE) {
567 state = &dev->state[AD_WAV_STATE];
568 if (!state) return 0;
569 dmabuf = &state->dmabuf;
570 poll_wait(file, &dmabuf->wait, wait);
571 }
572
573 if (file->f_mode & FMODE_READ) {
574 state = &dev->state[AD_ADC_STATE];
575 if (!state) return 0;
576 dmabuf = &state->dmabuf;
577 poll_wait(file, &dmabuf->wait, wait);
578 }
579
580 spin_lock_irqsave(&dev->lock, flags);
581 ad1889_update_ptr(dev, 0);
582
583 if (file->f_mode & FMODE_WRITE) {
584 state = &dev->state[WAV_STATE];
585 dmabuf = &state->dmabuf;
586 if (dmabuf->mapped) {
587 if (dmabuf->count >= (int)dmabuf->fragsize)
588 mask |= POLLOUT | POLLWRNORM;
589 } else {
590 if ((int)dmabuf->dmasize >= dmabuf->count +
591 (int)dmabuf->fragsize)
592 mask |= POLLOUT | POLLWRNORM;
593 }
594 }
595
596 if (file ->f_mode & FMODE_READ) {
597 state = &dev->state[AD_ADC_STATE];
598 dmabuf = &state->dmabuf;
599 if (dmabuf->count >= (int)dmabuf->fragsize)
600 mask |= POLLIN | POLLRDNORM;
601 }
602 spin_unlock_irqrestore(&dev->lock, flags);
603
604#endif
605 return mask;
606}
607
608static int ad1889_mmap(struct file *file, struct vm_area_struct *vma)
609{
610 return 0;
611}
612
613static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
614 unsigned long arg)
615{
616 int val = 0;
617 ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
618 struct dmabuf *dmabuf;
619 audio_buf_info abinfo;
620 int __user *p = (int __user *)arg;
621
622 DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
623
624 switch (cmd)
625 {
626 case OSS_GETVERSION:
627 return put_user(SOUND_VERSION, p);
628
629 case SNDCTL_DSP_RESET:
630 break;
631
632 case SNDCTL_DSP_SYNC:
633 break;
634
635 case SNDCTL_DSP_SPEED:
636 /* set sampling rate */
637 if (get_user(val, p))
638 return -EFAULT;
639 if (val > 5400 && val < 48000)
640 {
641 if (file->f_mode & FMODE_WRITE)
Stuart Bradye74eb802005-03-01 23:00:56 +0000642 AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 if (file->f_mode & FMODE_READ)
Stuart Bradye74eb802005-03-01 23:00:56 +0000644 AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 }
646 return 0;
647
648 case SNDCTL_DSP_STEREO: /* undocumented? */
649 if (get_user(val, p))
650 return -EFAULT;
651 if (file->f_mode & FMODE_READ) {
Stuart Bradye74eb802005-03-01 23:00:56 +0000652 val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 if (val) {
654 val |= 0x0200; /* set WAST */
655 } else {
656 val &= ~0x0200; /* clear WAST */
657 }
Stuart Bradye74eb802005-03-01 23:00:56 +0000658 AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 }
660 if (file->f_mode & FMODE_WRITE) {
Stuart Bradye74eb802005-03-01 23:00:56 +0000661 val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 if (val) {
663 val |= 0x0002; /* set ADST */
664 } else {
665 val &= ~0x0002; /* clear ADST */
666 }
Stuart Bradye74eb802005-03-01 23:00:56 +0000667 AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 }
669
670 return 0;
671
672 case SNDCTL_DSP_GETBLKSIZE:
673 return put_user(DMA_SIZE, p);
674
675 case SNDCTL_DSP_GETFMTS:
676 return put_user(AFMT_S16_LE|AFMT_U8, p);
677
678 case SNDCTL_DSP_SETFMT:
679 if (get_user(val, p))
680 return -EFAULT;
681
682 if (val == 0) {
683 if (file->f_mode & FMODE_READ)
684 ad1889_set_adc_fmt(dev, val);
685
686 if (file->f_mode & FMODE_WRITE)
687 ad1889_set_wav_fmt(dev, val);
688 } else {
689 val = AFMT_S16_LE | AFMT_U8;
690 }
691
692 return put_user(val, p);
693
694 case SNDCTL_DSP_CHANNELS:
695 break;
696
697 case SNDCTL_DSP_POST:
698 /* send all data to device */
699 break;
700
701 case SNDCTL_DSP_SUBDIVIDE:
702 break;
703
704 case SNDCTL_DSP_SETFRAGMENT:
705 /* not supported; uses fixed fragment sizes */
706 return put_user(DMA_SIZE, p);
707
708 case SNDCTL_DSP_GETOSPACE:
709 case SNDCTL_DSP_GETISPACE:
710 /* space left in dma buffers */
711 if (cmd == SNDCTL_DSP_GETOSPACE)
712 dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
713 else
714 dmabuf = &dev->state[AD_ADC_STATE].dmabuf;
715 abinfo.fragments = 1;
716 abinfo.fragstotal = 1;
717 abinfo.fragsize = DMA_SIZE;
718 abinfo.bytes = DMA_SIZE;
719 return copy_to_user(p, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
720 case SNDCTL_DSP_NONBLOCK:
721 file->f_flags |= O_NONBLOCK;
722 return 0;
723
724 case SNDCTL_DSP_GETCAPS:
725 return put_user(0, p);
726
727 case SNDCTL_DSP_GETTRIGGER:
728 case SNDCTL_DSP_SETTRIGGER:
729 break;
730
731 case SNDCTL_DSP_GETIPTR:
732 case SNDCTL_DSP_GETOPTR:
733 break;
734
735 case SNDCTL_DSP_SETDUPLEX:
736 break;
737
738 case SNDCTL_DSP_GETODELAY:
739 break;
740
741 case SOUND_PCM_READ_RATE:
Stuart Bradye74eb802005-03-01 23:00:56 +0000742 return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
744 case SOUND_PCM_READ_CHANNELS:
745 case SOUND_PCM_READ_BITS:
746 break;
747
748 case SNDCTL_DSP_MAPINBUF:
749 case SNDCTL_DSP_MAPOUTBUF:
750 case SNDCTL_DSP_SETSYNCRO:
751 case SOUND_PCM_WRITE_FILTER:
752 case SOUND_PCM_READ_FILTER:
753 break;
754
755 default:
756 break;
757 }
758
759 return -ENOTTY;
760}
761
762static int ad1889_open(struct inode *inode, struct file *file)
763{
764 /* check minor; only support /dev/dsp atm */
765 if (iminor(inode) != 3)
766 return -ENXIO;
767
768 file->private_data = ad1889_dev;
769
770 ad1889_set_wav_rate(ad1889_dev, 48000);
771 ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
Stuart Bradye74eb802005-03-01 23:00:56 +0000772 AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 return nonseekable_open(inode, file);
774}
775
776static int ad1889_release(struct inode *inode, struct file *file)
777{
778 /* if we have state free it here */
779 return 0;
780}
781
782static struct file_operations ad1889_fops = {
783 .owner = THIS_MODULE,
784 .llseek = no_llseek,
785 .read = ad1889_read,
786 .write = ad1889_write,
787 .poll = ad1889_poll,
788 .ioctl = ad1889_ioctl,
789 .mmap = ad1889_mmap,
790 .open = ad1889_open,
791 .release = ad1889_release,
792};
793
794/************************* /dev/mixer interfaces ************************ */
795static int ad1889_mixer_open(struct inode *inode, struct file *file)
796{
797 if (ad1889_dev->ac97_codec->dev_mixer != iminor(inode))
798 return -ENODEV;
799
800 file->private_data = ad1889_dev->ac97_codec;
801 return 0;
802}
803
804static int ad1889_mixer_release(struct inode *inode, struct file *file)
805{
806 return 0;
807}
808
809static int ad1889_mixer_ioctl(struct inode *inode, struct file *file,
810 unsigned int cmd, unsigned long arg)
811{
812 struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
813 return codec->mixer_ioctl(codec, cmd, arg);
814}
815
816static struct file_operations ad1889_mixer_fops = {
817 .owner = THIS_MODULE,
818 .llseek = no_llseek,
819 .ioctl = ad1889_mixer_ioctl,
820 .open = ad1889_mixer_open,
821 .release = ad1889_mixer_release,
822};
823
824/************************* AC97 interfaces ****************************** */
825static void ad1889_codec_write(struct ac97_codec *ac97, u8 reg, u16 val)
826{
827 ad1889_dev_t *dev = ac97->private_data;
828
Stuart Bradye74eb802005-03-01 23:00:56 +0000829 //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
830 AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831}
832
833static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
834{
835 ad1889_dev_t *dev = ac97->private_data;
Stuart Bradye74eb802005-03-01 23:00:56 +0000836 //DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
837 return AD1889_READW(dev, AD_AC97_BASE + reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838}
839
840static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
841{
842 struct ac97_codec *ac97;
843 u16 eid;
844
845 if ((ac97 = ac97_alloc_codec()) == NULL)
846 return -ENOMEM;
847
848 ac97->private_data = dev;
849 ac97->id = id;
850
851 ac97->codec_read = ad1889_codec_read;
852 ac97->codec_write = ad1889_codec_write;
853
854 if (ac97_probe_codec(ac97) == 0) {
855 printk(DEVNAME ": ac97_probe_codec failed\n");
856 goto out_free;
857 }
858
859 eid = ad1889_codec_read(ac97, AC97_EXTENDED_ID);
860 if (eid == 0xffff) {
861 printk(KERN_WARNING DEVNAME ": no codec attached?\n");
862 goto out_free;
863 }
864
865 dev->ac97_features = eid;
866
867 if ((ac97->dev_mixer = register_sound_mixer(&ad1889_mixer_fops, -1)) < 0) {
868 printk(KERN_ERR DEVNAME ": cannot register mixer\n");
869 goto out_free;
870 }
871
872 dev->ac97_codec = ac97;
873 return 0;
874
875out_free:
876 ac97_release_codec(ac97);
877 return -ENODEV;
878}
879
880static int ad1889_aclink_reset(struct pci_dev * pcidev)
881{
882 u16 stat;
883 int retry = 200;
884 ad1889_dev_t *dev = pci_get_drvdata(pcidev);
885
Stuart Bradye74eb802005-03-01 23:00:56 +0000886 AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
887 AD1889_READW(dev, AD_DS_CCS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
889 WAIT_10MS();
890
Stuart Bradye74eb802005-03-01 23:00:56 +0000891 stat = AD1889_READW(dev, AD_AC97_ACIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 stat |= 0x0002; /* Reset Disable */
Stuart Bradye74eb802005-03-01 23:00:56 +0000893 AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
894 (void) AD1889_READW(dev, AD_AC97_ACIC); /* flush posted write */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
896 udelay(10);
897
Stuart Bradye74eb802005-03-01 23:00:56 +0000898 stat = AD1889_READW(dev, AD_AC97_ACIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 stat |= 0x0001; /* Interface Enable */
Stuart Bradye74eb802005-03-01 23:00:56 +0000900 AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 do {
Stuart Bradye74eb802005-03-01 23:00:56 +0000903 if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000) /* Ready */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 break;
905 WAIT_10MS();
906 retry--;
907 } while (retry > 0);
908
909 if (!retry) {
910 printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
Stuart Bradye74eb802005-03-01 23:00:56 +0000911 AD1889_READW(dev, AD_AC97_ACIC));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 return -EBUSY;
913 }
914
915 /* TODO reset AC97 codec */
916 /* TODO set wave/adc pci ctrl status */
917
Stuart Bradye74eb802005-03-01 23:00:56 +0000918 stat = AD1889_READW(dev, AD_AC97_ACIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 stat |= 0x0004; /* Audio Stream Output Enable */
Stuart Bradye74eb802005-03-01 23:00:56 +0000920 AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 return 0;
922}
923
924/************************* PCI interfaces ****************************** */
925/* PCI device table */
926static struct pci_device_id ad1889_id_tbl[] = {
927 { PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS, PCI_ANY_ID,
928 PCI_ANY_ID, 0, 0, (unsigned long)DEVNAME },
929 { },
930};
931MODULE_DEVICE_TABLE(pci, ad1889_id_tbl);
932
933static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
934{
935 u32 stat;
936 ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
937
Stuart Bradye74eb802005-03-01 23:00:56 +0000938 stat = AD1889_READL(dev, AD_DMA_DISR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
940 /* clear ISR */
Stuart Bradye74eb802005-03-01 23:00:56 +0000941 AD1889_WRITEL(dev, AD_DMA_DISR, stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
943 if (stat & 0x8) { /* WAVI */
944 DBG("WAV interrupt\n");
945 dev->stats.wav_intrs++;
946 if (dev->state[AD_WAV_STATE].dmabuf.ready) {
947 ad1889_stop_wav(&dev->state[AD_WAV_STATE]); /* clean up */
948 ad1889_start_wav(&dev->state[AD_WAV_STATE]); /* start new */
949 }
950 }
951
952 if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
953 DBG("ADC interrupt\n");
954 dev->stats.adc_intrs++;
955 }
956 if(stat)
957 return IRQ_HANDLED;
958 return IRQ_NONE;
959}
960
961static void ad1889_initcfg(ad1889_dev_t *dev)
962{
963 u16 tmp16;
964 u32 tmp32;
965
966 /* make sure the interrupt bits are setup the way we want */
Stuart Bradye74eb802005-03-01 23:00:56 +0000967 tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
969 tmp32 |= 0x6; /* intr on count, loop */
Stuart Bradye74eb802005-03-01 23:00:56 +0000970 AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972 /* unmute... */
Stuart Bradye74eb802005-03-01 23:00:56 +0000973 tmp16 = AD1889_READW(dev, AD_DS_WADA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 tmp16 &= ~0x8080;
Stuart Bradye74eb802005-03-01 23:00:56 +0000975 AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976}
977
978static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
979{
980 int err;
981 ad1889_dev_t *dev;
982 unsigned long bar;
983 struct proc_dir_entry *proc_root = NULL;
984
985 if ((err = pci_enable_device(pcidev)) != 0) {
986 printk(KERN_ERR DEVNAME ": pci_enable_device failed\n");
987 return err;
988 }
989
990 pci_set_master(pcidev);
991 if ((dev = ad1889_alloc_dev(pcidev)) == NULL) {
992 printk(KERN_ERR DEVNAME ": cannot allocate memory for device\n");
993 return -ENOMEM;
994 }
995 pci_set_drvdata(pcidev, dev);
996 bar = pci_resource_start(pcidev, 0);
997
998 if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
999 printk(KERN_ERR DEVNAME ": memory region not assigned\n");
1000 goto out1;
1001 }
1002
1003 if (pci_request_region(pcidev, 0, DEVNAME)) {
1004 printk(KERN_ERR DEVNAME ": unable to request memory region\n");
1005 goto out1;
1006 }
1007
Stuart Bradye74eb802005-03-01 23:00:56 +00001008 dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 if (!dev->regbase) {
1010 printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
1011 goto out2;
1012 }
1013
1014 if (request_irq(pcidev->irq, ad1889_interrupt, SA_SHIRQ, DEVNAME, dev) != 0) {
1015 printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
1016 goto out3;
1017 }
1018
1019 printk(KERN_INFO DEVNAME ": %s at %p IRQ %d\n",
1020 (char *)ent->driver_data, dev->regbase, pcidev->irq);
1021
1022 if (ad1889_aclink_reset(pcidev) != 0)
1023 goto out4;
1024
1025 /* register /dev/dsp */
1026 if ((dev->dev_audio = register_sound_dsp(&ad1889_fops, -1)) < 0) {
1027 printk(KERN_ERR DEVNAME ": cannot register /dev/dsp\n");
1028 goto out4;
1029 }
1030
1031 if ((err = ad1889_ac97_init(dev, 0)) != 0)
1032 goto out5;
1033
1034 /* XXX: cleanups */
1035 if (((proc_root = proc_mkdir("driver/ad1889", NULL)) == NULL) ||
1036 create_proc_read_entry("ac97", S_IFREG|S_IRUGO, proc_root, ac97_read_proc, dev->ac97_codec) == NULL ||
1037 create_proc_read_entry("info", S_IFREG|S_IRUGO, proc_root, ad1889_read_proc, dev) == NULL)
1038 goto out5;
1039
1040 ad1889_initcfg(dev);
1041
1042 //DBG(DEVNAME ": Driver initialization done!\n");
1043
1044 ad1889_dev = dev;
1045
1046 return 0;
1047
1048out5:
1049 unregister_sound_dsp(dev->dev_audio);
1050out4:
1051 free_irq(pcidev->irq, dev);
1052out3:
1053 iounmap(dev->regbase);
1054out2:
1055 pci_release_region(pcidev, 0);
1056out1:
1057 ad1889_free_dev(dev);
1058 pci_set_drvdata(pcidev, NULL);
1059
1060 return -ENODEV;
1061}
1062
1063static void __devexit ad1889_remove(struct pci_dev *pcidev)
1064{
1065 ad1889_dev_t *dev = pci_get_drvdata(pcidev);
1066
1067 if (dev == NULL) return;
1068
1069 unregister_sound_mixer(dev->ac97_codec->dev_mixer);
1070 unregister_sound_dsp(dev->dev_audio);
1071 free_irq(pcidev->irq, dev);
1072 iounmap(dev->regbase);
1073 pci_release_region(pcidev, 0);
1074
1075 /* any hw programming needed? */
1076 ad1889_free_dev(dev);
1077 pci_set_drvdata(pcidev, NULL);
1078}
1079
1080MODULE_AUTHOR("Randolph Chung");
1081MODULE_DESCRIPTION("Analog Devices AD1889 PCI Audio");
1082MODULE_LICENSE("GPL");
1083
1084static struct pci_driver ad1889_driver = {
1085 .name = DEVNAME,
1086 .id_table = ad1889_id_tbl,
1087 .probe = ad1889_probe,
1088 .remove = __devexit_p(ad1889_remove),
1089};
1090
1091static int __init ad1889_init_module(void)
1092{
Greg Kroah-Hartman46654722005-12-06 15:33:15 -08001093 return pci_register_driver(&ad1889_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
1096static void ad1889_exit_module(void)
1097{
1098 pci_unregister_driver(&ad1889_driver);
1099 return;
1100}
1101
1102module_init(ad1889_init_module);
1103module_exit(ad1889_exit_module);