Commit f23f6e08c47acbdd20e9c49a79da8c404ea168e1
1 parent
d7fe0f241d
Exists in
master
and in
40 other branches
[PATCH] severing poll.h -> mm.h
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 12 changed files with 13 additions and 1 deletions Inline Diff
drivers/char/hpet.c
1 | /* | 1 | /* |
2 | * Intel & MS High Precision Event Timer Implementation. | 2 | * Intel & MS High Precision Event Timer Implementation. |
3 | * | 3 | * |
4 | * Copyright (C) 2003 Intel Corporation | 4 | * Copyright (C) 2003 Intel Corporation |
5 | * Venki Pallipadi | 5 | * Venki Pallipadi |
6 | * (c) Copyright 2004 Hewlett-Packard Development Company, L.P. | 6 | * (c) Copyright 2004 Hewlett-Packard Development Company, L.P. |
7 | * Bob Picco <robert.picco@hp.com> | 7 | * Bob Picco <robert.picco@hp.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/miscdevice.h> | 18 | #include <linux/miscdevice.h> |
19 | #include <linux/major.h> | 19 | #include <linux/major.h> |
20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
21 | #include <linux/fcntl.h> | 21 | #include <linux/fcntl.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/poll.h> | 23 | #include <linux/poll.h> |
24 | #include <linux/mm.h> | ||
24 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
25 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
26 | #include <linux/sysctl.h> | 27 | #include <linux/sysctl.h> |
27 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
28 | #include <linux/bcd.h> | 29 | #include <linux/bcd.h> |
29 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
30 | #include <linux/bitops.h> | 31 | #include <linux/bitops.h> |
31 | 32 | ||
32 | #include <asm/current.h> | 33 | #include <asm/current.h> |
33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
37 | #include <asm/div64.h> | 38 | #include <asm/div64.h> |
38 | 39 | ||
39 | #include <linux/acpi.h> | 40 | #include <linux/acpi.h> |
40 | #include <acpi/acpi_bus.h> | 41 | #include <acpi/acpi_bus.h> |
41 | #include <linux/hpet.h> | 42 | #include <linux/hpet.h> |
42 | 43 | ||
43 | /* | 44 | /* |
44 | * The High Precision Event Timer driver. | 45 | * The High Precision Event Timer driver. |
45 | * This driver is closely modelled after the rtc.c driver. | 46 | * This driver is closely modelled after the rtc.c driver. |
46 | * http://www.intel.com/hardwaredesign/hpetspec.htm | 47 | * http://www.intel.com/hardwaredesign/hpetspec.htm |
47 | */ | 48 | */ |
48 | #define HPET_USER_FREQ (64) | 49 | #define HPET_USER_FREQ (64) |
49 | #define HPET_DRIFT (500) | 50 | #define HPET_DRIFT (500) |
50 | 51 | ||
51 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ | 52 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ |
52 | 53 | ||
53 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; | 54 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; |
54 | 55 | ||
55 | /* A lock for concurrent access by app and isr hpet activity. */ | 56 | /* A lock for concurrent access by app and isr hpet activity. */ |
56 | static DEFINE_SPINLOCK(hpet_lock); | 57 | static DEFINE_SPINLOCK(hpet_lock); |
57 | /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ | 58 | /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ |
58 | static DEFINE_SPINLOCK(hpet_task_lock); | 59 | static DEFINE_SPINLOCK(hpet_task_lock); |
59 | 60 | ||
60 | #define HPET_DEV_NAME (7) | 61 | #define HPET_DEV_NAME (7) |
61 | 62 | ||
62 | struct hpet_dev { | 63 | struct hpet_dev { |
63 | struct hpets *hd_hpets; | 64 | struct hpets *hd_hpets; |
64 | struct hpet __iomem *hd_hpet; | 65 | struct hpet __iomem *hd_hpet; |
65 | struct hpet_timer __iomem *hd_timer; | 66 | struct hpet_timer __iomem *hd_timer; |
66 | unsigned long hd_ireqfreq; | 67 | unsigned long hd_ireqfreq; |
67 | unsigned long hd_irqdata; | 68 | unsigned long hd_irqdata; |
68 | wait_queue_head_t hd_waitqueue; | 69 | wait_queue_head_t hd_waitqueue; |
69 | struct fasync_struct *hd_async_queue; | 70 | struct fasync_struct *hd_async_queue; |
70 | struct hpet_task *hd_task; | 71 | struct hpet_task *hd_task; |
71 | unsigned int hd_flags; | 72 | unsigned int hd_flags; |
72 | unsigned int hd_irq; | 73 | unsigned int hd_irq; |
73 | unsigned int hd_hdwirq; | 74 | unsigned int hd_hdwirq; |
74 | char hd_name[HPET_DEV_NAME]; | 75 | char hd_name[HPET_DEV_NAME]; |
75 | }; | 76 | }; |
76 | 77 | ||
77 | struct hpets { | 78 | struct hpets { |
78 | struct hpets *hp_next; | 79 | struct hpets *hp_next; |
79 | struct hpet __iomem *hp_hpet; | 80 | struct hpet __iomem *hp_hpet; |
80 | unsigned long hp_hpet_phys; | 81 | unsigned long hp_hpet_phys; |
81 | struct time_interpolator *hp_interpolator; | 82 | struct time_interpolator *hp_interpolator; |
82 | unsigned long long hp_tick_freq; | 83 | unsigned long long hp_tick_freq; |
83 | unsigned long hp_delta; | 84 | unsigned long hp_delta; |
84 | unsigned int hp_ntimer; | 85 | unsigned int hp_ntimer; |
85 | unsigned int hp_which; | 86 | unsigned int hp_which; |
86 | struct hpet_dev hp_dev[1]; | 87 | struct hpet_dev hp_dev[1]; |
87 | }; | 88 | }; |
88 | 89 | ||
89 | static struct hpets *hpets; | 90 | static struct hpets *hpets; |
90 | 91 | ||
91 | #define HPET_OPEN 0x0001 | 92 | #define HPET_OPEN 0x0001 |
92 | #define HPET_IE 0x0002 /* interrupt enabled */ | 93 | #define HPET_IE 0x0002 /* interrupt enabled */ |
93 | #define HPET_PERIODIC 0x0004 | 94 | #define HPET_PERIODIC 0x0004 |
94 | #define HPET_SHARED_IRQ 0x0008 | 95 | #define HPET_SHARED_IRQ 0x0008 |
95 | 96 | ||
96 | #if BITS_PER_LONG == 64 | 97 | #if BITS_PER_LONG == 64 |
97 | #define write_counter(V, MC) writeq(V, MC) | 98 | #define write_counter(V, MC) writeq(V, MC) |
98 | #define read_counter(MC) readq(MC) | 99 | #define read_counter(MC) readq(MC) |
99 | #else | 100 | #else |
100 | #define write_counter(V, MC) writel(V, MC) | 101 | #define write_counter(V, MC) writel(V, MC) |
101 | #define read_counter(MC) readl(MC) | 102 | #define read_counter(MC) readl(MC) |
102 | #endif | 103 | #endif |
103 | 104 | ||
104 | #ifndef readq | 105 | #ifndef readq |
105 | static inline unsigned long long readq(void __iomem *addr) | 106 | static inline unsigned long long readq(void __iomem *addr) |
106 | { | 107 | { |
107 | return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL); | 108 | return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL); |
108 | } | 109 | } |
109 | #endif | 110 | #endif |
110 | 111 | ||
111 | #ifndef writeq | 112 | #ifndef writeq |
112 | static inline void writeq(unsigned long long v, void __iomem *addr) | 113 | static inline void writeq(unsigned long long v, void __iomem *addr) |
113 | { | 114 | { |
114 | writel(v & 0xffffffff, addr); | 115 | writel(v & 0xffffffff, addr); |
115 | writel(v >> 32, addr + 4); | 116 | writel(v >> 32, addr + 4); |
116 | } | 117 | } |
117 | #endif | 118 | #endif |
118 | 119 | ||
119 | static irqreturn_t hpet_interrupt(int irq, void *data) | 120 | static irqreturn_t hpet_interrupt(int irq, void *data) |
120 | { | 121 | { |
121 | struct hpet_dev *devp; | 122 | struct hpet_dev *devp; |
122 | unsigned long isr; | 123 | unsigned long isr; |
123 | 124 | ||
124 | devp = data; | 125 | devp = data; |
125 | isr = 1 << (devp - devp->hd_hpets->hp_dev); | 126 | isr = 1 << (devp - devp->hd_hpets->hp_dev); |
126 | 127 | ||
127 | if ((devp->hd_flags & HPET_SHARED_IRQ) && | 128 | if ((devp->hd_flags & HPET_SHARED_IRQ) && |
128 | !(isr & readl(&devp->hd_hpet->hpet_isr))) | 129 | !(isr & readl(&devp->hd_hpet->hpet_isr))) |
129 | return IRQ_NONE; | 130 | return IRQ_NONE; |
130 | 131 | ||
131 | spin_lock(&hpet_lock); | 132 | spin_lock(&hpet_lock); |
132 | devp->hd_irqdata++; | 133 | devp->hd_irqdata++; |
133 | 134 | ||
134 | /* | 135 | /* |
135 | * For non-periodic timers, increment the accumulator. | 136 | * For non-periodic timers, increment the accumulator. |
136 | * This has the effect of treating non-periodic like periodic. | 137 | * This has the effect of treating non-periodic like periodic. |
137 | */ | 138 | */ |
138 | if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) { | 139 | if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) { |
139 | unsigned long m, t; | 140 | unsigned long m, t; |
140 | 141 | ||
141 | t = devp->hd_ireqfreq; | 142 | t = devp->hd_ireqfreq; |
142 | m = read_counter(&devp->hd_hpet->hpet_mc); | 143 | m = read_counter(&devp->hd_hpet->hpet_mc); |
143 | write_counter(t + m + devp->hd_hpets->hp_delta, | 144 | write_counter(t + m + devp->hd_hpets->hp_delta, |
144 | &devp->hd_timer->hpet_compare); | 145 | &devp->hd_timer->hpet_compare); |
145 | } | 146 | } |
146 | 147 | ||
147 | if (devp->hd_flags & HPET_SHARED_IRQ) | 148 | if (devp->hd_flags & HPET_SHARED_IRQ) |
148 | writel(isr, &devp->hd_hpet->hpet_isr); | 149 | writel(isr, &devp->hd_hpet->hpet_isr); |
149 | spin_unlock(&hpet_lock); | 150 | spin_unlock(&hpet_lock); |
150 | 151 | ||
151 | spin_lock(&hpet_task_lock); | 152 | spin_lock(&hpet_task_lock); |
152 | if (devp->hd_task) | 153 | if (devp->hd_task) |
153 | devp->hd_task->ht_func(devp->hd_task->ht_data); | 154 | devp->hd_task->ht_func(devp->hd_task->ht_data); |
154 | spin_unlock(&hpet_task_lock); | 155 | spin_unlock(&hpet_task_lock); |
155 | 156 | ||
156 | wake_up_interruptible(&devp->hd_waitqueue); | 157 | wake_up_interruptible(&devp->hd_waitqueue); |
157 | 158 | ||
158 | kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN); | 159 | kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN); |
159 | 160 | ||
160 | return IRQ_HANDLED; | 161 | return IRQ_HANDLED; |
161 | } | 162 | } |
162 | 163 | ||
163 | static int hpet_open(struct inode *inode, struct file *file) | 164 | static int hpet_open(struct inode *inode, struct file *file) |
164 | { | 165 | { |
165 | struct hpet_dev *devp; | 166 | struct hpet_dev *devp; |
166 | struct hpets *hpetp; | 167 | struct hpets *hpetp; |
167 | int i; | 168 | int i; |
168 | 169 | ||
169 | if (file->f_mode & FMODE_WRITE) | 170 | if (file->f_mode & FMODE_WRITE) |
170 | return -EINVAL; | 171 | return -EINVAL; |
171 | 172 | ||
172 | spin_lock_irq(&hpet_lock); | 173 | spin_lock_irq(&hpet_lock); |
173 | 174 | ||
174 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) | 175 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) |
175 | for (i = 0; i < hpetp->hp_ntimer; i++) | 176 | for (i = 0; i < hpetp->hp_ntimer; i++) |
176 | if (hpetp->hp_dev[i].hd_flags & HPET_OPEN | 177 | if (hpetp->hp_dev[i].hd_flags & HPET_OPEN |
177 | || hpetp->hp_dev[i].hd_task) | 178 | || hpetp->hp_dev[i].hd_task) |
178 | continue; | 179 | continue; |
179 | else { | 180 | else { |
180 | devp = &hpetp->hp_dev[i]; | 181 | devp = &hpetp->hp_dev[i]; |
181 | break; | 182 | break; |
182 | } | 183 | } |
183 | 184 | ||
184 | if (!devp) { | 185 | if (!devp) { |
185 | spin_unlock_irq(&hpet_lock); | 186 | spin_unlock_irq(&hpet_lock); |
186 | return -EBUSY; | 187 | return -EBUSY; |
187 | } | 188 | } |
188 | 189 | ||
189 | file->private_data = devp; | 190 | file->private_data = devp; |
190 | devp->hd_irqdata = 0; | 191 | devp->hd_irqdata = 0; |
191 | devp->hd_flags |= HPET_OPEN; | 192 | devp->hd_flags |= HPET_OPEN; |
192 | spin_unlock_irq(&hpet_lock); | 193 | spin_unlock_irq(&hpet_lock); |
193 | 194 | ||
194 | return 0; | 195 | return 0; |
195 | } | 196 | } |
196 | 197 | ||
197 | static ssize_t | 198 | static ssize_t |
198 | hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) | 199 | hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) |
199 | { | 200 | { |
200 | DECLARE_WAITQUEUE(wait, current); | 201 | DECLARE_WAITQUEUE(wait, current); |
201 | unsigned long data; | 202 | unsigned long data; |
202 | ssize_t retval; | 203 | ssize_t retval; |
203 | struct hpet_dev *devp; | 204 | struct hpet_dev *devp; |
204 | 205 | ||
205 | devp = file->private_data; | 206 | devp = file->private_data; |
206 | if (!devp->hd_ireqfreq) | 207 | if (!devp->hd_ireqfreq) |
207 | return -EIO; | 208 | return -EIO; |
208 | 209 | ||
209 | if (count < sizeof(unsigned long)) | 210 | if (count < sizeof(unsigned long)) |
210 | return -EINVAL; | 211 | return -EINVAL; |
211 | 212 | ||
212 | add_wait_queue(&devp->hd_waitqueue, &wait); | 213 | add_wait_queue(&devp->hd_waitqueue, &wait); |
213 | 214 | ||
214 | for ( ; ; ) { | 215 | for ( ; ; ) { |
215 | set_current_state(TASK_INTERRUPTIBLE); | 216 | set_current_state(TASK_INTERRUPTIBLE); |
216 | 217 | ||
217 | spin_lock_irq(&hpet_lock); | 218 | spin_lock_irq(&hpet_lock); |
218 | data = devp->hd_irqdata; | 219 | data = devp->hd_irqdata; |
219 | devp->hd_irqdata = 0; | 220 | devp->hd_irqdata = 0; |
220 | spin_unlock_irq(&hpet_lock); | 221 | spin_unlock_irq(&hpet_lock); |
221 | 222 | ||
222 | if (data) | 223 | if (data) |
223 | break; | 224 | break; |
224 | else if (file->f_flags & O_NONBLOCK) { | 225 | else if (file->f_flags & O_NONBLOCK) { |
225 | retval = -EAGAIN; | 226 | retval = -EAGAIN; |
226 | goto out; | 227 | goto out; |
227 | } else if (signal_pending(current)) { | 228 | } else if (signal_pending(current)) { |
228 | retval = -ERESTARTSYS; | 229 | retval = -ERESTARTSYS; |
229 | goto out; | 230 | goto out; |
230 | } | 231 | } |
231 | schedule(); | 232 | schedule(); |
232 | } | 233 | } |
233 | 234 | ||
234 | retval = put_user(data, (unsigned long __user *)buf); | 235 | retval = put_user(data, (unsigned long __user *)buf); |
235 | if (!retval) | 236 | if (!retval) |
236 | retval = sizeof(unsigned long); | 237 | retval = sizeof(unsigned long); |
237 | out: | 238 | out: |
238 | __set_current_state(TASK_RUNNING); | 239 | __set_current_state(TASK_RUNNING); |
239 | remove_wait_queue(&devp->hd_waitqueue, &wait); | 240 | remove_wait_queue(&devp->hd_waitqueue, &wait); |
240 | 241 | ||
241 | return retval; | 242 | return retval; |
242 | } | 243 | } |
243 | 244 | ||
244 | static unsigned int hpet_poll(struct file *file, poll_table * wait) | 245 | static unsigned int hpet_poll(struct file *file, poll_table * wait) |
245 | { | 246 | { |
246 | unsigned long v; | 247 | unsigned long v; |
247 | struct hpet_dev *devp; | 248 | struct hpet_dev *devp; |
248 | 249 | ||
249 | devp = file->private_data; | 250 | devp = file->private_data; |
250 | 251 | ||
251 | if (!devp->hd_ireqfreq) | 252 | if (!devp->hd_ireqfreq) |
252 | return 0; | 253 | return 0; |
253 | 254 | ||
254 | poll_wait(file, &devp->hd_waitqueue, wait); | 255 | poll_wait(file, &devp->hd_waitqueue, wait); |
255 | 256 | ||
256 | spin_lock_irq(&hpet_lock); | 257 | spin_lock_irq(&hpet_lock); |
257 | v = devp->hd_irqdata; | 258 | v = devp->hd_irqdata; |
258 | spin_unlock_irq(&hpet_lock); | 259 | spin_unlock_irq(&hpet_lock); |
259 | 260 | ||
260 | if (v != 0) | 261 | if (v != 0) |
261 | return POLLIN | POLLRDNORM; | 262 | return POLLIN | POLLRDNORM; |
262 | 263 | ||
263 | return 0; | 264 | return 0; |
264 | } | 265 | } |
265 | 266 | ||
266 | static int hpet_mmap(struct file *file, struct vm_area_struct *vma) | 267 | static int hpet_mmap(struct file *file, struct vm_area_struct *vma) |
267 | { | 268 | { |
268 | #ifdef CONFIG_HPET_MMAP | 269 | #ifdef CONFIG_HPET_MMAP |
269 | struct hpet_dev *devp; | 270 | struct hpet_dev *devp; |
270 | unsigned long addr; | 271 | unsigned long addr; |
271 | 272 | ||
272 | if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff) | 273 | if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff) |
273 | return -EINVAL; | 274 | return -EINVAL; |
274 | 275 | ||
275 | devp = file->private_data; | 276 | devp = file->private_data; |
276 | addr = devp->hd_hpets->hp_hpet_phys; | 277 | addr = devp->hd_hpets->hp_hpet_phys; |
277 | 278 | ||
278 | if (addr & (PAGE_SIZE - 1)) | 279 | if (addr & (PAGE_SIZE - 1)) |
279 | return -ENOSYS; | 280 | return -ENOSYS; |
280 | 281 | ||
281 | vma->vm_flags |= VM_IO; | 282 | vma->vm_flags |= VM_IO; |
282 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 283 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
283 | 284 | ||
284 | if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, | 285 | if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, |
285 | PAGE_SIZE, vma->vm_page_prot)) { | 286 | PAGE_SIZE, vma->vm_page_prot)) { |
286 | printk(KERN_ERR "%s: io_remap_pfn_range failed\n", | 287 | printk(KERN_ERR "%s: io_remap_pfn_range failed\n", |
287 | __FUNCTION__); | 288 | __FUNCTION__); |
288 | return -EAGAIN; | 289 | return -EAGAIN; |
289 | } | 290 | } |
290 | 291 | ||
291 | return 0; | 292 | return 0; |
292 | #else | 293 | #else |
293 | return -ENOSYS; | 294 | return -ENOSYS; |
294 | #endif | 295 | #endif |
295 | } | 296 | } |
296 | 297 | ||
297 | static int hpet_fasync(int fd, struct file *file, int on) | 298 | static int hpet_fasync(int fd, struct file *file, int on) |
298 | { | 299 | { |
299 | struct hpet_dev *devp; | 300 | struct hpet_dev *devp; |
300 | 301 | ||
301 | devp = file->private_data; | 302 | devp = file->private_data; |
302 | 303 | ||
303 | if (fasync_helper(fd, file, on, &devp->hd_async_queue) >= 0) | 304 | if (fasync_helper(fd, file, on, &devp->hd_async_queue) >= 0) |
304 | return 0; | 305 | return 0; |
305 | else | 306 | else |
306 | return -EIO; | 307 | return -EIO; |
307 | } | 308 | } |
308 | 309 | ||
309 | static int hpet_release(struct inode *inode, struct file *file) | 310 | static int hpet_release(struct inode *inode, struct file *file) |
310 | { | 311 | { |
311 | struct hpet_dev *devp; | 312 | struct hpet_dev *devp; |
312 | struct hpet_timer __iomem *timer; | 313 | struct hpet_timer __iomem *timer; |
313 | int irq = 0; | 314 | int irq = 0; |
314 | 315 | ||
315 | devp = file->private_data; | 316 | devp = file->private_data; |
316 | timer = devp->hd_timer; | 317 | timer = devp->hd_timer; |
317 | 318 | ||
318 | spin_lock_irq(&hpet_lock); | 319 | spin_lock_irq(&hpet_lock); |
319 | 320 | ||
320 | writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), | 321 | writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), |
321 | &timer->hpet_config); | 322 | &timer->hpet_config); |
322 | 323 | ||
323 | irq = devp->hd_irq; | 324 | irq = devp->hd_irq; |
324 | devp->hd_irq = 0; | 325 | devp->hd_irq = 0; |
325 | 326 | ||
326 | devp->hd_ireqfreq = 0; | 327 | devp->hd_ireqfreq = 0; |
327 | 328 | ||
328 | if (devp->hd_flags & HPET_PERIODIC | 329 | if (devp->hd_flags & HPET_PERIODIC |
329 | && readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) { | 330 | && readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) { |
330 | unsigned long v; | 331 | unsigned long v; |
331 | 332 | ||
332 | v = readq(&timer->hpet_config); | 333 | v = readq(&timer->hpet_config); |
333 | v ^= Tn_TYPE_CNF_MASK; | 334 | v ^= Tn_TYPE_CNF_MASK; |
334 | writeq(v, &timer->hpet_config); | 335 | writeq(v, &timer->hpet_config); |
335 | } | 336 | } |
336 | 337 | ||
337 | devp->hd_flags &= ~(HPET_OPEN | HPET_IE | HPET_PERIODIC); | 338 | devp->hd_flags &= ~(HPET_OPEN | HPET_IE | HPET_PERIODIC); |
338 | spin_unlock_irq(&hpet_lock); | 339 | spin_unlock_irq(&hpet_lock); |
339 | 340 | ||
340 | if (irq) | 341 | if (irq) |
341 | free_irq(irq, devp); | 342 | free_irq(irq, devp); |
342 | 343 | ||
343 | if (file->f_flags & FASYNC) | 344 | if (file->f_flags & FASYNC) |
344 | hpet_fasync(-1, file, 0); | 345 | hpet_fasync(-1, file, 0); |
345 | 346 | ||
346 | file->private_data = NULL; | 347 | file->private_data = NULL; |
347 | return 0; | 348 | return 0; |
348 | } | 349 | } |
349 | 350 | ||
350 | static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int); | 351 | static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int); |
351 | 352 | ||
352 | static int | 353 | static int |
353 | hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 354 | hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd, |
354 | unsigned long arg) | 355 | unsigned long arg) |
355 | { | 356 | { |
356 | struct hpet_dev *devp; | 357 | struct hpet_dev *devp; |
357 | 358 | ||
358 | devp = file->private_data; | 359 | devp = file->private_data; |
359 | return hpet_ioctl_common(devp, cmd, arg, 0); | 360 | return hpet_ioctl_common(devp, cmd, arg, 0); |
360 | } | 361 | } |
361 | 362 | ||
362 | static int hpet_ioctl_ieon(struct hpet_dev *devp) | 363 | static int hpet_ioctl_ieon(struct hpet_dev *devp) |
363 | { | 364 | { |
364 | struct hpet_timer __iomem *timer; | 365 | struct hpet_timer __iomem *timer; |
365 | struct hpet __iomem *hpet; | 366 | struct hpet __iomem *hpet; |
366 | struct hpets *hpetp; | 367 | struct hpets *hpetp; |
367 | int irq; | 368 | int irq; |
368 | unsigned long g, v, t, m; | 369 | unsigned long g, v, t, m; |
369 | unsigned long flags, isr; | 370 | unsigned long flags, isr; |
370 | 371 | ||
371 | timer = devp->hd_timer; | 372 | timer = devp->hd_timer; |
372 | hpet = devp->hd_hpet; | 373 | hpet = devp->hd_hpet; |
373 | hpetp = devp->hd_hpets; | 374 | hpetp = devp->hd_hpets; |
374 | 375 | ||
375 | if (!devp->hd_ireqfreq) | 376 | if (!devp->hd_ireqfreq) |
376 | return -EIO; | 377 | return -EIO; |
377 | 378 | ||
378 | spin_lock_irq(&hpet_lock); | 379 | spin_lock_irq(&hpet_lock); |
379 | 380 | ||
380 | if (devp->hd_flags & HPET_IE) { | 381 | if (devp->hd_flags & HPET_IE) { |
381 | spin_unlock_irq(&hpet_lock); | 382 | spin_unlock_irq(&hpet_lock); |
382 | return -EBUSY; | 383 | return -EBUSY; |
383 | } | 384 | } |
384 | 385 | ||
385 | devp->hd_flags |= HPET_IE; | 386 | devp->hd_flags |= HPET_IE; |
386 | 387 | ||
387 | if (readl(&timer->hpet_config) & Tn_INT_TYPE_CNF_MASK) | 388 | if (readl(&timer->hpet_config) & Tn_INT_TYPE_CNF_MASK) |
388 | devp->hd_flags |= HPET_SHARED_IRQ; | 389 | devp->hd_flags |= HPET_SHARED_IRQ; |
389 | spin_unlock_irq(&hpet_lock); | 390 | spin_unlock_irq(&hpet_lock); |
390 | 391 | ||
391 | irq = devp->hd_hdwirq; | 392 | irq = devp->hd_hdwirq; |
392 | 393 | ||
393 | if (irq) { | 394 | if (irq) { |
394 | unsigned long irq_flags; | 395 | unsigned long irq_flags; |
395 | 396 | ||
396 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); | 397 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); |
397 | irq_flags = devp->hd_flags & HPET_SHARED_IRQ | 398 | irq_flags = devp->hd_flags & HPET_SHARED_IRQ |
398 | ? IRQF_SHARED : IRQF_DISABLED; | 399 | ? IRQF_SHARED : IRQF_DISABLED; |
399 | if (request_irq(irq, hpet_interrupt, irq_flags, | 400 | if (request_irq(irq, hpet_interrupt, irq_flags, |
400 | devp->hd_name, (void *)devp)) { | 401 | devp->hd_name, (void *)devp)) { |
401 | printk(KERN_ERR "hpet: IRQ %d is not free\n", irq); | 402 | printk(KERN_ERR "hpet: IRQ %d is not free\n", irq); |
402 | irq = 0; | 403 | irq = 0; |
403 | } | 404 | } |
404 | } | 405 | } |
405 | 406 | ||
406 | if (irq == 0) { | 407 | if (irq == 0) { |
407 | spin_lock_irq(&hpet_lock); | 408 | spin_lock_irq(&hpet_lock); |
408 | devp->hd_flags ^= HPET_IE; | 409 | devp->hd_flags ^= HPET_IE; |
409 | spin_unlock_irq(&hpet_lock); | 410 | spin_unlock_irq(&hpet_lock); |
410 | return -EIO; | 411 | return -EIO; |
411 | } | 412 | } |
412 | 413 | ||
413 | devp->hd_irq = irq; | 414 | devp->hd_irq = irq; |
414 | t = devp->hd_ireqfreq; | 415 | t = devp->hd_ireqfreq; |
415 | v = readq(&timer->hpet_config); | 416 | v = readq(&timer->hpet_config); |
416 | g = v | Tn_INT_ENB_CNF_MASK; | 417 | g = v | Tn_INT_ENB_CNF_MASK; |
417 | 418 | ||
418 | if (devp->hd_flags & HPET_PERIODIC) { | 419 | if (devp->hd_flags & HPET_PERIODIC) { |
419 | write_counter(t, &timer->hpet_compare); | 420 | write_counter(t, &timer->hpet_compare); |
420 | g |= Tn_TYPE_CNF_MASK; | 421 | g |= Tn_TYPE_CNF_MASK; |
421 | v |= Tn_TYPE_CNF_MASK; | 422 | v |= Tn_TYPE_CNF_MASK; |
422 | writeq(v, &timer->hpet_config); | 423 | writeq(v, &timer->hpet_config); |
423 | v |= Tn_VAL_SET_CNF_MASK; | 424 | v |= Tn_VAL_SET_CNF_MASK; |
424 | writeq(v, &timer->hpet_config); | 425 | writeq(v, &timer->hpet_config); |
425 | local_irq_save(flags); | 426 | local_irq_save(flags); |
426 | m = read_counter(&hpet->hpet_mc); | 427 | m = read_counter(&hpet->hpet_mc); |
427 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); | 428 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); |
428 | } else { | 429 | } else { |
429 | local_irq_save(flags); | 430 | local_irq_save(flags); |
430 | m = read_counter(&hpet->hpet_mc); | 431 | m = read_counter(&hpet->hpet_mc); |
431 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); | 432 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); |
432 | } | 433 | } |
433 | 434 | ||
434 | if (devp->hd_flags & HPET_SHARED_IRQ) { | 435 | if (devp->hd_flags & HPET_SHARED_IRQ) { |
435 | isr = 1 << (devp - devp->hd_hpets->hp_dev); | 436 | isr = 1 << (devp - devp->hd_hpets->hp_dev); |
436 | writel(isr, &hpet->hpet_isr); | 437 | writel(isr, &hpet->hpet_isr); |
437 | } | 438 | } |
438 | writeq(g, &timer->hpet_config); | 439 | writeq(g, &timer->hpet_config); |
439 | local_irq_restore(flags); | 440 | local_irq_restore(flags); |
440 | 441 | ||
441 | return 0; | 442 | return 0; |
442 | } | 443 | } |
443 | 444 | ||
444 | /* converts Hz to number of timer ticks */ | 445 | /* converts Hz to number of timer ticks */ |
445 | static inline unsigned long hpet_time_div(struct hpets *hpets, | 446 | static inline unsigned long hpet_time_div(struct hpets *hpets, |
446 | unsigned long dis) | 447 | unsigned long dis) |
447 | { | 448 | { |
448 | unsigned long long m; | 449 | unsigned long long m; |
449 | 450 | ||
450 | m = hpets->hp_tick_freq + (dis >> 1); | 451 | m = hpets->hp_tick_freq + (dis >> 1); |
451 | do_div(m, dis); | 452 | do_div(m, dis); |
452 | return (unsigned long)m; | 453 | return (unsigned long)m; |
453 | } | 454 | } |
454 | 455 | ||
455 | static int | 456 | static int |
456 | hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | 457 | hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) |
457 | { | 458 | { |
458 | struct hpet_timer __iomem *timer; | 459 | struct hpet_timer __iomem *timer; |
459 | struct hpet __iomem *hpet; | 460 | struct hpet __iomem *hpet; |
460 | struct hpets *hpetp; | 461 | struct hpets *hpetp; |
461 | int err; | 462 | int err; |
462 | unsigned long v; | 463 | unsigned long v; |
463 | 464 | ||
464 | switch (cmd) { | 465 | switch (cmd) { |
465 | case HPET_IE_OFF: | 466 | case HPET_IE_OFF: |
466 | case HPET_INFO: | 467 | case HPET_INFO: |
467 | case HPET_EPI: | 468 | case HPET_EPI: |
468 | case HPET_DPI: | 469 | case HPET_DPI: |
469 | case HPET_IRQFREQ: | 470 | case HPET_IRQFREQ: |
470 | timer = devp->hd_timer; | 471 | timer = devp->hd_timer; |
471 | hpet = devp->hd_hpet; | 472 | hpet = devp->hd_hpet; |
472 | hpetp = devp->hd_hpets; | 473 | hpetp = devp->hd_hpets; |
473 | break; | 474 | break; |
474 | case HPET_IE_ON: | 475 | case HPET_IE_ON: |
475 | return hpet_ioctl_ieon(devp); | 476 | return hpet_ioctl_ieon(devp); |
476 | default: | 477 | default: |
477 | return -EINVAL; | 478 | return -EINVAL; |
478 | } | 479 | } |
479 | 480 | ||
480 | err = 0; | 481 | err = 0; |
481 | 482 | ||
482 | switch (cmd) { | 483 | switch (cmd) { |
483 | case HPET_IE_OFF: | 484 | case HPET_IE_OFF: |
484 | if ((devp->hd_flags & HPET_IE) == 0) | 485 | if ((devp->hd_flags & HPET_IE) == 0) |
485 | break; | 486 | break; |
486 | v = readq(&timer->hpet_config); | 487 | v = readq(&timer->hpet_config); |
487 | v &= ~Tn_INT_ENB_CNF_MASK; | 488 | v &= ~Tn_INT_ENB_CNF_MASK; |
488 | writeq(v, &timer->hpet_config); | 489 | writeq(v, &timer->hpet_config); |
489 | if (devp->hd_irq) { | 490 | if (devp->hd_irq) { |
490 | free_irq(devp->hd_irq, devp); | 491 | free_irq(devp->hd_irq, devp); |
491 | devp->hd_irq = 0; | 492 | devp->hd_irq = 0; |
492 | } | 493 | } |
493 | devp->hd_flags ^= HPET_IE; | 494 | devp->hd_flags ^= HPET_IE; |
494 | break; | 495 | break; |
495 | case HPET_INFO: | 496 | case HPET_INFO: |
496 | { | 497 | { |
497 | struct hpet_info info; | 498 | struct hpet_info info; |
498 | 499 | ||
499 | if (devp->hd_ireqfreq) | 500 | if (devp->hd_ireqfreq) |
500 | info.hi_ireqfreq = | 501 | info.hi_ireqfreq = |
501 | hpet_time_div(hpetp, devp->hd_ireqfreq); | 502 | hpet_time_div(hpetp, devp->hd_ireqfreq); |
502 | else | 503 | else |
503 | info.hi_ireqfreq = 0; | 504 | info.hi_ireqfreq = 0; |
504 | info.hi_flags = | 505 | info.hi_flags = |
505 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; | 506 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; |
506 | info.hi_hpet = hpetp->hp_which; | 507 | info.hi_hpet = hpetp->hp_which; |
507 | info.hi_timer = devp - hpetp->hp_dev; | 508 | info.hi_timer = devp - hpetp->hp_dev; |
508 | if (kernel) | 509 | if (kernel) |
509 | memcpy((void *)arg, &info, sizeof(info)); | 510 | memcpy((void *)arg, &info, sizeof(info)); |
510 | else | 511 | else |
511 | if (copy_to_user((void __user *)arg, &info, | 512 | if (copy_to_user((void __user *)arg, &info, |
512 | sizeof(info))) | 513 | sizeof(info))) |
513 | err = -EFAULT; | 514 | err = -EFAULT; |
514 | break; | 515 | break; |
515 | } | 516 | } |
516 | case HPET_EPI: | 517 | case HPET_EPI: |
517 | v = readq(&timer->hpet_config); | 518 | v = readq(&timer->hpet_config); |
518 | if ((v & Tn_PER_INT_CAP_MASK) == 0) { | 519 | if ((v & Tn_PER_INT_CAP_MASK) == 0) { |
519 | err = -ENXIO; | 520 | err = -ENXIO; |
520 | break; | 521 | break; |
521 | } | 522 | } |
522 | devp->hd_flags |= HPET_PERIODIC; | 523 | devp->hd_flags |= HPET_PERIODIC; |
523 | break; | 524 | break; |
524 | case HPET_DPI: | 525 | case HPET_DPI: |
525 | v = readq(&timer->hpet_config); | 526 | v = readq(&timer->hpet_config); |
526 | if ((v & Tn_PER_INT_CAP_MASK) == 0) { | 527 | if ((v & Tn_PER_INT_CAP_MASK) == 0) { |
527 | err = -ENXIO; | 528 | err = -ENXIO; |
528 | break; | 529 | break; |
529 | } | 530 | } |
530 | if (devp->hd_flags & HPET_PERIODIC && | 531 | if (devp->hd_flags & HPET_PERIODIC && |
531 | readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) { | 532 | readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) { |
532 | v = readq(&timer->hpet_config); | 533 | v = readq(&timer->hpet_config); |
533 | v ^= Tn_TYPE_CNF_MASK; | 534 | v ^= Tn_TYPE_CNF_MASK; |
534 | writeq(v, &timer->hpet_config); | 535 | writeq(v, &timer->hpet_config); |
535 | } | 536 | } |
536 | devp->hd_flags &= ~HPET_PERIODIC; | 537 | devp->hd_flags &= ~HPET_PERIODIC; |
537 | break; | 538 | break; |
538 | case HPET_IRQFREQ: | 539 | case HPET_IRQFREQ: |
539 | if (!kernel && (arg > hpet_max_freq) && | 540 | if (!kernel && (arg > hpet_max_freq) && |
540 | !capable(CAP_SYS_RESOURCE)) { | 541 | !capable(CAP_SYS_RESOURCE)) { |
541 | err = -EACCES; | 542 | err = -EACCES; |
542 | break; | 543 | break; |
543 | } | 544 | } |
544 | 545 | ||
545 | if (!arg) { | 546 | if (!arg) { |
546 | err = -EINVAL; | 547 | err = -EINVAL; |
547 | break; | 548 | break; |
548 | } | 549 | } |
549 | 550 | ||
550 | devp->hd_ireqfreq = hpet_time_div(hpetp, arg); | 551 | devp->hd_ireqfreq = hpet_time_div(hpetp, arg); |
551 | } | 552 | } |
552 | 553 | ||
553 | return err; | 554 | return err; |
554 | } | 555 | } |
555 | 556 | ||
556 | static const struct file_operations hpet_fops = { | 557 | static const struct file_operations hpet_fops = { |
557 | .owner = THIS_MODULE, | 558 | .owner = THIS_MODULE, |
558 | .llseek = no_llseek, | 559 | .llseek = no_llseek, |
559 | .read = hpet_read, | 560 | .read = hpet_read, |
560 | .poll = hpet_poll, | 561 | .poll = hpet_poll, |
561 | .ioctl = hpet_ioctl, | 562 | .ioctl = hpet_ioctl, |
562 | .open = hpet_open, | 563 | .open = hpet_open, |
563 | .release = hpet_release, | 564 | .release = hpet_release, |
564 | .fasync = hpet_fasync, | 565 | .fasync = hpet_fasync, |
565 | .mmap = hpet_mmap, | 566 | .mmap = hpet_mmap, |
566 | }; | 567 | }; |
567 | 568 | ||
568 | static int hpet_is_known(struct hpet_data *hdp) | 569 | static int hpet_is_known(struct hpet_data *hdp) |
569 | { | 570 | { |
570 | struct hpets *hpetp; | 571 | struct hpets *hpetp; |
571 | 572 | ||
572 | for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) | 573 | for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) |
573 | if (hpetp->hp_hpet_phys == hdp->hd_phys_address) | 574 | if (hpetp->hp_hpet_phys == hdp->hd_phys_address) |
574 | return 1; | 575 | return 1; |
575 | 576 | ||
576 | return 0; | 577 | return 0; |
577 | } | 578 | } |
578 | 579 | ||
579 | EXPORT_SYMBOL(hpet_alloc); | 580 | EXPORT_SYMBOL(hpet_alloc); |
580 | EXPORT_SYMBOL(hpet_register); | 581 | EXPORT_SYMBOL(hpet_register); |
581 | EXPORT_SYMBOL(hpet_unregister); | 582 | EXPORT_SYMBOL(hpet_unregister); |
582 | EXPORT_SYMBOL(hpet_control); | 583 | EXPORT_SYMBOL(hpet_control); |
583 | 584 | ||
584 | int hpet_register(struct hpet_task *tp, int periodic) | 585 | int hpet_register(struct hpet_task *tp, int periodic) |
585 | { | 586 | { |
586 | unsigned int i; | 587 | unsigned int i; |
587 | u64 mask; | 588 | u64 mask; |
588 | struct hpet_timer __iomem *timer; | 589 | struct hpet_timer __iomem *timer; |
589 | struct hpet_dev *devp; | 590 | struct hpet_dev *devp; |
590 | struct hpets *hpetp; | 591 | struct hpets *hpetp; |
591 | 592 | ||
592 | switch (periodic) { | 593 | switch (periodic) { |
593 | case 1: | 594 | case 1: |
594 | mask = Tn_PER_INT_CAP_MASK; | 595 | mask = Tn_PER_INT_CAP_MASK; |
595 | break; | 596 | break; |
596 | case 0: | 597 | case 0: |
597 | mask = 0; | 598 | mask = 0; |
598 | break; | 599 | break; |
599 | default: | 600 | default: |
600 | return -EINVAL; | 601 | return -EINVAL; |
601 | } | 602 | } |
602 | 603 | ||
603 | tp->ht_opaque = NULL; | 604 | tp->ht_opaque = NULL; |
604 | 605 | ||
605 | spin_lock_irq(&hpet_task_lock); | 606 | spin_lock_irq(&hpet_task_lock); |
606 | spin_lock(&hpet_lock); | 607 | spin_lock(&hpet_lock); |
607 | 608 | ||
608 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) | 609 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) |
609 | for (timer = hpetp->hp_hpet->hpet_timers, i = 0; | 610 | for (timer = hpetp->hp_hpet->hpet_timers, i = 0; |
610 | i < hpetp->hp_ntimer; i++, timer++) { | 611 | i < hpetp->hp_ntimer; i++, timer++) { |
611 | if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK) | 612 | if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK) |
612 | != mask) | 613 | != mask) |
613 | continue; | 614 | continue; |
614 | 615 | ||
615 | devp = &hpetp->hp_dev[i]; | 616 | devp = &hpetp->hp_dev[i]; |
616 | 617 | ||
617 | if (devp->hd_flags & HPET_OPEN || devp->hd_task) { | 618 | if (devp->hd_flags & HPET_OPEN || devp->hd_task) { |
618 | devp = NULL; | 619 | devp = NULL; |
619 | continue; | 620 | continue; |
620 | } | 621 | } |
621 | 622 | ||
622 | tp->ht_opaque = devp; | 623 | tp->ht_opaque = devp; |
623 | devp->hd_task = tp; | 624 | devp->hd_task = tp; |
624 | break; | 625 | break; |
625 | } | 626 | } |
626 | 627 | ||
627 | spin_unlock(&hpet_lock); | 628 | spin_unlock(&hpet_lock); |
628 | spin_unlock_irq(&hpet_task_lock); | 629 | spin_unlock_irq(&hpet_task_lock); |
629 | 630 | ||
630 | if (tp->ht_opaque) | 631 | if (tp->ht_opaque) |
631 | return 0; | 632 | return 0; |
632 | else | 633 | else |
633 | return -EBUSY; | 634 | return -EBUSY; |
634 | } | 635 | } |
635 | 636 | ||
636 | static inline int hpet_tpcheck(struct hpet_task *tp) | 637 | static inline int hpet_tpcheck(struct hpet_task *tp) |
637 | { | 638 | { |
638 | struct hpet_dev *devp; | 639 | struct hpet_dev *devp; |
639 | struct hpets *hpetp; | 640 | struct hpets *hpetp; |
640 | 641 | ||
641 | devp = tp->ht_opaque; | 642 | devp = tp->ht_opaque; |
642 | 643 | ||
643 | if (!devp) | 644 | if (!devp) |
644 | return -ENXIO; | 645 | return -ENXIO; |
645 | 646 | ||
646 | for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) | 647 | for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) |
647 | if (devp >= hpetp->hp_dev | 648 | if (devp >= hpetp->hp_dev |
648 | && devp < (hpetp->hp_dev + hpetp->hp_ntimer) | 649 | && devp < (hpetp->hp_dev + hpetp->hp_ntimer) |
649 | && devp->hd_hpet == hpetp->hp_hpet) | 650 | && devp->hd_hpet == hpetp->hp_hpet) |
650 | return 0; | 651 | return 0; |
651 | 652 | ||
652 | return -ENXIO; | 653 | return -ENXIO; |
653 | } | 654 | } |
654 | 655 | ||
655 | int hpet_unregister(struct hpet_task *tp) | 656 | int hpet_unregister(struct hpet_task *tp) |
656 | { | 657 | { |
657 | struct hpet_dev *devp; | 658 | struct hpet_dev *devp; |
658 | struct hpet_timer __iomem *timer; | 659 | struct hpet_timer __iomem *timer; |
659 | int err; | 660 | int err; |
660 | 661 | ||
661 | if ((err = hpet_tpcheck(tp))) | 662 | if ((err = hpet_tpcheck(tp))) |
662 | return err; | 663 | return err; |
663 | 664 | ||
664 | spin_lock_irq(&hpet_task_lock); | 665 | spin_lock_irq(&hpet_task_lock); |
665 | spin_lock(&hpet_lock); | 666 | spin_lock(&hpet_lock); |
666 | 667 | ||
667 | devp = tp->ht_opaque; | 668 | devp = tp->ht_opaque; |
668 | if (devp->hd_task != tp) { | 669 | if (devp->hd_task != tp) { |
669 | spin_unlock(&hpet_lock); | 670 | spin_unlock(&hpet_lock); |
670 | spin_unlock_irq(&hpet_task_lock); | 671 | spin_unlock_irq(&hpet_task_lock); |
671 | return -ENXIO; | 672 | return -ENXIO; |
672 | } | 673 | } |
673 | 674 | ||
674 | timer = devp->hd_timer; | 675 | timer = devp->hd_timer; |
675 | writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), | 676 | writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), |
676 | &timer->hpet_config); | 677 | &timer->hpet_config); |
677 | devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC); | 678 | devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC); |
678 | devp->hd_task = NULL; | 679 | devp->hd_task = NULL; |
679 | spin_unlock(&hpet_lock); | 680 | spin_unlock(&hpet_lock); |
680 | spin_unlock_irq(&hpet_task_lock); | 681 | spin_unlock_irq(&hpet_task_lock); |
681 | 682 | ||
682 | return 0; | 683 | return 0; |
683 | } | 684 | } |
684 | 685 | ||
685 | int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) | 686 | int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) |
686 | { | 687 | { |
687 | struct hpet_dev *devp; | 688 | struct hpet_dev *devp; |
688 | int err; | 689 | int err; |
689 | 690 | ||
690 | if ((err = hpet_tpcheck(tp))) | 691 | if ((err = hpet_tpcheck(tp))) |
691 | return err; | 692 | return err; |
692 | 693 | ||
693 | spin_lock_irq(&hpet_lock); | 694 | spin_lock_irq(&hpet_lock); |
694 | devp = tp->ht_opaque; | 695 | devp = tp->ht_opaque; |
695 | if (devp->hd_task != tp) { | 696 | if (devp->hd_task != tp) { |
696 | spin_unlock_irq(&hpet_lock); | 697 | spin_unlock_irq(&hpet_lock); |
697 | return -ENXIO; | 698 | return -ENXIO; |
698 | } | 699 | } |
699 | spin_unlock_irq(&hpet_lock); | 700 | spin_unlock_irq(&hpet_lock); |
700 | return hpet_ioctl_common(devp, cmd, arg, 1); | 701 | return hpet_ioctl_common(devp, cmd, arg, 1); |
701 | } | 702 | } |
702 | 703 | ||
703 | static ctl_table hpet_table[] = { | 704 | static ctl_table hpet_table[] = { |
704 | { | 705 | { |
705 | .ctl_name = 1, | 706 | .ctl_name = 1, |
706 | .procname = "max-user-freq", | 707 | .procname = "max-user-freq", |
707 | .data = &hpet_max_freq, | 708 | .data = &hpet_max_freq, |
708 | .maxlen = sizeof(int), | 709 | .maxlen = sizeof(int), |
709 | .mode = 0644, | 710 | .mode = 0644, |
710 | .proc_handler = &proc_dointvec, | 711 | .proc_handler = &proc_dointvec, |
711 | }, | 712 | }, |
712 | {.ctl_name = 0} | 713 | {.ctl_name = 0} |
713 | }; | 714 | }; |
714 | 715 | ||
715 | static ctl_table hpet_root[] = { | 716 | static ctl_table hpet_root[] = { |
716 | { | 717 | { |
717 | .ctl_name = 1, | 718 | .ctl_name = 1, |
718 | .procname = "hpet", | 719 | .procname = "hpet", |
719 | .maxlen = 0, | 720 | .maxlen = 0, |
720 | .mode = 0555, | 721 | .mode = 0555, |
721 | .child = hpet_table, | 722 | .child = hpet_table, |
722 | }, | 723 | }, |
723 | {.ctl_name = 0} | 724 | {.ctl_name = 0} |
724 | }; | 725 | }; |
725 | 726 | ||
726 | static ctl_table dev_root[] = { | 727 | static ctl_table dev_root[] = { |
727 | { | 728 | { |
728 | .ctl_name = CTL_DEV, | 729 | .ctl_name = CTL_DEV, |
729 | .procname = "dev", | 730 | .procname = "dev", |
730 | .maxlen = 0, | 731 | .maxlen = 0, |
731 | .mode = 0555, | 732 | .mode = 0555, |
732 | .child = hpet_root, | 733 | .child = hpet_root, |
733 | }, | 734 | }, |
734 | {.ctl_name = 0} | 735 | {.ctl_name = 0} |
735 | }; | 736 | }; |
736 | 737 | ||
737 | static struct ctl_table_header *sysctl_header; | 738 | static struct ctl_table_header *sysctl_header; |
738 | 739 | ||
739 | static void hpet_register_interpolator(struct hpets *hpetp) | 740 | static void hpet_register_interpolator(struct hpets *hpetp) |
740 | { | 741 | { |
741 | #ifdef CONFIG_TIME_INTERPOLATION | 742 | #ifdef CONFIG_TIME_INTERPOLATION |
742 | struct time_interpolator *ti; | 743 | struct time_interpolator *ti; |
743 | 744 | ||
744 | ti = kzalloc(sizeof(*ti), GFP_KERNEL); | 745 | ti = kzalloc(sizeof(*ti), GFP_KERNEL); |
745 | if (!ti) | 746 | if (!ti) |
746 | return; | 747 | return; |
747 | 748 | ||
748 | ti->source = TIME_SOURCE_MMIO64; | 749 | ti->source = TIME_SOURCE_MMIO64; |
749 | ti->shift = 10; | 750 | ti->shift = 10; |
750 | ti->addr = &hpetp->hp_hpet->hpet_mc; | 751 | ti->addr = &hpetp->hp_hpet->hpet_mc; |
751 | ti->frequency = hpetp->hp_tick_freq; | 752 | ti->frequency = hpetp->hp_tick_freq; |
752 | ti->drift = HPET_DRIFT; | 753 | ti->drift = HPET_DRIFT; |
753 | ti->mask = -1; | 754 | ti->mask = -1; |
754 | 755 | ||
755 | hpetp->hp_interpolator = ti; | 756 | hpetp->hp_interpolator = ti; |
756 | register_time_interpolator(ti); | 757 | register_time_interpolator(ti); |
757 | #endif | 758 | #endif |
758 | } | 759 | } |
759 | 760 | ||
760 | /* | 761 | /* |
761 | * Adjustment for when arming the timer with | 762 | * Adjustment for when arming the timer with |
762 | * initial conditions. That is, main counter | 763 | * initial conditions. That is, main counter |
763 | * ticks expired before interrupts are enabled. | 764 | * ticks expired before interrupts are enabled. |
764 | */ | 765 | */ |
765 | #define TICK_CALIBRATE (1000UL) | 766 | #define TICK_CALIBRATE (1000UL) |
766 | 767 | ||
767 | static unsigned long hpet_calibrate(struct hpets *hpetp) | 768 | static unsigned long hpet_calibrate(struct hpets *hpetp) |
768 | { | 769 | { |
769 | struct hpet_timer __iomem *timer = NULL; | 770 | struct hpet_timer __iomem *timer = NULL; |
770 | unsigned long t, m, count, i, flags, start; | 771 | unsigned long t, m, count, i, flags, start; |
771 | struct hpet_dev *devp; | 772 | struct hpet_dev *devp; |
772 | int j; | 773 | int j; |
773 | struct hpet __iomem *hpet; | 774 | struct hpet __iomem *hpet; |
774 | 775 | ||
775 | for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++) | 776 | for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++) |
776 | if ((devp->hd_flags & HPET_OPEN) == 0) { | 777 | if ((devp->hd_flags & HPET_OPEN) == 0) { |
777 | timer = devp->hd_timer; | 778 | timer = devp->hd_timer; |
778 | break; | 779 | break; |
779 | } | 780 | } |
780 | 781 | ||
781 | if (!timer) | 782 | if (!timer) |
782 | return 0; | 783 | return 0; |
783 | 784 | ||
784 | hpet = hpetp->hp_hpet; | 785 | hpet = hpetp->hp_hpet; |
785 | t = read_counter(&timer->hpet_compare); | 786 | t = read_counter(&timer->hpet_compare); |
786 | 787 | ||
787 | i = 0; | 788 | i = 0; |
788 | count = hpet_time_div(hpetp, TICK_CALIBRATE); | 789 | count = hpet_time_div(hpetp, TICK_CALIBRATE); |
789 | 790 | ||
790 | local_irq_save(flags); | 791 | local_irq_save(flags); |
791 | 792 | ||
792 | start = read_counter(&hpet->hpet_mc); | 793 | start = read_counter(&hpet->hpet_mc); |
793 | 794 | ||
794 | do { | 795 | do { |
795 | m = read_counter(&hpet->hpet_mc); | 796 | m = read_counter(&hpet->hpet_mc); |
796 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); | 797 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); |
797 | } while (i++, (m - start) < count); | 798 | } while (i++, (m - start) < count); |
798 | 799 | ||
799 | local_irq_restore(flags); | 800 | local_irq_restore(flags); |
800 | 801 | ||
801 | return (m - start) / i; | 802 | return (m - start) / i; |
802 | } | 803 | } |
803 | 804 | ||
804 | int hpet_alloc(struct hpet_data *hdp) | 805 | int hpet_alloc(struct hpet_data *hdp) |
805 | { | 806 | { |
806 | u64 cap, mcfg; | 807 | u64 cap, mcfg; |
807 | struct hpet_dev *devp; | 808 | struct hpet_dev *devp; |
808 | u32 i, ntimer; | 809 | u32 i, ntimer; |
809 | struct hpets *hpetp; | 810 | struct hpets *hpetp; |
810 | size_t siz; | 811 | size_t siz; |
811 | struct hpet __iomem *hpet; | 812 | struct hpet __iomem *hpet; |
812 | static struct hpets *last = NULL; | 813 | static struct hpets *last = NULL; |
813 | unsigned long period; | 814 | unsigned long period; |
814 | unsigned long long temp; | 815 | unsigned long long temp; |
815 | 816 | ||
816 | /* | 817 | /* |
817 | * hpet_alloc can be called by platform dependent code. | 818 | * hpet_alloc can be called by platform dependent code. |
818 | * If platform dependent code has allocated the hpet that | 819 | * If platform dependent code has allocated the hpet that |
819 | * ACPI has also reported, then we catch it here. | 820 | * ACPI has also reported, then we catch it here. |
820 | */ | 821 | */ |
821 | if (hpet_is_known(hdp)) { | 822 | if (hpet_is_known(hdp)) { |
822 | printk(KERN_DEBUG "%s: duplicate HPET ignored\n", | 823 | printk(KERN_DEBUG "%s: duplicate HPET ignored\n", |
823 | __FUNCTION__); | 824 | __FUNCTION__); |
824 | return 0; | 825 | return 0; |
825 | } | 826 | } |
826 | 827 | ||
827 | siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * | 828 | siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * |
828 | sizeof(struct hpet_dev)); | 829 | sizeof(struct hpet_dev)); |
829 | 830 | ||
830 | hpetp = kzalloc(siz, GFP_KERNEL); | 831 | hpetp = kzalloc(siz, GFP_KERNEL); |
831 | 832 | ||
832 | if (!hpetp) | 833 | if (!hpetp) |
833 | return -ENOMEM; | 834 | return -ENOMEM; |
834 | 835 | ||
835 | hpetp->hp_which = hpet_nhpet++; | 836 | hpetp->hp_which = hpet_nhpet++; |
836 | hpetp->hp_hpet = hdp->hd_address; | 837 | hpetp->hp_hpet = hdp->hd_address; |
837 | hpetp->hp_hpet_phys = hdp->hd_phys_address; | 838 | hpetp->hp_hpet_phys = hdp->hd_phys_address; |
838 | 839 | ||
839 | hpetp->hp_ntimer = hdp->hd_nirqs; | 840 | hpetp->hp_ntimer = hdp->hd_nirqs; |
840 | 841 | ||
841 | for (i = 0; i < hdp->hd_nirqs; i++) | 842 | for (i = 0; i < hdp->hd_nirqs; i++) |
842 | hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; | 843 | hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; |
843 | 844 | ||
844 | hpet = hpetp->hp_hpet; | 845 | hpet = hpetp->hp_hpet; |
845 | 846 | ||
846 | cap = readq(&hpet->hpet_cap); | 847 | cap = readq(&hpet->hpet_cap); |
847 | 848 | ||
848 | ntimer = ((cap & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT) + 1; | 849 | ntimer = ((cap & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT) + 1; |
849 | 850 | ||
850 | if (hpetp->hp_ntimer != ntimer) { | 851 | if (hpetp->hp_ntimer != ntimer) { |
851 | printk(KERN_WARNING "hpet: number irqs doesn't agree" | 852 | printk(KERN_WARNING "hpet: number irqs doesn't agree" |
852 | " with number of timers\n"); | 853 | " with number of timers\n"); |
853 | kfree(hpetp); | 854 | kfree(hpetp); |
854 | return -ENODEV; | 855 | return -ENODEV; |
855 | } | 856 | } |
856 | 857 | ||
857 | if (last) | 858 | if (last) |
858 | last->hp_next = hpetp; | 859 | last->hp_next = hpetp; |
859 | else | 860 | else |
860 | hpets = hpetp; | 861 | hpets = hpetp; |
861 | 862 | ||
862 | last = hpetp; | 863 | last = hpetp; |
863 | 864 | ||
864 | period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> | 865 | period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> |
865 | HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */ | 866 | HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */ |
866 | temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */ | 867 | temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */ |
867 | temp += period >> 1; /* round */ | 868 | temp += period >> 1; /* round */ |
868 | do_div(temp, period); | 869 | do_div(temp, period); |
869 | hpetp->hp_tick_freq = temp; /* ticks per second */ | 870 | hpetp->hp_tick_freq = temp; /* ticks per second */ |
870 | 871 | ||
871 | printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s", | 872 | printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s", |
872 | hpetp->hp_which, hdp->hd_phys_address, | 873 | hpetp->hp_which, hdp->hd_phys_address, |
873 | hpetp->hp_ntimer > 1 ? "s" : ""); | 874 | hpetp->hp_ntimer > 1 ? "s" : ""); |
874 | for (i = 0; i < hpetp->hp_ntimer; i++) | 875 | for (i = 0; i < hpetp->hp_ntimer; i++) |
875 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); | 876 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); |
876 | printk("\n"); | 877 | printk("\n"); |
877 | 878 | ||
878 | printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", | 879 | printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", |
879 | hpetp->hp_which, hpetp->hp_ntimer, | 880 | hpetp->hp_which, hpetp->hp_ntimer, |
880 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq); | 881 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq); |
881 | 882 | ||
882 | mcfg = readq(&hpet->hpet_config); | 883 | mcfg = readq(&hpet->hpet_config); |
883 | if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { | 884 | if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { |
884 | write_counter(0L, &hpet->hpet_mc); | 885 | write_counter(0L, &hpet->hpet_mc); |
885 | mcfg |= HPET_ENABLE_CNF_MASK; | 886 | mcfg |= HPET_ENABLE_CNF_MASK; |
886 | writeq(mcfg, &hpet->hpet_config); | 887 | writeq(mcfg, &hpet->hpet_config); |
887 | } | 888 | } |
888 | 889 | ||
889 | for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) { | 890 | for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) { |
890 | struct hpet_timer __iomem *timer; | 891 | struct hpet_timer __iomem *timer; |
891 | 892 | ||
892 | timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; | 893 | timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; |
893 | 894 | ||
894 | devp->hd_hpets = hpetp; | 895 | devp->hd_hpets = hpetp; |
895 | devp->hd_hpet = hpet; | 896 | devp->hd_hpet = hpet; |
896 | devp->hd_timer = timer; | 897 | devp->hd_timer = timer; |
897 | 898 | ||
898 | /* | 899 | /* |
899 | * If the timer was reserved by platform code, | 900 | * If the timer was reserved by platform code, |
900 | * then make timer unavailable for opens. | 901 | * then make timer unavailable for opens. |
901 | */ | 902 | */ |
902 | if (hdp->hd_state & (1 << i)) { | 903 | if (hdp->hd_state & (1 << i)) { |
903 | devp->hd_flags = HPET_OPEN; | 904 | devp->hd_flags = HPET_OPEN; |
904 | continue; | 905 | continue; |
905 | } | 906 | } |
906 | 907 | ||
907 | init_waitqueue_head(&devp->hd_waitqueue); | 908 | init_waitqueue_head(&devp->hd_waitqueue); |
908 | } | 909 | } |
909 | 910 | ||
910 | hpetp->hp_delta = hpet_calibrate(hpetp); | 911 | hpetp->hp_delta = hpet_calibrate(hpetp); |
911 | hpet_register_interpolator(hpetp); | 912 | hpet_register_interpolator(hpetp); |
912 | 913 | ||
913 | return 0; | 914 | return 0; |
914 | } | 915 | } |
915 | 916 | ||
916 | static acpi_status hpet_resources(struct acpi_resource *res, void *data) | 917 | static acpi_status hpet_resources(struct acpi_resource *res, void *data) |
917 | { | 918 | { |
918 | struct hpet_data *hdp; | 919 | struct hpet_data *hdp; |
919 | acpi_status status; | 920 | acpi_status status; |
920 | struct acpi_resource_address64 addr; | 921 | struct acpi_resource_address64 addr; |
921 | 922 | ||
922 | hdp = data; | 923 | hdp = data; |
923 | 924 | ||
924 | status = acpi_resource_to_address64(res, &addr); | 925 | status = acpi_resource_to_address64(res, &addr); |
925 | 926 | ||
926 | if (ACPI_SUCCESS(status)) { | 927 | if (ACPI_SUCCESS(status)) { |
927 | hdp->hd_phys_address = addr.minimum; | 928 | hdp->hd_phys_address = addr.minimum; |
928 | hdp->hd_address = ioremap(addr.minimum, addr.address_length); | 929 | hdp->hd_address = ioremap(addr.minimum, addr.address_length); |
929 | 930 | ||
930 | if (hpet_is_known(hdp)) { | 931 | if (hpet_is_known(hdp)) { |
931 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", | 932 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", |
932 | __FUNCTION__, hdp->hd_phys_address); | 933 | __FUNCTION__, hdp->hd_phys_address); |
933 | iounmap(hdp->hd_address); | 934 | iounmap(hdp->hd_address); |
934 | return -EBUSY; | 935 | return -EBUSY; |
935 | } | 936 | } |
936 | } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { | 937 | } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { |
937 | struct acpi_resource_fixed_memory32 *fixmem32; | 938 | struct acpi_resource_fixed_memory32 *fixmem32; |
938 | 939 | ||
939 | fixmem32 = &res->data.fixed_memory32; | 940 | fixmem32 = &res->data.fixed_memory32; |
940 | if (!fixmem32) | 941 | if (!fixmem32) |
941 | return -EINVAL; | 942 | return -EINVAL; |
942 | 943 | ||
943 | hdp->hd_phys_address = fixmem32->address; | 944 | hdp->hd_phys_address = fixmem32->address; |
944 | hdp->hd_address = ioremap(fixmem32->address, | 945 | hdp->hd_address = ioremap(fixmem32->address, |
945 | HPET_RANGE_SIZE); | 946 | HPET_RANGE_SIZE); |
946 | 947 | ||
947 | if (hpet_is_known(hdp)) { | 948 | if (hpet_is_known(hdp)) { |
948 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", | 949 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", |
949 | __FUNCTION__, hdp->hd_phys_address); | 950 | __FUNCTION__, hdp->hd_phys_address); |
950 | iounmap(hdp->hd_address); | 951 | iounmap(hdp->hd_address); |
951 | return -EBUSY; | 952 | return -EBUSY; |
952 | } | 953 | } |
953 | } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { | 954 | } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { |
954 | struct acpi_resource_extended_irq *irqp; | 955 | struct acpi_resource_extended_irq *irqp; |
955 | int i, irq; | 956 | int i, irq; |
956 | 957 | ||
957 | irqp = &res->data.extended_irq; | 958 | irqp = &res->data.extended_irq; |
958 | 959 | ||
959 | for (i = 0; i < irqp->interrupt_count; i++) { | 960 | for (i = 0; i < irqp->interrupt_count; i++) { |
960 | irq = acpi_register_gsi(irqp->interrupts[i], | 961 | irq = acpi_register_gsi(irqp->interrupts[i], |
961 | irqp->triggering, irqp->polarity); | 962 | irqp->triggering, irqp->polarity); |
962 | if (irq < 0) | 963 | if (irq < 0) |
963 | return AE_ERROR; | 964 | return AE_ERROR; |
964 | 965 | ||
965 | hdp->hd_irq[hdp->hd_nirqs] = irq; | 966 | hdp->hd_irq[hdp->hd_nirqs] = irq; |
966 | hdp->hd_nirqs++; | 967 | hdp->hd_nirqs++; |
967 | } | 968 | } |
968 | } | 969 | } |
969 | 970 | ||
970 | return AE_OK; | 971 | return AE_OK; |
971 | } | 972 | } |
972 | 973 | ||
973 | static int hpet_acpi_add(struct acpi_device *device) | 974 | static int hpet_acpi_add(struct acpi_device *device) |
974 | { | 975 | { |
975 | acpi_status result; | 976 | acpi_status result; |
976 | struct hpet_data data; | 977 | struct hpet_data data; |
977 | 978 | ||
978 | memset(&data, 0, sizeof(data)); | 979 | memset(&data, 0, sizeof(data)); |
979 | 980 | ||
980 | result = | 981 | result = |
981 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, | 982 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
982 | hpet_resources, &data); | 983 | hpet_resources, &data); |
983 | 984 | ||
984 | if (ACPI_FAILURE(result)) | 985 | if (ACPI_FAILURE(result)) |
985 | return -ENODEV; | 986 | return -ENODEV; |
986 | 987 | ||
987 | if (!data.hd_address || !data.hd_nirqs) { | 988 | if (!data.hd_address || !data.hd_nirqs) { |
988 | printk("%s: no address or irqs in _CRS\n", __FUNCTION__); | 989 | printk("%s: no address or irqs in _CRS\n", __FUNCTION__); |
989 | return -ENODEV; | 990 | return -ENODEV; |
990 | } | 991 | } |
991 | 992 | ||
992 | return hpet_alloc(&data); | 993 | return hpet_alloc(&data); |
993 | } | 994 | } |
994 | 995 | ||
995 | static int hpet_acpi_remove(struct acpi_device *device, int type) | 996 | static int hpet_acpi_remove(struct acpi_device *device, int type) |
996 | { | 997 | { |
997 | /* XXX need to unregister interpolator, dealloc mem, etc */ | 998 | /* XXX need to unregister interpolator, dealloc mem, etc */ |
998 | return -EINVAL; | 999 | return -EINVAL; |
999 | } | 1000 | } |
1000 | 1001 | ||
1001 | static struct acpi_driver hpet_acpi_driver = { | 1002 | static struct acpi_driver hpet_acpi_driver = { |
1002 | .name = "hpet", | 1003 | .name = "hpet", |
1003 | .ids = "PNP0103", | 1004 | .ids = "PNP0103", |
1004 | .ops = { | 1005 | .ops = { |
1005 | .add = hpet_acpi_add, | 1006 | .add = hpet_acpi_add, |
1006 | .remove = hpet_acpi_remove, | 1007 | .remove = hpet_acpi_remove, |
1007 | }, | 1008 | }, |
1008 | }; | 1009 | }; |
1009 | 1010 | ||
1010 | static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops }; | 1011 | static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops }; |
1011 | 1012 | ||
1012 | static int __init hpet_init(void) | 1013 | static int __init hpet_init(void) |
1013 | { | 1014 | { |
1014 | int result; | 1015 | int result; |
1015 | 1016 | ||
1016 | result = misc_register(&hpet_misc); | 1017 | result = misc_register(&hpet_misc); |
1017 | if (result < 0) | 1018 | if (result < 0) |
1018 | return -ENODEV; | 1019 | return -ENODEV; |
1019 | 1020 | ||
1020 | sysctl_header = register_sysctl_table(dev_root, 0); | 1021 | sysctl_header = register_sysctl_table(dev_root, 0); |
1021 | 1022 | ||
1022 | result = acpi_bus_register_driver(&hpet_acpi_driver); | 1023 | result = acpi_bus_register_driver(&hpet_acpi_driver); |
1023 | if (result < 0) { | 1024 | if (result < 0) { |
1024 | if (sysctl_header) | 1025 | if (sysctl_header) |
1025 | unregister_sysctl_table(sysctl_header); | 1026 | unregister_sysctl_table(sysctl_header); |
1026 | misc_deregister(&hpet_misc); | 1027 | misc_deregister(&hpet_misc); |
1027 | return result; | 1028 | return result; |
1028 | } | 1029 | } |
1029 | 1030 | ||
1030 | return 0; | 1031 | return 0; |
1031 | } | 1032 | } |
1032 | 1033 | ||
1033 | static void __exit hpet_exit(void) | 1034 | static void __exit hpet_exit(void) |
1034 | { | 1035 | { |
1035 | acpi_bus_unregister_driver(&hpet_acpi_driver); | 1036 | acpi_bus_unregister_driver(&hpet_acpi_driver); |
1036 | 1037 | ||
1037 | if (sysctl_header) | 1038 | if (sysctl_header) |
1038 | unregister_sysctl_table(sysctl_header); | 1039 | unregister_sysctl_table(sysctl_header); |
1039 | misc_deregister(&hpet_misc); | 1040 | misc_deregister(&hpet_misc); |
1040 | 1041 | ||
1041 | return; | 1042 | return; |
1042 | } | 1043 | } |
1043 | 1044 | ||
1044 | module_init(hpet_init); | 1045 | module_init(hpet_init); |
1045 | module_exit(hpet_exit); | 1046 | module_exit(hpet_exit); |
1046 | MODULE_AUTHOR("Bob Picco <Robert.Picco@hp.com>"); | 1047 | MODULE_AUTHOR("Bob Picco <Robert.Picco@hp.com>"); |
1047 | MODULE_LICENSE("GPL"); | 1048 | MODULE_LICENSE("GPL"); |
1048 | 1049 |
drivers/media/dvb/cinergyT2/cinergyT2.c
1 | /* | 1 | /* |
2 | * TerraTec Cinergy Tยฒ/qanu USB2 DVB-T adapter. | 2 | * TerraTec Cinergy Tยฒ/qanu USB2 DVB-T adapter. |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | 4 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and |
5 | * Holger Waechtler <holger@qanu.de> | 5 | * Holger Waechtler <holger@qanu.de> |
6 | * | 6 | * |
7 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | 7 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or | 11 | * the Free Software Foundation; either version 2 of the License, or |
12 | * (at your option) any later version. | 12 | * (at your option) any later version. |
13 | * | 13 | * |
14 | * This program is distributed in the hope that it will be useful, | 14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. | 17 | * GNU General Public License for more details. |
18 | * | 18 | * |
19 | * You should have received a copy of the GNU General Public License | 19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/input.h> | 30 | #include <linux/input.h> |
31 | #include <linux/dvb/frontend.h> | 31 | #include <linux/dvb/frontend.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/mm.h> | ||
33 | 34 | ||
34 | #include "dmxdev.h" | 35 | #include "dmxdev.h" |
35 | #include "dvb_demux.h" | 36 | #include "dvb_demux.h" |
36 | #include "dvb_net.h" | 37 | #include "dvb_net.h" |
37 | 38 | ||
38 | #ifdef CONFIG_DVB_CINERGYT2_TUNING | 39 | #ifdef CONFIG_DVB_CINERGYT2_TUNING |
39 | #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) | 40 | #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) |
40 | #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) | 41 | #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) |
41 | #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL) | 42 | #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL) |
42 | #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE | 43 | #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE |
43 | #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL) | 44 | #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL) |
44 | #define ENABLE_RC (1) | 45 | #define ENABLE_RC (1) |
45 | #endif | 46 | #endif |
46 | #else | 47 | #else |
47 | #define STREAM_URB_COUNT (32) | 48 | #define STREAM_URB_COUNT (32) |
48 | #define STREAM_BUF_SIZE (512) /* bytes */ | 49 | #define STREAM_BUF_SIZE (512) /* bytes */ |
49 | #define ENABLE_RC (1) | 50 | #define ENABLE_RC (1) |
50 | #define RC_QUERY_INTERVAL (50) /* milliseconds */ | 51 | #define RC_QUERY_INTERVAL (50) /* milliseconds */ |
51 | #define QUERY_INTERVAL (333) /* milliseconds */ | 52 | #define QUERY_INTERVAL (333) /* milliseconds */ |
52 | #endif | 53 | #endif |
53 | 54 | ||
54 | #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" | 55 | #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" |
55 | 56 | ||
56 | static int debug; | 57 | static int debug; |
57 | module_param_named(debug, debug, int, 0644); | 58 | module_param_named(debug, debug, int, 0644); |
58 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | 59 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); |
59 | 60 | ||
60 | #define dprintk(level, args...) \ | 61 | #define dprintk(level, args...) \ |
61 | do { \ | 62 | do { \ |
62 | if ((debug & level)) { \ | 63 | if ((debug & level)) { \ |
63 | printk("%s: %s(): ", KBUILD_MODNAME, \ | 64 | printk("%s: %s(): ", KBUILD_MODNAME, \ |
64 | __FUNCTION__); \ | 65 | __FUNCTION__); \ |
65 | printk(args); } \ | 66 | printk(args); } \ |
66 | } while (0) | 67 | } while (0) |
67 | 68 | ||
68 | enum cinergyt2_ep1_cmd { | 69 | enum cinergyt2_ep1_cmd { |
69 | CINERGYT2_EP1_PID_TABLE_RESET = 0x01, | 70 | CINERGYT2_EP1_PID_TABLE_RESET = 0x01, |
70 | CINERGYT2_EP1_PID_SETUP = 0x02, | 71 | CINERGYT2_EP1_PID_SETUP = 0x02, |
71 | CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, | 72 | CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, |
72 | CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, | 73 | CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, |
73 | CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, | 74 | CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, |
74 | CINERGYT2_EP1_START_SCAN = 0x06, | 75 | CINERGYT2_EP1_START_SCAN = 0x06, |
75 | CINERGYT2_EP1_CONTINUE_SCAN = 0x07, | 76 | CINERGYT2_EP1_CONTINUE_SCAN = 0x07, |
76 | CINERGYT2_EP1_GET_RC_EVENTS = 0x08, | 77 | CINERGYT2_EP1_GET_RC_EVENTS = 0x08, |
77 | CINERGYT2_EP1_SLEEP_MODE = 0x09 | 78 | CINERGYT2_EP1_SLEEP_MODE = 0x09 |
78 | }; | 79 | }; |
79 | 80 | ||
80 | struct dvbt_set_parameters_msg { | 81 | struct dvbt_set_parameters_msg { |
81 | uint8_t cmd; | 82 | uint8_t cmd; |
82 | uint32_t freq; | 83 | uint32_t freq; |
83 | uint8_t bandwidth; | 84 | uint8_t bandwidth; |
84 | uint16_t tps; | 85 | uint16_t tps; |
85 | uint8_t flags; | 86 | uint8_t flags; |
86 | } __attribute__((packed)); | 87 | } __attribute__((packed)); |
87 | 88 | ||
88 | struct dvbt_get_status_msg { | 89 | struct dvbt_get_status_msg { |
89 | uint32_t freq; | 90 | uint32_t freq; |
90 | uint8_t bandwidth; | 91 | uint8_t bandwidth; |
91 | uint16_t tps; | 92 | uint16_t tps; |
92 | uint8_t flags; | 93 | uint8_t flags; |
93 | uint16_t gain; | 94 | uint16_t gain; |
94 | uint8_t snr; | 95 | uint8_t snr; |
95 | uint32_t viterbi_error_rate; | 96 | uint32_t viterbi_error_rate; |
96 | uint32_t rs_error_rate; | 97 | uint32_t rs_error_rate; |
97 | uint32_t uncorrected_block_count; | 98 | uint32_t uncorrected_block_count; |
98 | uint8_t lock_bits; | 99 | uint8_t lock_bits; |
99 | uint8_t prev_lock_bits; | 100 | uint8_t prev_lock_bits; |
100 | } __attribute__((packed)); | 101 | } __attribute__((packed)); |
101 | 102 | ||
102 | static struct dvb_frontend_info cinergyt2_fe_info = { | 103 | static struct dvb_frontend_info cinergyt2_fe_info = { |
103 | .name = DRIVER_NAME, | 104 | .name = DRIVER_NAME, |
104 | .type = FE_OFDM, | 105 | .type = FE_OFDM, |
105 | .frequency_min = 174000000, | 106 | .frequency_min = 174000000, |
106 | .frequency_max = 862000000, | 107 | .frequency_max = 862000000, |
107 | .frequency_stepsize = 166667, | 108 | .frequency_stepsize = 166667, |
108 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | 109 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | |
109 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | 110 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | |
110 | FE_CAN_FEC_AUTO | | 111 | FE_CAN_FEC_AUTO | |
111 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | 112 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | |
112 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | | 113 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | |
113 | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS | 114 | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS |
114 | }; | 115 | }; |
115 | 116 | ||
116 | struct cinergyt2 { | 117 | struct cinergyt2 { |
117 | struct dvb_demux demux; | 118 | struct dvb_demux demux; |
118 | struct usb_device *udev; | 119 | struct usb_device *udev; |
119 | struct mutex sem; | 120 | struct mutex sem; |
120 | struct dvb_adapter adapter; | 121 | struct dvb_adapter adapter; |
121 | struct dvb_device *fedev; | 122 | struct dvb_device *fedev; |
122 | struct dmxdev dmxdev; | 123 | struct dmxdev dmxdev; |
123 | struct dvb_net dvbnet; | 124 | struct dvb_net dvbnet; |
124 | 125 | ||
125 | int streaming; | 126 | int streaming; |
126 | int sleeping; | 127 | int sleeping; |
127 | 128 | ||
128 | struct dvbt_set_parameters_msg param; | 129 | struct dvbt_set_parameters_msg param; |
129 | struct dvbt_get_status_msg status; | 130 | struct dvbt_get_status_msg status; |
130 | struct work_struct query_work; | 131 | struct work_struct query_work; |
131 | 132 | ||
132 | wait_queue_head_t poll_wq; | 133 | wait_queue_head_t poll_wq; |
133 | int pending_fe_events; | 134 | int pending_fe_events; |
134 | int disconnect_pending; | 135 | int disconnect_pending; |
135 | atomic_t inuse; | 136 | atomic_t inuse; |
136 | 137 | ||
137 | void *streambuf; | 138 | void *streambuf; |
138 | dma_addr_t streambuf_dmahandle; | 139 | dma_addr_t streambuf_dmahandle; |
139 | struct urb *stream_urb [STREAM_URB_COUNT]; | 140 | struct urb *stream_urb [STREAM_URB_COUNT]; |
140 | 141 | ||
141 | #ifdef ENABLE_RC | 142 | #ifdef ENABLE_RC |
142 | struct input_dev *rc_input_dev; | 143 | struct input_dev *rc_input_dev; |
143 | char phys[64]; | 144 | char phys[64]; |
144 | struct work_struct rc_query_work; | 145 | struct work_struct rc_query_work; |
145 | int rc_input_event; | 146 | int rc_input_event; |
146 | u32 rc_last_code; | 147 | u32 rc_last_code; |
147 | unsigned long last_event_jiffies; | 148 | unsigned long last_event_jiffies; |
148 | #endif | 149 | #endif |
149 | }; | 150 | }; |
150 | 151 | ||
151 | enum { | 152 | enum { |
152 | CINERGYT2_RC_EVENT_TYPE_NONE = 0x00, | 153 | CINERGYT2_RC_EVENT_TYPE_NONE = 0x00, |
153 | CINERGYT2_RC_EVENT_TYPE_NEC = 0x01, | 154 | CINERGYT2_RC_EVENT_TYPE_NEC = 0x01, |
154 | CINERGYT2_RC_EVENT_TYPE_RC5 = 0x02 | 155 | CINERGYT2_RC_EVENT_TYPE_RC5 = 0x02 |
155 | }; | 156 | }; |
156 | 157 | ||
157 | struct cinergyt2_rc_event { | 158 | struct cinergyt2_rc_event { |
158 | char type; | 159 | char type; |
159 | uint32_t value; | 160 | uint32_t value; |
160 | } __attribute__((packed)); | 161 | } __attribute__((packed)); |
161 | 162 | ||
162 | static const uint32_t rc_keys[] = { | 163 | static const uint32_t rc_keys[] = { |
163 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER, | 164 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER, |
164 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, | 165 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, |
165 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, | 166 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, |
166 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3, | 167 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3, |
167 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4, | 168 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4, |
168 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5, | 169 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5, |
169 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6, | 170 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6, |
170 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7, | 171 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7, |
171 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8, | 172 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8, |
172 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9, | 173 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9, |
173 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0, | 174 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0, |
174 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf40beb04, KEY_VIDEO, | 175 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf40beb04, KEY_VIDEO, |
175 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf20deb04, KEY_REFRESH, | 176 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf20deb04, KEY_REFRESH, |
176 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT, | 177 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT, |
177 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG, | 178 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG, |
178 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP, | 179 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP, |
179 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN, | 180 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN, |
180 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT, | 181 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT, |
181 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT, | 182 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT, |
182 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK, | 183 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK, |
183 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT, | 184 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT, |
184 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO, | 185 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO, |
185 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED, | 186 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED, |
186 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN, | 187 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN, |
187 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW, | 188 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW, |
188 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE, | 189 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE, |
189 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP, | 190 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP, |
190 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN, | 191 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN, |
191 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE, | 192 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE, |
192 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP, | 193 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP, |
193 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN, | 194 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN, |
194 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE, | 195 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE, |
195 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY, | 196 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY, |
196 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD, | 197 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD, |
197 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS, | 198 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS, |
198 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP, | 199 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP, |
199 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT | 200 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT |
200 | }; | 201 | }; |
201 | 202 | ||
202 | static int cinergyt2_command (struct cinergyt2 *cinergyt2, | 203 | static int cinergyt2_command (struct cinergyt2 *cinergyt2, |
203 | char *send_buf, int send_buf_len, | 204 | char *send_buf, int send_buf_len, |
204 | char *recv_buf, int recv_buf_len) | 205 | char *recv_buf, int recv_buf_len) |
205 | { | 206 | { |
206 | int actual_len; | 207 | int actual_len; |
207 | char dummy; | 208 | char dummy; |
208 | int ret; | 209 | int ret; |
209 | 210 | ||
210 | ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1), | 211 | ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1), |
211 | send_buf, send_buf_len, &actual_len, 1000); | 212 | send_buf, send_buf_len, &actual_len, 1000); |
212 | 213 | ||
213 | if (ret) | 214 | if (ret) |
214 | dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret); | 215 | dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret); |
215 | 216 | ||
216 | if (!recv_buf) | 217 | if (!recv_buf) |
217 | recv_buf = &dummy; | 218 | recv_buf = &dummy; |
218 | 219 | ||
219 | ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1), | 220 | ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1), |
220 | recv_buf, recv_buf_len, &actual_len, 1000); | 221 | recv_buf, recv_buf_len, &actual_len, 1000); |
221 | 222 | ||
222 | if (ret) | 223 | if (ret) |
223 | dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret); | 224 | dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret); |
224 | 225 | ||
225 | return ret ? ret : actual_len; | 226 | return ret ? ret : actual_len; |
226 | } | 227 | } |
227 | 228 | ||
228 | static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable) | 229 | static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable) |
229 | { | 230 | { |
230 | char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; | 231 | char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; |
231 | cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); | 232 | cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); |
232 | } | 233 | } |
233 | 234 | ||
234 | static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep) | 235 | static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep) |
235 | { | 236 | { |
236 | char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 }; | 237 | char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 }; |
237 | cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); | 238 | cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); |
238 | cinergyt2->sleeping = sleep; | 239 | cinergyt2->sleeping = sleep; |
239 | } | 240 | } |
240 | 241 | ||
241 | static void cinergyt2_stream_irq (struct urb *urb); | 242 | static void cinergyt2_stream_irq (struct urb *urb); |
242 | 243 | ||
243 | static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb) | 244 | static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb) |
244 | { | 245 | { |
245 | int err; | 246 | int err; |
246 | 247 | ||
247 | usb_fill_bulk_urb(urb, | 248 | usb_fill_bulk_urb(urb, |
248 | cinergyt2->udev, | 249 | cinergyt2->udev, |
249 | usb_rcvbulkpipe(cinergyt2->udev, 0x2), | 250 | usb_rcvbulkpipe(cinergyt2->udev, 0x2), |
250 | urb->transfer_buffer, | 251 | urb->transfer_buffer, |
251 | STREAM_BUF_SIZE, | 252 | STREAM_BUF_SIZE, |
252 | cinergyt2_stream_irq, | 253 | cinergyt2_stream_irq, |
253 | cinergyt2); | 254 | cinergyt2); |
254 | 255 | ||
255 | if ((err = usb_submit_urb(urb, GFP_ATOMIC))) | 256 | if ((err = usb_submit_urb(urb, GFP_ATOMIC))) |
256 | dprintk(1, "urb submission failed (err = %i)!\n", err); | 257 | dprintk(1, "urb submission failed (err = %i)!\n", err); |
257 | 258 | ||
258 | return err; | 259 | return err; |
259 | } | 260 | } |
260 | 261 | ||
261 | static void cinergyt2_stream_irq (struct urb *urb) | 262 | static void cinergyt2_stream_irq (struct urb *urb) |
262 | { | 263 | { |
263 | struct cinergyt2 *cinergyt2 = urb->context; | 264 | struct cinergyt2 *cinergyt2 = urb->context; |
264 | 265 | ||
265 | if (urb->actual_length > 0) | 266 | if (urb->actual_length > 0) |
266 | dvb_dmx_swfilter(&cinergyt2->demux, | 267 | dvb_dmx_swfilter(&cinergyt2->demux, |
267 | urb->transfer_buffer, urb->actual_length); | 268 | urb->transfer_buffer, urb->actual_length); |
268 | 269 | ||
269 | if (cinergyt2->streaming) | 270 | if (cinergyt2->streaming) |
270 | cinergyt2_submit_stream_urb(cinergyt2, urb); | 271 | cinergyt2_submit_stream_urb(cinergyt2, urb); |
271 | } | 272 | } |
272 | 273 | ||
273 | static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2) | 274 | static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2) |
274 | { | 275 | { |
275 | int i; | 276 | int i; |
276 | 277 | ||
277 | for (i=0; i<STREAM_URB_COUNT; i++) | 278 | for (i=0; i<STREAM_URB_COUNT; i++) |
278 | usb_free_urb(cinergyt2->stream_urb[i]); | 279 | usb_free_urb(cinergyt2->stream_urb[i]); |
279 | 280 | ||
280 | usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, | 281 | usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, |
281 | cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); | 282 | cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); |
282 | } | 283 | } |
283 | 284 | ||
284 | static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2) | 285 | static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2) |
285 | { | 286 | { |
286 | int i; | 287 | int i; |
287 | 288 | ||
288 | cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, | 289 | cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, |
289 | SLAB_KERNEL, &cinergyt2->streambuf_dmahandle); | 290 | SLAB_KERNEL, &cinergyt2->streambuf_dmahandle); |
290 | if (!cinergyt2->streambuf) { | 291 | if (!cinergyt2->streambuf) { |
291 | dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); | 292 | dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); |
292 | return -ENOMEM; | 293 | return -ENOMEM; |
293 | } | 294 | } |
294 | 295 | ||
295 | memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE); | 296 | memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE); |
296 | 297 | ||
297 | for (i=0; i<STREAM_URB_COUNT; i++) { | 298 | for (i=0; i<STREAM_URB_COUNT; i++) { |
298 | struct urb *urb; | 299 | struct urb *urb; |
299 | 300 | ||
300 | if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) { | 301 | if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) { |
301 | dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n"); | 302 | dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n"); |
302 | cinergyt2_free_stream_urbs(cinergyt2); | 303 | cinergyt2_free_stream_urbs(cinergyt2); |
303 | return -ENOMEM; | 304 | return -ENOMEM; |
304 | } | 305 | } |
305 | 306 | ||
306 | urb->transfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE; | 307 | urb->transfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE; |
307 | urb->transfer_buffer_length = STREAM_BUF_SIZE; | 308 | urb->transfer_buffer_length = STREAM_BUF_SIZE; |
308 | 309 | ||
309 | cinergyt2->stream_urb[i] = urb; | 310 | cinergyt2->stream_urb[i] = urb; |
310 | } | 311 | } |
311 | 312 | ||
312 | return 0; | 313 | return 0; |
313 | } | 314 | } |
314 | 315 | ||
315 | static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2) | 316 | static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2) |
316 | { | 317 | { |
317 | int i; | 318 | int i; |
318 | 319 | ||
319 | cinergyt2_control_stream_transfer(cinergyt2, 0); | 320 | cinergyt2_control_stream_transfer(cinergyt2, 0); |
320 | 321 | ||
321 | for (i=0; i<STREAM_URB_COUNT; i++) | 322 | for (i=0; i<STREAM_URB_COUNT; i++) |
322 | usb_kill_urb(cinergyt2->stream_urb[i]); | 323 | usb_kill_urb(cinergyt2->stream_urb[i]); |
323 | } | 324 | } |
324 | 325 | ||
325 | static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) | 326 | static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) |
326 | { | 327 | { |
327 | int i, err; | 328 | int i, err; |
328 | 329 | ||
329 | for (i=0; i<STREAM_URB_COUNT; i++) { | 330 | for (i=0; i<STREAM_URB_COUNT; i++) { |
330 | if ((err = cinergyt2_submit_stream_urb(cinergyt2, cinergyt2->stream_urb[i]))) { | 331 | if ((err = cinergyt2_submit_stream_urb(cinergyt2, cinergyt2->stream_urb[i]))) { |
331 | cinergyt2_stop_stream_xfer(cinergyt2); | 332 | cinergyt2_stop_stream_xfer(cinergyt2); |
332 | dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err); | 333 | dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err); |
333 | return err; | 334 | return err; |
334 | } | 335 | } |
335 | } | 336 | } |
336 | 337 | ||
337 | cinergyt2_control_stream_transfer(cinergyt2, 1); | 338 | cinergyt2_control_stream_transfer(cinergyt2, 1); |
338 | return 0; | 339 | return 0; |
339 | } | 340 | } |
340 | 341 | ||
341 | static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) | 342 | static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) |
342 | { | 343 | { |
343 | struct dvb_demux *demux = dvbdmxfeed->demux; | 344 | struct dvb_demux *demux = dvbdmxfeed->demux; |
344 | struct cinergyt2 *cinergyt2 = demux->priv; | 345 | struct cinergyt2 *cinergyt2 = demux->priv; |
345 | 346 | ||
346 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 347 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
347 | return -ERESTARTSYS; | 348 | return -ERESTARTSYS; |
348 | 349 | ||
349 | if (cinergyt2->streaming == 0) | 350 | if (cinergyt2->streaming == 0) |
350 | cinergyt2_start_stream_xfer(cinergyt2); | 351 | cinergyt2_start_stream_xfer(cinergyt2); |
351 | 352 | ||
352 | cinergyt2->streaming++; | 353 | cinergyt2->streaming++; |
353 | mutex_unlock(&cinergyt2->sem); | 354 | mutex_unlock(&cinergyt2->sem); |
354 | return 0; | 355 | return 0; |
355 | } | 356 | } |
356 | 357 | ||
357 | static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | 358 | static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) |
358 | { | 359 | { |
359 | struct dvb_demux *demux = dvbdmxfeed->demux; | 360 | struct dvb_demux *demux = dvbdmxfeed->demux; |
360 | struct cinergyt2 *cinergyt2 = demux->priv; | 361 | struct cinergyt2 *cinergyt2 = demux->priv; |
361 | 362 | ||
362 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 363 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
363 | return -ERESTARTSYS; | 364 | return -ERESTARTSYS; |
364 | 365 | ||
365 | if (--cinergyt2->streaming == 0) | 366 | if (--cinergyt2->streaming == 0) |
366 | cinergyt2_stop_stream_xfer(cinergyt2); | 367 | cinergyt2_stop_stream_xfer(cinergyt2); |
367 | 368 | ||
368 | mutex_unlock(&cinergyt2->sem); | 369 | mutex_unlock(&cinergyt2->sem); |
369 | return 0; | 370 | return 0; |
370 | } | 371 | } |
371 | 372 | ||
372 | /** | 373 | /** |
373 | * convert linux-dvb frontend parameter set into TPS. | 374 | * convert linux-dvb frontend parameter set into TPS. |
374 | * See ETSI ETS-300744, section 4.6.2, table 9 for details. | 375 | * See ETSI ETS-300744, section 4.6.2, table 9 for details. |
375 | * | 376 | * |
376 | * This function is probably reusable and may better get placed in a support | 377 | * This function is probably reusable and may better get placed in a support |
377 | * library. | 378 | * library. |
378 | * | 379 | * |
379 | * We replace errornous fields by default TPS fields (the ones with value 0). | 380 | * We replace errornous fields by default TPS fields (the ones with value 0). |
380 | */ | 381 | */ |
381 | static uint16_t compute_tps (struct dvb_frontend_parameters *p) | 382 | static uint16_t compute_tps (struct dvb_frontend_parameters *p) |
382 | { | 383 | { |
383 | struct dvb_ofdm_parameters *op = &p->u.ofdm; | 384 | struct dvb_ofdm_parameters *op = &p->u.ofdm; |
384 | uint16_t tps = 0; | 385 | uint16_t tps = 0; |
385 | 386 | ||
386 | switch (op->code_rate_HP) { | 387 | switch (op->code_rate_HP) { |
387 | case FEC_2_3: | 388 | case FEC_2_3: |
388 | tps |= (1 << 7); | 389 | tps |= (1 << 7); |
389 | break; | 390 | break; |
390 | case FEC_3_4: | 391 | case FEC_3_4: |
391 | tps |= (2 << 7); | 392 | tps |= (2 << 7); |
392 | break; | 393 | break; |
393 | case FEC_5_6: | 394 | case FEC_5_6: |
394 | tps |= (3 << 7); | 395 | tps |= (3 << 7); |
395 | break; | 396 | break; |
396 | case FEC_7_8: | 397 | case FEC_7_8: |
397 | tps |= (4 << 7); | 398 | tps |= (4 << 7); |
398 | break; | 399 | break; |
399 | case FEC_1_2: | 400 | case FEC_1_2: |
400 | case FEC_AUTO: | 401 | case FEC_AUTO: |
401 | default: | 402 | default: |
402 | /* tps |= (0 << 7) */; | 403 | /* tps |= (0 << 7) */; |
403 | } | 404 | } |
404 | 405 | ||
405 | switch (op->code_rate_LP) { | 406 | switch (op->code_rate_LP) { |
406 | case FEC_2_3: | 407 | case FEC_2_3: |
407 | tps |= (1 << 4); | 408 | tps |= (1 << 4); |
408 | break; | 409 | break; |
409 | case FEC_3_4: | 410 | case FEC_3_4: |
410 | tps |= (2 << 4); | 411 | tps |= (2 << 4); |
411 | break; | 412 | break; |
412 | case FEC_5_6: | 413 | case FEC_5_6: |
413 | tps |= (3 << 4); | 414 | tps |= (3 << 4); |
414 | break; | 415 | break; |
415 | case FEC_7_8: | 416 | case FEC_7_8: |
416 | tps |= (4 << 4); | 417 | tps |= (4 << 4); |
417 | break; | 418 | break; |
418 | case FEC_1_2: | 419 | case FEC_1_2: |
419 | case FEC_AUTO: | 420 | case FEC_AUTO: |
420 | default: | 421 | default: |
421 | /* tps |= (0 << 4) */; | 422 | /* tps |= (0 << 4) */; |
422 | } | 423 | } |
423 | 424 | ||
424 | switch (op->constellation) { | 425 | switch (op->constellation) { |
425 | case QAM_16: | 426 | case QAM_16: |
426 | tps |= (1 << 13); | 427 | tps |= (1 << 13); |
427 | break; | 428 | break; |
428 | case QAM_64: | 429 | case QAM_64: |
429 | tps |= (2 << 13); | 430 | tps |= (2 << 13); |
430 | break; | 431 | break; |
431 | case QPSK: | 432 | case QPSK: |
432 | default: | 433 | default: |
433 | /* tps |= (0 << 13) */; | 434 | /* tps |= (0 << 13) */; |
434 | } | 435 | } |
435 | 436 | ||
436 | switch (op->transmission_mode) { | 437 | switch (op->transmission_mode) { |
437 | case TRANSMISSION_MODE_8K: | 438 | case TRANSMISSION_MODE_8K: |
438 | tps |= (1 << 0); | 439 | tps |= (1 << 0); |
439 | break; | 440 | break; |
440 | case TRANSMISSION_MODE_2K: | 441 | case TRANSMISSION_MODE_2K: |
441 | default: | 442 | default: |
442 | /* tps |= (0 << 0) */; | 443 | /* tps |= (0 << 0) */; |
443 | } | 444 | } |
444 | 445 | ||
445 | switch (op->guard_interval) { | 446 | switch (op->guard_interval) { |
446 | case GUARD_INTERVAL_1_16: | 447 | case GUARD_INTERVAL_1_16: |
447 | tps |= (1 << 2); | 448 | tps |= (1 << 2); |
448 | break; | 449 | break; |
449 | case GUARD_INTERVAL_1_8: | 450 | case GUARD_INTERVAL_1_8: |
450 | tps |= (2 << 2); | 451 | tps |= (2 << 2); |
451 | break; | 452 | break; |
452 | case GUARD_INTERVAL_1_4: | 453 | case GUARD_INTERVAL_1_4: |
453 | tps |= (3 << 2); | 454 | tps |= (3 << 2); |
454 | break; | 455 | break; |
455 | case GUARD_INTERVAL_1_32: | 456 | case GUARD_INTERVAL_1_32: |
456 | default: | 457 | default: |
457 | /* tps |= (0 << 2) */; | 458 | /* tps |= (0 << 2) */; |
458 | } | 459 | } |
459 | 460 | ||
460 | switch (op->hierarchy_information) { | 461 | switch (op->hierarchy_information) { |
461 | case HIERARCHY_1: | 462 | case HIERARCHY_1: |
462 | tps |= (1 << 10); | 463 | tps |= (1 << 10); |
463 | break; | 464 | break; |
464 | case HIERARCHY_2: | 465 | case HIERARCHY_2: |
465 | tps |= (2 << 10); | 466 | tps |= (2 << 10); |
466 | break; | 467 | break; |
467 | case HIERARCHY_4: | 468 | case HIERARCHY_4: |
468 | tps |= (3 << 10); | 469 | tps |= (3 << 10); |
469 | break; | 470 | break; |
470 | case HIERARCHY_NONE: | 471 | case HIERARCHY_NONE: |
471 | default: | 472 | default: |
472 | /* tps |= (0 << 10) */; | 473 | /* tps |= (0 << 10) */; |
473 | } | 474 | } |
474 | 475 | ||
475 | return tps; | 476 | return tps; |
476 | } | 477 | } |
477 | 478 | ||
478 | static int cinergyt2_open (struct inode *inode, struct file *file) | 479 | static int cinergyt2_open (struct inode *inode, struct file *file) |
479 | { | 480 | { |
480 | struct dvb_device *dvbdev = file->private_data; | 481 | struct dvb_device *dvbdev = file->private_data; |
481 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | 482 | struct cinergyt2 *cinergyt2 = dvbdev->priv; |
482 | int err = -ERESTARTSYS; | 483 | int err = -ERESTARTSYS; |
483 | 484 | ||
484 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 485 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
485 | return -ERESTARTSYS; | 486 | return -ERESTARTSYS; |
486 | 487 | ||
487 | if ((err = dvb_generic_open(inode, file))) { | 488 | if ((err = dvb_generic_open(inode, file))) { |
488 | mutex_unlock(&cinergyt2->sem); | 489 | mutex_unlock(&cinergyt2->sem); |
489 | return err; | 490 | return err; |
490 | } | 491 | } |
491 | 492 | ||
492 | 493 | ||
493 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | 494 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { |
494 | cinergyt2_sleep(cinergyt2, 0); | 495 | cinergyt2_sleep(cinergyt2, 0); |
495 | schedule_delayed_work(&cinergyt2->query_work, HZ/2); | 496 | schedule_delayed_work(&cinergyt2->query_work, HZ/2); |
496 | } | 497 | } |
497 | 498 | ||
498 | atomic_inc(&cinergyt2->inuse); | 499 | atomic_inc(&cinergyt2->inuse); |
499 | 500 | ||
500 | mutex_unlock(&cinergyt2->sem); | 501 | mutex_unlock(&cinergyt2->sem); |
501 | return 0; | 502 | return 0; |
502 | } | 503 | } |
503 | 504 | ||
504 | static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) | 505 | static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) |
505 | { | 506 | { |
506 | dvb_net_release(&cinergyt2->dvbnet); | 507 | dvb_net_release(&cinergyt2->dvbnet); |
507 | dvb_dmxdev_release(&cinergyt2->dmxdev); | 508 | dvb_dmxdev_release(&cinergyt2->dmxdev); |
508 | dvb_dmx_release(&cinergyt2->demux); | 509 | dvb_dmx_release(&cinergyt2->demux); |
509 | dvb_unregister_device(cinergyt2->fedev); | 510 | dvb_unregister_device(cinergyt2->fedev); |
510 | dvb_unregister_adapter(&cinergyt2->adapter); | 511 | dvb_unregister_adapter(&cinergyt2->adapter); |
511 | 512 | ||
512 | cinergyt2_free_stream_urbs(cinergyt2); | 513 | cinergyt2_free_stream_urbs(cinergyt2); |
513 | kfree(cinergyt2); | 514 | kfree(cinergyt2); |
514 | } | 515 | } |
515 | 516 | ||
516 | static int cinergyt2_release (struct inode *inode, struct file *file) | 517 | static int cinergyt2_release (struct inode *inode, struct file *file) |
517 | { | 518 | { |
518 | struct dvb_device *dvbdev = file->private_data; | 519 | struct dvb_device *dvbdev = file->private_data; |
519 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | 520 | struct cinergyt2 *cinergyt2 = dvbdev->priv; |
520 | 521 | ||
521 | if (mutex_lock_interruptible(&cinergyt2->sem)) | 522 | if (mutex_lock_interruptible(&cinergyt2->sem)) |
522 | return -ERESTARTSYS; | 523 | return -ERESTARTSYS; |
523 | 524 | ||
524 | if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { | 525 | if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { |
525 | cancel_delayed_work(&cinergyt2->query_work); | 526 | cancel_delayed_work(&cinergyt2->query_work); |
526 | flush_scheduled_work(); | 527 | flush_scheduled_work(); |
527 | cinergyt2_sleep(cinergyt2, 1); | 528 | cinergyt2_sleep(cinergyt2, 1); |
528 | } | 529 | } |
529 | 530 | ||
530 | mutex_unlock(&cinergyt2->sem); | 531 | mutex_unlock(&cinergyt2->sem); |
531 | 532 | ||
532 | if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { | 533 | if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { |
533 | warn("delayed unregister in release"); | 534 | warn("delayed unregister in release"); |
534 | cinergyt2_unregister(cinergyt2); | 535 | cinergyt2_unregister(cinergyt2); |
535 | } | 536 | } |
536 | 537 | ||
537 | return dvb_generic_release(inode, file); | 538 | return dvb_generic_release(inode, file); |
538 | } | 539 | } |
539 | 540 | ||
540 | static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait) | 541 | static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait) |
541 | { | 542 | { |
542 | struct dvb_device *dvbdev = file->private_data; | 543 | struct dvb_device *dvbdev = file->private_data; |
543 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | 544 | struct cinergyt2 *cinergyt2 = dvbdev->priv; |
544 | unsigned int mask = 0; | 545 | unsigned int mask = 0; |
545 | 546 | ||
546 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 547 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
547 | return -ERESTARTSYS; | 548 | return -ERESTARTSYS; |
548 | 549 | ||
549 | poll_wait(file, &cinergyt2->poll_wq, wait); | 550 | poll_wait(file, &cinergyt2->poll_wq, wait); |
550 | 551 | ||
551 | if (cinergyt2->pending_fe_events != 0) | 552 | if (cinergyt2->pending_fe_events != 0) |
552 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | 553 | mask |= (POLLIN | POLLRDNORM | POLLPRI); |
553 | 554 | ||
554 | mutex_unlock(&cinergyt2->sem); | 555 | mutex_unlock(&cinergyt2->sem); |
555 | 556 | ||
556 | return mask; | 557 | return mask; |
557 | } | 558 | } |
558 | 559 | ||
559 | 560 | ||
560 | static int cinergyt2_ioctl (struct inode *inode, struct file *file, | 561 | static int cinergyt2_ioctl (struct inode *inode, struct file *file, |
561 | unsigned cmd, unsigned long arg) | 562 | unsigned cmd, unsigned long arg) |
562 | { | 563 | { |
563 | struct dvb_device *dvbdev = file->private_data; | 564 | struct dvb_device *dvbdev = file->private_data; |
564 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | 565 | struct cinergyt2 *cinergyt2 = dvbdev->priv; |
565 | struct dvbt_get_status_msg *stat = &cinergyt2->status; | 566 | struct dvbt_get_status_msg *stat = &cinergyt2->status; |
566 | fe_status_t status = 0; | 567 | fe_status_t status = 0; |
567 | 568 | ||
568 | switch (cmd) { | 569 | switch (cmd) { |
569 | case FE_GET_INFO: | 570 | case FE_GET_INFO: |
570 | return copy_to_user((void __user*) arg, &cinergyt2_fe_info, | 571 | return copy_to_user((void __user*) arg, &cinergyt2_fe_info, |
571 | sizeof(struct dvb_frontend_info)); | 572 | sizeof(struct dvb_frontend_info)); |
572 | 573 | ||
573 | case FE_READ_STATUS: | 574 | case FE_READ_STATUS: |
574 | if (0xffff - le16_to_cpu(stat->gain) > 30) | 575 | if (0xffff - le16_to_cpu(stat->gain) > 30) |
575 | status |= FE_HAS_SIGNAL; | 576 | status |= FE_HAS_SIGNAL; |
576 | if (stat->lock_bits & (1 << 6)) | 577 | if (stat->lock_bits & (1 << 6)) |
577 | status |= FE_HAS_LOCK; | 578 | status |= FE_HAS_LOCK; |
578 | if (stat->lock_bits & (1 << 5)) | 579 | if (stat->lock_bits & (1 << 5)) |
579 | status |= FE_HAS_SYNC; | 580 | status |= FE_HAS_SYNC; |
580 | if (stat->lock_bits & (1 << 4)) | 581 | if (stat->lock_bits & (1 << 4)) |
581 | status |= FE_HAS_CARRIER; | 582 | status |= FE_HAS_CARRIER; |
582 | if (stat->lock_bits & (1 << 1)) | 583 | if (stat->lock_bits & (1 << 1)) |
583 | status |= FE_HAS_VITERBI; | 584 | status |= FE_HAS_VITERBI; |
584 | 585 | ||
585 | return copy_to_user((void __user*) arg, &status, sizeof(status)); | 586 | return copy_to_user((void __user*) arg, &status, sizeof(status)); |
586 | 587 | ||
587 | case FE_READ_BER: | 588 | case FE_READ_BER: |
588 | return put_user(le32_to_cpu(stat->viterbi_error_rate), | 589 | return put_user(le32_to_cpu(stat->viterbi_error_rate), |
589 | (__u32 __user *) arg); | 590 | (__u32 __user *) arg); |
590 | 591 | ||
591 | case FE_READ_SIGNAL_STRENGTH: | 592 | case FE_READ_SIGNAL_STRENGTH: |
592 | return put_user(0xffff - le16_to_cpu(stat->gain), | 593 | return put_user(0xffff - le16_to_cpu(stat->gain), |
593 | (__u16 __user *) arg); | 594 | (__u16 __user *) arg); |
594 | 595 | ||
595 | case FE_READ_SNR: | 596 | case FE_READ_SNR: |
596 | return put_user((stat->snr << 8) | stat->snr, | 597 | return put_user((stat->snr << 8) | stat->snr, |
597 | (__u16 __user *) arg); | 598 | (__u16 __user *) arg); |
598 | 599 | ||
599 | case FE_READ_UNCORRECTED_BLOCKS: | 600 | case FE_READ_UNCORRECTED_BLOCKS: |
600 | { | 601 | { |
601 | uint32_t unc_count; | 602 | uint32_t unc_count; |
602 | 603 | ||
603 | unc_count = stat->uncorrected_block_count; | 604 | unc_count = stat->uncorrected_block_count; |
604 | stat->uncorrected_block_count = 0; | 605 | stat->uncorrected_block_count = 0; |
605 | 606 | ||
606 | /* UNC are already converted to host byte order... */ | 607 | /* UNC are already converted to host byte order... */ |
607 | return put_user(unc_count,(__u32 __user *) arg); | 608 | return put_user(unc_count,(__u32 __user *) arg); |
608 | } | 609 | } |
609 | case FE_SET_FRONTEND: | 610 | case FE_SET_FRONTEND: |
610 | { | 611 | { |
611 | struct dvbt_set_parameters_msg *param = &cinergyt2->param; | 612 | struct dvbt_set_parameters_msg *param = &cinergyt2->param; |
612 | struct dvb_frontend_parameters p; | 613 | struct dvb_frontend_parameters p; |
613 | int err; | 614 | int err; |
614 | 615 | ||
615 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | 616 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) |
616 | return -EPERM; | 617 | return -EPERM; |
617 | 618 | ||
618 | if (copy_from_user(&p, (void __user*) arg, sizeof(p))) | 619 | if (copy_from_user(&p, (void __user*) arg, sizeof(p))) |
619 | return -EFAULT; | 620 | return -EFAULT; |
620 | 621 | ||
621 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 622 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
622 | return -ERESTARTSYS; | 623 | return -ERESTARTSYS; |
623 | 624 | ||
624 | param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; | 625 | param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; |
625 | param->tps = cpu_to_le16(compute_tps(&p)); | 626 | param->tps = cpu_to_le16(compute_tps(&p)); |
626 | param->freq = cpu_to_le32(p.frequency / 1000); | 627 | param->freq = cpu_to_le32(p.frequency / 1000); |
627 | param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ; | 628 | param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ; |
628 | 629 | ||
629 | stat->lock_bits = 0; | 630 | stat->lock_bits = 0; |
630 | cinergyt2->pending_fe_events++; | 631 | cinergyt2->pending_fe_events++; |
631 | wake_up_interruptible(&cinergyt2->poll_wq); | 632 | wake_up_interruptible(&cinergyt2->poll_wq); |
632 | 633 | ||
633 | err = cinergyt2_command(cinergyt2, | 634 | err = cinergyt2_command(cinergyt2, |
634 | (char *) param, sizeof(*param), | 635 | (char *) param, sizeof(*param), |
635 | NULL, 0); | 636 | NULL, 0); |
636 | 637 | ||
637 | mutex_unlock(&cinergyt2->sem); | 638 | mutex_unlock(&cinergyt2->sem); |
638 | 639 | ||
639 | return (err < 0) ? err : 0; | 640 | return (err < 0) ? err : 0; |
640 | } | 641 | } |
641 | 642 | ||
642 | case FE_GET_FRONTEND: | 643 | case FE_GET_FRONTEND: |
643 | /** | 644 | /** |
644 | * trivial to implement (see struct dvbt_get_status_msg). | 645 | * trivial to implement (see struct dvbt_get_status_msg). |
645 | * equivalent to FE_READ ioctls, but needs | 646 | * equivalent to FE_READ ioctls, but needs |
646 | * TPS -> linux-dvb parameter set conversion. Feel free | 647 | * TPS -> linux-dvb parameter set conversion. Feel free |
647 | * to implement this and send us a patch if you need this | 648 | * to implement this and send us a patch if you need this |
648 | * functionality. | 649 | * functionality. |
649 | */ | 650 | */ |
650 | break; | 651 | break; |
651 | 652 | ||
652 | case FE_GET_EVENT: | 653 | case FE_GET_EVENT: |
653 | { | 654 | { |
654 | /** | 655 | /** |
655 | * for now we only fill the status field. the parameters | 656 | * for now we only fill the status field. the parameters |
656 | * are trivial to fill as soon FE_GET_FRONTEND is done. | 657 | * are trivial to fill as soon FE_GET_FRONTEND is done. |
657 | */ | 658 | */ |
658 | struct dvb_frontend_event __user *e = (void __user *) arg; | 659 | struct dvb_frontend_event __user *e = (void __user *) arg; |
659 | if (cinergyt2->pending_fe_events == 0) { | 660 | if (cinergyt2->pending_fe_events == 0) { |
660 | if (file->f_flags & O_NONBLOCK) | 661 | if (file->f_flags & O_NONBLOCK) |
661 | return -EWOULDBLOCK; | 662 | return -EWOULDBLOCK; |
662 | wait_event_interruptible(cinergyt2->poll_wq, | 663 | wait_event_interruptible(cinergyt2->poll_wq, |
663 | cinergyt2->pending_fe_events > 0); | 664 | cinergyt2->pending_fe_events > 0); |
664 | } | 665 | } |
665 | cinergyt2->pending_fe_events = 0; | 666 | cinergyt2->pending_fe_events = 0; |
666 | return cinergyt2_ioctl(inode, file, FE_READ_STATUS, | 667 | return cinergyt2_ioctl(inode, file, FE_READ_STATUS, |
667 | (unsigned long) &e->status); | 668 | (unsigned long) &e->status); |
668 | } | 669 | } |
669 | 670 | ||
670 | default: | 671 | default: |
671 | ; | 672 | ; |
672 | } | 673 | } |
673 | 674 | ||
674 | return -EINVAL; | 675 | return -EINVAL; |
675 | } | 676 | } |
676 | 677 | ||
677 | static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma) | 678 | static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma) |
678 | { | 679 | { |
679 | struct dvb_device *dvbdev = file->private_data; | 680 | struct dvb_device *dvbdev = file->private_data; |
680 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | 681 | struct cinergyt2 *cinergyt2 = dvbdev->priv; |
681 | int ret = 0; | 682 | int ret = 0; |
682 | 683 | ||
683 | lock_kernel(); | 684 | lock_kernel(); |
684 | 685 | ||
685 | if (vma->vm_flags & (VM_WRITE | VM_EXEC)) { | 686 | if (vma->vm_flags & (VM_WRITE | VM_EXEC)) { |
686 | ret = -EPERM; | 687 | ret = -EPERM; |
687 | goto bailout; | 688 | goto bailout; |
688 | } | 689 | } |
689 | 690 | ||
690 | if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) { | 691 | if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) { |
691 | ret = -EINVAL; | 692 | ret = -EINVAL; |
692 | goto bailout; | 693 | goto bailout; |
693 | } | 694 | } |
694 | 695 | ||
695 | vma->vm_flags |= (VM_IO | VM_DONTCOPY); | 696 | vma->vm_flags |= (VM_IO | VM_DONTCOPY); |
696 | vma->vm_file = file; | 697 | vma->vm_file = file; |
697 | 698 | ||
698 | ret = remap_pfn_range(vma, vma->vm_start, | 699 | ret = remap_pfn_range(vma, vma->vm_start, |
699 | virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT, | 700 | virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT, |
700 | vma->vm_end - vma->vm_start, | 701 | vma->vm_end - vma->vm_start, |
701 | vma->vm_page_prot) ? -EAGAIN : 0; | 702 | vma->vm_page_prot) ? -EAGAIN : 0; |
702 | bailout: | 703 | bailout: |
703 | unlock_kernel(); | 704 | unlock_kernel(); |
704 | return ret; | 705 | return ret; |
705 | } | 706 | } |
706 | 707 | ||
707 | static struct file_operations cinergyt2_fops = { | 708 | static struct file_operations cinergyt2_fops = { |
708 | .owner = THIS_MODULE, | 709 | .owner = THIS_MODULE, |
709 | .ioctl = cinergyt2_ioctl, | 710 | .ioctl = cinergyt2_ioctl, |
710 | .poll = cinergyt2_poll, | 711 | .poll = cinergyt2_poll, |
711 | .open = cinergyt2_open, | 712 | .open = cinergyt2_open, |
712 | .release = cinergyt2_release, | 713 | .release = cinergyt2_release, |
713 | .mmap = cinergyt2_mmap | 714 | .mmap = cinergyt2_mmap |
714 | }; | 715 | }; |
715 | 716 | ||
716 | static struct dvb_device cinergyt2_fe_template = { | 717 | static struct dvb_device cinergyt2_fe_template = { |
717 | .users = ~0, | 718 | .users = ~0, |
718 | .writers = 1, | 719 | .writers = 1, |
719 | .readers = (~0)-1, | 720 | .readers = (~0)-1, |
720 | .fops = &cinergyt2_fops | 721 | .fops = &cinergyt2_fops |
721 | }; | 722 | }; |
722 | 723 | ||
723 | #ifdef ENABLE_RC | 724 | #ifdef ENABLE_RC |
724 | 725 | ||
725 | static void cinergyt2_query_rc (void *data) | 726 | static void cinergyt2_query_rc (void *data) |
726 | { | 727 | { |
727 | struct cinergyt2 *cinergyt2 = data; | 728 | struct cinergyt2 *cinergyt2 = data; |
728 | char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; | 729 | char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; |
729 | struct cinergyt2_rc_event rc_events[12]; | 730 | struct cinergyt2_rc_event rc_events[12]; |
730 | int n, len, i; | 731 | int n, len, i; |
731 | 732 | ||
732 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 733 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
733 | return; | 734 | return; |
734 | 735 | ||
735 | len = cinergyt2_command(cinergyt2, buf, sizeof(buf), | 736 | len = cinergyt2_command(cinergyt2, buf, sizeof(buf), |
736 | (char *) rc_events, sizeof(rc_events)); | 737 | (char *) rc_events, sizeof(rc_events)); |
737 | if (len < 0) | 738 | if (len < 0) |
738 | goto out; | 739 | goto out; |
739 | if (len == 0) { | 740 | if (len == 0) { |
740 | if (time_after(jiffies, cinergyt2->last_event_jiffies + | 741 | if (time_after(jiffies, cinergyt2->last_event_jiffies + |
741 | msecs_to_jiffies(150))) { | 742 | msecs_to_jiffies(150))) { |
742 | /* stop key repeat */ | 743 | /* stop key repeat */ |
743 | if (cinergyt2->rc_input_event != KEY_MAX) { | 744 | if (cinergyt2->rc_input_event != KEY_MAX) { |
744 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); | 745 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); |
745 | input_report_key(cinergyt2->rc_input_dev, | 746 | input_report_key(cinergyt2->rc_input_dev, |
746 | cinergyt2->rc_input_event, 0); | 747 | cinergyt2->rc_input_event, 0); |
747 | cinergyt2->rc_input_event = KEY_MAX; | 748 | cinergyt2->rc_input_event = KEY_MAX; |
748 | } | 749 | } |
749 | cinergyt2->rc_last_code = ~0; | 750 | cinergyt2->rc_last_code = ~0; |
750 | } | 751 | } |
751 | goto out; | 752 | goto out; |
752 | } | 753 | } |
753 | cinergyt2->last_event_jiffies = jiffies; | 754 | cinergyt2->last_event_jiffies = jiffies; |
754 | 755 | ||
755 | for (n = 0; n < (len / sizeof(rc_events[0])); n++) { | 756 | for (n = 0; n < (len / sizeof(rc_events[0])); n++) { |
756 | dprintk(1, "rc_events[%d].value = %x, type=%x\n", | 757 | dprintk(1, "rc_events[%d].value = %x, type=%x\n", |
757 | n, le32_to_cpu(rc_events[n].value), rc_events[n].type); | 758 | n, le32_to_cpu(rc_events[n].value), rc_events[n].type); |
758 | 759 | ||
759 | if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && | 760 | if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && |
760 | rc_events[n].value == ~0) { | 761 | rc_events[n].value == ~0) { |
761 | /* keyrepeat bit -> just repeat last rc_input_event */ | 762 | /* keyrepeat bit -> just repeat last rc_input_event */ |
762 | } else { | 763 | } else { |
763 | cinergyt2->rc_input_event = KEY_MAX; | 764 | cinergyt2->rc_input_event = KEY_MAX; |
764 | for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) { | 765 | for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) { |
765 | if (rc_keys[i + 0] == rc_events[n].type && | 766 | if (rc_keys[i + 0] == rc_events[n].type && |
766 | rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) { | 767 | rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) { |
767 | cinergyt2->rc_input_event = rc_keys[i + 2]; | 768 | cinergyt2->rc_input_event = rc_keys[i + 2]; |
768 | break; | 769 | break; |
769 | } | 770 | } |
770 | } | 771 | } |
771 | } | 772 | } |
772 | 773 | ||
773 | if (cinergyt2->rc_input_event != KEY_MAX) { | 774 | if (cinergyt2->rc_input_event != KEY_MAX) { |
774 | if (rc_events[n].value == cinergyt2->rc_last_code && | 775 | if (rc_events[n].value == cinergyt2->rc_last_code && |
775 | cinergyt2->rc_last_code != ~0) { | 776 | cinergyt2->rc_last_code != ~0) { |
776 | /* emit a key-up so the double event is recognized */ | 777 | /* emit a key-up so the double event is recognized */ |
777 | dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event); | 778 | dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event); |
778 | input_report_key(cinergyt2->rc_input_dev, | 779 | input_report_key(cinergyt2->rc_input_dev, |
779 | cinergyt2->rc_input_event, 0); | 780 | cinergyt2->rc_input_event, 0); |
780 | } | 781 | } |
781 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); | 782 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); |
782 | input_report_key(cinergyt2->rc_input_dev, | 783 | input_report_key(cinergyt2->rc_input_dev, |
783 | cinergyt2->rc_input_event, 1); | 784 | cinergyt2->rc_input_event, 1); |
784 | cinergyt2->rc_last_code = rc_events[n].value; | 785 | cinergyt2->rc_last_code = rc_events[n].value; |
785 | } | 786 | } |
786 | } | 787 | } |
787 | 788 | ||
788 | out: | 789 | out: |
789 | schedule_delayed_work(&cinergyt2->rc_query_work, | 790 | schedule_delayed_work(&cinergyt2->rc_query_work, |
790 | msecs_to_jiffies(RC_QUERY_INTERVAL)); | 791 | msecs_to_jiffies(RC_QUERY_INTERVAL)); |
791 | 792 | ||
792 | mutex_unlock(&cinergyt2->sem); | 793 | mutex_unlock(&cinergyt2->sem); |
793 | } | 794 | } |
794 | 795 | ||
795 | static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | 796 | static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) |
796 | { | 797 | { |
797 | struct input_dev *input_dev; | 798 | struct input_dev *input_dev; |
798 | int i; | 799 | int i; |
799 | 800 | ||
800 | cinergyt2->rc_input_dev = input_dev = input_allocate_device(); | 801 | cinergyt2->rc_input_dev = input_dev = input_allocate_device(); |
801 | if (!input_dev) | 802 | if (!input_dev) |
802 | return -ENOMEM; | 803 | return -ENOMEM; |
803 | 804 | ||
804 | usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys)); | 805 | usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys)); |
805 | strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); | 806 | strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); |
806 | cinergyt2->rc_input_event = KEY_MAX; | 807 | cinergyt2->rc_input_event = KEY_MAX; |
807 | cinergyt2->rc_last_code = ~0; | 808 | cinergyt2->rc_last_code = ~0; |
808 | INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); | 809 | INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); |
809 | 810 | ||
810 | input_dev->name = DRIVER_NAME " remote control"; | 811 | input_dev->name = DRIVER_NAME " remote control"; |
811 | input_dev->phys = cinergyt2->phys; | 812 | input_dev->phys = cinergyt2->phys; |
812 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 813 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
813 | for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) | 814 | for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) |
814 | set_bit(rc_keys[i + 2], input_dev->keybit); | 815 | set_bit(rc_keys[i + 2], input_dev->keybit); |
815 | input_dev->keycodesize = 0; | 816 | input_dev->keycodesize = 0; |
816 | input_dev->keycodemax = 0; | 817 | input_dev->keycodemax = 0; |
817 | 818 | ||
818 | input_register_device(cinergyt2->rc_input_dev); | 819 | input_register_device(cinergyt2->rc_input_dev); |
819 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | 820 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); |
820 | 821 | ||
821 | return 0; | 822 | return 0; |
822 | } | 823 | } |
823 | 824 | ||
824 | static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) | 825 | static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) |
825 | { | 826 | { |
826 | cancel_delayed_work(&cinergyt2->rc_query_work); | 827 | cancel_delayed_work(&cinergyt2->rc_query_work); |
827 | input_unregister_device(cinergyt2->rc_input_dev); | 828 | input_unregister_device(cinergyt2->rc_input_dev); |
828 | } | 829 | } |
829 | 830 | ||
830 | static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) | 831 | static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) |
831 | { | 832 | { |
832 | cancel_delayed_work(&cinergyt2->rc_query_work); | 833 | cancel_delayed_work(&cinergyt2->rc_query_work); |
833 | } | 834 | } |
834 | 835 | ||
835 | static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) | 836 | static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) |
836 | { | 837 | { |
837 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | 838 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); |
838 | } | 839 | } |
839 | 840 | ||
840 | #else | 841 | #else |
841 | 842 | ||
842 | static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; } | 843 | static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; } |
843 | static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { } | 844 | static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { } |
844 | static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { } | 845 | static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { } |
845 | static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } | 846 | static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } |
846 | 847 | ||
847 | #endif /* ENABLE_RC */ | 848 | #endif /* ENABLE_RC */ |
848 | 849 | ||
849 | static void cinergyt2_query (void *data) | 850 | static void cinergyt2_query (void *data) |
850 | { | 851 | { |
851 | struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; | 852 | struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; |
852 | char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | 853 | char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; |
853 | struct dvbt_get_status_msg *s = &cinergyt2->status; | 854 | struct dvbt_get_status_msg *s = &cinergyt2->status; |
854 | uint8_t lock_bits; | 855 | uint8_t lock_bits; |
855 | uint32_t unc; | 856 | uint32_t unc; |
856 | 857 | ||
857 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 858 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
858 | return; | 859 | return; |
859 | 860 | ||
860 | unc = s->uncorrected_block_count; | 861 | unc = s->uncorrected_block_count; |
861 | lock_bits = s->lock_bits; | 862 | lock_bits = s->lock_bits; |
862 | 863 | ||
863 | cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s)); | 864 | cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s)); |
864 | 865 | ||
865 | unc += le32_to_cpu(s->uncorrected_block_count); | 866 | unc += le32_to_cpu(s->uncorrected_block_count); |
866 | s->uncorrected_block_count = unc; | 867 | s->uncorrected_block_count = unc; |
867 | 868 | ||
868 | if (lock_bits != s->lock_bits) { | 869 | if (lock_bits != s->lock_bits) { |
869 | wake_up_interruptible(&cinergyt2->poll_wq); | 870 | wake_up_interruptible(&cinergyt2->poll_wq); |
870 | cinergyt2->pending_fe_events++; | 871 | cinergyt2->pending_fe_events++; |
871 | } | 872 | } |
872 | 873 | ||
873 | schedule_delayed_work(&cinergyt2->query_work, | 874 | schedule_delayed_work(&cinergyt2->query_work, |
874 | msecs_to_jiffies(QUERY_INTERVAL)); | 875 | msecs_to_jiffies(QUERY_INTERVAL)); |
875 | 876 | ||
876 | mutex_unlock(&cinergyt2->sem); | 877 | mutex_unlock(&cinergyt2->sem); |
877 | } | 878 | } |
878 | 879 | ||
879 | static int cinergyt2_probe (struct usb_interface *intf, | 880 | static int cinergyt2_probe (struct usb_interface *intf, |
880 | const struct usb_device_id *id) | 881 | const struct usb_device_id *id) |
881 | { | 882 | { |
882 | struct cinergyt2 *cinergyt2; | 883 | struct cinergyt2 *cinergyt2; |
883 | int err; | 884 | int err; |
884 | 885 | ||
885 | if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { | 886 | if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { |
886 | dprintk(1, "out of memory?!?\n"); | 887 | dprintk(1, "out of memory?!?\n"); |
887 | return -ENOMEM; | 888 | return -ENOMEM; |
888 | } | 889 | } |
889 | 890 | ||
890 | memset (cinergyt2, 0, sizeof (struct cinergyt2)); | 891 | memset (cinergyt2, 0, sizeof (struct cinergyt2)); |
891 | usb_set_intfdata (intf, (void *) cinergyt2); | 892 | usb_set_intfdata (intf, (void *) cinergyt2); |
892 | 893 | ||
893 | mutex_init(&cinergyt2->sem); | 894 | mutex_init(&cinergyt2->sem); |
894 | init_waitqueue_head (&cinergyt2->poll_wq); | 895 | init_waitqueue_head (&cinergyt2->poll_wq); |
895 | INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); | 896 | INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); |
896 | 897 | ||
897 | cinergyt2->udev = interface_to_usbdev(intf); | 898 | cinergyt2->udev = interface_to_usbdev(intf); |
898 | cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; | 899 | cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; |
899 | 900 | ||
900 | if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) { | 901 | if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) { |
901 | dprintk(1, "unable to allocate stream urbs\n"); | 902 | dprintk(1, "unable to allocate stream urbs\n"); |
902 | kfree(cinergyt2); | 903 | kfree(cinergyt2); |
903 | return -ENOMEM; | 904 | return -ENOMEM; |
904 | } | 905 | } |
905 | 906 | ||
906 | if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) { | 907 | if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) { |
907 | kfree(cinergyt2); | 908 | kfree(cinergyt2); |
908 | return err; | 909 | return err; |
909 | } | 910 | } |
910 | 911 | ||
911 | cinergyt2->demux.priv = cinergyt2; | 912 | cinergyt2->demux.priv = cinergyt2; |
912 | cinergyt2->demux.filternum = 256; | 913 | cinergyt2->demux.filternum = 256; |
913 | cinergyt2->demux.feednum = 256; | 914 | cinergyt2->demux.feednum = 256; |
914 | cinergyt2->demux.start_feed = cinergyt2_start_feed; | 915 | cinergyt2->demux.start_feed = cinergyt2_start_feed; |
915 | cinergyt2->demux.stop_feed = cinergyt2_stop_feed; | 916 | cinergyt2->demux.stop_feed = cinergyt2_stop_feed; |
916 | cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING | | 917 | cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING | |
917 | DMX_SECTION_FILTERING | | 918 | DMX_SECTION_FILTERING | |
918 | DMX_MEMORY_BASED_FILTERING; | 919 | DMX_MEMORY_BASED_FILTERING; |
919 | 920 | ||
920 | if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) { | 921 | if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) { |
921 | dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err); | 922 | dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err); |
922 | goto bailout; | 923 | goto bailout; |
923 | } | 924 | } |
924 | 925 | ||
925 | cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum; | 926 | cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum; |
926 | cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx; | 927 | cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx; |
927 | cinergyt2->dmxdev.capabilities = 0; | 928 | cinergyt2->dmxdev.capabilities = 0; |
928 | 929 | ||
929 | if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) { | 930 | if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) { |
930 | dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err); | 931 | dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err); |
931 | goto bailout; | 932 | goto bailout; |
932 | } | 933 | } |
933 | 934 | ||
934 | if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx)) | 935 | if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx)) |
935 | dprintk(1, "dvb_net_init() failed!\n"); | 936 | dprintk(1, "dvb_net_init() failed!\n"); |
936 | 937 | ||
937 | dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev, | 938 | dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev, |
938 | &cinergyt2_fe_template, cinergyt2, | 939 | &cinergyt2_fe_template, cinergyt2, |
939 | DVB_DEVICE_FRONTEND); | 940 | DVB_DEVICE_FRONTEND); |
940 | 941 | ||
941 | err = cinergyt2_register_rc(cinergyt2); | 942 | err = cinergyt2_register_rc(cinergyt2); |
942 | if (err) | 943 | if (err) |
943 | goto bailout; | 944 | goto bailout; |
944 | 945 | ||
945 | return 0; | 946 | return 0; |
946 | 947 | ||
947 | bailout: | 948 | bailout: |
948 | dvb_net_release(&cinergyt2->dvbnet); | 949 | dvb_net_release(&cinergyt2->dvbnet); |
949 | dvb_dmxdev_release(&cinergyt2->dmxdev); | 950 | dvb_dmxdev_release(&cinergyt2->dmxdev); |
950 | dvb_dmx_release(&cinergyt2->demux); | 951 | dvb_dmx_release(&cinergyt2->demux); |
951 | dvb_unregister_adapter(&cinergyt2->adapter); | 952 | dvb_unregister_adapter(&cinergyt2->adapter); |
952 | cinergyt2_free_stream_urbs(cinergyt2); | 953 | cinergyt2_free_stream_urbs(cinergyt2); |
953 | kfree(cinergyt2); | 954 | kfree(cinergyt2); |
954 | return -ENOMEM; | 955 | return -ENOMEM; |
955 | } | 956 | } |
956 | 957 | ||
957 | static void cinergyt2_disconnect (struct usb_interface *intf) | 958 | static void cinergyt2_disconnect (struct usb_interface *intf) |
958 | { | 959 | { |
959 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); | 960 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); |
960 | 961 | ||
961 | flush_scheduled_work(); | 962 | flush_scheduled_work(); |
962 | 963 | ||
963 | cinergyt2_unregister_rc(cinergyt2); | 964 | cinergyt2_unregister_rc(cinergyt2); |
964 | 965 | ||
965 | cancel_delayed_work(&cinergyt2->query_work); | 966 | cancel_delayed_work(&cinergyt2->query_work); |
966 | wake_up_interruptible(&cinergyt2->poll_wq); | 967 | wake_up_interruptible(&cinergyt2->poll_wq); |
967 | 968 | ||
968 | cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx); | 969 | cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx); |
969 | cinergyt2->disconnect_pending = 1; | 970 | cinergyt2->disconnect_pending = 1; |
970 | 971 | ||
971 | if (!atomic_read(&cinergyt2->inuse)) | 972 | if (!atomic_read(&cinergyt2->inuse)) |
972 | cinergyt2_unregister(cinergyt2); | 973 | cinergyt2_unregister(cinergyt2); |
973 | } | 974 | } |
974 | 975 | ||
975 | static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) | 976 | static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) |
976 | { | 977 | { |
977 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); | 978 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); |
978 | 979 | ||
979 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 980 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
980 | return -ERESTARTSYS; | 981 | return -ERESTARTSYS; |
981 | 982 | ||
982 | if (1) { | 983 | if (1) { |
983 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); | 984 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); |
984 | 985 | ||
985 | cinergyt2_suspend_rc(cinergyt2); | 986 | cinergyt2_suspend_rc(cinergyt2); |
986 | cancel_delayed_work(&cinergyt2->query_work); | 987 | cancel_delayed_work(&cinergyt2->query_work); |
987 | if (cinergyt2->streaming) | 988 | if (cinergyt2->streaming) |
988 | cinergyt2_stop_stream_xfer(cinergyt2); | 989 | cinergyt2_stop_stream_xfer(cinergyt2); |
989 | flush_scheduled_work(); | 990 | flush_scheduled_work(); |
990 | cinergyt2_sleep(cinergyt2, 1); | 991 | cinergyt2_sleep(cinergyt2, 1); |
991 | } | 992 | } |
992 | 993 | ||
993 | mutex_unlock(&cinergyt2->sem); | 994 | mutex_unlock(&cinergyt2->sem); |
994 | return 0; | 995 | return 0; |
995 | } | 996 | } |
996 | 997 | ||
997 | static int cinergyt2_resume (struct usb_interface *intf) | 998 | static int cinergyt2_resume (struct usb_interface *intf) |
998 | { | 999 | { |
999 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); | 1000 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); |
1000 | struct dvbt_set_parameters_msg *param = &cinergyt2->param; | 1001 | struct dvbt_set_parameters_msg *param = &cinergyt2->param; |
1001 | 1002 | ||
1002 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 1003 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
1003 | return -ERESTARTSYS; | 1004 | return -ERESTARTSYS; |
1004 | 1005 | ||
1005 | if (!cinergyt2->sleeping) { | 1006 | if (!cinergyt2->sleeping) { |
1006 | cinergyt2_sleep(cinergyt2, 0); | 1007 | cinergyt2_sleep(cinergyt2, 0); |
1007 | cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0); | 1008 | cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0); |
1008 | if (cinergyt2->streaming) | 1009 | if (cinergyt2->streaming) |
1009 | cinergyt2_start_stream_xfer(cinergyt2); | 1010 | cinergyt2_start_stream_xfer(cinergyt2); |
1010 | schedule_delayed_work(&cinergyt2->query_work, HZ/2); | 1011 | schedule_delayed_work(&cinergyt2->query_work, HZ/2); |
1011 | } | 1012 | } |
1012 | 1013 | ||
1013 | cinergyt2_resume_rc(cinergyt2); | 1014 | cinergyt2_resume_rc(cinergyt2); |
1014 | 1015 | ||
1015 | mutex_unlock(&cinergyt2->sem); | 1016 | mutex_unlock(&cinergyt2->sem); |
1016 | return 0; | 1017 | return 0; |
1017 | } | 1018 | } |
1018 | 1019 | ||
1019 | static const struct usb_device_id cinergyt2_table [] __devinitdata = { | 1020 | static const struct usb_device_id cinergyt2_table [] __devinitdata = { |
1020 | { USB_DEVICE(0x0ccd, 0x0038) }, | 1021 | { USB_DEVICE(0x0ccd, 0x0038) }, |
1021 | { 0 } | 1022 | { 0 } |
1022 | }; | 1023 | }; |
1023 | 1024 | ||
1024 | MODULE_DEVICE_TABLE(usb, cinergyt2_table); | 1025 | MODULE_DEVICE_TABLE(usb, cinergyt2_table); |
1025 | 1026 | ||
1026 | static struct usb_driver cinergyt2_driver = { | 1027 | static struct usb_driver cinergyt2_driver = { |
1027 | .name = "cinergyT2", | 1028 | .name = "cinergyT2", |
1028 | .probe = cinergyt2_probe, | 1029 | .probe = cinergyt2_probe, |
1029 | .disconnect = cinergyt2_disconnect, | 1030 | .disconnect = cinergyt2_disconnect, |
1030 | .suspend = cinergyt2_suspend, | 1031 | .suspend = cinergyt2_suspend, |
1031 | .resume = cinergyt2_resume, | 1032 | .resume = cinergyt2_resume, |
1032 | .id_table = cinergyt2_table | 1033 | .id_table = cinergyt2_table |
1033 | }; | 1034 | }; |
1034 | 1035 | ||
1035 | static int __init cinergyt2_init (void) | 1036 | static int __init cinergyt2_init (void) |
1036 | { | 1037 | { |
1037 | int err; | 1038 | int err; |
1038 | 1039 | ||
1039 | if ((err = usb_register(&cinergyt2_driver)) < 0) | 1040 | if ((err = usb_register(&cinergyt2_driver)) < 0) |
1040 | dprintk(1, "usb_register() failed! (err %i)\n", err); | 1041 | dprintk(1, "usb_register() failed! (err %i)\n", err); |
1041 | 1042 | ||
1042 | return err; | 1043 | return err; |
1043 | } | 1044 | } |
1044 | 1045 | ||
1045 | static void __exit cinergyt2_exit (void) | 1046 | static void __exit cinergyt2_exit (void) |
1046 | { | 1047 | { |
1047 | usb_deregister(&cinergyt2_driver); | 1048 | usb_deregister(&cinergyt2_driver); |
1048 | } | 1049 | } |
1049 | 1050 | ||
1050 | module_init (cinergyt2_init); | 1051 | module_init (cinergyt2_init); |
1051 | module_exit (cinergyt2_exit); | 1052 | module_exit (cinergyt2_exit); |
1052 | 1053 | ||
1053 | MODULE_LICENSE("GPL"); | 1054 | MODULE_LICENSE("GPL"); |
1054 | MODULE_AUTHOR("Holger Waechtler, Daniel Mack"); | 1055 | MODULE_AUTHOR("Holger Waechtler, Daniel Mack"); |
1055 | 1056 |
include/linux/poll.h
1 | #ifndef _LINUX_POLL_H | 1 | #ifndef _LINUX_POLL_H |
2 | #define _LINUX_POLL_H | 2 | #define _LINUX_POLL_H |
3 | 3 | ||
4 | #include <asm/poll.h> | 4 | #include <asm/poll.h> |
5 | 5 | ||
6 | #ifdef __KERNEL__ | 6 | #ifdef __KERNEL__ |
7 | 7 | ||
8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
9 | #include <linux/wait.h> | 9 | #include <linux/wait.h> |
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/sched.h> | ||
12 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
13 | 14 | ||
14 | /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating | 15 | /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating |
15 | additional memory. */ | 16 | additional memory. */ |
16 | #define MAX_STACK_ALLOC 832 | 17 | #define MAX_STACK_ALLOC 832 |
17 | #define FRONTEND_STACK_ALLOC 256 | 18 | #define FRONTEND_STACK_ALLOC 256 |
18 | #define SELECT_STACK_ALLOC FRONTEND_STACK_ALLOC | 19 | #define SELECT_STACK_ALLOC FRONTEND_STACK_ALLOC |
19 | #define POLL_STACK_ALLOC FRONTEND_STACK_ALLOC | 20 | #define POLL_STACK_ALLOC FRONTEND_STACK_ALLOC |
20 | #define WQUEUES_STACK_ALLOC (MAX_STACK_ALLOC - FRONTEND_STACK_ALLOC) | 21 | #define WQUEUES_STACK_ALLOC (MAX_STACK_ALLOC - FRONTEND_STACK_ALLOC) |
21 | #define N_INLINE_POLL_ENTRIES (WQUEUES_STACK_ALLOC / sizeof(struct poll_table_entry)) | 22 | #define N_INLINE_POLL_ENTRIES (WQUEUES_STACK_ALLOC / sizeof(struct poll_table_entry)) |
22 | 23 | ||
23 | struct poll_table_struct; | 24 | struct poll_table_struct; |
24 | 25 | ||
25 | /* | 26 | /* |
26 | * structures and helpers for f_op->poll implementations | 27 | * structures and helpers for f_op->poll implementations |
27 | */ | 28 | */ |
28 | typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *); | 29 | typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *); |
29 | 30 | ||
30 | typedef struct poll_table_struct { | 31 | typedef struct poll_table_struct { |
31 | poll_queue_proc qproc; | 32 | poll_queue_proc qproc; |
32 | } poll_table; | 33 | } poll_table; |
33 | 34 | ||
34 | static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) | 35 | static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) |
35 | { | 36 | { |
36 | if (p && wait_address) | 37 | if (p && wait_address) |
37 | p->qproc(filp, wait_address, p); | 38 | p->qproc(filp, wait_address, p); |
38 | } | 39 | } |
39 | 40 | ||
40 | static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) | 41 | static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) |
41 | { | 42 | { |
42 | pt->qproc = qproc; | 43 | pt->qproc = qproc; |
43 | } | 44 | } |
44 | 45 | ||
45 | struct poll_table_entry { | 46 | struct poll_table_entry { |
46 | struct file * filp; | 47 | struct file * filp; |
47 | wait_queue_t wait; | 48 | wait_queue_t wait; |
48 | wait_queue_head_t * wait_address; | 49 | wait_queue_head_t * wait_address; |
49 | }; | 50 | }; |
50 | 51 | ||
51 | /* | 52 | /* |
52 | * Structures and helpers for sys_poll/sys_poll | 53 | * Structures and helpers for sys_poll/sys_poll |
53 | */ | 54 | */ |
54 | struct poll_wqueues { | 55 | struct poll_wqueues { |
55 | poll_table pt; | 56 | poll_table pt; |
56 | struct poll_table_page * table; | 57 | struct poll_table_page * table; |
57 | int error; | 58 | int error; |
58 | int inline_index; | 59 | int inline_index; |
59 | struct poll_table_entry inline_entries[N_INLINE_POLL_ENTRIES]; | 60 | struct poll_table_entry inline_entries[N_INLINE_POLL_ENTRIES]; |
60 | }; | 61 | }; |
61 | 62 | ||
62 | extern void poll_initwait(struct poll_wqueues *pwq); | 63 | extern void poll_initwait(struct poll_wqueues *pwq); |
63 | extern void poll_freewait(struct poll_wqueues *pwq); | 64 | extern void poll_freewait(struct poll_wqueues *pwq); |
64 | 65 | ||
65 | /* | 66 | /* |
66 | * Scaleable version of the fd_set. | 67 | * Scaleable version of the fd_set. |
67 | */ | 68 | */ |
68 | 69 | ||
69 | typedef struct { | 70 | typedef struct { |
70 | unsigned long *in, *out, *ex; | 71 | unsigned long *in, *out, *ex; |
71 | unsigned long *res_in, *res_out, *res_ex; | 72 | unsigned long *res_in, *res_out, *res_ex; |
72 | } fd_set_bits; | 73 | } fd_set_bits; |
73 | 74 | ||
74 | /* | 75 | /* |
75 | * How many longwords for "nr" bits? | 76 | * How many longwords for "nr" bits? |
76 | */ | 77 | */ |
77 | #define FDS_BITPERLONG (8*sizeof(long)) | 78 | #define FDS_BITPERLONG (8*sizeof(long)) |
78 | #define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG) | 79 | #define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG) |
79 | #define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long)) | 80 | #define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long)) |
80 | 81 | ||
81 | /* | 82 | /* |
82 | * We do a VERIFY_WRITE here even though we are only reading this time: | 83 | * We do a VERIFY_WRITE here even though we are only reading this time: |
83 | * we'll write to it eventually.. | 84 | * we'll write to it eventually.. |
84 | * | 85 | * |
85 | * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned. | 86 | * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned. |
86 | */ | 87 | */ |
87 | static inline | 88 | static inline |
88 | int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset) | 89 | int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset) |
89 | { | 90 | { |
90 | nr = FDS_BYTES(nr); | 91 | nr = FDS_BYTES(nr); |
91 | if (ufdset) | 92 | if (ufdset) |
92 | return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0; | 93 | return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0; |
93 | 94 | ||
94 | memset(fdset, 0, nr); | 95 | memset(fdset, 0, nr); |
95 | return 0; | 96 | return 0; |
96 | } | 97 | } |
97 | 98 | ||
98 | static inline unsigned long __must_check | 99 | static inline unsigned long __must_check |
99 | set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset) | 100 | set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset) |
100 | { | 101 | { |
101 | if (ufdset) | 102 | if (ufdset) |
102 | return __copy_to_user(ufdset, fdset, FDS_BYTES(nr)); | 103 | return __copy_to_user(ufdset, fdset, FDS_BYTES(nr)); |
103 | return 0; | 104 | return 0; |
104 | } | 105 | } |
105 | 106 | ||
106 | static inline | 107 | static inline |
107 | void zero_fd_set(unsigned long nr, unsigned long *fdset) | 108 | void zero_fd_set(unsigned long nr, unsigned long *fdset) |
108 | { | 109 | { |
109 | memset(fdset, 0, FDS_BYTES(nr)); | 110 | memset(fdset, 0, FDS_BYTES(nr)); |
110 | } | 111 | } |
111 | 112 | ||
112 | #define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1) | 113 | #define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1) |
113 | 114 | ||
114 | extern int do_select(int n, fd_set_bits *fds, s64 *timeout); | 115 | extern int do_select(int n, fd_set_bits *fds, s64 *timeout); |
115 | extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds, | 116 | extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds, |
116 | s64 *timeout); | 117 | s64 *timeout); |
117 | 118 | ||
118 | #endif /* KERNEL */ | 119 | #endif /* KERNEL */ |
119 | 120 | ||
120 | #endif /* _LINUX_POLL_H */ | 121 | #endif /* _LINUX_POLL_H */ |
121 | 122 |
include/sound/pcm.h
1 | #ifndef __SOUND_PCM_H | 1 | #ifndef __SOUND_PCM_H |
2 | #define __SOUND_PCM_H | 2 | #define __SOUND_PCM_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * Digital Audio (PCM) abstract layer | 5 | * Digital Audio (PCM) abstract layer |
6 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> |
7 | * Abramo Bagnara <abramo@alsa-project.org> | 7 | * Abramo Bagnara <abramo@alsa-project.org> |
8 | * | 8 | * |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | 14 | * |
15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | * | 19 | * |
20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <sound/asound.h> | 26 | #include <sound/asound.h> |
27 | #include <sound/memalloc.h> | 27 | #include <sound/memalloc.h> |
28 | #include <linux/poll.h> | 28 | #include <linux/poll.h> |
29 | #include <linux/mm.h> | ||
29 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
30 | 31 | ||
31 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) | 32 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) |
32 | #define snd_pcm_chip(pcm) ((pcm)->private_data) | 33 | #define snd_pcm_chip(pcm) ((pcm)->private_data) |
33 | 34 | ||
34 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 35 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
35 | #include "pcm_oss.h" | 36 | #include "pcm_oss.h" |
36 | #endif | 37 | #endif |
37 | 38 | ||
38 | /* | 39 | /* |
39 | * Hardware (lowlevel) section | 40 | * Hardware (lowlevel) section |
40 | */ | 41 | */ |
41 | 42 | ||
42 | struct snd_pcm_hardware { | 43 | struct snd_pcm_hardware { |
43 | unsigned int info; /* SNDRV_PCM_INFO_* */ | 44 | unsigned int info; /* SNDRV_PCM_INFO_* */ |
44 | u64 formats; /* SNDRV_PCM_FMTBIT_* */ | 45 | u64 formats; /* SNDRV_PCM_FMTBIT_* */ |
45 | unsigned int rates; /* SNDRV_PCM_RATE_* */ | 46 | unsigned int rates; /* SNDRV_PCM_RATE_* */ |
46 | unsigned int rate_min; /* min rate */ | 47 | unsigned int rate_min; /* min rate */ |
47 | unsigned int rate_max; /* max rate */ | 48 | unsigned int rate_max; /* max rate */ |
48 | unsigned int channels_min; /* min channels */ | 49 | unsigned int channels_min; /* min channels */ |
49 | unsigned int channels_max; /* max channels */ | 50 | unsigned int channels_max; /* max channels */ |
50 | size_t buffer_bytes_max; /* max buffer size */ | 51 | size_t buffer_bytes_max; /* max buffer size */ |
51 | size_t period_bytes_min; /* min period size */ | 52 | size_t period_bytes_min; /* min period size */ |
52 | size_t period_bytes_max; /* max period size */ | 53 | size_t period_bytes_max; /* max period size */ |
53 | unsigned int periods_min; /* min # of periods */ | 54 | unsigned int periods_min; /* min # of periods */ |
54 | unsigned int periods_max; /* max # of periods */ | 55 | unsigned int periods_max; /* max # of periods */ |
55 | size_t fifo_size; /* fifo size in bytes */ | 56 | size_t fifo_size; /* fifo size in bytes */ |
56 | }; | 57 | }; |
57 | 58 | ||
58 | struct snd_pcm_ops { | 59 | struct snd_pcm_ops { |
59 | int (*open)(struct snd_pcm_substream *substream); | 60 | int (*open)(struct snd_pcm_substream *substream); |
60 | int (*close)(struct snd_pcm_substream *substream); | 61 | int (*close)(struct snd_pcm_substream *substream); |
61 | int (*ioctl)(struct snd_pcm_substream * substream, | 62 | int (*ioctl)(struct snd_pcm_substream * substream, |
62 | unsigned int cmd, void *arg); | 63 | unsigned int cmd, void *arg); |
63 | int (*hw_params)(struct snd_pcm_substream *substream, | 64 | int (*hw_params)(struct snd_pcm_substream *substream, |
64 | struct snd_pcm_hw_params *params); | 65 | struct snd_pcm_hw_params *params); |
65 | int (*hw_free)(struct snd_pcm_substream *substream); | 66 | int (*hw_free)(struct snd_pcm_substream *substream); |
66 | int (*prepare)(struct snd_pcm_substream *substream); | 67 | int (*prepare)(struct snd_pcm_substream *substream); |
67 | int (*trigger)(struct snd_pcm_substream *substream, int cmd); | 68 | int (*trigger)(struct snd_pcm_substream *substream, int cmd); |
68 | snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream); | 69 | snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream); |
69 | int (*copy)(struct snd_pcm_substream *substream, int channel, | 70 | int (*copy)(struct snd_pcm_substream *substream, int channel, |
70 | snd_pcm_uframes_t pos, | 71 | snd_pcm_uframes_t pos, |
71 | void __user *buf, snd_pcm_uframes_t count); | 72 | void __user *buf, snd_pcm_uframes_t count); |
72 | int (*silence)(struct snd_pcm_substream *substream, int channel, | 73 | int (*silence)(struct snd_pcm_substream *substream, int channel, |
73 | snd_pcm_uframes_t pos, snd_pcm_uframes_t count); | 74 | snd_pcm_uframes_t pos, snd_pcm_uframes_t count); |
74 | struct page *(*page)(struct snd_pcm_substream *substream, | 75 | struct page *(*page)(struct snd_pcm_substream *substream, |
75 | unsigned long offset); | 76 | unsigned long offset); |
76 | int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); | 77 | int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); |
77 | int (*ack)(struct snd_pcm_substream *substream); | 78 | int (*ack)(struct snd_pcm_substream *substream); |
78 | }; | 79 | }; |
79 | 80 | ||
80 | /* | 81 | /* |
81 | * | 82 | * |
82 | */ | 83 | */ |
83 | 84 | ||
84 | #define SNDRV_PCM_DEVICES 8 | 85 | #define SNDRV_PCM_DEVICES 8 |
85 | 86 | ||
86 | #define SNDRV_PCM_IOCTL1_FALSE ((void *)0) | 87 | #define SNDRV_PCM_IOCTL1_FALSE ((void *)0) |
87 | #define SNDRV_PCM_IOCTL1_TRUE ((void *)1) | 88 | #define SNDRV_PCM_IOCTL1_TRUE ((void *)1) |
88 | 89 | ||
89 | #define SNDRV_PCM_IOCTL1_RESET 0 | 90 | #define SNDRV_PCM_IOCTL1_RESET 0 |
90 | #define SNDRV_PCM_IOCTL1_INFO 1 | 91 | #define SNDRV_PCM_IOCTL1_INFO 1 |
91 | #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 | 92 | #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 |
92 | #define SNDRV_PCM_IOCTL1_GSTATE 3 | 93 | #define SNDRV_PCM_IOCTL1_GSTATE 3 |
93 | 94 | ||
94 | #define SNDRV_PCM_TRIGGER_STOP 0 | 95 | #define SNDRV_PCM_TRIGGER_STOP 0 |
95 | #define SNDRV_PCM_TRIGGER_START 1 | 96 | #define SNDRV_PCM_TRIGGER_START 1 |
96 | #define SNDRV_PCM_TRIGGER_PAUSE_PUSH 3 | 97 | #define SNDRV_PCM_TRIGGER_PAUSE_PUSH 3 |
97 | #define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 4 | 98 | #define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 4 |
98 | #define SNDRV_PCM_TRIGGER_SUSPEND 5 | 99 | #define SNDRV_PCM_TRIGGER_SUSPEND 5 |
99 | #define SNDRV_PCM_TRIGGER_RESUME 6 | 100 | #define SNDRV_PCM_TRIGGER_RESUME 6 |
100 | 101 | ||
101 | #define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) | 102 | #define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) |
102 | 103 | ||
103 | /* If you change this don't forget to change rates[] table in pcm_native.c */ | 104 | /* If you change this don't forget to change rates[] table in pcm_native.c */ |
104 | #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ | 105 | #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ |
105 | #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ | 106 | #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ |
106 | #define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ | 107 | #define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ |
107 | #define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ | 108 | #define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ |
108 | #define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ | 109 | #define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ |
109 | #define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ | 110 | #define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ |
110 | #define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ | 111 | #define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ |
111 | #define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ | 112 | #define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ |
112 | #define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ | 113 | #define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ |
113 | #define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ | 114 | #define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ |
114 | #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ | 115 | #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ |
115 | #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ | 116 | #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ |
116 | #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ | 117 | #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ |
117 | 118 | ||
118 | #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ | 119 | #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ |
119 | #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ | 120 | #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ |
120 | 121 | ||
121 | #define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ | 122 | #define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ |
122 | SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ | 123 | SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ |
123 | SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) | 124 | SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) |
124 | #define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000) | 125 | #define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000) |
125 | #define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\ | 126 | #define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\ |
126 | SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) | 127 | SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) |
127 | #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ | 128 | #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ |
128 | SNDRV_PCM_RATE_192000) | 129 | SNDRV_PCM_RATE_192000) |
129 | #define SNDRV_PCM_FMTBIT_S8 (1ULL << SNDRV_PCM_FORMAT_S8) | 130 | #define SNDRV_PCM_FMTBIT_S8 (1ULL << SNDRV_PCM_FORMAT_S8) |
130 | #define SNDRV_PCM_FMTBIT_U8 (1ULL << SNDRV_PCM_FORMAT_U8) | 131 | #define SNDRV_PCM_FMTBIT_U8 (1ULL << SNDRV_PCM_FORMAT_U8) |
131 | #define SNDRV_PCM_FMTBIT_S16_LE (1ULL << SNDRV_PCM_FORMAT_S16_LE) | 132 | #define SNDRV_PCM_FMTBIT_S16_LE (1ULL << SNDRV_PCM_FORMAT_S16_LE) |
132 | #define SNDRV_PCM_FMTBIT_S16_BE (1ULL << SNDRV_PCM_FORMAT_S16_BE) | 133 | #define SNDRV_PCM_FMTBIT_S16_BE (1ULL << SNDRV_PCM_FORMAT_S16_BE) |
133 | #define SNDRV_PCM_FMTBIT_U16_LE (1ULL << SNDRV_PCM_FORMAT_U16_LE) | 134 | #define SNDRV_PCM_FMTBIT_U16_LE (1ULL << SNDRV_PCM_FORMAT_U16_LE) |
134 | #define SNDRV_PCM_FMTBIT_U16_BE (1ULL << SNDRV_PCM_FORMAT_U16_BE) | 135 | #define SNDRV_PCM_FMTBIT_U16_BE (1ULL << SNDRV_PCM_FORMAT_U16_BE) |
135 | #define SNDRV_PCM_FMTBIT_S24_LE (1ULL << SNDRV_PCM_FORMAT_S24_LE) | 136 | #define SNDRV_PCM_FMTBIT_S24_LE (1ULL << SNDRV_PCM_FORMAT_S24_LE) |
136 | #define SNDRV_PCM_FMTBIT_S24_BE (1ULL << SNDRV_PCM_FORMAT_S24_BE) | 137 | #define SNDRV_PCM_FMTBIT_S24_BE (1ULL << SNDRV_PCM_FORMAT_S24_BE) |
137 | #define SNDRV_PCM_FMTBIT_U24_LE (1ULL << SNDRV_PCM_FORMAT_U24_LE) | 138 | #define SNDRV_PCM_FMTBIT_U24_LE (1ULL << SNDRV_PCM_FORMAT_U24_LE) |
138 | #define SNDRV_PCM_FMTBIT_U24_BE (1ULL << SNDRV_PCM_FORMAT_U24_BE) | 139 | #define SNDRV_PCM_FMTBIT_U24_BE (1ULL << SNDRV_PCM_FORMAT_U24_BE) |
139 | #define SNDRV_PCM_FMTBIT_S32_LE (1ULL << SNDRV_PCM_FORMAT_S32_LE) | 140 | #define SNDRV_PCM_FMTBIT_S32_LE (1ULL << SNDRV_PCM_FORMAT_S32_LE) |
140 | #define SNDRV_PCM_FMTBIT_S32_BE (1ULL << SNDRV_PCM_FORMAT_S32_BE) | 141 | #define SNDRV_PCM_FMTBIT_S32_BE (1ULL << SNDRV_PCM_FORMAT_S32_BE) |
141 | #define SNDRV_PCM_FMTBIT_U32_LE (1ULL << SNDRV_PCM_FORMAT_U32_LE) | 142 | #define SNDRV_PCM_FMTBIT_U32_LE (1ULL << SNDRV_PCM_FORMAT_U32_LE) |
142 | #define SNDRV_PCM_FMTBIT_U32_BE (1ULL << SNDRV_PCM_FORMAT_U32_BE) | 143 | #define SNDRV_PCM_FMTBIT_U32_BE (1ULL << SNDRV_PCM_FORMAT_U32_BE) |
143 | #define SNDRV_PCM_FMTBIT_FLOAT_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT_LE) | 144 | #define SNDRV_PCM_FMTBIT_FLOAT_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT_LE) |
144 | #define SNDRV_PCM_FMTBIT_FLOAT_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT_BE) | 145 | #define SNDRV_PCM_FMTBIT_FLOAT_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT_BE) |
145 | #define SNDRV_PCM_FMTBIT_FLOAT64_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE) | 146 | #define SNDRV_PCM_FMTBIT_FLOAT64_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE) |
146 | #define SNDRV_PCM_FMTBIT_FLOAT64_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE) | 147 | #define SNDRV_PCM_FMTBIT_FLOAT64_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE) |
147 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) | 148 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) |
148 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE) | 149 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE) |
149 | #define SNDRV_PCM_FMTBIT_MU_LAW (1ULL << SNDRV_PCM_FORMAT_MU_LAW) | 150 | #define SNDRV_PCM_FMTBIT_MU_LAW (1ULL << SNDRV_PCM_FORMAT_MU_LAW) |
150 | #define SNDRV_PCM_FMTBIT_A_LAW (1ULL << SNDRV_PCM_FORMAT_A_LAW) | 151 | #define SNDRV_PCM_FMTBIT_A_LAW (1ULL << SNDRV_PCM_FORMAT_A_LAW) |
151 | #define SNDRV_PCM_FMTBIT_IMA_ADPCM (1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM) | 152 | #define SNDRV_PCM_FMTBIT_IMA_ADPCM (1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM) |
152 | #define SNDRV_PCM_FMTBIT_MPEG (1ULL << SNDRV_PCM_FORMAT_MPEG) | 153 | #define SNDRV_PCM_FMTBIT_MPEG (1ULL << SNDRV_PCM_FORMAT_MPEG) |
153 | #define SNDRV_PCM_FMTBIT_GSM (1ULL << SNDRV_PCM_FORMAT_GSM) | 154 | #define SNDRV_PCM_FMTBIT_GSM (1ULL << SNDRV_PCM_FORMAT_GSM) |
154 | #define SNDRV_PCM_FMTBIT_SPECIAL (1ULL << SNDRV_PCM_FORMAT_SPECIAL) | 155 | #define SNDRV_PCM_FMTBIT_SPECIAL (1ULL << SNDRV_PCM_FORMAT_SPECIAL) |
155 | #define SNDRV_PCM_FMTBIT_S24_3LE (1ULL << SNDRV_PCM_FORMAT_S24_3LE) | 156 | #define SNDRV_PCM_FMTBIT_S24_3LE (1ULL << SNDRV_PCM_FORMAT_S24_3LE) |
156 | #define SNDRV_PCM_FMTBIT_U24_3LE (1ULL << SNDRV_PCM_FORMAT_U24_3LE) | 157 | #define SNDRV_PCM_FMTBIT_U24_3LE (1ULL << SNDRV_PCM_FORMAT_U24_3LE) |
157 | #define SNDRV_PCM_FMTBIT_S24_3BE (1ULL << SNDRV_PCM_FORMAT_S24_3BE) | 158 | #define SNDRV_PCM_FMTBIT_S24_3BE (1ULL << SNDRV_PCM_FORMAT_S24_3BE) |
158 | #define SNDRV_PCM_FMTBIT_U24_3BE (1ULL << SNDRV_PCM_FORMAT_U24_3BE) | 159 | #define SNDRV_PCM_FMTBIT_U24_3BE (1ULL << SNDRV_PCM_FORMAT_U24_3BE) |
159 | #define SNDRV_PCM_FMTBIT_S20_3LE (1ULL << SNDRV_PCM_FORMAT_S20_3LE) | 160 | #define SNDRV_PCM_FMTBIT_S20_3LE (1ULL << SNDRV_PCM_FORMAT_S20_3LE) |
160 | #define SNDRV_PCM_FMTBIT_U20_3LE (1ULL << SNDRV_PCM_FORMAT_U20_3LE) | 161 | #define SNDRV_PCM_FMTBIT_U20_3LE (1ULL << SNDRV_PCM_FORMAT_U20_3LE) |
161 | #define SNDRV_PCM_FMTBIT_S20_3BE (1ULL << SNDRV_PCM_FORMAT_S20_3BE) | 162 | #define SNDRV_PCM_FMTBIT_S20_3BE (1ULL << SNDRV_PCM_FORMAT_S20_3BE) |
162 | #define SNDRV_PCM_FMTBIT_U20_3BE (1ULL << SNDRV_PCM_FORMAT_U20_3BE) | 163 | #define SNDRV_PCM_FMTBIT_U20_3BE (1ULL << SNDRV_PCM_FORMAT_U20_3BE) |
163 | #define SNDRV_PCM_FMTBIT_S18_3LE (1ULL << SNDRV_PCM_FORMAT_S18_3LE) | 164 | #define SNDRV_PCM_FMTBIT_S18_3LE (1ULL << SNDRV_PCM_FORMAT_S18_3LE) |
164 | #define SNDRV_PCM_FMTBIT_U18_3LE (1ULL << SNDRV_PCM_FORMAT_U18_3LE) | 165 | #define SNDRV_PCM_FMTBIT_U18_3LE (1ULL << SNDRV_PCM_FORMAT_U18_3LE) |
165 | #define SNDRV_PCM_FMTBIT_S18_3BE (1ULL << SNDRV_PCM_FORMAT_S18_3BE) | 166 | #define SNDRV_PCM_FMTBIT_S18_3BE (1ULL << SNDRV_PCM_FORMAT_S18_3BE) |
166 | #define SNDRV_PCM_FMTBIT_U18_3BE (1ULL << SNDRV_PCM_FORMAT_U18_3BE) | 167 | #define SNDRV_PCM_FMTBIT_U18_3BE (1ULL << SNDRV_PCM_FORMAT_U18_3BE) |
167 | 168 | ||
168 | #ifdef SNDRV_LITTLE_ENDIAN | 169 | #ifdef SNDRV_LITTLE_ENDIAN |
169 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE | 170 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE |
170 | #define SNDRV_PCM_FMTBIT_U16 SNDRV_PCM_FMTBIT_U16_LE | 171 | #define SNDRV_PCM_FMTBIT_U16 SNDRV_PCM_FMTBIT_U16_LE |
171 | #define SNDRV_PCM_FMTBIT_S24 SNDRV_PCM_FMTBIT_S24_LE | 172 | #define SNDRV_PCM_FMTBIT_S24 SNDRV_PCM_FMTBIT_S24_LE |
172 | #define SNDRV_PCM_FMTBIT_U24 SNDRV_PCM_FMTBIT_U24_LE | 173 | #define SNDRV_PCM_FMTBIT_U24 SNDRV_PCM_FMTBIT_U24_LE |
173 | #define SNDRV_PCM_FMTBIT_S32 SNDRV_PCM_FMTBIT_S32_LE | 174 | #define SNDRV_PCM_FMTBIT_S32 SNDRV_PCM_FMTBIT_S32_LE |
174 | #define SNDRV_PCM_FMTBIT_U32 SNDRV_PCM_FMTBIT_U32_LE | 175 | #define SNDRV_PCM_FMTBIT_U32 SNDRV_PCM_FMTBIT_U32_LE |
175 | #define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_LE | 176 | #define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_LE |
176 | #define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_LE | 177 | #define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_LE |
177 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | 178 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
178 | #endif | 179 | #endif |
179 | #ifdef SNDRV_BIG_ENDIAN | 180 | #ifdef SNDRV_BIG_ENDIAN |
180 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_BE | 181 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_BE |
181 | #define SNDRV_PCM_FMTBIT_U16 SNDRV_PCM_FMTBIT_U16_BE | 182 | #define SNDRV_PCM_FMTBIT_U16 SNDRV_PCM_FMTBIT_U16_BE |
182 | #define SNDRV_PCM_FMTBIT_S24 SNDRV_PCM_FMTBIT_S24_BE | 183 | #define SNDRV_PCM_FMTBIT_S24 SNDRV_PCM_FMTBIT_S24_BE |
183 | #define SNDRV_PCM_FMTBIT_U24 SNDRV_PCM_FMTBIT_U24_BE | 184 | #define SNDRV_PCM_FMTBIT_U24 SNDRV_PCM_FMTBIT_U24_BE |
184 | #define SNDRV_PCM_FMTBIT_S32 SNDRV_PCM_FMTBIT_S32_BE | 185 | #define SNDRV_PCM_FMTBIT_S32 SNDRV_PCM_FMTBIT_S32_BE |
185 | #define SNDRV_PCM_FMTBIT_U32 SNDRV_PCM_FMTBIT_U32_BE | 186 | #define SNDRV_PCM_FMTBIT_U32 SNDRV_PCM_FMTBIT_U32_BE |
186 | #define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_BE | 187 | #define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_BE |
187 | #define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_BE | 188 | #define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_BE |
188 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE | 189 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE |
189 | #endif | 190 | #endif |
190 | 191 | ||
191 | struct snd_pcm_file { | 192 | struct snd_pcm_file { |
192 | struct snd_pcm_substream *substream; | 193 | struct snd_pcm_substream *substream; |
193 | int no_compat_mmap; | 194 | int no_compat_mmap; |
194 | }; | 195 | }; |
195 | 196 | ||
196 | struct snd_pcm_hw_rule; | 197 | struct snd_pcm_hw_rule; |
197 | typedef int (*snd_pcm_hw_rule_func_t)(struct snd_pcm_hw_params *params, | 198 | typedef int (*snd_pcm_hw_rule_func_t)(struct snd_pcm_hw_params *params, |
198 | struct snd_pcm_hw_rule *rule); | 199 | struct snd_pcm_hw_rule *rule); |
199 | 200 | ||
200 | struct snd_pcm_hw_rule { | 201 | struct snd_pcm_hw_rule { |
201 | unsigned int cond; | 202 | unsigned int cond; |
202 | snd_pcm_hw_rule_func_t func; | 203 | snd_pcm_hw_rule_func_t func; |
203 | int var; | 204 | int var; |
204 | int deps[4]; | 205 | int deps[4]; |
205 | void *private; | 206 | void *private; |
206 | }; | 207 | }; |
207 | 208 | ||
208 | struct snd_pcm_hw_constraints { | 209 | struct snd_pcm_hw_constraints { |
209 | struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - | 210 | struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - |
210 | SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; | 211 | SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; |
211 | struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - | 212 | struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - |
212 | SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; | 213 | SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; |
213 | unsigned int rules_num; | 214 | unsigned int rules_num; |
214 | unsigned int rules_all; | 215 | unsigned int rules_all; |
215 | struct snd_pcm_hw_rule *rules; | 216 | struct snd_pcm_hw_rule *rules; |
216 | }; | 217 | }; |
217 | 218 | ||
218 | static inline struct snd_mask *constrs_mask(struct snd_pcm_hw_constraints *constrs, | 219 | static inline struct snd_mask *constrs_mask(struct snd_pcm_hw_constraints *constrs, |
219 | snd_pcm_hw_param_t var) | 220 | snd_pcm_hw_param_t var) |
220 | { | 221 | { |
221 | return &constrs->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; | 222 | return &constrs->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; |
222 | } | 223 | } |
223 | 224 | ||
224 | static inline struct snd_interval *constrs_interval(struct snd_pcm_hw_constraints *constrs, | 225 | static inline struct snd_interval *constrs_interval(struct snd_pcm_hw_constraints *constrs, |
225 | snd_pcm_hw_param_t var) | 226 | snd_pcm_hw_param_t var) |
226 | { | 227 | { |
227 | return &constrs->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; | 228 | return &constrs->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; |
228 | } | 229 | } |
229 | 230 | ||
230 | struct snd_ratnum { | 231 | struct snd_ratnum { |
231 | unsigned int num; | 232 | unsigned int num; |
232 | unsigned int den_min, den_max, den_step; | 233 | unsigned int den_min, den_max, den_step; |
233 | }; | 234 | }; |
234 | 235 | ||
235 | struct snd_ratden { | 236 | struct snd_ratden { |
236 | unsigned int num_min, num_max, num_step; | 237 | unsigned int num_min, num_max, num_step; |
237 | unsigned int den; | 238 | unsigned int den; |
238 | }; | 239 | }; |
239 | 240 | ||
240 | struct snd_pcm_hw_constraint_ratnums { | 241 | struct snd_pcm_hw_constraint_ratnums { |
241 | int nrats; | 242 | int nrats; |
242 | struct snd_ratnum *rats; | 243 | struct snd_ratnum *rats; |
243 | }; | 244 | }; |
244 | 245 | ||
245 | struct snd_pcm_hw_constraint_ratdens { | 246 | struct snd_pcm_hw_constraint_ratdens { |
246 | int nrats; | 247 | int nrats; |
247 | struct snd_ratden *rats; | 248 | struct snd_ratden *rats; |
248 | }; | 249 | }; |
249 | 250 | ||
250 | struct snd_pcm_hw_constraint_list { | 251 | struct snd_pcm_hw_constraint_list { |
251 | unsigned int count; | 252 | unsigned int count; |
252 | unsigned int *list; | 253 | unsigned int *list; |
253 | unsigned int mask; | 254 | unsigned int mask; |
254 | }; | 255 | }; |
255 | 256 | ||
256 | struct snd_pcm_runtime { | 257 | struct snd_pcm_runtime { |
257 | /* -- Status -- */ | 258 | /* -- Status -- */ |
258 | struct snd_pcm_substream *trigger_master; | 259 | struct snd_pcm_substream *trigger_master; |
259 | struct timespec trigger_tstamp; /* trigger timestamp */ | 260 | struct timespec trigger_tstamp; /* trigger timestamp */ |
260 | int overrange; | 261 | int overrange; |
261 | snd_pcm_uframes_t avail_max; | 262 | snd_pcm_uframes_t avail_max; |
262 | snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ | 263 | snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ |
263 | snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/ | 264 | snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/ |
264 | 265 | ||
265 | /* -- HW params -- */ | 266 | /* -- HW params -- */ |
266 | snd_pcm_access_t access; /* access mode */ | 267 | snd_pcm_access_t access; /* access mode */ |
267 | snd_pcm_format_t format; /* SNDRV_PCM_FORMAT_* */ | 268 | snd_pcm_format_t format; /* SNDRV_PCM_FORMAT_* */ |
268 | snd_pcm_subformat_t subformat; /* subformat */ | 269 | snd_pcm_subformat_t subformat; /* subformat */ |
269 | unsigned int rate; /* rate in Hz */ | 270 | unsigned int rate; /* rate in Hz */ |
270 | unsigned int channels; /* channels */ | 271 | unsigned int channels; /* channels */ |
271 | snd_pcm_uframes_t period_size; /* period size */ | 272 | snd_pcm_uframes_t period_size; /* period size */ |
272 | unsigned int periods; /* periods */ | 273 | unsigned int periods; /* periods */ |
273 | snd_pcm_uframes_t buffer_size; /* buffer size */ | 274 | snd_pcm_uframes_t buffer_size; /* buffer size */ |
274 | unsigned int tick_time; /* tick time */ | 275 | unsigned int tick_time; /* tick time */ |
275 | snd_pcm_uframes_t min_align; /* Min alignment for the format */ | 276 | snd_pcm_uframes_t min_align; /* Min alignment for the format */ |
276 | size_t byte_align; | 277 | size_t byte_align; |
277 | unsigned int frame_bits; | 278 | unsigned int frame_bits; |
278 | unsigned int sample_bits; | 279 | unsigned int sample_bits; |
279 | unsigned int info; | 280 | unsigned int info; |
280 | unsigned int rate_num; | 281 | unsigned int rate_num; |
281 | unsigned int rate_den; | 282 | unsigned int rate_den; |
282 | 283 | ||
283 | /* -- SW params -- */ | 284 | /* -- SW params -- */ |
284 | int tstamp_mode; /* mmap timestamp is updated */ | 285 | int tstamp_mode; /* mmap timestamp is updated */ |
285 | unsigned int period_step; | 286 | unsigned int period_step; |
286 | unsigned int sleep_min; /* min ticks to sleep */ | 287 | unsigned int sleep_min; /* min ticks to sleep */ |
287 | snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ | 288 | snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ |
288 | snd_pcm_uframes_t start_threshold; | 289 | snd_pcm_uframes_t start_threshold; |
289 | snd_pcm_uframes_t stop_threshold; | 290 | snd_pcm_uframes_t stop_threshold; |
290 | snd_pcm_uframes_t silence_threshold; /* Silence filling happens when | 291 | snd_pcm_uframes_t silence_threshold; /* Silence filling happens when |
291 | noise is nearest than this */ | 292 | noise is nearest than this */ |
292 | snd_pcm_uframes_t silence_size; /* Silence filling size */ | 293 | snd_pcm_uframes_t silence_size; /* Silence filling size */ |
293 | snd_pcm_uframes_t boundary; /* pointers wrap point */ | 294 | snd_pcm_uframes_t boundary; /* pointers wrap point */ |
294 | 295 | ||
295 | snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ | 296 | snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ |
296 | snd_pcm_uframes_t silence_filled; /* size filled with silence */ | 297 | snd_pcm_uframes_t silence_filled; /* size filled with silence */ |
297 | 298 | ||
298 | union snd_pcm_sync_id sync; /* hardware synchronization ID */ | 299 | union snd_pcm_sync_id sync; /* hardware synchronization ID */ |
299 | 300 | ||
300 | /* -- mmap -- */ | 301 | /* -- mmap -- */ |
301 | volatile struct snd_pcm_mmap_status *status; | 302 | volatile struct snd_pcm_mmap_status *status; |
302 | volatile struct snd_pcm_mmap_control *control; | 303 | volatile struct snd_pcm_mmap_control *control; |
303 | 304 | ||
304 | /* -- locking / scheduling -- */ | 305 | /* -- locking / scheduling -- */ |
305 | wait_queue_head_t sleep; | 306 | wait_queue_head_t sleep; |
306 | struct timer_list tick_timer; | 307 | struct timer_list tick_timer; |
307 | struct fasync_struct *fasync; | 308 | struct fasync_struct *fasync; |
308 | 309 | ||
309 | /* -- private section -- */ | 310 | /* -- private section -- */ |
310 | void *private_data; | 311 | void *private_data; |
311 | void (*private_free)(struct snd_pcm_runtime *runtime); | 312 | void (*private_free)(struct snd_pcm_runtime *runtime); |
312 | 313 | ||
313 | /* -- hardware description -- */ | 314 | /* -- hardware description -- */ |
314 | struct snd_pcm_hardware hw; | 315 | struct snd_pcm_hardware hw; |
315 | struct snd_pcm_hw_constraints hw_constraints; | 316 | struct snd_pcm_hw_constraints hw_constraints; |
316 | 317 | ||
317 | /* -- interrupt callbacks -- */ | 318 | /* -- interrupt callbacks -- */ |
318 | void (*transfer_ack_begin)(struct snd_pcm_substream *substream); | 319 | void (*transfer_ack_begin)(struct snd_pcm_substream *substream); |
319 | void (*transfer_ack_end)(struct snd_pcm_substream *substream); | 320 | void (*transfer_ack_end)(struct snd_pcm_substream *substream); |
320 | 321 | ||
321 | /* -- timer -- */ | 322 | /* -- timer -- */ |
322 | unsigned int timer_resolution; /* timer resolution */ | 323 | unsigned int timer_resolution; /* timer resolution */ |
323 | 324 | ||
324 | /* -- DMA -- */ | 325 | /* -- DMA -- */ |
325 | unsigned char *dma_area; /* DMA area */ | 326 | unsigned char *dma_area; /* DMA area */ |
326 | dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ | 327 | dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ |
327 | size_t dma_bytes; /* size of DMA area */ | 328 | size_t dma_bytes; /* size of DMA area */ |
328 | 329 | ||
329 | struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */ | 330 | struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */ |
330 | 331 | ||
331 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 332 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
332 | /* -- OSS things -- */ | 333 | /* -- OSS things -- */ |
333 | struct snd_pcm_oss_runtime oss; | 334 | struct snd_pcm_oss_runtime oss; |
334 | #endif | 335 | #endif |
335 | }; | 336 | }; |
336 | 337 | ||
337 | struct snd_pcm_group { /* keep linked substreams */ | 338 | struct snd_pcm_group { /* keep linked substreams */ |
338 | spinlock_t lock; | 339 | spinlock_t lock; |
339 | struct list_head substreams; | 340 | struct list_head substreams; |
340 | int count; | 341 | int count; |
341 | }; | 342 | }; |
342 | 343 | ||
343 | struct snd_pcm_substream { | 344 | struct snd_pcm_substream { |
344 | struct snd_pcm *pcm; | 345 | struct snd_pcm *pcm; |
345 | struct snd_pcm_str *pstr; | 346 | struct snd_pcm_str *pstr; |
346 | void *private_data; /* copied from pcm->private_data */ | 347 | void *private_data; /* copied from pcm->private_data */ |
347 | int number; | 348 | int number; |
348 | char name[32]; /* substream name */ | 349 | char name[32]; /* substream name */ |
349 | int stream; /* stream (direction) */ | 350 | int stream; /* stream (direction) */ |
350 | char latency_id[20]; /* latency identifier */ | 351 | char latency_id[20]; /* latency identifier */ |
351 | size_t buffer_bytes_max; /* limit ring buffer size */ | 352 | size_t buffer_bytes_max; /* limit ring buffer size */ |
352 | struct snd_dma_buffer dma_buffer; | 353 | struct snd_dma_buffer dma_buffer; |
353 | unsigned int dma_buf_id; | 354 | unsigned int dma_buf_id; |
354 | size_t dma_max; | 355 | size_t dma_max; |
355 | /* -- hardware operations -- */ | 356 | /* -- hardware operations -- */ |
356 | struct snd_pcm_ops *ops; | 357 | struct snd_pcm_ops *ops; |
357 | /* -- runtime information -- */ | 358 | /* -- runtime information -- */ |
358 | struct snd_pcm_runtime *runtime; | 359 | struct snd_pcm_runtime *runtime; |
359 | /* -- timer section -- */ | 360 | /* -- timer section -- */ |
360 | struct snd_timer *timer; /* timer */ | 361 | struct snd_timer *timer; /* timer */ |
361 | unsigned timer_running: 1; /* time is running */ | 362 | unsigned timer_running: 1; /* time is running */ |
362 | spinlock_t timer_lock; | 363 | spinlock_t timer_lock; |
363 | /* -- next substream -- */ | 364 | /* -- next substream -- */ |
364 | struct snd_pcm_substream *next; | 365 | struct snd_pcm_substream *next; |
365 | /* -- linked substreams -- */ | 366 | /* -- linked substreams -- */ |
366 | struct list_head link_list; /* linked list member */ | 367 | struct list_head link_list; /* linked list member */ |
367 | struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */ | 368 | struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */ |
368 | struct snd_pcm_group *group; /* pointer to current group */ | 369 | struct snd_pcm_group *group; /* pointer to current group */ |
369 | /* -- assigned files -- */ | 370 | /* -- assigned files -- */ |
370 | void *file; | 371 | void *file; |
371 | int ref_count; | 372 | int ref_count; |
372 | atomic_t mmap_count; | 373 | atomic_t mmap_count; |
373 | unsigned int f_flags; | 374 | unsigned int f_flags; |
374 | void (*pcm_release)(struct snd_pcm_substream *); | 375 | void (*pcm_release)(struct snd_pcm_substream *); |
375 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 376 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
376 | /* -- OSS things -- */ | 377 | /* -- OSS things -- */ |
377 | struct snd_pcm_oss_substream oss; | 378 | struct snd_pcm_oss_substream oss; |
378 | #endif | 379 | #endif |
379 | #ifdef CONFIG_SND_VERBOSE_PROCFS | 380 | #ifdef CONFIG_SND_VERBOSE_PROCFS |
380 | struct snd_info_entry *proc_root; | 381 | struct snd_info_entry *proc_root; |
381 | struct snd_info_entry *proc_info_entry; | 382 | struct snd_info_entry *proc_info_entry; |
382 | struct snd_info_entry *proc_hw_params_entry; | 383 | struct snd_info_entry *proc_hw_params_entry; |
383 | struct snd_info_entry *proc_sw_params_entry; | 384 | struct snd_info_entry *proc_sw_params_entry; |
384 | struct snd_info_entry *proc_status_entry; | 385 | struct snd_info_entry *proc_status_entry; |
385 | struct snd_info_entry *proc_prealloc_entry; | 386 | struct snd_info_entry *proc_prealloc_entry; |
386 | #endif | 387 | #endif |
387 | /* misc flags */ | 388 | /* misc flags */ |
388 | unsigned int hw_opened: 1; | 389 | unsigned int hw_opened: 1; |
389 | }; | 390 | }; |
390 | 391 | ||
391 | #define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) | 392 | #define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) |
392 | 393 | ||
393 | 394 | ||
394 | struct snd_pcm_str { | 395 | struct snd_pcm_str { |
395 | int stream; /* stream (direction) */ | 396 | int stream; /* stream (direction) */ |
396 | struct snd_pcm *pcm; | 397 | struct snd_pcm *pcm; |
397 | /* -- substreams -- */ | 398 | /* -- substreams -- */ |
398 | unsigned int substream_count; | 399 | unsigned int substream_count; |
399 | unsigned int substream_opened; | 400 | unsigned int substream_opened; |
400 | struct snd_pcm_substream *substream; | 401 | struct snd_pcm_substream *substream; |
401 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 402 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
402 | /* -- OSS things -- */ | 403 | /* -- OSS things -- */ |
403 | struct snd_pcm_oss_stream oss; | 404 | struct snd_pcm_oss_stream oss; |
404 | #endif | 405 | #endif |
405 | #ifdef CONFIG_SND_VERBOSE_PROCFS | 406 | #ifdef CONFIG_SND_VERBOSE_PROCFS |
406 | struct snd_info_entry *proc_root; | 407 | struct snd_info_entry *proc_root; |
407 | struct snd_info_entry *proc_info_entry; | 408 | struct snd_info_entry *proc_info_entry; |
408 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG | 409 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG |
409 | unsigned int xrun_debug; /* 0 = disabled, 1 = verbose, 2 = stacktrace */ | 410 | unsigned int xrun_debug; /* 0 = disabled, 1 = verbose, 2 = stacktrace */ |
410 | struct snd_info_entry *proc_xrun_debug_entry; | 411 | struct snd_info_entry *proc_xrun_debug_entry; |
411 | #endif | 412 | #endif |
412 | #endif | 413 | #endif |
413 | }; | 414 | }; |
414 | 415 | ||
415 | struct snd_pcm { | 416 | struct snd_pcm { |
416 | struct snd_card *card; | 417 | struct snd_card *card; |
417 | struct list_head list; | 418 | struct list_head list; |
418 | unsigned int device; /* device number */ | 419 | unsigned int device; /* device number */ |
419 | unsigned int info_flags; | 420 | unsigned int info_flags; |
420 | unsigned short dev_class; | 421 | unsigned short dev_class; |
421 | unsigned short dev_subclass; | 422 | unsigned short dev_subclass; |
422 | char id[64]; | 423 | char id[64]; |
423 | char name[80]; | 424 | char name[80]; |
424 | struct snd_pcm_str streams[2]; | 425 | struct snd_pcm_str streams[2]; |
425 | struct mutex open_mutex; | 426 | struct mutex open_mutex; |
426 | wait_queue_head_t open_wait; | 427 | wait_queue_head_t open_wait; |
427 | void *private_data; | 428 | void *private_data; |
428 | void (*private_free) (struct snd_pcm *pcm); | 429 | void (*private_free) (struct snd_pcm *pcm); |
429 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 430 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
430 | struct snd_pcm_oss oss; | 431 | struct snd_pcm_oss oss; |
431 | #endif | 432 | #endif |
432 | }; | 433 | }; |
433 | 434 | ||
434 | struct snd_pcm_notify { | 435 | struct snd_pcm_notify { |
435 | int (*n_register) (struct snd_pcm * pcm); | 436 | int (*n_register) (struct snd_pcm * pcm); |
436 | int (*n_disconnect) (struct snd_pcm * pcm); | 437 | int (*n_disconnect) (struct snd_pcm * pcm); |
437 | int (*n_unregister) (struct snd_pcm * pcm); | 438 | int (*n_unregister) (struct snd_pcm * pcm); |
438 | struct list_head list; | 439 | struct list_head list; |
439 | }; | 440 | }; |
440 | 441 | ||
441 | /* | 442 | /* |
442 | * Registering | 443 | * Registering |
443 | */ | 444 | */ |
444 | 445 | ||
445 | extern struct file_operations snd_pcm_f_ops[2]; | 446 | extern struct file_operations snd_pcm_f_ops[2]; |
446 | 447 | ||
447 | int snd_pcm_new(struct snd_card *card, char *id, int device, | 448 | int snd_pcm_new(struct snd_card *card, char *id, int device, |
448 | int playback_count, int capture_count, | 449 | int playback_count, int capture_count, |
449 | struct snd_pcm **rpcm); | 450 | struct snd_pcm **rpcm); |
450 | int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count); | 451 | int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count); |
451 | 452 | ||
452 | int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree); | 453 | int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree); |
453 | 454 | ||
454 | /* | 455 | /* |
455 | * Native I/O | 456 | * Native I/O |
456 | */ | 457 | */ |
457 | 458 | ||
458 | extern rwlock_t snd_pcm_link_rwlock; | 459 | extern rwlock_t snd_pcm_link_rwlock; |
459 | 460 | ||
460 | int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info); | 461 | int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info); |
461 | int snd_pcm_info_user(struct snd_pcm_substream *substream, | 462 | int snd_pcm_info_user(struct snd_pcm_substream *substream, |
462 | struct snd_pcm_info __user *info); | 463 | struct snd_pcm_info __user *info); |
463 | int snd_pcm_status(struct snd_pcm_substream *substream, | 464 | int snd_pcm_status(struct snd_pcm_substream *substream, |
464 | struct snd_pcm_status *status); | 465 | struct snd_pcm_status *status); |
465 | int snd_pcm_start(struct snd_pcm_substream *substream); | 466 | int snd_pcm_start(struct snd_pcm_substream *substream); |
466 | int snd_pcm_stop(struct snd_pcm_substream *substream, int status); | 467 | int snd_pcm_stop(struct snd_pcm_substream *substream, int status); |
467 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); | 468 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); |
468 | #ifdef CONFIG_PM | 469 | #ifdef CONFIG_PM |
469 | int snd_pcm_suspend(struct snd_pcm_substream *substream); | 470 | int snd_pcm_suspend(struct snd_pcm_substream *substream); |
470 | int snd_pcm_suspend_all(struct snd_pcm *pcm); | 471 | int snd_pcm_suspend_all(struct snd_pcm *pcm); |
471 | #endif | 472 | #endif |
472 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); | 473 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); |
473 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, | 474 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, |
474 | struct snd_pcm_substream **rsubstream); | 475 | struct snd_pcm_substream **rsubstream); |
475 | void snd_pcm_release_substream(struct snd_pcm_substream *substream); | 476 | void snd_pcm_release_substream(struct snd_pcm_substream *substream); |
476 | int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file, | 477 | int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file, |
477 | struct snd_pcm_substream **rsubstream); | 478 | struct snd_pcm_substream **rsubstream); |
478 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream); | 479 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream); |
479 | void snd_pcm_vma_notify_data(void *client, void *data); | 480 | void snd_pcm_vma_notify_data(void *client, void *data); |
480 | int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); | 481 | int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); |
481 | 482 | ||
482 | #if BITS_PER_LONG >= 64 | 483 | #if BITS_PER_LONG >= 64 |
483 | 484 | ||
484 | static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) | 485 | static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) |
485 | { | 486 | { |
486 | *rem = *n % div; | 487 | *rem = *n % div; |
487 | *n /= div; | 488 | *n /= div; |
488 | } | 489 | } |
489 | 490 | ||
490 | #elif defined(i386) | 491 | #elif defined(i386) |
491 | 492 | ||
492 | static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) | 493 | static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) |
493 | { | 494 | { |
494 | u_int32_t low, high; | 495 | u_int32_t low, high; |
495 | low = *n & 0xffffffff; | 496 | low = *n & 0xffffffff; |
496 | high = *n >> 32; | 497 | high = *n >> 32; |
497 | if (high) { | 498 | if (high) { |
498 | u_int32_t high1 = high % div; | 499 | u_int32_t high1 = high % div; |
499 | high /= div; | 500 | high /= div; |
500 | asm("divl %2":"=a" (low), "=d" (*rem):"rm" (div), "a" (low), "d" (high1)); | 501 | asm("divl %2":"=a" (low), "=d" (*rem):"rm" (div), "a" (low), "d" (high1)); |
501 | *n = (u_int64_t)high << 32 | low; | 502 | *n = (u_int64_t)high << 32 | low; |
502 | } else { | 503 | } else { |
503 | *n = low / div; | 504 | *n = low / div; |
504 | *rem = low % div; | 505 | *rem = low % div; |
505 | } | 506 | } |
506 | } | 507 | } |
507 | #else | 508 | #else |
508 | 509 | ||
509 | static inline void divl(u_int32_t high, u_int32_t low, | 510 | static inline void divl(u_int32_t high, u_int32_t low, |
510 | u_int32_t div, | 511 | u_int32_t div, |
511 | u_int32_t *q, u_int32_t *r) | 512 | u_int32_t *q, u_int32_t *r) |
512 | { | 513 | { |
513 | u_int64_t n = (u_int64_t)high << 32 | low; | 514 | u_int64_t n = (u_int64_t)high << 32 | low; |
514 | u_int64_t d = (u_int64_t)div << 31; | 515 | u_int64_t d = (u_int64_t)div << 31; |
515 | u_int32_t q1 = 0; | 516 | u_int32_t q1 = 0; |
516 | int c = 32; | 517 | int c = 32; |
517 | while (n > 0xffffffffU) { | 518 | while (n > 0xffffffffU) { |
518 | q1 <<= 1; | 519 | q1 <<= 1; |
519 | if (n >= d) { | 520 | if (n >= d) { |
520 | n -= d; | 521 | n -= d; |
521 | q1 |= 1; | 522 | q1 |= 1; |
522 | } | 523 | } |
523 | d >>= 1; | 524 | d >>= 1; |
524 | c--; | 525 | c--; |
525 | } | 526 | } |
526 | q1 <<= c; | 527 | q1 <<= c; |
527 | if (n) { | 528 | if (n) { |
528 | low = n; | 529 | low = n; |
529 | *q = q1 | (low / div); | 530 | *q = q1 | (low / div); |
530 | *r = low % div; | 531 | *r = low % div; |
531 | } else { | 532 | } else { |
532 | *r = 0; | 533 | *r = 0; |
533 | *q = q1; | 534 | *q = q1; |
534 | } | 535 | } |
535 | return; | 536 | return; |
536 | } | 537 | } |
537 | 538 | ||
538 | static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) | 539 | static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) |
539 | { | 540 | { |
540 | u_int32_t low, high; | 541 | u_int32_t low, high; |
541 | low = *n & 0xffffffff; | 542 | low = *n & 0xffffffff; |
542 | high = *n >> 32; | 543 | high = *n >> 32; |
543 | if (high) { | 544 | if (high) { |
544 | u_int32_t high1 = high % div; | 545 | u_int32_t high1 = high % div; |
545 | u_int32_t low1 = low; | 546 | u_int32_t low1 = low; |
546 | high /= div; | 547 | high /= div; |
547 | divl(high1, low1, div, &low, rem); | 548 | divl(high1, low1, div, &low, rem); |
548 | *n = (u_int64_t)high << 32 | low; | 549 | *n = (u_int64_t)high << 32 | low; |
549 | } else { | 550 | } else { |
550 | *n = low / div; | 551 | *n = low / div; |
551 | *rem = low % div; | 552 | *rem = low % div; |
552 | } | 553 | } |
553 | } | 554 | } |
554 | #endif | 555 | #endif |
555 | 556 | ||
556 | /* | 557 | /* |
557 | * PCM library | 558 | * PCM library |
558 | */ | 559 | */ |
559 | 560 | ||
560 | static inline int snd_pcm_stream_linked(struct snd_pcm_substream *substream) | 561 | static inline int snd_pcm_stream_linked(struct snd_pcm_substream *substream) |
561 | { | 562 | { |
562 | return substream->group != &substream->self_group; | 563 | return substream->group != &substream->self_group; |
563 | } | 564 | } |
564 | 565 | ||
565 | static inline void snd_pcm_stream_lock(struct snd_pcm_substream *substream) | 566 | static inline void snd_pcm_stream_lock(struct snd_pcm_substream *substream) |
566 | { | 567 | { |
567 | read_lock(&snd_pcm_link_rwlock); | 568 | read_lock(&snd_pcm_link_rwlock); |
568 | spin_lock(&substream->self_group.lock); | 569 | spin_lock(&substream->self_group.lock); |
569 | } | 570 | } |
570 | 571 | ||
571 | static inline void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) | 572 | static inline void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) |
572 | { | 573 | { |
573 | spin_unlock(&substream->self_group.lock); | 574 | spin_unlock(&substream->self_group.lock); |
574 | read_unlock(&snd_pcm_link_rwlock); | 575 | read_unlock(&snd_pcm_link_rwlock); |
575 | } | 576 | } |
576 | 577 | ||
577 | static inline void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) | 578 | static inline void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) |
578 | { | 579 | { |
579 | read_lock_irq(&snd_pcm_link_rwlock); | 580 | read_lock_irq(&snd_pcm_link_rwlock); |
580 | spin_lock(&substream->self_group.lock); | 581 | spin_lock(&substream->self_group.lock); |
581 | } | 582 | } |
582 | 583 | ||
583 | static inline void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) | 584 | static inline void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) |
584 | { | 585 | { |
585 | spin_unlock(&substream->self_group.lock); | 586 | spin_unlock(&substream->self_group.lock); |
586 | read_unlock_irq(&snd_pcm_link_rwlock); | 587 | read_unlock_irq(&snd_pcm_link_rwlock); |
587 | } | 588 | } |
588 | 589 | ||
589 | #define snd_pcm_stream_lock_irqsave(substream, flags) \ | 590 | #define snd_pcm_stream_lock_irqsave(substream, flags) \ |
590 | do { \ | 591 | do { \ |
591 | read_lock_irqsave(&snd_pcm_link_rwlock, (flags)); \ | 592 | read_lock_irqsave(&snd_pcm_link_rwlock, (flags)); \ |
592 | spin_lock(&substream->self_group.lock); \ | 593 | spin_lock(&substream->self_group.lock); \ |
593 | } while (0) | 594 | } while (0) |
594 | 595 | ||
595 | #define snd_pcm_stream_unlock_irqrestore(substream, flags) \ | 596 | #define snd_pcm_stream_unlock_irqrestore(substream, flags) \ |
596 | do { \ | 597 | do { \ |
597 | spin_unlock(&substream->self_group.lock); \ | 598 | spin_unlock(&substream->self_group.lock); \ |
598 | read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \ | 599 | read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \ |
599 | } while (0) | 600 | } while (0) |
600 | 601 | ||
601 | #define snd_pcm_group_for_each(pos, substream) \ | 602 | #define snd_pcm_group_for_each(pos, substream) \ |
602 | list_for_each(pos, &substream->group->substreams) | 603 | list_for_each(pos, &substream->group->substreams) |
603 | 604 | ||
604 | #define snd_pcm_group_substream_entry(pos) \ | 605 | #define snd_pcm_group_substream_entry(pos) \ |
605 | list_entry(pos, struct snd_pcm_substream, link_list) | 606 | list_entry(pos, struct snd_pcm_substream, link_list) |
606 | 607 | ||
607 | static inline int snd_pcm_running(struct snd_pcm_substream *substream) | 608 | static inline int snd_pcm_running(struct snd_pcm_substream *substream) |
608 | { | 609 | { |
609 | return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING || | 610 | return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING || |
610 | (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING && | 611 | (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING && |
611 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); | 612 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); |
612 | } | 613 | } |
613 | 614 | ||
614 | static inline ssize_t bytes_to_samples(struct snd_pcm_runtime *runtime, ssize_t size) | 615 | static inline ssize_t bytes_to_samples(struct snd_pcm_runtime *runtime, ssize_t size) |
615 | { | 616 | { |
616 | return size * 8 / runtime->sample_bits; | 617 | return size * 8 / runtime->sample_bits; |
617 | } | 618 | } |
618 | 619 | ||
619 | static inline snd_pcm_sframes_t bytes_to_frames(struct snd_pcm_runtime *runtime, ssize_t size) | 620 | static inline snd_pcm_sframes_t bytes_to_frames(struct snd_pcm_runtime *runtime, ssize_t size) |
620 | { | 621 | { |
621 | return size * 8 / runtime->frame_bits; | 622 | return size * 8 / runtime->frame_bits; |
622 | } | 623 | } |
623 | 624 | ||
624 | static inline ssize_t samples_to_bytes(struct snd_pcm_runtime *runtime, ssize_t size) | 625 | static inline ssize_t samples_to_bytes(struct snd_pcm_runtime *runtime, ssize_t size) |
625 | { | 626 | { |
626 | return size * runtime->sample_bits / 8; | 627 | return size * runtime->sample_bits / 8; |
627 | } | 628 | } |
628 | 629 | ||
629 | static inline ssize_t frames_to_bytes(struct snd_pcm_runtime *runtime, snd_pcm_sframes_t size) | 630 | static inline ssize_t frames_to_bytes(struct snd_pcm_runtime *runtime, snd_pcm_sframes_t size) |
630 | { | 631 | { |
631 | return size * runtime->frame_bits / 8; | 632 | return size * runtime->frame_bits / 8; |
632 | } | 633 | } |
633 | 634 | ||
634 | static inline int frame_aligned(struct snd_pcm_runtime *runtime, ssize_t bytes) | 635 | static inline int frame_aligned(struct snd_pcm_runtime *runtime, ssize_t bytes) |
635 | { | 636 | { |
636 | return bytes % runtime->byte_align == 0; | 637 | return bytes % runtime->byte_align == 0; |
637 | } | 638 | } |
638 | 639 | ||
639 | static inline size_t snd_pcm_lib_buffer_bytes(struct snd_pcm_substream *substream) | 640 | static inline size_t snd_pcm_lib_buffer_bytes(struct snd_pcm_substream *substream) |
640 | { | 641 | { |
641 | struct snd_pcm_runtime *runtime = substream->runtime; | 642 | struct snd_pcm_runtime *runtime = substream->runtime; |
642 | return frames_to_bytes(runtime, runtime->buffer_size); | 643 | return frames_to_bytes(runtime, runtime->buffer_size); |
643 | } | 644 | } |
644 | 645 | ||
645 | static inline size_t snd_pcm_lib_period_bytes(struct snd_pcm_substream *substream) | 646 | static inline size_t snd_pcm_lib_period_bytes(struct snd_pcm_substream *substream) |
646 | { | 647 | { |
647 | struct snd_pcm_runtime *runtime = substream->runtime; | 648 | struct snd_pcm_runtime *runtime = substream->runtime; |
648 | return frames_to_bytes(runtime, runtime->period_size); | 649 | return frames_to_bytes(runtime, runtime->period_size); |
649 | } | 650 | } |
650 | 651 | ||
651 | /* | 652 | /* |
652 | * result is: 0 ... (boundary - 1) | 653 | * result is: 0 ... (boundary - 1) |
653 | */ | 654 | */ |
654 | static inline snd_pcm_uframes_t snd_pcm_playback_avail(struct snd_pcm_runtime *runtime) | 655 | static inline snd_pcm_uframes_t snd_pcm_playback_avail(struct snd_pcm_runtime *runtime) |
655 | { | 656 | { |
656 | snd_pcm_sframes_t avail = runtime->status->hw_ptr + runtime->buffer_size - runtime->control->appl_ptr; | 657 | snd_pcm_sframes_t avail = runtime->status->hw_ptr + runtime->buffer_size - runtime->control->appl_ptr; |
657 | if (avail < 0) | 658 | if (avail < 0) |
658 | avail += runtime->boundary; | 659 | avail += runtime->boundary; |
659 | else if ((snd_pcm_uframes_t) avail >= runtime->boundary) | 660 | else if ((snd_pcm_uframes_t) avail >= runtime->boundary) |
660 | avail -= runtime->boundary; | 661 | avail -= runtime->boundary; |
661 | return avail; | 662 | return avail; |
662 | } | 663 | } |
663 | 664 | ||
664 | /* | 665 | /* |
665 | * result is: 0 ... (boundary - 1) | 666 | * result is: 0 ... (boundary - 1) |
666 | */ | 667 | */ |
667 | static inline snd_pcm_uframes_t snd_pcm_capture_avail(struct snd_pcm_runtime *runtime) | 668 | static inline snd_pcm_uframes_t snd_pcm_capture_avail(struct snd_pcm_runtime *runtime) |
668 | { | 669 | { |
669 | snd_pcm_sframes_t avail = runtime->status->hw_ptr - runtime->control->appl_ptr; | 670 | snd_pcm_sframes_t avail = runtime->status->hw_ptr - runtime->control->appl_ptr; |
670 | if (avail < 0) | 671 | if (avail < 0) |
671 | avail += runtime->boundary; | 672 | avail += runtime->boundary; |
672 | return avail; | 673 | return avail; |
673 | } | 674 | } |
674 | 675 | ||
675 | static inline snd_pcm_sframes_t snd_pcm_playback_hw_avail(struct snd_pcm_runtime *runtime) | 676 | static inline snd_pcm_sframes_t snd_pcm_playback_hw_avail(struct snd_pcm_runtime *runtime) |
676 | { | 677 | { |
677 | return runtime->buffer_size - snd_pcm_playback_avail(runtime); | 678 | return runtime->buffer_size - snd_pcm_playback_avail(runtime); |
678 | } | 679 | } |
679 | 680 | ||
680 | static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime *runtime) | 681 | static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime *runtime) |
681 | { | 682 | { |
682 | return runtime->buffer_size - snd_pcm_capture_avail(runtime); | 683 | return runtime->buffer_size - snd_pcm_capture_avail(runtime); |
683 | } | 684 | } |
684 | 685 | ||
685 | /** | 686 | /** |
686 | * snd_pcm_playback_ready - check whether the playback buffer is available | 687 | * snd_pcm_playback_ready - check whether the playback buffer is available |
687 | * @substream: the pcm substream instance | 688 | * @substream: the pcm substream instance |
688 | * | 689 | * |
689 | * Checks whether enough free space is available on the playback buffer. | 690 | * Checks whether enough free space is available on the playback buffer. |
690 | * | 691 | * |
691 | * Returns non-zero if available, or zero if not. | 692 | * Returns non-zero if available, or zero if not. |
692 | */ | 693 | */ |
693 | static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream) | 694 | static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream) |
694 | { | 695 | { |
695 | struct snd_pcm_runtime *runtime = substream->runtime; | 696 | struct snd_pcm_runtime *runtime = substream->runtime; |
696 | return snd_pcm_playback_avail(runtime) >= runtime->control->avail_min; | 697 | return snd_pcm_playback_avail(runtime) >= runtime->control->avail_min; |
697 | } | 698 | } |
698 | 699 | ||
699 | /** | 700 | /** |
700 | * snd_pcm_capture_ready - check whether the capture buffer is available | 701 | * snd_pcm_capture_ready - check whether the capture buffer is available |
701 | * @substream: the pcm substream instance | 702 | * @substream: the pcm substream instance |
702 | * | 703 | * |
703 | * Checks whether enough capture data is available on the capture buffer. | 704 | * Checks whether enough capture data is available on the capture buffer. |
704 | * | 705 | * |
705 | * Returns non-zero if available, or zero if not. | 706 | * Returns non-zero if available, or zero if not. |
706 | */ | 707 | */ |
707 | static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream) | 708 | static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream) |
708 | { | 709 | { |
709 | struct snd_pcm_runtime *runtime = substream->runtime; | 710 | struct snd_pcm_runtime *runtime = substream->runtime; |
710 | return snd_pcm_capture_avail(runtime) >= runtime->control->avail_min; | 711 | return snd_pcm_capture_avail(runtime) >= runtime->control->avail_min; |
711 | } | 712 | } |
712 | 713 | ||
713 | /** | 714 | /** |
714 | * snd_pcm_playback_data - check whether any data exists on the playback buffer | 715 | * snd_pcm_playback_data - check whether any data exists on the playback buffer |
715 | * @substream: the pcm substream instance | 716 | * @substream: the pcm substream instance |
716 | * | 717 | * |
717 | * Checks whether any data exists on the playback buffer. If stop_threshold | 718 | * Checks whether any data exists on the playback buffer. If stop_threshold |
718 | * is bigger or equal to boundary, then this function returns always non-zero. | 719 | * is bigger or equal to boundary, then this function returns always non-zero. |
719 | * | 720 | * |
720 | * Returns non-zero if exists, or zero if not. | 721 | * Returns non-zero if exists, or zero if not. |
721 | */ | 722 | */ |
722 | static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream) | 723 | static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream) |
723 | { | 724 | { |
724 | struct snd_pcm_runtime *runtime = substream->runtime; | 725 | struct snd_pcm_runtime *runtime = substream->runtime; |
725 | 726 | ||
726 | if (runtime->stop_threshold >= runtime->boundary) | 727 | if (runtime->stop_threshold >= runtime->boundary) |
727 | return 1; | 728 | return 1; |
728 | return snd_pcm_playback_avail(runtime) < runtime->buffer_size; | 729 | return snd_pcm_playback_avail(runtime) < runtime->buffer_size; |
729 | } | 730 | } |
730 | 731 | ||
731 | /** | 732 | /** |
732 | * snd_pcm_playback_empty - check whether the playback buffer is empty | 733 | * snd_pcm_playback_empty - check whether the playback buffer is empty |
733 | * @substream: the pcm substream instance | 734 | * @substream: the pcm substream instance |
734 | * | 735 | * |
735 | * Checks whether the playback buffer is empty. | 736 | * Checks whether the playback buffer is empty. |
736 | * | 737 | * |
737 | * Returns non-zero if empty, or zero if not. | 738 | * Returns non-zero if empty, or zero if not. |
738 | */ | 739 | */ |
739 | static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream) | 740 | static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream) |
740 | { | 741 | { |
741 | struct snd_pcm_runtime *runtime = substream->runtime; | 742 | struct snd_pcm_runtime *runtime = substream->runtime; |
742 | return snd_pcm_playback_avail(runtime) >= runtime->buffer_size; | 743 | return snd_pcm_playback_avail(runtime) >= runtime->buffer_size; |
743 | } | 744 | } |
744 | 745 | ||
745 | /** | 746 | /** |
746 | * snd_pcm_capture_empty - check whether the capture buffer is empty | 747 | * snd_pcm_capture_empty - check whether the capture buffer is empty |
747 | * @substream: the pcm substream instance | 748 | * @substream: the pcm substream instance |
748 | * | 749 | * |
749 | * Checks whether the capture buffer is empty. | 750 | * Checks whether the capture buffer is empty. |
750 | * | 751 | * |
751 | * Returns non-zero if empty, or zero if not. | 752 | * Returns non-zero if empty, or zero if not. |
752 | */ | 753 | */ |
753 | static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream) | 754 | static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream) |
754 | { | 755 | { |
755 | struct snd_pcm_runtime *runtime = substream->runtime; | 756 | struct snd_pcm_runtime *runtime = substream->runtime; |
756 | return snd_pcm_capture_avail(runtime) == 0; | 757 | return snd_pcm_capture_avail(runtime) == 0; |
757 | } | 758 | } |
758 | 759 | ||
759 | static inline void snd_pcm_trigger_done(struct snd_pcm_substream *substream, | 760 | static inline void snd_pcm_trigger_done(struct snd_pcm_substream *substream, |
760 | struct snd_pcm_substream *master) | 761 | struct snd_pcm_substream *master) |
761 | { | 762 | { |
762 | substream->runtime->trigger_master = master; | 763 | substream->runtime->trigger_master = master; |
763 | } | 764 | } |
764 | 765 | ||
765 | static inline int hw_is_mask(int var) | 766 | static inline int hw_is_mask(int var) |
766 | { | 767 | { |
767 | return var >= SNDRV_PCM_HW_PARAM_FIRST_MASK && | 768 | return var >= SNDRV_PCM_HW_PARAM_FIRST_MASK && |
768 | var <= SNDRV_PCM_HW_PARAM_LAST_MASK; | 769 | var <= SNDRV_PCM_HW_PARAM_LAST_MASK; |
769 | } | 770 | } |
770 | 771 | ||
771 | static inline int hw_is_interval(int var) | 772 | static inline int hw_is_interval(int var) |
772 | { | 773 | { |
773 | return var >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL && | 774 | return var >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL && |
774 | var <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; | 775 | var <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; |
775 | } | 776 | } |
776 | 777 | ||
777 | static inline struct snd_mask *hw_param_mask(struct snd_pcm_hw_params *params, | 778 | static inline struct snd_mask *hw_param_mask(struct snd_pcm_hw_params *params, |
778 | snd_pcm_hw_param_t var) | 779 | snd_pcm_hw_param_t var) |
779 | { | 780 | { |
780 | return ¶ms->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; | 781 | return ¶ms->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; |
781 | } | 782 | } |
782 | 783 | ||
783 | static inline struct snd_interval *hw_param_interval(struct snd_pcm_hw_params *params, | 784 | static inline struct snd_interval *hw_param_interval(struct snd_pcm_hw_params *params, |
784 | snd_pcm_hw_param_t var) | 785 | snd_pcm_hw_param_t var) |
785 | { | 786 | { |
786 | return ¶ms->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; | 787 | return ¶ms->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; |
787 | } | 788 | } |
788 | 789 | ||
789 | static inline const struct snd_mask *hw_param_mask_c(const struct snd_pcm_hw_params *params, | 790 | static inline const struct snd_mask *hw_param_mask_c(const struct snd_pcm_hw_params *params, |
790 | snd_pcm_hw_param_t var) | 791 | snd_pcm_hw_param_t var) |
791 | { | 792 | { |
792 | return (const struct snd_mask *)hw_param_mask((struct snd_pcm_hw_params*) params, var); | 793 | return (const struct snd_mask *)hw_param_mask((struct snd_pcm_hw_params*) params, var); |
793 | } | 794 | } |
794 | 795 | ||
795 | static inline const struct snd_interval *hw_param_interval_c(const struct snd_pcm_hw_params *params, | 796 | static inline const struct snd_interval *hw_param_interval_c(const struct snd_pcm_hw_params *params, |
796 | snd_pcm_hw_param_t var) | 797 | snd_pcm_hw_param_t var) |
797 | { | 798 | { |
798 | return (const struct snd_interval *)hw_param_interval((struct snd_pcm_hw_params*) params, var); | 799 | return (const struct snd_interval *)hw_param_interval((struct snd_pcm_hw_params*) params, var); |
799 | } | 800 | } |
800 | 801 | ||
801 | #define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)) | 802 | #define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)) |
802 | #define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)) | 803 | #define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)) |
803 | #define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT)) | 804 | #define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT)) |
804 | #define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min | 805 | #define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min |
805 | #define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min | 806 | #define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min |
806 | #define params_period_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min | 807 | #define params_period_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min |
807 | #define params_period_bytes(p) ((params_period_size(p)*snd_pcm_format_physical_width(params_format(p))*params_channels(p))/8) | 808 | #define params_period_bytes(p) ((params_period_size(p)*snd_pcm_format_physical_width(params_format(p))*params_channels(p))/8) |
808 | #define params_periods(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIODS)->min | 809 | #define params_periods(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIODS)->min |
809 | #define params_buffer_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min | 810 | #define params_buffer_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min |
810 | #define params_buffer_bytes(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min | 811 | #define params_buffer_bytes(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min |
811 | #define params_tick_time(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_TICK_TIME)->min | 812 | #define params_tick_time(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_TICK_TIME)->min |
812 | 813 | ||
813 | 814 | ||
814 | int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v); | 815 | int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v); |
815 | void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); | 816 | void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); |
816 | void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); | 817 | void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); |
817 | void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b, | 818 | void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b, |
818 | unsigned int k, struct snd_interval *c); | 819 | unsigned int k, struct snd_interval *c); |
819 | void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, | 820 | void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, |
820 | const struct snd_interval *b, struct snd_interval *c); | 821 | const struct snd_interval *b, struct snd_interval *c); |
821 | int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask); | 822 | int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask); |
822 | int snd_interval_ratnum(struct snd_interval *i, | 823 | int snd_interval_ratnum(struct snd_interval *i, |
823 | unsigned int rats_count, struct snd_ratnum *rats, | 824 | unsigned int rats_count, struct snd_ratnum *rats, |
824 | unsigned int *nump, unsigned int *denp); | 825 | unsigned int *nump, unsigned int *denp); |
825 | 826 | ||
826 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); | 827 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); |
827 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); | 828 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); |
828 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); | 829 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); |
829 | 830 | ||
830 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); | 831 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); |
831 | 832 | ||
832 | int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream); | 833 | int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream); |
833 | int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream); | 834 | int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream); |
834 | 835 | ||
835 | int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, | 836 | int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, |
836 | u_int32_t mask); | 837 | u_int32_t mask); |
837 | int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, | 838 | int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, |
838 | u_int64_t mask); | 839 | u_int64_t mask); |
839 | int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, | 840 | int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, |
840 | unsigned int min, unsigned int max); | 841 | unsigned int min, unsigned int max); |
841 | int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var); | 842 | int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var); |
842 | int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, | 843 | int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, |
843 | unsigned int cond, | 844 | unsigned int cond, |
844 | snd_pcm_hw_param_t var, | 845 | snd_pcm_hw_param_t var, |
845 | struct snd_pcm_hw_constraint_list *l); | 846 | struct snd_pcm_hw_constraint_list *l); |
846 | int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, | 847 | int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, |
847 | unsigned int cond, | 848 | unsigned int cond, |
848 | snd_pcm_hw_param_t var, | 849 | snd_pcm_hw_param_t var, |
849 | struct snd_pcm_hw_constraint_ratnums *r); | 850 | struct snd_pcm_hw_constraint_ratnums *r); |
850 | int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, | 851 | int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, |
851 | unsigned int cond, | 852 | unsigned int cond, |
852 | snd_pcm_hw_param_t var, | 853 | snd_pcm_hw_param_t var, |
853 | struct snd_pcm_hw_constraint_ratdens *r); | 854 | struct snd_pcm_hw_constraint_ratdens *r); |
854 | int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, | 855 | int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, |
855 | unsigned int cond, | 856 | unsigned int cond, |
856 | unsigned int width, | 857 | unsigned int width, |
857 | unsigned int msbits); | 858 | unsigned int msbits); |
858 | int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, | 859 | int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, |
859 | unsigned int cond, | 860 | unsigned int cond, |
860 | snd_pcm_hw_param_t var, | 861 | snd_pcm_hw_param_t var, |
861 | unsigned long step); | 862 | unsigned long step); |
862 | int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, | 863 | int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, |
863 | unsigned int cond, | 864 | unsigned int cond, |
864 | snd_pcm_hw_param_t var); | 865 | snd_pcm_hw_param_t var); |
865 | int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, | 866 | int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, |
866 | unsigned int cond, | 867 | unsigned int cond, |
867 | int var, | 868 | int var, |
868 | snd_pcm_hw_rule_func_t func, void *private, | 869 | snd_pcm_hw_rule_func_t func, void *private, |
869 | int dep, ...); | 870 | int dep, ...); |
870 | 871 | ||
871 | int snd_pcm_format_signed(snd_pcm_format_t format); | 872 | int snd_pcm_format_signed(snd_pcm_format_t format); |
872 | int snd_pcm_format_unsigned(snd_pcm_format_t format); | 873 | int snd_pcm_format_unsigned(snd_pcm_format_t format); |
873 | int snd_pcm_format_linear(snd_pcm_format_t format); | 874 | int snd_pcm_format_linear(snd_pcm_format_t format); |
874 | int snd_pcm_format_little_endian(snd_pcm_format_t format); | 875 | int snd_pcm_format_little_endian(snd_pcm_format_t format); |
875 | int snd_pcm_format_big_endian(snd_pcm_format_t format); | 876 | int snd_pcm_format_big_endian(snd_pcm_format_t format); |
876 | #if 0 /* just for DocBook */ | 877 | #if 0 /* just for DocBook */ |
877 | /** | 878 | /** |
878 | * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian | 879 | * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian |
879 | * @format: the format to check | 880 | * @format: the format to check |
880 | * | 881 | * |
881 | * Returns 1 if the given PCM format is CPU-endian, 0 if | 882 | * Returns 1 if the given PCM format is CPU-endian, 0 if |
882 | * opposite, or a negative error code if endian not specified. | 883 | * opposite, or a negative error code if endian not specified. |
883 | */ | 884 | */ |
884 | int snd_pcm_format_cpu_endian(snd_pcm_format_t format); | 885 | int snd_pcm_format_cpu_endian(snd_pcm_format_t format); |
885 | #endif /* DocBook */ | 886 | #endif /* DocBook */ |
886 | #ifdef SNDRV_LITTLE_ENDIAN | 887 | #ifdef SNDRV_LITTLE_ENDIAN |
887 | #define snd_pcm_format_cpu_endian(format) snd_pcm_format_little_endian(format) | 888 | #define snd_pcm_format_cpu_endian(format) snd_pcm_format_little_endian(format) |
888 | #else | 889 | #else |
889 | #define snd_pcm_format_cpu_endian(format) snd_pcm_format_big_endian(format) | 890 | #define snd_pcm_format_cpu_endian(format) snd_pcm_format_big_endian(format) |
890 | #endif | 891 | #endif |
891 | int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */ | 892 | int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */ |
892 | int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */ | 893 | int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */ |
893 | ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples); | 894 | ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples); |
894 | const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format); | 895 | const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format); |
895 | int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames); | 896 | int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames); |
896 | snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian); | 897 | snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian); |
897 | 898 | ||
898 | void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops); | 899 | void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops); |
899 | void snd_pcm_set_sync(struct snd_pcm_substream *substream); | 900 | void snd_pcm_set_sync(struct snd_pcm_substream *substream); |
900 | int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); | 901 | int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); |
901 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | 902 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, |
902 | unsigned int cmd, void *arg); | 903 | unsigned int cmd, void *arg); |
903 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); | 904 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); |
904 | int snd_pcm_playback_xrun_check(struct snd_pcm_substream *substream); | 905 | int snd_pcm_playback_xrun_check(struct snd_pcm_substream *substream); |
905 | int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream); | 906 | int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream); |
906 | int snd_pcm_playback_xrun_asap(struct snd_pcm_substream *substream); | 907 | int snd_pcm_playback_xrun_asap(struct snd_pcm_substream *substream); |
907 | int snd_pcm_capture_xrun_asap(struct snd_pcm_substream *substream); | 908 | int snd_pcm_capture_xrun_asap(struct snd_pcm_substream *substream); |
908 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr); | 909 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr); |
909 | void snd_pcm_tick_prepare(struct snd_pcm_substream *substream); | 910 | void snd_pcm_tick_prepare(struct snd_pcm_substream *substream); |
910 | void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks); | 911 | void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks); |
911 | void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream); | 912 | void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream); |
912 | void snd_pcm_period_elapsed(struct snd_pcm_substream *substream); | 913 | void snd_pcm_period_elapsed(struct snd_pcm_substream *substream); |
913 | snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, | 914 | snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, |
914 | const void __user *buf, | 915 | const void __user *buf, |
915 | snd_pcm_uframes_t frames); | 916 | snd_pcm_uframes_t frames); |
916 | snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, | 917 | snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, |
917 | void __user *buf, snd_pcm_uframes_t frames); | 918 | void __user *buf, snd_pcm_uframes_t frames); |
918 | snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, | 919 | snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, |
919 | void __user **bufs, snd_pcm_uframes_t frames); | 920 | void __user **bufs, snd_pcm_uframes_t frames); |
920 | snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | 921 | snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, |
921 | void __user **bufs, snd_pcm_uframes_t frames); | 922 | void __user **bufs, snd_pcm_uframes_t frames); |
922 | 923 | ||
923 | int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); | 924 | int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); |
924 | 925 | ||
925 | static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream, | 926 | static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream, |
926 | struct snd_dma_buffer *bufp) | 927 | struct snd_dma_buffer *bufp) |
927 | { | 928 | { |
928 | struct snd_pcm_runtime *runtime = substream->runtime; | 929 | struct snd_pcm_runtime *runtime = substream->runtime; |
929 | if (bufp) { | 930 | if (bufp) { |
930 | runtime->dma_buffer_p = bufp; | 931 | runtime->dma_buffer_p = bufp; |
931 | runtime->dma_area = bufp->area; | 932 | runtime->dma_area = bufp->area; |
932 | runtime->dma_addr = bufp->addr; | 933 | runtime->dma_addr = bufp->addr; |
933 | runtime->dma_bytes = bufp->bytes; | 934 | runtime->dma_bytes = bufp->bytes; |
934 | } else { | 935 | } else { |
935 | runtime->dma_buffer_p = NULL; | 936 | runtime->dma_buffer_p = NULL; |
936 | runtime->dma_area = NULL; | 937 | runtime->dma_area = NULL; |
937 | runtime->dma_addr = 0; | 938 | runtime->dma_addr = 0; |
938 | runtime->dma_bytes = 0; | 939 | runtime->dma_bytes = 0; |
939 | } | 940 | } |
940 | } | 941 | } |
941 | 942 | ||
942 | /* | 943 | /* |
943 | * Timer interface | 944 | * Timer interface |
944 | */ | 945 | */ |
945 | 946 | ||
946 | void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); | 947 | void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); |
947 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); | 948 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); |
948 | void snd_pcm_timer_done(struct snd_pcm_substream *substream); | 949 | void snd_pcm_timer_done(struct snd_pcm_substream *substream); |
949 | 950 | ||
950 | /* | 951 | /* |
951 | * Memory | 952 | * Memory |
952 | */ | 953 | */ |
953 | 954 | ||
954 | int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream); | 955 | int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream); |
955 | int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm); | 956 | int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm); |
956 | int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, | 957 | int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, |
957 | int type, struct device *data, | 958 | int type, struct device *data, |
958 | size_t size, size_t max); | 959 | size_t size, size_t max); |
959 | int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, | 960 | int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, |
960 | int type, void *data, | 961 | int type, void *data, |
961 | size_t size, size_t max); | 962 | size_t size, size_t max); |
962 | int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size); | 963 | int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size); |
963 | int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream); | 964 | int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream); |
964 | 965 | ||
965 | #define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data) | 966 | #define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data) |
966 | #define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size) | 967 | #define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size) |
967 | #define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs) | 968 | #define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs) |
968 | struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset); | 969 | struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset); |
969 | 970 | ||
970 | /* handle mmap counter - PCM mmap callback should handle this counter properly */ | 971 | /* handle mmap counter - PCM mmap callback should handle this counter properly */ |
971 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) | 972 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) |
972 | { | 973 | { |
973 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; | 974 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; |
974 | atomic_inc(&substream->mmap_count); | 975 | atomic_inc(&substream->mmap_count); |
975 | } | 976 | } |
976 | 977 | ||
977 | static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) | 978 | static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) |
978 | { | 979 | { |
979 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; | 980 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; |
980 | atomic_dec(&substream->mmap_count); | 981 | atomic_dec(&substream->mmap_count); |
981 | } | 982 | } |
982 | 983 | ||
983 | /* mmap for io-memory area */ | 984 | /* mmap for io-memory area */ |
984 | #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA) | 985 | #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA) |
985 | #define SNDRV_PCM_INFO_MMAP_IOMEM SNDRV_PCM_INFO_MMAP | 986 | #define SNDRV_PCM_INFO_MMAP_IOMEM SNDRV_PCM_INFO_MMAP |
986 | int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area); | 987 | int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area); |
987 | #else | 988 | #else |
988 | #define SNDRV_PCM_INFO_MMAP_IOMEM 0 | 989 | #define SNDRV_PCM_INFO_MMAP_IOMEM 0 |
989 | #define snd_pcm_lib_mmap_iomem NULL | 990 | #define snd_pcm_lib_mmap_iomem NULL |
990 | #endif | 991 | #endif |
991 | 992 | ||
992 | static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) | 993 | static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) |
993 | { | 994 | { |
994 | *max = dma < 4 ? 64 * 1024 : 128 * 1024; | 995 | *max = dma < 4 ? 64 * 1024 : 128 * 1024; |
995 | } | 996 | } |
996 | 997 | ||
997 | /* | 998 | /* |
998 | * Misc | 999 | * Misc |
999 | */ | 1000 | */ |
1000 | 1001 | ||
1001 | #define SNDRV_PCM_DEFAULT_CON_SPDIF (IEC958_AES0_CON_EMPHASIS_NONE|\ | 1002 | #define SNDRV_PCM_DEFAULT_CON_SPDIF (IEC958_AES0_CON_EMPHASIS_NONE|\ |
1002 | (IEC958_AES1_CON_ORIGINAL<<8)|\ | 1003 | (IEC958_AES1_CON_ORIGINAL<<8)|\ |
1003 | (IEC958_AES1_CON_PCM_CODER<<8)|\ | 1004 | (IEC958_AES1_CON_PCM_CODER<<8)|\ |
1004 | (IEC958_AES3_CON_FS_48000<<24)) | 1005 | (IEC958_AES3_CON_FS_48000<<24)) |
1005 | 1006 | ||
1006 | #endif /* __SOUND_PCM_H */ | 1007 | #endif /* __SOUND_PCM_H */ |
1007 | 1008 |
sound/oss/cs46xx.c
1 | /* | 1 | /* |
2 | * Crystal SoundFusion CS46xx driver | 2 | * Crystal SoundFusion CS46xx driver |
3 | * | 3 | * |
4 | * Copyright 1998-2001 Cirrus Logic Corporation <pcaudio@crystal.cirrus.com> | 4 | * Copyright 1998-2001 Cirrus Logic Corporation <pcaudio@crystal.cirrus.com> |
5 | * <twoller@crystal.cirrus.com> | 5 | * <twoller@crystal.cirrus.com> |
6 | * Copyright 1999-2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright 1999-2000 Jaroslav Kysela <perex@suse.cz> |
7 | * Copyright 2000 Alan Cox <alan@redhat.com> | 7 | * Copyright 2000 Alan Cox <alan@redhat.com> |
8 | * | 8 | * |
9 | * The core of this code is taken from the ALSA project driver by | 9 | * The core of this code is taken from the ALSA project driver by |
10 | * Jaroslav. Please send Jaroslav the credit for the driver and | 10 | * Jaroslav. Please send Jaroslav the credit for the driver and |
11 | * report bugs in this port to <alan@redhat.com> | 11 | * report bugs in this port to <alan@redhat.com> |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
15 | * the Free Software Foundation; either version 2 of the License, or | 15 | * the Free Software Foundation; either version 2 of the License, or |
16 | * (at your option) any later version. | 16 | * (at your option) any later version. |
17 | * | 17 | * |
18 | * This program is distributed in the hope that it will be useful, | 18 | * This program is distributed in the hope that it will be useful, |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
22 | * | 22 | * |
23 | * You should have received a copy of the GNU General Public License | 23 | * You should have received a copy of the GNU General Public License |
24 | * along with this program; if not, write to the Free Software | 24 | * along with this program; if not, write to the Free Software |
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | * Current maintainers: | 26 | * Current maintainers: |
27 | * Cirrus Logic Corporation, Thomas Woller (tw) | 27 | * Cirrus Logic Corporation, Thomas Woller (tw) |
28 | * <twoller@crystal.cirrus.com> | 28 | * <twoller@crystal.cirrus.com> |
29 | * Nils Faerber (nf) | 29 | * Nils Faerber (nf) |
30 | * <nils@kernelconcepts.de> | 30 | * <nils@kernelconcepts.de> |
31 | * Thanks to David Pollard for testing. | 31 | * Thanks to David Pollard for testing. |
32 | * | 32 | * |
33 | * Changes: | 33 | * Changes: |
34 | * 20000909-nf Changed cs_read, cs_write and drain_dac | 34 | * 20000909-nf Changed cs_read, cs_write and drain_dac |
35 | * 20001025-tw Separate Playback/Capture structs and buffers. | 35 | * 20001025-tw Separate Playback/Capture structs and buffers. |
36 | * Added Scatter/Gather support for Playback. | 36 | * Added Scatter/Gather support for Playback. |
37 | * Added Capture. | 37 | * Added Capture. |
38 | * 20001027-nf Port to kernel 2.4.0-test9, some clean-ups | 38 | * 20001027-nf Port to kernel 2.4.0-test9, some clean-ups |
39 | * Start of powermanagement support (CS46XX_PM). | 39 | * Start of powermanagement support (CS46XX_PM). |
40 | * 20001128-tw Add module parm for default buffer order. | 40 | * 20001128-tw Add module parm for default buffer order. |
41 | * added DMA_GFP flag to kmalloc dma buffer allocs. | 41 | * added DMA_GFP flag to kmalloc dma buffer allocs. |
42 | * backfill silence to eliminate stuttering on | 42 | * backfill silence to eliminate stuttering on |
43 | * underruns. | 43 | * underruns. |
44 | * 20001201-tw add resyncing of swptr on underruns. | 44 | * 20001201-tw add resyncing of swptr on underruns. |
45 | * 20001205-tw-nf fixed GETOSPACE ioctl() after open() | 45 | * 20001205-tw-nf fixed GETOSPACE ioctl() after open() |
46 | * 20010113-tw patch from Hans Grobler general cleanup. | 46 | * 20010113-tw patch from Hans Grobler general cleanup. |
47 | * 20010117-tw 2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0 | 47 | * 20010117-tw 2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0 |
48 | * 20010118-tw basic PM support for 2.2.16+ and 2.4.0/2.4.2. | 48 | * 20010118-tw basic PM support for 2.2.16+ and 2.4.0/2.4.2. |
49 | * 20010228-dh patch from David Huggins - cs_update_ptr recursion. | 49 | * 20010228-dh patch from David Huggins - cs_update_ptr recursion. |
50 | * 20010409-tw add hercules game theatre XP amp code. | 50 | * 20010409-tw add hercules game theatre XP amp code. |
51 | * 20010420-tw cleanup powerdown/up code. | 51 | * 20010420-tw cleanup powerdown/up code. |
52 | * 20010521-tw eliminate pops, and fixes for powerdown. | 52 | * 20010521-tw eliminate pops, and fixes for powerdown. |
53 | * 20010525-tw added fixes for thinkpads with powerdown logic. | 53 | * 20010525-tw added fixes for thinkpads with powerdown logic. |
54 | * 20010723-sh patch from Horms (Simon Horman) - | 54 | * 20010723-sh patch from Horms (Simon Horman) - |
55 | * SOUND_PCM_READ_BITS returns bits as set in driver | 55 | * SOUND_PCM_READ_BITS returns bits as set in driver |
56 | * rather than a logical or of the possible values. | 56 | * rather than a logical or of the possible values. |
57 | * Various ioctls handle the case where the device | 57 | * Various ioctls handle the case where the device |
58 | * is open for reading or writing but not both better. | 58 | * is open for reading or writing but not both better. |
59 | * | 59 | * |
60 | * Status: | 60 | * Status: |
61 | * Playback/Capture supported from 8k-48k. | 61 | * Playback/Capture supported from 8k-48k. |
62 | * 16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported. | 62 | * 16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported. |
63 | * | 63 | * |
64 | * APM/PM - 2.2.x APM is enabled and functioning fine. APM can also | 64 | * APM/PM - 2.2.x APM is enabled and functioning fine. APM can also |
65 | * be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro | 65 | * be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro |
66 | * definition. | 66 | * definition. |
67 | * | 67 | * |
68 | * Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp, | 68 | * Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp, |
69 | * so, use the drain/polarity to enable. | 69 | * so, use the drain/polarity to enable. |
70 | * hercules_egpio_disable set to 1, will force a 0 to EGPIODR. | 70 | * hercules_egpio_disable set to 1, will force a 0 to EGPIODR. |
71 | * | 71 | * |
72 | * VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control | 72 | * VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control |
73 | * the external amplifier for the "back" speakers, since we do not | 73 | * the external amplifier for the "back" speakers, since we do not |
74 | * support the secondary codec then this external amp is also not | 74 | * support the secondary codec then this external amp is also not |
75 | * turned on. | 75 | * turned on. |
76 | */ | 76 | */ |
77 | 77 | ||
78 | #include <linux/interrupt.h> | 78 | #include <linux/interrupt.h> |
79 | #include <linux/list.h> | 79 | #include <linux/list.h> |
80 | #include <linux/module.h> | 80 | #include <linux/module.h> |
81 | #include <linux/string.h> | 81 | #include <linux/string.h> |
82 | #include <linux/ioport.h> | 82 | #include <linux/ioport.h> |
83 | #include <linux/sched.h> | 83 | #include <linux/sched.h> |
84 | #include <linux/delay.h> | 84 | #include <linux/delay.h> |
85 | #include <linux/sound.h> | 85 | #include <linux/sound.h> |
86 | #include <linux/slab.h> | 86 | #include <linux/slab.h> |
87 | #include <linux/soundcard.h> | 87 | #include <linux/soundcard.h> |
88 | #include <linux/pci.h> | 88 | #include <linux/pci.h> |
89 | #include <linux/bitops.h> | 89 | #include <linux/bitops.h> |
90 | #include <linux/init.h> | 90 | #include <linux/init.h> |
91 | #include <linux/poll.h> | 91 | #include <linux/poll.h> |
92 | #include <linux/ac97_codec.h> | 92 | #include <linux/ac97_codec.h> |
93 | #include <linux/mutex.h> | 93 | #include <linux/mutex.h> |
94 | #include <linux/mm.h> | ||
94 | 95 | ||
95 | #include <asm/io.h> | 96 | #include <asm/io.h> |
96 | #include <asm/dma.h> | 97 | #include <asm/dma.h> |
97 | #include <asm/uaccess.h> | 98 | #include <asm/uaccess.h> |
98 | 99 | ||
99 | #include "cs46xxpm.h" | 100 | #include "cs46xxpm.h" |
100 | #include "cs46xx_wrapper-24.h" | 101 | #include "cs46xx_wrapper-24.h" |
101 | #include "cs461x.h" | 102 | #include "cs461x.h" |
102 | 103 | ||
103 | /* MIDI buffer sizes */ | 104 | /* MIDI buffer sizes */ |
104 | #define CS_MIDIINBUF 500 | 105 | #define CS_MIDIINBUF 500 |
105 | #define CS_MIDIOUTBUF 500 | 106 | #define CS_MIDIOUTBUF 500 |
106 | 107 | ||
107 | #define ADC_RUNNING 1 | 108 | #define ADC_RUNNING 1 |
108 | #define DAC_RUNNING 2 | 109 | #define DAC_RUNNING 2 |
109 | 110 | ||
110 | #define CS_FMT_16BIT 1 /* These are fixed in fact */ | 111 | #define CS_FMT_16BIT 1 /* These are fixed in fact */ |
111 | #define CS_FMT_STEREO 2 | 112 | #define CS_FMT_STEREO 2 |
112 | #define CS_FMT_MASK 3 | 113 | #define CS_FMT_MASK 3 |
113 | 114 | ||
114 | #define CS_TYPE_ADC 1 | 115 | #define CS_TYPE_ADC 1 |
115 | #define CS_TYPE_DAC 2 | 116 | #define CS_TYPE_DAC 2 |
116 | 117 | ||
117 | #define CS_TRUE 1 | 118 | #define CS_TRUE 1 |
118 | #define CS_FALSE 0 | 119 | #define CS_FALSE 0 |
119 | 120 | ||
120 | #define CS_INC_USE_COUNT(m) (atomic_inc(m)) | 121 | #define CS_INC_USE_COUNT(m) (atomic_inc(m)) |
121 | #define CS_DEC_USE_COUNT(m) (atomic_dec(m)) | 122 | #define CS_DEC_USE_COUNT(m) (atomic_dec(m)) |
122 | #define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m)) | 123 | #define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m)) |
123 | #define CS_IN_USE(m) (atomic_read(m) != 0) | 124 | #define CS_IN_USE(m) (atomic_read(m) != 0) |
124 | 125 | ||
125 | #define CS_DBGBREAKPOINT {__asm__("INT $3");} | 126 | #define CS_DBGBREAKPOINT {__asm__("INT $3");} |
126 | /* | 127 | /* |
127 | * CS461x definitions | 128 | * CS461x definitions |
128 | */ | 129 | */ |
129 | 130 | ||
130 | #define CS461X_BA0_SIZE 0x2000 | 131 | #define CS461X_BA0_SIZE 0x2000 |
131 | #define CS461X_BA1_DATA0_SIZE 0x3000 | 132 | #define CS461X_BA1_DATA0_SIZE 0x3000 |
132 | #define CS461X_BA1_DATA1_SIZE 0x3800 | 133 | #define CS461X_BA1_DATA1_SIZE 0x3800 |
133 | #define CS461X_BA1_PRG_SIZE 0x7000 | 134 | #define CS461X_BA1_PRG_SIZE 0x7000 |
134 | #define CS461X_BA1_REG_SIZE 0x0100 | 135 | #define CS461X_BA1_REG_SIZE 0x0100 |
135 | 136 | ||
136 | #define GOF_PER_SEC 200 | 137 | #define GOF_PER_SEC 200 |
137 | 138 | ||
138 | #define CSDEBUG_INTERFACE 1 | 139 | #define CSDEBUG_INTERFACE 1 |
139 | #define CSDEBUG 1 | 140 | #define CSDEBUG 1 |
140 | /* | 141 | /* |
141 | * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG | 142 | * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG |
142 | * | 143 | * |
143 | * | 144 | * |
144 | * CSDEBUG is usual mode is set to 1, then use the | 145 | * CSDEBUG is usual mode is set to 1, then use the |
145 | * cs_debuglevel and cs_debugmask to turn on or off debugging. | 146 | * cs_debuglevel and cs_debugmask to turn on or off debugging. |
146 | * Debug level of 1 has been defined to be kernel errors and info | 147 | * Debug level of 1 has been defined to be kernel errors and info |
147 | * that should be printed on any released driver. | 148 | * that should be printed on any released driver. |
148 | */ | 149 | */ |
149 | #if CSDEBUG | 150 | #if CSDEBUG |
150 | #define CS_DBGOUT(mask,level,x) if ((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} | 151 | #define CS_DBGOUT(mask,level,x) if ((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} |
151 | #else | 152 | #else |
152 | #define CS_DBGOUT(mask,level,x) | 153 | #define CS_DBGOUT(mask,level,x) |
153 | #endif | 154 | #endif |
154 | /* | 155 | /* |
155 | * cs_debugmask areas | 156 | * cs_debugmask areas |
156 | */ | 157 | */ |
157 | #define CS_INIT 0x00000001 /* initialization and probe functions */ | 158 | #define CS_INIT 0x00000001 /* initialization and probe functions */ |
158 | #define CS_ERROR 0x00000002 /* tmp debugging bit placeholder */ | 159 | #define CS_ERROR 0x00000002 /* tmp debugging bit placeholder */ |
159 | #define CS_INTERRUPT 0x00000004 /* interrupt handler (separate from all other) */ | 160 | #define CS_INTERRUPT 0x00000004 /* interrupt handler (separate from all other) */ |
160 | #define CS_FUNCTION 0x00000008 /* enter/leave functions */ | 161 | #define CS_FUNCTION 0x00000008 /* enter/leave functions */ |
161 | #define CS_WAVE_WRITE 0x00000010 /* write information for wave */ | 162 | #define CS_WAVE_WRITE 0x00000010 /* write information for wave */ |
162 | #define CS_WAVE_READ 0x00000020 /* read information for wave */ | 163 | #define CS_WAVE_READ 0x00000020 /* read information for wave */ |
163 | #define CS_MIDI_WRITE 0x00000040 /* write information for midi */ | 164 | #define CS_MIDI_WRITE 0x00000040 /* write information for midi */ |
164 | #define CS_MIDI_READ 0x00000080 /* read information for midi */ | 165 | #define CS_MIDI_READ 0x00000080 /* read information for midi */ |
165 | #define CS_MPU401_WRITE 0x00000100 /* write information for mpu401 */ | 166 | #define CS_MPU401_WRITE 0x00000100 /* write information for mpu401 */ |
166 | #define CS_MPU401_READ 0x00000200 /* read information for mpu401 */ | 167 | #define CS_MPU401_READ 0x00000200 /* read information for mpu401 */ |
167 | #define CS_OPEN 0x00000400 /* all open functions in the driver */ | 168 | #define CS_OPEN 0x00000400 /* all open functions in the driver */ |
168 | #define CS_RELEASE 0x00000800 /* all release functions in the driver */ | 169 | #define CS_RELEASE 0x00000800 /* all release functions in the driver */ |
169 | #define CS_PARMS 0x00001000 /* functional and operational parameters */ | 170 | #define CS_PARMS 0x00001000 /* functional and operational parameters */ |
170 | #define CS_IOCTL 0x00002000 /* ioctl (non-mixer) */ | 171 | #define CS_IOCTL 0x00002000 /* ioctl (non-mixer) */ |
171 | #define CS_PM 0x00004000 /* PM */ | 172 | #define CS_PM 0x00004000 /* PM */ |
172 | #define CS_TMP 0x10000000 /* tmp debug mask bit */ | 173 | #define CS_TMP 0x10000000 /* tmp debug mask bit */ |
173 | 174 | ||
174 | #define CS_IOCTL_CMD_SUSPEND 0x1 // suspend | 175 | #define CS_IOCTL_CMD_SUSPEND 0x1 // suspend |
175 | #define CS_IOCTL_CMD_RESUME 0x2 // resume | 176 | #define CS_IOCTL_CMD_RESUME 0x2 // resume |
176 | 177 | ||
177 | #if CSDEBUG | 178 | #if CSDEBUG |
178 | static unsigned long cs_debuglevel = 1; /* levels range from 1-9 */ | 179 | static unsigned long cs_debuglevel = 1; /* levels range from 1-9 */ |
179 | module_param(cs_debuglevel, ulong, 0644); | 180 | module_param(cs_debuglevel, ulong, 0644); |
180 | static unsigned long cs_debugmask = CS_INIT | CS_ERROR; /* use CS_DBGOUT with various mask values */ | 181 | static unsigned long cs_debugmask = CS_INIT | CS_ERROR; /* use CS_DBGOUT with various mask values */ |
181 | module_param(cs_debugmask, ulong, 0644); | 182 | module_param(cs_debugmask, ulong, 0644); |
182 | #endif | 183 | #endif |
183 | static unsigned long hercules_egpio_disable; /* if non-zero set all EGPIO to 0 */ | 184 | static unsigned long hercules_egpio_disable; /* if non-zero set all EGPIO to 0 */ |
184 | module_param(hercules_egpio_disable, ulong, 0); | 185 | module_param(hercules_egpio_disable, ulong, 0); |
185 | static unsigned long initdelay = 700; /* PM delay in millisecs */ | 186 | static unsigned long initdelay = 700; /* PM delay in millisecs */ |
186 | module_param(initdelay, ulong, 0); | 187 | module_param(initdelay, ulong, 0); |
187 | static unsigned long powerdown = -1; /* turn on/off powerdown processing in driver */ | 188 | static unsigned long powerdown = -1; /* turn on/off powerdown processing in driver */ |
188 | module_param(powerdown, ulong, 0); | 189 | module_param(powerdown, ulong, 0); |
189 | #define DMABUF_DEFAULTORDER 3 | 190 | #define DMABUF_DEFAULTORDER 3 |
190 | static unsigned long defaultorder = DMABUF_DEFAULTORDER; | 191 | static unsigned long defaultorder = DMABUF_DEFAULTORDER; |
191 | module_param(defaultorder, ulong, 0); | 192 | module_param(defaultorder, ulong, 0); |
192 | 193 | ||
193 | static int external_amp; | 194 | static int external_amp; |
194 | module_param(external_amp, bool, 0); | 195 | module_param(external_amp, bool, 0); |
195 | static int thinkpad; | 196 | static int thinkpad; |
196 | module_param(thinkpad, bool, 0); | 197 | module_param(thinkpad, bool, 0); |
197 | 198 | ||
198 | /* | 199 | /* |
199 | * set the powerdown module parm to 0 to disable all | 200 | * set the powerdown module parm to 0 to disable all |
200 | * powerdown. also set thinkpad to 1 to disable powerdown, | 201 | * powerdown. also set thinkpad to 1 to disable powerdown, |
201 | * but also to enable the clkrun functionality. | 202 | * but also to enable the clkrun functionality. |
202 | */ | 203 | */ |
203 | static unsigned cs_powerdown = 1; | 204 | static unsigned cs_powerdown = 1; |
204 | static unsigned cs_laptop_wait = 1; | 205 | static unsigned cs_laptop_wait = 1; |
205 | 206 | ||
206 | /* An instance of the 4610 channel */ | 207 | /* An instance of the 4610 channel */ |
207 | struct cs_channel | 208 | struct cs_channel |
208 | { | 209 | { |
209 | int used; | 210 | int used; |
210 | int num; | 211 | int num; |
211 | void *state; | 212 | void *state; |
212 | }; | 213 | }; |
213 | 214 | ||
214 | #define CS46XX_MAJOR_VERSION "1" | 215 | #define CS46XX_MAJOR_VERSION "1" |
215 | #define CS46XX_MINOR_VERSION "28" | 216 | #define CS46XX_MINOR_VERSION "28" |
216 | 217 | ||
217 | #ifdef __ia64__ | 218 | #ifdef __ia64__ |
218 | #define CS46XX_ARCH "64" //architecture key | 219 | #define CS46XX_ARCH "64" //architecture key |
219 | #else | 220 | #else |
220 | #define CS46XX_ARCH "32" //architecture key | 221 | #define CS46XX_ARCH "32" //architecture key |
221 | #endif | 222 | #endif |
222 | 223 | ||
223 | static struct list_head cs46xx_devs = { &cs46xx_devs, &cs46xx_devs }; | 224 | static struct list_head cs46xx_devs = { &cs46xx_devs, &cs46xx_devs }; |
224 | 225 | ||
225 | /* magic numbers to protect our data structures */ | 226 | /* magic numbers to protect our data structures */ |
226 | #define CS_CARD_MAGIC 0x43525553 /* "CRUS" */ | 227 | #define CS_CARD_MAGIC 0x43525553 /* "CRUS" */ |
227 | #define CS_STATE_MAGIC 0x4c4f4749 /* "LOGI" */ | 228 | #define CS_STATE_MAGIC 0x4c4f4749 /* "LOGI" */ |
228 | #define NR_HW_CH 3 | 229 | #define NR_HW_CH 3 |
229 | 230 | ||
230 | /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ | 231 | /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ |
231 | #define NR_AC97 2 | 232 | #define NR_AC97 2 |
232 | 233 | ||
233 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; | 234 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; |
234 | static const unsigned sample_shift[] = { 0, 1, 1, 2 }; | 235 | static const unsigned sample_shift[] = { 0, 1, 1, 2 }; |
235 | 236 | ||
236 | /* "software" or virtual channel, an instance of opened /dev/dsp */ | 237 | /* "software" or virtual channel, an instance of opened /dev/dsp */ |
237 | struct cs_state { | 238 | struct cs_state { |
238 | unsigned int magic; | 239 | unsigned int magic; |
239 | struct cs_card *card; /* Card info */ | 240 | struct cs_card *card; /* Card info */ |
240 | 241 | ||
241 | /* single open lock mechanism, only used for recording */ | 242 | /* single open lock mechanism, only used for recording */ |
242 | struct mutex open_mutex; | 243 | struct mutex open_mutex; |
243 | wait_queue_head_t open_wait; | 244 | wait_queue_head_t open_wait; |
244 | 245 | ||
245 | /* file mode */ | 246 | /* file mode */ |
246 | mode_t open_mode; | 247 | mode_t open_mode; |
247 | 248 | ||
248 | /* virtual channel number */ | 249 | /* virtual channel number */ |
249 | int virt; | 250 | int virt; |
250 | 251 | ||
251 | struct dmabuf { | 252 | struct dmabuf { |
252 | /* wave sample stuff */ | 253 | /* wave sample stuff */ |
253 | unsigned int rate; | 254 | unsigned int rate; |
254 | unsigned char fmt, enable; | 255 | unsigned char fmt, enable; |
255 | 256 | ||
256 | /* hardware channel */ | 257 | /* hardware channel */ |
257 | struct cs_channel *channel; | 258 | struct cs_channel *channel; |
258 | int pringbuf; /* Software ring slot */ | 259 | int pringbuf; /* Software ring slot */ |
259 | void *pbuf; /* 4K hardware DMA buffer */ | 260 | void *pbuf; /* 4K hardware DMA buffer */ |
260 | 261 | ||
261 | /* OSS buffer management stuff */ | 262 | /* OSS buffer management stuff */ |
262 | void *rawbuf; | 263 | void *rawbuf; |
263 | dma_addr_t dma_handle; | 264 | dma_addr_t dma_handle; |
264 | unsigned buforder; | 265 | unsigned buforder; |
265 | unsigned numfrag; | 266 | unsigned numfrag; |
266 | unsigned fragshift; | 267 | unsigned fragshift; |
267 | unsigned divisor; | 268 | unsigned divisor; |
268 | unsigned type; | 269 | unsigned type; |
269 | void *tmpbuff; /* tmp buffer for sample conversions */ | 270 | void *tmpbuff; /* tmp buffer for sample conversions */ |
270 | dma_addr_t dmaaddr; | 271 | dma_addr_t dmaaddr; |
271 | dma_addr_t dmaaddr_tmpbuff; | 272 | dma_addr_t dmaaddr_tmpbuff; |
272 | unsigned buforder_tmpbuff; /* Log base 2 of size in bytes.. */ | 273 | unsigned buforder_tmpbuff; /* Log base 2 of size in bytes.. */ |
273 | 274 | ||
274 | /* our buffer acts like a circular ring */ | 275 | /* our buffer acts like a circular ring */ |
275 | unsigned hwptr; /* where dma last started, updated by update_ptr */ | 276 | unsigned hwptr; /* where dma last started, updated by update_ptr */ |
276 | unsigned swptr; /* where driver last clear/filled, updated by read/write */ | 277 | unsigned swptr; /* where driver last clear/filled, updated by read/write */ |
277 | int count; /* bytes to be comsumed or been generated by dma machine */ | 278 | int count; /* bytes to be comsumed or been generated by dma machine */ |
278 | unsigned total_bytes; /* total bytes dmaed by hardware */ | 279 | unsigned total_bytes; /* total bytes dmaed by hardware */ |
279 | unsigned blocks; /* total blocks */ | 280 | unsigned blocks; /* total blocks */ |
280 | 281 | ||
281 | unsigned error; /* number of over/underruns */ | 282 | unsigned error; /* number of over/underruns */ |
282 | unsigned underrun; /* underrun pending before next write has occurred */ | 283 | unsigned underrun; /* underrun pending before next write has occurred */ |
283 | wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */ | 284 | wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */ |
284 | 285 | ||
285 | /* redundant, but makes calculations easier */ | 286 | /* redundant, but makes calculations easier */ |
286 | unsigned fragsize; | 287 | unsigned fragsize; |
287 | unsigned dmasize; | 288 | unsigned dmasize; |
288 | unsigned fragsamples; | 289 | unsigned fragsamples; |
289 | 290 | ||
290 | /* OSS stuff */ | 291 | /* OSS stuff */ |
291 | unsigned mapped:1; | 292 | unsigned mapped:1; |
292 | unsigned ready:1; | 293 | unsigned ready:1; |
293 | unsigned endcleared:1; | 294 | unsigned endcleared:1; |
294 | unsigned SGok:1; | 295 | unsigned SGok:1; |
295 | unsigned update_flag; | 296 | unsigned update_flag; |
296 | unsigned ossfragshift; | 297 | unsigned ossfragshift; |
297 | int ossmaxfrags; | 298 | int ossmaxfrags; |
298 | unsigned subdivision; | 299 | unsigned subdivision; |
299 | } dmabuf; | 300 | } dmabuf; |
300 | /* Guard against mmap/write/read races */ | 301 | /* Guard against mmap/write/read races */ |
301 | struct mutex sem; | 302 | struct mutex sem; |
302 | }; | 303 | }; |
303 | 304 | ||
304 | struct cs_card { | 305 | struct cs_card { |
305 | struct cs_channel channel[2]; | 306 | struct cs_channel channel[2]; |
306 | unsigned int magic; | 307 | unsigned int magic; |
307 | 308 | ||
308 | /* We keep cs461x cards in a linked list */ | 309 | /* We keep cs461x cards in a linked list */ |
309 | struct cs_card *next; | 310 | struct cs_card *next; |
310 | 311 | ||
311 | /* The cs461x has a certain amount of cross channel interaction | 312 | /* The cs461x has a certain amount of cross channel interaction |
312 | so we use a single per card lock */ | 313 | so we use a single per card lock */ |
313 | spinlock_t lock; | 314 | spinlock_t lock; |
314 | 315 | ||
315 | /* Keep AC97 sane */ | 316 | /* Keep AC97 sane */ |
316 | spinlock_t ac97_lock; | 317 | spinlock_t ac97_lock; |
317 | 318 | ||
318 | /* mixer use count */ | 319 | /* mixer use count */ |
319 | atomic_t mixer_use_cnt; | 320 | atomic_t mixer_use_cnt; |
320 | 321 | ||
321 | /* PCI device stuff */ | 322 | /* PCI device stuff */ |
322 | struct pci_dev *pci_dev; | 323 | struct pci_dev *pci_dev; |
323 | struct list_head list; | 324 | struct list_head list; |
324 | 325 | ||
325 | unsigned int pctl, cctl; /* Hardware DMA flag sets */ | 326 | unsigned int pctl, cctl; /* Hardware DMA flag sets */ |
326 | 327 | ||
327 | /* soundcore stuff */ | 328 | /* soundcore stuff */ |
328 | int dev_audio; | 329 | int dev_audio; |
329 | int dev_midi; | 330 | int dev_midi; |
330 | 331 | ||
331 | /* structures for abstraction of hardware facilities, codecs, banks and channels*/ | 332 | /* structures for abstraction of hardware facilities, codecs, banks and channels*/ |
332 | struct ac97_codec *ac97_codec[NR_AC97]; | 333 | struct ac97_codec *ac97_codec[NR_AC97]; |
333 | struct cs_state *states[2]; | 334 | struct cs_state *states[2]; |
334 | 335 | ||
335 | u16 ac97_features; | 336 | u16 ac97_features; |
336 | 337 | ||
337 | int amplifier; /* Amplifier control */ | 338 | int amplifier; /* Amplifier control */ |
338 | void (*amplifier_ctrl)(struct cs_card *, int); | 339 | void (*amplifier_ctrl)(struct cs_card *, int); |
339 | void (*amp_init)(struct cs_card *); | 340 | void (*amp_init)(struct cs_card *); |
340 | 341 | ||
341 | int active; /* Active clocking */ | 342 | int active; /* Active clocking */ |
342 | void (*active_ctrl)(struct cs_card *, int); | 343 | void (*active_ctrl)(struct cs_card *, int); |
343 | 344 | ||
344 | /* hardware resources */ | 345 | /* hardware resources */ |
345 | unsigned long ba0_addr; | 346 | unsigned long ba0_addr; |
346 | unsigned long ba1_addr; | 347 | unsigned long ba1_addr; |
347 | u32 irq; | 348 | u32 irq; |
348 | 349 | ||
349 | /* mappings */ | 350 | /* mappings */ |
350 | void __iomem *ba0; | 351 | void __iomem *ba0; |
351 | union | 352 | union |
352 | { | 353 | { |
353 | struct | 354 | struct |
354 | { | 355 | { |
355 | u8 __iomem *data0; | 356 | u8 __iomem *data0; |
356 | u8 __iomem *data1; | 357 | u8 __iomem *data1; |
357 | u8 __iomem *pmem; | 358 | u8 __iomem *pmem; |
358 | u8 __iomem *reg; | 359 | u8 __iomem *reg; |
359 | } name; | 360 | } name; |
360 | u8 __iomem *idx[4]; | 361 | u8 __iomem *idx[4]; |
361 | } ba1; | 362 | } ba1; |
362 | 363 | ||
363 | /* Function support */ | 364 | /* Function support */ |
364 | struct cs_channel *(*alloc_pcm_channel)(struct cs_card *); | 365 | struct cs_channel *(*alloc_pcm_channel)(struct cs_card *); |
365 | struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *); | 366 | struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *); |
366 | void (*free_pcm_channel)(struct cs_card *, int chan); | 367 | void (*free_pcm_channel)(struct cs_card *, int chan); |
367 | 368 | ||
368 | /* /dev/midi stuff */ | 369 | /* /dev/midi stuff */ |
369 | struct { | 370 | struct { |
370 | unsigned ird, iwr, icnt; | 371 | unsigned ird, iwr, icnt; |
371 | unsigned ord, owr, ocnt; | 372 | unsigned ord, owr, ocnt; |
372 | wait_queue_head_t open_wait; | 373 | wait_queue_head_t open_wait; |
373 | wait_queue_head_t iwait; | 374 | wait_queue_head_t iwait; |
374 | wait_queue_head_t owait; | 375 | wait_queue_head_t owait; |
375 | spinlock_t lock; | 376 | spinlock_t lock; |
376 | unsigned char ibuf[CS_MIDIINBUF]; | 377 | unsigned char ibuf[CS_MIDIINBUF]; |
377 | unsigned char obuf[CS_MIDIOUTBUF]; | 378 | unsigned char obuf[CS_MIDIOUTBUF]; |
378 | mode_t open_mode; | 379 | mode_t open_mode; |
379 | struct mutex open_mutex; | 380 | struct mutex open_mutex; |
380 | } midi; | 381 | } midi; |
381 | struct cs46xx_pm pm; | 382 | struct cs46xx_pm pm; |
382 | }; | 383 | }; |
383 | 384 | ||
384 | static int cs_open_mixdev(struct inode *inode, struct file *file); | 385 | static int cs_open_mixdev(struct inode *inode, struct file *file); |
385 | static int cs_release_mixdev(struct inode *inode, struct file *file); | 386 | static int cs_release_mixdev(struct inode *inode, struct file *file); |
386 | static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, | 387 | static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, |
387 | unsigned long arg); | 388 | unsigned long arg); |
388 | static int cs_hardware_init(struct cs_card *card); | 389 | static int cs_hardware_init(struct cs_card *card); |
389 | static int cs46xx_powerup(struct cs_card *card, unsigned int type); | 390 | static int cs46xx_powerup(struct cs_card *card, unsigned int type); |
390 | static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag); | 391 | static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag); |
391 | static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type); | 392 | static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type); |
392 | #ifdef CONFIG_PM | 393 | #ifdef CONFIG_PM |
393 | static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state); | 394 | static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state); |
394 | static int cs46xx_resume_tbl(struct pci_dev *pcidev); | 395 | static int cs46xx_resume_tbl(struct pci_dev *pcidev); |
395 | #endif | 396 | #endif |
396 | 397 | ||
397 | #if CSDEBUG | 398 | #if CSDEBUG |
398 | 399 | ||
399 | /* DEBUG ROUTINES */ | 400 | /* DEBUG ROUTINES */ |
400 | 401 | ||
401 | #define SOUND_MIXER_CS_GETDBGLEVEL _SIOWR('M',120, int) | 402 | #define SOUND_MIXER_CS_GETDBGLEVEL _SIOWR('M',120, int) |
402 | #define SOUND_MIXER_CS_SETDBGLEVEL _SIOWR('M',121, int) | 403 | #define SOUND_MIXER_CS_SETDBGLEVEL _SIOWR('M',121, int) |
403 | #define SOUND_MIXER_CS_GETDBGMASK _SIOWR('M',122, int) | 404 | #define SOUND_MIXER_CS_GETDBGMASK _SIOWR('M',122, int) |
404 | #define SOUND_MIXER_CS_SETDBGMASK _SIOWR('M',123, int) | 405 | #define SOUND_MIXER_CS_SETDBGMASK _SIOWR('M',123, int) |
405 | #define SOUND_MIXER_CS_APM _SIOWR('M',124, int) | 406 | #define SOUND_MIXER_CS_APM _SIOWR('M',124, int) |
406 | 407 | ||
407 | static void printioctl(unsigned int x) | 408 | static void printioctl(unsigned int x) |
408 | { | 409 | { |
409 | unsigned int i; | 410 | unsigned int i; |
410 | unsigned char vidx; | 411 | unsigned char vidx; |
411 | /* these values are incorrect for the ac97 driver, fix. | 412 | /* these values are incorrect for the ac97 driver, fix. |
412 | * Index of mixtable1[] member is Device ID | 413 | * Index of mixtable1[] member is Device ID |
413 | * and must be <= SOUND_MIXER_NRDEVICES. | 414 | * and must be <= SOUND_MIXER_NRDEVICES. |
414 | * Value of array member is index into s->mix.vol[] | 415 | * Value of array member is index into s->mix.vol[] |
415 | */ | 416 | */ |
416 | static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = { | 417 | static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = { |
417 | [SOUND_MIXER_PCM] = 1, /* voice */ | 418 | [SOUND_MIXER_PCM] = 1, /* voice */ |
418 | [SOUND_MIXER_LINE1] = 2, /* AUX */ | 419 | [SOUND_MIXER_LINE1] = 2, /* AUX */ |
419 | [SOUND_MIXER_CD] = 3, /* CD */ | 420 | [SOUND_MIXER_CD] = 3, /* CD */ |
420 | [SOUND_MIXER_LINE] = 4, /* Line */ | 421 | [SOUND_MIXER_LINE] = 4, /* Line */ |
421 | [SOUND_MIXER_SYNTH] = 5, /* FM */ | 422 | [SOUND_MIXER_SYNTH] = 5, /* FM */ |
422 | [SOUND_MIXER_MIC] = 6, /* Mic */ | 423 | [SOUND_MIXER_MIC] = 6, /* Mic */ |
423 | [SOUND_MIXER_SPEAKER] = 7, /* Speaker */ | 424 | [SOUND_MIXER_SPEAKER] = 7, /* Speaker */ |
424 | [SOUND_MIXER_RECLEV] = 8, /* Recording level */ | 425 | [SOUND_MIXER_RECLEV] = 8, /* Recording level */ |
425 | [SOUND_MIXER_VOLUME] = 9 /* Master Volume */ | 426 | [SOUND_MIXER_VOLUME] = 9 /* Master Volume */ |
426 | }; | 427 | }; |
427 | 428 | ||
428 | switch (x) { | 429 | switch (x) { |
429 | case SOUND_MIXER_CS_GETDBGMASK: | 430 | case SOUND_MIXER_CS_GETDBGMASK: |
430 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") ); | 431 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") ); |
431 | break; | 432 | break; |
432 | case SOUND_MIXER_CS_GETDBGLEVEL: | 433 | case SOUND_MIXER_CS_GETDBGLEVEL: |
433 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGLEVEL: ") ); | 434 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGLEVEL: ") ); |
434 | break; | 435 | break; |
435 | case SOUND_MIXER_CS_SETDBGMASK: | 436 | case SOUND_MIXER_CS_SETDBGMASK: |
436 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGMASK: ") ); | 437 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGMASK: ") ); |
437 | break; | 438 | break; |
438 | case SOUND_MIXER_CS_SETDBGLEVEL: | 439 | case SOUND_MIXER_CS_SETDBGLEVEL: |
439 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGLEVEL: ") ); | 440 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGLEVEL: ") ); |
440 | break; | 441 | break; |
441 | case OSS_GETVERSION: | 442 | case OSS_GETVERSION: |
442 | CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION: ") ); | 443 | CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION: ") ); |
443 | break; | 444 | break; |
444 | case SNDCTL_DSP_SYNC: | 445 | case SNDCTL_DSP_SYNC: |
445 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC: ") ); | 446 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC: ") ); |
446 | break; | 447 | break; |
447 | case SNDCTL_DSP_SETDUPLEX: | 448 | case SNDCTL_DSP_SETDUPLEX: |
448 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX: ") ); | 449 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX: ") ); |
449 | break; | 450 | break; |
450 | case SNDCTL_DSP_GETCAPS: | 451 | case SNDCTL_DSP_GETCAPS: |
451 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS: ") ); | 452 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS: ") ); |
452 | break; | 453 | break; |
453 | case SNDCTL_DSP_RESET: | 454 | case SNDCTL_DSP_RESET: |
454 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET: ") ); | 455 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET: ") ); |
455 | break; | 456 | break; |
456 | case SNDCTL_DSP_SPEED: | 457 | case SNDCTL_DSP_SPEED: |
457 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED: ") ); | 458 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED: ") ); |
458 | break; | 459 | break; |
459 | case SNDCTL_DSP_STEREO: | 460 | case SNDCTL_DSP_STEREO: |
460 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO: ") ); | 461 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO: ") ); |
461 | break; | 462 | break; |
462 | case SNDCTL_DSP_CHANNELS: | 463 | case SNDCTL_DSP_CHANNELS: |
463 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS: ") ); | 464 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS: ") ); |
464 | break; | 465 | break; |
465 | case SNDCTL_DSP_GETFMTS: | 466 | case SNDCTL_DSP_GETFMTS: |
466 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS: ") ); | 467 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS: ") ); |
467 | break; | 468 | break; |
468 | case SNDCTL_DSP_SETFMT: | 469 | case SNDCTL_DSP_SETFMT: |
469 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT: ") ); | 470 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT: ") ); |
470 | break; | 471 | break; |
471 | case SNDCTL_DSP_POST: | 472 | case SNDCTL_DSP_POST: |
472 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST: ") ); | 473 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST: ") ); |
473 | break; | 474 | break; |
474 | case SNDCTL_DSP_GETTRIGGER: | 475 | case SNDCTL_DSP_GETTRIGGER: |
475 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER: ") ); | 476 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER: ") ); |
476 | break; | 477 | break; |
477 | case SNDCTL_DSP_SETTRIGGER: | 478 | case SNDCTL_DSP_SETTRIGGER: |
478 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER: ") ); | 479 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER: ") ); |
479 | break; | 480 | break; |
480 | case SNDCTL_DSP_GETOSPACE: | 481 | case SNDCTL_DSP_GETOSPACE: |
481 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE: ") ); | 482 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE: ") ); |
482 | break; | 483 | break; |
483 | case SNDCTL_DSP_GETISPACE: | 484 | case SNDCTL_DSP_GETISPACE: |
484 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE: ") ); | 485 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE: ") ); |
485 | break; | 486 | break; |
486 | case SNDCTL_DSP_NONBLOCK: | 487 | case SNDCTL_DSP_NONBLOCK: |
487 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK: ") ); | 488 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK: ") ); |
488 | break; | 489 | break; |
489 | case SNDCTL_DSP_GETODELAY: | 490 | case SNDCTL_DSP_GETODELAY: |
490 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY: ") ); | 491 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY: ") ); |
491 | break; | 492 | break; |
492 | case SNDCTL_DSP_GETIPTR: | 493 | case SNDCTL_DSP_GETIPTR: |
493 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR: ") ); | 494 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR: ") ); |
494 | break; | 495 | break; |
495 | case SNDCTL_DSP_GETOPTR: | 496 | case SNDCTL_DSP_GETOPTR: |
496 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR: ") ); | 497 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR: ") ); |
497 | break; | 498 | break; |
498 | case SNDCTL_DSP_GETBLKSIZE: | 499 | case SNDCTL_DSP_GETBLKSIZE: |
499 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE: ") ); | 500 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE: ") ); |
500 | break; | 501 | break; |
501 | case SNDCTL_DSP_SETFRAGMENT: | 502 | case SNDCTL_DSP_SETFRAGMENT: |
502 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT: ") ); | 503 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT: ") ); |
503 | break; | 504 | break; |
504 | case SNDCTL_DSP_SUBDIVIDE: | 505 | case SNDCTL_DSP_SUBDIVIDE: |
505 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE: ") ); | 506 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE: ") ); |
506 | break; | 507 | break; |
507 | case SOUND_PCM_READ_RATE: | 508 | case SOUND_PCM_READ_RATE: |
508 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE: ") ); | 509 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE: ") ); |
509 | break; | 510 | break; |
510 | case SOUND_PCM_READ_CHANNELS: | 511 | case SOUND_PCM_READ_CHANNELS: |
511 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS: ") ); | 512 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS: ") ); |
512 | break; | 513 | break; |
513 | case SOUND_PCM_READ_BITS: | 514 | case SOUND_PCM_READ_BITS: |
514 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS: ") ); | 515 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS: ") ); |
515 | break; | 516 | break; |
516 | case SOUND_PCM_WRITE_FILTER: | 517 | case SOUND_PCM_WRITE_FILTER: |
517 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER: ") ); | 518 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER: ") ); |
518 | break; | 519 | break; |
519 | case SNDCTL_DSP_SETSYNCRO: | 520 | case SNDCTL_DSP_SETSYNCRO: |
520 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO: ") ); | 521 | CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO: ") ); |
521 | break; | 522 | break; |
522 | case SOUND_PCM_READ_FILTER: | 523 | case SOUND_PCM_READ_FILTER: |
523 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") ); | 524 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") ); |
524 | break; | 525 | break; |
525 | case SOUND_MIXER_PRIVATE1: | 526 | case SOUND_MIXER_PRIVATE1: |
526 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") ); | 527 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") ); |
527 | break; | 528 | break; |
528 | case SOUND_MIXER_PRIVATE2: | 529 | case SOUND_MIXER_PRIVATE2: |
529 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2: ") ); | 530 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2: ") ); |
530 | break; | 531 | break; |
531 | case SOUND_MIXER_PRIVATE3: | 532 | case SOUND_MIXER_PRIVATE3: |
532 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3: ") ); | 533 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3: ") ); |
533 | break; | 534 | break; |
534 | case SOUND_MIXER_PRIVATE4: | 535 | case SOUND_MIXER_PRIVATE4: |
535 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4: ") ); | 536 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4: ") ); |
536 | break; | 537 | break; |
537 | case SOUND_MIXER_PRIVATE5: | 538 | case SOUND_MIXER_PRIVATE5: |
538 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5: ") ); | 539 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5: ") ); |
539 | break; | 540 | break; |
540 | case SOUND_MIXER_INFO: | 541 | case SOUND_MIXER_INFO: |
541 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO: ") ); | 542 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO: ") ); |
542 | break; | 543 | break; |
543 | case SOUND_OLD_MIXER_INFO: | 544 | case SOUND_OLD_MIXER_INFO: |
544 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") ); | 545 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") ); |
545 | break; | 546 | break; |
546 | default: | 547 | default: |
547 | switch (_IOC_NR(x)) { | 548 | switch (_IOC_NR(x)) { |
548 | case SOUND_MIXER_VOLUME: | 549 | case SOUND_MIXER_VOLUME: |
549 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") ); | 550 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") ); |
550 | break; | 551 | break; |
551 | case SOUND_MIXER_SPEAKER: | 552 | case SOUND_MIXER_SPEAKER: |
552 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER: ") ); | 553 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER: ") ); |
553 | break; | 554 | break; |
554 | case SOUND_MIXER_RECLEV: | 555 | case SOUND_MIXER_RECLEV: |
555 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV: ") ); | 556 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV: ") ); |
556 | break; | 557 | break; |
557 | case SOUND_MIXER_MIC: | 558 | case SOUND_MIXER_MIC: |
558 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC: ") ); | 559 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC: ") ); |
559 | break; | 560 | break; |
560 | case SOUND_MIXER_SYNTH: | 561 | case SOUND_MIXER_SYNTH: |
561 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH: ") ); | 562 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH: ") ); |
562 | break; | 563 | break; |
563 | case SOUND_MIXER_RECSRC: | 564 | case SOUND_MIXER_RECSRC: |
564 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC: ") ); | 565 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC: ") ); |
565 | break; | 566 | break; |
566 | case SOUND_MIXER_DEVMASK: | 567 | case SOUND_MIXER_DEVMASK: |
567 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK: ") ); | 568 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK: ") ); |
568 | break; | 569 | break; |
569 | case SOUND_MIXER_RECMASK: | 570 | case SOUND_MIXER_RECMASK: |
570 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK: ") ); | 571 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK: ") ); |
571 | break; | 572 | break; |
572 | case SOUND_MIXER_STEREODEVS: | 573 | case SOUND_MIXER_STEREODEVS: |
573 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS: ") ); | 574 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS: ") ); |
574 | break; | 575 | break; |
575 | case SOUND_MIXER_CAPS: | 576 | case SOUND_MIXER_CAPS: |
576 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:") ); | 577 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:") ); |
577 | break; | 578 | break; |
578 | default: | 579 | default: |
579 | i = _IOC_NR(x); | 580 | i = _IOC_NR(x); |
580 | if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) { | 581 | if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) { |
581 | CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) ); | 582 | CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) ); |
582 | } else { | 583 | } else { |
583 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ", | 584 | CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ", |
584 | x,i)); | 585 | x,i)); |
585 | } | 586 | } |
586 | break; | 587 | break; |
587 | } | 588 | } |
588 | } | 589 | } |
589 | CS_DBGOUT(CS_IOCTL, 4, printk("command = 0x%x IOC_NR=%d\n",x, _IOC_NR(x)) ); | 590 | CS_DBGOUT(CS_IOCTL, 4, printk("command = 0x%x IOC_NR=%d\n",x, _IOC_NR(x)) ); |
590 | } | 591 | } |
591 | #endif | 592 | #endif |
592 | 593 | ||
593 | /* | 594 | /* |
594 | * common I/O routines | 595 | * common I/O routines |
595 | */ | 596 | */ |
596 | 597 | ||
597 | static void cs461x_poke(struct cs_card *codec, unsigned long reg, unsigned int val) | 598 | static void cs461x_poke(struct cs_card *codec, unsigned long reg, unsigned int val) |
598 | { | 599 | { |
599 | writel(val, codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff)); | 600 | writel(val, codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff)); |
600 | } | 601 | } |
601 | 602 | ||
602 | static unsigned int cs461x_peek(struct cs_card *codec, unsigned long reg) | 603 | static unsigned int cs461x_peek(struct cs_card *codec, unsigned long reg) |
603 | { | 604 | { |
604 | return readl(codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff)); | 605 | return readl(codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff)); |
605 | } | 606 | } |
606 | 607 | ||
607 | static void cs461x_pokeBA0(struct cs_card *codec, unsigned long reg, unsigned int val) | 608 | static void cs461x_pokeBA0(struct cs_card *codec, unsigned long reg, unsigned int val) |
608 | { | 609 | { |
609 | writel(val, codec->ba0 + reg); | 610 | writel(val, codec->ba0 + reg); |
610 | } | 611 | } |
611 | 612 | ||
612 | static unsigned int cs461x_peekBA0(struct cs_card *codec, unsigned long reg) | 613 | static unsigned int cs461x_peekBA0(struct cs_card *codec, unsigned long reg) |
613 | { | 614 | { |
614 | return readl(codec->ba0 + reg); | 615 | return readl(codec->ba0 + reg); |
615 | } | 616 | } |
616 | 617 | ||
617 | 618 | ||
618 | static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg); | 619 | static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg); |
619 | static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 data); | 620 | static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 data); |
620 | 621 | ||
621 | static struct cs_channel *cs_alloc_pcm_channel(struct cs_card *card) | 622 | static struct cs_channel *cs_alloc_pcm_channel(struct cs_card *card) |
622 | { | 623 | { |
623 | if (card->channel[1].used == 1) | 624 | if (card->channel[1].used == 1) |
624 | return NULL; | 625 | return NULL; |
625 | card->channel[1].used = 1; | 626 | card->channel[1].used = 1; |
626 | card->channel[1].num = 1; | 627 | card->channel[1].num = 1; |
627 | return &card->channel[1]; | 628 | return &card->channel[1]; |
628 | } | 629 | } |
629 | 630 | ||
630 | static struct cs_channel *cs_alloc_rec_pcm_channel(struct cs_card *card) | 631 | static struct cs_channel *cs_alloc_rec_pcm_channel(struct cs_card *card) |
631 | { | 632 | { |
632 | if (card->channel[0].used == 1) | 633 | if (card->channel[0].used == 1) |
633 | return NULL; | 634 | return NULL; |
634 | card->channel[0].used = 1; | 635 | card->channel[0].used = 1; |
635 | card->channel[0].num = 0; | 636 | card->channel[0].num = 0; |
636 | return &card->channel[0]; | 637 | return &card->channel[0]; |
637 | } | 638 | } |
638 | 639 | ||
639 | static void cs_free_pcm_channel(struct cs_card *card, int channel) | 640 | static void cs_free_pcm_channel(struct cs_card *card, int channel) |
640 | { | 641 | { |
641 | card->channel[channel].state = NULL; | 642 | card->channel[channel].state = NULL; |
642 | card->channel[channel].used = 0; | 643 | card->channel[channel].used = 0; |
643 | } | 644 | } |
644 | 645 | ||
645 | /* | 646 | /* |
646 | * setup a divisor value to help with conversion from | 647 | * setup a divisor value to help with conversion from |
647 | * 16bit Stereo, down to 8bit stereo/mono or 16bit mono. | 648 | * 16bit Stereo, down to 8bit stereo/mono or 16bit mono. |
648 | * assign a divisor of 1 if using 16bit Stereo as that is | 649 | * assign a divisor of 1 if using 16bit Stereo as that is |
649 | * the only format that the static image will capture. | 650 | * the only format that the static image will capture. |
650 | */ | 651 | */ |
651 | static void cs_set_divisor(struct dmabuf *dmabuf) | 652 | static void cs_set_divisor(struct dmabuf *dmabuf) |
652 | { | 653 | { |
653 | if (dmabuf->type == CS_TYPE_DAC) | 654 | if (dmabuf->type == CS_TYPE_DAC) |
654 | dmabuf->divisor = 1; | 655 | dmabuf->divisor = 1; |
655 | else if (!(dmabuf->fmt & CS_FMT_STEREO) && | 656 | else if (!(dmabuf->fmt & CS_FMT_STEREO) && |
656 | (dmabuf->fmt & CS_FMT_16BIT)) | 657 | (dmabuf->fmt & CS_FMT_16BIT)) |
657 | dmabuf->divisor = 2; | 658 | dmabuf->divisor = 2; |
658 | else if ((dmabuf->fmt & CS_FMT_STEREO) && | 659 | else if ((dmabuf->fmt & CS_FMT_STEREO) && |
659 | !(dmabuf->fmt & CS_FMT_16BIT)) | 660 | !(dmabuf->fmt & CS_FMT_16BIT)) |
660 | dmabuf->divisor = 2; | 661 | dmabuf->divisor = 2; |
661 | else if (!(dmabuf->fmt & CS_FMT_STEREO) && | 662 | else if (!(dmabuf->fmt & CS_FMT_STEREO) && |
662 | !(dmabuf->fmt & CS_FMT_16BIT)) | 663 | !(dmabuf->fmt & CS_FMT_16BIT)) |
663 | dmabuf->divisor = 4; | 664 | dmabuf->divisor = 4; |
664 | else | 665 | else |
665 | dmabuf->divisor = 1; | 666 | dmabuf->divisor = 1; |
666 | 667 | ||
667 | CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, printk( | 668 | CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, printk( |
668 | "cs46xx: cs_set_divisor()- %s %d\n", | 669 | "cs46xx: cs_set_divisor()- %s %d\n", |
669 | (dmabuf->type == CS_TYPE_ADC) ? "ADC" : "DAC", | 670 | (dmabuf->type == CS_TYPE_ADC) ? "ADC" : "DAC", |
670 | dmabuf->divisor) ); | 671 | dmabuf->divisor) ); |
671 | } | 672 | } |
672 | 673 | ||
673 | /* | 674 | /* |
674 | * mute some of the more prevalent registers to avoid popping. | 675 | * mute some of the more prevalent registers to avoid popping. |
675 | */ | 676 | */ |
676 | static void cs_mute(struct cs_card *card, int state) | 677 | static void cs_mute(struct cs_card *card, int state) |
677 | { | 678 | { |
678 | struct ac97_codec *dev = card->ac97_codec[0]; | 679 | struct ac97_codec *dev = card->ac97_codec[0]; |
679 | 680 | ||
680 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()+ %s\n", | 681 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()+ %s\n", |
681 | (state == CS_TRUE) ? "Muting" : "UnMuting")); | 682 | (state == CS_TRUE) ? "Muting" : "UnMuting")); |
682 | 683 | ||
683 | if (state == CS_TRUE) { | 684 | if (state == CS_TRUE) { |
684 | /* | 685 | /* |
685 | * fix pops when powering up on thinkpads | 686 | * fix pops when powering up on thinkpads |
686 | */ | 687 | */ |
687 | card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, | 688 | card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, |
688 | (u8)BA0_AC97_MASTER_VOLUME); | 689 | (u8)BA0_AC97_MASTER_VOLUME); |
689 | card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, | 690 | card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, |
690 | (u8)BA0_AC97_HEADPHONE_VOLUME); | 691 | (u8)BA0_AC97_HEADPHONE_VOLUME); |
691 | card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, | 692 | card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, |
692 | (u8)BA0_AC97_MASTER_VOLUME_MONO); | 693 | (u8)BA0_AC97_MASTER_VOLUME_MONO); |
693 | card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, | 694 | card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, |
694 | (u8)BA0_AC97_PCM_OUT_VOLUME); | 695 | (u8)BA0_AC97_PCM_OUT_VOLUME); |
695 | 696 | ||
696 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000); | 697 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000); |
697 | cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000); | 698 | cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000); |
698 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000); | 699 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000); |
699 | cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000); | 700 | cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000); |
700 | } else { | 701 | } else { |
701 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume); | 702 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume); |
702 | cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume); | 703 | cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume); |
703 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono); | 704 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono); |
704 | cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume); | 705 | cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume); |
705 | } | 706 | } |
706 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()-\n")); | 707 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()-\n")); |
707 | } | 708 | } |
708 | 709 | ||
709 | /* set playback sample rate */ | 710 | /* set playback sample rate */ |
710 | static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate) | 711 | static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate) |
711 | { | 712 | { |
712 | struct dmabuf *dmabuf = &state->dmabuf; | 713 | struct dmabuf *dmabuf = &state->dmabuf; |
713 | unsigned int tmp1, tmp2; | 714 | unsigned int tmp1, tmp2; |
714 | unsigned int phiIncr; | 715 | unsigned int phiIncr; |
715 | unsigned int correctionPerGOF, correctionPerSec; | 716 | unsigned int correctionPerGOF, correctionPerSec; |
716 | unsigned long flags; | 717 | unsigned long flags; |
717 | 718 | ||
718 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()+ %d\n",rate) ); | 719 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()+ %d\n",rate) ); |
719 | 720 | ||
720 | /* | 721 | /* |
721 | * Compute the values used to drive the actual sample rate conversion. | 722 | * Compute the values used to drive the actual sample rate conversion. |
722 | * The following formulas are being computed, using inline assembly | 723 | * The following formulas are being computed, using inline assembly |
723 | * since we need to use 64 bit arithmetic to compute the values: | 724 | * since we need to use 64 bit arithmetic to compute the values: |
724 | * | 725 | * |
725 | * phiIncr = floor((Fs,in * 2^26) / Fs,out) | 726 | * phiIncr = floor((Fs,in * 2^26) / Fs,out) |
726 | * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / | 727 | * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / |
727 | * GOF_PER_SEC) | 728 | * GOF_PER_SEC) |
728 | * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M | 729 | * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M |
729 | * GOF_PER_SEC * correctionPerGOF | 730 | * GOF_PER_SEC * correctionPerGOF |
730 | * | 731 | * |
731 | * i.e. | 732 | * i.e. |
732 | * | 733 | * |
733 | * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out) | 734 | * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out) |
734 | * correctionPerGOF:correctionPerSec = | 735 | * correctionPerGOF:correctionPerSec = |
735 | * dividend:remainder(ulOther / GOF_PER_SEC) | 736 | * dividend:remainder(ulOther / GOF_PER_SEC) |
736 | */ | 737 | */ |
737 | tmp1 = rate << 16; | 738 | tmp1 = rate << 16; |
738 | phiIncr = tmp1 / 48000; | 739 | phiIncr = tmp1 / 48000; |
739 | tmp1 -= phiIncr * 48000; | 740 | tmp1 -= phiIncr * 48000; |
740 | tmp1 <<= 10; | 741 | tmp1 <<= 10; |
741 | phiIncr <<= 10; | 742 | phiIncr <<= 10; |
742 | tmp2 = tmp1 / 48000; | 743 | tmp2 = tmp1 / 48000; |
743 | phiIncr += tmp2; | 744 | phiIncr += tmp2; |
744 | tmp1 -= tmp2 * 48000; | 745 | tmp1 -= tmp2 * 48000; |
745 | correctionPerGOF = tmp1 / GOF_PER_SEC; | 746 | correctionPerGOF = tmp1 / GOF_PER_SEC; |
746 | tmp1 -= correctionPerGOF * GOF_PER_SEC; | 747 | tmp1 -= correctionPerGOF * GOF_PER_SEC; |
747 | correctionPerSec = tmp1; | 748 | correctionPerSec = tmp1; |
748 | 749 | ||
749 | /* | 750 | /* |
750 | * Fill in the SampleRateConverter control block. | 751 | * Fill in the SampleRateConverter control block. |
751 | */ | 752 | */ |
752 | spin_lock_irqsave(&state->card->lock, flags); | 753 | spin_lock_irqsave(&state->card->lock, flags); |
753 | cs461x_poke(state->card, BA1_PSRC, | 754 | cs461x_poke(state->card, BA1_PSRC, |
754 | ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); | 755 | ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); |
755 | cs461x_poke(state->card, BA1_PPI, phiIncr); | 756 | cs461x_poke(state->card, BA1_PPI, phiIncr); |
756 | spin_unlock_irqrestore(&state->card->lock, flags); | 757 | spin_unlock_irqrestore(&state->card->lock, flags); |
757 | dmabuf->rate = rate; | 758 | dmabuf->rate = rate; |
758 | 759 | ||
759 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()- %d\n",rate) ); | 760 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()- %d\n",rate) ); |
760 | return rate; | 761 | return rate; |
761 | } | 762 | } |
762 | 763 | ||
763 | /* set recording sample rate */ | 764 | /* set recording sample rate */ |
764 | static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate) | 765 | static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate) |
765 | { | 766 | { |
766 | struct dmabuf *dmabuf = &state->dmabuf; | 767 | struct dmabuf *dmabuf = &state->dmabuf; |
767 | struct cs_card *card = state->card; | 768 | struct cs_card *card = state->card; |
768 | unsigned int phiIncr, coeffIncr, tmp1, tmp2; | 769 | unsigned int phiIncr, coeffIncr, tmp1, tmp2; |
769 | unsigned int correctionPerGOF, correctionPerSec, initialDelay; | 770 | unsigned int correctionPerGOF, correctionPerSec, initialDelay; |
770 | unsigned int frameGroupLength, cnt; | 771 | unsigned int frameGroupLength, cnt; |
771 | unsigned long flags; | 772 | unsigned long flags; |
772 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()+ %d\n",rate) ); | 773 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()+ %d\n",rate) ); |
773 | 774 | ||
774 | /* | 775 | /* |
775 | * We can only decimate by up to a factor of 1/9th the hardware rate. | 776 | * We can only decimate by up to a factor of 1/9th the hardware rate. |
776 | * Correct the value if an attempt is made to stray outside that limit. | 777 | * Correct the value if an attempt is made to stray outside that limit. |
777 | */ | 778 | */ |
778 | if ((rate * 9) < 48000) | 779 | if ((rate * 9) < 48000) |
779 | rate = 48000 / 9; | 780 | rate = 48000 / 9; |
780 | 781 | ||
781 | /* | 782 | /* |
782 | * We cannot capture at at rate greater than the Input Rate (48000). | 783 | * We cannot capture at at rate greater than the Input Rate (48000). |
783 | * Return an error if an attempt is made to stray outside that limit. | 784 | * Return an error if an attempt is made to stray outside that limit. |
784 | */ | 785 | */ |
785 | if (rate > 48000) | 786 | if (rate > 48000) |
786 | rate = 48000; | 787 | rate = 48000; |
787 | 788 | ||
788 | /* | 789 | /* |
789 | * Compute the values used to drive the actual sample rate conversion. | 790 | * Compute the values used to drive the actual sample rate conversion. |
790 | * The following formulas are being computed, using inline assembly | 791 | * The following formulas are being computed, using inline assembly |
791 | * since we need to use 64 bit arithmetic to compute the values: | 792 | * since we need to use 64 bit arithmetic to compute the values: |
792 | * | 793 | * |
793 | * coeffIncr = -floor((Fs,out * 2^23) / Fs,in) | 794 | * coeffIncr = -floor((Fs,out * 2^23) / Fs,in) |
794 | * phiIncr = floor((Fs,in * 2^26) / Fs,out) | 795 | * phiIncr = floor((Fs,in * 2^26) / Fs,out) |
795 | * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / | 796 | * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / |
796 | * GOF_PER_SEC) | 797 | * GOF_PER_SEC) |
797 | * correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr - | 798 | * correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr - |
798 | * GOF_PER_SEC * correctionPerGOF | 799 | * GOF_PER_SEC * correctionPerGOF |
799 | * initialDelay = ceil((24 * Fs,in) / Fs,out) | 800 | * initialDelay = ceil((24 * Fs,in) / Fs,out) |
800 | * | 801 | * |
801 | * i.e. | 802 | * i.e. |
802 | * | 803 | * |
803 | * coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in)) | 804 | * coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in)) |
804 | * phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out) | 805 | * phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out) |
805 | * correctionPerGOF:correctionPerSec = | 806 | * correctionPerGOF:correctionPerSec = |
806 | * dividend:remainder(ulOther / GOF_PER_SEC) | 807 | * dividend:remainder(ulOther / GOF_PER_SEC) |
807 | * initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out) | 808 | * initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out) |
808 | */ | 809 | */ |
809 | tmp1 = rate << 16; | 810 | tmp1 = rate << 16; |
810 | coeffIncr = tmp1 / 48000; | 811 | coeffIncr = tmp1 / 48000; |
811 | tmp1 -= coeffIncr * 48000; | 812 | tmp1 -= coeffIncr * 48000; |
812 | tmp1 <<= 7; | 813 | tmp1 <<= 7; |
813 | coeffIncr <<= 7; | 814 | coeffIncr <<= 7; |
814 | coeffIncr += tmp1 / 48000; | 815 | coeffIncr += tmp1 / 48000; |
815 | coeffIncr ^= 0xFFFFFFFF; | 816 | coeffIncr ^= 0xFFFFFFFF; |
816 | coeffIncr++; | 817 | coeffIncr++; |
817 | tmp1 = 48000 << 16; | 818 | tmp1 = 48000 << 16; |
818 | phiIncr = tmp1 / rate; | 819 | phiIncr = tmp1 / rate; |
819 | tmp1 -= phiIncr * rate; | 820 | tmp1 -= phiIncr * rate; |
820 | tmp1 <<= 10; | 821 | tmp1 <<= 10; |
821 | phiIncr <<= 10; | 822 | phiIncr <<= 10; |
822 | tmp2 = tmp1 / rate; | 823 | tmp2 = tmp1 / rate; |
823 | phiIncr += tmp2; | 824 | phiIncr += tmp2; |
824 | tmp1 -= tmp2 * rate; | 825 | tmp1 -= tmp2 * rate; |
825 | correctionPerGOF = tmp1 / GOF_PER_SEC; | 826 | correctionPerGOF = tmp1 / GOF_PER_SEC; |
826 | tmp1 -= correctionPerGOF * GOF_PER_SEC; | 827 | tmp1 -= correctionPerGOF * GOF_PER_SEC; |
827 | correctionPerSec = tmp1; | 828 | correctionPerSec = tmp1; |
828 | initialDelay = ((48000 * 24) + rate - 1) / rate; | 829 | initialDelay = ((48000 * 24) + rate - 1) / rate; |
829 | 830 | ||
830 | /* | 831 | /* |
831 | * Fill in the VariDecimate control block. | 832 | * Fill in the VariDecimate control block. |
832 | */ | 833 | */ |
833 | spin_lock_irqsave(&card->lock, flags); | 834 | spin_lock_irqsave(&card->lock, flags); |
834 | cs461x_poke(card, BA1_CSRC, | 835 | cs461x_poke(card, BA1_CSRC, |
835 | ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); | 836 | ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); |
836 | cs461x_poke(card, BA1_CCI, coeffIncr); | 837 | cs461x_poke(card, BA1_CCI, coeffIncr); |
837 | cs461x_poke(card, BA1_CD, | 838 | cs461x_poke(card, BA1_CD, |
838 | (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80); | 839 | (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80); |
839 | cs461x_poke(card, BA1_CPI, phiIncr); | 840 | cs461x_poke(card, BA1_CPI, phiIncr); |
840 | spin_unlock_irqrestore(&card->lock, flags); | 841 | spin_unlock_irqrestore(&card->lock, flags); |
841 | 842 | ||
842 | /* | 843 | /* |
843 | * Figure out the frame group length for the write back task. Basically, | 844 | * Figure out the frame group length for the write back task. Basically, |
844 | * this is just the factors of 24000 (2^6*3*5^3) that are not present in | 845 | * this is just the factors of 24000 (2^6*3*5^3) that are not present in |
845 | * the output sample rate. | 846 | * the output sample rate. |
846 | */ | 847 | */ |
847 | frameGroupLength = 1; | 848 | frameGroupLength = 1; |
848 | for (cnt = 2; cnt <= 64; cnt *= 2) { | 849 | for (cnt = 2; cnt <= 64; cnt *= 2) { |
849 | if (((rate / cnt) * cnt) != rate) | 850 | if (((rate / cnt) * cnt) != rate) |
850 | frameGroupLength *= 2; | 851 | frameGroupLength *= 2; |
851 | } | 852 | } |
852 | if (((rate / 3) * 3) != rate) { | 853 | if (((rate / 3) * 3) != rate) { |
853 | frameGroupLength *= 3; | 854 | frameGroupLength *= 3; |
854 | } | 855 | } |
855 | for (cnt = 5; cnt <= 125; cnt *= 5) { | 856 | for (cnt = 5; cnt <= 125; cnt *= 5) { |
856 | if (((rate / cnt) * cnt) != rate) | 857 | if (((rate / cnt) * cnt) != rate) |
857 | frameGroupLength *= 5; | 858 | frameGroupLength *= 5; |
858 | } | 859 | } |
859 | 860 | ||
860 | /* | 861 | /* |
861 | * Fill in the WriteBack control block. | 862 | * Fill in the WriteBack control block. |
862 | */ | 863 | */ |
863 | spin_lock_irqsave(&card->lock, flags); | 864 | spin_lock_irqsave(&card->lock, flags); |
864 | cs461x_poke(card, BA1_CFG1, frameGroupLength); | 865 | cs461x_poke(card, BA1_CFG1, frameGroupLength); |
865 | cs461x_poke(card, BA1_CFG2, (0x00800000 | frameGroupLength)); | 866 | cs461x_poke(card, BA1_CFG2, (0x00800000 | frameGroupLength)); |
866 | cs461x_poke(card, BA1_CCST, 0x0000FFFF); | 867 | cs461x_poke(card, BA1_CCST, 0x0000FFFF); |
867 | cs461x_poke(card, BA1_CSPB, ((65536 * rate) / 24000)); | 868 | cs461x_poke(card, BA1_CSPB, ((65536 * rate) / 24000)); |
868 | cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF); | 869 | cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF); |
869 | spin_unlock_irqrestore(&card->lock, flags); | 870 | spin_unlock_irqrestore(&card->lock, flags); |
870 | dmabuf->rate = rate; | 871 | dmabuf->rate = rate; |
871 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) ); | 872 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) ); |
872 | return rate; | 873 | return rate; |
873 | } | 874 | } |
874 | 875 | ||
875 | /* prepare channel attributes for playback */ | 876 | /* prepare channel attributes for playback */ |
876 | static void cs_play_setup(struct cs_state *state) | 877 | static void cs_play_setup(struct cs_state *state) |
877 | { | 878 | { |
878 | struct dmabuf *dmabuf = &state->dmabuf; | 879 | struct dmabuf *dmabuf = &state->dmabuf; |
879 | struct cs_card *card = state->card; | 880 | struct cs_card *card = state->card; |
880 | unsigned int tmp, Count, playFormat; | 881 | unsigned int tmp, Count, playFormat; |
881 | 882 | ||
882 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") ); | 883 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") ); |
883 | cs461x_poke(card, BA1_PVOL, 0x80008000); | 884 | cs461x_poke(card, BA1_PVOL, 0x80008000); |
884 | if (!dmabuf->SGok) | 885 | if (!dmabuf->SGok) |
885 | cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf)); | 886 | cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf)); |
886 | 887 | ||
887 | Count = 4; | 888 | Count = 4; |
888 | playFormat=cs461x_peek(card, BA1_PFIE); | 889 | playFormat=cs461x_peek(card, BA1_PFIE); |
889 | if ((dmabuf->fmt & CS_FMT_STEREO)) { | 890 | if ((dmabuf->fmt & CS_FMT_STEREO)) { |
890 | playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO; | 891 | playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO; |
891 | Count *= 2; | 892 | Count *= 2; |
892 | } else | 893 | } else |
893 | playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO; | 894 | playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO; |
894 | 895 | ||
895 | if ((dmabuf->fmt & CS_FMT_16BIT)) { | 896 | if ((dmabuf->fmt & CS_FMT_16BIT)) { |
896 | playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT | 897 | playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT |
897 | | DMA_RQ_C2_AC_SIGNED_CONVERT); | 898 | | DMA_RQ_C2_AC_SIGNED_CONVERT); |
898 | Count *= 2; | 899 | Count *= 2; |
899 | } else | 900 | } else |
900 | playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT | 901 | playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT |
901 | | DMA_RQ_C2_AC_SIGNED_CONVERT); | 902 | | DMA_RQ_C2_AC_SIGNED_CONVERT); |
902 | 903 | ||
903 | cs461x_poke(card, BA1_PFIE, playFormat); | 904 | cs461x_poke(card, BA1_PFIE, playFormat); |
904 | 905 | ||
905 | tmp = cs461x_peek(card, BA1_PDTC); | 906 | tmp = cs461x_peek(card, BA1_PDTC); |
906 | tmp &= 0xfffffe00; | 907 | tmp &= 0xfffffe00; |
907 | cs461x_poke(card, BA1_PDTC, tmp | --Count); | 908 | cs461x_poke(card, BA1_PDTC, tmp | --Count); |
908 | 909 | ||
909 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") ); | 910 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") ); |
910 | } | 911 | } |
911 | 912 | ||
912 | static struct InitStruct | 913 | static struct InitStruct |
913 | { | 914 | { |
914 | u32 off; | 915 | u32 off; |
915 | u32 val; | 916 | u32 val; |
916 | } InitArray[] = { {0x00000040, 0x3fc0000f}, | 917 | } InitArray[] = { {0x00000040, 0x3fc0000f}, |
917 | {0x0000004c, 0x04800000}, | 918 | {0x0000004c, 0x04800000}, |
918 | 919 | ||
919 | {0x000000b3, 0x00000780}, | 920 | {0x000000b3, 0x00000780}, |
920 | {0x000000b7, 0x00000000}, | 921 | {0x000000b7, 0x00000000}, |
921 | {0x000000bc, 0x07800000}, | 922 | {0x000000bc, 0x07800000}, |
922 | 923 | ||
923 | {0x000000cd, 0x00800000}, | 924 | {0x000000cd, 0x00800000}, |
924 | }; | 925 | }; |
925 | 926 | ||
926 | /* | 927 | /* |
927 | * "SetCaptureSPValues()" -- Initialize record task values before each | 928 | * "SetCaptureSPValues()" -- Initialize record task values before each |
928 | * capture startup. | 929 | * capture startup. |
929 | */ | 930 | */ |
930 | static void SetCaptureSPValues(struct cs_card *card) | 931 | static void SetCaptureSPValues(struct cs_card *card) |
931 | { | 932 | { |
932 | unsigned i, offset; | 933 | unsigned i, offset; |
933 | CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") ); | 934 | CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") ); |
934 | for (i = 0; i < sizeof(InitArray) / sizeof(struct InitStruct); i++) { | 935 | for (i = 0; i < sizeof(InitArray) / sizeof(struct InitStruct); i++) { |
935 | offset = InitArray[i].off*4; /* 8bit to 32bit offset value */ | 936 | offset = InitArray[i].off*4; /* 8bit to 32bit offset value */ |
936 | cs461x_poke(card, offset, InitArray[i].val ); | 937 | cs461x_poke(card, offset, InitArray[i].val ); |
937 | } | 938 | } |
938 | CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()-\n") ); | 939 | CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()-\n") ); |
939 | } | 940 | } |
940 | 941 | ||
941 | /* prepare channel attributes for recording */ | 942 | /* prepare channel attributes for recording */ |
942 | static void cs_rec_setup(struct cs_state *state) | 943 | static void cs_rec_setup(struct cs_state *state) |
943 | { | 944 | { |
944 | struct cs_card *card = state->card; | 945 | struct cs_card *card = state->card; |
945 | struct dmabuf *dmabuf = &state->dmabuf; | 946 | struct dmabuf *dmabuf = &state->dmabuf; |
946 | 947 | ||
947 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n")); | 948 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n")); |
948 | SetCaptureSPValues(card); | 949 | SetCaptureSPValues(card); |
949 | 950 | ||
950 | /* | 951 | /* |
951 | * set the attenuation to 0dB | 952 | * set the attenuation to 0dB |
952 | */ | 953 | */ |
953 | cs461x_poke(card, BA1_CVOL, 0x80008000); | 954 | cs461x_poke(card, BA1_CVOL, 0x80008000); |
954 | 955 | ||
955 | /* | 956 | /* |
956 | * set the physical address of the capture buffer into the SP | 957 | * set the physical address of the capture buffer into the SP |
957 | */ | 958 | */ |
958 | cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf)); | 959 | cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf)); |
959 | 960 | ||
960 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") ); | 961 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") ); |
961 | } | 962 | } |
962 | 963 | ||
963 | 964 | ||
964 | /* get current playback/recording dma buffer pointer (byte offset from LBA), | 965 | /* get current playback/recording dma buffer pointer (byte offset from LBA), |
965 | called with spinlock held! */ | 966 | called with spinlock held! */ |
966 | 967 | ||
967 | static inline unsigned cs_get_dma_addr(struct cs_state *state) | 968 | static inline unsigned cs_get_dma_addr(struct cs_state *state) |
968 | { | 969 | { |
969 | struct dmabuf *dmabuf = &state->dmabuf; | 970 | struct dmabuf *dmabuf = &state->dmabuf; |
970 | u32 offset; | 971 | u32 offset; |
971 | 972 | ||
972 | if ( (!(dmabuf->enable & DAC_RUNNING)) && | 973 | if ( (!(dmabuf->enable & DAC_RUNNING)) && |
973 | (!(dmabuf->enable & ADC_RUNNING) ) ) | 974 | (!(dmabuf->enable & ADC_RUNNING) ) ) |
974 | { | 975 | { |
975 | CS_DBGOUT(CS_ERROR, 2, printk( | 976 | CS_DBGOUT(CS_ERROR, 2, printk( |
976 | "cs46xx: ERROR cs_get_dma_addr(): not enabled \n") ); | 977 | "cs46xx: ERROR cs_get_dma_addr(): not enabled \n") ); |
977 | return 0; | 978 | return 0; |
978 | } | 979 | } |
979 | 980 | ||
980 | /* | 981 | /* |
981 | * granularity is byte boundary, good part. | 982 | * granularity is byte boundary, good part. |
982 | */ | 983 | */ |
983 | if (dmabuf->enable & DAC_RUNNING) | 984 | if (dmabuf->enable & DAC_RUNNING) |
984 | offset = cs461x_peek(state->card, BA1_PBA); | 985 | offset = cs461x_peek(state->card, BA1_PBA); |
985 | else /* ADC_RUNNING must be set */ | 986 | else /* ADC_RUNNING must be set */ |
986 | offset = cs461x_peek(state->card, BA1_CBA); | 987 | offset = cs461x_peek(state->card, BA1_CBA); |
987 | 988 | ||
988 | CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9, | 989 | CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9, |
989 | printk("cs46xx: cs_get_dma_addr() %d\n",offset) ); | 990 | printk("cs46xx: cs_get_dma_addr() %d\n",offset) ); |
990 | offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf; | 991 | offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf; |
991 | CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, | 992 | CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, |
992 | printk("cs46xx: cs_get_dma_addr()- %d\n",offset) ); | 993 | printk("cs46xx: cs_get_dma_addr()- %d\n",offset) ); |
993 | return offset; | 994 | return offset; |
994 | } | 995 | } |
995 | 996 | ||
996 | static void resync_dma_ptrs(struct cs_state *state) | 997 | static void resync_dma_ptrs(struct cs_state *state) |
997 | { | 998 | { |
998 | struct dmabuf *dmabuf; | 999 | struct dmabuf *dmabuf; |
999 | 1000 | ||
1000 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") ); | 1001 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") ); |
1001 | if (state) { | 1002 | if (state) { |
1002 | dmabuf = &state->dmabuf; | 1003 | dmabuf = &state->dmabuf; |
1003 | dmabuf->hwptr=dmabuf->swptr = 0; | 1004 | dmabuf->hwptr=dmabuf->swptr = 0; |
1004 | dmabuf->pringbuf = 0; | 1005 | dmabuf->pringbuf = 0; |
1005 | } | 1006 | } |
1006 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") ); | 1007 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") ); |
1007 | } | 1008 | } |
1008 | 1009 | ||
1009 | /* Stop recording (lock held) */ | 1010 | /* Stop recording (lock held) */ |
1010 | static inline void __stop_adc(struct cs_state *state) | 1011 | static inline void __stop_adc(struct cs_state *state) |
1011 | { | 1012 | { |
1012 | struct dmabuf *dmabuf = &state->dmabuf; | 1013 | struct dmabuf *dmabuf = &state->dmabuf; |
1013 | struct cs_card *card = state->card; | 1014 | struct cs_card *card = state->card; |
1014 | unsigned int tmp; | 1015 | unsigned int tmp; |
1015 | 1016 | ||
1016 | dmabuf->enable &= ~ADC_RUNNING; | 1017 | dmabuf->enable &= ~ADC_RUNNING; |
1017 | 1018 | ||
1018 | tmp = cs461x_peek(card, BA1_CCTL); | 1019 | tmp = cs461x_peek(card, BA1_CCTL); |
1019 | tmp &= 0xFFFF0000; | 1020 | tmp &= 0xFFFF0000; |
1020 | cs461x_poke(card, BA1_CCTL, tmp ); | 1021 | cs461x_poke(card, BA1_CCTL, tmp ); |
1021 | } | 1022 | } |
1022 | 1023 | ||
1023 | static void stop_adc(struct cs_state *state) | 1024 | static void stop_adc(struct cs_state *state) |
1024 | { | 1025 | { |
1025 | unsigned long flags; | 1026 | unsigned long flags; |
1026 | 1027 | ||
1027 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") ); | 1028 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") ); |
1028 | spin_lock_irqsave(&state->card->lock, flags); | 1029 | spin_lock_irqsave(&state->card->lock, flags); |
1029 | __stop_adc(state); | 1030 | __stop_adc(state); |
1030 | spin_unlock_irqrestore(&state->card->lock, flags); | 1031 | spin_unlock_irqrestore(&state->card->lock, flags); |
1031 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") ); | 1032 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") ); |
1032 | } | 1033 | } |
1033 | 1034 | ||
1034 | static void start_adc(struct cs_state *state) | 1035 | static void start_adc(struct cs_state *state) |
1035 | { | 1036 | { |
1036 | struct dmabuf *dmabuf = &state->dmabuf; | 1037 | struct dmabuf *dmabuf = &state->dmabuf; |
1037 | struct cs_card *card = state->card; | 1038 | struct cs_card *card = state->card; |
1038 | unsigned long flags; | 1039 | unsigned long flags; |
1039 | unsigned int tmp; | 1040 | unsigned int tmp; |
1040 | 1041 | ||
1041 | spin_lock_irqsave(&card->lock, flags); | 1042 | spin_lock_irqsave(&card->lock, flags); |
1042 | if (!(dmabuf->enable & ADC_RUNNING) && | 1043 | if (!(dmabuf->enable & ADC_RUNNING) && |
1043 | ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) | 1044 | ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) |
1044 | && dmabuf->ready) && | 1045 | && dmabuf->ready) && |
1045 | ((card->pm.flags & CS46XX_PM_IDLE) || | 1046 | ((card->pm.flags & CS46XX_PM_IDLE) || |
1046 | (card->pm.flags & CS46XX_PM_RESUMED)) ) | 1047 | (card->pm.flags & CS46XX_PM_RESUMED)) ) |
1047 | { | 1048 | { |
1048 | dmabuf->enable |= ADC_RUNNING; | 1049 | dmabuf->enable |= ADC_RUNNING; |
1049 | cs_set_divisor(dmabuf); | 1050 | cs_set_divisor(dmabuf); |
1050 | tmp = cs461x_peek(card, BA1_CCTL); | 1051 | tmp = cs461x_peek(card, BA1_CCTL); |
1051 | tmp &= 0xFFFF0000; | 1052 | tmp &= 0xFFFF0000; |
1052 | tmp |= card->cctl; | 1053 | tmp |= card->cctl; |
1053 | CS_DBGOUT(CS_FUNCTION, 2, printk( | 1054 | CS_DBGOUT(CS_FUNCTION, 2, printk( |
1054 | "cs46xx: start_adc() poke 0x%x \n",tmp) ); | 1055 | "cs46xx: start_adc() poke 0x%x \n",tmp) ); |
1055 | cs461x_poke(card, BA1_CCTL, tmp); | 1056 | cs461x_poke(card, BA1_CCTL, tmp); |
1056 | } | 1057 | } |
1057 | spin_unlock_irqrestore(&card->lock, flags); | 1058 | spin_unlock_irqrestore(&card->lock, flags); |
1058 | } | 1059 | } |
1059 | 1060 | ||
1060 | /* stop playback (lock held) */ | 1061 | /* stop playback (lock held) */ |
1061 | static inline void __stop_dac(struct cs_state *state) | 1062 | static inline void __stop_dac(struct cs_state *state) |
1062 | { | 1063 | { |
1063 | struct dmabuf *dmabuf = &state->dmabuf; | 1064 | struct dmabuf *dmabuf = &state->dmabuf; |
1064 | struct cs_card *card = state->card; | 1065 | struct cs_card *card = state->card; |
1065 | unsigned int tmp; | 1066 | unsigned int tmp; |
1066 | 1067 | ||
1067 | dmabuf->enable &= ~DAC_RUNNING; | 1068 | dmabuf->enable &= ~DAC_RUNNING; |
1068 | 1069 | ||
1069 | tmp=cs461x_peek(card, BA1_PCTL); | 1070 | tmp=cs461x_peek(card, BA1_PCTL); |
1070 | tmp&=0xFFFF; | 1071 | tmp&=0xFFFF; |
1071 | cs461x_poke(card, BA1_PCTL, tmp); | 1072 | cs461x_poke(card, BA1_PCTL, tmp); |
1072 | } | 1073 | } |
1073 | 1074 | ||
1074 | static void stop_dac(struct cs_state *state) | 1075 | static void stop_dac(struct cs_state *state) |
1075 | { | 1076 | { |
1076 | unsigned long flags; | 1077 | unsigned long flags; |
1077 | 1078 | ||
1078 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") ); | 1079 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") ); |
1079 | spin_lock_irqsave(&state->card->lock, flags); | 1080 | spin_lock_irqsave(&state->card->lock, flags); |
1080 | __stop_dac(state); | 1081 | __stop_dac(state); |
1081 | spin_unlock_irqrestore(&state->card->lock, flags); | 1082 | spin_unlock_irqrestore(&state->card->lock, flags); |
1082 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") ); | 1083 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") ); |
1083 | } | 1084 | } |
1084 | 1085 | ||
1085 | static void start_dac(struct cs_state *state) | 1086 | static void start_dac(struct cs_state *state) |
1086 | { | 1087 | { |
1087 | struct dmabuf *dmabuf = &state->dmabuf; | 1088 | struct dmabuf *dmabuf = &state->dmabuf; |
1088 | struct cs_card *card = state->card; | 1089 | struct cs_card *card = state->card; |
1089 | unsigned long flags; | 1090 | unsigned long flags; |
1090 | int tmp; | 1091 | int tmp; |
1091 | 1092 | ||
1092 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") ); | 1093 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") ); |
1093 | spin_lock_irqsave(&card->lock, flags); | 1094 | spin_lock_irqsave(&card->lock, flags); |
1094 | if (!(dmabuf->enable & DAC_RUNNING) && | 1095 | if (!(dmabuf->enable & DAC_RUNNING) && |
1095 | ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) && | 1096 | ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) && |
1096 | ((card->pm.flags & CS46XX_PM_IDLE) || | 1097 | ((card->pm.flags & CS46XX_PM_IDLE) || |
1097 | (card->pm.flags & CS46XX_PM_RESUMED)) ) | 1098 | (card->pm.flags & CS46XX_PM_RESUMED)) ) |
1098 | { | 1099 | { |
1099 | dmabuf->enable |= DAC_RUNNING; | 1100 | dmabuf->enable |= DAC_RUNNING; |
1100 | tmp = cs461x_peek(card, BA1_PCTL); | 1101 | tmp = cs461x_peek(card, BA1_PCTL); |
1101 | tmp &= 0xFFFF; | 1102 | tmp &= 0xFFFF; |
1102 | tmp |= card->pctl; | 1103 | tmp |= card->pctl; |
1103 | CS_DBGOUT(CS_PARMS, 6, printk( | 1104 | CS_DBGOUT(CS_PARMS, 6, printk( |
1104 | "cs46xx: start_dac() poke card=%p tmp=0x%.08x addr=%p \n", | 1105 | "cs46xx: start_dac() poke card=%p tmp=0x%.08x addr=%p \n", |
1105 | card, (unsigned)tmp, | 1106 | card, (unsigned)tmp, |
1106 | card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) ); | 1107 | card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) ); |
1107 | cs461x_poke(card, BA1_PCTL, tmp); | 1108 | cs461x_poke(card, BA1_PCTL, tmp); |
1108 | } | 1109 | } |
1109 | spin_unlock_irqrestore(&card->lock, flags); | 1110 | spin_unlock_irqrestore(&card->lock, flags); |
1110 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") ); | 1111 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") ); |
1111 | } | 1112 | } |
1112 | 1113 | ||
1113 | #define DMABUF_MINORDER 1 | 1114 | #define DMABUF_MINORDER 1 |
1114 | 1115 | ||
1115 | /* | 1116 | /* |
1116 | * allocate DMA buffer, playback and recording buffers are separate. | 1117 | * allocate DMA buffer, playback and recording buffers are separate. |
1117 | */ | 1118 | */ |
1118 | static int alloc_dmabuf(struct cs_state *state) | 1119 | static int alloc_dmabuf(struct cs_state *state) |
1119 | { | 1120 | { |
1120 | 1121 | ||
1121 | struct cs_card *card=state->card; | 1122 | struct cs_card *card=state->card; |
1122 | struct dmabuf *dmabuf = &state->dmabuf; | 1123 | struct dmabuf *dmabuf = &state->dmabuf; |
1123 | void *rawbuf = NULL; | 1124 | void *rawbuf = NULL; |
1124 | void *tmpbuff = NULL; | 1125 | void *tmpbuff = NULL; |
1125 | int order; | 1126 | int order; |
1126 | struct page *map, *mapend; | 1127 | struct page *map, *mapend; |
1127 | unsigned long df; | 1128 | unsigned long df; |
1128 | 1129 | ||
1129 | dmabuf->ready = dmabuf->mapped = 0; | 1130 | dmabuf->ready = dmabuf->mapped = 0; |
1130 | dmabuf->SGok = 0; | 1131 | dmabuf->SGok = 0; |
1131 | /* | 1132 | /* |
1132 | * check for order within limits, but do not overwrite value. | 1133 | * check for order within limits, but do not overwrite value. |
1133 | */ | 1134 | */ |
1134 | if ((defaultorder > 1) && (defaultorder < 12)) | 1135 | if ((defaultorder > 1) && (defaultorder < 12)) |
1135 | df = defaultorder; | 1136 | df = defaultorder; |
1136 | else | 1137 | else |
1137 | df = 2; | 1138 | df = 2; |
1138 | 1139 | ||
1139 | for (order = df; order >= DMABUF_MINORDER; order--) | 1140 | for (order = df; order >= DMABUF_MINORDER; order--) |
1140 | if ((rawbuf = (void *)pci_alloc_consistent( | 1141 | if ((rawbuf = (void *)pci_alloc_consistent( |
1141 | card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr))) | 1142 | card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr))) |
1142 | break; | 1143 | break; |
1143 | if (!rawbuf) { | 1144 | if (!rawbuf) { |
1144 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR | 1145 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR |
1145 | "cs46xx: alloc_dmabuf(): unable to allocate rawbuf\n")); | 1146 | "cs46xx: alloc_dmabuf(): unable to allocate rawbuf\n")); |
1146 | return -ENOMEM; | 1147 | return -ENOMEM; |
1147 | } | 1148 | } |
1148 | dmabuf->buforder = order; | 1149 | dmabuf->buforder = order; |
1149 | dmabuf->rawbuf = rawbuf; | 1150 | dmabuf->rawbuf = rawbuf; |
1150 | // Now mark the pages as reserved; otherwise the | 1151 | // Now mark the pages as reserved; otherwise the |
1151 | // remap_pfn_range() in cs46xx_mmap doesn't work. | 1152 | // remap_pfn_range() in cs46xx_mmap doesn't work. |
1152 | // 1. get index to last page in mem_map array for rawbuf. | 1153 | // 1. get index to last page in mem_map array for rawbuf. |
1153 | mapend = virt_to_page(dmabuf->rawbuf + | 1154 | mapend = virt_to_page(dmabuf->rawbuf + |
1154 | (PAGE_SIZE << dmabuf->buforder) - 1); | 1155 | (PAGE_SIZE << dmabuf->buforder) - 1); |
1155 | 1156 | ||
1156 | // 2. mark each physical page in range as 'reserved'. | 1157 | // 2. mark each physical page in range as 'reserved'. |
1157 | for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++) | 1158 | for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++) |
1158 | cs4x_mem_map_reserve(map); | 1159 | cs4x_mem_map_reserve(map); |
1159 | 1160 | ||
1160 | CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: alloc_dmabuf(): allocated %ld (order = %d) bytes at %p\n", | 1161 | CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: alloc_dmabuf(): allocated %ld (order = %d) bytes at %p\n", |
1161 | PAGE_SIZE << order, order, rawbuf) ); | 1162 | PAGE_SIZE << order, order, rawbuf) ); |
1162 | 1163 | ||
1163 | /* | 1164 | /* |
1164 | * only allocate the conversion buffer for the ADC | 1165 | * only allocate the conversion buffer for the ADC |
1165 | */ | 1166 | */ |
1166 | if (dmabuf->type == CS_TYPE_DAC) { | 1167 | if (dmabuf->type == CS_TYPE_DAC) { |
1167 | dmabuf->tmpbuff = NULL; | 1168 | dmabuf->tmpbuff = NULL; |
1168 | dmabuf->buforder_tmpbuff = 0; | 1169 | dmabuf->buforder_tmpbuff = 0; |
1169 | return 0; | 1170 | return 0; |
1170 | } | 1171 | } |
1171 | /* | 1172 | /* |
1172 | * now the temp buffer for 16/8 conversions | 1173 | * now the temp buffer for 16/8 conversions |
1173 | */ | 1174 | */ |
1174 | 1175 | ||
1175 | tmpbuff = (void *) pci_alloc_consistent( | 1176 | tmpbuff = (void *) pci_alloc_consistent( |
1176 | card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr_tmpbuff); | 1177 | card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr_tmpbuff); |
1177 | 1178 | ||
1178 | if (!tmpbuff) | 1179 | if (!tmpbuff) |
1179 | return -ENOMEM; | 1180 | return -ENOMEM; |
1180 | CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: allocated %ld (order = %d) bytes at %p\n", | 1181 | CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: allocated %ld (order = %d) bytes at %p\n", |
1181 | PAGE_SIZE << order, order, tmpbuff) ); | 1182 | PAGE_SIZE << order, order, tmpbuff) ); |
1182 | 1183 | ||
1183 | dmabuf->tmpbuff = tmpbuff; | 1184 | dmabuf->tmpbuff = tmpbuff; |
1184 | dmabuf->buforder_tmpbuff = order; | 1185 | dmabuf->buforder_tmpbuff = order; |
1185 | 1186 | ||
1186 | // Now mark the pages as reserved; otherwise the | 1187 | // Now mark the pages as reserved; otherwise the |
1187 | // remap_pfn_range() in cs46xx_mmap doesn't work. | 1188 | // remap_pfn_range() in cs46xx_mmap doesn't work. |
1188 | // 1. get index to last page in mem_map array for rawbuf. | 1189 | // 1. get index to last page in mem_map array for rawbuf. |
1189 | mapend = virt_to_page(dmabuf->tmpbuff + | 1190 | mapend = virt_to_page(dmabuf->tmpbuff + |
1190 | (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1); | 1191 | (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1); |
1191 | 1192 | ||
1192 | // 2. mark each physical page in range as 'reserved'. | 1193 | // 2. mark each physical page in range as 'reserved'. |
1193 | for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++) | 1194 | for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++) |
1194 | cs4x_mem_map_reserve(map); | 1195 | cs4x_mem_map_reserve(map); |
1195 | return 0; | 1196 | return 0; |
1196 | } | 1197 | } |
1197 | 1198 | ||
1198 | /* free DMA buffer */ | 1199 | /* free DMA buffer */ |
1199 | static void dealloc_dmabuf(struct cs_state *state) | 1200 | static void dealloc_dmabuf(struct cs_state *state) |
1200 | { | 1201 | { |
1201 | struct dmabuf *dmabuf = &state->dmabuf; | 1202 | struct dmabuf *dmabuf = &state->dmabuf; |
1202 | struct page *map, *mapend; | 1203 | struct page *map, *mapend; |
1203 | 1204 | ||
1204 | if (dmabuf->rawbuf) { | 1205 | if (dmabuf->rawbuf) { |
1205 | // Undo prog_dmabuf()'s marking the pages as reserved | 1206 | // Undo prog_dmabuf()'s marking the pages as reserved |
1206 | mapend = virt_to_page(dmabuf->rawbuf + | 1207 | mapend = virt_to_page(dmabuf->rawbuf + |
1207 | (PAGE_SIZE << dmabuf->buforder) - 1); | 1208 | (PAGE_SIZE << dmabuf->buforder) - 1); |
1208 | for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++) | 1209 | for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++) |
1209 | cs4x_mem_map_unreserve(map); | 1210 | cs4x_mem_map_unreserve(map); |
1210 | free_dmabuf(state->card, dmabuf); | 1211 | free_dmabuf(state->card, dmabuf); |
1211 | } | 1212 | } |
1212 | 1213 | ||
1213 | if (dmabuf->tmpbuff) { | 1214 | if (dmabuf->tmpbuff) { |
1214 | // Undo prog_dmabuf()'s marking the pages as reserved | 1215 | // Undo prog_dmabuf()'s marking the pages as reserved |
1215 | mapend = virt_to_page(dmabuf->tmpbuff + | 1216 | mapend = virt_to_page(dmabuf->tmpbuff + |
1216 | (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1); | 1217 | (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1); |
1217 | for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++) | 1218 | for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++) |
1218 | cs4x_mem_map_unreserve(map); | 1219 | cs4x_mem_map_unreserve(map); |
1219 | free_dmabuf2(state->card, dmabuf); | 1220 | free_dmabuf2(state->card, dmabuf); |
1220 | } | 1221 | } |
1221 | 1222 | ||
1222 | dmabuf->rawbuf = NULL; | 1223 | dmabuf->rawbuf = NULL; |
1223 | dmabuf->tmpbuff = NULL; | 1224 | dmabuf->tmpbuff = NULL; |
1224 | dmabuf->mapped = dmabuf->ready = 0; | 1225 | dmabuf->mapped = dmabuf->ready = 0; |
1225 | dmabuf->SGok = 0; | 1226 | dmabuf->SGok = 0; |
1226 | } | 1227 | } |
1227 | 1228 | ||
1228 | static int __prog_dmabuf(struct cs_state *state) | 1229 | static int __prog_dmabuf(struct cs_state *state) |
1229 | { | 1230 | { |
1230 | struct dmabuf *dmabuf = &state->dmabuf; | 1231 | struct dmabuf *dmabuf = &state->dmabuf; |
1231 | unsigned long flags; | 1232 | unsigned long flags; |
1232 | unsigned long allocated_pages, allocated_bytes; | 1233 | unsigned long allocated_pages, allocated_bytes; |
1233 | unsigned long tmp1, tmp2, fmt=0; | 1234 | unsigned long tmp1, tmp2, fmt=0; |
1234 | unsigned long *ptmp = (unsigned long *) dmabuf->pbuf; | 1235 | unsigned long *ptmp = (unsigned long *) dmabuf->pbuf; |
1235 | unsigned long SGarray[9], nSGpages=0; | 1236 | unsigned long SGarray[9], nSGpages=0; |
1236 | int ret; | 1237 | int ret; |
1237 | 1238 | ||
1238 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n")); | 1239 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n")); |
1239 | /* | 1240 | /* |
1240 | * check for CAPTURE and use only non-sg for initial release | 1241 | * check for CAPTURE and use only non-sg for initial release |
1241 | */ | 1242 | */ |
1242 | if (dmabuf->type == CS_TYPE_ADC) { | 1243 | if (dmabuf->type == CS_TYPE_ADC) { |
1243 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n")); | 1244 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n")); |
1244 | /* | 1245 | /* |
1245 | * add in non-sg support for capture. | 1246 | * add in non-sg support for capture. |
1246 | */ | 1247 | */ |
1247 | spin_lock_irqsave(&state->card->lock, flags); | 1248 | spin_lock_irqsave(&state->card->lock, flags); |
1248 | /* add code to reset the rawbuf memory. TRW */ | 1249 | /* add code to reset the rawbuf memory. TRW */ |
1249 | resync_dma_ptrs(state); | 1250 | resync_dma_ptrs(state); |
1250 | dmabuf->total_bytes = dmabuf->blocks = 0; | 1251 | dmabuf->total_bytes = dmabuf->blocks = 0; |
1251 | dmabuf->count = dmabuf->error = dmabuf->underrun = 0; | 1252 | dmabuf->count = dmabuf->error = dmabuf->underrun = 0; |
1252 | 1253 | ||
1253 | dmabuf->SGok = 0; | 1254 | dmabuf->SGok = 0; |
1254 | 1255 | ||
1255 | spin_unlock_irqrestore(&state->card->lock, flags); | 1256 | spin_unlock_irqrestore(&state->card->lock, flags); |
1256 | 1257 | ||
1257 | /* allocate DMA buffer if not allocated yet */ | 1258 | /* allocate DMA buffer if not allocated yet */ |
1258 | if (!dmabuf->rawbuf || !dmabuf->tmpbuff) | 1259 | if (!dmabuf->rawbuf || !dmabuf->tmpbuff) |
1259 | if ((ret = alloc_dmabuf(state))) | 1260 | if ((ret = alloc_dmabuf(state))) |
1260 | return ret; | 1261 | return ret; |
1261 | /* | 1262 | /* |
1262 | * static image only supports 16Bit signed, stereo - hard code fmt | 1263 | * static image only supports 16Bit signed, stereo - hard code fmt |
1263 | */ | 1264 | */ |
1264 | fmt = CS_FMT_16BIT | CS_FMT_STEREO; | 1265 | fmt = CS_FMT_16BIT | CS_FMT_STEREO; |
1265 | 1266 | ||
1266 | dmabuf->numfrag = 2; | 1267 | dmabuf->numfrag = 2; |
1267 | dmabuf->fragsize = 2048; | 1268 | dmabuf->fragsize = 2048; |
1268 | dmabuf->fragsamples = 2048 >> sample_shift[fmt]; | 1269 | dmabuf->fragsamples = 2048 >> sample_shift[fmt]; |
1269 | dmabuf->dmasize = 4096; | 1270 | dmabuf->dmasize = 4096; |
1270 | dmabuf->fragshift = 11; | 1271 | dmabuf->fragshift = 11; |
1271 | 1272 | ||
1272 | memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80, | 1273 | memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80, |
1273 | dmabuf->dmasize); | 1274 | dmabuf->dmasize); |
1274 | memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80, | 1275 | memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80, |
1275 | PAGE_SIZE<<dmabuf->buforder_tmpbuff); | 1276 | PAGE_SIZE<<dmabuf->buforder_tmpbuff); |
1276 | 1277 | ||
1277 | /* | 1278 | /* |
1278 | * Now set up the ring | 1279 | * Now set up the ring |
1279 | */ | 1280 | */ |
1280 | 1281 | ||
1281 | spin_lock_irqsave(&state->card->lock, flags); | 1282 | spin_lock_irqsave(&state->card->lock, flags); |
1282 | cs_rec_setup(state); | 1283 | cs_rec_setup(state); |
1283 | spin_unlock_irqrestore(&state->card->lock, flags); | 1284 | spin_unlock_irqrestore(&state->card->lock, flags); |
1284 | 1285 | ||
1285 | /* set the ready flag for the dma buffer */ | 1286 | /* set the ready flag for the dma buffer */ |
1286 | dmabuf->ready = 1; | 1287 | dmabuf->ready = 1; |
1287 | 1288 | ||
1288 | CS_DBGOUT(CS_PARMS, 4, printk( | 1289 | CS_DBGOUT(CS_PARMS, 4, printk( |
1289 | "cs46xx: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d " | 1290 | "cs46xx: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d " |
1290 | "fragsize=%d dmasize=%d\n", | 1291 | "fragsize=%d dmasize=%d\n", |
1291 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, | 1292 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, |
1292 | dmabuf->fragsize, dmabuf->dmasize) ); | 1293 | dmabuf->fragsize, dmabuf->dmasize) ); |
1293 | 1294 | ||
1294 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n")); | 1295 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n")); |
1295 | return 0; | 1296 | return 0; |
1296 | } else if (dmabuf->type == CS_TYPE_DAC) { | 1297 | } else if (dmabuf->type == CS_TYPE_DAC) { |
1297 | /* | 1298 | /* |
1298 | * Must be DAC | 1299 | * Must be DAC |
1299 | */ | 1300 | */ |
1300 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n")); | 1301 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n")); |
1301 | spin_lock_irqsave(&state->card->lock, flags); | 1302 | spin_lock_irqsave(&state->card->lock, flags); |
1302 | resync_dma_ptrs(state); | 1303 | resync_dma_ptrs(state); |
1303 | dmabuf->total_bytes = dmabuf->blocks = 0; | 1304 | dmabuf->total_bytes = dmabuf->blocks = 0; |
1304 | dmabuf->count = dmabuf->error = dmabuf->underrun = 0; | 1305 | dmabuf->count = dmabuf->error = dmabuf->underrun = 0; |
1305 | 1306 | ||
1306 | dmabuf->SGok = 0; | 1307 | dmabuf->SGok = 0; |
1307 | 1308 | ||
1308 | spin_unlock_irqrestore(&state->card->lock, flags); | 1309 | spin_unlock_irqrestore(&state->card->lock, flags); |
1309 | 1310 | ||
1310 | /* allocate DMA buffer if not allocated yet */ | 1311 | /* allocate DMA buffer if not allocated yet */ |
1311 | if (!dmabuf->rawbuf) | 1312 | if (!dmabuf->rawbuf) |
1312 | if ((ret = alloc_dmabuf(state))) | 1313 | if ((ret = alloc_dmabuf(state))) |
1313 | return ret; | 1314 | return ret; |
1314 | 1315 | ||
1315 | allocated_pages = 1 << dmabuf->buforder; | 1316 | allocated_pages = 1 << dmabuf->buforder; |
1316 | allocated_bytes = allocated_pages*PAGE_SIZE; | 1317 | allocated_bytes = allocated_pages*PAGE_SIZE; |
1317 | 1318 | ||
1318 | if (allocated_pages < 2) { | 1319 | if (allocated_pages < 2) { |
1319 | CS_DBGOUT(CS_FUNCTION, 4, printk( | 1320 | CS_DBGOUT(CS_FUNCTION, 4, printk( |
1320 | "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n", | 1321 | "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n", |
1321 | (unsigned)allocated_pages)); | 1322 | (unsigned)allocated_pages)); |
1322 | return -ENOMEM; | 1323 | return -ENOMEM; |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | /* Use all the pages allocated, fragsize 4k. */ | 1326 | /* Use all the pages allocated, fragsize 4k. */ |
1326 | /* Use 'pbuf' for S/G page map table. */ | 1327 | /* Use 'pbuf' for S/G page map table. */ |
1327 | dmabuf->SGok = 1; /* Use S/G. */ | 1328 | dmabuf->SGok = 1; /* Use S/G. */ |
1328 | 1329 | ||
1329 | nSGpages = allocated_bytes/4096; /* S/G pages always 4k. */ | 1330 | nSGpages = allocated_bytes/4096; /* S/G pages always 4k. */ |
1330 | 1331 | ||
1331 | /* Set up S/G variables. */ | 1332 | /* Set up S/G variables. */ |
1332 | *ptmp = virt_to_bus(dmabuf->rawbuf); | 1333 | *ptmp = virt_to_bus(dmabuf->rawbuf); |
1333 | *(ptmp + 1) = 0x00000008; | 1334 | *(ptmp + 1) = 0x00000008; |
1334 | for (tmp1 = 1; tmp1 < nSGpages; tmp1++) { | 1335 | for (tmp1 = 1; tmp1 < nSGpages; tmp1++) { |
1335 | *(ptmp + 2 * tmp1) = virt_to_bus((dmabuf->rawbuf) + 4096 * tmp1); | 1336 | *(ptmp + 2 * tmp1) = virt_to_bus((dmabuf->rawbuf) + 4096 * tmp1); |
1336 | if (tmp1 == nSGpages - 1) | 1337 | if (tmp1 == nSGpages - 1) |
1337 | tmp2 = 0xbfff0000; | 1338 | tmp2 = 0xbfff0000; |
1338 | else | 1339 | else |
1339 | tmp2 = 0x80000000 + 8 * (tmp1 + 1); | 1340 | tmp2 = 0x80000000 + 8 * (tmp1 + 1); |
1340 | *(ptmp + 2 * tmp1 + 1) = tmp2; | 1341 | *(ptmp + 2 * tmp1 + 1) = tmp2; |
1341 | } | 1342 | } |
1342 | SGarray[0] = 0x82c0200d; | 1343 | SGarray[0] = 0x82c0200d; |
1343 | SGarray[1] = 0xffff0000; | 1344 | SGarray[1] = 0xffff0000; |
1344 | SGarray[2] = *ptmp; | 1345 | SGarray[2] = *ptmp; |
1345 | SGarray[3] = 0x00010600; | 1346 | SGarray[3] = 0x00010600; |
1346 | SGarray[4] = *(ptmp+2); | 1347 | SGarray[4] = *(ptmp+2); |
1347 | SGarray[5] = 0x80000010; | 1348 | SGarray[5] = 0x80000010; |
1348 | SGarray[6] = *ptmp; | 1349 | SGarray[6] = *ptmp; |
1349 | SGarray[7] = *(ptmp+2); | 1350 | SGarray[7] = *(ptmp+2); |
1350 | SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10; | 1351 | SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10; |
1351 | 1352 | ||
1352 | if (dmabuf->SGok) { | 1353 | if (dmabuf->SGok) { |
1353 | dmabuf->numfrag = nSGpages; | 1354 | dmabuf->numfrag = nSGpages; |
1354 | dmabuf->fragsize = 4096; | 1355 | dmabuf->fragsize = 4096; |
1355 | dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt]; | 1356 | dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt]; |
1356 | dmabuf->fragshift = 12; | 1357 | dmabuf->fragshift = 12; |
1357 | dmabuf->dmasize = dmabuf->numfrag * 4096; | 1358 | dmabuf->dmasize = dmabuf->numfrag * 4096; |
1358 | } else { | 1359 | } else { |
1359 | SGarray[0] = 0xf2c0000f; | 1360 | SGarray[0] = 0xf2c0000f; |
1360 | SGarray[1] = 0x00000200; | 1361 | SGarray[1] = 0x00000200; |
1361 | SGarray[2] = 0; | 1362 | SGarray[2] = 0; |
1362 | SGarray[3] = 0x00010600; | 1363 | SGarray[3] = 0x00010600; |
1363 | SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0; | 1364 | SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0; |
1364 | dmabuf->numfrag = 2; | 1365 | dmabuf->numfrag = 2; |
1365 | dmabuf->fragsize = 2048; | 1366 | dmabuf->fragsize = 2048; |
1366 | dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt]; | 1367 | dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt]; |
1367 | dmabuf->dmasize = 4096; | 1368 | dmabuf->dmasize = 4096; |
1368 | dmabuf->fragshift = 11; | 1369 | dmabuf->fragshift = 11; |
1369 | } | 1370 | } |
1370 | for (tmp1 = 0; tmp1 < sizeof(SGarray) / 4; tmp1++) | 1371 | for (tmp1 = 0; tmp1 < sizeof(SGarray) / 4; tmp1++) |
1371 | cs461x_poke(state->card, BA1_PDTC+tmp1 * 4, SGarray[tmp1]); | 1372 | cs461x_poke(state->card, BA1_PDTC+tmp1 * 4, SGarray[tmp1]); |
1372 | 1373 | ||
1373 | memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, | 1374 | memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, |
1374 | dmabuf->dmasize); | 1375 | dmabuf->dmasize); |
1375 | 1376 | ||
1376 | /* | 1377 | /* |
1377 | * Now set up the ring | 1378 | * Now set up the ring |
1378 | */ | 1379 | */ |
1379 | 1380 | ||
1380 | spin_lock_irqsave(&state->card->lock, flags); | 1381 | spin_lock_irqsave(&state->card->lock, flags); |
1381 | cs_play_setup(state); | 1382 | cs_play_setup(state); |
1382 | spin_unlock_irqrestore(&state->card->lock, flags); | 1383 | spin_unlock_irqrestore(&state->card->lock, flags); |
1383 | 1384 | ||
1384 | /* set the ready flag for the dma buffer */ | 1385 | /* set the ready flag for the dma buffer */ |
1385 | dmabuf->ready = 1; | 1386 | dmabuf->ready = 1; |
1386 | 1387 | ||
1387 | CS_DBGOUT(CS_PARMS, 4, printk( | 1388 | CS_DBGOUT(CS_PARMS, 4, printk( |
1388 | "cs46xx: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d " | 1389 | "cs46xx: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d " |
1389 | "fragsize=%d dmasize=%d\n", | 1390 | "fragsize=%d dmasize=%d\n", |
1390 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, | 1391 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, |
1391 | dmabuf->fragsize, dmabuf->dmasize) ); | 1392 | dmabuf->fragsize, dmabuf->dmasize) ); |
1392 | 1393 | ||
1393 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n")); | 1394 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n")); |
1394 | return 0; | 1395 | return 0; |
1395 | } else { | 1396 | } else { |
1396 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n", | 1397 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n", |
1397 | dmabuf->type)); | 1398 | dmabuf->type)); |
1398 | } | 1399 | } |
1399 | return 1; | 1400 | return 1; |
1400 | } | 1401 | } |
1401 | 1402 | ||
1402 | static int prog_dmabuf(struct cs_state *state) | 1403 | static int prog_dmabuf(struct cs_state *state) |
1403 | { | 1404 | { |
1404 | int ret; | 1405 | int ret; |
1405 | 1406 | ||
1406 | mutex_lock(&state->sem); | 1407 | mutex_lock(&state->sem); |
1407 | ret = __prog_dmabuf(state); | 1408 | ret = __prog_dmabuf(state); |
1408 | mutex_unlock(&state->sem); | 1409 | mutex_unlock(&state->sem); |
1409 | 1410 | ||
1410 | return ret; | 1411 | return ret; |
1411 | } | 1412 | } |
1412 | 1413 | ||
1413 | static void cs_clear_tail(struct cs_state *state) | 1414 | static void cs_clear_tail(struct cs_state *state) |
1414 | { | 1415 | { |
1415 | } | 1416 | } |
1416 | 1417 | ||
1417 | static int drain_dac(struct cs_state *state, int nonblock) | 1418 | static int drain_dac(struct cs_state *state, int nonblock) |
1418 | { | 1419 | { |
1419 | DECLARE_WAITQUEUE(wait, current); | 1420 | DECLARE_WAITQUEUE(wait, current); |
1420 | struct dmabuf *dmabuf = &state->dmabuf; | 1421 | struct dmabuf *dmabuf = &state->dmabuf; |
1421 | struct cs_card *card=state->card; | 1422 | struct cs_card *card=state->card; |
1422 | unsigned long flags; | 1423 | unsigned long flags; |
1423 | unsigned long tmo; | 1424 | unsigned long tmo; |
1424 | int count; | 1425 | int count; |
1425 | 1426 | ||
1426 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()+ \n")); | 1427 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()+ \n")); |
1427 | if (dmabuf->mapped || !dmabuf->ready) | 1428 | if (dmabuf->mapped || !dmabuf->ready) |
1428 | { | 1429 | { |
1429 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0, not ready\n")); | 1430 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0, not ready\n")); |
1430 | return 0; | 1431 | return 0; |
1431 | } | 1432 | } |
1432 | 1433 | ||
1433 | add_wait_queue(&dmabuf->wait, &wait); | 1434 | add_wait_queue(&dmabuf->wait, &wait); |
1434 | for (;;) { | 1435 | for (;;) { |
1435 | /* It seems that we have to set the current state to TASK_INTERRUPTIBLE | 1436 | /* It seems that we have to set the current state to TASK_INTERRUPTIBLE |
1436 | every time to make the process really go to sleep */ | 1437 | every time to make the process really go to sleep */ |
1437 | current->state = TASK_INTERRUPTIBLE; | 1438 | current->state = TASK_INTERRUPTIBLE; |
1438 | 1439 | ||
1439 | spin_lock_irqsave(&state->card->lock, flags); | 1440 | spin_lock_irqsave(&state->card->lock, flags); |
1440 | count = dmabuf->count; | 1441 | count = dmabuf->count; |
1441 | spin_unlock_irqrestore(&state->card->lock, flags); | 1442 | spin_unlock_irqrestore(&state->card->lock, flags); |
1442 | 1443 | ||
1443 | if (count <= 0) | 1444 | if (count <= 0) |
1444 | break; | 1445 | break; |
1445 | 1446 | ||
1446 | if (signal_pending(current)) | 1447 | if (signal_pending(current)) |
1447 | break; | 1448 | break; |
1448 | 1449 | ||
1449 | if (nonblock) { | 1450 | if (nonblock) { |
1450 | remove_wait_queue(&dmabuf->wait, &wait); | 1451 | remove_wait_queue(&dmabuf->wait, &wait); |
1451 | current->state = TASK_RUNNING; | 1452 | current->state = TASK_RUNNING; |
1452 | return -EBUSY; | 1453 | return -EBUSY; |
1453 | } | 1454 | } |
1454 | 1455 | ||
1455 | tmo = (dmabuf->dmasize * HZ) / dmabuf->rate; | 1456 | tmo = (dmabuf->dmasize * HZ) / dmabuf->rate; |
1456 | tmo >>= sample_shift[dmabuf->fmt]; | 1457 | tmo >>= sample_shift[dmabuf->fmt]; |
1457 | tmo += (2048*HZ)/dmabuf->rate; | 1458 | tmo += (2048*HZ)/dmabuf->rate; |
1458 | 1459 | ||
1459 | if (!schedule_timeout(tmo ? tmo : 1) && tmo){ | 1460 | if (!schedule_timeout(tmo ? tmo : 1) && tmo){ |
1460 | printk(KERN_ERR "cs46xx: drain_dac, dma timeout? %d\n", count); | 1461 | printk(KERN_ERR "cs46xx: drain_dac, dma timeout? %d\n", count); |
1461 | break; | 1462 | break; |
1462 | } | 1463 | } |
1463 | } | 1464 | } |
1464 | remove_wait_queue(&dmabuf->wait, &wait); | 1465 | remove_wait_queue(&dmabuf->wait, &wait); |
1465 | current->state = TASK_RUNNING; | 1466 | current->state = TASK_RUNNING; |
1466 | if (signal_pending(current)) { | 1467 | if (signal_pending(current)) { |
1467 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n")); | 1468 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n")); |
1468 | /* | 1469 | /* |
1469 | * set to silence and let that clear the fifos. | 1470 | * set to silence and let that clear the fifos. |
1470 | */ | 1471 | */ |
1471 | cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC); | 1472 | cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC); |
1472 | return -ERESTARTSYS; | 1473 | return -ERESTARTSYS; |
1473 | } | 1474 | } |
1474 | 1475 | ||
1475 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0\n")); | 1476 | CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0\n")); |
1476 | return 0; | 1477 | return 0; |
1477 | } | 1478 | } |
1478 | 1479 | ||
1479 | 1480 | ||
1480 | /* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */ | 1481 | /* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */ |
1481 | static void cs_update_ptr(struct cs_card *card, int wake) | 1482 | static void cs_update_ptr(struct cs_card *card, int wake) |
1482 | { | 1483 | { |
1483 | struct cs_state *state; | 1484 | struct cs_state *state; |
1484 | struct dmabuf *dmabuf; | 1485 | struct dmabuf *dmabuf; |
1485 | unsigned hwptr; | 1486 | unsigned hwptr; |
1486 | int diff; | 1487 | int diff; |
1487 | 1488 | ||
1488 | /* error handling and process wake up for ADC */ | 1489 | /* error handling and process wake up for ADC */ |
1489 | state = card->states[0]; | 1490 | state = card->states[0]; |
1490 | if (state) { | 1491 | if (state) { |
1491 | dmabuf = &state->dmabuf; | 1492 | dmabuf = &state->dmabuf; |
1492 | if (dmabuf->enable & ADC_RUNNING) { | 1493 | if (dmabuf->enable & ADC_RUNNING) { |
1493 | /* update hardware pointer */ | 1494 | /* update hardware pointer */ |
1494 | hwptr = cs_get_dma_addr(state); | 1495 | hwptr = cs_get_dma_addr(state); |
1495 | 1496 | ||
1496 | diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; | 1497 | diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; |
1497 | CS_DBGOUT(CS_PARMS, 9, printk( | 1498 | CS_DBGOUT(CS_PARMS, 9, printk( |
1498 | "cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n", | 1499 | "cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n", |
1499 | hwptr,diff) ); | 1500 | hwptr,diff) ); |
1500 | dmabuf->hwptr = hwptr; | 1501 | dmabuf->hwptr = hwptr; |
1501 | dmabuf->total_bytes += diff; | 1502 | dmabuf->total_bytes += diff; |
1502 | dmabuf->count += diff; | 1503 | dmabuf->count += diff; |
1503 | if (dmabuf->count > dmabuf->dmasize) | 1504 | if (dmabuf->count > dmabuf->dmasize) |
1504 | dmabuf->count = dmabuf->dmasize; | 1505 | dmabuf->count = dmabuf->dmasize; |
1505 | 1506 | ||
1506 | if (dmabuf->mapped) { | 1507 | if (dmabuf->mapped) { |
1507 | if (wake && dmabuf->count >= (signed)dmabuf->fragsize) | 1508 | if (wake && dmabuf->count >= (signed)dmabuf->fragsize) |
1508 | wake_up(&dmabuf->wait); | 1509 | wake_up(&dmabuf->wait); |
1509 | } else { | 1510 | } else { |
1510 | if (wake && dmabuf->count > 0) | 1511 | if (wake && dmabuf->count > 0) |
1511 | wake_up(&dmabuf->wait); | 1512 | wake_up(&dmabuf->wait); |
1512 | } | 1513 | } |
1513 | } | 1514 | } |
1514 | } | 1515 | } |
1515 | 1516 | ||
1516 | /* | 1517 | /* |
1517 | * Now the DAC | 1518 | * Now the DAC |
1518 | */ | 1519 | */ |
1519 | state = card->states[1]; | 1520 | state = card->states[1]; |
1520 | if (state) { | 1521 | if (state) { |
1521 | dmabuf = &state->dmabuf; | 1522 | dmabuf = &state->dmabuf; |
1522 | /* error handling and process wake up for DAC */ | 1523 | /* error handling and process wake up for DAC */ |
1523 | if (dmabuf->enable & DAC_RUNNING) { | 1524 | if (dmabuf->enable & DAC_RUNNING) { |
1524 | /* update hardware pointer */ | 1525 | /* update hardware pointer */ |
1525 | hwptr = cs_get_dma_addr(state); | 1526 | hwptr = cs_get_dma_addr(state); |
1526 | 1527 | ||
1527 | diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; | 1528 | diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; |
1528 | CS_DBGOUT(CS_PARMS, 9, printk( | 1529 | CS_DBGOUT(CS_PARMS, 9, printk( |
1529 | "cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n", | 1530 | "cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n", |
1530 | hwptr,diff) ); | 1531 | hwptr,diff) ); |
1531 | dmabuf->hwptr = hwptr; | 1532 | dmabuf->hwptr = hwptr; |
1532 | dmabuf->total_bytes += diff; | 1533 | dmabuf->total_bytes += diff; |
1533 | if (dmabuf->mapped) { | 1534 | if (dmabuf->mapped) { |
1534 | dmabuf->count += diff; | 1535 | dmabuf->count += diff; |
1535 | if (wake && dmabuf->count >= (signed)dmabuf->fragsize) | 1536 | if (wake && dmabuf->count >= (signed)dmabuf->fragsize) |
1536 | wake_up(&dmabuf->wait); | 1537 | wake_up(&dmabuf->wait); |
1537 | /* | 1538 | /* |
1538 | * other drivers use fragsize, but don't see any sense | 1539 | * other drivers use fragsize, but don't see any sense |
1539 | * in that, since dmasize is the buffer asked for | 1540 | * in that, since dmasize is the buffer asked for |
1540 | * via mmap. | 1541 | * via mmap. |
1541 | */ | 1542 | */ |
1542 | if (dmabuf->count > dmabuf->dmasize) | 1543 | if (dmabuf->count > dmabuf->dmasize) |
1543 | dmabuf->count &= dmabuf->dmasize-1; | 1544 | dmabuf->count &= dmabuf->dmasize-1; |
1544 | } else { | 1545 | } else { |
1545 | dmabuf->count -= diff; | 1546 | dmabuf->count -= diff; |
1546 | /* | 1547 | /* |
1547 | * backfill with silence and clear out the last | 1548 | * backfill with silence and clear out the last |
1548 | * "diff" number of bytes. | 1549 | * "diff" number of bytes. |
1549 | */ | 1550 | */ |
1550 | if (hwptr >= diff) { | 1551 | if (hwptr >= diff) { |
1551 | memset(dmabuf->rawbuf + hwptr - diff, | 1552 | memset(dmabuf->rawbuf + hwptr - diff, |
1552 | (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff); | 1553 | (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff); |
1553 | } else { | 1554 | } else { |
1554 | memset(dmabuf->rawbuf, | 1555 | memset(dmabuf->rawbuf, |
1555 | (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, | 1556 | (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, |
1556 | (unsigned)hwptr); | 1557 | (unsigned)hwptr); |
1557 | memset((char *)dmabuf->rawbuf + | 1558 | memset((char *)dmabuf->rawbuf + |
1558 | dmabuf->dmasize + hwptr - diff, | 1559 | dmabuf->dmasize + hwptr - diff, |
1559 | (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, | 1560 | (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, |
1560 | diff - hwptr); | 1561 | diff - hwptr); |
1561 | } | 1562 | } |
1562 | 1563 | ||
1563 | if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { | 1564 | if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { |
1564 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO | 1565 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO |
1565 | "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n", | 1566 | "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n", |
1566 | dmabuf->count)); | 1567 | dmabuf->count)); |
1567 | /* | 1568 | /* |
1568 | * buffer underrun or buffer overrun, reset the | 1569 | * buffer underrun or buffer overrun, reset the |
1569 | * count of bytes written back to 0. | 1570 | * count of bytes written back to 0. |
1570 | */ | 1571 | */ |
1571 | if (dmabuf->count < 0) | 1572 | if (dmabuf->count < 0) |
1572 | dmabuf->underrun = 1; | 1573 | dmabuf->underrun = 1; |
1573 | dmabuf->count = 0; | 1574 | dmabuf->count = 0; |
1574 | dmabuf->error++; | 1575 | dmabuf->error++; |
1575 | } | 1576 | } |
1576 | if (wake && dmabuf->count < (signed)dmabuf->dmasize / 2) | 1577 | if (wake && dmabuf->count < (signed)dmabuf->dmasize / 2) |
1577 | wake_up(&dmabuf->wait); | 1578 | wake_up(&dmabuf->wait); |
1578 | } | 1579 | } |
1579 | } | 1580 | } |
1580 | } | 1581 | } |
1581 | } | 1582 | } |
1582 | 1583 | ||
1583 | 1584 | ||
1584 | /* hold spinlock for the following! */ | 1585 | /* hold spinlock for the following! */ |
1585 | static void cs_handle_midi(struct cs_card *card) | 1586 | static void cs_handle_midi(struct cs_card *card) |
1586 | { | 1587 | { |
1587 | unsigned char ch; | 1588 | unsigned char ch; |
1588 | int wake; | 1589 | int wake; |
1589 | unsigned temp1; | 1590 | unsigned temp1; |
1590 | 1591 | ||
1591 | wake = 0; | 1592 | wake = 0; |
1592 | while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_RBE)) { | 1593 | while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_RBE)) { |
1593 | ch = cs461x_peekBA0(card, BA0_MIDRP); | 1594 | ch = cs461x_peekBA0(card, BA0_MIDRP); |
1594 | if (card->midi.icnt < CS_MIDIINBUF) { | 1595 | if (card->midi.icnt < CS_MIDIINBUF) { |
1595 | card->midi.ibuf[card->midi.iwr] = ch; | 1596 | card->midi.ibuf[card->midi.iwr] = ch; |
1596 | card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF; | 1597 | card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF; |
1597 | card->midi.icnt++; | 1598 | card->midi.icnt++; |
1598 | } | 1599 | } |
1599 | wake = 1; | 1600 | wake = 1; |
1600 | } | 1601 | } |
1601 | if (wake) | 1602 | if (wake) |
1602 | wake_up(&card->midi.iwait); | 1603 | wake_up(&card->midi.iwait); |
1603 | wake = 0; | 1604 | wake = 0; |
1604 | while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) { | 1605 | while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) { |
1605 | temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff; | 1606 | temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff; |
1606 | cs461x_pokeBA0(card, BA0_MIDWP,temp1); | 1607 | cs461x_pokeBA0(card, BA0_MIDWP,temp1); |
1607 | card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF; | 1608 | card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF; |
1608 | card->midi.ocnt--; | 1609 | card->midi.ocnt--; |
1609 | if (card->midi.ocnt < CS_MIDIOUTBUF-16) | 1610 | if (card->midi.ocnt < CS_MIDIOUTBUF-16) |
1610 | wake = 1; | 1611 | wake = 1; |
1611 | } | 1612 | } |
1612 | if (wake) | 1613 | if (wake) |
1613 | wake_up(&card->midi.owait); | 1614 | wake_up(&card->midi.owait); |
1614 | } | 1615 | } |
1615 | 1616 | ||
1616 | static irqreturn_t cs_interrupt(int irq, void *dev_id) | 1617 | static irqreturn_t cs_interrupt(int irq, void *dev_id) |
1617 | { | 1618 | { |
1618 | struct cs_card *card = (struct cs_card *)dev_id; | 1619 | struct cs_card *card = (struct cs_card *)dev_id; |
1619 | /* Single channel card */ | 1620 | /* Single channel card */ |
1620 | struct cs_state *recstate = card->channel[0].state; | 1621 | struct cs_state *recstate = card->channel[0].state; |
1621 | struct cs_state *playstate = card->channel[1].state; | 1622 | struct cs_state *playstate = card->channel[1].state; |
1622 | u32 status; | 1623 | u32 status; |
1623 | 1624 | ||
1624 | CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n")); | 1625 | CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n")); |
1625 | 1626 | ||
1626 | spin_lock(&card->lock); | 1627 | spin_lock(&card->lock); |
1627 | 1628 | ||
1628 | status = cs461x_peekBA0(card, BA0_HISR); | 1629 | status = cs461x_peekBA0(card, BA0_HISR); |
1629 | 1630 | ||
1630 | if ((status & 0x7fffffff) == 0) { | 1631 | if ((status & 0x7fffffff) == 0) { |
1631 | cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV); | 1632 | cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV); |
1632 | spin_unlock(&card->lock); | 1633 | spin_unlock(&card->lock); |
1633 | return IRQ_HANDLED; /* Might be IRQ_NONE.. */ | 1634 | return IRQ_HANDLED; /* Might be IRQ_NONE.. */ |
1634 | } | 1635 | } |
1635 | 1636 | ||
1636 | /* | 1637 | /* |
1637 | * check for playback or capture interrupt only | 1638 | * check for playback or capture interrupt only |
1638 | */ | 1639 | */ |
1639 | if (((status & HISR_VC0) && playstate && playstate->dmabuf.ready) || | 1640 | if (((status & HISR_VC0) && playstate && playstate->dmabuf.ready) || |
1640 | (((status & HISR_VC1) && recstate && recstate->dmabuf.ready))) { | 1641 | (((status & HISR_VC1) && recstate && recstate->dmabuf.ready))) { |
1641 | CS_DBGOUT(CS_INTERRUPT, 8, printk( | 1642 | CS_DBGOUT(CS_INTERRUPT, 8, printk( |
1642 | "cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status)); | 1643 | "cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status)); |
1643 | cs_update_ptr(card, CS_TRUE); | 1644 | cs_update_ptr(card, CS_TRUE); |
1644 | } | 1645 | } |
1645 | 1646 | ||
1646 | if (status & HISR_MIDI) | 1647 | if (status & HISR_MIDI) |
1647 | cs_handle_midi(card); | 1648 | cs_handle_midi(card); |
1648 | 1649 | ||
1649 | /* clear 'em */ | 1650 | /* clear 'em */ |
1650 | cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV); | 1651 | cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV); |
1651 | spin_unlock(&card->lock); | 1652 | spin_unlock(&card->lock); |
1652 | CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n")); | 1653 | CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n")); |
1653 | return IRQ_HANDLED; | 1654 | return IRQ_HANDLED; |
1654 | } | 1655 | } |
1655 | 1656 | ||
1656 | 1657 | ||
1657 | /**********************************************************************/ | 1658 | /**********************************************************************/ |
1658 | 1659 | ||
1659 | static ssize_t cs_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 1660 | static ssize_t cs_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
1660 | { | 1661 | { |
1661 | struct cs_card *card = file->private_data; | 1662 | struct cs_card *card = file->private_data; |
1662 | ssize_t ret; | 1663 | ssize_t ret; |
1663 | unsigned long flags; | 1664 | unsigned long flags; |
1664 | unsigned ptr; | 1665 | unsigned ptr; |
1665 | int cnt; | 1666 | int cnt; |
1666 | 1667 | ||
1667 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 1668 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
1668 | return -EFAULT; | 1669 | return -EFAULT; |
1669 | ret = 0; | 1670 | ret = 0; |
1670 | while (count > 0) { | 1671 | while (count > 0) { |
1671 | spin_lock_irqsave(&card->lock, flags); | 1672 | spin_lock_irqsave(&card->lock, flags); |
1672 | ptr = card->midi.ird; | 1673 | ptr = card->midi.ird; |
1673 | cnt = CS_MIDIINBUF - ptr; | 1674 | cnt = CS_MIDIINBUF - ptr; |
1674 | if (card->midi.icnt < cnt) | 1675 | if (card->midi.icnt < cnt) |
1675 | cnt = card->midi.icnt; | 1676 | cnt = card->midi.icnt; |
1676 | spin_unlock_irqrestore(&card->lock, flags); | 1677 | spin_unlock_irqrestore(&card->lock, flags); |
1677 | if (cnt > count) | 1678 | if (cnt > count) |
1678 | cnt = count; | 1679 | cnt = count; |
1679 | if (cnt <= 0) { | 1680 | if (cnt <= 0) { |
1680 | if (file->f_flags & O_NONBLOCK) | 1681 | if (file->f_flags & O_NONBLOCK) |
1681 | return ret ? ret : -EAGAIN; | 1682 | return ret ? ret : -EAGAIN; |
1682 | interruptible_sleep_on(&card->midi.iwait); | 1683 | interruptible_sleep_on(&card->midi.iwait); |
1683 | if (signal_pending(current)) | 1684 | if (signal_pending(current)) |
1684 | return ret ? ret : -ERESTARTSYS; | 1685 | return ret ? ret : -ERESTARTSYS; |
1685 | continue; | 1686 | continue; |
1686 | } | 1687 | } |
1687 | if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt)) | 1688 | if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt)) |
1688 | return ret ? ret : -EFAULT; | 1689 | return ret ? ret : -EFAULT; |
1689 | ptr = (ptr + cnt) % CS_MIDIINBUF; | 1690 | ptr = (ptr + cnt) % CS_MIDIINBUF; |
1690 | spin_lock_irqsave(&card->lock, flags); | 1691 | spin_lock_irqsave(&card->lock, flags); |
1691 | card->midi.ird = ptr; | 1692 | card->midi.ird = ptr; |
1692 | card->midi.icnt -= cnt; | 1693 | card->midi.icnt -= cnt; |
1693 | spin_unlock_irqrestore(&card->lock, flags); | 1694 | spin_unlock_irqrestore(&card->lock, flags); |
1694 | count -= cnt; | 1695 | count -= cnt; |
1695 | buffer += cnt; | 1696 | buffer += cnt; |
1696 | ret += cnt; | 1697 | ret += cnt; |
1697 | } | 1698 | } |
1698 | return ret; | 1699 | return ret; |
1699 | } | 1700 | } |
1700 | 1701 | ||
1701 | 1702 | ||
1702 | static ssize_t cs_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 1703 | static ssize_t cs_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
1703 | { | 1704 | { |
1704 | struct cs_card *card = file->private_data; | 1705 | struct cs_card *card = file->private_data; |
1705 | ssize_t ret; | 1706 | ssize_t ret; |
1706 | unsigned long flags; | 1707 | unsigned long flags; |
1707 | unsigned ptr; | 1708 | unsigned ptr; |
1708 | int cnt; | 1709 | int cnt; |
1709 | 1710 | ||
1710 | if (!access_ok(VERIFY_READ, buffer, count)) | 1711 | if (!access_ok(VERIFY_READ, buffer, count)) |
1711 | return -EFAULT; | 1712 | return -EFAULT; |
1712 | ret = 0; | 1713 | ret = 0; |
1713 | while (count > 0) { | 1714 | while (count > 0) { |
1714 | spin_lock_irqsave(&card->lock, flags); | 1715 | spin_lock_irqsave(&card->lock, flags); |
1715 | ptr = card->midi.owr; | 1716 | ptr = card->midi.owr; |
1716 | cnt = CS_MIDIOUTBUF - ptr; | 1717 | cnt = CS_MIDIOUTBUF - ptr; |
1717 | if (card->midi.ocnt + cnt > CS_MIDIOUTBUF) | 1718 | if (card->midi.ocnt + cnt > CS_MIDIOUTBUF) |
1718 | cnt = CS_MIDIOUTBUF - card->midi.ocnt; | 1719 | cnt = CS_MIDIOUTBUF - card->midi.ocnt; |
1719 | if (cnt <= 0) | 1720 | if (cnt <= 0) |
1720 | cs_handle_midi(card); | 1721 | cs_handle_midi(card); |
1721 | spin_unlock_irqrestore(&card->lock, flags); | 1722 | spin_unlock_irqrestore(&card->lock, flags); |
1722 | if (cnt > count) | 1723 | if (cnt > count) |
1723 | cnt = count; | 1724 | cnt = count; |
1724 | if (cnt <= 0) { | 1725 | if (cnt <= 0) { |
1725 | if (file->f_flags & O_NONBLOCK) | 1726 | if (file->f_flags & O_NONBLOCK) |
1726 | return ret ? ret : -EAGAIN; | 1727 | return ret ? ret : -EAGAIN; |
1727 | interruptible_sleep_on(&card->midi.owait); | 1728 | interruptible_sleep_on(&card->midi.owait); |
1728 | if (signal_pending(current)) | 1729 | if (signal_pending(current)) |
1729 | return ret ? ret : -ERESTARTSYS; | 1730 | return ret ? ret : -ERESTARTSYS; |
1730 | continue; | 1731 | continue; |
1731 | } | 1732 | } |
1732 | if (copy_from_user(card->midi.obuf + ptr, buffer, cnt)) | 1733 | if (copy_from_user(card->midi.obuf + ptr, buffer, cnt)) |
1733 | return ret ? ret : -EFAULT; | 1734 | return ret ? ret : -EFAULT; |
1734 | ptr = (ptr + cnt) % CS_MIDIOUTBUF; | 1735 | ptr = (ptr + cnt) % CS_MIDIOUTBUF; |
1735 | spin_lock_irqsave(&card->lock, flags); | 1736 | spin_lock_irqsave(&card->lock, flags); |
1736 | card->midi.owr = ptr; | 1737 | card->midi.owr = ptr; |
1737 | card->midi.ocnt += cnt; | 1738 | card->midi.ocnt += cnt; |
1738 | spin_unlock_irqrestore(&card->lock, flags); | 1739 | spin_unlock_irqrestore(&card->lock, flags); |
1739 | count -= cnt; | 1740 | count -= cnt; |
1740 | buffer += cnt; | 1741 | buffer += cnt; |
1741 | ret += cnt; | 1742 | ret += cnt; |
1742 | spin_lock_irqsave(&card->lock, flags); | 1743 | spin_lock_irqsave(&card->lock, flags); |
1743 | cs_handle_midi(card); | 1744 | cs_handle_midi(card); |
1744 | spin_unlock_irqrestore(&card->lock, flags); | 1745 | spin_unlock_irqrestore(&card->lock, flags); |
1745 | } | 1746 | } |
1746 | return ret; | 1747 | return ret; |
1747 | } | 1748 | } |
1748 | 1749 | ||
1749 | 1750 | ||
1750 | static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait) | 1751 | static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait) |
1751 | { | 1752 | { |
1752 | struct cs_card *card = file->private_data; | 1753 | struct cs_card *card = file->private_data; |
1753 | unsigned long flags; | 1754 | unsigned long flags; |
1754 | unsigned int mask = 0; | 1755 | unsigned int mask = 0; |
1755 | 1756 | ||
1756 | if (file->f_flags & FMODE_WRITE) | 1757 | if (file->f_flags & FMODE_WRITE) |
1757 | poll_wait(file, &card->midi.owait, wait); | 1758 | poll_wait(file, &card->midi.owait, wait); |
1758 | if (file->f_flags & FMODE_READ) | 1759 | if (file->f_flags & FMODE_READ) |
1759 | poll_wait(file, &card->midi.iwait, wait); | 1760 | poll_wait(file, &card->midi.iwait, wait); |
1760 | spin_lock_irqsave(&card->lock, flags); | 1761 | spin_lock_irqsave(&card->lock, flags); |
1761 | if (file->f_flags & FMODE_READ) { | 1762 | if (file->f_flags & FMODE_READ) { |
1762 | if (card->midi.icnt > 0) | 1763 | if (card->midi.icnt > 0) |
1763 | mask |= POLLIN | POLLRDNORM; | 1764 | mask |= POLLIN | POLLRDNORM; |
1764 | } | 1765 | } |
1765 | if (file->f_flags & FMODE_WRITE) { | 1766 | if (file->f_flags & FMODE_WRITE) { |
1766 | if (card->midi.ocnt < CS_MIDIOUTBUF) | 1767 | if (card->midi.ocnt < CS_MIDIOUTBUF) |
1767 | mask |= POLLOUT | POLLWRNORM; | 1768 | mask |= POLLOUT | POLLWRNORM; |
1768 | } | 1769 | } |
1769 | spin_unlock_irqrestore(&card->lock, flags); | 1770 | spin_unlock_irqrestore(&card->lock, flags); |
1770 | return mask; | 1771 | return mask; |
1771 | } | 1772 | } |
1772 | 1773 | ||
1773 | 1774 | ||
1774 | static int cs_midi_open(struct inode *inode, struct file *file) | 1775 | static int cs_midi_open(struct inode *inode, struct file *file) |
1775 | { | 1776 | { |
1776 | unsigned int minor = iminor(inode); | 1777 | unsigned int minor = iminor(inode); |
1777 | struct cs_card *card = NULL; | 1778 | struct cs_card *card = NULL; |
1778 | unsigned long flags; | 1779 | unsigned long flags; |
1779 | struct list_head *entry; | 1780 | struct list_head *entry; |
1780 | 1781 | ||
1781 | list_for_each(entry, &cs46xx_devs) { | 1782 | list_for_each(entry, &cs46xx_devs) { |
1782 | card = list_entry(entry, struct cs_card, list); | 1783 | card = list_entry(entry, struct cs_card, list); |
1783 | if (card->dev_midi == minor) | 1784 | if (card->dev_midi == minor) |
1784 | break; | 1785 | break; |
1785 | } | 1786 | } |
1786 | 1787 | ||
1787 | if (entry == &cs46xx_devs) | 1788 | if (entry == &cs46xx_devs) |
1788 | return -ENODEV; | 1789 | return -ENODEV; |
1789 | if (!card) { | 1790 | if (!card) { |
1790 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO | 1791 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO |
1791 | "cs46xx: cs46xx_midi_open(): Error - unable to find card struct\n")); | 1792 | "cs46xx: cs46xx_midi_open(): Error - unable to find card struct\n")); |
1792 | return -ENODEV; | 1793 | return -ENODEV; |
1793 | } | 1794 | } |
1794 | 1795 | ||
1795 | file->private_data = card; | 1796 | file->private_data = card; |
1796 | /* wait for device to become free */ | 1797 | /* wait for device to become free */ |
1797 | mutex_lock(&card->midi.open_mutex); | 1798 | mutex_lock(&card->midi.open_mutex); |
1798 | while (card->midi.open_mode & file->f_mode) { | 1799 | while (card->midi.open_mode & file->f_mode) { |
1799 | if (file->f_flags & O_NONBLOCK) { | 1800 | if (file->f_flags & O_NONBLOCK) { |
1800 | mutex_unlock(&card->midi.open_mutex); | 1801 | mutex_unlock(&card->midi.open_mutex); |
1801 | return -EBUSY; | 1802 | return -EBUSY; |
1802 | } | 1803 | } |
1803 | mutex_unlock(&card->midi.open_mutex); | 1804 | mutex_unlock(&card->midi.open_mutex); |
1804 | interruptible_sleep_on(&card->midi.open_wait); | 1805 | interruptible_sleep_on(&card->midi.open_wait); |
1805 | if (signal_pending(current)) | 1806 | if (signal_pending(current)) |
1806 | return -ERESTARTSYS; | 1807 | return -ERESTARTSYS; |
1807 | mutex_lock(&card->midi.open_mutex); | 1808 | mutex_lock(&card->midi.open_mutex); |
1808 | } | 1809 | } |
1809 | spin_lock_irqsave(&card->midi.lock, flags); | 1810 | spin_lock_irqsave(&card->midi.lock, flags); |
1810 | if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) { | 1811 | if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) { |
1811 | card->midi.ird = card->midi.iwr = card->midi.icnt = 0; | 1812 | card->midi.ird = card->midi.iwr = card->midi.icnt = 0; |
1812 | card->midi.ord = card->midi.owr = card->midi.ocnt = 0; | 1813 | card->midi.ord = card->midi.owr = card->midi.ocnt = 0; |
1813 | card->midi.ird = card->midi.iwr = card->midi.icnt = 0; | 1814 | card->midi.ird = card->midi.iwr = card->midi.icnt = 0; |
1814 | cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f); /* Enable xmit, rcv. */ | 1815 | cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f); /* Enable xmit, rcv. */ |
1815 | cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM); /* Enable interrupts */ | 1816 | cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM); /* Enable interrupts */ |
1816 | } | 1817 | } |
1817 | if (file->f_mode & FMODE_READ) | 1818 | if (file->f_mode & FMODE_READ) |
1818 | card->midi.ird = card->midi.iwr = card->midi.icnt = 0; | 1819 | card->midi.ird = card->midi.iwr = card->midi.icnt = 0; |
1819 | if (file->f_mode & FMODE_WRITE) | 1820 | if (file->f_mode & FMODE_WRITE) |
1820 | card->midi.ord = card->midi.owr = card->midi.ocnt = 0; | 1821 | card->midi.ord = card->midi.owr = card->midi.ocnt = 0; |
1821 | spin_unlock_irqrestore(&card->midi.lock, flags); | 1822 | spin_unlock_irqrestore(&card->midi.lock, flags); |
1822 | card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE)); | 1823 | card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE)); |
1823 | mutex_unlock(&card->midi.open_mutex); | 1824 | mutex_unlock(&card->midi.open_mutex); |
1824 | return 0; | 1825 | return 0; |
1825 | } | 1826 | } |
1826 | 1827 | ||
1827 | 1828 | ||
1828 | static int cs_midi_release(struct inode *inode, struct file *file) | 1829 | static int cs_midi_release(struct inode *inode, struct file *file) |
1829 | { | 1830 | { |
1830 | struct cs_card *card = file->private_data; | 1831 | struct cs_card *card = file->private_data; |
1831 | DECLARE_WAITQUEUE(wait, current); | 1832 | DECLARE_WAITQUEUE(wait, current); |
1832 | unsigned long flags; | 1833 | unsigned long flags; |
1833 | unsigned count, tmo; | 1834 | unsigned count, tmo; |
1834 | 1835 | ||
1835 | if (file->f_mode & FMODE_WRITE) { | 1836 | if (file->f_mode & FMODE_WRITE) { |
1836 | current->state = TASK_INTERRUPTIBLE; | 1837 | current->state = TASK_INTERRUPTIBLE; |
1837 | add_wait_queue(&card->midi.owait, &wait); | 1838 | add_wait_queue(&card->midi.owait, &wait); |
1838 | for (;;) { | 1839 | for (;;) { |
1839 | spin_lock_irqsave(&card->midi.lock, flags); | 1840 | spin_lock_irqsave(&card->midi.lock, flags); |
1840 | count = card->midi.ocnt; | 1841 | count = card->midi.ocnt; |
1841 | spin_unlock_irqrestore(&card->midi.lock, flags); | 1842 | spin_unlock_irqrestore(&card->midi.lock, flags); |
1842 | if (count <= 0) | 1843 | if (count <= 0) |
1843 | break; | 1844 | break; |
1844 | if (signal_pending(current)) | 1845 | if (signal_pending(current)) |
1845 | break; | 1846 | break; |
1846 | if (file->f_flags & O_NONBLOCK) | 1847 | if (file->f_flags & O_NONBLOCK) |
1847 | break; | 1848 | break; |
1848 | tmo = (count * HZ) / 3100; | 1849 | tmo = (count * HZ) / 3100; |
1849 | if (!schedule_timeout(tmo ? : 1) && tmo) | 1850 | if (!schedule_timeout(tmo ? : 1) && tmo) |
1850 | printk(KERN_DEBUG "cs46xx: midi timed out??\n"); | 1851 | printk(KERN_DEBUG "cs46xx: midi timed out??\n"); |
1851 | } | 1852 | } |
1852 | remove_wait_queue(&card->midi.owait, &wait); | 1853 | remove_wait_queue(&card->midi.owait, &wait); |
1853 | current->state = TASK_RUNNING; | 1854 | current->state = TASK_RUNNING; |
1854 | } | 1855 | } |
1855 | mutex_lock(&card->midi.open_mutex); | 1856 | mutex_lock(&card->midi.open_mutex); |
1856 | card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE))); | 1857 | card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE))); |
1857 | mutex_unlock(&card->midi.open_mutex); | 1858 | mutex_unlock(&card->midi.open_mutex); |
1858 | wake_up(&card->midi.open_wait); | 1859 | wake_up(&card->midi.open_wait); |
1859 | return 0; | 1860 | return 0; |
1860 | } | 1861 | } |
1861 | 1862 | ||
1862 | /* | 1863 | /* |
1863 | * Midi file operations struct. | 1864 | * Midi file operations struct. |
1864 | */ | 1865 | */ |
1865 | static /*const*/ struct file_operations cs_midi_fops = { | 1866 | static /*const*/ struct file_operations cs_midi_fops = { |
1866 | CS_OWNER CS_THIS_MODULE | 1867 | CS_OWNER CS_THIS_MODULE |
1867 | .llseek = no_llseek, | 1868 | .llseek = no_llseek, |
1868 | .read = cs_midi_read, | 1869 | .read = cs_midi_read, |
1869 | .write = cs_midi_write, | 1870 | .write = cs_midi_write, |
1870 | .poll = cs_midi_poll, | 1871 | .poll = cs_midi_poll, |
1871 | .open = cs_midi_open, | 1872 | .open = cs_midi_open, |
1872 | .release = cs_midi_release, | 1873 | .release = cs_midi_release, |
1873 | }; | 1874 | }; |
1874 | 1875 | ||
1875 | /* | 1876 | /* |
1876 | * | 1877 | * |
1877 | * CopySamples copies 16-bit stereo signed samples from the source to the | 1878 | * CopySamples copies 16-bit stereo signed samples from the source to the |
1878 | * destination, possibly converting down to unsigned 8-bit and/or mono. | 1879 | * destination, possibly converting down to unsigned 8-bit and/or mono. |
1879 | * count specifies the number of output bytes to write. | 1880 | * count specifies the number of output bytes to write. |
1880 | * | 1881 | * |
1881 | * Arguments: | 1882 | * Arguments: |
1882 | * | 1883 | * |
1883 | * dst - Pointer to a destination buffer. | 1884 | * dst - Pointer to a destination buffer. |
1884 | * src - Pointer to a source buffer | 1885 | * src - Pointer to a source buffer |
1885 | * count - The number of bytes to copy into the destination buffer. | 1886 | * count - The number of bytes to copy into the destination buffer. |
1886 | * fmt - CS_FMT_16BIT and/or CS_FMT_STEREO bits | 1887 | * fmt - CS_FMT_16BIT and/or CS_FMT_STEREO bits |
1887 | * dmabuf - pointer to the dma buffer structure | 1888 | * dmabuf - pointer to the dma buffer structure |
1888 | * | 1889 | * |
1889 | * NOTES: only call this routine if the output desired is not 16 Signed Stereo | 1890 | * NOTES: only call this routine if the output desired is not 16 Signed Stereo |
1890 | * | 1891 | * |
1891 | * | 1892 | * |
1892 | */ | 1893 | */ |
1893 | static void CopySamples(char *dst, char *src, int count, unsigned fmt, | 1894 | static void CopySamples(char *dst, char *src, int count, unsigned fmt, |
1894 | struct dmabuf *dmabuf) | 1895 | struct dmabuf *dmabuf) |
1895 | { | 1896 | { |
1896 | s32 s32AudioSample; | 1897 | s32 s32AudioSample; |
1897 | s16 *psSrc = (s16 *)src; | 1898 | s16 *psSrc = (s16 *)src; |
1898 | s16 *psDst = (s16 *)dst; | 1899 | s16 *psDst = (s16 *)dst; |
1899 | u8 *pucDst = (u8 *)dst; | 1900 | u8 *pucDst = (u8 *)dst; |
1900 | 1901 | ||
1901 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: CopySamples()+ ") ); | 1902 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: CopySamples()+ ") ); |
1902 | CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO | 1903 | CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO |
1903 | " dst=%p src=%p count=%d fmt=0x%x\n", | 1904 | " dst=%p src=%p count=%d fmt=0x%x\n", |
1904 | dst,src,count,fmt) ); | 1905 | dst,src,count,fmt) ); |
1905 | 1906 | ||
1906 | /* | 1907 | /* |
1907 | * See if the data should be output as 8-bit unsigned stereo. | 1908 | * See if the data should be output as 8-bit unsigned stereo. |
1908 | */ | 1909 | */ |
1909 | if ((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) { | 1910 | if ((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) { |
1910 | /* | 1911 | /* |
1911 | * Convert each 16-bit signed stereo sample to 8-bit unsigned | 1912 | * Convert each 16-bit signed stereo sample to 8-bit unsigned |
1912 | * stereo using rounding. | 1913 | * stereo using rounding. |
1913 | */ | 1914 | */ |
1914 | psSrc = (s16 *)src; | 1915 | psSrc = (s16 *)src; |
1915 | count = count / 2; | 1916 | count = count / 2; |
1916 | while (count--) | 1917 | while (count--) |
1917 | *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8); | 1918 | *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8); |
1918 | } | 1919 | } |
1919 | /* | 1920 | /* |
1920 | * See if the data should be output at 8-bit unsigned mono. | 1921 | * See if the data should be output at 8-bit unsigned mono. |
1921 | */ | 1922 | */ |
1922 | else if (!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) { | 1923 | else if (!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) { |
1923 | /* | 1924 | /* |
1924 | * Convert each 16-bit signed stereo sample to 8-bit unsigned | 1925 | * Convert each 16-bit signed stereo sample to 8-bit unsigned |
1925 | * mono using averaging and rounding. | 1926 | * mono using averaging and rounding. |
1926 | */ | 1927 | */ |
1927 | psSrc = (s16 *)src; | 1928 | psSrc = (s16 *)src; |
1928 | count = count / 2; | 1929 | count = count / 2; |
1929 | while (count--) { | 1930 | while (count--) { |
1930 | s32AudioSample = ((*psSrc) + (*(psSrc + 1))) / 2 + (s32)0x80; | 1931 | s32AudioSample = ((*psSrc) + (*(psSrc + 1))) / 2 + (s32)0x80; |
1931 | if (s32AudioSample > 0x7fff) | 1932 | if (s32AudioSample > 0x7fff) |
1932 | s32AudioSample = 0x7fff; | 1933 | s32AudioSample = 0x7fff; |
1933 | *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8); | 1934 | *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8); |
1934 | psSrc += 2; | 1935 | psSrc += 2; |
1935 | } | 1936 | } |
1936 | } | 1937 | } |
1937 | /* | 1938 | /* |
1938 | * See if the data should be output at 16-bit signed mono. | 1939 | * See if the data should be output at 16-bit signed mono. |
1939 | */ | 1940 | */ |
1940 | else if (!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT)) { | 1941 | else if (!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT)) { |
1941 | /* | 1942 | /* |
1942 | * Convert each 16-bit signed stereo sample to 16-bit signed | 1943 | * Convert each 16-bit signed stereo sample to 16-bit signed |
1943 | * mono using averaging. | 1944 | * mono using averaging. |
1944 | */ | 1945 | */ |
1945 | psSrc = (s16 *)src; | 1946 | psSrc = (s16 *)src; |
1946 | count = count / 2; | 1947 | count = count / 2; |
1947 | while (count--) { | 1948 | while (count--) { |
1948 | *(psDst++) = (s16)((*psSrc) + (*(psSrc + 1))) / 2; | 1949 | *(psDst++) = (s16)((*psSrc) + (*(psSrc + 1))) / 2; |
1949 | psSrc += 2; | 1950 | psSrc += 2; |
1950 | } | 1951 | } |
1951 | } | 1952 | } |
1952 | } | 1953 | } |
1953 | 1954 | ||
1954 | /* | 1955 | /* |
1955 | * cs_copy_to_user() | 1956 | * cs_copy_to_user() |
1956 | * replacement for the standard copy_to_user, to allow for a conversion from | 1957 | * replacement for the standard copy_to_user, to allow for a conversion from |
1957 | * 16 bit to 8 bit and from stereo to mono, if the record conversion is active. | 1958 | * 16 bit to 8 bit and from stereo to mono, if the record conversion is active. |
1958 | * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo, | 1959 | * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo, |
1959 | * so we convert from any of the other format combinations. | 1960 | * so we convert from any of the other format combinations. |
1960 | */ | 1961 | */ |
1961 | static unsigned cs_copy_to_user( | 1962 | static unsigned cs_copy_to_user( |
1962 | struct cs_state *s, | 1963 | struct cs_state *s, |
1963 | void __user *dest, | 1964 | void __user *dest, |
1964 | void *hwsrc, | 1965 | void *hwsrc, |
1965 | unsigned cnt, | 1966 | unsigned cnt, |
1966 | unsigned *copied) | 1967 | unsigned *copied) |
1967 | { | 1968 | { |
1968 | struct dmabuf *dmabuf = &s->dmabuf; | 1969 | struct dmabuf *dmabuf = &s->dmabuf; |
1969 | void *src = hwsrc; /* default to the standard destination buffer addr */ | 1970 | void *src = hwsrc; /* default to the standard destination buffer addr */ |
1970 | 1971 | ||
1971 | CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO | 1972 | CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO |
1972 | "cs_copy_to_user()+ fmt=0x%x cnt=%d dest=%p\n", | 1973 | "cs_copy_to_user()+ fmt=0x%x cnt=%d dest=%p\n", |
1973 | dmabuf->fmt,(unsigned)cnt,dest) ); | 1974 | dmabuf->fmt,(unsigned)cnt,dest) ); |
1974 | 1975 | ||
1975 | if (cnt > dmabuf->dmasize) | 1976 | if (cnt > dmabuf->dmasize) |
1976 | cnt = dmabuf->dmasize; | 1977 | cnt = dmabuf->dmasize; |
1977 | if (!cnt) { | 1978 | if (!cnt) { |
1978 | *copied = 0; | 1979 | *copied = 0; |
1979 | return 0; | 1980 | return 0; |
1980 | } | 1981 | } |
1981 | if (dmabuf->divisor != 1) { | 1982 | if (dmabuf->divisor != 1) { |
1982 | if (!dmabuf->tmpbuff) { | 1983 | if (!dmabuf->tmpbuff) { |
1983 | *copied = cnt / dmabuf->divisor; | 1984 | *copied = cnt / dmabuf->divisor; |
1984 | return 0; | 1985 | return 0; |
1985 | } | 1986 | } |
1986 | 1987 | ||
1987 | CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt, | 1988 | CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt, |
1988 | dmabuf->fmt, dmabuf); | 1989 | dmabuf->fmt, dmabuf); |
1989 | src = dmabuf->tmpbuff; | 1990 | src = dmabuf->tmpbuff; |
1990 | cnt = cnt/dmabuf->divisor; | 1991 | cnt = cnt/dmabuf->divisor; |
1991 | } | 1992 | } |
1992 | if (copy_to_user(dest, src, cnt)) { | 1993 | if (copy_to_user(dest, src, cnt)) { |
1993 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR | 1994 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR |
1994 | "cs46xx: cs_copy_to_user()- fault dest=%p src=%p cnt=%d\n", | 1995 | "cs46xx: cs_copy_to_user()- fault dest=%p src=%p cnt=%d\n", |
1995 | dest,src,cnt)); | 1996 | dest,src,cnt)); |
1996 | *copied = 0; | 1997 | *copied = 0; |
1997 | return -EFAULT; | 1998 | return -EFAULT; |
1998 | } | 1999 | } |
1999 | *copied = cnt; | 2000 | *copied = cnt; |
2000 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO | 2001 | CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO |
2001 | "cs46xx: cs_copy_to_user()- copied bytes is %d \n",cnt)); | 2002 | "cs46xx: cs_copy_to_user()- copied bytes is %d \n",cnt)); |
2002 | return 0; | 2003 | return 0; |
2003 | } | 2004 | } |
2004 | 2005 | ||
2005 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to | 2006 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to |
2006 | the user's buffer. it is filled by the dma machine and drained by this loop. */ | 2007 | the user's buffer. it is filled by the dma machine and drained by this loop. */ |
2007 | static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 2008 | static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
2008 | { | 2009 | { |
2009 | struct cs_card *card = file->private_data; | 2010 | struct cs_card *card = file->private_data; |
2010 | struct cs_state *state; | 2011 | struct cs_state *state; |
2011 | DECLARE_WAITQUEUE(wait, current); | 2012 | DECLARE_WAITQUEUE(wait, current); |
2012 | struct dmabuf *dmabuf; | 2013 | struct dmabuf *dmabuf; |
2013 | ssize_t ret = 0; | 2014 | ssize_t ret = 0; |
2014 | unsigned long flags; | 2015 | unsigned long flags; |
2015 | unsigned swptr; | 2016 | unsigned swptr; |
2016 | int cnt; | 2017 | int cnt; |
2017 | unsigned copied = 0; | 2018 | unsigned copied = 0; |
2018 | 2019 | ||
2019 | CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, | 2020 | CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, |
2020 | printk("cs46xx: cs_read()+ %zd\n",count) ); | 2021 | printk("cs46xx: cs_read()+ %zd\n",count) ); |
2021 | state = card->states[0]; | 2022 | state = card->states[0]; |
2022 | if (!state) | 2023 | if (!state) |
2023 | return -ENODEV; | 2024 | return -ENODEV; |
2024 | dmabuf = &state->dmabuf; | 2025 | dmabuf = &state->dmabuf; |
2025 | 2026 | ||
2026 | if (dmabuf->mapped) | 2027 | if (dmabuf->mapped) |
2027 | return -ENXIO; | 2028 | return -ENXIO; |
2028 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 2029 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
2029 | return -EFAULT; | 2030 | return -EFAULT; |
2030 | 2031 | ||
2031 | mutex_lock(&state->sem); | 2032 | mutex_lock(&state->sem); |
2032 | if (!dmabuf->ready && (ret = __prog_dmabuf(state))) | 2033 | if (!dmabuf->ready && (ret = __prog_dmabuf(state))) |
2033 | goto out2; | 2034 | goto out2; |
2034 | 2035 | ||
2035 | add_wait_queue(&state->dmabuf.wait, &wait); | 2036 | add_wait_queue(&state->dmabuf.wait, &wait); |
2036 | while (count > 0) { | 2037 | while (count > 0) { |
2037 | while (!(card->pm.flags & CS46XX_PM_IDLE)) { | 2038 | while (!(card->pm.flags & CS46XX_PM_IDLE)) { |
2038 | schedule(); | 2039 | schedule(); |
2039 | if (signal_pending(current)) { | 2040 | if (signal_pending(current)) { |
2040 | if (!ret) | 2041 | if (!ret) |
2041 | ret = -ERESTARTSYS; | 2042 | ret = -ERESTARTSYS; |
2042 | goto out; | 2043 | goto out; |
2043 | } | 2044 | } |
2044 | } | 2045 | } |
2045 | spin_lock_irqsave(&state->card->lock, flags); | 2046 | spin_lock_irqsave(&state->card->lock, flags); |
2046 | swptr = dmabuf->swptr; | 2047 | swptr = dmabuf->swptr; |
2047 | cnt = dmabuf->dmasize - swptr; | 2048 | cnt = dmabuf->dmasize - swptr; |
2048 | if (dmabuf->count < cnt) | 2049 | if (dmabuf->count < cnt) |
2049 | cnt = dmabuf->count; | 2050 | cnt = dmabuf->count; |
2050 | if (cnt <= 0) | 2051 | if (cnt <= 0) |
2051 | __set_current_state(TASK_INTERRUPTIBLE); | 2052 | __set_current_state(TASK_INTERRUPTIBLE); |
2052 | spin_unlock_irqrestore(&state->card->lock, flags); | 2053 | spin_unlock_irqrestore(&state->card->lock, flags); |
2053 | 2054 | ||
2054 | if (cnt > (count * dmabuf->divisor)) | 2055 | if (cnt > (count * dmabuf->divisor)) |
2055 | cnt = count * dmabuf->divisor; | 2056 | cnt = count * dmabuf->divisor; |
2056 | if (cnt <= 0) { | 2057 | if (cnt <= 0) { |
2057 | /* buffer is empty, start the dma machine and wait for data to be | 2058 | /* buffer is empty, start the dma machine and wait for data to be |
2058 | recorded */ | 2059 | recorded */ |
2059 | start_adc(state); | 2060 | start_adc(state); |
2060 | if (file->f_flags & O_NONBLOCK) { | 2061 | if (file->f_flags & O_NONBLOCK) { |
2061 | if (!ret) | 2062 | if (!ret) |
2062 | ret = -EAGAIN; | 2063 | ret = -EAGAIN; |
2063 | goto out; | 2064 | goto out; |
2064 | } | 2065 | } |
2065 | mutex_unlock(&state->sem); | 2066 | mutex_unlock(&state->sem); |
2066 | schedule(); | 2067 | schedule(); |
2067 | if (signal_pending(current)) { | 2068 | if (signal_pending(current)) { |
2068 | if (!ret) | 2069 | if (!ret) |
2069 | ret = -ERESTARTSYS; | 2070 | ret = -ERESTARTSYS; |
2070 | goto out; | 2071 | goto out; |
2071 | } | 2072 | } |
2072 | mutex_lock(&state->sem); | 2073 | mutex_lock(&state->sem); |
2073 | if (dmabuf->mapped) { | 2074 | if (dmabuf->mapped) { |
2074 | if (!ret) | 2075 | if (!ret) |
2075 | ret = -ENXIO; | 2076 | ret = -ENXIO; |
2076 | goto out; | 2077 | goto out; |
2077 | } | 2078 | } |
2078 | continue; | 2079 | continue; |
2079 | } | 2080 | } |
2080 | 2081 | ||
2081 | CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO | 2082 | CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO |
2082 | "_read() copy_to cnt=%d count=%zd ", cnt,count) ); | 2083 | "_read() copy_to cnt=%d count=%zd ", cnt,count) ); |
2083 | CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO | 2084 | CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO |
2084 | " .dmasize=%d .count=%d buffer=%p ret=%zd\n", | 2085 | " .dmasize=%d .count=%d buffer=%p ret=%zd\n", |
2085 | dmabuf->dmasize,dmabuf->count,buffer,ret)); | 2086 | dmabuf->dmasize,dmabuf->count,buffer,ret)); |
2086 | 2087 | ||
2087 | if (cs_copy_to_user(state, buffer, | 2088 | if (cs_copy_to_user(state, buffer, |
2088 | (char *)dmabuf->rawbuf + swptr, cnt, &copied)) { | 2089 | (char *)dmabuf->rawbuf + swptr, cnt, &copied)) { |
2089 | if (!ret) | 2090 | if (!ret) |
2090 | ret = -EFAULT; | 2091 | ret = -EFAULT; |
2091 | goto out; | 2092 | goto out; |
2092 | } | 2093 | } |
2093 | swptr = (swptr + cnt) % dmabuf->dmasize; | 2094 | swptr = (swptr + cnt) % dmabuf->dmasize; |
2094 | spin_lock_irqsave(&card->lock, flags); | 2095 | spin_lock_irqsave(&card->lock, flags); |
2095 | dmabuf->swptr = swptr; | 2096 | dmabuf->swptr = swptr; |
2096 | dmabuf->count -= cnt; | 2097 | dmabuf->count -= cnt; |
2097 | spin_unlock_irqrestore(&card->lock, flags); | 2098 | spin_unlock_irqrestore(&card->lock, flags); |
2098 | count -= copied; | 2099 | count -= copied; |
2099 | buffer += copied; | 2100 | buffer += copied; |
2100 | ret += copied; | 2101 | ret += copied; |
2101 | start_adc(state); | 2102 | start_adc(state); |
2102 | } | 2103 | } |
2103 | out: | 2104 | out: |
2104 | remove_wait_queue(&state->dmabuf.wait, &wait); | 2105 | remove_wait_queue(&state->dmabuf.wait, &wait); |
2105 | out2: | 2106 | out2: |
2106 | mutex_unlock(&state->sem); | 2107 | mutex_unlock(&state->sem); |
2107 | set_current_state(TASK_RUNNING); | 2108 | set_current_state(TASK_RUNNING); |
2108 | CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, | 2109 | CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, |
2109 | printk("cs46xx: cs_read()- %zd\n",ret) ); | 2110 | printk("cs46xx: cs_read()- %zd\n",ret) ); |
2110 | return ret; | 2111 | return ret; |
2111 | } | 2112 | } |
2112 | 2113 | ||
2113 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to | 2114 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to |
2114 | the soundcard. it is drained by the dma machine and filled by this loop. */ | 2115 | the soundcard. it is drained by the dma machine and filled by this loop. */ |
2115 | static ssize_t cs_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 2116 | static ssize_t cs_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
2116 | { | 2117 | { |
2117 | struct cs_card *card = file->private_data; | 2118 | struct cs_card *card = file->private_data; |
2118 | struct cs_state *state; | 2119 | struct cs_state *state; |
2119 | DECLARE_WAITQUEUE(wait, current); | 2120 | DECLARE_WAITQUEUE(wait, current); |
2120 | struct dmabuf *dmabuf; | 2121 | struct dmabuf *dmabuf; |
2121 | ssize_t ret; | 2122 | ssize_t ret; |
2122 | unsigned long flags; | 2123 | unsigned long flags; |
2123 | unsigned swptr; | 2124 | unsigned swptr; |
2124 | int cnt; | 2125 | int cnt; |
2125 | 2126 | ||
2126 | CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4, | 2127 | CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4, |
2127 | printk("cs46xx: cs_write called, count = %zd\n", count) ); | 2128 | printk("cs46xx: cs_write called, count = %zd\n", count) ); |
2128 | state = card->states[1]; | 2129 | state = card->states[1]; |
2129 | if (!state) | 2130 | if (!state) |
2130 | return -ENODEV; | 2131 | return -ENODEV; |
2131 | if (!access_ok(VERIFY_READ, buffer, count)) | 2132 | if (!access_ok(VERIFY_READ, buffer, count)) |
2132 | return -EFAULT; | 2133 | return -EFAULT; |
2133 | dmabuf = &state->dmabuf; | 2134 | dmabuf = &state->dmabuf; |
2134 | 2135 | ||
2135 | mutex_lock(&state->sem); | 2136 | mutex_lock(&state->sem); |
2136 | if (dmabuf->mapped) { | 2137 | if (dmabuf->mapped) { |
2137 | ret = -ENXIO; | 2138 | ret = -ENXIO; |
2138 | goto out; | 2139 | goto out; |
2139 | } | 2140 | } |
2140 | 2141 | ||
2141 | if (!dmabuf->ready && (ret = __prog_dmabuf(state))) | 2142 | if (!dmabuf->ready && (ret = __prog_dmabuf(state))) |
2142 | goto out; | 2143 | goto out; |
2143 | add_wait_queue(&state->dmabuf.wait, &wait); | 2144 | add_wait_queue(&state->dmabuf.wait, &wait); |
2144 | ret = 0; | 2145 | ret = 0; |
2145 | /* | 2146 | /* |
2146 | * Start the loop to read from the user's buffer and write to the dma buffer. | 2147 | * Start the loop to read from the user's buffer and write to the dma buffer. |
2147 | * check for PM events and underrun/overrun in the loop. | 2148 | * check for PM events and underrun/overrun in the loop. |
2148 | */ | 2149 | */ |
2149 | while (count > 0) { | 2150 | while (count > 0) { |
2150 | while (!(card->pm.flags & CS46XX_PM_IDLE)) { | 2151 | while (!(card->pm.flags & CS46XX_PM_IDLE)) { |
2151 | schedule(); | 2152 | schedule(); |
2152 | if (signal_pending(current)) { | 2153 | if (signal_pending(current)) { |
2153 | if (!ret) | 2154 | if (!ret) |
2154 | ret = -ERESTARTSYS; | 2155 | ret = -ERESTARTSYS; |
2155 | goto out; | 2156 | goto out; |
2156 | } | 2157 | } |
2157 | } | 2158 | } |
2158 | spin_lock_irqsave(&state->card->lock, flags); | 2159 | spin_lock_irqsave(&state->card->lock, flags); |
2159 | if (dmabuf->count < 0) { | 2160 | if (dmabuf->count < 0) { |
2160 | /* buffer underrun, we are recovering from sleep_on_timeout, | 2161 | /* buffer underrun, we are recovering from sleep_on_timeout, |
2161 | resync hwptr and swptr */ | 2162 | resync hwptr and swptr */ |
2162 | dmabuf->count = 0; | 2163 | dmabuf->count = 0; |
2163 | dmabuf->swptr = dmabuf->hwptr; | 2164 | dmabuf->swptr = dmabuf->hwptr; |
2164 | } | 2165 | } |
2165 | if (dmabuf->underrun) { | 2166 | if (dmabuf->underrun) { |
2166 | dmabuf->underrun = 0; | 2167 | dmabuf->underrun = 0; |
2167 | dmabuf->hwptr = cs_get_dma_addr(state); | 2168 | dmabuf->hwptr = cs_get_dma_addr(state); |
2168 | dmabuf->swptr = dmabuf->hwptr; | 2169 | dmabuf->swptr = dmabuf->hwptr; |
2169 | } | 2170 | } |
2170 | 2171 | ||
2171 | swptr = dmabuf->swptr; | 2172 | swptr = dmabuf->swptr; |
2172 | cnt = dmabuf->dmasize - swptr; | 2173 | cnt = dmabuf->dmasize - swptr; |
2173 | if (dmabuf->count + cnt > dmabuf->dmasize) | 2174 | if (dmabuf->count + cnt > dmabuf->dmasize) |
2174 | cnt = dmabuf->dmasize - dmabuf->count; | 2175 | cnt = dmabuf->dmasize - dmabuf->count; |
2175 | if (cnt <= 0) | 2176 | if (cnt <= 0) |
2176 | __set_current_state(TASK_INTERRUPTIBLE); | 2177 | __set_current_state(TASK_INTERRUPTIBLE); |
2177 | spin_unlock_irqrestore(&state->card->lock, flags); | 2178 | spin_unlock_irqrestore(&state->card->lock, flags); |
2178 | 2179 | ||
2179 | if (cnt > count) | 2180 | if (cnt > count) |
2180 | cnt = count; | 2181 | cnt = count; |
2181 | if (cnt <= 0) { | 2182 | if (cnt <= 0) { |
2182 | /* buffer is full, start the dma machine and wait for data to be | 2183 | /* buffer is full, start the dma machine and wait for data to be |
2183 | played */ | 2184 | played */ |
2184 | start_dac(state); | 2185 | start_dac(state); |
2185 | if (file->f_flags & O_NONBLOCK) { | 2186 | if (file->f_flags & O_NONBLOCK) { |
2186 | if (!ret) | 2187 | if (!ret) |
2187 | ret = -EAGAIN; | 2188 | ret = -EAGAIN; |
2188 | goto out; | 2189 | goto out; |
2189 | } | 2190 | } |
2190 | mutex_unlock(&state->sem); | 2191 | mutex_unlock(&state->sem); |
2191 | schedule(); | 2192 | schedule(); |
2192 | if (signal_pending(current)) { | 2193 | if (signal_pending(current)) { |
2193 | if (!ret) | 2194 | if (!ret) |
2194 | ret = -ERESTARTSYS; | 2195 | ret = -ERESTARTSYS; |
2195 | goto out; | 2196 | goto out; |
2196 | } | 2197 | } |
2197 | mutex_lock(&state->sem); | 2198 | mutex_lock(&state->sem); |
2198 | if (dmabuf->mapped) { | 2199 | if (dmabuf->mapped) { |
2199 | if (!ret) | 2200 | if (!ret) |
2200 | ret = -ENXIO; | 2201 | ret = -ENXIO; |
2201 | goto out; | 2202 | goto out; |
2202 | } | 2203 | } |
2203 | continue; | 2204 | continue; |
2204 | } | 2205 | } |
2205 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { | 2206 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { |
2206 | if (!ret) | 2207 | if (!ret) |
2207 | ret = -EFAULT; | 2208 | ret = -EFAULT; |
2208 | goto out; | 2209 | goto out; |
2209 | } | 2210 | } |
2210 | spin_lock_irqsave(&state->card->lock, flags); | 2211 | spin_lock_irqsave(&state->card->lock, flags); |
2211 | swptr = (swptr + cnt) % dmabuf->dmasize; | 2212 | swptr = (swptr + cnt) % dmabuf->dmasize; |
2212 | dmabuf->swptr = swptr; | 2213 | dmabuf->swptr = swptr; |
2213 | dmabuf->count += cnt; | 2214 | dmabuf->count += cnt; |
2214 | if (dmabuf->count > dmabuf->dmasize) { | 2215 | if (dmabuf->count > dmabuf->dmasize) { |
2215 | CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk( | 2216 | CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk( |
2216 | "cs46xx: cs_write() d->count > dmasize - resetting\n")); | 2217 | "cs46xx: cs_write() d->count > dmasize - resetting\n")); |
2217 | dmabuf->count = dmabuf->dmasize; | 2218 | dmabuf->count = dmabuf->dmasize; |
2218 | } | 2219 | } |
2219 | dmabuf->endcleared = 0; | 2220 | dmabuf->endcleared = 0; |
2220 | spin_unlock_irqrestore(&state->card->lock, flags); | 2221 | spin_unlock_irqrestore(&state->card->lock, flags); |
2221 | 2222 | ||
2222 | count -= cnt; | 2223 | count -= cnt; |
2223 | buffer += cnt; | 2224 | buffer += cnt; |
2224 | ret += cnt; | 2225 | ret += cnt; |
2225 | start_dac(state); | 2226 | start_dac(state); |
2226 | } | 2227 | } |
2227 | out: | 2228 | out: |
2228 | mutex_unlock(&state->sem); | 2229 | mutex_unlock(&state->sem); |
2229 | remove_wait_queue(&state->dmabuf.wait, &wait); | 2230 | remove_wait_queue(&state->dmabuf.wait, &wait); |
2230 | set_current_state(TASK_RUNNING); | 2231 | set_current_state(TASK_RUNNING); |
2231 | 2232 | ||
2232 | CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, | 2233 | CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, |
2233 | printk("cs46xx: cs_write()- ret=%zd\n", ret)); | 2234 | printk("cs46xx: cs_write()- ret=%zd\n", ret)); |
2234 | return ret; | 2235 | return ret; |
2235 | } | 2236 | } |
2236 | 2237 | ||
2237 | static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait) | 2238 | static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait) |
2238 | { | 2239 | { |
2239 | struct cs_card *card = file->private_data; | 2240 | struct cs_card *card = file->private_data; |
2240 | struct dmabuf *dmabuf; | 2241 | struct dmabuf *dmabuf; |
2241 | struct cs_state *state; | 2242 | struct cs_state *state; |
2242 | unsigned long flags; | 2243 | unsigned long flags; |
2243 | unsigned int mask = 0; | 2244 | unsigned int mask = 0; |
2244 | 2245 | ||
2245 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n")); | 2246 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n")); |
2246 | if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) { | 2247 | if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) { |
2247 | return -EINVAL; | 2248 | return -EINVAL; |
2248 | } | 2249 | } |
2249 | if (file->f_mode & FMODE_WRITE) { | 2250 | if (file->f_mode & FMODE_WRITE) { |
2250 | state = card->states[1]; | 2251 | state = card->states[1]; |
2251 | if (state) { | 2252 | if (state) { |
2252 | dmabuf = &state->dmabuf; | 2253 | dmabuf = &state->dmabuf; |
2253 | poll_wait(file, &dmabuf->wait, wait); | 2254 | poll_wait(file, &dmabuf->wait, wait); |
2254 | } | 2255 | } |
2255 | } | 2256 | } |
2256 | if (file->f_mode & FMODE_READ) { | 2257 | if (file->f_mode & FMODE_READ) { |
2257 | state = card->states[0]; | 2258 | state = card->states[0]; |
2258 | if (state) { | 2259 | if (state) { |
2259 | dmabuf = &state->dmabuf; | 2260 | dmabuf = &state->dmabuf; |
2260 | poll_wait(file, &dmabuf->wait, wait); | 2261 | poll_wait(file, &dmabuf->wait, wait); |
2261 | } | 2262 | } |
2262 | } | 2263 | } |
2263 | 2264 | ||
2264 | spin_lock_irqsave(&card->lock, flags); | 2265 | spin_lock_irqsave(&card->lock, flags); |
2265 | cs_update_ptr(card, CS_FALSE); | 2266 | cs_update_ptr(card, CS_FALSE); |
2266 | if (file->f_mode & FMODE_READ) { | 2267 | if (file->f_mode & FMODE_READ) { |
2267 | state = card->states[0]; | 2268 | state = card->states[0]; |
2268 | if (state) { | 2269 | if (state) { |
2269 | dmabuf = &state->dmabuf; | 2270 | dmabuf = &state->dmabuf; |
2270 | if (dmabuf->count >= (signed)dmabuf->fragsize) | 2271 | if (dmabuf->count >= (signed)dmabuf->fragsize) |
2271 | mask |= POLLIN | POLLRDNORM; | 2272 | mask |= POLLIN | POLLRDNORM; |
2272 | } | 2273 | } |
2273 | } | 2274 | } |
2274 | if (file->f_mode & FMODE_WRITE) { | 2275 | if (file->f_mode & FMODE_WRITE) { |
2275 | state = card->states[1]; | 2276 | state = card->states[1]; |
2276 | if (state) { | 2277 | if (state) { |
2277 | dmabuf = &state->dmabuf; | 2278 | dmabuf = &state->dmabuf; |
2278 | if (dmabuf->mapped) { | 2279 | if (dmabuf->mapped) { |
2279 | if (dmabuf->count >= (signed)dmabuf->fragsize) | 2280 | if (dmabuf->count >= (signed)dmabuf->fragsize) |
2280 | mask |= POLLOUT | POLLWRNORM; | 2281 | mask |= POLLOUT | POLLWRNORM; |
2281 | } else { | 2282 | } else { |
2282 | if ((signed)dmabuf->dmasize >= dmabuf->count | 2283 | if ((signed)dmabuf->dmasize >= dmabuf->count |
2283 | + (signed)dmabuf->fragsize) | 2284 | + (signed)dmabuf->fragsize) |
2284 | mask |= POLLOUT | POLLWRNORM; | 2285 | mask |= POLLOUT | POLLWRNORM; |
2285 | } | 2286 | } |
2286 | } | 2287 | } |
2287 | } | 2288 | } |
2288 | spin_unlock_irqrestore(&card->lock, flags); | 2289 | spin_unlock_irqrestore(&card->lock, flags); |
2289 | 2290 | ||
2290 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()- (0x%x) \n", | 2291 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()- (0x%x) \n", |
2291 | mask)); | 2292 | mask)); |
2292 | return mask; | 2293 | return mask; |
2293 | } | 2294 | } |
2294 | 2295 | ||
2295 | /* | 2296 | /* |
2296 | * We let users mmap the ring buffer. Its not the real DMA buffer but | 2297 | * We let users mmap the ring buffer. Its not the real DMA buffer but |
2297 | * that side of the code is hidden in the IRQ handling. We do a software | 2298 | * that side of the code is hidden in the IRQ handling. We do a software |
2298 | * emulation of DMA from a 64K or so buffer into a 2K FIFO. | 2299 | * emulation of DMA from a 64K or so buffer into a 2K FIFO. |
2299 | * (the hardware probably deserves a moan here but Crystal send me nice | 2300 | * (the hardware probably deserves a moan here but Crystal send me nice |
2300 | * toys ;)). | 2301 | * toys ;)). |
2301 | */ | 2302 | */ |
2302 | 2303 | ||
2303 | static int cs_mmap(struct file *file, struct vm_area_struct *vma) | 2304 | static int cs_mmap(struct file *file, struct vm_area_struct *vma) |
2304 | { | 2305 | { |
2305 | struct cs_card *card = file->private_data; | 2306 | struct cs_card *card = file->private_data; |
2306 | struct cs_state *state; | 2307 | struct cs_state *state; |
2307 | struct dmabuf *dmabuf; | 2308 | struct dmabuf *dmabuf; |
2308 | int ret = 0; | 2309 | int ret = 0; |
2309 | unsigned long size; | 2310 | unsigned long size; |
2310 | 2311 | ||
2311 | CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=%p %s %s\n", | 2312 | CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=%p %s %s\n", |
2312 | file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "", | 2313 | file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "", |
2313 | vma->vm_flags & VM_READ ? "VM_READ" : "") ); | 2314 | vma->vm_flags & VM_READ ? "VM_READ" : "") ); |
2314 | 2315 | ||
2315 | if (vma->vm_flags & VM_WRITE) { | 2316 | if (vma->vm_flags & VM_WRITE) { |
2316 | state = card->states[1]; | 2317 | state = card->states[1]; |
2317 | if (state) { | 2318 | if (state) { |
2318 | CS_DBGOUT(CS_OPEN, 2, printk( | 2319 | CS_DBGOUT(CS_OPEN, 2, printk( |
2319 | "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") ); | 2320 | "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") ); |
2320 | if ((ret = prog_dmabuf(state)) != 0) | 2321 | if ((ret = prog_dmabuf(state)) != 0) |
2321 | return ret; | 2322 | return ret; |
2322 | } | 2323 | } |
2323 | } else if (vma->vm_flags & VM_READ) { | 2324 | } else if (vma->vm_flags & VM_READ) { |
2324 | state = card->states[0]; | 2325 | state = card->states[0]; |
2325 | if (state) { | 2326 | if (state) { |
2326 | CS_DBGOUT(CS_OPEN, 2, printk( | 2327 | CS_DBGOUT(CS_OPEN, 2, printk( |
2327 | "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") ); | 2328 | "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") ); |
2328 | if ((ret = prog_dmabuf(state)) != 0) | 2329 | if ((ret = prog_dmabuf(state)) != 0) |
2329 | return ret; | 2330 | return ret; |
2330 | } | 2331 | } |
2331 | } else { | 2332 | } else { |
2332 | CS_DBGOUT(CS_ERROR, 2, printk( | 2333 | CS_DBGOUT(CS_ERROR, 2, printk( |
2333 | "cs46xx: cs_mmap() return -EINVAL\n") ); | 2334 | "cs46xx: cs_mmap() return -EINVAL\n") ); |
2334 | return -EINVAL; | 2335 | return -EINVAL; |
2335 | } | 2336 | } |
2336 | 2337 | ||
2337 | /* | 2338 | /* |
2338 | * For now ONLY support playback, but seems like the only way to use | 2339 | * For now ONLY support playback, but seems like the only way to use |
2339 | * mmap() is to open an FD with RDWR, just read or just write access | 2340 | * mmap() is to open an FD with RDWR, just read or just write access |
2340 | * does not function, get an error back from the kernel. | 2341 | * does not function, get an error back from the kernel. |
2341 | * Also, QuakeIII opens with RDWR! So, there must be something | 2342 | * Also, QuakeIII opens with RDWR! So, there must be something |
2342 | * to needing read/write access mapping. So, allow read/write but | 2343 | * to needing read/write access mapping. So, allow read/write but |
2343 | * use the DAC only. | 2344 | * use the DAC only. |
2344 | */ | 2345 | */ |
2345 | state = card->states[1]; | 2346 | state = card->states[1]; |
2346 | if (!state) { | 2347 | if (!state) { |
2347 | ret = -EINVAL; | 2348 | ret = -EINVAL; |
2348 | goto out; | 2349 | goto out; |
2349 | } | 2350 | } |
2350 | 2351 | ||
2351 | mutex_lock(&state->sem); | 2352 | mutex_lock(&state->sem); |
2352 | dmabuf = &state->dmabuf; | 2353 | dmabuf = &state->dmabuf; |
2353 | if (cs4x_pgoff(vma) != 0) { | 2354 | if (cs4x_pgoff(vma) != 0) { |
2354 | ret = -EINVAL; | 2355 | ret = -EINVAL; |
2355 | goto out; | 2356 | goto out; |
2356 | } | 2357 | } |
2357 | size = vma->vm_end - vma->vm_start; | 2358 | size = vma->vm_end - vma->vm_start; |
2358 | 2359 | ||
2359 | CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) ); | 2360 | CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) ); |
2360 | 2361 | ||
2361 | if (size > (PAGE_SIZE << dmabuf->buforder)) { | 2362 | if (size > (PAGE_SIZE << dmabuf->buforder)) { |
2362 | ret = -EINVAL; | 2363 | ret = -EINVAL; |
2363 | goto out; | 2364 | goto out; |
2364 | } | 2365 | } |
2365 | if (remap_pfn_range(vma, vma->vm_start, | 2366 | if (remap_pfn_range(vma, vma->vm_start, |
2366 | virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT, | 2367 | virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT, |
2367 | size, vma->vm_page_prot)) { | 2368 | size, vma->vm_page_prot)) { |
2368 | ret = -EAGAIN; | 2369 | ret = -EAGAIN; |
2369 | goto out; | 2370 | goto out; |
2370 | } | 2371 | } |
2371 | dmabuf->mapped = 1; | 2372 | dmabuf->mapped = 1; |
2372 | 2373 | ||
2373 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") ); | 2374 | CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") ); |
2374 | out: | 2375 | out: |
2375 | mutex_unlock(&state->sem); | 2376 | mutex_unlock(&state->sem); |
2376 | return ret; | 2377 | return ret; |
2377 | } | 2378 | } |
2378 | 2379 | ||
2379 | static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 2380 | static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
2380 | { | 2381 | { |
2381 | struct cs_card *card = file->private_data; | 2382 | struct cs_card *card = file->private_data; |
2382 | struct cs_state *state; | 2383 | struct cs_state *state; |
2383 | struct dmabuf *dmabuf = NULL; | 2384 | struct dmabuf *dmabuf = NULL; |
2384 | unsigned long flags; | 2385 | unsigned long flags; |
2385 | audio_buf_info abinfo; | 2386 | audio_buf_info abinfo; |
2386 | count_info cinfo; | 2387 | count_info cinfo; |
2387 | int val, valsave, ret; | 2388 | int val, valsave, ret; |
2388 | int mapped = 0; | 2389 | int mapped = 0; |
2389 | void __user *argp = (void __user *)arg; | 2390 | void __user *argp = (void __user *)arg; |
2390 | int __user *p = argp; | 2391 | int __user *p = argp; |
2391 | 2392 | ||
2392 | state = card->states[0]; | 2393 | state = card->states[0]; |
2393 | if (state) { | 2394 | if (state) { |
2394 | dmabuf = &state->dmabuf; | 2395 | dmabuf = &state->dmabuf; |
2395 | mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped; | 2396 | mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped; |
2396 | } | 2397 | } |
2397 | state = card->states[1]; | 2398 | state = card->states[1]; |
2398 | if (state) { | 2399 | if (state) { |
2399 | dmabuf = &state->dmabuf; | 2400 | dmabuf = &state->dmabuf; |
2400 | mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped; | 2401 | mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped; |
2401 | } | 2402 | } |
2402 | 2403 | ||
2403 | #if CSDEBUG | 2404 | #if CSDEBUG |
2404 | printioctl(cmd); | 2405 | printioctl(cmd); |
2405 | #endif | 2406 | #endif |
2406 | 2407 | ||
2407 | switch (cmd) { | 2408 | switch (cmd) { |
2408 | case OSS_GETVERSION: | 2409 | case OSS_GETVERSION: |
2409 | return put_user(SOUND_VERSION, p); | 2410 | return put_user(SOUND_VERSION, p); |
2410 | case SNDCTL_DSP_RESET: | 2411 | case SNDCTL_DSP_RESET: |
2411 | /* FIXME: spin_lock ? */ | 2412 | /* FIXME: spin_lock ? */ |
2412 | if (file->f_mode & FMODE_WRITE) { | 2413 | if (file->f_mode & FMODE_WRITE) { |
2413 | state = card->states[1]; | 2414 | state = card->states[1]; |
2414 | if (state) { | 2415 | if (state) { |
2415 | dmabuf = &state->dmabuf; | 2416 | dmabuf = &state->dmabuf; |
2416 | stop_dac(state); | 2417 | stop_dac(state); |
2417 | synchronize_irq(card->irq); | 2418 | synchronize_irq(card->irq); |
2418 | dmabuf->ready = 0; | 2419 | dmabuf->ready = 0; |
2419 | resync_dma_ptrs(state); | 2420 | resync_dma_ptrs(state); |
2420 | dmabuf->swptr = dmabuf->hwptr = 0; | 2421 | dmabuf->swptr = dmabuf->hwptr = 0; |
2421 | dmabuf->count = dmabuf->total_bytes = 0; | 2422 | dmabuf->count = dmabuf->total_bytes = 0; |
2422 | dmabuf->blocks = 0; | 2423 | dmabuf->blocks = 0; |
2423 | dmabuf->SGok = 0; | 2424 | dmabuf->SGok = 0; |
2424 | } | 2425 | } |
2425 | } | 2426 | } |
2426 | if (file->f_mode & FMODE_READ) { | 2427 | if (file->f_mode & FMODE_READ) { |
2427 | state = card->states[0]; | 2428 | state = card->states[0]; |
2428 | if (state) { | 2429 | if (state) { |
2429 | dmabuf = &state->dmabuf; | 2430 | dmabuf = &state->dmabuf; |
2430 | stop_adc(state); | 2431 | stop_adc(state); |
2431 | synchronize_irq(card->irq); | 2432 | synchronize_irq(card->irq); |
2432 | resync_dma_ptrs(state); | 2433 | resync_dma_ptrs(state); |
2433 | dmabuf->ready = 0; | 2434 | dmabuf->ready = 0; |
2434 | dmabuf->swptr = dmabuf->hwptr = 0; | 2435 | dmabuf->swptr = dmabuf->hwptr = 0; |
2435 | dmabuf->count = dmabuf->total_bytes = 0; | 2436 | dmabuf->count = dmabuf->total_bytes = 0; |
2436 | dmabuf->blocks = 0; | 2437 | dmabuf->blocks = 0; |
2437 | dmabuf->SGok = 0; | 2438 | dmabuf->SGok = 0; |
2438 | } | 2439 | } |
2439 | } | 2440 | } |
2440 | CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") ); | 2441 | CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") ); |
2441 | return 0; | 2442 | return 0; |
2442 | case SNDCTL_DSP_SYNC: | 2443 | case SNDCTL_DSP_SYNC: |
2443 | if (file->f_mode & FMODE_WRITE) | 2444 | if (file->f_mode & FMODE_WRITE) |
2444 | return drain_dac(state, file->f_flags & O_NONBLOCK); | 2445 | return drain_dac(state, file->f_flags & O_NONBLOCK); |
2445 | return 0; | 2446 | return 0; |
2446 | case SNDCTL_DSP_SPEED: /* set sample rate */ | 2447 | case SNDCTL_DSP_SPEED: /* set sample rate */ |
2447 | if (get_user(val, p)) | 2448 | if (get_user(val, p)) |
2448 | return -EFAULT; | 2449 | return -EFAULT; |
2449 | if (val >= 0) { | 2450 | if (val >= 0) { |
2450 | if (file->f_mode & FMODE_READ) { | 2451 | if (file->f_mode & FMODE_READ) { |
2451 | state = card->states[0]; | 2452 | state = card->states[0]; |
2452 | if (state) { | 2453 | if (state) { |
2453 | dmabuf = &state->dmabuf; | 2454 | dmabuf = &state->dmabuf; |
2454 | stop_adc(state); | 2455 | stop_adc(state); |
2455 | dmabuf->ready = 0; | 2456 | dmabuf->ready = 0; |
2456 | dmabuf->SGok = 0; | 2457 | dmabuf->SGok = 0; |
2457 | cs_set_adc_rate(state, val); | 2458 | cs_set_adc_rate(state, val); |
2458 | cs_set_divisor(dmabuf); | 2459 | cs_set_divisor(dmabuf); |
2459 | } | 2460 | } |
2460 | } | 2461 | } |
2461 | if (file->f_mode & FMODE_WRITE) { | 2462 | if (file->f_mode & FMODE_WRITE) { |
2462 | state = card->states[1]; | 2463 | state = card->states[1]; |
2463 | if (state) { | 2464 | if (state) { |
2464 | dmabuf = &state->dmabuf; | 2465 | dmabuf = &state->dmabuf; |
2465 | stop_dac(state); | 2466 | stop_dac(state); |
2466 | dmabuf->ready = 0; | 2467 | dmabuf->ready = 0; |
2467 | dmabuf->SGok = 0; | 2468 | dmabuf->SGok = 0; |
2468 | cs_set_dac_rate(state, val); | 2469 | cs_set_dac_rate(state, val); |
2469 | cs_set_divisor(dmabuf); | 2470 | cs_set_divisor(dmabuf); |
2470 | } | 2471 | } |
2471 | } | 2472 | } |
2472 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( | 2473 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( |
2473 | "cs46xx: cs_ioctl() DSP_SPEED %s %s %d\n", | 2474 | "cs46xx: cs_ioctl() DSP_SPEED %s %s %d\n", |
2474 | file->f_mode & FMODE_WRITE ? "DAC" : "", | 2475 | file->f_mode & FMODE_WRITE ? "DAC" : "", |
2475 | file->f_mode & FMODE_READ ? "ADC" : "", | 2476 | file->f_mode & FMODE_READ ? "ADC" : "", |
2476 | dmabuf->rate ) ); | 2477 | dmabuf->rate ) ); |
2477 | return put_user(dmabuf->rate, p); | 2478 | return put_user(dmabuf->rate, p); |
2478 | } | 2479 | } |
2479 | return put_user(0, p); | 2480 | return put_user(0, p); |
2480 | case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ | 2481 | case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ |
2481 | if (get_user(val, p)) | 2482 | if (get_user(val, p)) |
2482 | return -EFAULT; | 2483 | return -EFAULT; |
2483 | if (file->f_mode & FMODE_WRITE) { | 2484 | if (file->f_mode & FMODE_WRITE) { |
2484 | state = card->states[1]; | 2485 | state = card->states[1]; |
2485 | if (state) { | 2486 | if (state) { |
2486 | dmabuf = &state->dmabuf; | 2487 | dmabuf = &state->dmabuf; |
2487 | stop_dac(state); | 2488 | stop_dac(state); |
2488 | dmabuf->ready = 0; | 2489 | dmabuf->ready = 0; |
2489 | dmabuf->SGok = 0; | 2490 | dmabuf->SGok = 0; |
2490 | if (val) | 2491 | if (val) |
2491 | dmabuf->fmt |= CS_FMT_STEREO; | 2492 | dmabuf->fmt |= CS_FMT_STEREO; |
2492 | else | 2493 | else |
2493 | dmabuf->fmt &= ~CS_FMT_STEREO; | 2494 | dmabuf->fmt &= ~CS_FMT_STEREO; |
2494 | cs_set_divisor(dmabuf); | 2495 | cs_set_divisor(dmabuf); |
2495 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( | 2496 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( |
2496 | "cs46xx: DSP_STEREO() DAC %s\n", | 2497 | "cs46xx: DSP_STEREO() DAC %s\n", |
2497 | (dmabuf->fmt & CS_FMT_STEREO) ? | 2498 | (dmabuf->fmt & CS_FMT_STEREO) ? |
2498 | "STEREO":"MONO") ); | 2499 | "STEREO":"MONO") ); |
2499 | } | 2500 | } |
2500 | } | 2501 | } |
2501 | if (file->f_mode & FMODE_READ) { | 2502 | if (file->f_mode & FMODE_READ) { |
2502 | state = card->states[0]; | 2503 | state = card->states[0]; |
2503 | if (state) { | 2504 | if (state) { |
2504 | dmabuf = &state->dmabuf; | 2505 | dmabuf = &state->dmabuf; |
2505 | stop_adc(state); | 2506 | stop_adc(state); |
2506 | dmabuf->ready = 0; | 2507 | dmabuf->ready = 0; |
2507 | dmabuf->SGok = 0; | 2508 | dmabuf->SGok = 0; |
2508 | if (val) | 2509 | if (val) |
2509 | dmabuf->fmt |= CS_FMT_STEREO; | 2510 | dmabuf->fmt |= CS_FMT_STEREO; |
2510 | else | 2511 | else |
2511 | dmabuf->fmt &= ~CS_FMT_STEREO; | 2512 | dmabuf->fmt &= ~CS_FMT_STEREO; |
2512 | cs_set_divisor(dmabuf); | 2513 | cs_set_divisor(dmabuf); |
2513 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( | 2514 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( |
2514 | "cs46xx: DSP_STEREO() ADC %s\n", | 2515 | "cs46xx: DSP_STEREO() ADC %s\n", |
2515 | (dmabuf->fmt & CS_FMT_STEREO) ? | 2516 | (dmabuf->fmt & CS_FMT_STEREO) ? |
2516 | "STEREO":"MONO") ); | 2517 | "STEREO":"MONO") ); |
2517 | } | 2518 | } |
2518 | } | 2519 | } |
2519 | return 0; | 2520 | return 0; |
2520 | case SNDCTL_DSP_GETBLKSIZE: | 2521 | case SNDCTL_DSP_GETBLKSIZE: |
2521 | if (file->f_mode & FMODE_WRITE) { | 2522 | if (file->f_mode & FMODE_WRITE) { |
2522 | state = card->states[1]; | 2523 | state = card->states[1]; |
2523 | if (state) { | 2524 | if (state) { |
2524 | dmabuf = &state->dmabuf; | 2525 | dmabuf = &state->dmabuf; |
2525 | if ((val = prog_dmabuf(state))) | 2526 | if ((val = prog_dmabuf(state))) |
2526 | return val; | 2527 | return val; |
2527 | return put_user(dmabuf->fragsize, p); | 2528 | return put_user(dmabuf->fragsize, p); |
2528 | } | 2529 | } |
2529 | } | 2530 | } |
2530 | if (file->f_mode & FMODE_READ) { | 2531 | if (file->f_mode & FMODE_READ) { |
2531 | state = card->states[0]; | 2532 | state = card->states[0]; |
2532 | if (state) { | 2533 | if (state) { |
2533 | dmabuf = &state->dmabuf; | 2534 | dmabuf = &state->dmabuf; |
2534 | if ((val = prog_dmabuf(state))) | 2535 | if ((val = prog_dmabuf(state))) |
2535 | return val; | 2536 | return val; |
2536 | return put_user(dmabuf->fragsize/dmabuf->divisor, | 2537 | return put_user(dmabuf->fragsize/dmabuf->divisor, |
2537 | p); | 2538 | p); |
2538 | } | 2539 | } |
2539 | } | 2540 | } |
2540 | return put_user(0, p); | 2541 | return put_user(0, p); |
2541 | case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ | 2542 | case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ |
2542 | return put_user(AFMT_S16_LE | AFMT_U8, p); | 2543 | return put_user(AFMT_S16_LE | AFMT_U8, p); |
2543 | case SNDCTL_DSP_SETFMT: /* Select sample format */ | 2544 | case SNDCTL_DSP_SETFMT: /* Select sample format */ |
2544 | if (get_user(val, p)) | 2545 | if (get_user(val, p)) |
2545 | return -EFAULT; | 2546 | return -EFAULT; |
2546 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( | 2547 | CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( |
2547 | "cs46xx: cs_ioctl() DSP_SETFMT %s %s %s %s\n", | 2548 | "cs46xx: cs_ioctl() DSP_SETFMT %s %s %s %s\n", |
2548 | file->f_mode & FMODE_WRITE ? "DAC" : "", | 2549 | file->f_mode & FMODE_WRITE ? "DAC" : "", |
2549 | file->f_mode & FMODE_READ ? "ADC" : "", | 2550 | file->f_mode & FMODE_READ ? "ADC" : "", |
2550 | val == AFMT_S16_LE ? "16Bit Signed" : "", | 2551 | val == AFMT_S16_LE ? "16Bit Signed" : "", |
2551 | val == AFMT_U8 ? "8Bit Unsigned" : "") ); | 2552 | val == AFMT_U8 ? "8Bit Unsigned" : "") ); |
2552 | valsave = val; | 2553 | valsave = val; |
2553 | if (val != AFMT_QUERY) { | 2554 | if (val != AFMT_QUERY) { |
2554 | if (val==AFMT_S16_LE || val==AFMT_U8) { | 2555 | if (val==AFMT_S16_LE || val==AFMT_U8) { |
2555 | if (file->f_mode & FMODE_WRITE) { | 2556 | if (file->f_mode & FMODE_WRITE) { |
2556 | state = card->states[1]; | 2557 | state = card->states[1]; |
2557 | if (state) { | 2558 | if (state) { |
2558 | dmabuf = &state->dmabuf; | 2559 | dmabuf = &state->dmabuf; |
2559 | stop_dac(state); | 2560 | stop_dac(state); |
2560 | dmabuf->ready = 0; | 2561 | dmabuf->ready = 0; |
2561 | dmabuf->SGok = 0; | 2562 | dmabuf->SGok = 0; |
2562 | if (val == AFMT_S16_LE) | 2563 | if (val == AFMT_S16_LE) |
2563 | dmabuf->fmt |= CS_FMT_16BIT; | 2564 | dmabuf->fmt |= CS_FMT_16BIT; |
2564 | else | 2565 | else |
2565 | dmabuf->fmt &= ~CS_FMT_16BIT; | 2566 | dmabuf->fmt &= ~CS_FMT_16BIT; |
2566 | cs_set_divisor(dmabuf); | 2567 | cs_set_divisor(dmabuf); |
2567 | if ((ret = prog_dmabuf(state))) | 2568 | if ((ret = prog_dmabuf(state))) |
2568 | return ret; | 2569 | return ret; |
2569 | } | 2570 | } |
2570 | } | 2571 | } |
2571 | if (file->f_mode & FMODE_READ) { | 2572 | if (file->f_mode & FMODE_READ) { |
2572 | val = valsave; | 2573 | val = valsave; |
2573 | state = card->states[0]; | 2574 | state = card->states[0]; |
2574 | if (state) { | 2575 | if (state) { |
2575 | dmabuf = &state->dmabuf; | 2576 | dmabuf = &state->dmabuf; |
2576 | stop_adc(state); | 2577 | stop_adc(state); |
2577 | dmabuf->ready = 0; | 2578 | dmabuf->ready = 0; |
2578 | dmabuf->SGok = 0; | 2579 | dmabuf->SGok = 0; |
2579 | if (val == AFMT_S16_LE) | 2580 | if (val == AFMT_S16_LE) |
2580 | dmabuf->fmt |= CS_FMT_16BIT; | 2581 | dmabuf->fmt |= CS_FMT_16BIT; |
2581 | else | 2582 | else |
2582 | dmabuf->fmt &= ~CS_FMT_16BIT; | 2583 | dmabuf->fmt &= ~CS_FMT_16BIT; |
2583 | cs_set_divisor(dmabuf); | 2584 | cs_set_divisor(dmabuf); |
2584 | if ((ret = prog_dmabuf(state))) | 2585 | if ((ret = prog_dmabuf(state))) |
2585 | return ret; | 2586 | return ret; |
2586 | } | 2587 | } |
2587 | } | 2588 | } |
2588 | } else { | 2589 | } else { |
2589 | CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk( | 2590 | CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk( |
2590 | "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n", | 2591 | "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n", |
2591 | valsave) ); | 2592 | valsave) ); |
2592 | } | 2593 | } |
2593 | } else { | 2594 | } else { |
2594 | if (file->f_mode & FMODE_WRITE) { | 2595 | if (file->f_mode & FMODE_WRITE) { |
2595 | state = card->states[1]; | 2596 | state = card->states[1]; |
2596 | if (state) | 2597 | if (state) |
2597 | dmabuf = &state->dmabuf; | 2598 | dmabuf = &state->dmabuf; |
2598 | } else if (file->f_mode & FMODE_READ) { | 2599 | } else if (file->f_mode & FMODE_READ) { |
2599 | state = card->states[0]; | 2600 | state = card->states[0]; |
2600 | if (state) | 2601 | if (state) |
2601 | dmabuf = &state->dmabuf; | 2602 | dmabuf = &state->dmabuf; |
2602 | } | 2603 | } |
2603 | } | 2604 | } |
2604 | if (dmabuf) { | 2605 | if (dmabuf) { |
2605 | if (dmabuf->fmt & CS_FMT_16BIT) | 2606 | if (dmabuf->fmt & CS_FMT_16BIT) |
2606 | return put_user(AFMT_S16_LE, p); | 2607 | return put_user(AFMT_S16_LE, p); |
2607 | else | 2608 | else |
2608 | return put_user(AFMT_U8, p); | 2609 | return put_user(AFMT_U8, p); |
2609 | } | 2610 | } |
2610 | return put_user(0, p); | 2611 | return put_user(0, p); |
2611 | case SNDCTL_DSP_CHANNELS: | 2612 | case SNDCTL_DSP_CHANNELS: |
2612 | if (get_user(val, p)) | 2613 | if (get_user(val, p)) |
2613 | return -EFAULT; | 2614 | return -EFAULT; |
2614 | if (val != 0) { | 2615 | if (val != 0) { |
2615 | if (file->f_mode & FMODE_WRITE) { | 2616 | if (file->f_mode & FMODE_WRITE) { |
2616 | state = card->states[1]; | 2617 | state = card->states[1]; |
2617 | if (state) { | 2618 | if (state) { |
2618 | dmabuf = &state->dmabuf; | 2619 | dmabuf = &state->dmabuf; |
2619 | stop_dac(state); | 2620 | stop_dac(state); |
2620 | dmabuf->ready = 0; | 2621 | dmabuf->ready = 0; |
2621 | dmabuf->SGok = 0; | 2622 | dmabuf->SGok = 0; |
2622 | if (val > 1) | 2623 | if (val > 1) |
2623 | dmabuf->fmt |= CS_FMT_STEREO; | 2624 | dmabuf->fmt |= CS_FMT_STEREO; |
2624 | else | 2625 | else |
2625 | dmabuf->fmt &= ~CS_FMT_STEREO; | 2626 | dmabuf->fmt &= ~CS_FMT_STEREO; |
2626 | cs_set_divisor(dmabuf); | 2627 | cs_set_divisor(dmabuf); |
2627 | if (prog_dmabuf(state)) | 2628 | if (prog_dmabuf(state)) |
2628 | return 0; | 2629 | return 0; |
2629 | } | 2630 | } |
2630 | } | 2631 | } |
2631 | if (file->f_mode & FMODE_READ) { | 2632 | if (file->f_mode & FMODE_READ) { |
2632 | state = card->states[0]; | 2633 | state = card->states[0]; |
2633 | if (state) { | 2634 | if (state) { |
2634 | dmabuf = &state->dmabuf; | 2635 | dmabuf = &state->dmabuf; |
2635 | stop_adc(state); | 2636 | stop_adc(state); |
2636 | dmabuf->ready = 0; | 2637 | dmabuf->ready = 0; |
2637 | dmabuf->SGok = 0; | 2638 | dmabuf->SGok = 0; |
2638 | if (val > 1) | 2639 | if (val > 1) |
2639 | dmabuf->fmt |= CS_FMT_STEREO; | 2640 | dmabuf->fmt |= CS_FMT_STEREO; |
2640 | else | 2641 | else |
2641 | dmabuf->fmt &= ~CS_FMT_STEREO; | 2642 | dmabuf->fmt &= ~CS_FMT_STEREO; |
2642 | cs_set_divisor(dmabuf); | 2643 | cs_set_divisor(dmabuf); |
2643 | if (prog_dmabuf(state)) | 2644 | if (prog_dmabuf(state)) |
2644 | return 0; | 2645 | return 0; |
2645 | } | 2646 | } |
2646 | } | 2647 | } |
2647 | } | 2648 | } |
2648 | return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1, | 2649 | return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1, |
2649 | p); | 2650 | p); |
2650 | case SNDCTL_DSP_POST: | 2651 | case SNDCTL_DSP_POST: |
2651 | /* | 2652 | /* |
2652 | * There will be a longer than normal pause in the data. | 2653 | * There will be a longer than normal pause in the data. |
2653 | * so... do nothing, because there is nothing that we can do. | 2654 | * so... do nothing, because there is nothing that we can do. |
2654 | */ | 2655 | */ |
2655 | return 0; | 2656 | return 0; |
2656 | case SNDCTL_DSP_SUBDIVIDE: | 2657 | case SNDCTL_DSP_SUBDIVIDE: |
2657 | if (file->f_mode & FMODE_WRITE) { | 2658 | if (file->f_mode & FMODE_WRITE) { |
2658 | state = card->states[1]; | 2659 | state = card->states[1]; |
2659 | if (state) { | 2660 | if (state) { |
2660 | dmabuf = &state->dmabuf; | 2661 | dmabuf = &state->dmabuf; |
2661 | if (dmabuf->subdivision) | 2662 | if (dmabuf->subdivision) |
2662 | return -EINVAL; | 2663 | return -EINVAL; |
2663 | if (get_user(val, p)) | 2664 | if (get_user(val, p)) |
2664 | return -EFAULT; | 2665 | return -EFAULT; |
2665 | if (val != 1 && val != 2) | 2666 | if (val != 1 && val != 2) |
2666 | return -EINVAL; | 2667 | return -EINVAL; |
2667 | dmabuf->subdivision = val; | 2668 | dmabuf->subdivision = val; |
2668 | } | 2669 | } |
2669 | } | 2670 | } |
2670 | if (file->f_mode & FMODE_READ) { | 2671 | if (file->f_mode & FMODE_READ) { |
2671 | state = card->states[0]; | 2672 | state = card->states[0]; |
2672 | if (state) { | 2673 | if (state) { |
2673 | dmabuf = &state->dmabuf; | 2674 | dmabuf = &state->dmabuf; |
2674 | if (dmabuf->subdivision) | 2675 | if (dmabuf->subdivision) |
2675 | return -EINVAL; | 2676 | return -EINVAL; |
2676 | if (get_user(val, p)) | 2677 | if (get_user(val, p)) |
2677 | return -EFAULT; | 2678 | return -EFAULT; |
2678 | if (val != 1 && val != 2) | 2679 | if (val != 1 && val != 2) |
2679 | return -EINVAL; | 2680 | return -EINVAL; |
2680 | dmabuf->subdivision = val; | 2681 | dmabuf->subdivision = val; |
2681 | } | 2682 | } |
2682 | } | 2683 | } |
2683 | return 0; | 2684 | return 0; |
2684 | case SNDCTL_DSP_SETFRAGMENT: | 2685 | case SNDCTL_DSP_SETFRAGMENT: |
2685 | if (get_user(val, p)) | 2686 | if (get_user(val, p)) |
2686 | return -EFAULT; | 2687 | return -EFAULT; |
2687 | if (file->f_mode & FMODE_WRITE) { | 2688 | if (file->f_mode & FMODE_WRITE) { |
2688 | state = card->states[1]; | 2689 | state = card->states[1]; |
2689 | if (state) { | 2690 | if (state) { |
2690 | dmabuf = &state->dmabuf; | 2691 | dmabuf = &state->dmabuf; |
2691 | dmabuf->ossfragshift = val & 0xffff; | 2692 | dmabuf->ossfragshift = val & 0xffff; |
2692 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; | 2693 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; |
2693 | } | 2694 | } |
2694 | } | 2695 | } |
2695 | if (file->f_mode & FMODE_READ) { | 2696 | if (file->f_mode & FMODE_READ) { |
2696 | state = card->states[0]; | 2697 | state = card->states[0]; |
2697 | if (state) { | 2698 | if (state) { |
2698 | dmabuf = &state->dmabuf; | 2699 | dmabuf = &state->dmabuf; |
2699 | dmabuf->ossfragshift = val & 0xffff; | 2700 | dmabuf->ossfragshift = val & 0xffff; |
2700 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; | 2701 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; |
2701 | } | 2702 | } |
2702 | } | 2703 | } |
2703 | return 0; | 2704 | return 0; |
2704 | case SNDCTL_DSP_GETOSPACE: | 2705 | case SNDCTL_DSP_GETOSPACE: |
2705 | if (!(file->f_mode & FMODE_WRITE)) | 2706 | if (!(file->f_mode & FMODE_WRITE)) |
2706 | return -EINVAL; | 2707 | return -EINVAL; |
2707 | state = card->states[1]; | 2708 | state = card->states[1]; |
2708 | if (state) { | 2709 | if (state) { |
2709 | dmabuf = &state->dmabuf; | 2710 | dmabuf = &state->dmabuf; |
2710 | spin_lock_irqsave(&state->card->lock, flags); | 2711 | spin_lock_irqsave(&state->card->lock, flags); |
2711 | cs_update_ptr(card, CS_TRUE); | 2712 | cs_update_ptr(card, CS_TRUE); |
2712 | abinfo.fragsize = dmabuf->fragsize; | 2713 | abinfo.fragsize = dmabuf->fragsize; |
2713 | abinfo.fragstotal = dmabuf->numfrag; | 2714 | abinfo.fragstotal = dmabuf->numfrag; |
2714 | /* | 2715 | /* |
2715 | * for mmap we always have total space available | 2716 | * for mmap we always have total space available |
2716 | */ | 2717 | */ |
2717 | if (dmabuf->mapped) | 2718 | if (dmabuf->mapped) |
2718 | abinfo.bytes = dmabuf->dmasize; | 2719 | abinfo.bytes = dmabuf->dmasize; |
2719 | else | 2720 | else |
2720 | abinfo.bytes = dmabuf->dmasize - dmabuf->count; | 2721 | abinfo.bytes = dmabuf->dmasize - dmabuf->count; |
2721 | 2722 | ||
2722 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; | 2723 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; |
2723 | spin_unlock_irqrestore(&state->card->lock, flags); | 2724 | spin_unlock_irqrestore(&state->card->lock, flags); |
2724 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 2725 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; |
2725 | } | 2726 | } |
2726 | return -ENODEV; | 2727 | return -ENODEV; |
2727 | case SNDCTL_DSP_GETISPACE: | 2728 | case SNDCTL_DSP_GETISPACE: |
2728 | if (!(file->f_mode & FMODE_READ)) | 2729 | if (!(file->f_mode & FMODE_READ)) |
2729 | return -EINVAL; | 2730 | return -EINVAL; |
2730 | state = card->states[0]; | 2731 | state = card->states[0]; |
2731 | if (state) { | 2732 | if (state) { |
2732 | dmabuf = &state->dmabuf; | 2733 | dmabuf = &state->dmabuf; |
2733 | spin_lock_irqsave(&state->card->lock, flags); | 2734 | spin_lock_irqsave(&state->card->lock, flags); |
2734 | cs_update_ptr(card, CS_TRUE); | 2735 | cs_update_ptr(card, CS_TRUE); |
2735 | abinfo.fragsize = dmabuf->fragsize/dmabuf->divisor; | 2736 | abinfo.fragsize = dmabuf->fragsize/dmabuf->divisor; |
2736 | abinfo.bytes = dmabuf->count/dmabuf->divisor; | 2737 | abinfo.bytes = dmabuf->count/dmabuf->divisor; |
2737 | abinfo.fragstotal = dmabuf->numfrag; | 2738 | abinfo.fragstotal = dmabuf->numfrag; |
2738 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; | 2739 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; |
2739 | spin_unlock_irqrestore(&state->card->lock, flags); | 2740 | spin_unlock_irqrestore(&state->card->lock, flags); |
2740 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 2741 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; |
2741 | } | 2742 | } |
2742 | return -ENODEV; | 2743 | return -ENODEV; |
2743 | case SNDCTL_DSP_NONBLOCK: | 2744 | case SNDCTL_DSP_NONBLOCK: |
2744 | file->f_flags |= O_NONBLOCK; | 2745 | file->f_flags |= O_NONBLOCK; |
2745 | return 0; | 2746 | return 0; |
2746 | case SNDCTL_DSP_GETCAPS: | 2747 | case SNDCTL_DSP_GETCAPS: |
2747 | return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP, | 2748 | return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP, |
2748 | p); | 2749 | p); |
2749 | case SNDCTL_DSP_GETTRIGGER: | 2750 | case SNDCTL_DSP_GETTRIGGER: |
2750 | val = 0; | 2751 | val = 0; |
2751 | CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") ); | 2752 | CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") ); |
2752 | if (file->f_mode & FMODE_WRITE) { | 2753 | if (file->f_mode & FMODE_WRITE) { |
2753 | state = card->states[1]; | 2754 | state = card->states[1]; |
2754 | if (state) { | 2755 | if (state) { |
2755 | dmabuf = &state->dmabuf; | 2756 | dmabuf = &state->dmabuf; |
2756 | if (dmabuf->enable & DAC_RUNNING) | 2757 | if (dmabuf->enable & DAC_RUNNING) |
2757 | val |= PCM_ENABLE_INPUT; | 2758 | val |= PCM_ENABLE_INPUT; |
2758 | } | 2759 | } |
2759 | } | 2760 | } |
2760 | if (file->f_mode & FMODE_READ) { | 2761 | if (file->f_mode & FMODE_READ) { |
2761 | if (state) { | 2762 | if (state) { |
2762 | state = card->states[0]; | 2763 | state = card->states[0]; |
2763 | dmabuf = &state->dmabuf; | 2764 | dmabuf = &state->dmabuf; |
2764 | if (dmabuf->enable & ADC_RUNNING) | 2765 | if (dmabuf->enable & ADC_RUNNING) |
2765 | val |= PCM_ENABLE_OUTPUT; | 2766 | val |= PCM_ENABLE_OUTPUT; |
2766 | } | 2767 | } |
2767 | } | 2768 | } |
2768 | CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) ); | 2769 | CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) ); |
2769 | return put_user(val, p); | 2770 | return put_user(val, p); |
2770 | case SNDCTL_DSP_SETTRIGGER: | 2771 | case SNDCTL_DSP_SETTRIGGER: |
2771 | if (get_user(val, p)) | 2772 | if (get_user(val, p)) |
2772 | return -EFAULT; | 2773 | return -EFAULT; |
2773 | if (file->f_mode & FMODE_READ) { | 2774 | if (file->f_mode & FMODE_READ) { |
2774 | state = card->states[0]; | 2775 | state = card->states[0]; |
2775 | if (state) { | 2776 | if (state) { |
2776 | dmabuf = &state->dmabuf; | 2777 | dmabuf = &state->dmabuf; |
2777 | if (val & PCM_ENABLE_INPUT) { | 2778 | if (val & PCM_ENABLE_INPUT) { |
2778 | if (!dmabuf->ready && (ret = prog_dmabuf(state))) | 2779 | if (!dmabuf->ready && (ret = prog_dmabuf(state))) |
2779 | return ret; | 2780 | return ret; |
2780 | start_adc(state); | 2781 | start_adc(state); |
2781 | } else | 2782 | } else |
2782 | stop_adc(state); | 2783 | stop_adc(state); |
2783 | } | 2784 | } |
2784 | } | 2785 | } |
2785 | if (file->f_mode & FMODE_WRITE) { | 2786 | if (file->f_mode & FMODE_WRITE) { |
2786 | state = card->states[1]; | 2787 | state = card->states[1]; |
2787 | if (state) { | 2788 | if (state) { |
2788 | dmabuf = &state->dmabuf; | 2789 | dmabuf = &state->dmabuf; |
2789 | if (val & PCM_ENABLE_OUTPUT) { | 2790 | if (val & PCM_ENABLE_OUTPUT) { |
2790 | if (!dmabuf->ready && (ret = prog_dmabuf(state))) | 2791 | if (!dmabuf->ready && (ret = prog_dmabuf(state))) |
2791 | return ret; | 2792 | return ret; |
2792 | start_dac(state); | 2793 | start_dac(state); |
2793 | } else | 2794 | } else |
2794 | stop_dac(state); | 2795 | stop_dac(state); |
2795 | } | 2796 | } |
2796 | } | 2797 | } |
2797 | return 0; | 2798 | return 0; |
2798 | case SNDCTL_DSP_GETIPTR: | 2799 | case SNDCTL_DSP_GETIPTR: |
2799 | if (!(file->f_mode & FMODE_READ)) | 2800 | if (!(file->f_mode & FMODE_READ)) |
2800 | return -EINVAL; | 2801 | return -EINVAL; |
2801 | state = card->states[0]; | 2802 | state = card->states[0]; |
2802 | if (state) { | 2803 | if (state) { |
2803 | dmabuf = &state->dmabuf; | 2804 | dmabuf = &state->dmabuf; |
2804 | spin_lock_irqsave(&state->card->lock, flags); | 2805 | spin_lock_irqsave(&state->card->lock, flags); |
2805 | cs_update_ptr(card, CS_TRUE); | 2806 | cs_update_ptr(card, CS_TRUE); |
2806 | cinfo.bytes = dmabuf->total_bytes/dmabuf->divisor; | 2807 | cinfo.bytes = dmabuf->total_bytes/dmabuf->divisor; |
2807 | cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift; | 2808 | cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift; |
2808 | cinfo.ptr = dmabuf->hwptr/dmabuf->divisor; | 2809 | cinfo.ptr = dmabuf->hwptr/dmabuf->divisor; |
2809 | spin_unlock_irqrestore(&state->card->lock, flags); | 2810 | spin_unlock_irqrestore(&state->card->lock, flags); |
2810 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) | 2811 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) |
2811 | return -EFAULT; | 2812 | return -EFAULT; |
2812 | return 0; | 2813 | return 0; |
2813 | } | 2814 | } |
2814 | return -ENODEV; | 2815 | return -ENODEV; |
2815 | case SNDCTL_DSP_GETOPTR: | 2816 | case SNDCTL_DSP_GETOPTR: |
2816 | if (!(file->f_mode & FMODE_WRITE)) | 2817 | if (!(file->f_mode & FMODE_WRITE)) |
2817 | return -EINVAL; | 2818 | return -EINVAL; |
2818 | state = card->states[1]; | 2819 | state = card->states[1]; |
2819 | if (state) { | 2820 | if (state) { |
2820 | dmabuf = &state->dmabuf; | 2821 | dmabuf = &state->dmabuf; |
2821 | spin_lock_irqsave(&state->card->lock, flags); | 2822 | spin_lock_irqsave(&state->card->lock, flags); |
2822 | cs_update_ptr(card, CS_TRUE); | 2823 | cs_update_ptr(card, CS_TRUE); |
2823 | cinfo.bytes = dmabuf->total_bytes; | 2824 | cinfo.bytes = dmabuf->total_bytes; |
2824 | if (dmabuf->mapped) { | 2825 | if (dmabuf->mapped) { |
2825 | cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift) | 2826 | cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift) |
2826 | - dmabuf->blocks; | 2827 | - dmabuf->blocks; |
2827 | CS_DBGOUT(CS_PARMS, 8, | 2828 | CS_DBGOUT(CS_PARMS, 8, |
2828 | printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n", | 2829 | printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n", |
2829 | cinfo.bytes,cinfo.blocks,dmabuf->blocks) ); | 2830 | cinfo.bytes,cinfo.blocks,dmabuf->blocks) ); |
2830 | dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift; | 2831 | dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift; |
2831 | } else { | 2832 | } else { |
2832 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; | 2833 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; |
2833 | } | 2834 | } |
2834 | cinfo.ptr = dmabuf->hwptr; | 2835 | cinfo.ptr = dmabuf->hwptr; |
2835 | 2836 | ||
2836 | CS_DBGOUT(CS_PARMS, 4, printk( | 2837 | CS_DBGOUT(CS_PARMS, 4, printk( |
2837 | "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n", | 2838 | "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n", |
2838 | cinfo.bytes,cinfo.blocks,cinfo.ptr) ); | 2839 | cinfo.bytes,cinfo.blocks,cinfo.ptr) ); |
2839 | spin_unlock_irqrestore(&state->card->lock, flags); | 2840 | spin_unlock_irqrestore(&state->card->lock, flags); |
2840 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) | 2841 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) |
2841 | return -EFAULT; | 2842 | return -EFAULT; |
2842 | return 0; | 2843 | return 0; |
2843 | } | 2844 | } |
2844 | return -ENODEV; | 2845 | return -ENODEV; |
2845 | case SNDCTL_DSP_SETDUPLEX: | 2846 | case SNDCTL_DSP_SETDUPLEX: |
2846 | return 0; | 2847 | return 0; |
2847 | case SNDCTL_DSP_GETODELAY: | 2848 | case SNDCTL_DSP_GETODELAY: |
2848 | if (!(file->f_mode & FMODE_WRITE)) | 2849 | if (!(file->f_mode & FMODE_WRITE)) |
2849 | return -EINVAL; | 2850 | return -EINVAL; |
2850 | state = card->states[1]; | 2851 | state = card->states[1]; |
2851 | if (state) { | 2852 | if (state) { |
2852 | dmabuf = &state->dmabuf; | 2853 | dmabuf = &state->dmabuf; |
2853 | spin_lock_irqsave(&state->card->lock, flags); | 2854 | spin_lock_irqsave(&state->card->lock, flags); |
2854 | cs_update_ptr(card, CS_TRUE); | 2855 | cs_update_ptr(card, CS_TRUE); |
2855 | val = dmabuf->count; | 2856 | val = dmabuf->count; |
2856 | spin_unlock_irqrestore(&state->card->lock, flags); | 2857 | spin_unlock_irqrestore(&state->card->lock, flags); |
2857 | } else | 2858 | } else |
2858 | val = 0; | 2859 | val = 0; |
2859 | return put_user(val, p); | 2860 | return put_user(val, p); |
2860 | case SOUND_PCM_READ_RATE: | 2861 | case SOUND_PCM_READ_RATE: |
2861 | if (file->f_mode & FMODE_READ) | 2862 | if (file->f_mode & FMODE_READ) |
2862 | state = card->states[0]; | 2863 | state = card->states[0]; |
2863 | else | 2864 | else |
2864 | state = card->states[1]; | 2865 | state = card->states[1]; |
2865 | if (state) { | 2866 | if (state) { |
2866 | dmabuf = &state->dmabuf; | 2867 | dmabuf = &state->dmabuf; |
2867 | return put_user(dmabuf->rate, p); | 2868 | return put_user(dmabuf->rate, p); |
2868 | } | 2869 | } |
2869 | return put_user(0, p); | 2870 | return put_user(0, p); |
2870 | case SOUND_PCM_READ_CHANNELS: | 2871 | case SOUND_PCM_READ_CHANNELS: |
2871 | if (file->f_mode & FMODE_READ) | 2872 | if (file->f_mode & FMODE_READ) |
2872 | state = card->states[0]; | 2873 | state = card->states[0]; |
2873 | else | 2874 | else |
2874 | state = card->states[1]; | 2875 | state = card->states[1]; |
2875 | if (state) { | 2876 | if (state) { |
2876 | dmabuf = &state->dmabuf; | 2877 | dmabuf = &state->dmabuf; |
2877 | return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1, | 2878 | return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1, |
2878 | p); | 2879 | p); |
2879 | } | 2880 | } |
2880 | return put_user(0, p); | 2881 | return put_user(0, p); |
2881 | case SOUND_PCM_READ_BITS: | 2882 | case SOUND_PCM_READ_BITS: |
2882 | if (file->f_mode & FMODE_READ) | 2883 | if (file->f_mode & FMODE_READ) |
2883 | state = card->states[0]; | 2884 | state = card->states[0]; |
2884 | else | 2885 | else |
2885 | state = card->states[1]; | 2886 | state = card->states[1]; |
2886 | if (state) { | 2887 | if (state) { |
2887 | dmabuf = &state->dmabuf; | 2888 | dmabuf = &state->dmabuf; |
2888 | return put_user((dmabuf->fmt & CS_FMT_16BIT) ? | 2889 | return put_user((dmabuf->fmt & CS_FMT_16BIT) ? |
2889 | AFMT_S16_LE : AFMT_U8, p); | 2890 | AFMT_S16_LE : AFMT_U8, p); |
2890 | 2891 | ||
2891 | } | 2892 | } |
2892 | return put_user(0, p); | 2893 | return put_user(0, p); |
2893 | case SNDCTL_DSP_MAPINBUF: | 2894 | case SNDCTL_DSP_MAPINBUF: |
2894 | case SNDCTL_DSP_MAPOUTBUF: | 2895 | case SNDCTL_DSP_MAPOUTBUF: |
2895 | case SNDCTL_DSP_SETSYNCRO: | 2896 | case SNDCTL_DSP_SETSYNCRO: |
2896 | case SOUND_PCM_WRITE_FILTER: | 2897 | case SOUND_PCM_WRITE_FILTER: |
2897 | case SOUND_PCM_READ_FILTER: | 2898 | case SOUND_PCM_READ_FILTER: |
2898 | return -EINVAL; | 2899 | return -EINVAL; |
2899 | } | 2900 | } |
2900 | return -EINVAL; | 2901 | return -EINVAL; |
2901 | } | 2902 | } |
2902 | 2903 | ||
2903 | 2904 | ||
2904 | /* | 2905 | /* |
2905 | * AMP control - null AMP | 2906 | * AMP control - null AMP |
2906 | */ | 2907 | */ |
2907 | 2908 | ||
2908 | static void amp_none(struct cs_card *card, int change) | 2909 | static void amp_none(struct cs_card *card, int change) |
2909 | { | 2910 | { |
2910 | } | 2911 | } |
2911 | 2912 | ||
2912 | /* | 2913 | /* |
2913 | * Crystal EAPD mode | 2914 | * Crystal EAPD mode |
2914 | */ | 2915 | */ |
2915 | 2916 | ||
2916 | static void amp_voyetra(struct cs_card *card, int change) | 2917 | static void amp_voyetra(struct cs_card *card, int change) |
2917 | { | 2918 | { |
2918 | /* Manage the EAPD bit on the Crystal 4297 | 2919 | /* Manage the EAPD bit on the Crystal 4297 |
2919 | and the Analog AD1885 */ | 2920 | and the Analog AD1885 */ |
2920 | 2921 | ||
2921 | int old = card->amplifier; | 2922 | int old = card->amplifier; |
2922 | 2923 | ||
2923 | card->amplifier+=change; | 2924 | card->amplifier+=change; |
2924 | if (card->amplifier && !old) { | 2925 | if (card->amplifier && !old) { |
2925 | /* Turn the EAPD amp on */ | 2926 | /* Turn the EAPD amp on */ |
2926 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, | 2927 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, |
2927 | cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) | | 2928 | cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) | |
2928 | 0x8000); | 2929 | 0x8000); |
2929 | } else if(old && !card->amplifier) { | 2930 | } else if(old && !card->amplifier) { |
2930 | /* Turn the EAPD amp off */ | 2931 | /* Turn the EAPD amp off */ |
2931 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, | 2932 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, |
2932 | cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 2933 | cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
2933 | ~0x8000); | 2934 | ~0x8000); |
2934 | } | 2935 | } |
2935 | } | 2936 | } |
2936 | 2937 | ||
2937 | 2938 | ||
2938 | /* | 2939 | /* |
2939 | * Game Theatre XP card - EGPIO[2] is used to enable the external amp. | 2940 | * Game Theatre XP card - EGPIO[2] is used to enable the external amp. |
2940 | */ | 2941 | */ |
2941 | 2942 | ||
2942 | static void amp_hercules(struct cs_card *card, int change) | 2943 | static void amp_hercules(struct cs_card *card, int change) |
2943 | { | 2944 | { |
2944 | int old = card->amplifier; | 2945 | int old = card->amplifier; |
2945 | if (!card) { | 2946 | if (!card) { |
2946 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO | 2947 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO |
2947 | "cs46xx: amp_hercules() called before initialized.\n")); | 2948 | "cs46xx: amp_hercules() called before initialized.\n")); |
2948 | return; | 2949 | return; |
2949 | } | 2950 | } |
2950 | card->amplifier+=change; | 2951 | card->amplifier+=change; |
2951 | if ((card->amplifier && !old) && !(hercules_egpio_disable)) { | 2952 | if ((card->amplifier && !old) && !(hercules_egpio_disable)) { |
2952 | CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO | 2953 | CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO |
2953 | "cs46xx: amp_hercules() external amp enabled\n")); | 2954 | "cs46xx: amp_hercules() external amp enabled\n")); |
2954 | cs461x_pokeBA0(card, BA0_EGPIODR, | 2955 | cs461x_pokeBA0(card, BA0_EGPIODR, |
2955 | EGPIODR_GPOE2); /* enable EGPIO2 output */ | 2956 | EGPIODR_GPOE2); /* enable EGPIO2 output */ |
2956 | cs461x_pokeBA0(card, BA0_EGPIOPTR, | 2957 | cs461x_pokeBA0(card, BA0_EGPIOPTR, |
2957 | EGPIOPTR_GPPT2); /* open-drain on output */ | 2958 | EGPIOPTR_GPPT2); /* open-drain on output */ |
2958 | } else if (old && !card->amplifier) { | 2959 | } else if (old && !card->amplifier) { |
2959 | CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO | 2960 | CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO |
2960 | "cs46xx: amp_hercules() external amp disabled\n")); | 2961 | "cs46xx: amp_hercules() external amp disabled\n")); |
2961 | cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */ | 2962 | cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */ |
2962 | cs461x_pokeBA0(card, BA0_EGPIOPTR, 0); /* disable */ | 2963 | cs461x_pokeBA0(card, BA0_EGPIOPTR, 0); /* disable */ |
2963 | } | 2964 | } |
2964 | } | 2965 | } |
2965 | 2966 | ||
2966 | /* | 2967 | /* |
2967 | * Handle the CLKRUN on a thinkpad. We must disable CLKRUN support | 2968 | * Handle the CLKRUN on a thinkpad. We must disable CLKRUN support |
2968 | * whenever we need to beat on the chip. | 2969 | * whenever we need to beat on the chip. |
2969 | * | 2970 | * |
2970 | * The original idea and code for this hack comes from David Kaiser at | 2971 | * The original idea and code for this hack comes from David Kaiser at |
2971 | * Linuxcare. Perhaps one day Crystal will document their chips well | 2972 | * Linuxcare. Perhaps one day Crystal will document their chips well |
2972 | * enough to make them useful. | 2973 | * enough to make them useful. |
2973 | */ | 2974 | */ |
2974 | 2975 | ||
2975 | static void clkrun_hack(struct cs_card *card, int change) | 2976 | static void clkrun_hack(struct cs_card *card, int change) |
2976 | { | 2977 | { |
2977 | struct pci_dev *acpi_dev; | 2978 | struct pci_dev *acpi_dev; |
2978 | u16 control; | 2979 | u16 control; |
2979 | u8 pp; | 2980 | u8 pp; |
2980 | unsigned long port; | 2981 | unsigned long port; |
2981 | int old = card->active; | 2982 | int old = card->active; |
2982 | 2983 | ||
2983 | card->active+=change; | 2984 | card->active+=change; |
2984 | 2985 | ||
2985 | acpi_dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL); | 2986 | acpi_dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL); |
2986 | if (acpi_dev == NULL) | 2987 | if (acpi_dev == NULL) |
2987 | return; /* Not a thinkpad thats for sure */ | 2988 | return; /* Not a thinkpad thats for sure */ |
2988 | 2989 | ||
2989 | /* Find the control port */ | 2990 | /* Find the control port */ |
2990 | pci_read_config_byte(acpi_dev, 0x41, &pp); | 2991 | pci_read_config_byte(acpi_dev, 0x41, &pp); |
2991 | port = pp << 8; | 2992 | port = pp << 8; |
2992 | 2993 | ||
2993 | /* Read ACPI port */ | 2994 | /* Read ACPI port */ |
2994 | control = inw(port + 0x10); | 2995 | control = inw(port + 0x10); |
2995 | 2996 | ||
2996 | /* Flip CLKRUN off while running */ | 2997 | /* Flip CLKRUN off while running */ |
2997 | if (!card->active && old) { | 2998 | if (!card->active && old) { |
2998 | CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO | 2999 | CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO |
2999 | "cs46xx: clkrun() enable clkrun - change=%d active=%d\n", | 3000 | "cs46xx: clkrun() enable clkrun - change=%d active=%d\n", |
3000 | change,card->active)); | 3001 | change,card->active)); |
3001 | outw(control|0x2000, port+0x10); | 3002 | outw(control|0x2000, port+0x10); |
3002 | } else { | 3003 | } else { |
3003 | /* | 3004 | /* |
3004 | * sometimes on a resume the bit is set, so always reset the bit. | 3005 | * sometimes on a resume the bit is set, so always reset the bit. |
3005 | */ | 3006 | */ |
3006 | CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO | 3007 | CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO |
3007 | "cs46xx: clkrun() disable clkrun - change=%d active=%d\n", | 3008 | "cs46xx: clkrun() disable clkrun - change=%d active=%d\n", |
3008 | change,card->active)); | 3009 | change,card->active)); |
3009 | outw(control&~0x2000, port+0x10); | 3010 | outw(control&~0x2000, port+0x10); |
3010 | } | 3011 | } |
3011 | pci_dev_put(acpi_dev); | 3012 | pci_dev_put(acpi_dev); |
3012 | } | 3013 | } |
3013 | 3014 | ||
3014 | 3015 | ||
3015 | static int cs_open(struct inode *inode, struct file *file) | 3016 | static int cs_open(struct inode *inode, struct file *file) |
3016 | { | 3017 | { |
3017 | struct cs_card *card = file->private_data; | 3018 | struct cs_card *card = file->private_data; |
3018 | struct cs_state *state = NULL; | 3019 | struct cs_state *state = NULL; |
3019 | struct dmabuf *dmabuf = NULL; | 3020 | struct dmabuf *dmabuf = NULL; |
3020 | struct list_head *entry; | 3021 | struct list_head *entry; |
3021 | unsigned int minor = iminor(inode); | 3022 | unsigned int minor = iminor(inode); |
3022 | int ret = 0; | 3023 | int ret = 0; |
3023 | unsigned int tmp; | 3024 | unsigned int tmp; |
3024 | 3025 | ||
3025 | CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=%p %s %s\n", | 3026 | CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=%p %s %s\n", |
3026 | file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "", | 3027 | file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "", |
3027 | file->f_mode & FMODE_READ ? "FMODE_READ" : "") ); | 3028 | file->f_mode & FMODE_READ ? "FMODE_READ" : "") ); |
3028 | 3029 | ||
3029 | list_for_each(entry, &cs46xx_devs) { | 3030 | list_for_each(entry, &cs46xx_devs) { |
3030 | card = list_entry(entry, struct cs_card, list); | 3031 | card = list_entry(entry, struct cs_card, list); |
3031 | 3032 | ||
3032 | if (!((card->dev_audio ^ minor) & ~0xf)) | 3033 | if (!((card->dev_audio ^ minor) & ~0xf)) |
3033 | break; | 3034 | break; |
3034 | } | 3035 | } |
3035 | if (entry == &cs46xx_devs) | 3036 | if (entry == &cs46xx_devs) |
3036 | return -ENODEV; | 3037 | return -ENODEV; |
3037 | if (!card) { | 3038 | if (!card) { |
3038 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO | 3039 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO |
3039 | "cs46xx: cs_open(): Error - unable to find audio card struct\n")); | 3040 | "cs46xx: cs_open(): Error - unable to find audio card struct\n")); |
3040 | return -ENODEV; | 3041 | return -ENODEV; |
3041 | } | 3042 | } |
3042 | 3043 | ||
3043 | /* | 3044 | /* |
3044 | * hardcode state[0] for capture, [1] for playback | 3045 | * hardcode state[0] for capture, [1] for playback |
3045 | */ | 3046 | */ |
3046 | if (file->f_mode & FMODE_READ) { | 3047 | if (file->f_mode & FMODE_READ) { |
3047 | CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") ); | 3048 | CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") ); |
3048 | if (card->states[0] == NULL) { | 3049 | if (card->states[0] == NULL) { |
3049 | state = card->states[0] = | 3050 | state = card->states[0] = |
3050 | kmalloc(sizeof(struct cs_state), GFP_KERNEL); | 3051 | kmalloc(sizeof(struct cs_state), GFP_KERNEL); |
3051 | if (state == NULL) | 3052 | if (state == NULL) |
3052 | return -ENOMEM; | 3053 | return -ENOMEM; |
3053 | memset(state, 0, sizeof(struct cs_state)); | 3054 | memset(state, 0, sizeof(struct cs_state)); |
3054 | mutex_init(&state->sem); | 3055 | mutex_init(&state->sem); |
3055 | dmabuf = &state->dmabuf; | 3056 | dmabuf = &state->dmabuf; |
3056 | dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 3057 | dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
3057 | if (dmabuf->pbuf == NULL) { | 3058 | if (dmabuf->pbuf == NULL) { |
3058 | kfree(state); | 3059 | kfree(state); |
3059 | card->states[0] = NULL; | 3060 | card->states[0] = NULL; |
3060 | return -ENOMEM; | 3061 | return -ENOMEM; |
3061 | } | 3062 | } |
3062 | } else { | 3063 | } else { |
3063 | state = card->states[0]; | 3064 | state = card->states[0]; |
3064 | if (state->open_mode & FMODE_READ) | 3065 | if (state->open_mode & FMODE_READ) |
3065 | return -EBUSY; | 3066 | return -EBUSY; |
3066 | } | 3067 | } |
3067 | dmabuf->channel = card->alloc_rec_pcm_channel(card); | 3068 | dmabuf->channel = card->alloc_rec_pcm_channel(card); |
3068 | 3069 | ||
3069 | if (dmabuf->channel == NULL) { | 3070 | if (dmabuf->channel == NULL) { |
3070 | kfree(card->states[0]); | 3071 | kfree(card->states[0]); |
3071 | card->states[0] = NULL; | 3072 | card->states[0] = NULL; |
3072 | return -ENODEV; | 3073 | return -ENODEV; |
3073 | } | 3074 | } |
3074 | 3075 | ||
3075 | /* Now turn on external AMP if needed */ | 3076 | /* Now turn on external AMP if needed */ |
3076 | state->card = card; | 3077 | state->card = card; |
3077 | state->card->active_ctrl(state->card, 1); | 3078 | state->card->active_ctrl(state->card, 1); |
3078 | state->card->amplifier_ctrl(state->card, 1); | 3079 | state->card->amplifier_ctrl(state->card, 1); |
3079 | 3080 | ||
3080 | if ((tmp = cs46xx_powerup(card, CS_POWER_ADC))) { | 3081 | if ((tmp = cs46xx_powerup(card, CS_POWER_ADC))) { |
3081 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 3082 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
3082 | "cs46xx: cs46xx_powerup of ADC failed (0x%x)\n", tmp)); | 3083 | "cs46xx: cs46xx_powerup of ADC failed (0x%x)\n", tmp)); |
3083 | return -EIO; | 3084 | return -EIO; |
3084 | } | 3085 | } |
3085 | 3086 | ||
3086 | dmabuf->channel->state = state; | 3087 | dmabuf->channel->state = state; |
3087 | /* initialize the virtual channel */ | 3088 | /* initialize the virtual channel */ |
3088 | state->virt = 0; | 3089 | state->virt = 0; |
3089 | state->magic = CS_STATE_MAGIC; | 3090 | state->magic = CS_STATE_MAGIC; |
3090 | init_waitqueue_head(&dmabuf->wait); | 3091 | init_waitqueue_head(&dmabuf->wait); |
3091 | mutex_init(&state->open_mutex); | 3092 | mutex_init(&state->open_mutex); |
3092 | file->private_data = card; | 3093 | file->private_data = card; |
3093 | 3094 | ||
3094 | mutex_lock(&state->open_mutex); | 3095 | mutex_lock(&state->open_mutex); |
3095 | 3096 | ||
3096 | /* set default sample format. According to OSS Programmer's Guide /dev/dsp | 3097 | /* set default sample format. According to OSS Programmer's Guide /dev/dsp |
3097 | should be default to unsigned 8-bits, mono, with sample rate 8kHz and | 3098 | should be default to unsigned 8-bits, mono, with sample rate 8kHz and |
3098 | /dev/dspW will accept 16-bits sample */ | 3099 | /dev/dspW will accept 16-bits sample */ |
3099 | 3100 | ||
3100 | /* Default input is 8bit mono */ | 3101 | /* Default input is 8bit mono */ |
3101 | dmabuf->fmt &= ~CS_FMT_MASK; | 3102 | dmabuf->fmt &= ~CS_FMT_MASK; |
3102 | dmabuf->type = CS_TYPE_ADC; | 3103 | dmabuf->type = CS_TYPE_ADC; |
3103 | dmabuf->ossfragshift = 0; | 3104 | dmabuf->ossfragshift = 0; |
3104 | dmabuf->ossmaxfrags = 0; | 3105 | dmabuf->ossmaxfrags = 0; |
3105 | dmabuf->subdivision = 0; | 3106 | dmabuf->subdivision = 0; |
3106 | cs_set_adc_rate(state, 8000); | 3107 | cs_set_adc_rate(state, 8000); |
3107 | cs_set_divisor(dmabuf); | 3108 | cs_set_divisor(dmabuf); |
3108 | 3109 | ||
3109 | state->open_mode |= FMODE_READ; | 3110 | state->open_mode |= FMODE_READ; |
3110 | mutex_unlock(&state->open_mutex); | 3111 | mutex_unlock(&state->open_mutex); |
3111 | } | 3112 | } |
3112 | if (file->f_mode & FMODE_WRITE) { | 3113 | if (file->f_mode & FMODE_WRITE) { |
3113 | CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") ); | 3114 | CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") ); |
3114 | if (card->states[1] == NULL) { | 3115 | if (card->states[1] == NULL) { |
3115 | state = card->states[1] = | 3116 | state = card->states[1] = |
3116 | kmalloc(sizeof(struct cs_state), GFP_KERNEL); | 3117 | kmalloc(sizeof(struct cs_state), GFP_KERNEL); |
3117 | if (state == NULL) | 3118 | if (state == NULL) |
3118 | return -ENOMEM; | 3119 | return -ENOMEM; |
3119 | memset(state, 0, sizeof(struct cs_state)); | 3120 | memset(state, 0, sizeof(struct cs_state)); |
3120 | mutex_init(&state->sem); | 3121 | mutex_init(&state->sem); |
3121 | dmabuf = &state->dmabuf; | 3122 | dmabuf = &state->dmabuf; |
3122 | dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 3123 | dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
3123 | if (dmabuf->pbuf == NULL) { | 3124 | if (dmabuf->pbuf == NULL) { |
3124 | kfree(state); | 3125 | kfree(state); |
3125 | card->states[1] = NULL; | 3126 | card->states[1] = NULL; |
3126 | return -ENOMEM; | 3127 | return -ENOMEM; |
3127 | } | 3128 | } |
3128 | } else { | 3129 | } else { |
3129 | state = card->states[1]; | 3130 | state = card->states[1]; |
3130 | if (state->open_mode & FMODE_WRITE) | 3131 | if (state->open_mode & FMODE_WRITE) |
3131 | return -EBUSY; | 3132 | return -EBUSY; |
3132 | } | 3133 | } |
3133 | dmabuf->channel = card->alloc_pcm_channel(card); | 3134 | dmabuf->channel = card->alloc_pcm_channel(card); |
3134 | 3135 | ||
3135 | if (dmabuf->channel == NULL) { | 3136 | if (dmabuf->channel == NULL) { |
3136 | kfree(card->states[1]); | 3137 | kfree(card->states[1]); |
3137 | card->states[1] = NULL; | 3138 | card->states[1] = NULL; |
3138 | return -ENODEV; | 3139 | return -ENODEV; |
3139 | } | 3140 | } |
3140 | 3141 | ||
3141 | /* Now turn on external AMP if needed */ | 3142 | /* Now turn on external AMP if needed */ |
3142 | state->card = card; | 3143 | state->card = card; |
3143 | state->card->active_ctrl(state->card, 1); | 3144 | state->card->active_ctrl(state->card, 1); |
3144 | state->card->amplifier_ctrl(state->card, 1); | 3145 | state->card->amplifier_ctrl(state->card, 1); |
3145 | 3146 | ||
3146 | if ((tmp = cs46xx_powerup(card, CS_POWER_DAC))) { | 3147 | if ((tmp = cs46xx_powerup(card, CS_POWER_DAC))) { |
3147 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 3148 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
3148 | "cs46xx: cs46xx_powerup of DAC failed (0x%x)\n", tmp)); | 3149 | "cs46xx: cs46xx_powerup of DAC failed (0x%x)\n", tmp)); |
3149 | return -EIO; | 3150 | return -EIO; |
3150 | } | 3151 | } |
3151 | 3152 | ||
3152 | dmabuf->channel->state = state; | 3153 | dmabuf->channel->state = state; |
3153 | /* initialize the virtual channel */ | 3154 | /* initialize the virtual channel */ |
3154 | state->virt = 1; | 3155 | state->virt = 1; |
3155 | state->magic = CS_STATE_MAGIC; | 3156 | state->magic = CS_STATE_MAGIC; |
3156 | init_waitqueue_head(&dmabuf->wait); | 3157 | init_waitqueue_head(&dmabuf->wait); |
3157 | mutex_init(&state->open_mutex); | 3158 | mutex_init(&state->open_mutex); |
3158 | file->private_data = card; | 3159 | file->private_data = card; |
3159 | 3160 | ||
3160 | mutex_lock(&state->open_mutex); | 3161 | mutex_lock(&state->open_mutex); |
3161 | 3162 | ||
3162 | /* set default sample format. According to OSS Programmer's Guide /dev/dsp | 3163 | /* set default sample format. According to OSS Programmer's Guide /dev/dsp |
3163 | should be default to unsigned 8-bits, mono, with sample rate 8kHz and | 3164 | should be default to unsigned 8-bits, mono, with sample rate 8kHz and |
3164 | /dev/dspW will accept 16-bits sample */ | 3165 | /dev/dspW will accept 16-bits sample */ |
3165 | 3166 | ||
3166 | /* Default output is 8bit mono. */ | 3167 | /* Default output is 8bit mono. */ |
3167 | dmabuf->fmt &= ~CS_FMT_MASK; | 3168 | dmabuf->fmt &= ~CS_FMT_MASK; |
3168 | dmabuf->type = CS_TYPE_DAC; | 3169 | dmabuf->type = CS_TYPE_DAC; |
3169 | dmabuf->ossfragshift = 0; | 3170 | dmabuf->ossfragshift = 0; |
3170 | dmabuf->ossmaxfrags = 0; | 3171 | dmabuf->ossmaxfrags = 0; |
3171 | dmabuf->subdivision = 0; | 3172 | dmabuf->subdivision = 0; |
3172 | cs_set_dac_rate(state, 8000); | 3173 | cs_set_dac_rate(state, 8000); |
3173 | cs_set_divisor(dmabuf); | 3174 | cs_set_divisor(dmabuf); |
3174 | 3175 | ||
3175 | state->open_mode |= FMODE_WRITE; | 3176 | state->open_mode |= FMODE_WRITE; |
3176 | mutex_unlock(&state->open_mutex); | 3177 | mutex_unlock(&state->open_mutex); |
3177 | if ((ret = prog_dmabuf(state))) | 3178 | if ((ret = prog_dmabuf(state))) |
3178 | return ret; | 3179 | return ret; |
3179 | } | 3180 | } |
3180 | CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n")); | 3181 | CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n")); |
3181 | return nonseekable_open(inode, file); | 3182 | return nonseekable_open(inode, file); |
3182 | } | 3183 | } |
3183 | 3184 | ||
3184 | static int cs_release(struct inode *inode, struct file *file) | 3185 | static int cs_release(struct inode *inode, struct file *file) |
3185 | { | 3186 | { |
3186 | struct cs_card *card = file->private_data; | 3187 | struct cs_card *card = file->private_data; |
3187 | struct dmabuf *dmabuf; | 3188 | struct dmabuf *dmabuf; |
3188 | struct cs_state *state; | 3189 | struct cs_state *state; |
3189 | unsigned int tmp; | 3190 | unsigned int tmp; |
3190 | CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=%p %s %s\n", | 3191 | CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=%p %s %s\n", |
3191 | file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "", | 3192 | file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "", |
3192 | file->f_mode & FMODE_READ ? "FMODE_READ" : "")); | 3193 | file->f_mode & FMODE_READ ? "FMODE_READ" : "")); |
3193 | 3194 | ||
3194 | if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) | 3195 | if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) |
3195 | return -EINVAL; | 3196 | return -EINVAL; |
3196 | state = card->states[1]; | 3197 | state = card->states[1]; |
3197 | if (state) { | 3198 | if (state) { |
3198 | if ((state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE)) { | 3199 | if ((state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE)) { |
3199 | CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n")); | 3200 | CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n")); |
3200 | dmabuf = &state->dmabuf; | 3201 | dmabuf = &state->dmabuf; |
3201 | cs_clear_tail(state); | 3202 | cs_clear_tail(state); |
3202 | drain_dac(state, file->f_flags & O_NONBLOCK); | 3203 | drain_dac(state, file->f_flags & O_NONBLOCK); |
3203 | /* stop DMA state machine and free DMA buffers/channels */ | 3204 | /* stop DMA state machine and free DMA buffers/channels */ |
3204 | mutex_lock(&state->open_mutex); | 3205 | mutex_lock(&state->open_mutex); |
3205 | stop_dac(state); | 3206 | stop_dac(state); |
3206 | dealloc_dmabuf(state); | 3207 | dealloc_dmabuf(state); |
3207 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); | 3208 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); |
3208 | free_page((unsigned long)state->dmabuf.pbuf); | 3209 | free_page((unsigned long)state->dmabuf.pbuf); |
3209 | 3210 | ||
3210 | /* we're covered by the open_mutex */ | 3211 | /* we're covered by the open_mutex */ |
3211 | mutex_unlock(&state->open_mutex); | 3212 | mutex_unlock(&state->open_mutex); |
3212 | state->card->states[state->virt] = NULL; | 3213 | state->card->states[state->virt] = NULL; |
3213 | state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); | 3214 | state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); |
3214 | 3215 | ||
3215 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE))) { | 3216 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE))) { |
3216 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO | 3217 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO |
3217 | "cs46xx: cs_release_mixdev() powerdown DAC failure (0x%x)\n",tmp) ); | 3218 | "cs46xx: cs_release_mixdev() powerdown DAC failure (0x%x)\n",tmp) ); |
3218 | } | 3219 | } |
3219 | 3220 | ||
3220 | /* Now turn off external AMP if needed */ | 3221 | /* Now turn off external AMP if needed */ |
3221 | state->card->amplifier_ctrl(state->card, -1); | 3222 | state->card->amplifier_ctrl(state->card, -1); |
3222 | state->card->active_ctrl(state->card, -1); | 3223 | state->card->active_ctrl(state->card, -1); |
3223 | kfree(state); | 3224 | kfree(state); |
3224 | } | 3225 | } |
3225 | } | 3226 | } |
3226 | 3227 | ||
3227 | state = card->states[0]; | 3228 | state = card->states[0]; |
3228 | if (state) { | 3229 | if (state) { |
3229 | if ((state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ)) { | 3230 | if ((state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ)) { |
3230 | CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n")); | 3231 | CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n")); |
3231 | dmabuf = &state->dmabuf; | 3232 | dmabuf = &state->dmabuf; |
3232 | mutex_lock(&state->open_mutex); | 3233 | mutex_lock(&state->open_mutex); |
3233 | stop_adc(state); | 3234 | stop_adc(state); |
3234 | dealloc_dmabuf(state); | 3235 | dealloc_dmabuf(state); |
3235 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); | 3236 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); |
3236 | free_page((unsigned long)state->dmabuf.pbuf); | 3237 | free_page((unsigned long)state->dmabuf.pbuf); |
3237 | 3238 | ||
3238 | /* we're covered by the open_mutex */ | 3239 | /* we're covered by the open_mutex */ |
3239 | mutex_unlock(&state->open_mutex); | 3240 | mutex_unlock(&state->open_mutex); |
3240 | state->card->states[state->virt] = NULL; | 3241 | state->card->states[state->virt] = NULL; |
3241 | state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); | 3242 | state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); |
3242 | 3243 | ||
3243 | if ((tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE))) { | 3244 | if ((tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE))) { |
3244 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO | 3245 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO |
3245 | "cs46xx: cs_release_mixdev() powerdown ADC failure (0x%x)\n",tmp) ); | 3246 | "cs46xx: cs_release_mixdev() powerdown ADC failure (0x%x)\n",tmp) ); |
3246 | } | 3247 | } |
3247 | 3248 | ||
3248 | /* Now turn off external AMP if needed */ | 3249 | /* Now turn off external AMP if needed */ |
3249 | state->card->amplifier_ctrl(state->card, -1); | 3250 | state->card->amplifier_ctrl(state->card, -1); |
3250 | state->card->active_ctrl(state->card, -1); | 3251 | state->card->active_ctrl(state->card, -1); |
3251 | kfree(state); | 3252 | kfree(state); |
3252 | } | 3253 | } |
3253 | } | 3254 | } |
3254 | 3255 | ||
3255 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n")); | 3256 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n")); |
3256 | return 0; | 3257 | return 0; |
3257 | } | 3258 | } |
3258 | 3259 | ||
3259 | static void printpm(struct cs_card *s) | 3260 | static void printpm(struct cs_card *s) |
3260 | { | 3261 | { |
3261 | CS_DBGOUT(CS_PM, 9, printk("pm struct:\n")); | 3262 | CS_DBGOUT(CS_PM, 9, printk("pm struct:\n")); |
3262 | CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n", | 3263 | CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n", |
3263 | (unsigned)s->pm.flags,s->pm.u32CLKCR1_SAVE,s->pm.u32SSPMValue)); | 3264 | (unsigned)s->pm.flags,s->pm.u32CLKCR1_SAVE,s->pm.u32SSPMValue)); |
3264 | CS_DBGOUT(CS_PM, 9, printk("u32PPLVCvalue: 0x%x u32PPRVCvalue: 0x%x\n", | 3265 | CS_DBGOUT(CS_PM, 9, printk("u32PPLVCvalue: 0x%x u32PPRVCvalue: 0x%x\n", |
3265 | s->pm.u32PPLVCvalue,s->pm.u32PPRVCvalue)); | 3266 | s->pm.u32PPLVCvalue,s->pm.u32PPRVCvalue)); |
3266 | CS_DBGOUT(CS_PM, 9, printk("u32FMLVCvalue: 0x%x u32FMRVCvalue: 0x%x\n", | 3267 | CS_DBGOUT(CS_PM, 9, printk("u32FMLVCvalue: 0x%x u32FMRVCvalue: 0x%x\n", |
3267 | s->pm.u32FMLVCvalue,s->pm.u32FMRVCvalue)); | 3268 | s->pm.u32FMLVCvalue,s->pm.u32FMRVCvalue)); |
3268 | CS_DBGOUT(CS_PM, 9, printk("u32GPIORvalue: 0x%x u32JSCTLvalue: 0x%x\n", | 3269 | CS_DBGOUT(CS_PM, 9, printk("u32GPIORvalue: 0x%x u32JSCTLvalue: 0x%x\n", |
3269 | s->pm.u32GPIORvalue,s->pm.u32JSCTLvalue)); | 3270 | s->pm.u32GPIORvalue,s->pm.u32JSCTLvalue)); |
3270 | CS_DBGOUT(CS_PM, 9, printk("u32SSCR: 0x%x u32SRCSA: 0x%x\n", | 3271 | CS_DBGOUT(CS_PM, 9, printk("u32SSCR: 0x%x u32SRCSA: 0x%x\n", |
3271 | s->pm.u32SSCR,s->pm.u32SRCSA)); | 3272 | s->pm.u32SSCR,s->pm.u32SRCSA)); |
3272 | CS_DBGOUT(CS_PM, 9, printk("u32DacASR: 0x%x u32AdcASR: 0x%x\n", | 3273 | CS_DBGOUT(CS_PM, 9, printk("u32DacASR: 0x%x u32AdcASR: 0x%x\n", |
3273 | s->pm.u32DacASR,s->pm.u32AdcASR)); | 3274 | s->pm.u32DacASR,s->pm.u32AdcASR)); |
3274 | CS_DBGOUT(CS_PM, 9, printk("u32DacSR: 0x%x u32AdcSR: 0x%x\n", | 3275 | CS_DBGOUT(CS_PM, 9, printk("u32DacSR: 0x%x u32AdcSR: 0x%x\n", |
3275 | s->pm.u32DacSR,s->pm.u32AdcSR)); | 3276 | s->pm.u32DacSR,s->pm.u32AdcSR)); |
3276 | CS_DBGOUT(CS_PM, 9, printk("u32MIDCR_Save: 0x%x\n", | 3277 | CS_DBGOUT(CS_PM, 9, printk("u32MIDCR_Save: 0x%x\n", |
3277 | s->pm.u32MIDCR_Save)); | 3278 | s->pm.u32MIDCR_Save)); |
3278 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_powerdown: 0x%x _general_purpose 0x%x\n", | 3279 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_powerdown: 0x%x _general_purpose 0x%x\n", |
3279 | s->pm.u32AC97_powerdown,s->pm.u32AC97_general_purpose)); | 3280 | s->pm.u32AC97_powerdown,s->pm.u32AC97_general_purpose)); |
3280 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume: 0x%x\n", | 3281 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume: 0x%x\n", |
3281 | s->pm.u32AC97_master_volume)); | 3282 | s->pm.u32AC97_master_volume)); |
3282 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_headphone_volume: 0x%x\n", | 3283 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_headphone_volume: 0x%x\n", |
3283 | s->pm.u32AC97_headphone_volume)); | 3284 | s->pm.u32AC97_headphone_volume)); |
3284 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume_mono: 0x%x\n", | 3285 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume_mono: 0x%x\n", |
3285 | s->pm.u32AC97_master_volume_mono)); | 3286 | s->pm.u32AC97_master_volume_mono)); |
3286 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_pcm_out_volume: 0x%x\n", | 3287 | CS_DBGOUT(CS_PM, 9, printk("u32AC97_pcm_out_volume: 0x%x\n", |
3287 | s->pm.u32AC97_pcm_out_volume)); | 3288 | s->pm.u32AC97_pcm_out_volume)); |
3288 | CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_play: 0x%x dmabuf_count_play: %d\n", | 3289 | CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_play: 0x%x dmabuf_count_play: %d\n", |
3289 | s->pm.dmabuf_swptr_play,s->pm.dmabuf_count_play)); | 3290 | s->pm.dmabuf_swptr_play,s->pm.dmabuf_count_play)); |
3290 | CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_capture: 0x%x dmabuf_count_capture: %d\n", | 3291 | CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_capture: 0x%x dmabuf_count_capture: %d\n", |
3291 | s->pm.dmabuf_swptr_capture,s->pm.dmabuf_count_capture)); | 3292 | s->pm.dmabuf_swptr_capture,s->pm.dmabuf_count_capture)); |
3292 | 3293 | ||
3293 | } | 3294 | } |
3294 | 3295 | ||
3295 | /**************************************************************************** | 3296 | /**************************************************************************** |
3296 | * | 3297 | * |
3297 | * Suspend - save the ac97 regs, mute the outputs and power down the part. | 3298 | * Suspend - save the ac97 regs, mute the outputs and power down the part. |
3298 | * | 3299 | * |
3299 | ****************************************************************************/ | 3300 | ****************************************************************************/ |
3300 | static void cs46xx_ac97_suspend(struct cs_card *card) | 3301 | static void cs46xx_ac97_suspend(struct cs_card *card) |
3301 | { | 3302 | { |
3302 | int Count,i; | 3303 | int Count,i; |
3303 | struct ac97_codec *dev=card->ac97_codec[0]; | 3304 | struct ac97_codec *dev=card->ac97_codec[0]; |
3304 | unsigned int tmp; | 3305 | unsigned int tmp; |
3305 | 3306 | ||
3306 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()+\n")); | 3307 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()+\n")); |
3307 | 3308 | ||
3308 | if (card->states[1]) { | 3309 | if (card->states[1]) { |
3309 | stop_dac(card->states[1]); | 3310 | stop_dac(card->states[1]); |
3310 | resync_dma_ptrs(card->states[1]); | 3311 | resync_dma_ptrs(card->states[1]); |
3311 | } | 3312 | } |
3312 | if (card->states[0]) { | 3313 | if (card->states[0]) { |
3313 | stop_adc(card->states[0]); | 3314 | stop_adc(card->states[0]); |
3314 | resync_dma_ptrs(card->states[0]); | 3315 | resync_dma_ptrs(card->states[0]); |
3315 | } | 3316 | } |
3316 | 3317 | ||
3317 | for (Count = 0x2, i = 0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) | 3318 | for (Count = 0x2, i = 0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) |
3318 | && (i < CS46XX_AC97_NUMBER_RESTORE_REGS); | 3319 | && (i < CS46XX_AC97_NUMBER_RESTORE_REGS); |
3319 | Count += 2, i++) { | 3320 | Count += 2, i++) { |
3320 | card->pm.ac97[i] = cs_ac97_get(dev, BA0_AC97_RESET + Count); | 3321 | card->pm.ac97[i] = cs_ac97_get(dev, BA0_AC97_RESET + Count); |
3321 | } | 3322 | } |
3322 | /* | 3323 | /* |
3323 | * Save the ac97 volume registers as well as the current powerdown state. | 3324 | * Save the ac97 volume registers as well as the current powerdown state. |
3324 | * Now, mute the all the outputs (master, headphone, and mono), as well | 3325 | * Now, mute the all the outputs (master, headphone, and mono), as well |
3325 | * as the PCM volume, in preparation for powering down the entire part. | 3326 | * as the PCM volume, in preparation for powering down the entire part. |
3326 | card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, | 3327 | card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, |
3327 | (u8)BA0_AC97_MASTER_VOLUME); | 3328 | (u8)BA0_AC97_MASTER_VOLUME); |
3328 | card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, | 3329 | card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, |
3329 | (u8)BA0_AC97_HEADPHONE_VOLUME); | 3330 | (u8)BA0_AC97_HEADPHONE_VOLUME); |
3330 | card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, | 3331 | card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, |
3331 | (u8)BA0_AC97_MASTER_VOLUME_MONO); | 3332 | (u8)BA0_AC97_MASTER_VOLUME_MONO); |
3332 | card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, | 3333 | card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, |
3333 | (u8)BA0_AC97_PCM_OUT_VOLUME); | 3334 | (u8)BA0_AC97_PCM_OUT_VOLUME); |
3334 | */ | 3335 | */ |
3335 | /* | 3336 | /* |
3336 | * mute the outputs | 3337 | * mute the outputs |
3337 | */ | 3338 | */ |
3338 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000); | 3339 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000); |
3339 | cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000); | 3340 | cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000); |
3340 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000); | 3341 | cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000); |
3341 | cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000); | 3342 | cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000); |
3342 | 3343 | ||
3343 | /* | 3344 | /* |
3344 | * save the registers that cause pops | 3345 | * save the registers that cause pops |
3345 | */ | 3346 | */ |
3346 | card->pm.u32AC97_powerdown = (u32)cs_ac97_get(dev, (u8)AC97_POWER_CONTROL); | 3347 | card->pm.u32AC97_powerdown = (u32)cs_ac97_get(dev, (u8)AC97_POWER_CONTROL); |
3347 | card->pm.u32AC97_general_purpose = (u32)cs_ac97_get(dev, (u8)BA0_AC97_GENERAL_PURPOSE); | 3348 | card->pm.u32AC97_general_purpose = (u32)cs_ac97_get(dev, (u8)BA0_AC97_GENERAL_PURPOSE); |
3348 | /* | 3349 | /* |
3349 | * And power down everything on the AC97 codec. | 3350 | * And power down everything on the AC97 codec. |
3350 | * well, for now, only power down the DAC/ADC and MIXER VREFON components. | 3351 | * well, for now, only power down the DAC/ADC and MIXER VREFON components. |
3351 | * trouble with removing VREF. | 3352 | * trouble with removing VREF. |
3352 | */ | 3353 | */ |
3353 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | | 3354 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | |
3354 | CS_POWER_MIXVON, CS_TRUE))) { | 3355 | CS_POWER_MIXVON, CS_TRUE))) { |
3355 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 3356 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
3356 | "cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp)); | 3357 | "cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp)); |
3357 | } | 3358 | } |
3358 | 3359 | ||
3359 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n")); | 3360 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n")); |
3360 | } | 3361 | } |
3361 | 3362 | ||
3362 | /**************************************************************************** | 3363 | /**************************************************************************** |
3363 | * | 3364 | * |
3364 | * Resume - power up the part and restore its registers.. | 3365 | * Resume - power up the part and restore its registers.. |
3365 | * | 3366 | * |
3366 | ****************************************************************************/ | 3367 | ****************************************************************************/ |
3367 | static void cs46xx_ac97_resume(struct cs_card *card) | 3368 | static void cs46xx_ac97_resume(struct cs_card *card) |
3368 | { | 3369 | { |
3369 | int Count,i; | 3370 | int Count,i; |
3370 | struct ac97_codec *dev=card->ac97_codec[0]; | 3371 | struct ac97_codec *dev=card->ac97_codec[0]; |
3371 | 3372 | ||
3372 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()+\n")); | 3373 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()+\n")); |
3373 | 3374 | ||
3374 | /* | 3375 | /* |
3375 | * First, we restore the state of the general purpose register. This | 3376 | * First, we restore the state of the general purpose register. This |
3376 | * contains the mic select (mic1 or mic2) and if we restore this after | 3377 | * contains the mic select (mic1 or mic2) and if we restore this after |
3377 | * we restore the mic volume/boost state and mic2 was selected at | 3378 | * we restore the mic volume/boost state and mic2 was selected at |
3378 | * suspend time, we will end up with a brief period of time where mic1 | 3379 | * suspend time, we will end up with a brief period of time where mic1 |
3379 | * is selected with the volume/boost settings for mic2, causing | 3380 | * is selected with the volume/boost settings for mic2, causing |
3380 | * acoustic feedback. So we restore the general purpose register | 3381 | * acoustic feedback. So we restore the general purpose register |
3381 | * first, thereby getting the correct mic selected before we restore | 3382 | * first, thereby getting the correct mic selected before we restore |
3382 | * the mic volume/boost. | 3383 | * the mic volume/boost. |
3383 | */ | 3384 | */ |
3384 | cs_ac97_set(dev, (u8)BA0_AC97_GENERAL_PURPOSE, | 3385 | cs_ac97_set(dev, (u8)BA0_AC97_GENERAL_PURPOSE, |
3385 | (u16)card->pm.u32AC97_general_purpose); | 3386 | (u16)card->pm.u32AC97_general_purpose); |
3386 | /* | 3387 | /* |
3387 | * Now, while the outputs are still muted, restore the state of power | 3388 | * Now, while the outputs are still muted, restore the state of power |
3388 | * on the AC97 part. | 3389 | * on the AC97 part. |
3389 | */ | 3390 | */ |
3390 | cs_ac97_set(dev, (u8)BA0_AC97_POWERDOWN, (u16)card->pm.u32AC97_powerdown); | 3391 | cs_ac97_set(dev, (u8)BA0_AC97_POWERDOWN, (u16)card->pm.u32AC97_powerdown); |
3391 | mdelay(5 * cs_laptop_wait); | 3392 | mdelay(5 * cs_laptop_wait); |
3392 | /* | 3393 | /* |
3393 | * Restore just the first set of registers, from register number | 3394 | * Restore just the first set of registers, from register number |
3394 | * 0x02 to the register number that ulHighestRegToRestore specifies. | 3395 | * 0x02 to the register number that ulHighestRegToRestore specifies. |
3395 | */ | 3396 | */ |
3396 | for (Count = 0x2, i=0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) && | 3397 | for (Count = 0x2, i=0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) && |
3397 | (i < CS46XX_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) { | 3398 | (i < CS46XX_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) { |
3398 | cs_ac97_set(dev, (u8)(BA0_AC97_RESET + Count), (u16)card->pm.ac97[i]); | 3399 | cs_ac97_set(dev, (u8)(BA0_AC97_RESET + Count), (u16)card->pm.ac97[i]); |
3399 | } | 3400 | } |
3400 | 3401 | ||
3401 | /* Check if we have to init the amplifier */ | 3402 | /* Check if we have to init the amplifier */ |
3402 | if (card->amp_init) | 3403 | if (card->amp_init) |
3403 | card->amp_init(card); | 3404 | card->amp_init(card); |
3404 | 3405 | ||
3405 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n")); | 3406 | CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n")); |
3406 | } | 3407 | } |
3407 | 3408 | ||
3408 | 3409 | ||
3409 | static int cs46xx_restart_part(struct cs_card *card) | 3410 | static int cs46xx_restart_part(struct cs_card *card) |
3410 | { | 3411 | { |
3411 | struct dmabuf *dmabuf; | 3412 | struct dmabuf *dmabuf; |
3412 | 3413 | ||
3413 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, | 3414 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, |
3414 | printk( "cs46xx: cs46xx_restart_part()+\n")); | 3415 | printk( "cs46xx: cs46xx_restart_part()+\n")); |
3415 | if (card->states[1]) { | 3416 | if (card->states[1]) { |
3416 | dmabuf = &card->states[1]->dmabuf; | 3417 | dmabuf = &card->states[1]->dmabuf; |
3417 | dmabuf->ready = 0; | 3418 | dmabuf->ready = 0; |
3418 | resync_dma_ptrs(card->states[1]); | 3419 | resync_dma_ptrs(card->states[1]); |
3419 | cs_set_divisor(dmabuf); | 3420 | cs_set_divisor(dmabuf); |
3420 | if (__prog_dmabuf(card->states[1])) { | 3421 | if (__prog_dmabuf(card->states[1])) { |
3421 | CS_DBGOUT(CS_PM | CS_ERROR, 1, | 3422 | CS_DBGOUT(CS_PM | CS_ERROR, 1, |
3422 | printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() dac error\n")); | 3423 | printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() dac error\n")); |
3423 | return -1; | 3424 | return -1; |
3424 | } | 3425 | } |
3425 | cs_set_dac_rate(card->states[1], dmabuf->rate); | 3426 | cs_set_dac_rate(card->states[1], dmabuf->rate); |
3426 | } | 3427 | } |
3427 | if (card->states[0]) { | 3428 | if (card->states[0]) { |
3428 | dmabuf = &card->states[0]->dmabuf; | 3429 | dmabuf = &card->states[0]->dmabuf; |
3429 | dmabuf->ready = 0; | 3430 | dmabuf->ready = 0; |
3430 | resync_dma_ptrs(card->states[0]); | 3431 | resync_dma_ptrs(card->states[0]); |
3431 | cs_set_divisor(dmabuf); | 3432 | cs_set_divisor(dmabuf); |
3432 | if (__prog_dmabuf(card->states[0])) { | 3433 | if (__prog_dmabuf(card->states[0])) { |
3433 | CS_DBGOUT(CS_PM | CS_ERROR, 1, | 3434 | CS_DBGOUT(CS_PM | CS_ERROR, 1, |
3434 | printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() adc error\n")); | 3435 | printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() adc error\n")); |
3435 | return -1; | 3436 | return -1; |
3436 | } | 3437 | } |
3437 | cs_set_adc_rate(card->states[0], dmabuf->rate); | 3438 | cs_set_adc_rate(card->states[0], dmabuf->rate); |
3438 | } | 3439 | } |
3439 | card->pm.flags |= CS46XX_PM_RESUMED; | 3440 | card->pm.flags |= CS46XX_PM_RESUMED; |
3440 | if (card->states[0]) | 3441 | if (card->states[0]) |
3441 | start_adc(card->states[0]); | 3442 | start_adc(card->states[0]); |
3442 | if (card->states[1]) | 3443 | if (card->states[1]) |
3443 | start_dac(card->states[1]); | 3444 | start_dac(card->states[1]); |
3444 | 3445 | ||
3445 | card->pm.flags |= CS46XX_PM_IDLE; | 3446 | card->pm.flags |= CS46XX_PM_IDLE; |
3446 | card->pm.flags &= ~(CS46XX_PM_SUSPENDING | CS46XX_PM_SUSPENDED | 3447 | card->pm.flags &= ~(CS46XX_PM_SUSPENDING | CS46XX_PM_SUSPENDED |
3447 | | CS46XX_PM_RESUMING | CS46XX_PM_RESUMED); | 3448 | | CS46XX_PM_RESUMING | CS46XX_PM_RESUMED); |
3448 | if (card->states[0]) | 3449 | if (card->states[0]) |
3449 | wake_up(&card->states[0]->dmabuf.wait); | 3450 | wake_up(&card->states[0]->dmabuf.wait); |
3450 | if (card->states[1]) | 3451 | if (card->states[1]) |
3451 | wake_up(&card->states[1]->dmabuf.wait); | 3452 | wake_up(&card->states[1]->dmabuf.wait); |
3452 | 3453 | ||
3453 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, | 3454 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, |
3454 | printk( "cs46xx: cs46xx_restart_part()-\n")); | 3455 | printk( "cs46xx: cs46xx_restart_part()-\n")); |
3455 | return 0; | 3456 | return 0; |
3456 | } | 3457 | } |
3457 | 3458 | ||
3458 | static void cs461x_reset(struct cs_card *card); | 3459 | static void cs461x_reset(struct cs_card *card); |
3459 | static void cs461x_proc_stop(struct cs_card *card); | 3460 | static void cs461x_proc_stop(struct cs_card *card); |
3460 | static int cs46xx_suspend(struct cs_card *card, pm_message_t state) | 3461 | static int cs46xx_suspend(struct cs_card *card, pm_message_t state) |
3461 | { | 3462 | { |
3462 | unsigned int tmp; | 3463 | unsigned int tmp; |
3463 | 3464 | ||
3464 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, | 3465 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, |
3465 | printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=%p\n", | 3466 | printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=%p\n", |
3466 | (unsigned)card->pm.flags,card)); | 3467 | (unsigned)card->pm.flags,card)); |
3467 | /* | 3468 | /* |
3468 | * check the current state, only suspend if IDLE | 3469 | * check the current state, only suspend if IDLE |
3469 | */ | 3470 | */ |
3470 | if (!(card->pm.flags & CS46XX_PM_IDLE)) { | 3471 | if (!(card->pm.flags & CS46XX_PM_IDLE)) { |
3471 | CS_DBGOUT(CS_PM | CS_ERROR, 2, | 3472 | CS_DBGOUT(CS_PM | CS_ERROR, 2, |
3472 | printk("cs46xx: cs46xx_suspend() unable to suspend, not IDLE\n")); | 3473 | printk("cs46xx: cs46xx_suspend() unable to suspend, not IDLE\n")); |
3473 | return 1; | 3474 | return 1; |
3474 | } | 3475 | } |
3475 | card->pm.flags &= ~CS46XX_PM_IDLE; | 3476 | card->pm.flags &= ~CS46XX_PM_IDLE; |
3476 | card->pm.flags |= CS46XX_PM_SUSPENDING; | 3477 | card->pm.flags |= CS46XX_PM_SUSPENDING; |
3477 | 3478 | ||
3478 | card->active_ctrl(card,1); | 3479 | card->active_ctrl(card,1); |
3479 | 3480 | ||
3480 | tmp = cs461x_peek(card, BA1_PFIE); | 3481 | tmp = cs461x_peek(card, BA1_PFIE); |
3481 | tmp &= ~0x0000f03f; | 3482 | tmp &= ~0x0000f03f; |
3482 | tmp |= 0x00000010; | 3483 | tmp |= 0x00000010; |
3483 | cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt disable */ | 3484 | cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt disable */ |
3484 | 3485 | ||
3485 | tmp = cs461x_peek(card, BA1_CIE); | 3486 | tmp = cs461x_peek(card, BA1_CIE); |
3486 | tmp &= ~0x0000003f; | 3487 | tmp &= ~0x0000003f; |
3487 | tmp |= 0x00000011; | 3488 | tmp |= 0x00000011; |
3488 | cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt disable */ | 3489 | cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt disable */ |
3489 | 3490 | ||
3490 | /* | 3491 | /* |
3491 | * Stop playback DMA. | 3492 | * Stop playback DMA. |
3492 | */ | 3493 | */ |
3493 | tmp = cs461x_peek(card, BA1_PCTL); | 3494 | tmp = cs461x_peek(card, BA1_PCTL); |
3494 | cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff); | 3495 | cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff); |
3495 | 3496 | ||
3496 | /* | 3497 | /* |
3497 | * Stop capture DMA. | 3498 | * Stop capture DMA. |
3498 | */ | 3499 | */ |
3499 | tmp = cs461x_peek(card, BA1_CCTL); | 3500 | tmp = cs461x_peek(card, BA1_CCTL); |
3500 | cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000); | 3501 | cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000); |
3501 | 3502 | ||
3502 | if (card->states[1]) { | 3503 | if (card->states[1]) { |
3503 | card->pm.dmabuf_swptr_play = card->states[1]->dmabuf.swptr; | 3504 | card->pm.dmabuf_swptr_play = card->states[1]->dmabuf.swptr; |
3504 | card->pm.dmabuf_count_play = card->states[1]->dmabuf.count; | 3505 | card->pm.dmabuf_count_play = card->states[1]->dmabuf.count; |
3505 | } | 3506 | } |
3506 | if (card->states[0]) { | 3507 | if (card->states[0]) { |
3507 | card->pm.dmabuf_swptr_capture = card->states[0]->dmabuf.swptr; | 3508 | card->pm.dmabuf_swptr_capture = card->states[0]->dmabuf.swptr; |
3508 | card->pm.dmabuf_count_capture = card->states[0]->dmabuf.count; | 3509 | card->pm.dmabuf_count_capture = card->states[0]->dmabuf.count; |
3509 | } | 3510 | } |
3510 | 3511 | ||
3511 | cs46xx_ac97_suspend(card); | 3512 | cs46xx_ac97_suspend(card); |
3512 | 3513 | ||
3513 | /* | 3514 | /* |
3514 | * Reset the processor. | 3515 | * Reset the processor. |
3515 | */ | 3516 | */ |
3516 | cs461x_reset(card); | 3517 | cs461x_reset(card); |
3517 | 3518 | ||
3518 | cs461x_proc_stop(card); | 3519 | cs461x_proc_stop(card); |
3519 | 3520 | ||
3520 | /* | 3521 | /* |
3521 | * Power down the DAC and ADC. For now leave the other areas on. | 3522 | * Power down the DAC and ADC. For now leave the other areas on. |
3522 | */ | 3523 | */ |
3523 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, 0x0300); | 3524 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, 0x0300); |
3524 | 3525 | ||
3525 | /* | 3526 | /* |
3526 | * Power down the PLL. | 3527 | * Power down the PLL. |
3527 | */ | 3528 | */ |
3528 | cs461x_pokeBA0(card, BA0_CLKCR1, 0); | 3529 | cs461x_pokeBA0(card, BA0_CLKCR1, 0); |
3529 | 3530 | ||
3530 | /* | 3531 | /* |
3531 | * Turn off the Processor by turning off the software clock enable flag in | 3532 | * Turn off the Processor by turning off the software clock enable flag in |
3532 | * the clock control register. | 3533 | * the clock control register. |
3533 | */ | 3534 | */ |
3534 | tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; | 3535 | tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; |
3535 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); | 3536 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); |
3536 | 3537 | ||
3537 | card->active_ctrl(card,-1); | 3538 | card->active_ctrl(card,-1); |
3538 | 3539 | ||
3539 | card->pm.flags &= ~CS46XX_PM_SUSPENDING; | 3540 | card->pm.flags &= ~CS46XX_PM_SUSPENDING; |
3540 | card->pm.flags |= CS46XX_PM_SUSPENDED; | 3541 | card->pm.flags |= CS46XX_PM_SUSPENDED; |
3541 | 3542 | ||
3542 | printpm(card); | 3543 | printpm(card); |
3543 | 3544 | ||
3544 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, | 3545 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, |
3545 | printk("cs46xx: cs46xx_suspend()- flags=0x%x\n", | 3546 | printk("cs46xx: cs46xx_suspend()- flags=0x%x\n", |
3546 | (unsigned)card->pm.flags)); | 3547 | (unsigned)card->pm.flags)); |
3547 | return 0; | 3548 | return 0; |
3548 | } | 3549 | } |
3549 | 3550 | ||
3550 | static int cs46xx_resume(struct cs_card *card) | 3551 | static int cs46xx_resume(struct cs_card *card) |
3551 | { | 3552 | { |
3552 | int i; | 3553 | int i; |
3553 | 3554 | ||
3554 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, | 3555 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, |
3555 | printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n", | 3556 | printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n", |
3556 | (unsigned)card->pm.flags)); | 3557 | (unsigned)card->pm.flags)); |
3557 | if (!(card->pm.flags & CS46XX_PM_SUSPENDED)) { | 3558 | if (!(card->pm.flags & CS46XX_PM_SUSPENDED)) { |
3558 | CS_DBGOUT(CS_PM | CS_ERROR, 2, | 3559 | CS_DBGOUT(CS_PM | CS_ERROR, 2, |
3559 | printk("cs46xx: cs46xx_resume() unable to resume, not SUSPENDED\n")); | 3560 | printk("cs46xx: cs46xx_resume() unable to resume, not SUSPENDED\n")); |
3560 | return 1; | 3561 | return 1; |
3561 | } | 3562 | } |
3562 | card->pm.flags |= CS46XX_PM_RESUMING; | 3563 | card->pm.flags |= CS46XX_PM_RESUMING; |
3563 | card->pm.flags &= ~CS46XX_PM_SUSPENDED; | 3564 | card->pm.flags &= ~CS46XX_PM_SUSPENDED; |
3564 | printpm(card); | 3565 | printpm(card); |
3565 | card->active_ctrl(card, 1); | 3566 | card->active_ctrl(card, 1); |
3566 | 3567 | ||
3567 | for (i = 0; i < 5; i++) { | 3568 | for (i = 0; i < 5; i++) { |
3568 | if (cs_hardware_init(card) != 0) { | 3569 | if (cs_hardware_init(card) != 0) { |
3569 | CS_DBGOUT(CS_PM | CS_ERROR, 4, printk( | 3570 | CS_DBGOUT(CS_PM | CS_ERROR, 4, printk( |
3570 | "cs46xx: cs46xx_resume()- ERROR in cs_hardware_init()\n")); | 3571 | "cs46xx: cs46xx_resume()- ERROR in cs_hardware_init()\n")); |
3571 | mdelay(10 * cs_laptop_wait); | 3572 | mdelay(10 * cs_laptop_wait); |
3572 | cs461x_reset(card); | 3573 | cs461x_reset(card); |
3573 | continue; | 3574 | continue; |
3574 | } | 3575 | } |
3575 | break; | 3576 | break; |
3576 | } | 3577 | } |
3577 | if (i >= 4) { | 3578 | if (i >= 4) { |
3578 | CS_DBGOUT(CS_PM | CS_ERROR, 1, printk( | 3579 | CS_DBGOUT(CS_PM | CS_ERROR, 1, printk( |
3579 | "cs46xx: cs46xx_resume()- cs_hardware_init() failed, retried %d times.\n",i)); | 3580 | "cs46xx: cs46xx_resume()- cs_hardware_init() failed, retried %d times.\n",i)); |
3580 | return 0; | 3581 | return 0; |
3581 | } | 3582 | } |
3582 | 3583 | ||
3583 | if (cs46xx_restart_part(card)) { | 3584 | if (cs46xx_restart_part(card)) { |
3584 | CS_DBGOUT(CS_PM | CS_ERROR, 4, printk( | 3585 | CS_DBGOUT(CS_PM | CS_ERROR, 4, printk( |
3585 | "cs46xx: cs46xx_resume(): cs46xx_restart_part() returned error\n")); | 3586 | "cs46xx: cs46xx_resume(): cs46xx_restart_part() returned error\n")); |
3586 | } | 3587 | } |
3587 | 3588 | ||
3588 | card->active_ctrl(card, -1); | 3589 | card->active_ctrl(card, -1); |
3589 | 3590 | ||
3590 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=0x%x\n", | 3591 | CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=0x%x\n", |
3591 | (unsigned)card->pm.flags)); | 3592 | (unsigned)card->pm.flags)); |
3592 | return 0; | 3593 | return 0; |
3593 | } | 3594 | } |
3594 | 3595 | ||
3595 | static /*const*/ struct file_operations cs461x_fops = { | 3596 | static /*const*/ struct file_operations cs461x_fops = { |
3596 | CS_OWNER CS_THIS_MODULE | 3597 | CS_OWNER CS_THIS_MODULE |
3597 | .llseek = no_llseek, | 3598 | .llseek = no_llseek, |
3598 | .read = cs_read, | 3599 | .read = cs_read, |
3599 | .write = cs_write, | 3600 | .write = cs_write, |
3600 | .poll = cs_poll, | 3601 | .poll = cs_poll, |
3601 | .ioctl = cs_ioctl, | 3602 | .ioctl = cs_ioctl, |
3602 | .mmap = cs_mmap, | 3603 | .mmap = cs_mmap, |
3603 | .open = cs_open, | 3604 | .open = cs_open, |
3604 | .release = cs_release, | 3605 | .release = cs_release, |
3605 | }; | 3606 | }; |
3606 | 3607 | ||
3607 | /* Write AC97 codec registers */ | 3608 | /* Write AC97 codec registers */ |
3608 | 3609 | ||
3609 | 3610 | ||
3610 | static u16 _cs_ac97_get(struct ac97_codec *dev, u8 reg) | 3611 | static u16 _cs_ac97_get(struct ac97_codec *dev, u8 reg) |
3611 | { | 3612 | { |
3612 | struct cs_card *card = dev->private_data; | 3613 | struct cs_card *card = dev->private_data; |
3613 | int count,loopcnt; | 3614 | int count,loopcnt; |
3614 | unsigned int tmp; | 3615 | unsigned int tmp; |
3615 | u16 ret; | 3616 | u16 ret; |
3616 | 3617 | ||
3617 | /* | 3618 | /* |
3618 | * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address | 3619 | * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address |
3619 | * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 | 3620 | * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 |
3620 | * 3. Write ACCTL = Control Register = 460h for initiating the write | 3621 | * 3. Write ACCTL = Control Register = 460h for initiating the write |
3621 | * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h | 3622 | * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h |
3622 | * 5. if DCV not cleared, break and return error | 3623 | * 5. if DCV not cleared, break and return error |
3623 | * 6. Read ACSTS = Status Register = 464h, check VSTS bit | 3624 | * 6. Read ACSTS = Status Register = 464h, check VSTS bit |
3624 | */ | 3625 | */ |
3625 | 3626 | ||
3626 | cs461x_peekBA0(card, BA0_ACSDA); | 3627 | cs461x_peekBA0(card, BA0_ACSDA); |
3627 | 3628 | ||
3628 | /* | 3629 | /* |
3629 | * Setup the AC97 control registers on the CS461x to send the | 3630 | * Setup the AC97 control registers on the CS461x to send the |
3630 | * appropriate command to the AC97 to perform the read. | 3631 | * appropriate command to the AC97 to perform the read. |
3631 | * ACCAD = Command Address Register = 46Ch | 3632 | * ACCAD = Command Address Register = 46Ch |
3632 | * ACCDA = Command Data Register = 470h | 3633 | * ACCDA = Command Data Register = 470h |
3633 | * ACCTL = Control Register = 460h | 3634 | * ACCTL = Control Register = 460h |
3634 | * set DCV - will clear when process completed | 3635 | * set DCV - will clear when process completed |
3635 | * set CRW - Read command | 3636 | * set CRW - Read command |
3636 | * set VFRM - valid frame enabled | 3637 | * set VFRM - valid frame enabled |
3637 | * set ESYN - ASYNC generation enabled | 3638 | * set ESYN - ASYNC generation enabled |
3638 | * set RSTN - ARST# inactive, AC97 codec not reset | 3639 | * set RSTN - ARST# inactive, AC97 codec not reset |
3639 | */ | 3640 | */ |
3640 | 3641 | ||
3641 | cs461x_pokeBA0(card, BA0_ACCAD, reg); | 3642 | cs461x_pokeBA0(card, BA0_ACCAD, reg); |
3642 | cs461x_pokeBA0(card, BA0_ACCDA, 0); | 3643 | cs461x_pokeBA0(card, BA0_ACCDA, 0); |
3643 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | | 3644 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | |
3644 | ACCTL_VFRM | ACCTL_ESYN | | 3645 | ACCTL_VFRM | ACCTL_ESYN | |
3645 | ACCTL_RSTN); | 3646 | ACCTL_RSTN); |
3646 | 3647 | ||
3647 | 3648 | ||
3648 | /* | 3649 | /* |
3649 | * Wait for the read to occur. | 3650 | * Wait for the read to occur. |
3650 | */ | 3651 | */ |
3651 | if (!(card->pm.flags & CS46XX_PM_IDLE)) | 3652 | if (!(card->pm.flags & CS46XX_PM_IDLE)) |
3652 | loopcnt = 2000; | 3653 | loopcnt = 2000; |
3653 | else | 3654 | else |
3654 | loopcnt = 500 * cs_laptop_wait; | 3655 | loopcnt = 500 * cs_laptop_wait; |
3655 | loopcnt *= cs_laptop_wait; | 3656 | loopcnt *= cs_laptop_wait; |
3656 | for (count = 0; count < loopcnt; count++) { | 3657 | for (count = 0; count < loopcnt; count++) { |
3657 | /* | 3658 | /* |
3658 | * First, we want to wait for a short time. | 3659 | * First, we want to wait for a short time. |
3659 | */ | 3660 | */ |
3660 | udelay(10 * cs_laptop_wait); | 3661 | udelay(10 * cs_laptop_wait); |
3661 | /* | 3662 | /* |
3662 | * Now, check to see if the read has completed. | 3663 | * Now, check to see if the read has completed. |
3663 | * ACCTL = 460h, DCV should be reset by now and 460h = 17h | 3664 | * ACCTL = 460h, DCV should be reset by now and 460h = 17h |
3664 | */ | 3665 | */ |
3665 | if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV)) | 3666 | if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV)) |
3666 | break; | 3667 | break; |
3667 | } | 3668 | } |
3668 | 3669 | ||
3669 | /* | 3670 | /* |
3670 | * Make sure the read completed. | 3671 | * Make sure the read completed. |
3671 | */ | 3672 | */ |
3672 | if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) { | 3673 | if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) { |
3673 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 3674 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
3674 | "cs46xx: AC'97 read problem (ACCTL_DCV), reg = 0x%x returning 0xffff\n", reg)); | 3675 | "cs46xx: AC'97 read problem (ACCTL_DCV), reg = 0x%x returning 0xffff\n", reg)); |
3675 | return 0xffff; | 3676 | return 0xffff; |
3676 | } | 3677 | } |
3677 | 3678 | ||
3678 | /* | 3679 | /* |
3679 | * Wait for the valid status bit to go active. | 3680 | * Wait for the valid status bit to go active. |
3680 | */ | 3681 | */ |
3681 | 3682 | ||
3682 | if (!(card->pm.flags & CS46XX_PM_IDLE)) | 3683 | if (!(card->pm.flags & CS46XX_PM_IDLE)) |
3683 | loopcnt = 2000; | 3684 | loopcnt = 2000; |
3684 | else | 3685 | else |
3685 | loopcnt = 1000; | 3686 | loopcnt = 1000; |
3686 | loopcnt *= cs_laptop_wait; | 3687 | loopcnt *= cs_laptop_wait; |
3687 | for (count = 0; count < loopcnt; count++) { | 3688 | for (count = 0; count < loopcnt; count++) { |
3688 | /* | 3689 | /* |
3689 | * Read the AC97 status register. | 3690 | * Read the AC97 status register. |
3690 | * ACSTS = Status Register = 464h | 3691 | * ACSTS = Status Register = 464h |
3691 | * VSTS - Valid Status | 3692 | * VSTS - Valid Status |
3692 | */ | 3693 | */ |
3693 | if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_VSTS) | 3694 | if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_VSTS) |
3694 | break; | 3695 | break; |
3695 | udelay(10 * cs_laptop_wait); | 3696 | udelay(10 * cs_laptop_wait); |
3696 | } | 3697 | } |
3697 | 3698 | ||
3698 | /* | 3699 | /* |
3699 | * Make sure we got valid status. | 3700 | * Make sure we got valid status. |
3700 | */ | 3701 | */ |
3701 | if (!((tmp = cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) { | 3702 | if (!((tmp = cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) { |
3702 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_WARNING | 3703 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_WARNING |
3703 | "cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x 0xffff \n", | 3704 | "cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x 0xffff \n", |
3704 | reg, tmp)); | 3705 | reg, tmp)); |
3705 | return 0xffff; | 3706 | return 0xffff; |
3706 | } | 3707 | } |
3707 | 3708 | ||
3708 | /* | 3709 | /* |
3709 | * Read the data returned from the AC97 register. | 3710 | * Read the data returned from the AC97 register. |
3710 | * ACSDA = Status Data Register = 474h | 3711 | * ACSDA = Status Data Register = 474h |
3711 | */ | 3712 | */ |
3712 | CS_DBGOUT(CS_FUNCTION, 9, printk(KERN_INFO | 3713 | CS_DBGOUT(CS_FUNCTION, 9, printk(KERN_INFO |
3713 | "cs46xx: cs_ac97_get() reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", | 3714 | "cs46xx: cs_ac97_get() reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", |
3714 | reg, cs461x_peekBA0(card, BA0_ACSDA), | 3715 | reg, cs461x_peekBA0(card, BA0_ACSDA), |
3715 | cs461x_peekBA0(card, BA0_ACCAD))); | 3716 | cs461x_peekBA0(card, BA0_ACCAD))); |
3716 | ret = cs461x_peekBA0(card, BA0_ACSDA); | 3717 | ret = cs461x_peekBA0(card, BA0_ACSDA); |
3717 | return ret; | 3718 | return ret; |
3718 | } | 3719 | } |
3719 | 3720 | ||
3720 | static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg) | 3721 | static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg) |
3721 | { | 3722 | { |
3722 | u16 ret; | 3723 | u16 ret; |
3723 | struct cs_card *card = dev->private_data; | 3724 | struct cs_card *card = dev->private_data; |
3724 | 3725 | ||
3725 | spin_lock(&card->ac97_lock); | 3726 | spin_lock(&card->ac97_lock); |
3726 | ret = _cs_ac97_get(dev, reg); | 3727 | ret = _cs_ac97_get(dev, reg); |
3727 | spin_unlock(&card->ac97_lock); | 3728 | spin_unlock(&card->ac97_lock); |
3728 | return ret; | 3729 | return ret; |
3729 | } | 3730 | } |
3730 | 3731 | ||
3731 | static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val) | 3732 | static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val) |
3732 | { | 3733 | { |
3733 | struct cs_card *card = dev->private_data; | 3734 | struct cs_card *card = dev->private_data; |
3734 | int count; | 3735 | int count; |
3735 | int val2 = 0; | 3736 | int val2 = 0; |
3736 | 3737 | ||
3737 | spin_lock(&card->ac97_lock); | 3738 | spin_lock(&card->ac97_lock); |
3738 | 3739 | ||
3739 | if (reg == AC97_CD_VOL) | 3740 | if (reg == AC97_CD_VOL) |
3740 | val2 = _cs_ac97_get(dev, AC97_CD_VOL); | 3741 | val2 = _cs_ac97_get(dev, AC97_CD_VOL); |
3741 | 3742 | ||
3742 | /* | 3743 | /* |
3743 | * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address | 3744 | * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address |
3744 | * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 | 3745 | * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 |
3745 | * 3. Write ACCTL = Control Register = 460h for initiating the write | 3746 | * 3. Write ACCTL = Control Register = 460h for initiating the write |
3746 | * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h | 3747 | * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h |
3747 | * 5. if DCV not cleared, break and return error | 3748 | * 5. if DCV not cleared, break and return error |
3748 | */ | 3749 | */ |
3749 | 3750 | ||
3750 | /* | 3751 | /* |
3751 | * Setup the AC97 control registers on the CS461x to send the | 3752 | * Setup the AC97 control registers on the CS461x to send the |
3752 | * appropriate command to the AC97 to perform the read. | 3753 | * appropriate command to the AC97 to perform the read. |
3753 | * ACCAD = Command Address Register = 46Ch | 3754 | * ACCAD = Command Address Register = 46Ch |
3754 | * ACCDA = Command Data Register = 470h | 3755 | * ACCDA = Command Data Register = 470h |
3755 | * ACCTL = Control Register = 460h | 3756 | * ACCTL = Control Register = 460h |
3756 | * set DCV - will clear when process completed | 3757 | * set DCV - will clear when process completed |
3757 | * reset CRW - Write command | 3758 | * reset CRW - Write command |
3758 | * set VFRM - valid frame enabled | 3759 | * set VFRM - valid frame enabled |
3759 | * set ESYN - ASYNC generation enabled | 3760 | * set ESYN - ASYNC generation enabled |
3760 | * set RSTN - ARST# inactive, AC97 codec not reset | 3761 | * set RSTN - ARST# inactive, AC97 codec not reset |
3761 | */ | 3762 | */ |
3762 | cs461x_pokeBA0(card, BA0_ACCAD, reg); | 3763 | cs461x_pokeBA0(card, BA0_ACCAD, reg); |
3763 | cs461x_pokeBA0(card, BA0_ACCDA, val); | 3764 | cs461x_pokeBA0(card, BA0_ACCDA, val); |
3764 | cs461x_peekBA0(card, BA0_ACCTL); | 3765 | cs461x_peekBA0(card, BA0_ACCTL); |
3765 | cs461x_pokeBA0(card, BA0_ACCTL, 0 | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); | 3766 | cs461x_pokeBA0(card, BA0_ACCTL, 0 | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); |
3766 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | | 3767 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | |
3767 | ACCTL_ESYN | ACCTL_RSTN); | 3768 | ACCTL_ESYN | ACCTL_RSTN); |
3768 | for (count = 0; count < 1000; count++) { | 3769 | for (count = 0; count < 1000; count++) { |
3769 | /* | 3770 | /* |
3770 | * First, we want to wait for a short time. | 3771 | * First, we want to wait for a short time. |
3771 | */ | 3772 | */ |
3772 | udelay(10 * cs_laptop_wait); | 3773 | udelay(10 * cs_laptop_wait); |
3773 | /* | 3774 | /* |
3774 | * Now, check to see if the write has completed. | 3775 | * Now, check to see if the write has completed. |
3775 | * ACCTL = 460h, DCV should be reset by now and 460h = 07h | 3776 | * ACCTL = 460h, DCV should be reset by now and 460h = 07h |
3776 | */ | 3777 | */ |
3777 | if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV)) | 3778 | if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV)) |
3778 | break; | 3779 | break; |
3779 | } | 3780 | } |
3780 | /* | 3781 | /* |
3781 | * Make sure the write completed. | 3782 | * Make sure the write completed. |
3782 | */ | 3783 | */ |
3783 | if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) { | 3784 | if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) { |
3784 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 3785 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
3785 | "cs46xx: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val)); | 3786 | "cs46xx: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val)); |
3786 | } | 3787 | } |
3787 | 3788 | ||
3788 | spin_unlock(&card->ac97_lock); | 3789 | spin_unlock(&card->ac97_lock); |
3789 | 3790 | ||
3790 | /* | 3791 | /* |
3791 | * Adjust power if the mixer is selected/deselected according | 3792 | * Adjust power if the mixer is selected/deselected according |
3792 | * to the CD. | 3793 | * to the CD. |
3793 | * | 3794 | * |
3794 | * IF the CD is a valid input source (mixer or direct) AND | 3795 | * IF the CD is a valid input source (mixer or direct) AND |
3795 | * the CD is not muted THEN power is needed | 3796 | * the CD is not muted THEN power is needed |
3796 | * | 3797 | * |
3797 | * We do two things. When record select changes the input to | 3798 | * We do two things. When record select changes the input to |
3798 | * add/remove the CD we adjust the power count if the CD is | 3799 | * add/remove the CD we adjust the power count if the CD is |
3799 | * unmuted. | 3800 | * unmuted. |
3800 | * | 3801 | * |
3801 | * When the CD mute changes we adjust the power level if the | 3802 | * When the CD mute changes we adjust the power level if the |
3802 | * CD was a valid input. | 3803 | * CD was a valid input. |
3803 | * | 3804 | * |
3804 | * We also check for CD volume != 0, as the CD mute isn't | 3805 | * We also check for CD volume != 0, as the CD mute isn't |
3805 | * normally tweaked from userspace. | 3806 | * normally tweaked from userspace. |
3806 | */ | 3807 | */ |
3807 | 3808 | ||
3808 | /* CD mute change ? */ | 3809 | /* CD mute change ? */ |
3809 | 3810 | ||
3810 | if (reg == AC97_CD_VOL) { | 3811 | if (reg == AC97_CD_VOL) { |
3811 | /* Mute bit change ? */ | 3812 | /* Mute bit change ? */ |
3812 | if ((val2^val) & 0x8000 || | 3813 | if ((val2^val) & 0x8000 || |
3813 | ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val)) { | 3814 | ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val)) { |
3814 | /* This is a hack but its cleaner than the alternatives. | 3815 | /* This is a hack but its cleaner than the alternatives. |
3815 | Right now card->ac97_codec[0] might be NULL as we are | 3816 | Right now card->ac97_codec[0] might be NULL as we are |
3816 | still doing codec setup. This does an early assignment | 3817 | still doing codec setup. This does an early assignment |
3817 | to avoid the problem if it occurs */ | 3818 | to avoid the problem if it occurs */ |
3818 | 3819 | ||
3819 | if (card->ac97_codec[0] == NULL) | 3820 | if (card->ac97_codec[0] == NULL) |
3820 | card->ac97_codec[0] = dev; | 3821 | card->ac97_codec[0] = dev; |
3821 | 3822 | ||
3822 | /* Mute on */ | 3823 | /* Mute on */ |
3823 | if (val & 0x8000 || val == 0x1f1f) | 3824 | if (val & 0x8000 || val == 0x1f1f) |
3824 | card->amplifier_ctrl(card, -1); | 3825 | card->amplifier_ctrl(card, -1); |
3825 | else { /* Mute off power on */ | 3826 | else { /* Mute off power on */ |
3826 | if (card->amp_init) | 3827 | if (card->amp_init) |
3827 | card->amp_init(card); | 3828 | card->amp_init(card); |
3828 | card->amplifier_ctrl(card, 1); | 3829 | card->amplifier_ctrl(card, 1); |
3829 | } | 3830 | } |
3830 | } | 3831 | } |
3831 | } | 3832 | } |
3832 | } | 3833 | } |
3833 | 3834 | ||
3834 | /* OSS /dev/mixer file operation methods */ | 3835 | /* OSS /dev/mixer file operation methods */ |
3835 | 3836 | ||
3836 | static int cs_open_mixdev(struct inode *inode, struct file *file) | 3837 | static int cs_open_mixdev(struct inode *inode, struct file *file) |
3837 | { | 3838 | { |
3838 | int i = 0; | 3839 | int i = 0; |
3839 | unsigned int minor = iminor(inode); | 3840 | unsigned int minor = iminor(inode); |
3840 | struct cs_card *card = NULL; | 3841 | struct cs_card *card = NULL; |
3841 | struct list_head *entry; | 3842 | struct list_head *entry; |
3842 | unsigned int tmp; | 3843 | unsigned int tmp; |
3843 | 3844 | ||
3844 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, | 3845 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, |
3845 | printk(KERN_INFO "cs46xx: cs_open_mixdev()+\n")); | 3846 | printk(KERN_INFO "cs46xx: cs_open_mixdev()+\n")); |
3846 | 3847 | ||
3847 | list_for_each(entry, &cs46xx_devs) { | 3848 | list_for_each(entry, &cs46xx_devs) { |
3848 | card = list_entry(entry, struct cs_card, list); | 3849 | card = list_entry(entry, struct cs_card, list); |
3849 | for (i = 0; i < NR_AC97; i++) | 3850 | for (i = 0; i < NR_AC97; i++) |
3850 | if (card->ac97_codec[i] != NULL && | 3851 | if (card->ac97_codec[i] != NULL && |
3851 | card->ac97_codec[i]->dev_mixer == minor) | 3852 | card->ac97_codec[i]->dev_mixer == minor) |
3852 | goto match; | 3853 | goto match; |
3853 | } | 3854 | } |
3854 | if (!card) { | 3855 | if (!card) { |
3855 | CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, | 3856 | CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, |
3856 | printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n")); | 3857 | printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n")); |
3857 | return -ENODEV; | 3858 | return -ENODEV; |
3858 | } | 3859 | } |
3859 | match: | 3860 | match: |
3860 | if (!card->ac97_codec[i]) | 3861 | if (!card->ac97_codec[i]) |
3861 | return -ENODEV; | 3862 | return -ENODEV; |
3862 | file->private_data = card->ac97_codec[i]; | 3863 | file->private_data = card->ac97_codec[i]; |
3863 | 3864 | ||
3864 | card->active_ctrl(card,1); | 3865 | card->active_ctrl(card,1); |
3865 | if (!CS_IN_USE(&card->mixer_use_cnt)) { | 3866 | if (!CS_IN_USE(&card->mixer_use_cnt)) { |
3866 | if ((tmp = cs46xx_powerup(card, CS_POWER_MIXVON))) { | 3867 | if ((tmp = cs46xx_powerup(card, CS_POWER_MIXVON))) { |
3867 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 3868 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
3868 | "cs46xx: cs_open_mixdev() powerup failure (0x%x)\n", tmp)); | 3869 | "cs46xx: cs_open_mixdev() powerup failure (0x%x)\n", tmp)); |
3869 | return -EIO; | 3870 | return -EIO; |
3870 | } | 3871 | } |
3871 | } | 3872 | } |
3872 | card->amplifier_ctrl(card, 1); | 3873 | card->amplifier_ctrl(card, 1); |
3873 | CS_INC_USE_COUNT(&card->mixer_use_cnt); | 3874 | CS_INC_USE_COUNT(&card->mixer_use_cnt); |
3874 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, | 3875 | CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, |
3875 | printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n")); | 3876 | printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n")); |
3876 | return nonseekable_open(inode, file); | 3877 | return nonseekable_open(inode, file); |
3877 | } | 3878 | } |
3878 | 3879 | ||
3879 | static int cs_release_mixdev(struct inode *inode, struct file *file) | 3880 | static int cs_release_mixdev(struct inode *inode, struct file *file) |
3880 | { | 3881 | { |
3881 | unsigned int minor = iminor(inode); | 3882 | unsigned int minor = iminor(inode); |
3882 | struct cs_card *card = NULL; | 3883 | struct cs_card *card = NULL; |
3883 | struct list_head *entry; | 3884 | struct list_head *entry; |
3884 | int i; | 3885 | int i; |
3885 | unsigned int tmp; | 3886 | unsigned int tmp; |
3886 | 3887 | ||
3887 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, | 3888 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, |
3888 | printk(KERN_INFO "cs46xx: cs_release_mixdev()+\n")); | 3889 | printk(KERN_INFO "cs46xx: cs_release_mixdev()+\n")); |
3889 | list_for_each(entry, &cs46xx_devs) | 3890 | list_for_each(entry, &cs46xx_devs) |
3890 | { | 3891 | { |
3891 | card = list_entry(entry, struct cs_card, list); | 3892 | card = list_entry(entry, struct cs_card, list); |
3892 | for (i = 0; i < NR_AC97; i++) | 3893 | for (i = 0; i < NR_AC97; i++) |
3893 | if (card->ac97_codec[i] != NULL && | 3894 | if (card->ac97_codec[i] != NULL && |
3894 | card->ac97_codec[i]->dev_mixer == minor) | 3895 | card->ac97_codec[i]->dev_mixer == minor) |
3895 | goto match; | 3896 | goto match; |
3896 | } | 3897 | } |
3897 | if (!card) { | 3898 | if (!card) { |
3898 | CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, | 3899 | CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, |
3899 | printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n")); | 3900 | printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n")); |
3900 | return -ENODEV; | 3901 | return -ENODEV; |
3901 | } | 3902 | } |
3902 | match: | 3903 | match: |
3903 | if (!CS_DEC_AND_TEST(&card->mixer_use_cnt)) { | 3904 | if (!CS_DEC_AND_TEST(&card->mixer_use_cnt)) { |
3904 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, | 3905 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, |
3905 | printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n")); | 3906 | printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n")); |
3906 | card->active_ctrl(card, -1); | 3907 | card->active_ctrl(card, -1); |
3907 | card->amplifier_ctrl(card, -1); | 3908 | card->amplifier_ctrl(card, -1); |
3908 | return 0; | 3909 | return 0; |
3909 | } | 3910 | } |
3910 | /* | 3911 | /* |
3911 | * ok, no outstanding mixer opens, so powerdown. | 3912 | * ok, no outstanding mixer opens, so powerdown. |
3912 | */ | 3913 | */ |
3913 | if ((tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE))) { | 3914 | if ((tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE))) { |
3914 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 3915 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
3915 | "cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n", tmp)); | 3916 | "cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n", tmp)); |
3916 | card->active_ctrl(card, -1); | 3917 | card->active_ctrl(card, -1); |
3917 | card->amplifier_ctrl(card, -1); | 3918 | card->amplifier_ctrl(card, -1); |
3918 | return -EIO; | 3919 | return -EIO; |
3919 | } | 3920 | } |
3920 | card->active_ctrl(card, -1); | 3921 | card->active_ctrl(card, -1); |
3921 | card->amplifier_ctrl(card, -1); | 3922 | card->amplifier_ctrl(card, -1); |
3922 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, | 3923 | CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, |
3923 | printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n")); | 3924 | printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n")); |
3924 | return 0; | 3925 | return 0; |
3925 | } | 3926 | } |
3926 | 3927 | ||
3927 | static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, | 3928 | static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, |
3928 | unsigned long arg) | 3929 | unsigned long arg) |
3929 | { | 3930 | { |
3930 | struct ac97_codec *codec = file->private_data; | 3931 | struct ac97_codec *codec = file->private_data; |
3931 | struct cs_card *card = NULL; | 3932 | struct cs_card *card = NULL; |
3932 | struct list_head *entry; | 3933 | struct list_head *entry; |
3933 | unsigned long __user *p = (long __user *)arg; | 3934 | unsigned long __user *p = (long __user *)arg; |
3934 | #if CSDEBUG_INTERFACE | 3935 | #if CSDEBUG_INTERFACE |
3935 | int val; | 3936 | int val; |
3936 | 3937 | ||
3937 | if ( (cmd == SOUND_MIXER_CS_GETDBGMASK) || | 3938 | if ( (cmd == SOUND_MIXER_CS_GETDBGMASK) || |
3938 | (cmd == SOUND_MIXER_CS_SETDBGMASK) || | 3939 | (cmd == SOUND_MIXER_CS_SETDBGMASK) || |
3939 | (cmd == SOUND_MIXER_CS_GETDBGLEVEL) || | 3940 | (cmd == SOUND_MIXER_CS_GETDBGLEVEL) || |
3940 | (cmd == SOUND_MIXER_CS_SETDBGLEVEL) || | 3941 | (cmd == SOUND_MIXER_CS_SETDBGLEVEL) || |
3941 | (cmd == SOUND_MIXER_CS_APM)) { | 3942 | (cmd == SOUND_MIXER_CS_APM)) { |
3942 | switch (cmd) { | 3943 | switch (cmd) { |
3943 | case SOUND_MIXER_CS_GETDBGMASK: | 3944 | case SOUND_MIXER_CS_GETDBGMASK: |
3944 | return put_user(cs_debugmask, p); | 3945 | return put_user(cs_debugmask, p); |
3945 | case SOUND_MIXER_CS_GETDBGLEVEL: | 3946 | case SOUND_MIXER_CS_GETDBGLEVEL: |
3946 | return put_user(cs_debuglevel, p); | 3947 | return put_user(cs_debuglevel, p); |
3947 | case SOUND_MIXER_CS_SETDBGMASK: | 3948 | case SOUND_MIXER_CS_SETDBGMASK: |
3948 | if (get_user(val, p)) | 3949 | if (get_user(val, p)) |
3949 | return -EFAULT; | 3950 | return -EFAULT; |
3950 | cs_debugmask = val; | 3951 | cs_debugmask = val; |
3951 | return 0; | 3952 | return 0; |
3952 | case SOUND_MIXER_CS_SETDBGLEVEL: | 3953 | case SOUND_MIXER_CS_SETDBGLEVEL: |
3953 | if (get_user(val, p)) | 3954 | if (get_user(val, p)) |
3954 | return -EFAULT; | 3955 | return -EFAULT; |
3955 | cs_debuglevel = val; | 3956 | cs_debuglevel = val; |
3956 | return 0; | 3957 | return 0; |
3957 | case SOUND_MIXER_CS_APM: | 3958 | case SOUND_MIXER_CS_APM: |
3958 | if (get_user(val, p)) | 3959 | if (get_user(val, p)) |
3959 | return -EFAULT; | 3960 | return -EFAULT; |
3960 | if (val == CS_IOCTL_CMD_SUSPEND) { | 3961 | if (val == CS_IOCTL_CMD_SUSPEND) { |
3961 | list_for_each(entry, &cs46xx_devs) { | 3962 | list_for_each(entry, &cs46xx_devs) { |
3962 | card = list_entry(entry, struct cs_card, list); | 3963 | card = list_entry(entry, struct cs_card, list); |
3963 | cs46xx_suspend(card, PMSG_ON); | 3964 | cs46xx_suspend(card, PMSG_ON); |
3964 | } | 3965 | } |
3965 | 3966 | ||
3966 | } else if (val == CS_IOCTL_CMD_RESUME) { | 3967 | } else if (val == CS_IOCTL_CMD_RESUME) { |
3967 | list_for_each(entry, &cs46xx_devs) { | 3968 | list_for_each(entry, &cs46xx_devs) { |
3968 | card = list_entry(entry, struct cs_card, list); | 3969 | card = list_entry(entry, struct cs_card, list); |
3969 | cs46xx_resume(card); | 3970 | cs46xx_resume(card); |
3970 | } | 3971 | } |
3971 | } else { | 3972 | } else { |
3972 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO | 3973 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO |
3973 | "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n", | 3974 | "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n", |
3974 | val)); | 3975 | val)); |
3975 | } | 3976 | } |
3976 | return 0; | 3977 | return 0; |
3977 | default: | 3978 | default: |
3978 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO | 3979 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO |
3979 | "cs46xx: mixer_ioctl(): ERROR unknown debug cmd\n")); | 3980 | "cs46xx: mixer_ioctl(): ERROR unknown debug cmd\n")); |
3980 | return 0; | 3981 | return 0; |
3981 | } | 3982 | } |
3982 | } | 3983 | } |
3983 | #endif | 3984 | #endif |
3984 | return codec->mixer_ioctl(codec, cmd, arg); | 3985 | return codec->mixer_ioctl(codec, cmd, arg); |
3985 | } | 3986 | } |
3986 | 3987 | ||
3987 | static /*const*/ struct file_operations cs_mixer_fops = { | 3988 | static /*const*/ struct file_operations cs_mixer_fops = { |
3988 | CS_OWNER CS_THIS_MODULE | 3989 | CS_OWNER CS_THIS_MODULE |
3989 | .llseek = no_llseek, | 3990 | .llseek = no_llseek, |
3990 | .ioctl = cs_ioctl_mixdev, | 3991 | .ioctl = cs_ioctl_mixdev, |
3991 | .open = cs_open_mixdev, | 3992 | .open = cs_open_mixdev, |
3992 | .release = cs_release_mixdev, | 3993 | .release = cs_release_mixdev, |
3993 | }; | 3994 | }; |
3994 | 3995 | ||
3995 | /* AC97 codec initialisation. */ | 3996 | /* AC97 codec initialisation. */ |
3996 | static int __init cs_ac97_init(struct cs_card *card) | 3997 | static int __init cs_ac97_init(struct cs_card *card) |
3997 | { | 3998 | { |
3998 | int num_ac97 = 0; | 3999 | int num_ac97 = 0; |
3999 | int ready_2nd = 0; | 4000 | int ready_2nd = 0; |
4000 | struct ac97_codec *codec; | 4001 | struct ac97_codec *codec; |
4001 | u16 eid; | 4002 | u16 eid; |
4002 | 4003 | ||
4003 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO | 4004 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO |
4004 | "cs46xx: cs_ac97_init()+\n") ); | 4005 | "cs46xx: cs_ac97_init()+\n") ); |
4005 | 4006 | ||
4006 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { | 4007 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { |
4007 | if ((codec = ac97_alloc_codec()) == NULL) | 4008 | if ((codec = ac97_alloc_codec()) == NULL) |
4008 | return -ENOMEM; | 4009 | return -ENOMEM; |
4009 | 4010 | ||
4010 | /* initialize some basic codec information, other fields will be filled | 4011 | /* initialize some basic codec information, other fields will be filled |
4011 | in ac97_probe_codec */ | 4012 | in ac97_probe_codec */ |
4012 | codec->private_data = card; | 4013 | codec->private_data = card; |
4013 | codec->id = num_ac97; | 4014 | codec->id = num_ac97; |
4014 | 4015 | ||
4015 | codec->codec_read = cs_ac97_get; | 4016 | codec->codec_read = cs_ac97_get; |
4016 | codec->codec_write = cs_ac97_set; | 4017 | codec->codec_write = cs_ac97_set; |
4017 | 4018 | ||
4018 | if (ac97_probe_codec(codec) == 0) { | 4019 | if (ac97_probe_codec(codec) == 0) { |
4019 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO | 4020 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO |
4020 | "cs46xx: cs_ac97_init()- codec number %d not found\n", | 4021 | "cs46xx: cs_ac97_init()- codec number %d not found\n", |
4021 | num_ac97) ); | 4022 | num_ac97) ); |
4022 | card->ac97_codec[num_ac97] = NULL; | 4023 | card->ac97_codec[num_ac97] = NULL; |
4023 | break; | 4024 | break; |
4024 | } | 4025 | } |
4025 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO | 4026 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO |
4026 | "cs46xx: cs_ac97_init() found codec %d\n",num_ac97)); | 4027 | "cs46xx: cs_ac97_init() found codec %d\n",num_ac97)); |
4027 | 4028 | ||
4028 | eid = cs_ac97_get(codec, AC97_EXTENDED_ID); | 4029 | eid = cs_ac97_get(codec, AC97_EXTENDED_ID); |
4029 | 4030 | ||
4030 | if (eid == 0xFFFF) { | 4031 | if (eid == 0xFFFF) { |
4031 | printk(KERN_WARNING "cs46xx: codec %d not present\n",num_ac97); | 4032 | printk(KERN_WARNING "cs46xx: codec %d not present\n",num_ac97); |
4032 | ac97_release_codec(codec); | 4033 | ac97_release_codec(codec); |
4033 | break; | 4034 | break; |
4034 | } | 4035 | } |
4035 | 4036 | ||
4036 | card->ac97_features = eid; | 4037 | card->ac97_features = eid; |
4037 | 4038 | ||
4038 | if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) { | 4039 | if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) { |
4039 | printk(KERN_ERR "cs46xx: couldn't register mixer!\n"); | 4040 | printk(KERN_ERR "cs46xx: couldn't register mixer!\n"); |
4040 | ac97_release_codec(codec); | 4041 | ac97_release_codec(codec); |
4041 | break; | 4042 | break; |
4042 | } | 4043 | } |
4043 | card->ac97_codec[num_ac97] = codec; | 4044 | card->ac97_codec[num_ac97] = codec; |
4044 | 4045 | ||
4045 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO | 4046 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO |
4046 | "cs46xx: cs_ac97_init() ac97_codec[%d] set to %p\n", | 4047 | "cs46xx: cs_ac97_init() ac97_codec[%d] set to %p\n", |
4047 | (unsigned int)num_ac97, | 4048 | (unsigned int)num_ac97, |
4048 | codec)); | 4049 | codec)); |
4049 | /* if there is no secondary codec at all, don't probe any more */ | 4050 | /* if there is no secondary codec at all, don't probe any more */ |
4050 | if (!ready_2nd) | 4051 | if (!ready_2nd) |
4051 | { | 4052 | { |
4052 | num_ac97 += 1; | 4053 | num_ac97 += 1; |
4053 | break; | 4054 | break; |
4054 | } | 4055 | } |
4055 | } | 4056 | } |
4056 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO | 4057 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO |
4057 | "cs46xx: cs_ac97_init()- %d\n", (unsigned int)num_ac97)); | 4058 | "cs46xx: cs_ac97_init()- %d\n", (unsigned int)num_ac97)); |
4058 | return num_ac97; | 4059 | return num_ac97; |
4059 | } | 4060 | } |
4060 | 4061 | ||
4061 | /* | 4062 | /* |
4062 | * load the static image into the DSP | 4063 | * load the static image into the DSP |
4063 | */ | 4064 | */ |
4064 | #include "cs461x_image.h" | 4065 | #include "cs461x_image.h" |
4065 | static void cs461x_download_image(struct cs_card *card) | 4066 | static void cs461x_download_image(struct cs_card *card) |
4066 | { | 4067 | { |
4067 | unsigned i, j, temp1, temp2, offset, count; | 4068 | unsigned i, j, temp1, temp2, offset, count; |
4068 | unsigned char __iomem *pBA1 = ioremap(card->ba1_addr, 0x40000); | 4069 | unsigned char __iomem *pBA1 = ioremap(card->ba1_addr, 0x40000); |
4069 | for (i = 0; i < CLEAR__COUNT; i++) { | 4070 | for (i = 0; i < CLEAR__COUNT; i++) { |
4070 | offset = ClrStat[i].BA1__DestByteOffset; | 4071 | offset = ClrStat[i].BA1__DestByteOffset; |
4071 | count = ClrStat[i].BA1__SourceSize; | 4072 | count = ClrStat[i].BA1__SourceSize; |
4072 | for (temp1 = offset; temp1 < (offset + count); temp1 += 4) | 4073 | for (temp1 = offset; temp1 < (offset + count); temp1 += 4) |
4073 | writel(0, pBA1+temp1); | 4074 | writel(0, pBA1+temp1); |
4074 | } | 4075 | } |
4075 | 4076 | ||
4076 | for (i = 0; i < FILL__COUNT; i++) { | 4077 | for (i = 0; i < FILL__COUNT; i++) { |
4077 | temp2 = FillStat[i].Offset; | 4078 | temp2 = FillStat[i].Offset; |
4078 | for (j = 0; j < (FillStat[i].Size) / 4; j++) { | 4079 | for (j = 0; j < (FillStat[i].Size) / 4; j++) { |
4079 | temp1 = (FillStat[i]).pFill[j]; | 4080 | temp1 = (FillStat[i]).pFill[j]; |
4080 | writel(temp1, pBA1+temp2 + j * 4); | 4081 | writel(temp1, pBA1+temp2 + j * 4); |
4081 | } | 4082 | } |
4082 | } | 4083 | } |
4083 | iounmap(pBA1); | 4084 | iounmap(pBA1); |
4084 | } | 4085 | } |
4085 | 4086 | ||
4086 | /* | 4087 | /* |
4087 | * Chip reset | 4088 | * Chip reset |
4088 | */ | 4089 | */ |
4089 | 4090 | ||
4090 | static void cs461x_reset(struct cs_card *card) | 4091 | static void cs461x_reset(struct cs_card *card) |
4091 | { | 4092 | { |
4092 | int idx; | 4093 | int idx; |
4093 | 4094 | ||
4094 | /* | 4095 | /* |
4095 | * Write the reset bit of the SP control register. | 4096 | * Write the reset bit of the SP control register. |
4096 | */ | 4097 | */ |
4097 | cs461x_poke(card, BA1_SPCR, SPCR_RSTSP); | 4098 | cs461x_poke(card, BA1_SPCR, SPCR_RSTSP); |
4098 | 4099 | ||
4099 | /* | 4100 | /* |
4100 | * Write the control register. | 4101 | * Write the control register. |
4101 | */ | 4102 | */ |
4102 | cs461x_poke(card, BA1_SPCR, SPCR_DRQEN); | 4103 | cs461x_poke(card, BA1_SPCR, SPCR_DRQEN); |
4103 | 4104 | ||
4104 | /* | 4105 | /* |
4105 | * Clear the trap registers. | 4106 | * Clear the trap registers. |
4106 | */ | 4107 | */ |
4107 | for (idx = 0; idx < 8; idx++) { | 4108 | for (idx = 0; idx < 8; idx++) { |
4108 | cs461x_poke(card, BA1_DREG, DREG_REGID_TRAP_SELECT + idx); | 4109 | cs461x_poke(card, BA1_DREG, DREG_REGID_TRAP_SELECT + idx); |
4109 | cs461x_poke(card, BA1_TWPR, 0xFFFF); | 4110 | cs461x_poke(card, BA1_TWPR, 0xFFFF); |
4110 | } | 4111 | } |
4111 | cs461x_poke(card, BA1_DREG, 0); | 4112 | cs461x_poke(card, BA1_DREG, 0); |
4112 | 4113 | ||
4113 | /* | 4114 | /* |
4114 | * Set the frame timer to reflect the number of cycles per frame. | 4115 | * Set the frame timer to reflect the number of cycles per frame. |
4115 | */ | 4116 | */ |
4116 | cs461x_poke(card, BA1_FRMT, 0xadf); | 4117 | cs461x_poke(card, BA1_FRMT, 0xadf); |
4117 | } | 4118 | } |
4118 | 4119 | ||
4119 | static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type) | 4120 | static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type) |
4120 | { | 4121 | { |
4121 | int idx, loop, startfifo=0, endfifo=0, powerdown1 = 0; | 4122 | int idx, loop, startfifo=0, endfifo=0, powerdown1 = 0; |
4122 | unsigned int tmp; | 4123 | unsigned int tmp; |
4123 | 4124 | ||
4124 | /* | 4125 | /* |
4125 | * See if the devices are powered down. If so, we must power them up first | 4126 | * See if the devices are powered down. If so, we must power them up first |
4126 | * or they will not respond. | 4127 | * or they will not respond. |
4127 | */ | 4128 | */ |
4128 | if (!((tmp = cs461x_peekBA0(card, BA0_CLKCR1)) & CLKCR1_SWCE)) { | 4129 | if (!((tmp = cs461x_peekBA0(card, BA0_CLKCR1)) & CLKCR1_SWCE)) { |
4129 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp | CLKCR1_SWCE); | 4130 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp | CLKCR1_SWCE); |
4130 | powerdown1 = 1; | 4131 | powerdown1 = 1; |
4131 | } | 4132 | } |
4132 | 4133 | ||
4133 | /* | 4134 | /* |
4134 | * We want to clear out the serial port FIFOs so we don't end up playing | 4135 | * We want to clear out the serial port FIFOs so we don't end up playing |
4135 | * whatever random garbage happens to be in them. We fill the sample FIFOS | 4136 | * whatever random garbage happens to be in them. We fill the sample FIFOS |
4136 | * with zero (silence). | 4137 | * with zero (silence). |
4137 | */ | 4138 | */ |
4138 | cs461x_pokeBA0(card, BA0_SERBWP, 0); | 4139 | cs461x_pokeBA0(card, BA0_SERBWP, 0); |
4139 | 4140 | ||
4140 | /* | 4141 | /* |
4141 | * Check for which FIFO locations to clear, if we are currently | 4142 | * Check for which FIFO locations to clear, if we are currently |
4142 | * playing or capturing then we don't want to put in 128 bytes of | 4143 | * playing or capturing then we don't want to put in 128 bytes of |
4143 | * "noise". | 4144 | * "noise". |
4144 | */ | 4145 | */ |
4145 | if (type & CS_TYPE_DAC) { | 4146 | if (type & CS_TYPE_DAC) { |
4146 | startfifo = 128; | 4147 | startfifo = 128; |
4147 | endfifo = 256; | 4148 | endfifo = 256; |
4148 | } | 4149 | } |
4149 | if (type & CS_TYPE_ADC) { | 4150 | if (type & CS_TYPE_ADC) { |
4150 | startfifo = 0; | 4151 | startfifo = 0; |
4151 | if (!endfifo) | 4152 | if (!endfifo) |
4152 | endfifo = 128; | 4153 | endfifo = 128; |
4153 | } | 4154 | } |
4154 | /* | 4155 | /* |
4155 | * Fill sample FIFO locations (256 locations total). | 4156 | * Fill sample FIFO locations (256 locations total). |
4156 | */ | 4157 | */ |
4157 | for (idx = startfifo; idx < endfifo; idx++) { | 4158 | for (idx = startfifo; idx < endfifo; idx++) { |
4158 | /* | 4159 | /* |
4159 | * Make sure the previous FIFO write operation has completed. | 4160 | * Make sure the previous FIFO write operation has completed. |
4160 | */ | 4161 | */ |
4161 | for (loop = 0; loop < 5; loop++) { | 4162 | for (loop = 0; loop < 5; loop++) { |
4162 | udelay(50); | 4163 | udelay(50); |
4163 | if (!(cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY)) | 4164 | if (!(cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY)) |
4164 | break; | 4165 | break; |
4165 | } | 4166 | } |
4166 | if (cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY) { | 4167 | if (cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY) { |
4167 | if (powerdown1) | 4168 | if (powerdown1) |
4168 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); | 4169 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); |
4169 | } | 4170 | } |
4170 | /* | 4171 | /* |
4171 | * Write the serial port FIFO index. | 4172 | * Write the serial port FIFO index. |
4172 | */ | 4173 | */ |
4173 | cs461x_pokeBA0(card, BA0_SERBAD, idx); | 4174 | cs461x_pokeBA0(card, BA0_SERBAD, idx); |
4174 | /* | 4175 | /* |
4175 | * Tell the serial port to load the new value into the FIFO location. | 4176 | * Tell the serial port to load the new value into the FIFO location. |
4176 | */ | 4177 | */ |
4177 | cs461x_pokeBA0(card, BA0_SERBCM, SERBCM_WRC); | 4178 | cs461x_pokeBA0(card, BA0_SERBCM, SERBCM_WRC); |
4178 | } | 4179 | } |
4179 | /* | 4180 | /* |
4180 | * Now, if we powered up the devices, then power them back down again. | 4181 | * Now, if we powered up the devices, then power them back down again. |
4181 | * This is kinda ugly, but should never happen. | 4182 | * This is kinda ugly, but should never happen. |
4182 | */ | 4183 | */ |
4183 | if (powerdown1) | 4184 | if (powerdown1) |
4184 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); | 4185 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); |
4185 | } | 4186 | } |
4186 | 4187 | ||
4187 | 4188 | ||
4188 | static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag) | 4189 | static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag) |
4189 | { | 4190 | { |
4190 | int count; | 4191 | int count; |
4191 | unsigned int tmp=0,muted=0; | 4192 | unsigned int tmp=0,muted=0; |
4192 | 4193 | ||
4193 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO | 4194 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO |
4194 | "cs46xx: cs461x_powerdown()+ type=0x%x\n",type)); | 4195 | "cs46xx: cs461x_powerdown()+ type=0x%x\n",type)); |
4195 | if (!cs_powerdown && !suspendflag) { | 4196 | if (!cs_powerdown && !suspendflag) { |
4196 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO | 4197 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO |
4197 | "cs46xx: cs461x_powerdown() DISABLED exiting\n")); | 4198 | "cs46xx: cs461x_powerdown() DISABLED exiting\n")); |
4198 | return 0; | 4199 | return 0; |
4199 | } | 4200 | } |
4200 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4201 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4201 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO | 4202 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO |
4202 | "cs46xx: cs461x_powerdown() powerdown reg=0x%x\n",tmp)); | 4203 | "cs46xx: cs461x_powerdown() powerdown reg=0x%x\n",tmp)); |
4203 | /* | 4204 | /* |
4204 | * if powering down only the VREF, and not powering down the DAC/ADC, | 4205 | * if powering down only the VREF, and not powering down the DAC/ADC, |
4205 | * then do not power down the VREF, UNLESS both the DAC and ADC are not | 4206 | * then do not power down the VREF, UNLESS both the DAC and ADC are not |
4206 | * currently powered down. If powering down DAC and ADC, then | 4207 | * currently powered down. If powering down DAC and ADC, then |
4207 | * it is possible to power down the VREF (ON). | 4208 | * it is possible to power down the VREF (ON). |
4208 | */ | 4209 | */ |
4209 | if (((type & CS_POWER_MIXVON) && | 4210 | if (((type & CS_POWER_MIXVON) && |
4210 | (!(type & CS_POWER_ADC) || (!(type & CS_POWER_DAC)))) | 4211 | (!(type & CS_POWER_ADC) || (!(type & CS_POWER_DAC)))) |
4211 | && | 4212 | && |
4212 | ((tmp & CS_AC97_POWER_CONTROL_ADC_ON) || | 4213 | ((tmp & CS_AC97_POWER_CONTROL_ADC_ON) || |
4213 | (tmp & CS_AC97_POWER_CONTROL_DAC_ON))) { | 4214 | (tmp & CS_AC97_POWER_CONTROL_DAC_ON))) { |
4214 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO | 4215 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO |
4215 | "cs46xx: cs461x_powerdown()- 0 unable to powerdown. tmp=0x%x\n",tmp)); | 4216 | "cs46xx: cs461x_powerdown()- 0 unable to powerdown. tmp=0x%x\n",tmp)); |
4216 | return 0; | 4217 | return 0; |
4217 | } | 4218 | } |
4218 | /* | 4219 | /* |
4219 | * for now, always keep power to the mixer block. | 4220 | * for now, always keep power to the mixer block. |
4220 | * not sure why it's a problem but it seems to be if we power off. | 4221 | * not sure why it's a problem but it seems to be if we power off. |
4221 | */ | 4222 | */ |
4222 | type &= ~CS_POWER_MIXVON; | 4223 | type &= ~CS_POWER_MIXVON; |
4223 | type &= ~CS_POWER_MIXVOFF; | 4224 | type &= ~CS_POWER_MIXVOFF; |
4224 | 4225 | ||
4225 | /* | 4226 | /* |
4226 | * Power down indicated areas. | 4227 | * Power down indicated areas. |
4227 | */ | 4228 | */ |
4228 | if (type & CS_POWER_MIXVOFF) { | 4229 | if (type & CS_POWER_MIXVOFF) { |
4229 | 4230 | ||
4230 | CS_DBGOUT(CS_FUNCTION, 4, | 4231 | CS_DBGOUT(CS_FUNCTION, 4, |
4231 | printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVOFF\n")); | 4232 | printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVOFF\n")); |
4232 | /* | 4233 | /* |
4233 | * Power down the MIXER (VREF ON) on the AC97 card. | 4234 | * Power down the MIXER (VREF ON) on the AC97 card. |
4234 | */ | 4235 | */ |
4235 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4236 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4236 | if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON) { | 4237 | if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON) { |
4237 | if (!muted) { | 4238 | if (!muted) { |
4238 | cs_mute(card, CS_TRUE); | 4239 | cs_mute(card, CS_TRUE); |
4239 | muted = 1; | 4240 | muted = 1; |
4240 | } | 4241 | } |
4241 | tmp |= CS_AC97_POWER_CONTROL_MIXVOFF; | 4242 | tmp |= CS_AC97_POWER_CONTROL_MIXVOFF; |
4242 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); | 4243 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); |
4243 | /* | 4244 | /* |
4244 | * Now, we wait until we sample a ready state. | 4245 | * Now, we wait until we sample a ready state. |
4245 | */ | 4246 | */ |
4246 | for (count = 0; count < 32; count++) { | 4247 | for (count = 0; count < 32; count++) { |
4247 | /* | 4248 | /* |
4248 | * First, lets wait a short while to let things settle out a | 4249 | * First, lets wait a short while to let things settle out a |
4249 | * bit, and to prevent retrying the read too quickly. | 4250 | * bit, and to prevent retrying the read too quickly. |
4250 | */ | 4251 | */ |
4251 | udelay(500); | 4252 | udelay(500); |
4252 | 4253 | ||
4253 | /* | 4254 | /* |
4254 | * Read the current state of the power control register. | 4255 | * Read the current state of the power control register. |
4255 | */ | 4256 | */ |
4256 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4257 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4257 | CS_AC97_POWER_CONTROL_MIXVOFF_ON)) | 4258 | CS_AC97_POWER_CONTROL_MIXVOFF_ON)) |
4258 | break; | 4259 | break; |
4259 | } | 4260 | } |
4260 | 4261 | ||
4261 | /* | 4262 | /* |
4262 | * Check the status.. | 4263 | * Check the status.. |
4263 | */ | 4264 | */ |
4264 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4265 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4265 | CS_AC97_POWER_CONTROL_MIXVOFF_ON) { | 4266 | CS_AC97_POWER_CONTROL_MIXVOFF_ON) { |
4266 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4267 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4267 | "cs46xx: powerdown MIXVOFF failed\n")); | 4268 | "cs46xx: powerdown MIXVOFF failed\n")); |
4268 | return 1; | 4269 | return 1; |
4269 | } | 4270 | } |
4270 | } | 4271 | } |
4271 | } | 4272 | } |
4272 | if (type & CS_POWER_MIXVON) { | 4273 | if (type & CS_POWER_MIXVON) { |
4273 | 4274 | ||
4274 | CS_DBGOUT(CS_FUNCTION, 4, | 4275 | CS_DBGOUT(CS_FUNCTION, 4, |
4275 | printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVON\n")); | 4276 | printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVON\n")); |
4276 | /* | 4277 | /* |
4277 | * Power down the MIXER (VREF ON) on the AC97 card. | 4278 | * Power down the MIXER (VREF ON) on the AC97 card. |
4278 | */ | 4279 | */ |
4279 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4280 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4280 | if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON) { | 4281 | if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON) { |
4281 | if (!muted) { | 4282 | if (!muted) { |
4282 | cs_mute(card, CS_TRUE); | 4283 | cs_mute(card, CS_TRUE); |
4283 | muted = 1; | 4284 | muted = 1; |
4284 | } | 4285 | } |
4285 | tmp |= CS_AC97_POWER_CONTROL_MIXVON; | 4286 | tmp |= CS_AC97_POWER_CONTROL_MIXVON; |
4286 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp); | 4287 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp); |
4287 | /* | 4288 | /* |
4288 | * Now, we wait until we sample a ready state. | 4289 | * Now, we wait until we sample a ready state. |
4289 | */ | 4290 | */ |
4290 | for (count = 0; count < 32; count++) { | 4291 | for (count = 0; count < 32; count++) { |
4291 | /* | 4292 | /* |
4292 | * First, lets wait a short while to let things settle out a | 4293 | * First, lets wait a short while to let things settle out a |
4293 | * bit, and to prevent retrying the read too quickly. | 4294 | * bit, and to prevent retrying the read too quickly. |
4294 | */ | 4295 | */ |
4295 | udelay(500); | 4296 | udelay(500); |
4296 | 4297 | ||
4297 | /* | 4298 | /* |
4298 | * Read the current state of the power control register. | 4299 | * Read the current state of the power control register. |
4299 | */ | 4300 | */ |
4300 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4301 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4301 | CS_AC97_POWER_CONTROL_MIXVON_ON)) | 4302 | CS_AC97_POWER_CONTROL_MIXVON_ON)) |
4302 | break; | 4303 | break; |
4303 | } | 4304 | } |
4304 | 4305 | ||
4305 | /* | 4306 | /* |
4306 | * Check the status.. | 4307 | * Check the status.. |
4307 | */ | 4308 | */ |
4308 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4309 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4309 | CS_AC97_POWER_CONTROL_MIXVON_ON) { | 4310 | CS_AC97_POWER_CONTROL_MIXVON_ON) { |
4310 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4311 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4311 | "cs46xx: powerdown MIXVON failed\n")); | 4312 | "cs46xx: powerdown MIXVON failed\n")); |
4312 | return 1; | 4313 | return 1; |
4313 | } | 4314 | } |
4314 | } | 4315 | } |
4315 | } | 4316 | } |
4316 | if (type & CS_POWER_ADC) { | 4317 | if (type & CS_POWER_ADC) { |
4317 | /* | 4318 | /* |
4318 | * Power down the ADC on the AC97 card. | 4319 | * Power down the ADC on the AC97 card. |
4319 | */ | 4320 | */ |
4320 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()+ ADC\n")); | 4321 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()+ ADC\n")); |
4321 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4322 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4322 | if (tmp & CS_AC97_POWER_CONTROL_ADC_ON) { | 4323 | if (tmp & CS_AC97_POWER_CONTROL_ADC_ON) { |
4323 | if (!muted) { | 4324 | if (!muted) { |
4324 | cs_mute(card, CS_TRUE); | 4325 | cs_mute(card, CS_TRUE); |
4325 | muted = 1; | 4326 | muted = 1; |
4326 | } | 4327 | } |
4327 | tmp |= CS_AC97_POWER_CONTROL_ADC; | 4328 | tmp |= CS_AC97_POWER_CONTROL_ADC; |
4328 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp); | 4329 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp); |
4329 | 4330 | ||
4330 | /* | 4331 | /* |
4331 | * Now, we wait until we sample a ready state. | 4332 | * Now, we wait until we sample a ready state. |
4332 | */ | 4333 | */ |
4333 | for (count = 0; count < 32; count++) { | 4334 | for (count = 0; count < 32; count++) { |
4334 | /* | 4335 | /* |
4335 | * First, lets wait a short while to let things settle out a | 4336 | * First, lets wait a short while to let things settle out a |
4336 | * bit, and to prevent retrying the read too quickly. | 4337 | * bit, and to prevent retrying the read too quickly. |
4337 | */ | 4338 | */ |
4338 | udelay(500); | 4339 | udelay(500); |
4339 | 4340 | ||
4340 | /* | 4341 | /* |
4341 | * Read the current state of the power control register. | 4342 | * Read the current state of the power control register. |
4342 | */ | 4343 | */ |
4343 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4344 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4344 | CS_AC97_POWER_CONTROL_ADC_ON)) | 4345 | CS_AC97_POWER_CONTROL_ADC_ON)) |
4345 | break; | 4346 | break; |
4346 | } | 4347 | } |
4347 | 4348 | ||
4348 | /* | 4349 | /* |
4349 | * Check the status.. | 4350 | * Check the status.. |
4350 | */ | 4351 | */ |
4351 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4352 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4352 | CS_AC97_POWER_CONTROL_ADC_ON) { | 4353 | CS_AC97_POWER_CONTROL_ADC_ON) { |
4353 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4354 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4354 | "cs46xx: powerdown ADC failed\n")); | 4355 | "cs46xx: powerdown ADC failed\n")); |
4355 | return 1; | 4356 | return 1; |
4356 | } | 4357 | } |
4357 | } | 4358 | } |
4358 | } | 4359 | } |
4359 | if (type & CS_POWER_DAC) { | 4360 | if (type & CS_POWER_DAC) { |
4360 | /* | 4361 | /* |
4361 | * Power down the DAC on the AC97 card. | 4362 | * Power down the DAC on the AC97 card. |
4362 | */ | 4363 | */ |
4363 | 4364 | ||
4364 | CS_DBGOUT(CS_FUNCTION, 4, | 4365 | CS_DBGOUT(CS_FUNCTION, 4, |
4365 | printk(KERN_INFO "cs46xx: cs461x_powerdown()+ DAC\n")); | 4366 | printk(KERN_INFO "cs46xx: cs461x_powerdown()+ DAC\n")); |
4366 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4367 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4367 | if (tmp & CS_AC97_POWER_CONTROL_DAC_ON) { | 4368 | if (tmp & CS_AC97_POWER_CONTROL_DAC_ON) { |
4368 | if (!muted) { | 4369 | if (!muted) { |
4369 | cs_mute(card, CS_TRUE); | 4370 | cs_mute(card, CS_TRUE); |
4370 | muted = 1; | 4371 | muted = 1; |
4371 | } | 4372 | } |
4372 | tmp |= CS_AC97_POWER_CONTROL_DAC; | 4373 | tmp |= CS_AC97_POWER_CONTROL_DAC; |
4373 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp); | 4374 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp); |
4374 | /* | 4375 | /* |
4375 | * Now, we wait until we sample a ready state. | 4376 | * Now, we wait until we sample a ready state. |
4376 | */ | 4377 | */ |
4377 | for (count = 0; count < 32; count++) { | 4378 | for (count = 0; count < 32; count++) { |
4378 | /* | 4379 | /* |
4379 | * First, lets wait a short while to let things settle out a | 4380 | * First, lets wait a short while to let things settle out a |
4380 | * bit, and to prevent retrying the read too quickly. | 4381 | * bit, and to prevent retrying the read too quickly. |
4381 | */ | 4382 | */ |
4382 | udelay(500); | 4383 | udelay(500); |
4383 | 4384 | ||
4384 | /* | 4385 | /* |
4385 | * Read the current state of the power control register. | 4386 | * Read the current state of the power control register. |
4386 | */ | 4387 | */ |
4387 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4388 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4388 | CS_AC97_POWER_CONTROL_DAC_ON)) | 4389 | CS_AC97_POWER_CONTROL_DAC_ON)) |
4389 | break; | 4390 | break; |
4390 | } | 4391 | } |
4391 | 4392 | ||
4392 | /* | 4393 | /* |
4393 | * Check the status.. | 4394 | * Check the status.. |
4394 | */ | 4395 | */ |
4395 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4396 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4396 | CS_AC97_POWER_CONTROL_DAC_ON) { | 4397 | CS_AC97_POWER_CONTROL_DAC_ON) { |
4397 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4398 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4398 | "cs46xx: powerdown DAC failed\n")); | 4399 | "cs46xx: powerdown DAC failed\n")); |
4399 | return 1; | 4400 | return 1; |
4400 | } | 4401 | } |
4401 | } | 4402 | } |
4402 | } | 4403 | } |
4403 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4404 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4404 | if (muted) | 4405 | if (muted) |
4405 | cs_mute(card, CS_FALSE); | 4406 | cs_mute(card, CS_FALSE); |
4406 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO | 4407 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO |
4407 | "cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp)); | 4408 | "cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp)); |
4408 | return 0; | 4409 | return 0; |
4409 | } | 4410 | } |
4410 | 4411 | ||
4411 | static int cs46xx_powerup(struct cs_card *card, unsigned int type) | 4412 | static int cs46xx_powerup(struct cs_card *card, unsigned int type) |
4412 | { | 4413 | { |
4413 | int count; | 4414 | int count; |
4414 | unsigned int tmp = 0, muted = 0; | 4415 | unsigned int tmp = 0, muted = 0; |
4415 | 4416 | ||
4416 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO | 4417 | CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO |
4417 | "cs46xx: cs46xx_powerup()+ type=0x%x\n",type)); | 4418 | "cs46xx: cs46xx_powerup()+ type=0x%x\n",type)); |
4418 | /* | 4419 | /* |
4419 | * check for VREF and powerup if need to. | 4420 | * check for VREF and powerup if need to. |
4420 | */ | 4421 | */ |
4421 | if (type & CS_POWER_MIXVON) | 4422 | if (type & CS_POWER_MIXVON) |
4422 | type |= CS_POWER_MIXVOFF; | 4423 | type |= CS_POWER_MIXVOFF; |
4423 | if (type & (CS_POWER_DAC | CS_POWER_ADC)) | 4424 | if (type & (CS_POWER_DAC | CS_POWER_ADC)) |
4424 | type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF; | 4425 | type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF; |
4425 | 4426 | ||
4426 | /* | 4427 | /* |
4427 | * Power up indicated areas. | 4428 | * Power up indicated areas. |
4428 | */ | 4429 | */ |
4429 | if (type & CS_POWER_MIXVOFF) { | 4430 | if (type & CS_POWER_MIXVOFF) { |
4430 | 4431 | ||
4431 | CS_DBGOUT(CS_FUNCTION, 4, | 4432 | CS_DBGOUT(CS_FUNCTION, 4, |
4432 | printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVOFF\n")); | 4433 | printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVOFF\n")); |
4433 | /* | 4434 | /* |
4434 | * Power up the MIXER (VREF ON) on the AC97 card. | 4435 | * Power up the MIXER (VREF ON) on the AC97 card. |
4435 | */ | 4436 | */ |
4436 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4437 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4437 | if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)) { | 4438 | if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)) { |
4438 | if (!muted) { | 4439 | if (!muted) { |
4439 | cs_mute(card, CS_TRUE); | 4440 | cs_mute(card, CS_TRUE); |
4440 | muted = 1; | 4441 | muted = 1; |
4441 | } | 4442 | } |
4442 | tmp &= ~CS_AC97_POWER_CONTROL_MIXVOFF; | 4443 | tmp &= ~CS_AC97_POWER_CONTROL_MIXVOFF; |
4443 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); | 4444 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); |
4444 | /* | 4445 | /* |
4445 | * Now, we wait until we sample a ready state. | 4446 | * Now, we wait until we sample a ready state. |
4446 | */ | 4447 | */ |
4447 | for (count = 0; count < 32; count++) { | 4448 | for (count = 0; count < 32; count++) { |
4448 | /* | 4449 | /* |
4449 | * First, lets wait a short while to let things settle out a | 4450 | * First, lets wait a short while to let things settle out a |
4450 | * bit, and to prevent retrying the read too quickly. | 4451 | * bit, and to prevent retrying the read too quickly. |
4451 | */ | 4452 | */ |
4452 | udelay(500); | 4453 | udelay(500); |
4453 | 4454 | ||
4454 | /* | 4455 | /* |
4455 | * Read the current state of the power control register. | 4456 | * Read the current state of the power control register. |
4456 | */ | 4457 | */ |
4457 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4458 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4458 | CS_AC97_POWER_CONTROL_MIXVOFF_ON) | 4459 | CS_AC97_POWER_CONTROL_MIXVOFF_ON) |
4459 | break; | 4460 | break; |
4460 | } | 4461 | } |
4461 | 4462 | ||
4462 | /* | 4463 | /* |
4463 | * Check the status.. | 4464 | * Check the status.. |
4464 | */ | 4465 | */ |
4465 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4466 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4466 | CS_AC97_POWER_CONTROL_MIXVOFF_ON)) { | 4467 | CS_AC97_POWER_CONTROL_MIXVOFF_ON)) { |
4467 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4468 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4468 | "cs46xx: powerup MIXVOFF failed\n")); | 4469 | "cs46xx: powerup MIXVOFF failed\n")); |
4469 | return 1; | 4470 | return 1; |
4470 | } | 4471 | } |
4471 | } | 4472 | } |
4472 | } | 4473 | } |
4473 | if(type & CS_POWER_MIXVON) { | 4474 | if(type & CS_POWER_MIXVON) { |
4474 | 4475 | ||
4475 | CS_DBGOUT(CS_FUNCTION, 4, | 4476 | CS_DBGOUT(CS_FUNCTION, 4, |
4476 | printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVON\n")); | 4477 | printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVON\n")); |
4477 | /* | 4478 | /* |
4478 | * Power up the MIXER (VREF ON) on the AC97 card. | 4479 | * Power up the MIXER (VREF ON) on the AC97 card. |
4479 | */ | 4480 | */ |
4480 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4481 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4481 | if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)) { | 4482 | if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)) { |
4482 | if (!muted) { | 4483 | if (!muted) { |
4483 | cs_mute(card, CS_TRUE); | 4484 | cs_mute(card, CS_TRUE); |
4484 | muted = 1; | 4485 | muted = 1; |
4485 | } | 4486 | } |
4486 | tmp &= ~CS_AC97_POWER_CONTROL_MIXVON; | 4487 | tmp &= ~CS_AC97_POWER_CONTROL_MIXVON; |
4487 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); | 4488 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); |
4488 | /* | 4489 | /* |
4489 | * Now, we wait until we sample a ready state. | 4490 | * Now, we wait until we sample a ready state. |
4490 | */ | 4491 | */ |
4491 | for (count = 0; count < 32; count++) { | 4492 | for (count = 0; count < 32; count++) { |
4492 | /* | 4493 | /* |
4493 | * First, lets wait a short while to let things settle out a | 4494 | * First, lets wait a short while to let things settle out a |
4494 | * bit, and to prevent retrying the read too quickly. | 4495 | * bit, and to prevent retrying the read too quickly. |
4495 | */ | 4496 | */ |
4496 | udelay(500); | 4497 | udelay(500); |
4497 | 4498 | ||
4498 | /* | 4499 | /* |
4499 | * Read the current state of the power control register. | 4500 | * Read the current state of the power control register. |
4500 | */ | 4501 | */ |
4501 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4502 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4502 | CS_AC97_POWER_CONTROL_MIXVON_ON) | 4503 | CS_AC97_POWER_CONTROL_MIXVON_ON) |
4503 | break; | 4504 | break; |
4504 | } | 4505 | } |
4505 | 4506 | ||
4506 | /* | 4507 | /* |
4507 | * Check the status.. | 4508 | * Check the status.. |
4508 | */ | 4509 | */ |
4509 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4510 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4510 | CS_AC97_POWER_CONTROL_MIXVON_ON)) { | 4511 | CS_AC97_POWER_CONTROL_MIXVON_ON)) { |
4511 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4512 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4512 | "cs46xx: powerup MIXVON failed\n")); | 4513 | "cs46xx: powerup MIXVON failed\n")); |
4513 | return 1; | 4514 | return 1; |
4514 | } | 4515 | } |
4515 | } | 4516 | } |
4516 | } | 4517 | } |
4517 | if (type & CS_POWER_ADC) { | 4518 | if (type & CS_POWER_ADC) { |
4518 | /* | 4519 | /* |
4519 | * Power up the ADC on the AC97 card. | 4520 | * Power up the ADC on the AC97 card. |
4520 | */ | 4521 | */ |
4521 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs46xx_powerup()+ ADC\n")); | 4522 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs46xx_powerup()+ ADC\n")); |
4522 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4523 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4523 | if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON)) { | 4524 | if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON)) { |
4524 | if (!muted) { | 4525 | if (!muted) { |
4525 | cs_mute(card, CS_TRUE); | 4526 | cs_mute(card, CS_TRUE); |
4526 | muted = 1; | 4527 | muted = 1; |
4527 | } | 4528 | } |
4528 | tmp &= ~CS_AC97_POWER_CONTROL_ADC; | 4529 | tmp &= ~CS_AC97_POWER_CONTROL_ADC; |
4529 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); | 4530 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); |
4530 | 4531 | ||
4531 | /* | 4532 | /* |
4532 | * Now, we wait until we sample a ready state. | 4533 | * Now, we wait until we sample a ready state. |
4533 | */ | 4534 | */ |
4534 | for (count = 0; count < 32; count++) { | 4535 | for (count = 0; count < 32; count++) { |
4535 | /* | 4536 | /* |
4536 | * First, lets wait a short while to let things settle out a | 4537 | * First, lets wait a short while to let things settle out a |
4537 | * bit, and to prevent retrying the read too quickly. | 4538 | * bit, and to prevent retrying the read too quickly. |
4538 | */ | 4539 | */ |
4539 | udelay(500); | 4540 | udelay(500); |
4540 | 4541 | ||
4541 | /* | 4542 | /* |
4542 | * Read the current state of the power control register. | 4543 | * Read the current state of the power control register. |
4543 | */ | 4544 | */ |
4544 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4545 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4545 | CS_AC97_POWER_CONTROL_ADC_ON) | 4546 | CS_AC97_POWER_CONTROL_ADC_ON) |
4546 | break; | 4547 | break; |
4547 | } | 4548 | } |
4548 | 4549 | ||
4549 | /* | 4550 | /* |
4550 | * Check the status.. | 4551 | * Check the status.. |
4551 | */ | 4552 | */ |
4552 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4553 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4553 | CS_AC97_POWER_CONTROL_ADC_ON)) { | 4554 | CS_AC97_POWER_CONTROL_ADC_ON)) { |
4554 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4555 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4555 | "cs46xx: powerup ADC failed\n")); | 4556 | "cs46xx: powerup ADC failed\n")); |
4556 | return 1; | 4557 | return 1; |
4557 | } | 4558 | } |
4558 | } | 4559 | } |
4559 | } | 4560 | } |
4560 | if (type & CS_POWER_DAC) { | 4561 | if (type & CS_POWER_DAC) { |
4561 | /* | 4562 | /* |
4562 | * Power up the DAC on the AC97 card. | 4563 | * Power up the DAC on the AC97 card. |
4563 | */ | 4564 | */ |
4564 | 4565 | ||
4565 | CS_DBGOUT(CS_FUNCTION, 4, | 4566 | CS_DBGOUT(CS_FUNCTION, 4, |
4566 | printk(KERN_INFO "cs46xx: cs46xx_powerup()+ DAC\n")); | 4567 | printk(KERN_INFO "cs46xx: cs46xx_powerup()+ DAC\n")); |
4567 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4568 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4568 | if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON)) { | 4569 | if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON)) { |
4569 | if (!muted) { | 4570 | if (!muted) { |
4570 | cs_mute(card, CS_TRUE); | 4571 | cs_mute(card, CS_TRUE); |
4571 | muted = 1; | 4572 | muted = 1; |
4572 | } | 4573 | } |
4573 | tmp &= ~CS_AC97_POWER_CONTROL_DAC; | 4574 | tmp &= ~CS_AC97_POWER_CONTROL_DAC; |
4574 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); | 4575 | cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); |
4575 | /* | 4576 | /* |
4576 | * Now, we wait until we sample a ready state. | 4577 | * Now, we wait until we sample a ready state. |
4577 | */ | 4578 | */ |
4578 | for (count = 0; count < 32; count++) { | 4579 | for (count = 0; count < 32; count++) { |
4579 | /* | 4580 | /* |
4580 | * First, lets wait a short while to let things settle out a | 4581 | * First, lets wait a short while to let things settle out a |
4581 | * bit, and to prevent retrying the read too quickly. | 4582 | * bit, and to prevent retrying the read too quickly. |
4582 | */ | 4583 | */ |
4583 | udelay(500); | 4584 | udelay(500); |
4584 | 4585 | ||
4585 | /* | 4586 | /* |
4586 | * Read the current state of the power control register. | 4587 | * Read the current state of the power control register. |
4587 | */ | 4588 | */ |
4588 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4589 | if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4589 | CS_AC97_POWER_CONTROL_DAC_ON) | 4590 | CS_AC97_POWER_CONTROL_DAC_ON) |
4590 | break; | 4591 | break; |
4591 | } | 4592 | } |
4592 | 4593 | ||
4593 | /* | 4594 | /* |
4594 | * Check the status.. | 4595 | * Check the status.. |
4595 | */ | 4596 | */ |
4596 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & | 4597 | if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & |
4597 | CS_AC97_POWER_CONTROL_DAC_ON)) { | 4598 | CS_AC97_POWER_CONTROL_DAC_ON)) { |
4598 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING | 4599 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING |
4599 | "cs46xx: powerup DAC failed\n")); | 4600 | "cs46xx: powerup DAC failed\n")); |
4600 | return 1; | 4601 | return 1; |
4601 | } | 4602 | } |
4602 | } | 4603 | } |
4603 | } | 4604 | } |
4604 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); | 4605 | tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); |
4605 | if (muted) | 4606 | if (muted) |
4606 | cs_mute(card, CS_FALSE); | 4607 | cs_mute(card, CS_FALSE); |
4607 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO | 4608 | CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO |
4608 | "cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp)); | 4609 | "cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp)); |
4609 | return 0; | 4610 | return 0; |
4610 | } | 4611 | } |
4611 | 4612 | ||
4612 | static void cs461x_proc_start(struct cs_card *card) | 4613 | static void cs461x_proc_start(struct cs_card *card) |
4613 | { | 4614 | { |
4614 | int cnt; | 4615 | int cnt; |
4615 | 4616 | ||
4616 | /* | 4617 | /* |
4617 | * Set the frame timer to reflect the number of cycles per frame. | 4618 | * Set the frame timer to reflect the number of cycles per frame. |
4618 | */ | 4619 | */ |
4619 | cs461x_poke(card, BA1_FRMT, 0xadf); | 4620 | cs461x_poke(card, BA1_FRMT, 0xadf); |
4620 | /* | 4621 | /* |
4621 | * Turn on the run, run at frame, and DMA enable bits in the local copy of | 4622 | * Turn on the run, run at frame, and DMA enable bits in the local copy of |
4622 | * the SP control register. | 4623 | * the SP control register. |
4623 | */ | 4624 | */ |
4624 | cs461x_poke(card, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN); | 4625 | cs461x_poke(card, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN); |
4625 | /* | 4626 | /* |
4626 | * Wait until the run at frame bit resets itself in the SP control | 4627 | * Wait until the run at frame bit resets itself in the SP control |
4627 | * register. | 4628 | * register. |
4628 | */ | 4629 | */ |
4629 | for (cnt = 0; cnt < 25; cnt++) { | 4630 | for (cnt = 0; cnt < 25; cnt++) { |
4630 | udelay(50); | 4631 | udelay(50); |
4631 | if (!(cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR)) | 4632 | if (!(cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR)) |
4632 | break; | 4633 | break; |
4633 | } | 4634 | } |
4634 | 4635 | ||
4635 | if (cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR) | 4636 | if (cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR) |
4636 | printk(KERN_WARNING "cs46xx: SPCR_RUNFR never reset\n"); | 4637 | printk(KERN_WARNING "cs46xx: SPCR_RUNFR never reset\n"); |
4637 | } | 4638 | } |
4638 | 4639 | ||
4639 | static void cs461x_proc_stop(struct cs_card *card) | 4640 | static void cs461x_proc_stop(struct cs_card *card) |
4640 | { | 4641 | { |
4641 | /* | 4642 | /* |
4642 | * Turn off the run, run at frame, and DMA enable bits in the local copy of | 4643 | * Turn off the run, run at frame, and DMA enable bits in the local copy of |
4643 | * the SP control register. | 4644 | * the SP control register. |
4644 | */ | 4645 | */ |
4645 | cs461x_poke(card, BA1_SPCR, 0); | 4646 | cs461x_poke(card, BA1_SPCR, 0); |
4646 | } | 4647 | } |
4647 | 4648 | ||
4648 | static int cs_hardware_init(struct cs_card *card) | 4649 | static int cs_hardware_init(struct cs_card *card) |
4649 | { | 4650 | { |
4650 | unsigned long end_time; | 4651 | unsigned long end_time; |
4651 | unsigned int tmp,count; | 4652 | unsigned int tmp,count; |
4652 | 4653 | ||
4653 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO | 4654 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO |
4654 | "cs46xx: cs_hardware_init()+\n") ); | 4655 | "cs46xx: cs_hardware_init()+\n") ); |
4655 | /* | 4656 | /* |
4656 | * First, blast the clock control register to zero so that the PLL starts | 4657 | * First, blast the clock control register to zero so that the PLL starts |
4657 | * out in a known state, and blast the master serial port control register | 4658 | * out in a known state, and blast the master serial port control register |
4658 | * to zero so that the serial ports also start out in a known state. | 4659 | * to zero so that the serial ports also start out in a known state. |
4659 | */ | 4660 | */ |
4660 | cs461x_pokeBA0(card, BA0_CLKCR1, 0); | 4661 | cs461x_pokeBA0(card, BA0_CLKCR1, 0); |
4661 | cs461x_pokeBA0(card, BA0_SERMC1, 0); | 4662 | cs461x_pokeBA0(card, BA0_SERMC1, 0); |
4662 | 4663 | ||
4663 | /* | 4664 | /* |
4664 | * If we are in AC97 mode, then we must set the part to a host controlled | 4665 | * If we are in AC97 mode, then we must set the part to a host controlled |
4665 | * AC-link. Otherwise, we won't be able to bring up the link. | 4666 | * AC-link. Otherwise, we won't be able to bring up the link. |
4666 | */ | 4667 | */ |
4667 | cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 card */ | 4668 | cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 card */ |
4668 | /* cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); */ /* 2.00 card */ | 4669 | /* cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); */ /* 2.00 card */ |
4669 | 4670 | ||
4670 | /* | 4671 | /* |
4671 | * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 | 4672 | * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 |
4672 | * spec) and then drive it high. This is done for non AC97 modes since | 4673 | * spec) and then drive it high. This is done for non AC97 modes since |
4673 | * there might be logic external to the CS461x that uses the ARST# line | 4674 | * there might be logic external to the CS461x that uses the ARST# line |
4674 | * for a reset. | 4675 | * for a reset. |
4675 | */ | 4676 | */ |
4676 | cs461x_pokeBA0(card, BA0_ACCTL, 1); | 4677 | cs461x_pokeBA0(card, BA0_ACCTL, 1); |
4677 | udelay(50); | 4678 | udelay(50); |
4678 | cs461x_pokeBA0(card, BA0_ACCTL, 0); | 4679 | cs461x_pokeBA0(card, BA0_ACCTL, 0); |
4679 | udelay(50); | 4680 | udelay(50); |
4680 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_RSTN); | 4681 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_RSTN); |
4681 | 4682 | ||
4682 | /* | 4683 | /* |
4683 | * The first thing we do here is to enable sync generation. As soon | 4684 | * The first thing we do here is to enable sync generation. As soon |
4684 | * as we start receiving bit clock, we'll start producing the SYNC | 4685 | * as we start receiving bit clock, we'll start producing the SYNC |
4685 | * signal. | 4686 | * signal. |
4686 | */ | 4687 | */ |
4687 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN); | 4688 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN); |
4688 | 4689 | ||
4689 | /* | 4690 | /* |
4690 | * Now wait for a short while to allow the AC97 part to start | 4691 | * Now wait for a short while to allow the AC97 part to start |
4691 | * generating bit clock (so we don't try to start the PLL without an | 4692 | * generating bit clock (so we don't try to start the PLL without an |
4692 | * input clock). | 4693 | * input clock). |
4693 | */ | 4694 | */ |
4694 | mdelay(5 * cs_laptop_wait); /* 1 should be enough ?? (and pigs might fly) */ | 4695 | mdelay(5 * cs_laptop_wait); /* 1 should be enough ?? (and pigs might fly) */ |
4695 | 4696 | ||
4696 | /* | 4697 | /* |
4697 | * Set the serial port timing configuration, so that | 4698 | * Set the serial port timing configuration, so that |
4698 | * the clock control circuit gets its clock from the correct place. | 4699 | * the clock control circuit gets its clock from the correct place. |
4699 | */ | 4700 | */ |
4700 | cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97); | 4701 | cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97); |
4701 | 4702 | ||
4702 | /* | 4703 | /* |
4703 | * The part seems to not be ready for a while after a resume. | 4704 | * The part seems to not be ready for a while after a resume. |
4704 | * so, if we are resuming, then wait for 700 mils. Note that 600 mils | 4705 | * so, if we are resuming, then wait for 700 mils. Note that 600 mils |
4705 | * is not enough for some platforms! tested on an IBM Thinkpads and | 4706 | * is not enough for some platforms! tested on an IBM Thinkpads and |
4706 | * reference cards. | 4707 | * reference cards. |
4707 | */ | 4708 | */ |
4708 | if (!(card->pm.flags & CS46XX_PM_IDLE)) | 4709 | if (!(card->pm.flags & CS46XX_PM_IDLE)) |
4709 | mdelay(initdelay); | 4710 | mdelay(initdelay); |
4710 | /* | 4711 | /* |
4711 | * Write the selected clock control setup to the hardware. Do not turn on | 4712 | * Write the selected clock control setup to the hardware. Do not turn on |
4712 | * SWCE yet (if requested), so that the devices clocked by the output of | 4713 | * SWCE yet (if requested), so that the devices clocked by the output of |
4713 | * PLL are not clocked until the PLL is stable. | 4714 | * PLL are not clocked until the PLL is stable. |
4714 | */ | 4715 | */ |
4715 | cs461x_pokeBA0(card, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ); | 4716 | cs461x_pokeBA0(card, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ); |
4716 | cs461x_pokeBA0(card, BA0_PLLM, 0x3a); | 4717 | cs461x_pokeBA0(card, BA0_PLLM, 0x3a); |
4717 | cs461x_pokeBA0(card, BA0_CLKCR2, CLKCR2_PDIVS_8); | 4718 | cs461x_pokeBA0(card, BA0_CLKCR2, CLKCR2_PDIVS_8); |
4718 | 4719 | ||
4719 | /* | 4720 | /* |
4720 | * Power up the PLL. | 4721 | * Power up the PLL. |
4721 | */ | 4722 | */ |
4722 | cs461x_pokeBA0(card, BA0_CLKCR1, CLKCR1_PLLP); | 4723 | cs461x_pokeBA0(card, BA0_CLKCR1, CLKCR1_PLLP); |
4723 | 4724 | ||
4724 | /* | 4725 | /* |
4725 | * Wait until the PLL has stabilized. | 4726 | * Wait until the PLL has stabilized. |
4726 | */ | 4727 | */ |
4727 | mdelay(5 * cs_laptop_wait); /* Again 1 should be enough ?? */ | 4728 | mdelay(5 * cs_laptop_wait); /* Again 1 should be enough ?? */ |
4728 | 4729 | ||
4729 | /* | 4730 | /* |
4730 | * Turn on clocking of the core so that we can setup the serial ports. | 4731 | * Turn on clocking of the core so that we can setup the serial ports. |
4731 | */ | 4732 | */ |
4732 | tmp = cs461x_peekBA0(card, BA0_CLKCR1) | CLKCR1_SWCE; | 4733 | tmp = cs461x_peekBA0(card, BA0_CLKCR1) | CLKCR1_SWCE; |
4733 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); | 4734 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); |
4734 | 4735 | ||
4735 | /* | 4736 | /* |
4736 | * Fill the serial port FIFOs with silence. | 4737 | * Fill the serial port FIFOs with silence. |
4737 | */ | 4738 | */ |
4738 | cs461x_clear_serial_FIFOs(card,CS_TYPE_DAC | CS_TYPE_ADC); | 4739 | cs461x_clear_serial_FIFOs(card,CS_TYPE_DAC | CS_TYPE_ADC); |
4739 | 4740 | ||
4740 | /* | 4741 | /* |
4741 | * Set the serial port FIFO pointer to the first sample in the FIFO. | 4742 | * Set the serial port FIFO pointer to the first sample in the FIFO. |
4742 | */ | 4743 | */ |
4743 | /* cs461x_pokeBA0(card, BA0_SERBSP, 0); */ | 4744 | /* cs461x_pokeBA0(card, BA0_SERBSP, 0); */ |
4744 | 4745 | ||
4745 | /* | 4746 | /* |
4746 | * Write the serial port configuration to the part. The master | 4747 | * Write the serial port configuration to the part. The master |
4747 | * enable bit is not set until all other values have been written. | 4748 | * enable bit is not set until all other values have been written. |
4748 | */ | 4749 | */ |
4749 | cs461x_pokeBA0(card, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN); | 4750 | cs461x_pokeBA0(card, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN); |
4750 | cs461x_pokeBA0(card, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN); | 4751 | cs461x_pokeBA0(card, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN); |
4751 | cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); | 4752 | cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); |
4752 | 4753 | ||
4753 | 4754 | ||
4754 | mdelay(5 * cs_laptop_wait); /* Shouldnt be needed ?? */ | 4755 | mdelay(5 * cs_laptop_wait); /* Shouldnt be needed ?? */ |
4755 | 4756 | ||
4756 | /* | 4757 | /* |
4757 | * If we are resuming under 2.2.x then we cannot schedule a timeout, | 4758 | * If we are resuming under 2.2.x then we cannot schedule a timeout, |
4758 | * so just spin the CPU. | 4759 | * so just spin the CPU. |
4759 | */ | 4760 | */ |
4760 | if (card->pm.flags & CS46XX_PM_IDLE) { | 4761 | if (card->pm.flags & CS46XX_PM_IDLE) { |
4761 | /* | 4762 | /* |
4762 | * Wait for the card ready signal from the AC97 card. | 4763 | * Wait for the card ready signal from the AC97 card. |
4763 | */ | 4764 | */ |
4764 | end_time = jiffies + 3 * (HZ >> 2); | 4765 | end_time = jiffies + 3 * (HZ >> 2); |
4765 | do { | 4766 | do { |
4766 | /* | 4767 | /* |
4767 | * Read the AC97 status register to see if we've seen a CODEC READY | 4768 | * Read the AC97 status register to see if we've seen a CODEC READY |
4768 | * signal from the AC97 card. | 4769 | * signal from the AC97 card. |
4769 | */ | 4770 | */ |
4770 | if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY) | 4771 | if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY) |
4771 | break; | 4772 | break; |
4772 | current->state = TASK_UNINTERRUPTIBLE; | 4773 | current->state = TASK_UNINTERRUPTIBLE; |
4773 | schedule_timeout(1); | 4774 | schedule_timeout(1); |
4774 | } while (time_before(jiffies, end_time)); | 4775 | } while (time_before(jiffies, end_time)); |
4775 | } else { | 4776 | } else { |
4776 | for (count = 0; count < 100; count++) { | 4777 | for (count = 0; count < 100; count++) { |
4777 | // First, we want to wait for a short time. | 4778 | // First, we want to wait for a short time. |
4778 | udelay(25 * cs_laptop_wait); | 4779 | udelay(25 * cs_laptop_wait); |
4779 | 4780 | ||
4780 | if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY) | 4781 | if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY) |
4781 | break; | 4782 | break; |
4782 | } | 4783 | } |
4783 | } | 4784 | } |
4784 | 4785 | ||
4785 | /* | 4786 | /* |
4786 | * Make sure CODEC is READY. | 4787 | * Make sure CODEC is READY. |
4787 | */ | 4788 | */ |
4788 | if (!(cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)) { | 4789 | if (!(cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)) { |
4789 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING | 4790 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING |
4790 | "cs46xx: create - never read card ready from AC'97\n")); | 4791 | "cs46xx: create - never read card ready from AC'97\n")); |
4791 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING | 4792 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING |
4792 | "cs46xx: probably not a bug, try using the CS4232 driver,\n")); | 4793 | "cs46xx: probably not a bug, try using the CS4232 driver,\n")); |
4793 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING | 4794 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING |
4794 | "cs46xx: or turn off any automatic Power Management support in the BIOS.\n")); | 4795 | "cs46xx: or turn off any automatic Power Management support in the BIOS.\n")); |
4795 | return -EIO; | 4796 | return -EIO; |
4796 | } | 4797 | } |
4797 | 4798 | ||
4798 | /* | 4799 | /* |
4799 | * Assert the vaid frame signal so that we can start sending commands | 4800 | * Assert the vaid frame signal so that we can start sending commands |
4800 | * to the AC97 card. | 4801 | * to the AC97 card. |
4801 | */ | 4802 | */ |
4802 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); | 4803 | cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); |
4803 | 4804 | ||
4804 | if (card->pm.flags & CS46XX_PM_IDLE) { | 4805 | if (card->pm.flags & CS46XX_PM_IDLE) { |
4805 | /* | 4806 | /* |
4806 | * Wait until we've sampled input slots 3 and 4 as valid, meaning that | 4807 | * Wait until we've sampled input slots 3 and 4 as valid, meaning that |
4807 | * the card is pumping ADC data across the AC-link. | 4808 | * the card is pumping ADC data across the AC-link. |
4808 | */ | 4809 | */ |
4809 | end_time = jiffies + 3 * (HZ >> 2); | 4810 | end_time = jiffies + 3 * (HZ >> 2); |
4810 | do { | 4811 | do { |
4811 | /* | 4812 | /* |
4812 | * Read the input slot valid register and see if input slots 3 and | 4813 | * Read the input slot valid register and see if input slots 3 and |
4813 | * 4 are valid yet. | 4814 | * 4 are valid yet. |
4814 | */ | 4815 | */ |
4815 | if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) | 4816 | if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) |
4816 | break; | 4817 | break; |
4817 | current->state = TASK_UNINTERRUPTIBLE; | 4818 | current->state = TASK_UNINTERRUPTIBLE; |
4818 | schedule_timeout(1); | 4819 | schedule_timeout(1); |
4819 | } while (time_before(jiffies, end_time)); | 4820 | } while (time_before(jiffies, end_time)); |
4820 | } else { | 4821 | } else { |
4821 | for (count = 0; count < 100; count++) { | 4822 | for (count = 0; count < 100; count++) { |
4822 | // First, we want to wait for a short time. | 4823 | // First, we want to wait for a short time. |
4823 | udelay(25 * cs_laptop_wait); | 4824 | udelay(25 * cs_laptop_wait); |
4824 | 4825 | ||
4825 | if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) | 4826 | if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) |
4826 | break; | 4827 | break; |
4827 | } | 4828 | } |
4828 | } | 4829 | } |
4829 | /* | 4830 | /* |
4830 | * Make sure input slots 3 and 4 are valid. If not, then return | 4831 | * Make sure input slots 3 and 4 are valid. If not, then return |
4831 | * an error. | 4832 | * an error. |
4832 | */ | 4833 | */ |
4833 | if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4)) { | 4834 | if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4)) { |
4834 | printk(KERN_WARNING "cs46xx: create - never read ISV3 & ISV4 from AC'97\n"); | 4835 | printk(KERN_WARNING "cs46xx: create - never read ISV3 & ISV4 from AC'97\n"); |
4835 | return -EIO; | 4836 | return -EIO; |
4836 | } | 4837 | } |
4837 | 4838 | ||
4838 | /* | 4839 | /* |
4839 | * Now, assert valid frame and the slot 3 and 4 valid bits. This will | 4840 | * Now, assert valid frame and the slot 3 and 4 valid bits. This will |
4840 | * commense the transfer of digital audio data to the AC97 card. | 4841 | * commense the transfer of digital audio data to the AC97 card. |
4841 | */ | 4842 | */ |
4842 | cs461x_pokeBA0(card, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); | 4843 | cs461x_pokeBA0(card, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); |
4843 | 4844 | ||
4844 | /* | 4845 | /* |
4845 | * Turn off the Processor by turning off the software clock enable flag in | 4846 | * Turn off the Processor by turning off the software clock enable flag in |
4846 | * the clock control register. | 4847 | * the clock control register. |
4847 | */ | 4848 | */ |
4848 | /* tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; */ | 4849 | /* tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; */ |
4849 | /* cs461x_pokeBA0(card, BA0_CLKCR1, tmp); */ | 4850 | /* cs461x_pokeBA0(card, BA0_CLKCR1, tmp); */ |
4850 | 4851 | ||
4851 | /* | 4852 | /* |
4852 | * Reset the processor. | 4853 | * Reset the processor. |
4853 | */ | 4854 | */ |
4854 | cs461x_reset(card); | 4855 | cs461x_reset(card); |
4855 | 4856 | ||
4856 | /* | 4857 | /* |
4857 | * Download the image to the processor. | 4858 | * Download the image to the processor. |
4858 | */ | 4859 | */ |
4859 | 4860 | ||
4860 | cs461x_download_image(card); | 4861 | cs461x_download_image(card); |
4861 | 4862 | ||
4862 | /* | 4863 | /* |
4863 | * Stop playback DMA. | 4864 | * Stop playback DMA. |
4864 | */ | 4865 | */ |
4865 | tmp = cs461x_peek(card, BA1_PCTL); | 4866 | tmp = cs461x_peek(card, BA1_PCTL); |
4866 | card->pctl = tmp & 0xffff0000; | 4867 | card->pctl = tmp & 0xffff0000; |
4867 | cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff); | 4868 | cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff); |
4868 | 4869 | ||
4869 | /* | 4870 | /* |
4870 | * Stop capture DMA. | 4871 | * Stop capture DMA. |
4871 | */ | 4872 | */ |
4872 | tmp = cs461x_peek(card, BA1_CCTL); | 4873 | tmp = cs461x_peek(card, BA1_CCTL); |
4873 | card->cctl = tmp & 0x0000ffff; | 4874 | card->cctl = tmp & 0x0000ffff; |
4874 | cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000); | 4875 | cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000); |
4875 | 4876 | ||
4876 | /* initialize AC97 codec and register /dev/mixer */ | 4877 | /* initialize AC97 codec and register /dev/mixer */ |
4877 | if (card->pm.flags & CS46XX_PM_IDLE) { | 4878 | if (card->pm.flags & CS46XX_PM_IDLE) { |
4878 | if (cs_ac97_init(card) <= 0) { | 4879 | if (cs_ac97_init(card) <= 0) { |
4879 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 4880 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
4880 | "cs46xx: cs_ac97_init() failure\n")); | 4881 | "cs46xx: cs_ac97_init() failure\n")); |
4881 | return -EIO; | 4882 | return -EIO; |
4882 | } | 4883 | } |
4883 | } else { | 4884 | } else { |
4884 | cs46xx_ac97_resume(card); | 4885 | cs46xx_ac97_resume(card); |
4885 | } | 4886 | } |
4886 | 4887 | ||
4887 | cs461x_proc_start(card); | 4888 | cs461x_proc_start(card); |
4888 | 4889 | ||
4889 | /* | 4890 | /* |
4890 | * Enable interrupts on the part. | 4891 | * Enable interrupts on the part. |
4891 | */ | 4892 | */ |
4892 | cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM); | 4893 | cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM); |
4893 | 4894 | ||
4894 | tmp = cs461x_peek(card, BA1_PFIE); | 4895 | tmp = cs461x_peek(card, BA1_PFIE); |
4895 | tmp &= ~0x0000f03f; | 4896 | tmp &= ~0x0000f03f; |
4896 | cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt enable */ | 4897 | cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt enable */ |
4897 | 4898 | ||
4898 | tmp = cs461x_peek(card, BA1_CIE); | 4899 | tmp = cs461x_peek(card, BA1_CIE); |
4899 | tmp &= ~0x0000003f; | 4900 | tmp &= ~0x0000003f; |
4900 | tmp |= 0x00000001; | 4901 | tmp |= 0x00000001; |
4901 | cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt enable */ | 4902 | cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt enable */ |
4902 | 4903 | ||
4903 | /* | 4904 | /* |
4904 | * If IDLE then Power down the part. We will power components up | 4905 | * If IDLE then Power down the part. We will power components up |
4905 | * when we need them. | 4906 | * when we need them. |
4906 | */ | 4907 | */ |
4907 | if (card->pm.flags & CS46XX_PM_IDLE) { | 4908 | if (card->pm.flags & CS46XX_PM_IDLE) { |
4908 | if (!cs_powerdown) { | 4909 | if (!cs_powerdown) { |
4909 | if ((tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC | | 4910 | if ((tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC | |
4910 | CS_POWER_MIXVON))) { | 4911 | CS_POWER_MIXVON))) { |
4911 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 4912 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
4912 | "cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) ); | 4913 | "cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) ); |
4913 | return -EIO; | 4914 | return -EIO; |
4914 | } | 4915 | } |
4915 | } else { | 4916 | } else { |
4916 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | | 4917 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | |
4917 | CS_POWER_MIXVON, CS_FALSE))) { | 4918 | CS_POWER_MIXVON, CS_FALSE))) { |
4918 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 4919 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
4919 | "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) ); | 4920 | "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) ); |
4920 | return -EIO; | 4921 | return -EIO; |
4921 | } | 4922 | } |
4922 | } | 4923 | } |
4923 | } | 4924 | } |
4924 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO | 4925 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO |
4925 | "cs46xx: cs_hardware_init()- 0\n")); | 4926 | "cs46xx: cs_hardware_init()- 0\n")); |
4926 | return 0; | 4927 | return 0; |
4927 | } | 4928 | } |
4928 | 4929 | ||
4929 | /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered | 4930 | /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered |
4930 | until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */ | 4931 | until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */ |
4931 | 4932 | ||
4932 | /* | 4933 | /* |
4933 | * Card subid table | 4934 | * Card subid table |
4934 | */ | 4935 | */ |
4935 | 4936 | ||
4936 | struct cs_card_type | 4937 | struct cs_card_type |
4937 | { | 4938 | { |
4938 | u16 vendor; | 4939 | u16 vendor; |
4939 | u16 id; | 4940 | u16 id; |
4940 | char *name; | 4941 | char *name; |
4941 | void (*amp)(struct cs_card *, int); | 4942 | void (*amp)(struct cs_card *, int); |
4942 | void (*amp_init)(struct cs_card *); | 4943 | void (*amp_init)(struct cs_card *); |
4943 | void (*active)(struct cs_card *, int); | 4944 | void (*active)(struct cs_card *, int); |
4944 | }; | 4945 | }; |
4945 | 4946 | ||
4946 | static struct cs_card_type cards[] = { | 4947 | static struct cs_card_type cards[] = { |
4947 | { | 4948 | { |
4948 | .vendor = 0x1489, | 4949 | .vendor = 0x1489, |
4949 | .id = 0x7001, | 4950 | .id = 0x7001, |
4950 | .name = "Genius Soundmaker 128 value", | 4951 | .name = "Genius Soundmaker 128 value", |
4951 | .amp = amp_none, | 4952 | .amp = amp_none, |
4952 | }, | 4953 | }, |
4953 | { | 4954 | { |
4954 | .vendor = 0x5053, | 4955 | .vendor = 0x5053, |
4955 | .id = 0x3357, | 4956 | .id = 0x3357, |
4956 | .name = "Voyetra", | 4957 | .name = "Voyetra", |
4957 | .amp = amp_voyetra, | 4958 | .amp = amp_voyetra, |
4958 | }, | 4959 | }, |
4959 | { | 4960 | { |
4960 | .vendor = 0x1071, | 4961 | .vendor = 0x1071, |
4961 | .id = 0x6003, | 4962 | .id = 0x6003, |
4962 | .name = "Mitac MI6020/21", | 4963 | .name = "Mitac MI6020/21", |
4963 | .amp = amp_voyetra, | 4964 | .amp = amp_voyetra, |
4964 | }, | 4965 | }, |
4965 | { | 4966 | { |
4966 | .vendor = 0x14AF, | 4967 | .vendor = 0x14AF, |
4967 | .id = 0x0050, | 4968 | .id = 0x0050, |
4968 | .name = "Hercules Game Theatre XP", | 4969 | .name = "Hercules Game Theatre XP", |
4969 | .amp = amp_hercules, | 4970 | .amp = amp_hercules, |
4970 | }, | 4971 | }, |
4971 | { | 4972 | { |
4972 | .vendor = 0x1681, | 4973 | .vendor = 0x1681, |
4973 | .id = 0x0050, | 4974 | .id = 0x0050, |
4974 | .name = "Hercules Game Theatre XP", | 4975 | .name = "Hercules Game Theatre XP", |
4975 | .amp = amp_hercules, | 4976 | .amp = amp_hercules, |
4976 | }, | 4977 | }, |
4977 | { | 4978 | { |
4978 | .vendor = 0x1681, | 4979 | .vendor = 0x1681, |
4979 | .id = 0x0051, | 4980 | .id = 0x0051, |
4980 | .name = "Hercules Game Theatre XP", | 4981 | .name = "Hercules Game Theatre XP", |
4981 | .amp = amp_hercules, | 4982 | .amp = amp_hercules, |
4982 | }, | 4983 | }, |
4983 | { | 4984 | { |
4984 | .vendor = 0x1681, | 4985 | .vendor = 0x1681, |
4985 | .id = 0x0052, | 4986 | .id = 0x0052, |
4986 | .name = "Hercules Game Theatre XP", | 4987 | .name = "Hercules Game Theatre XP", |
4987 | .amp = amp_hercules, | 4988 | .amp = amp_hercules, |
4988 | }, | 4989 | }, |
4989 | { | 4990 | { |
4990 | .vendor = 0x1681, | 4991 | .vendor = 0x1681, |
4991 | .id = 0x0053, | 4992 | .id = 0x0053, |
4992 | .name = "Hercules Game Theatre XP", | 4993 | .name = "Hercules Game Theatre XP", |
4993 | .amp = amp_hercules, | 4994 | .amp = amp_hercules, |
4994 | }, | 4995 | }, |
4995 | { | 4996 | { |
4996 | .vendor = 0x1681, | 4997 | .vendor = 0x1681, |
4997 | .id = 0x0054, | 4998 | .id = 0x0054, |
4998 | .name = "Hercules Game Theatre XP", | 4999 | .name = "Hercules Game Theatre XP", |
4999 | .amp = amp_hercules, | 5000 | .amp = amp_hercules, |
5000 | }, | 5001 | }, |
5001 | { | 5002 | { |
5002 | .vendor = 0x1681, | 5003 | .vendor = 0x1681, |
5003 | .id = 0xa010, | 5004 | .id = 0xa010, |
5004 | .name = "Hercules Fortissimo II", | 5005 | .name = "Hercules Fortissimo II", |
5005 | .amp = amp_none, | 5006 | .amp = amp_none, |
5006 | }, | 5007 | }, |
5007 | /* Not sure if the 570 needs the clkrun hack */ | 5008 | /* Not sure if the 570 needs the clkrun hack */ |
5008 | { | 5009 | { |
5009 | .vendor = PCI_VENDOR_ID_IBM, | 5010 | .vendor = PCI_VENDOR_ID_IBM, |
5010 | .id = 0x0132, | 5011 | .id = 0x0132, |
5011 | .name = "Thinkpad 570", | 5012 | .name = "Thinkpad 570", |
5012 | .amp = amp_none, | 5013 | .amp = amp_none, |
5013 | .active = clkrun_hack, | 5014 | .active = clkrun_hack, |
5014 | }, | 5015 | }, |
5015 | { | 5016 | { |
5016 | .vendor = PCI_VENDOR_ID_IBM, | 5017 | .vendor = PCI_VENDOR_ID_IBM, |
5017 | .id = 0x0153, | 5018 | .id = 0x0153, |
5018 | .name = "Thinkpad 600X/A20/T20", | 5019 | .name = "Thinkpad 600X/A20/T20", |
5019 | .amp = amp_none, | 5020 | .amp = amp_none, |
5020 | .active = clkrun_hack, | 5021 | .active = clkrun_hack, |
5021 | }, | 5022 | }, |
5022 | { | 5023 | { |
5023 | .vendor = PCI_VENDOR_ID_IBM, | 5024 | .vendor = PCI_VENDOR_ID_IBM, |
5024 | .id = 0x1010, | 5025 | .id = 0x1010, |
5025 | .name = "Thinkpad 600E (unsupported)", | 5026 | .name = "Thinkpad 600E (unsupported)", |
5026 | }, | 5027 | }, |
5027 | { | 5028 | { |
5028 | .name = "Card without SSID set", | 5029 | .name = "Card without SSID set", |
5029 | }, | 5030 | }, |
5030 | { 0, }, | 5031 | { 0, }, |
5031 | }; | 5032 | }; |
5032 | 5033 | ||
5033 | MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela, <pcaudio@crystal.cirrus.com>"); | 5034 | MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela, <pcaudio@crystal.cirrus.com>"); |
5034 | MODULE_DESCRIPTION("Crystal SoundFusion Audio Support"); | 5035 | MODULE_DESCRIPTION("Crystal SoundFusion Audio Support"); |
5035 | MODULE_LICENSE("GPL"); | 5036 | MODULE_LICENSE("GPL"); |
5036 | 5037 | ||
5037 | static const char cs46xx_banner[] = KERN_INFO "Crystal 4280/46xx + AC97 Audio, version " CS46XX_MAJOR_VERSION "." CS46XX_MINOR_VERSION "." CS46XX_ARCH ", " __TIME__ " " __DATE__ "\n"; | 5038 | static const char cs46xx_banner[] = KERN_INFO "Crystal 4280/46xx + AC97 Audio, version " CS46XX_MAJOR_VERSION "." CS46XX_MINOR_VERSION "." CS46XX_ARCH ", " __TIME__ " " __DATE__ "\n"; |
5038 | static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n"; | 5039 | static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n"; |
5039 | 5040 | ||
5040 | static int __devinit cs46xx_probe(struct pci_dev *pci_dev, | 5041 | static int __devinit cs46xx_probe(struct pci_dev *pci_dev, |
5041 | const struct pci_device_id *pciid) | 5042 | const struct pci_device_id *pciid) |
5042 | { | 5043 | { |
5043 | int i, j; | 5044 | int i, j; |
5044 | u16 ss_card, ss_vendor; | 5045 | u16 ss_card, ss_vendor; |
5045 | struct cs_card *card; | 5046 | struct cs_card *card; |
5046 | dma_addr_t dma_mask; | 5047 | dma_addr_t dma_mask; |
5047 | struct cs_card_type *cp = &cards[0]; | 5048 | struct cs_card_type *cp = &cards[0]; |
5048 | 5049 | ||
5049 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, | 5050 | CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, |
5050 | printk(KERN_INFO "cs46xx: probe()+\n")); | 5051 | printk(KERN_INFO "cs46xx: probe()+\n")); |
5051 | 5052 | ||
5052 | dma_mask = 0xffffffff; /* this enables playback and recording */ | 5053 | dma_mask = 0xffffffff; /* this enables playback and recording */ |
5053 | if (pci_enable_device(pci_dev)) { | 5054 | if (pci_enable_device(pci_dev)) { |
5054 | CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR | 5055 | CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR |
5055 | "cs46xx: pci_enable_device() failed\n")); | 5056 | "cs46xx: pci_enable_device() failed\n")); |
5056 | return -1; | 5057 | return -1; |
5057 | } | 5058 | } |
5058 | if (!RSRCISMEMORYREGION(pci_dev, 0) || | 5059 | if (!RSRCISMEMORYREGION(pci_dev, 0) || |
5059 | !RSRCISMEMORYREGION(pci_dev, 1)) { | 5060 | !RSRCISMEMORYREGION(pci_dev, 1)) { |
5060 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR | 5061 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR |
5061 | "cs46xx: probe()- Memory region not assigned\n")); | 5062 | "cs46xx: probe()- Memory region not assigned\n")); |
5062 | return -1; | 5063 | return -1; |
5063 | } | 5064 | } |
5064 | if (pci_dev->irq == 0) { | 5065 | if (pci_dev->irq == 0) { |
5065 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR | 5066 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR |
5066 | "cs46xx: probe() IRQ not assigned\n")); | 5067 | "cs46xx: probe() IRQ not assigned\n")); |
5067 | return -1; | 5068 | return -1; |
5068 | } | 5069 | } |
5069 | if (!pci_dma_supported(pci_dev, 0xffffffff)) { | 5070 | if (!pci_dma_supported(pci_dev, 0xffffffff)) { |
5070 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR | 5071 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR |
5071 | "cs46xx: probe() architecture does not support 32bit PCI busmaster DMA\n")); | 5072 | "cs46xx: probe() architecture does not support 32bit PCI busmaster DMA\n")); |
5072 | return -1; | 5073 | return -1; |
5073 | } | 5074 | } |
5074 | pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor); | 5075 | pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor); |
5075 | pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card); | 5076 | pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card); |
5076 | 5077 | ||
5077 | if ((card = kmalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) { | 5078 | if ((card = kmalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) { |
5078 | printk(KERN_ERR "cs46xx: out of memory\n"); | 5079 | printk(KERN_ERR "cs46xx: out of memory\n"); |
5079 | return -ENOMEM; | 5080 | return -ENOMEM; |
5080 | } | 5081 | } |
5081 | memset(card, 0, sizeof(*card)); | 5082 | memset(card, 0, sizeof(*card)); |
5082 | card->ba0_addr = RSRCADDRESS(pci_dev, 0); | 5083 | card->ba0_addr = RSRCADDRESS(pci_dev, 0); |
5083 | card->ba1_addr = RSRCADDRESS(pci_dev, 1); | 5084 | card->ba1_addr = RSRCADDRESS(pci_dev, 1); |
5084 | card->pci_dev = pci_dev; | 5085 | card->pci_dev = pci_dev; |
5085 | card->irq = pci_dev->irq; | 5086 | card->irq = pci_dev->irq; |
5086 | card->magic = CS_CARD_MAGIC; | 5087 | card->magic = CS_CARD_MAGIC; |
5087 | spin_lock_init(&card->lock); | 5088 | spin_lock_init(&card->lock); |
5088 | spin_lock_init(&card->ac97_lock); | 5089 | spin_lock_init(&card->ac97_lock); |
5089 | 5090 | ||
5090 | pci_set_master(pci_dev); | 5091 | pci_set_master(pci_dev); |
5091 | 5092 | ||
5092 | printk(cs46xx_banner); | 5093 | printk(cs46xx_banner); |
5093 | printk(KERN_INFO "cs46xx: Card found at 0x%08lx and 0x%08lx, IRQ %d\n", | 5094 | printk(KERN_INFO "cs46xx: Card found at 0x%08lx and 0x%08lx, IRQ %d\n", |
5094 | card->ba0_addr, card->ba1_addr, card->irq); | 5095 | card->ba0_addr, card->ba1_addr, card->irq); |
5095 | 5096 | ||
5096 | card->alloc_pcm_channel = cs_alloc_pcm_channel; | 5097 | card->alloc_pcm_channel = cs_alloc_pcm_channel; |
5097 | card->alloc_rec_pcm_channel = cs_alloc_rec_pcm_channel; | 5098 | card->alloc_rec_pcm_channel = cs_alloc_rec_pcm_channel; |
5098 | card->free_pcm_channel = cs_free_pcm_channel; | 5099 | card->free_pcm_channel = cs_free_pcm_channel; |
5099 | card->amplifier_ctrl = amp_none; | 5100 | card->amplifier_ctrl = amp_none; |
5100 | card->active_ctrl = amp_none; | 5101 | card->active_ctrl = amp_none; |
5101 | 5102 | ||
5102 | while (cp->name) | 5103 | while (cp->name) |
5103 | { | 5104 | { |
5104 | if (cp->vendor == ss_vendor && cp->id == ss_card) { | 5105 | if (cp->vendor == ss_vendor && cp->id == ss_card) { |
5105 | card->amplifier_ctrl = cp->amp; | 5106 | card->amplifier_ctrl = cp->amp; |
5106 | if (cp->active) | 5107 | if (cp->active) |
5107 | card->active_ctrl = cp->active; | 5108 | card->active_ctrl = cp->active; |
5108 | if (cp->amp_init) | 5109 | if (cp->amp_init) |
5109 | card->amp_init = cp->amp_init; | 5110 | card->amp_init = cp->amp_init; |
5110 | break; | 5111 | break; |
5111 | } | 5112 | } |
5112 | cp++; | 5113 | cp++; |
5113 | } | 5114 | } |
5114 | if (cp->name == NULL) { | 5115 | if (cp->name == NULL) { |
5115 | printk(KERN_INFO "cs46xx: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n", | 5116 | printk(KERN_INFO "cs46xx: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n", |
5116 | ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq); | 5117 | ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq); |
5117 | } else { | 5118 | } else { |
5118 | printk(KERN_INFO "cs46xx: %s (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n", | 5119 | printk(KERN_INFO "cs46xx: %s (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n", |
5119 | cp->name, ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq); | 5120 | cp->name, ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq); |
5120 | } | 5121 | } |
5121 | 5122 | ||
5122 | if (card->amplifier_ctrl == NULL) { | 5123 | if (card->amplifier_ctrl == NULL) { |
5123 | card->amplifier_ctrl = amp_none; | 5124 | card->amplifier_ctrl = amp_none; |
5124 | card->active_ctrl = clkrun_hack; | 5125 | card->active_ctrl = clkrun_hack; |
5125 | } | 5126 | } |
5126 | 5127 | ||
5127 | if (external_amp == 1) { | 5128 | if (external_amp == 1) { |
5128 | printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n"); | 5129 | printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n"); |
5129 | card->amplifier_ctrl = amp_voyetra; | 5130 | card->amplifier_ctrl = amp_voyetra; |
5130 | } | 5131 | } |
5131 | 5132 | ||
5132 | if (thinkpad == 1) { | 5133 | if (thinkpad == 1) { |
5133 | printk(KERN_INFO "cs46xx: Activating CLKRUN hack for Thinkpad.\n"); | 5134 | printk(KERN_INFO "cs46xx: Activating CLKRUN hack for Thinkpad.\n"); |
5134 | card->active_ctrl = clkrun_hack; | 5135 | card->active_ctrl = clkrun_hack; |
5135 | } | 5136 | } |
5136 | /* | 5137 | /* |
5137 | * The thinkpads don't work well without runtime updating on their kernel | 5138 | * The thinkpads don't work well without runtime updating on their kernel |
5138 | * delay values (or any laptop with variable CPU speeds really). | 5139 | * delay values (or any laptop with variable CPU speeds really). |
5139 | * so, just to be safe set the init delay to 2100. Eliminates | 5140 | * so, just to be safe set the init delay to 2100. Eliminates |
5140 | * failures on T21 Thinkpads. remove this code when the udelay | 5141 | * failures on T21 Thinkpads. remove this code when the udelay |
5141 | * and mdelay kernel code is replaced by a pm timer, or the delays | 5142 | * and mdelay kernel code is replaced by a pm timer, or the delays |
5142 | * work well for battery and/or AC power both. | 5143 | * work well for battery and/or AC power both. |
5143 | */ | 5144 | */ |
5144 | if (card->active_ctrl == clkrun_hack) { | 5145 | if (card->active_ctrl == clkrun_hack) { |
5145 | initdelay = 2100; | 5146 | initdelay = 2100; |
5146 | cs_laptop_wait = 5; | 5147 | cs_laptop_wait = 5; |
5147 | } | 5148 | } |
5148 | if ((card->active_ctrl == clkrun_hack) && !(powerdown == 1)) { | 5149 | if ((card->active_ctrl == clkrun_hack) && !(powerdown == 1)) { |
5149 | /* | 5150 | /* |
5150 | * for some currently unknown reason, powering down the DAC and ADC component | 5151 | * for some currently unknown reason, powering down the DAC and ADC component |
5151 | * blocks on thinkpads causes some funky behavior... distoorrrtion and ac97 | 5152 | * blocks on thinkpads causes some funky behavior... distoorrrtion and ac97 |
5152 | * codec access problems. probably the serial clock becomes unsynced. | 5153 | * codec access problems. probably the serial clock becomes unsynced. |
5153 | * added code to sync the chips back up, but only helped about 70% the time. | 5154 | * added code to sync the chips back up, but only helped about 70% the time. |
5154 | */ | 5155 | */ |
5155 | cs_powerdown = 0; | 5156 | cs_powerdown = 0; |
5156 | } | 5157 | } |
5157 | if (powerdown == 0) | 5158 | if (powerdown == 0) |
5158 | cs_powerdown = 0; | 5159 | cs_powerdown = 0; |
5159 | card->active_ctrl(card, 1); | 5160 | card->active_ctrl(card, 1); |
5160 | 5161 | ||
5161 | /* claim our iospace and irq */ | 5162 | /* claim our iospace and irq */ |
5162 | 5163 | ||
5163 | card->ba0 = ioremap_nocache(card->ba0_addr, CS461X_BA0_SIZE); | 5164 | card->ba0 = ioremap_nocache(card->ba0_addr, CS461X_BA0_SIZE); |
5164 | card->ba1.name.data0 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); | 5165 | card->ba1.name.data0 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); |
5165 | card->ba1.name.data1 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); | 5166 | card->ba1.name.data1 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); |
5166 | card->ba1.name.pmem = ioremap_nocache(card->ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); | 5167 | card->ba1.name.pmem = ioremap_nocache(card->ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); |
5167 | card->ba1.name.reg = ioremap_nocache(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); | 5168 | card->ba1.name.reg = ioremap_nocache(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); |
5168 | 5169 | ||
5169 | CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO | 5170 | CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO |
5170 | "cs46xx: card=%p card->ba0=%p\n",card,card->ba0) ); | 5171 | "cs46xx: card=%p card->ba0=%p\n",card,card->ba0) ); |
5171 | CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO | 5172 | CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO |
5172 | "cs46xx: card->ba1=%p %p %p %p\n", | 5173 | "cs46xx: card->ba1=%p %p %p %p\n", |
5173 | card->ba1.name.data0, | 5174 | card->ba1.name.data0, |
5174 | card->ba1.name.data1, | 5175 | card->ba1.name.data1, |
5175 | card->ba1.name.pmem, | 5176 | card->ba1.name.pmem, |
5176 | card->ba1.name.reg) ); | 5177 | card->ba1.name.reg) ); |
5177 | 5178 | ||
5178 | if (card->ba0 == 0 || card->ba1.name.data0 == 0 || | 5179 | if (card->ba0 == 0 || card->ba1.name.data0 == 0 || |
5179 | card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 || | 5180 | card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 || |
5180 | card->ba1.name.reg == 0) | 5181 | card->ba1.name.reg == 0) |
5181 | goto fail2; | 5182 | goto fail2; |
5182 | 5183 | ||
5183 | if (request_irq(card->irq, &cs_interrupt, IRQF_SHARED, "cs46xx", card)) { | 5184 | if (request_irq(card->irq, &cs_interrupt, IRQF_SHARED, "cs46xx", card)) { |
5184 | printk(KERN_ERR "cs46xx: unable to allocate irq %d\n", card->irq); | 5185 | printk(KERN_ERR "cs46xx: unable to allocate irq %d\n", card->irq); |
5185 | goto fail2; | 5186 | goto fail2; |
5186 | } | 5187 | } |
5187 | /* register /dev/dsp */ | 5188 | /* register /dev/dsp */ |
5188 | if ((card->dev_audio = register_sound_dsp(&cs461x_fops, -1)) < 0) { | 5189 | if ((card->dev_audio = register_sound_dsp(&cs461x_fops, -1)) < 0) { |
5189 | printk(KERN_ERR "cs46xx: unable to register dsp\n"); | 5190 | printk(KERN_ERR "cs46xx: unable to register dsp\n"); |
5190 | goto fail; | 5191 | goto fail; |
5191 | } | 5192 | } |
5192 | 5193 | ||
5193 | /* register /dev/midi */ | 5194 | /* register /dev/midi */ |
5194 | if ((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0) | 5195 | if ((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0) |
5195 | printk(KERN_ERR "cs46xx: unable to register midi\n"); | 5196 | printk(KERN_ERR "cs46xx: unable to register midi\n"); |
5196 | 5197 | ||
5197 | card->pm.flags |= CS46XX_PM_IDLE; | 5198 | card->pm.flags |= CS46XX_PM_IDLE; |
5198 | for (i = 0; i < 5; i++) { | 5199 | for (i = 0; i < 5; i++) { |
5199 | if (cs_hardware_init(card) != 0) { | 5200 | if (cs_hardware_init(card) != 0) { |
5200 | CS_DBGOUT(CS_ERROR, 4, printk( | 5201 | CS_DBGOUT(CS_ERROR, 4, printk( |
5201 | "cs46xx: ERROR in cs_hardware_init()... retrying\n")); | 5202 | "cs46xx: ERROR in cs_hardware_init()... retrying\n")); |
5202 | for (j = 0; j < NR_AC97; j++) | 5203 | for (j = 0; j < NR_AC97; j++) |
5203 | if (card->ac97_codec[j] != NULL) { | 5204 | if (card->ac97_codec[j] != NULL) { |
5204 | unregister_sound_mixer(card->ac97_codec[j]->dev_mixer); | 5205 | unregister_sound_mixer(card->ac97_codec[j]->dev_mixer); |
5205 | ac97_release_codec(card->ac97_codec[j]); | 5206 | ac97_release_codec(card->ac97_codec[j]); |
5206 | } | 5207 | } |
5207 | mdelay(10 * cs_laptop_wait); | 5208 | mdelay(10 * cs_laptop_wait); |
5208 | continue; | 5209 | continue; |
5209 | } | 5210 | } |
5210 | break; | 5211 | break; |
5211 | } | 5212 | } |
5212 | if(i >= 4) { | 5213 | if(i >= 4) { |
5213 | CS_DBGOUT(CS_PM | CS_ERROR, 1, printk( | 5214 | CS_DBGOUT(CS_PM | CS_ERROR, 1, printk( |
5214 | "cs46xx: cs46xx_probe()- cs_hardware_init() failed, retried %d times.\n",i)); | 5215 | "cs46xx: cs46xx_probe()- cs_hardware_init() failed, retried %d times.\n",i)); |
5215 | unregister_sound_dsp(card->dev_audio); | 5216 | unregister_sound_dsp(card->dev_audio); |
5216 | if (card->dev_midi) | 5217 | if (card->dev_midi) |
5217 | unregister_sound_midi(card->dev_midi); | 5218 | unregister_sound_midi(card->dev_midi); |
5218 | goto fail; | 5219 | goto fail; |
5219 | } | 5220 | } |
5220 | 5221 | ||
5221 | init_waitqueue_head(&card->midi.open_wait); | 5222 | init_waitqueue_head(&card->midi.open_wait); |
5222 | mutex_init(&card->midi.open_mutex); | 5223 | mutex_init(&card->midi.open_mutex); |
5223 | init_waitqueue_head(&card->midi.iwait); | 5224 | init_waitqueue_head(&card->midi.iwait); |
5224 | init_waitqueue_head(&card->midi.owait); | 5225 | init_waitqueue_head(&card->midi.owait); |
5225 | cs461x_pokeBA0(card, BA0_MIDCR, MIDCR_MRST); | 5226 | cs461x_pokeBA0(card, BA0_MIDCR, MIDCR_MRST); |
5226 | cs461x_pokeBA0(card, BA0_MIDCR, 0); | 5227 | cs461x_pokeBA0(card, BA0_MIDCR, 0); |
5227 | 5228 | ||
5228 | /* | 5229 | /* |
5229 | * Check if we have to init the amplifier, but probably already done | 5230 | * Check if we have to init the amplifier, but probably already done |
5230 | * since the CD logic in the ac97 init code will turn on the ext amp. | 5231 | * since the CD logic in the ac97 init code will turn on the ext amp. |
5231 | */ | 5232 | */ |
5232 | if (cp->amp_init) | 5233 | if (cp->amp_init) |
5233 | cp->amp_init(card); | 5234 | cp->amp_init(card); |
5234 | card->active_ctrl(card, -1); | 5235 | card->active_ctrl(card, -1); |
5235 | 5236 | ||
5236 | PCI_SET_DRIVER_DATA(pci_dev, card); | 5237 | PCI_SET_DRIVER_DATA(pci_dev, card); |
5237 | PCI_SET_DMA_MASK(pci_dev, dma_mask); | 5238 | PCI_SET_DMA_MASK(pci_dev, dma_mask); |
5238 | list_add(&card->list, &cs46xx_devs); | 5239 | list_add(&card->list, &cs46xx_devs); |
5239 | 5240 | ||
5240 | CS_DBGOUT(CS_PM, 9, printk(KERN_INFO "cs46xx: pm.flags=0x%x card=%p\n", | 5241 | CS_DBGOUT(CS_PM, 9, printk(KERN_INFO "cs46xx: pm.flags=0x%x card=%p\n", |
5241 | (unsigned)card->pm.flags,card)); | 5242 | (unsigned)card->pm.flags,card)); |
5242 | 5243 | ||
5243 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO | 5244 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO |
5244 | "cs46xx: probe()- device allocated successfully\n")); | 5245 | "cs46xx: probe()- device allocated successfully\n")); |
5245 | return 0; | 5246 | return 0; |
5246 | 5247 | ||
5247 | fail: | 5248 | fail: |
5248 | free_irq(card->irq, card); | 5249 | free_irq(card->irq, card); |
5249 | fail2: | 5250 | fail2: |
5250 | if (card->ba0) | 5251 | if (card->ba0) |
5251 | iounmap(card->ba0); | 5252 | iounmap(card->ba0); |
5252 | if (card->ba1.name.data0) | 5253 | if (card->ba1.name.data0) |
5253 | iounmap(card->ba1.name.data0); | 5254 | iounmap(card->ba1.name.data0); |
5254 | if (card->ba1.name.data1) | 5255 | if (card->ba1.name.data1) |
5255 | iounmap(card->ba1.name.data1); | 5256 | iounmap(card->ba1.name.data1); |
5256 | if (card->ba1.name.pmem) | 5257 | if (card->ba1.name.pmem) |
5257 | iounmap(card->ba1.name.pmem); | 5258 | iounmap(card->ba1.name.pmem); |
5258 | if (card->ba1.name.reg) | 5259 | if (card->ba1.name.reg) |
5259 | iounmap(card->ba1.name.reg); | 5260 | iounmap(card->ba1.name.reg); |
5260 | kfree(card); | 5261 | kfree(card); |
5261 | CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO | 5262 | CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO |
5262 | "cs46xx: probe()- no device allocated\n")); | 5263 | "cs46xx: probe()- no device allocated\n")); |
5263 | return -ENODEV; | 5264 | return -ENODEV; |
5264 | } // probe_cs46xx | 5265 | } // probe_cs46xx |
5265 | 5266 | ||
5266 | // --------------------------------------------------------------------- | 5267 | // --------------------------------------------------------------------- |
5267 | 5268 | ||
5268 | static void __devexit cs46xx_remove(struct pci_dev *pci_dev) | 5269 | static void __devexit cs46xx_remove(struct pci_dev *pci_dev) |
5269 | { | 5270 | { |
5270 | struct cs_card *card = PCI_GET_DRIVER_DATA(pci_dev); | 5271 | struct cs_card *card = PCI_GET_DRIVER_DATA(pci_dev); |
5271 | int i; | 5272 | int i; |
5272 | unsigned int tmp; | 5273 | unsigned int tmp; |
5273 | 5274 | ||
5274 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO | 5275 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO |
5275 | "cs46xx: cs46xx_remove()+\n")); | 5276 | "cs46xx: cs46xx_remove()+\n")); |
5276 | 5277 | ||
5277 | card->active_ctrl(card,1); | 5278 | card->active_ctrl(card,1); |
5278 | 5279 | ||
5279 | tmp = cs461x_peek(card, BA1_PFIE); | 5280 | tmp = cs461x_peek(card, BA1_PFIE); |
5280 | tmp &= ~0x0000f03f; | 5281 | tmp &= ~0x0000f03f; |
5281 | tmp |= 0x00000010; | 5282 | tmp |= 0x00000010; |
5282 | cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt disable */ | 5283 | cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt disable */ |
5283 | 5284 | ||
5284 | tmp = cs461x_peek(card, BA1_CIE); | 5285 | tmp = cs461x_peek(card, BA1_CIE); |
5285 | tmp &= ~0x0000003f; | 5286 | tmp &= ~0x0000003f; |
5286 | tmp |= 0x00000011; | 5287 | tmp |= 0x00000011; |
5287 | cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt disable */ | 5288 | cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt disable */ |
5288 | 5289 | ||
5289 | /* | 5290 | /* |
5290 | * Stop playback DMA. | 5291 | * Stop playback DMA. |
5291 | */ | 5292 | */ |
5292 | tmp = cs461x_peek(card, BA1_PCTL); | 5293 | tmp = cs461x_peek(card, BA1_PCTL); |
5293 | cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff); | 5294 | cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff); |
5294 | 5295 | ||
5295 | /* | 5296 | /* |
5296 | * Stop capture DMA. | 5297 | * Stop capture DMA. |
5297 | */ | 5298 | */ |
5298 | tmp = cs461x_peek(card, BA1_CCTL); | 5299 | tmp = cs461x_peek(card, BA1_CCTL); |
5299 | cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000); | 5300 | cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000); |
5300 | 5301 | ||
5301 | /* | 5302 | /* |
5302 | * Reset the processor. | 5303 | * Reset the processor. |
5303 | */ | 5304 | */ |
5304 | cs461x_reset(card); | 5305 | cs461x_reset(card); |
5305 | 5306 | ||
5306 | cs461x_proc_stop(card); | 5307 | cs461x_proc_stop(card); |
5307 | 5308 | ||
5308 | /* | 5309 | /* |
5309 | * Power down the DAC and ADC. We will power them up (if) when we need | 5310 | * Power down the DAC and ADC. We will power them up (if) when we need |
5310 | * them. | 5311 | * them. |
5311 | */ | 5312 | */ |
5312 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | | 5313 | if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | |
5313 | CS_POWER_MIXVON, CS_TRUE))) { | 5314 | CS_POWER_MIXVON, CS_TRUE))) { |
5314 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO | 5315 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO |
5315 | "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) ); | 5316 | "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) ); |
5316 | } | 5317 | } |
5317 | 5318 | ||
5318 | /* | 5319 | /* |
5319 | * Power down the PLL. | 5320 | * Power down the PLL. |
5320 | */ | 5321 | */ |
5321 | cs461x_pokeBA0(card, BA0_CLKCR1, 0); | 5322 | cs461x_pokeBA0(card, BA0_CLKCR1, 0); |
5322 | 5323 | ||
5323 | /* | 5324 | /* |
5324 | * Turn off the Processor by turning off the software clock enable flag in | 5325 | * Turn off the Processor by turning off the software clock enable flag in |
5325 | * the clock control register. | 5326 | * the clock control register. |
5326 | */ | 5327 | */ |
5327 | tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; | 5328 | tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; |
5328 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); | 5329 | cs461x_pokeBA0(card, BA0_CLKCR1, tmp); |
5329 | 5330 | ||
5330 | card->active_ctrl(card,-1); | 5331 | card->active_ctrl(card,-1); |
5331 | 5332 | ||
5332 | /* free hardware resources */ | 5333 | /* free hardware resources */ |
5333 | free_irq(card->irq, card); | 5334 | free_irq(card->irq, card); |
5334 | iounmap(card->ba0); | 5335 | iounmap(card->ba0); |
5335 | iounmap(card->ba1.name.data0); | 5336 | iounmap(card->ba1.name.data0); |
5336 | iounmap(card->ba1.name.data1); | 5337 | iounmap(card->ba1.name.data1); |
5337 | iounmap(card->ba1.name.pmem); | 5338 | iounmap(card->ba1.name.pmem); |
5338 | iounmap(card->ba1.name.reg); | 5339 | iounmap(card->ba1.name.reg); |
5339 | 5340 | ||
5340 | /* unregister audio devices */ | 5341 | /* unregister audio devices */ |
5341 | for (i = 0; i < NR_AC97; i++) | 5342 | for (i = 0; i < NR_AC97; i++) |
5342 | if (card->ac97_codec[i] != NULL) { | 5343 | if (card->ac97_codec[i] != NULL) { |
5343 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); | 5344 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); |
5344 | ac97_release_codec(card->ac97_codec[i]); | 5345 | ac97_release_codec(card->ac97_codec[i]); |
5345 | } | 5346 | } |
5346 | unregister_sound_dsp(card->dev_audio); | 5347 | unregister_sound_dsp(card->dev_audio); |
5347 | if (card->dev_midi) | 5348 | if (card->dev_midi) |
5348 | unregister_sound_midi(card->dev_midi); | 5349 | unregister_sound_midi(card->dev_midi); |
5349 | list_del(&card->list); | 5350 | list_del(&card->list); |
5350 | kfree(card); | 5351 | kfree(card); |
5351 | PCI_SET_DRIVER_DATA(pci_dev,NULL); | 5352 | PCI_SET_DRIVER_DATA(pci_dev,NULL); |
5352 | 5353 | ||
5353 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO | 5354 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO |
5354 | "cs46xx: cs46xx_remove()-: remove successful\n")); | 5355 | "cs46xx: cs46xx_remove()-: remove successful\n")); |
5355 | } | 5356 | } |
5356 | 5357 | ||
5357 | enum { | 5358 | enum { |
5358 | CS46XX_4610 = 0, | 5359 | CS46XX_4610 = 0, |
5359 | CS46XX_4612, /* same as 4630 */ | 5360 | CS46XX_4612, /* same as 4630 */ |
5360 | CS46XX_4615, /* same as 4624 */ | 5361 | CS46XX_4615, /* same as 4624 */ |
5361 | }; | 5362 | }; |
5362 | 5363 | ||
5363 | static struct pci_device_id cs46xx_pci_tbl[] = { | 5364 | static struct pci_device_id cs46xx_pci_tbl[] = { |
5364 | { | 5365 | { |
5365 | .vendor = PCI_VENDOR_ID_CIRRUS, | 5366 | .vendor = PCI_VENDOR_ID_CIRRUS, |
5366 | .device = PCI_DEVICE_ID_CIRRUS_4610, | 5367 | .device = PCI_DEVICE_ID_CIRRUS_4610, |
5367 | .subvendor = PCI_ANY_ID, | 5368 | .subvendor = PCI_ANY_ID, |
5368 | .subdevice = PCI_ANY_ID, | 5369 | .subdevice = PCI_ANY_ID, |
5369 | .driver_data = CS46XX_4610, | 5370 | .driver_data = CS46XX_4610, |
5370 | }, | 5371 | }, |
5371 | { | 5372 | { |
5372 | .vendor = PCI_VENDOR_ID_CIRRUS, | 5373 | .vendor = PCI_VENDOR_ID_CIRRUS, |
5373 | .device = PCI_DEVICE_ID_CIRRUS_4612, | 5374 | .device = PCI_DEVICE_ID_CIRRUS_4612, |
5374 | .subvendor = PCI_ANY_ID, | 5375 | .subvendor = PCI_ANY_ID, |
5375 | .subdevice = PCI_ANY_ID, | 5376 | .subdevice = PCI_ANY_ID, |
5376 | .driver_data = CS46XX_4612, | 5377 | .driver_data = CS46XX_4612, |
5377 | }, | 5378 | }, |
5378 | { | 5379 | { |
5379 | .vendor = PCI_VENDOR_ID_CIRRUS, | 5380 | .vendor = PCI_VENDOR_ID_CIRRUS, |
5380 | .device = PCI_DEVICE_ID_CIRRUS_4615, | 5381 | .device = PCI_DEVICE_ID_CIRRUS_4615, |
5381 | .subvendor = PCI_ANY_ID, | 5382 | .subvendor = PCI_ANY_ID, |
5382 | .subdevice = PCI_ANY_ID, | 5383 | .subdevice = PCI_ANY_ID, |
5383 | .driver_data = CS46XX_4615, | 5384 | .driver_data = CS46XX_4615, |
5384 | }, | 5385 | }, |
5385 | { 0, }, | 5386 | { 0, }, |
5386 | }; | 5387 | }; |
5387 | 5388 | ||
5388 | MODULE_DEVICE_TABLE(pci, cs46xx_pci_tbl); | 5389 | MODULE_DEVICE_TABLE(pci, cs46xx_pci_tbl); |
5389 | 5390 | ||
5390 | static struct pci_driver cs46xx_pci_driver = { | 5391 | static struct pci_driver cs46xx_pci_driver = { |
5391 | .name = "cs46xx", | 5392 | .name = "cs46xx", |
5392 | .id_table = cs46xx_pci_tbl, | 5393 | .id_table = cs46xx_pci_tbl, |
5393 | .probe = cs46xx_probe, | 5394 | .probe = cs46xx_probe, |
5394 | .remove = __devexit_p(cs46xx_remove), | 5395 | .remove = __devexit_p(cs46xx_remove), |
5395 | #ifdef CONFIG_PM | 5396 | #ifdef CONFIG_PM |
5396 | .suspend = cs46xx_suspend_tbl, | 5397 | .suspend = cs46xx_suspend_tbl, |
5397 | .resume = cs46xx_resume_tbl, | 5398 | .resume = cs46xx_resume_tbl, |
5398 | #endif | 5399 | #endif |
5399 | }; | 5400 | }; |
5400 | 5401 | ||
5401 | static int __init cs46xx_init_module(void) | 5402 | static int __init cs46xx_init_module(void) |
5402 | { | 5403 | { |
5403 | int rtn = 0; | 5404 | int rtn = 0; |
5404 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO | 5405 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO |
5405 | "cs46xx: cs46xx_init_module()+ \n")); | 5406 | "cs46xx: cs46xx_init_module()+ \n")); |
5406 | rtn = pci_register_driver(&cs46xx_pci_driver); | 5407 | rtn = pci_register_driver(&cs46xx_pci_driver); |
5407 | 5408 | ||
5408 | if (rtn == -ENODEV) { | 5409 | if (rtn == -ENODEV) { |
5409 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk( | 5410 | CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk( |
5410 | "cs46xx: Unable to detect valid cs46xx device\n")); | 5411 | "cs46xx: Unable to detect valid cs46xx device\n")); |
5411 | } | 5412 | } |
5412 | 5413 | ||
5413 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, | 5414 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, |
5414 | printk(KERN_INFO "cs46xx: cs46xx_init_module()- (%d)\n",rtn)); | 5415 | printk(KERN_INFO "cs46xx: cs46xx_init_module()- (%d)\n",rtn)); |
5415 | return rtn; | 5416 | return rtn; |
5416 | } | 5417 | } |
5417 | 5418 | ||
5418 | static void __exit cs46xx_cleanup_module(void) | 5419 | static void __exit cs46xx_cleanup_module(void) |
5419 | { | 5420 | { |
5420 | pci_unregister_driver(&cs46xx_pci_driver); | 5421 | pci_unregister_driver(&cs46xx_pci_driver); |
5421 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, | 5422 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, |
5422 | printk(KERN_INFO "cs46xx: cleanup_cs46xx() finished\n")); | 5423 | printk(KERN_INFO "cs46xx: cleanup_cs46xx() finished\n")); |
5423 | } | 5424 | } |
5424 | 5425 | ||
5425 | module_init(cs46xx_init_module); | 5426 | module_init(cs46xx_init_module); |
5426 | module_exit(cs46xx_cleanup_module); | 5427 | module_exit(cs46xx_cleanup_module); |
5427 | 5428 | ||
5428 | #ifdef CONFIG_PM | 5429 | #ifdef CONFIG_PM |
5429 | static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state) | 5430 | static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state) |
5430 | { | 5431 | { |
5431 | struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); | 5432 | struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); |
5432 | CS_DBGOUT(CS_PM | CS_FUNCTION, 2, | 5433 | CS_DBGOUT(CS_PM | CS_FUNCTION, 2, |
5433 | printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n")); | 5434 | printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n")); |
5434 | cs46xx_suspend(s, state); | 5435 | cs46xx_suspend(s, state); |
5435 | return 0; | 5436 | return 0; |
5436 | } | 5437 | } |
5437 | 5438 | ||
5438 | static int cs46xx_resume_tbl(struct pci_dev *pcidev) | 5439 | static int cs46xx_resume_tbl(struct pci_dev *pcidev) |
5439 | { | 5440 | { |
5440 | struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); | 5441 | struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); |
5441 | CS_DBGOUT(CS_PM | CS_FUNCTION, 2, | 5442 | CS_DBGOUT(CS_PM | CS_FUNCTION, 2, |
5442 | printk(KERN_INFO "cs46xx: cs46xx_resume_tbl request\n")); | 5443 | printk(KERN_INFO "cs46xx: cs46xx_resume_tbl request\n")); |
5443 | cs46xx_resume(s); | 5444 | cs46xx_resume(s); |
5444 | return 0; | 5445 | return 0; |
5445 | } | 5446 | } |
5446 | #endif | 5447 | #endif |
5447 | 5448 |
sound/oss/dmabuf.c
1 | /* | 1 | /* |
2 | * sound/oss/dmabuf.c | 2 | * sound/oss/dmabuf.c |
3 | * | 3 | * |
4 | * The DMA buffer manager for digitized voice applications | 4 | * The DMA buffer manager for digitized voice applications |
5 | */ | 5 | */ |
6 | /* | 6 | /* |
7 | * Copyright (C) by Hannu Savolainen 1993-1997 | 7 | * Copyright (C) by Hannu Savolainen 1993-1997 |
8 | * | 8 | * |
9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) | 9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) |
10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software | 10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software |
11 | * for more info. | 11 | * for more info. |
12 | * | 12 | * |
13 | * Thomas Sailer : moved several static variables into struct audio_operations | 13 | * Thomas Sailer : moved several static variables into struct audio_operations |
14 | * (which is grossly misnamed btw.) because they have the same | 14 | * (which is grossly misnamed btw.) because they have the same |
15 | * lifetime as the rest in there and dynamic allocation saves | 15 | * lifetime as the rest in there and dynamic allocation saves |
16 | * 12k or so | 16 | * 12k or so |
17 | * Thomas Sailer : remove {in,out}_sleep_flag. It was used for the sleeper to | 17 | * Thomas Sailer : remove {in,out}_sleep_flag. It was used for the sleeper to |
18 | * determine if it was woken up by the expiring timeout or by | 18 | * determine if it was woken up by the expiring timeout or by |
19 | * an explicit wake_up. The return value from schedule_timeout | 19 | * an explicit wake_up. The return value from schedule_timeout |
20 | * can be used instead; if 0, the wakeup was due to the timeout. | 20 | * can be used instead; if 0, the wakeup was due to the timeout. |
21 | * | 21 | * |
22 | * Rob Riggs Added persistent DMA buffers (1998/10/17) | 22 | * Rob Riggs Added persistent DMA buffers (1998/10/17) |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #define BE_CONSERVATIVE | 25 | #define BE_CONSERVATIVE |
26 | #define SAMPLE_ROUNDUP 0 | 26 | #define SAMPLE_ROUNDUP 0 |
27 | 27 | ||
28 | #include <linux/mm.h> | ||
28 | #include "sound_config.h" | 29 | #include "sound_config.h" |
29 | 30 | ||
30 | #define DMAP_FREE_ON_CLOSE 0 | 31 | #define DMAP_FREE_ON_CLOSE 0 |
31 | #define DMAP_KEEP_ON_CLOSE 1 | 32 | #define DMAP_KEEP_ON_CLOSE 1 |
32 | extern int sound_dmap_flag; | 33 | extern int sound_dmap_flag; |
33 | 34 | ||
34 | static void dma_reset_output(int dev); | 35 | static void dma_reset_output(int dev); |
35 | static void dma_reset_input(int dev); | 36 | static void dma_reset_input(int dev); |
36 | static int local_start_dma(struct audio_operations *adev, unsigned long physaddr, int count, int dma_mode); | 37 | static int local_start_dma(struct audio_operations *adev, unsigned long physaddr, int count, int dma_mode); |
37 | 38 | ||
38 | 39 | ||
39 | 40 | ||
40 | static int debugmem; /* switched off by default */ | 41 | static int debugmem; /* switched off by default */ |
41 | static int dma_buffsize = DSP_BUFFSIZE; | 42 | static int dma_buffsize = DSP_BUFFSIZE; |
42 | 43 | ||
43 | static long dmabuf_timeout(struct dma_buffparms *dmap) | 44 | static long dmabuf_timeout(struct dma_buffparms *dmap) |
44 | { | 45 | { |
45 | long tmout; | 46 | long tmout; |
46 | 47 | ||
47 | tmout = (dmap->fragment_size * HZ) / dmap->data_rate; | 48 | tmout = (dmap->fragment_size * HZ) / dmap->data_rate; |
48 | tmout += HZ / 5; /* Some safety distance */ | 49 | tmout += HZ / 5; /* Some safety distance */ |
49 | if (tmout < (HZ / 2)) | 50 | if (tmout < (HZ / 2)) |
50 | tmout = HZ / 2; | 51 | tmout = HZ / 2; |
51 | if (tmout > 20 * HZ) | 52 | if (tmout > 20 * HZ) |
52 | tmout = 20 * HZ; | 53 | tmout = 20 * HZ; |
53 | return tmout; | 54 | return tmout; |
54 | } | 55 | } |
55 | 56 | ||
56 | static int sound_alloc_dmap(struct dma_buffparms *dmap) | 57 | static int sound_alloc_dmap(struct dma_buffparms *dmap) |
57 | { | 58 | { |
58 | char *start_addr, *end_addr; | 59 | char *start_addr, *end_addr; |
59 | int dma_pagesize; | 60 | int dma_pagesize; |
60 | int sz, size; | 61 | int sz, size; |
61 | struct page *page; | 62 | struct page *page; |
62 | 63 | ||
63 | dmap->mapping_flags &= ~DMA_MAP_MAPPED; | 64 | dmap->mapping_flags &= ~DMA_MAP_MAPPED; |
64 | 65 | ||
65 | if (dmap->raw_buf != NULL) | 66 | if (dmap->raw_buf != NULL) |
66 | return 0; /* Already done */ | 67 | return 0; /* Already done */ |
67 | if (dma_buffsize < 4096) | 68 | if (dma_buffsize < 4096) |
68 | dma_buffsize = 4096; | 69 | dma_buffsize = 4096; |
69 | dma_pagesize = (dmap->dma < 4) ? (64 * 1024) : (128 * 1024); | 70 | dma_pagesize = (dmap->dma < 4) ? (64 * 1024) : (128 * 1024); |
70 | 71 | ||
71 | /* | 72 | /* |
72 | * Now check for the Cyrix problem. | 73 | * Now check for the Cyrix problem. |
73 | */ | 74 | */ |
74 | 75 | ||
75 | if(isa_dma_bridge_buggy==2) | 76 | if(isa_dma_bridge_buggy==2) |
76 | dma_pagesize=32768; | 77 | dma_pagesize=32768; |
77 | 78 | ||
78 | dmap->raw_buf = NULL; | 79 | dmap->raw_buf = NULL; |
79 | dmap->buffsize = dma_buffsize; | 80 | dmap->buffsize = dma_buffsize; |
80 | if (dmap->buffsize > dma_pagesize) | 81 | if (dmap->buffsize > dma_pagesize) |
81 | dmap->buffsize = dma_pagesize; | 82 | dmap->buffsize = dma_pagesize; |
82 | start_addr = NULL; | 83 | start_addr = NULL; |
83 | /* | 84 | /* |
84 | * Now loop until we get a free buffer. Try to get smaller buffer if | 85 | * Now loop until we get a free buffer. Try to get smaller buffer if |
85 | * it fails. Don't accept smaller than 8k buffer for performance | 86 | * it fails. Don't accept smaller than 8k buffer for performance |
86 | * reasons. | 87 | * reasons. |
87 | */ | 88 | */ |
88 | while (start_addr == NULL && dmap->buffsize > PAGE_SIZE) { | 89 | while (start_addr == NULL && dmap->buffsize > PAGE_SIZE) { |
89 | for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); | 90 | for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); |
90 | dmap->buffsize = PAGE_SIZE * (1 << sz); | 91 | dmap->buffsize = PAGE_SIZE * (1 << sz); |
91 | start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA|__GFP_NOWARN, sz); | 92 | start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA|__GFP_NOWARN, sz); |
92 | if (start_addr == NULL) | 93 | if (start_addr == NULL) |
93 | dmap->buffsize /= 2; | 94 | dmap->buffsize /= 2; |
94 | } | 95 | } |
95 | 96 | ||
96 | if (start_addr == NULL) { | 97 | if (start_addr == NULL) { |
97 | printk(KERN_WARNING "Sound error: Couldn't allocate DMA buffer\n"); | 98 | printk(KERN_WARNING "Sound error: Couldn't allocate DMA buffer\n"); |
98 | return -ENOMEM; | 99 | return -ENOMEM; |
99 | } else { | 100 | } else { |
100 | /* make some checks */ | 101 | /* make some checks */ |
101 | end_addr = start_addr + dmap->buffsize - 1; | 102 | end_addr = start_addr + dmap->buffsize - 1; |
102 | 103 | ||
103 | if (debugmem) | 104 | if (debugmem) |
104 | printk(KERN_DEBUG "sound: start 0x%lx, end 0x%lx\n", (long) start_addr, (long) end_addr); | 105 | printk(KERN_DEBUG "sound: start 0x%lx, end 0x%lx\n", (long) start_addr, (long) end_addr); |
105 | 106 | ||
106 | /* now check if it fits into the same dma-pagesize */ | 107 | /* now check if it fits into the same dma-pagesize */ |
107 | 108 | ||
108 | if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1)) | 109 | if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1)) |
109 | || end_addr >= (char *) (MAX_DMA_ADDRESS)) { | 110 | || end_addr >= (char *) (MAX_DMA_ADDRESS)) { |
110 | printk(KERN_ERR "sound: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, dmap->buffsize); | 111 | printk(KERN_ERR "sound: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, dmap->buffsize); |
111 | return -EFAULT; | 112 | return -EFAULT; |
112 | } | 113 | } |
113 | } | 114 | } |
114 | dmap->raw_buf = start_addr; | 115 | dmap->raw_buf = start_addr; |
115 | dmap->raw_buf_phys = virt_to_bus(start_addr); | 116 | dmap->raw_buf_phys = virt_to_bus(start_addr); |
116 | 117 | ||
117 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) | 118 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) |
118 | SetPageReserved(page); | 119 | SetPageReserved(page); |
119 | return 0; | 120 | return 0; |
120 | } | 121 | } |
121 | 122 | ||
122 | static void sound_free_dmap(struct dma_buffparms *dmap) | 123 | static void sound_free_dmap(struct dma_buffparms *dmap) |
123 | { | 124 | { |
124 | int sz, size; | 125 | int sz, size; |
125 | struct page *page; | 126 | struct page *page; |
126 | unsigned long start_addr, end_addr; | 127 | unsigned long start_addr, end_addr; |
127 | 128 | ||
128 | if (dmap->raw_buf == NULL) | 129 | if (dmap->raw_buf == NULL) |
129 | return; | 130 | return; |
130 | if (dmap->mapping_flags & DMA_MAP_MAPPED) | 131 | if (dmap->mapping_flags & DMA_MAP_MAPPED) |
131 | return; /* Don't free mmapped buffer. Will use it next time */ | 132 | return; /* Don't free mmapped buffer. Will use it next time */ |
132 | for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); | 133 | for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); |
133 | 134 | ||
134 | start_addr = (unsigned long) dmap->raw_buf; | 135 | start_addr = (unsigned long) dmap->raw_buf; |
135 | end_addr = start_addr + dmap->buffsize; | 136 | end_addr = start_addr + dmap->buffsize; |
136 | 137 | ||
137 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) | 138 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) |
138 | ClearPageReserved(page); | 139 | ClearPageReserved(page); |
139 | 140 | ||
140 | free_pages((unsigned long) dmap->raw_buf, sz); | 141 | free_pages((unsigned long) dmap->raw_buf, sz); |
141 | dmap->raw_buf = NULL; | 142 | dmap->raw_buf = NULL; |
142 | } | 143 | } |
143 | 144 | ||
144 | 145 | ||
145 | /* Intel version !!!!!!!!! */ | 146 | /* Intel version !!!!!!!!! */ |
146 | 147 | ||
147 | static int sound_start_dma(struct dma_buffparms *dmap, unsigned long physaddr, int count, int dma_mode) | 148 | static int sound_start_dma(struct dma_buffparms *dmap, unsigned long physaddr, int count, int dma_mode) |
148 | { | 149 | { |
149 | unsigned long flags; | 150 | unsigned long flags; |
150 | int chan = dmap->dma; | 151 | int chan = dmap->dma; |
151 | 152 | ||
152 | /* printk( "Start DMA%d %d, %d\n", chan, (int)(physaddr-dmap->raw_buf_phys), count); */ | 153 | /* printk( "Start DMA%d %d, %d\n", chan, (int)(physaddr-dmap->raw_buf_phys), count); */ |
153 | 154 | ||
154 | flags = claim_dma_lock(); | 155 | flags = claim_dma_lock(); |
155 | disable_dma(chan); | 156 | disable_dma(chan); |
156 | clear_dma_ff(chan); | 157 | clear_dma_ff(chan); |
157 | set_dma_mode(chan, dma_mode); | 158 | set_dma_mode(chan, dma_mode); |
158 | set_dma_addr(chan, physaddr); | 159 | set_dma_addr(chan, physaddr); |
159 | set_dma_count(chan, count); | 160 | set_dma_count(chan, count); |
160 | enable_dma(chan); | 161 | enable_dma(chan); |
161 | release_dma_lock(flags); | 162 | release_dma_lock(flags); |
162 | 163 | ||
163 | return 0; | 164 | return 0; |
164 | } | 165 | } |
165 | 166 | ||
166 | static void dma_init_buffers(struct dma_buffparms *dmap) | 167 | static void dma_init_buffers(struct dma_buffparms *dmap) |
167 | { | 168 | { |
168 | dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; | 169 | dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; |
169 | dmap->byte_counter = 0; | 170 | dmap->byte_counter = 0; |
170 | dmap->max_byte_counter = 8000 * 60 * 60; | 171 | dmap->max_byte_counter = 8000 * 60 * 60; |
171 | dmap->bytes_in_use = dmap->buffsize; | 172 | dmap->bytes_in_use = dmap->buffsize; |
172 | 173 | ||
173 | dmap->dma_mode = DMODE_NONE; | 174 | dmap->dma_mode = DMODE_NONE; |
174 | dmap->mapping_flags = 0; | 175 | dmap->mapping_flags = 0; |
175 | dmap->neutral_byte = 0x80; | 176 | dmap->neutral_byte = 0x80; |
176 | dmap->data_rate = 8000; | 177 | dmap->data_rate = 8000; |
177 | dmap->cfrag = -1; | 178 | dmap->cfrag = -1; |
178 | dmap->closing = 0; | 179 | dmap->closing = 0; |
179 | dmap->nbufs = 1; | 180 | dmap->nbufs = 1; |
180 | dmap->flags = DMA_BUSY; /* Other flags off */ | 181 | dmap->flags = DMA_BUSY; /* Other flags off */ |
181 | } | 182 | } |
182 | 183 | ||
183 | static int open_dmap(struct audio_operations *adev, int mode, struct dma_buffparms *dmap) | 184 | static int open_dmap(struct audio_operations *adev, int mode, struct dma_buffparms *dmap) |
184 | { | 185 | { |
185 | int err; | 186 | int err; |
186 | 187 | ||
187 | if (dmap->flags & DMA_BUSY) | 188 | if (dmap->flags & DMA_BUSY) |
188 | return -EBUSY; | 189 | return -EBUSY; |
189 | if ((err = sound_alloc_dmap(dmap)) < 0) | 190 | if ((err = sound_alloc_dmap(dmap)) < 0) |
190 | return err; | 191 | return err; |
191 | 192 | ||
192 | if (dmap->raw_buf == NULL) { | 193 | if (dmap->raw_buf == NULL) { |
193 | printk(KERN_WARNING "Sound: DMA buffers not available\n"); | 194 | printk(KERN_WARNING "Sound: DMA buffers not available\n"); |
194 | return -ENOSPC; /* Memory allocation failed during boot */ | 195 | return -ENOSPC; /* Memory allocation failed during boot */ |
195 | } | 196 | } |
196 | if (dmap->dma >= 0 && sound_open_dma(dmap->dma, adev->name)) { | 197 | if (dmap->dma >= 0 && sound_open_dma(dmap->dma, adev->name)) { |
197 | printk(KERN_WARNING "Unable to grab(2) DMA%d for the audio driver\n", dmap->dma); | 198 | printk(KERN_WARNING "Unable to grab(2) DMA%d for the audio driver\n", dmap->dma); |
198 | return -EBUSY; | 199 | return -EBUSY; |
199 | } | 200 | } |
200 | dma_init_buffers(dmap); | 201 | dma_init_buffers(dmap); |
201 | spin_lock_init(&dmap->lock); | 202 | spin_lock_init(&dmap->lock); |
202 | dmap->open_mode = mode; | 203 | dmap->open_mode = mode; |
203 | dmap->subdivision = dmap->underrun_count = 0; | 204 | dmap->subdivision = dmap->underrun_count = 0; |
204 | dmap->fragment_size = 0; | 205 | dmap->fragment_size = 0; |
205 | dmap->max_fragments = 65536; /* Just a large value */ | 206 | dmap->max_fragments = 65536; /* Just a large value */ |
206 | dmap->byte_counter = 0; | 207 | dmap->byte_counter = 0; |
207 | dmap->max_byte_counter = 8000 * 60 * 60; | 208 | dmap->max_byte_counter = 8000 * 60 * 60; |
208 | dmap->applic_profile = APF_NORMAL; | 209 | dmap->applic_profile = APF_NORMAL; |
209 | dmap->needs_reorg = 1; | 210 | dmap->needs_reorg = 1; |
210 | dmap->audio_callback = NULL; | 211 | dmap->audio_callback = NULL; |
211 | dmap->callback_parm = 0; | 212 | dmap->callback_parm = 0; |
212 | return 0; | 213 | return 0; |
213 | } | 214 | } |
214 | 215 | ||
215 | static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap) | 216 | static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap) |
216 | { | 217 | { |
217 | unsigned long flags; | 218 | unsigned long flags; |
218 | 219 | ||
219 | if (dmap->dma >= 0) { | 220 | if (dmap->dma >= 0) { |
220 | sound_close_dma(dmap->dma); | 221 | sound_close_dma(dmap->dma); |
221 | flags=claim_dma_lock(); | 222 | flags=claim_dma_lock(); |
222 | disable_dma(dmap->dma); | 223 | disable_dma(dmap->dma); |
223 | release_dma_lock(flags); | 224 | release_dma_lock(flags); |
224 | } | 225 | } |
225 | if (dmap->flags & DMA_BUSY) | 226 | if (dmap->flags & DMA_BUSY) |
226 | dmap->dma_mode = DMODE_NONE; | 227 | dmap->dma_mode = DMODE_NONE; |
227 | dmap->flags &= ~DMA_BUSY; | 228 | dmap->flags &= ~DMA_BUSY; |
228 | 229 | ||
229 | if (sound_dmap_flag == DMAP_FREE_ON_CLOSE) | 230 | if (sound_dmap_flag == DMAP_FREE_ON_CLOSE) |
230 | sound_free_dmap(dmap); | 231 | sound_free_dmap(dmap); |
231 | } | 232 | } |
232 | 233 | ||
233 | 234 | ||
234 | static unsigned int default_set_bits(int dev, unsigned int bits) | 235 | static unsigned int default_set_bits(int dev, unsigned int bits) |
235 | { | 236 | { |
236 | mm_segment_t fs = get_fs(); | 237 | mm_segment_t fs = get_fs(); |
237 | 238 | ||
238 | set_fs(get_ds()); | 239 | set_fs(get_ds()); |
239 | audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_SETFMT, (void __user *)&bits); | 240 | audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_SETFMT, (void __user *)&bits); |
240 | set_fs(fs); | 241 | set_fs(fs); |
241 | return bits; | 242 | return bits; |
242 | } | 243 | } |
243 | 244 | ||
244 | static int default_set_speed(int dev, int speed) | 245 | static int default_set_speed(int dev, int speed) |
245 | { | 246 | { |
246 | mm_segment_t fs = get_fs(); | 247 | mm_segment_t fs = get_fs(); |
247 | 248 | ||
248 | set_fs(get_ds()); | 249 | set_fs(get_ds()); |
249 | audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_SPEED, (void __user *)&speed); | 250 | audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_SPEED, (void __user *)&speed); |
250 | set_fs(fs); | 251 | set_fs(fs); |
251 | return speed; | 252 | return speed; |
252 | } | 253 | } |
253 | 254 | ||
254 | static short default_set_channels(int dev, short channels) | 255 | static short default_set_channels(int dev, short channels) |
255 | { | 256 | { |
256 | int c = channels; | 257 | int c = channels; |
257 | mm_segment_t fs = get_fs(); | 258 | mm_segment_t fs = get_fs(); |
258 | 259 | ||
259 | set_fs(get_ds()); | 260 | set_fs(get_ds()); |
260 | audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_CHANNELS, (void __user *)&c); | 261 | audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_CHANNELS, (void __user *)&c); |
261 | set_fs(fs); | 262 | set_fs(fs); |
262 | return c; | 263 | return c; |
263 | } | 264 | } |
264 | 265 | ||
265 | static void check_driver(struct audio_driver *d) | 266 | static void check_driver(struct audio_driver *d) |
266 | { | 267 | { |
267 | if (d->set_speed == NULL) | 268 | if (d->set_speed == NULL) |
268 | d->set_speed = default_set_speed; | 269 | d->set_speed = default_set_speed; |
269 | if (d->set_bits == NULL) | 270 | if (d->set_bits == NULL) |
270 | d->set_bits = default_set_bits; | 271 | d->set_bits = default_set_bits; |
271 | if (d->set_channels == NULL) | 272 | if (d->set_channels == NULL) |
272 | d->set_channels = default_set_channels; | 273 | d->set_channels = default_set_channels; |
273 | } | 274 | } |
274 | 275 | ||
275 | int DMAbuf_open(int dev, int mode) | 276 | int DMAbuf_open(int dev, int mode) |
276 | { | 277 | { |
277 | struct audio_operations *adev = audio_devs[dev]; | 278 | struct audio_operations *adev = audio_devs[dev]; |
278 | int retval; | 279 | int retval; |
279 | struct dma_buffparms *dmap_in = NULL; | 280 | struct dma_buffparms *dmap_in = NULL; |
280 | struct dma_buffparms *dmap_out = NULL; | 281 | struct dma_buffparms *dmap_out = NULL; |
281 | 282 | ||
282 | if (!adev) | 283 | if (!adev) |
283 | return -ENXIO; | 284 | return -ENXIO; |
284 | if (!(adev->flags & DMA_DUPLEX)) | 285 | if (!(adev->flags & DMA_DUPLEX)) |
285 | adev->dmap_in = adev->dmap_out; | 286 | adev->dmap_in = adev->dmap_out; |
286 | check_driver(adev->d); | 287 | check_driver(adev->d); |
287 | 288 | ||
288 | if ((retval = adev->d->open(dev, mode)) < 0) | 289 | if ((retval = adev->d->open(dev, mode)) < 0) |
289 | return retval; | 290 | return retval; |
290 | dmap_out = adev->dmap_out; | 291 | dmap_out = adev->dmap_out; |
291 | dmap_in = adev->dmap_in; | 292 | dmap_in = adev->dmap_in; |
292 | if (dmap_in == dmap_out) | 293 | if (dmap_in == dmap_out) |
293 | adev->flags &= ~DMA_DUPLEX; | 294 | adev->flags &= ~DMA_DUPLEX; |
294 | 295 | ||
295 | if (mode & OPEN_WRITE) { | 296 | if (mode & OPEN_WRITE) { |
296 | if ((retval = open_dmap(adev, mode, dmap_out)) < 0) { | 297 | if ((retval = open_dmap(adev, mode, dmap_out)) < 0) { |
297 | adev->d->close(dev); | 298 | adev->d->close(dev); |
298 | return retval; | 299 | return retval; |
299 | } | 300 | } |
300 | } | 301 | } |
301 | adev->enable_bits = mode; | 302 | adev->enable_bits = mode; |
302 | 303 | ||
303 | if (mode == OPEN_READ || (mode != OPEN_WRITE && (adev->flags & DMA_DUPLEX))) { | 304 | if (mode == OPEN_READ || (mode != OPEN_WRITE && (adev->flags & DMA_DUPLEX))) { |
304 | if ((retval = open_dmap(adev, mode, dmap_in)) < 0) { | 305 | if ((retval = open_dmap(adev, mode, dmap_in)) < 0) { |
305 | adev->d->close(dev); | 306 | adev->d->close(dev); |
306 | if (mode & OPEN_WRITE) | 307 | if (mode & OPEN_WRITE) |
307 | close_dmap(adev, dmap_out); | 308 | close_dmap(adev, dmap_out); |
308 | return retval; | 309 | return retval; |
309 | } | 310 | } |
310 | } | 311 | } |
311 | adev->open_mode = mode; | 312 | adev->open_mode = mode; |
312 | adev->go = 1; | 313 | adev->go = 1; |
313 | 314 | ||
314 | adev->d->set_bits(dev, 8); | 315 | adev->d->set_bits(dev, 8); |
315 | adev->d->set_channels(dev, 1); | 316 | adev->d->set_channels(dev, 1); |
316 | adev->d->set_speed(dev, DSP_DEFAULT_SPEED); | 317 | adev->d->set_speed(dev, DSP_DEFAULT_SPEED); |
317 | if (adev->dmap_out->dma_mode == DMODE_OUTPUT) | 318 | if (adev->dmap_out->dma_mode == DMODE_OUTPUT) |
318 | memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, | 319 | memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, |
319 | adev->dmap_out->bytes_in_use); | 320 | adev->dmap_out->bytes_in_use); |
320 | return 0; | 321 | return 0; |
321 | } | 322 | } |
322 | /* MUST not hold the spinlock */ | 323 | /* MUST not hold the spinlock */ |
323 | void DMAbuf_reset(int dev) | 324 | void DMAbuf_reset(int dev) |
324 | { | 325 | { |
325 | if (audio_devs[dev]->open_mode & OPEN_WRITE) | 326 | if (audio_devs[dev]->open_mode & OPEN_WRITE) |
326 | dma_reset_output(dev); | 327 | dma_reset_output(dev); |
327 | 328 | ||
328 | if (audio_devs[dev]->open_mode & OPEN_READ) | 329 | if (audio_devs[dev]->open_mode & OPEN_READ) |
329 | dma_reset_input(dev); | 330 | dma_reset_input(dev); |
330 | } | 331 | } |
331 | 332 | ||
332 | static void dma_reset_output(int dev) | 333 | static void dma_reset_output(int dev) |
333 | { | 334 | { |
334 | struct audio_operations *adev = audio_devs[dev]; | 335 | struct audio_operations *adev = audio_devs[dev]; |
335 | unsigned long flags,f ; | 336 | unsigned long flags,f ; |
336 | struct dma_buffparms *dmap = adev->dmap_out; | 337 | struct dma_buffparms *dmap = adev->dmap_out; |
337 | 338 | ||
338 | if (!(dmap->flags & DMA_STARTED)) /* DMA is not active */ | 339 | if (!(dmap->flags & DMA_STARTED)) /* DMA is not active */ |
339 | return; | 340 | return; |
340 | 341 | ||
341 | /* | 342 | /* |
342 | * First wait until the current fragment has been played completely | 343 | * First wait until the current fragment has been played completely |
343 | */ | 344 | */ |
344 | spin_lock_irqsave(&dmap->lock,flags); | 345 | spin_lock_irqsave(&dmap->lock,flags); |
345 | adev->dmap_out->flags |= DMA_SYNCING; | 346 | adev->dmap_out->flags |= DMA_SYNCING; |
346 | 347 | ||
347 | adev->dmap_out->underrun_count = 0; | 348 | adev->dmap_out->underrun_count = 0; |
348 | if (!signal_pending(current) && adev->dmap_out->qlen && | 349 | if (!signal_pending(current) && adev->dmap_out->qlen && |
349 | adev->dmap_out->underrun_count == 0){ | 350 | adev->dmap_out->underrun_count == 0){ |
350 | spin_unlock_irqrestore(&dmap->lock,flags); | 351 | spin_unlock_irqrestore(&dmap->lock,flags); |
351 | interruptible_sleep_on_timeout(&adev->out_sleeper, | 352 | interruptible_sleep_on_timeout(&adev->out_sleeper, |
352 | dmabuf_timeout(dmap)); | 353 | dmabuf_timeout(dmap)); |
353 | spin_lock_irqsave(&dmap->lock,flags); | 354 | spin_lock_irqsave(&dmap->lock,flags); |
354 | } | 355 | } |
355 | adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); | 356 | adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); |
356 | 357 | ||
357 | /* | 358 | /* |
358 | * Finally shut the device off | 359 | * Finally shut the device off |
359 | */ | 360 | */ |
360 | if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_output) | 361 | if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_output) |
361 | adev->d->halt_io(dev); | 362 | adev->d->halt_io(dev); |
362 | else | 363 | else |
363 | adev->d->halt_output(dev); | 364 | adev->d->halt_output(dev); |
364 | adev->dmap_out->flags &= ~DMA_STARTED; | 365 | adev->dmap_out->flags &= ~DMA_STARTED; |
365 | 366 | ||
366 | f=claim_dma_lock(); | 367 | f=claim_dma_lock(); |
367 | clear_dma_ff(dmap->dma); | 368 | clear_dma_ff(dmap->dma); |
368 | disable_dma(dmap->dma); | 369 | disable_dma(dmap->dma); |
369 | release_dma_lock(f); | 370 | release_dma_lock(f); |
370 | 371 | ||
371 | dmap->byte_counter = 0; | 372 | dmap->byte_counter = 0; |
372 | reorganize_buffers(dev, adev->dmap_out, 0); | 373 | reorganize_buffers(dev, adev->dmap_out, 0); |
373 | dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; | 374 | dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; |
374 | spin_unlock_irqrestore(&dmap->lock,flags); | 375 | spin_unlock_irqrestore(&dmap->lock,flags); |
375 | } | 376 | } |
376 | 377 | ||
377 | static void dma_reset_input(int dev) | 378 | static void dma_reset_input(int dev) |
378 | { | 379 | { |
379 | struct audio_operations *adev = audio_devs[dev]; | 380 | struct audio_operations *adev = audio_devs[dev]; |
380 | unsigned long flags; | 381 | unsigned long flags; |
381 | struct dma_buffparms *dmap = adev->dmap_in; | 382 | struct dma_buffparms *dmap = adev->dmap_in; |
382 | 383 | ||
383 | spin_lock_irqsave(&dmap->lock,flags); | 384 | spin_lock_irqsave(&dmap->lock,flags); |
384 | if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_input) | 385 | if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_input) |
385 | adev->d->halt_io(dev); | 386 | adev->d->halt_io(dev); |
386 | else | 387 | else |
387 | adev->d->halt_input(dev); | 388 | adev->d->halt_input(dev); |
388 | adev->dmap_in->flags &= ~DMA_STARTED; | 389 | adev->dmap_in->flags &= ~DMA_STARTED; |
389 | 390 | ||
390 | dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; | 391 | dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; |
391 | dmap->byte_counter = 0; | 392 | dmap->byte_counter = 0; |
392 | reorganize_buffers(dev, adev->dmap_in, 1); | 393 | reorganize_buffers(dev, adev->dmap_in, 1); |
393 | spin_unlock_irqrestore(&dmap->lock,flags); | 394 | spin_unlock_irqrestore(&dmap->lock,flags); |
394 | } | 395 | } |
395 | /* MUST be called with holding the dmap->lock */ | 396 | /* MUST be called with holding the dmap->lock */ |
396 | void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap) | 397 | void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap) |
397 | { | 398 | { |
398 | struct audio_operations *adev = audio_devs[dev]; | 399 | struct audio_operations *adev = audio_devs[dev]; |
399 | 400 | ||
400 | if (!((adev->enable_bits * adev->go) & PCM_ENABLE_OUTPUT)) | 401 | if (!((adev->enable_bits * adev->go) & PCM_ENABLE_OUTPUT)) |
401 | return; /* Don't start DMA yet */ | 402 | return; /* Don't start DMA yet */ |
402 | dmap->dma_mode = DMODE_OUTPUT; | 403 | dmap->dma_mode = DMODE_OUTPUT; |
403 | 404 | ||
404 | if (!(dmap->flags & DMA_ACTIVE) || !(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) { | 405 | if (!(dmap->flags & DMA_ACTIVE) || !(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) { |
405 | if (!(dmap->flags & DMA_STARTED)) { | 406 | if (!(dmap->flags & DMA_STARTED)) { |
406 | reorganize_buffers(dev, dmap, 0); | 407 | reorganize_buffers(dev, dmap, 0); |
407 | if (adev->d->prepare_for_output(dev, dmap->fragment_size, dmap->nbufs)) | 408 | if (adev->d->prepare_for_output(dev, dmap->fragment_size, dmap->nbufs)) |
408 | return; | 409 | return; |
409 | if (!(dmap->flags & DMA_NODMA)) | 410 | if (!(dmap->flags & DMA_NODMA)) |
410 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_WRITE); | 411 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_WRITE); |
411 | dmap->flags |= DMA_STARTED; | 412 | dmap->flags |= DMA_STARTED; |
412 | } | 413 | } |
413 | if (dmap->counts[dmap->qhead] == 0) | 414 | if (dmap->counts[dmap->qhead] == 0) |
414 | dmap->counts[dmap->qhead] = dmap->fragment_size; | 415 | dmap->counts[dmap->qhead] = dmap->fragment_size; |
415 | dmap->dma_mode = DMODE_OUTPUT; | 416 | dmap->dma_mode = DMODE_OUTPUT; |
416 | adev->d->output_block(dev, dmap->raw_buf_phys + dmap->qhead * dmap->fragment_size, | 417 | adev->d->output_block(dev, dmap->raw_buf_phys + dmap->qhead * dmap->fragment_size, |
417 | dmap->counts[dmap->qhead], 1); | 418 | dmap->counts[dmap->qhead], 1); |
418 | if (adev->d->trigger) | 419 | if (adev->d->trigger) |
419 | adev->d->trigger(dev,adev->enable_bits * adev->go); | 420 | adev->d->trigger(dev,adev->enable_bits * adev->go); |
420 | } | 421 | } |
421 | dmap->flags |= DMA_ACTIVE; | 422 | dmap->flags |= DMA_ACTIVE; |
422 | } | 423 | } |
423 | 424 | ||
424 | int DMAbuf_sync(int dev) | 425 | int DMAbuf_sync(int dev) |
425 | { | 426 | { |
426 | struct audio_operations *adev = audio_devs[dev]; | 427 | struct audio_operations *adev = audio_devs[dev]; |
427 | unsigned long flags; | 428 | unsigned long flags; |
428 | int n = 0; | 429 | int n = 0; |
429 | struct dma_buffparms *dmap; | 430 | struct dma_buffparms *dmap; |
430 | 431 | ||
431 | if (!adev->go && !(adev->enable_bits & PCM_ENABLE_OUTPUT)) | 432 | if (!adev->go && !(adev->enable_bits & PCM_ENABLE_OUTPUT)) |
432 | return 0; | 433 | return 0; |
433 | 434 | ||
434 | if (adev->dmap_out->dma_mode == DMODE_OUTPUT) { | 435 | if (adev->dmap_out->dma_mode == DMODE_OUTPUT) { |
435 | dmap = adev->dmap_out; | 436 | dmap = adev->dmap_out; |
436 | spin_lock_irqsave(&dmap->lock,flags); | 437 | spin_lock_irqsave(&dmap->lock,flags); |
437 | if (dmap->qlen > 0 && !(dmap->flags & DMA_ACTIVE)) | 438 | if (dmap->qlen > 0 && !(dmap->flags & DMA_ACTIVE)) |
438 | DMAbuf_launch_output(dev, dmap); | 439 | DMAbuf_launch_output(dev, dmap); |
439 | adev->dmap_out->flags |= DMA_SYNCING; | 440 | adev->dmap_out->flags |= DMA_SYNCING; |
440 | adev->dmap_out->underrun_count = 0; | 441 | adev->dmap_out->underrun_count = 0; |
441 | while (!signal_pending(current) && n++ <= adev->dmap_out->nbufs && | 442 | while (!signal_pending(current) && n++ <= adev->dmap_out->nbufs && |
442 | adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) { | 443 | adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) { |
443 | long t = dmabuf_timeout(dmap); | 444 | long t = dmabuf_timeout(dmap); |
444 | spin_unlock_irqrestore(&dmap->lock,flags); | 445 | spin_unlock_irqrestore(&dmap->lock,flags); |
445 | /* FIXME: not safe may miss events */ | 446 | /* FIXME: not safe may miss events */ |
446 | t = interruptible_sleep_on_timeout(&adev->out_sleeper, t); | 447 | t = interruptible_sleep_on_timeout(&adev->out_sleeper, t); |
447 | spin_lock_irqsave(&dmap->lock,flags); | 448 | spin_lock_irqsave(&dmap->lock,flags); |
448 | if (!t) { | 449 | if (!t) { |
449 | adev->dmap_out->flags &= ~DMA_SYNCING; | 450 | adev->dmap_out->flags &= ~DMA_SYNCING; |
450 | spin_unlock_irqrestore(&dmap->lock,flags); | 451 | spin_unlock_irqrestore(&dmap->lock,flags); |
451 | return adev->dmap_out->qlen; | 452 | return adev->dmap_out->qlen; |
452 | } | 453 | } |
453 | } | 454 | } |
454 | adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); | 455 | adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); |
455 | 456 | ||
456 | /* | 457 | /* |
457 | * Some devices such as GUS have huge amount of on board RAM for the | 458 | * Some devices such as GUS have huge amount of on board RAM for the |
458 | * audio data. We have to wait until the device has finished playing. | 459 | * audio data. We have to wait until the device has finished playing. |
459 | */ | 460 | */ |
460 | 461 | ||
461 | /* still holding the lock */ | 462 | /* still holding the lock */ |
462 | if (adev->d->local_qlen) { /* Device has hidden buffers */ | 463 | if (adev->d->local_qlen) { /* Device has hidden buffers */ |
463 | while (!signal_pending(current) && | 464 | while (!signal_pending(current) && |
464 | adev->d->local_qlen(dev)){ | 465 | adev->d->local_qlen(dev)){ |
465 | spin_unlock_irqrestore(&dmap->lock,flags); | 466 | spin_unlock_irqrestore(&dmap->lock,flags); |
466 | interruptible_sleep_on_timeout(&adev->out_sleeper, | 467 | interruptible_sleep_on_timeout(&adev->out_sleeper, |
467 | dmabuf_timeout(dmap)); | 468 | dmabuf_timeout(dmap)); |
468 | spin_lock_irqsave(&dmap->lock,flags); | 469 | spin_lock_irqsave(&dmap->lock,flags); |
469 | } | 470 | } |
470 | } | 471 | } |
471 | spin_unlock_irqrestore(&dmap->lock,flags); | 472 | spin_unlock_irqrestore(&dmap->lock,flags); |
472 | } | 473 | } |
473 | adev->dmap_out->dma_mode = DMODE_NONE; | 474 | adev->dmap_out->dma_mode = DMODE_NONE; |
474 | return adev->dmap_out->qlen; | 475 | return adev->dmap_out->qlen; |
475 | } | 476 | } |
476 | 477 | ||
477 | int DMAbuf_release(int dev, int mode) | 478 | int DMAbuf_release(int dev, int mode) |
478 | { | 479 | { |
479 | struct audio_operations *adev = audio_devs[dev]; | 480 | struct audio_operations *adev = audio_devs[dev]; |
480 | struct dma_buffparms *dmap; | 481 | struct dma_buffparms *dmap; |
481 | unsigned long flags; | 482 | unsigned long flags; |
482 | 483 | ||
483 | dmap = adev->dmap_out; | 484 | dmap = adev->dmap_out; |
484 | if (adev->open_mode & OPEN_WRITE) | 485 | if (adev->open_mode & OPEN_WRITE) |
485 | adev->dmap_out->closing = 1; | 486 | adev->dmap_out->closing = 1; |
486 | 487 | ||
487 | if (adev->open_mode & OPEN_READ){ | 488 | if (adev->open_mode & OPEN_READ){ |
488 | adev->dmap_in->closing = 1; | 489 | adev->dmap_in->closing = 1; |
489 | dmap = adev->dmap_in; | 490 | dmap = adev->dmap_in; |
490 | } | 491 | } |
491 | if (adev->open_mode & OPEN_WRITE) | 492 | if (adev->open_mode & OPEN_WRITE) |
492 | if (!(adev->dmap_out->mapping_flags & DMA_MAP_MAPPED)) | 493 | if (!(adev->dmap_out->mapping_flags & DMA_MAP_MAPPED)) |
493 | if (!signal_pending(current) && (adev->dmap_out->dma_mode == DMODE_OUTPUT)) | 494 | if (!signal_pending(current) && (adev->dmap_out->dma_mode == DMODE_OUTPUT)) |
494 | DMAbuf_sync(dev); | 495 | DMAbuf_sync(dev); |
495 | if (adev->dmap_out->dma_mode == DMODE_OUTPUT) | 496 | if (adev->dmap_out->dma_mode == DMODE_OUTPUT) |
496 | memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, adev->dmap_out->bytes_in_use); | 497 | memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, adev->dmap_out->bytes_in_use); |
497 | 498 | ||
498 | DMAbuf_reset(dev); | 499 | DMAbuf_reset(dev); |
499 | spin_lock_irqsave(&dmap->lock,flags); | 500 | spin_lock_irqsave(&dmap->lock,flags); |
500 | adev->d->close(dev); | 501 | adev->d->close(dev); |
501 | 502 | ||
502 | if (adev->open_mode & OPEN_WRITE) | 503 | if (adev->open_mode & OPEN_WRITE) |
503 | close_dmap(adev, adev->dmap_out); | 504 | close_dmap(adev, adev->dmap_out); |
504 | 505 | ||
505 | if (adev->open_mode == OPEN_READ || | 506 | if (adev->open_mode == OPEN_READ || |
506 | (adev->open_mode != OPEN_WRITE && | 507 | (adev->open_mode != OPEN_WRITE && |
507 | (adev->flags & DMA_DUPLEX))) | 508 | (adev->flags & DMA_DUPLEX))) |
508 | close_dmap(adev, adev->dmap_in); | 509 | close_dmap(adev, adev->dmap_in); |
509 | adev->open_mode = 0; | 510 | adev->open_mode = 0; |
510 | spin_unlock_irqrestore(&dmap->lock,flags); | 511 | spin_unlock_irqrestore(&dmap->lock,flags); |
511 | return 0; | 512 | return 0; |
512 | } | 513 | } |
513 | /* called with dmap->lock dold */ | 514 | /* called with dmap->lock dold */ |
514 | int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap) | 515 | int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap) |
515 | { | 516 | { |
516 | struct audio_operations *adev = audio_devs[dev]; | 517 | struct audio_operations *adev = audio_devs[dev]; |
517 | int err; | 518 | int err; |
518 | 519 | ||
519 | if (!(adev->open_mode & OPEN_READ)) | 520 | if (!(adev->open_mode & OPEN_READ)) |
520 | return 0; | 521 | return 0; |
521 | if (!(adev->enable_bits & PCM_ENABLE_INPUT)) | 522 | if (!(adev->enable_bits & PCM_ENABLE_INPUT)) |
522 | return 0; | 523 | return 0; |
523 | if (dmap->dma_mode == DMODE_OUTPUT) { /* Direction change */ | 524 | if (dmap->dma_mode == DMODE_OUTPUT) { /* Direction change */ |
524 | /* release lock - it's not recursive */ | 525 | /* release lock - it's not recursive */ |
525 | spin_unlock_irq(&dmap->lock); | 526 | spin_unlock_irq(&dmap->lock); |
526 | DMAbuf_sync(dev); | 527 | DMAbuf_sync(dev); |
527 | DMAbuf_reset(dev); | 528 | DMAbuf_reset(dev); |
528 | spin_lock_irq(&dmap->lock); | 529 | spin_lock_irq(&dmap->lock); |
529 | dmap->dma_mode = DMODE_NONE; | 530 | dmap->dma_mode = DMODE_NONE; |
530 | } | 531 | } |
531 | if (!dmap->dma_mode) { | 532 | if (!dmap->dma_mode) { |
532 | reorganize_buffers(dev, dmap, 1); | 533 | reorganize_buffers(dev, dmap, 1); |
533 | if ((err = adev->d->prepare_for_input(dev, | 534 | if ((err = adev->d->prepare_for_input(dev, |
534 | dmap->fragment_size, dmap->nbufs)) < 0) | 535 | dmap->fragment_size, dmap->nbufs)) < 0) |
535 | return err; | 536 | return err; |
536 | dmap->dma_mode = DMODE_INPUT; | 537 | dmap->dma_mode = DMODE_INPUT; |
537 | } | 538 | } |
538 | if (!(dmap->flags & DMA_ACTIVE)) { | 539 | if (!(dmap->flags & DMA_ACTIVE)) { |
539 | if (dmap->needs_reorg) | 540 | if (dmap->needs_reorg) |
540 | reorganize_buffers(dev, dmap, 0); | 541 | reorganize_buffers(dev, dmap, 0); |
541 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); | 542 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); |
542 | adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, | 543 | adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, |
543 | dmap->fragment_size, 0); | 544 | dmap->fragment_size, 0); |
544 | dmap->flags |= DMA_ACTIVE; | 545 | dmap->flags |= DMA_ACTIVE; |
545 | if (adev->d->trigger) | 546 | if (adev->d->trigger) |
546 | adev->d->trigger(dev, adev->enable_bits * adev->go); | 547 | adev->d->trigger(dev, adev->enable_bits * adev->go); |
547 | } | 548 | } |
548 | return 0; | 549 | return 0; |
549 | } | 550 | } |
550 | /* acquires lock */ | 551 | /* acquires lock */ |
551 | int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock) | 552 | int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock) |
552 | { | 553 | { |
553 | struct audio_operations *adev = audio_devs[dev]; | 554 | struct audio_operations *adev = audio_devs[dev]; |
554 | unsigned long flags; | 555 | unsigned long flags; |
555 | int err = 0, n = 0; | 556 | int err = 0, n = 0; |
556 | struct dma_buffparms *dmap = adev->dmap_in; | 557 | struct dma_buffparms *dmap = adev->dmap_in; |
557 | int go; | 558 | int go; |
558 | 559 | ||
559 | if (!(adev->open_mode & OPEN_READ)) | 560 | if (!(adev->open_mode & OPEN_READ)) |
560 | return -EIO; | 561 | return -EIO; |
561 | spin_lock_irqsave(&dmap->lock,flags); | 562 | spin_lock_irqsave(&dmap->lock,flags); |
562 | if (dmap->needs_reorg) | 563 | if (dmap->needs_reorg) |
563 | reorganize_buffers(dev, dmap, 0); | 564 | reorganize_buffers(dev, dmap, 0); |
564 | if (adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) { | 565 | if (adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) { |
565 | /* printk(KERN_WARNING "Sound: Can't read from mmapped device (1)\n");*/ | 566 | /* printk(KERN_WARNING "Sound: Can't read from mmapped device (1)\n");*/ |
566 | spin_unlock_irqrestore(&dmap->lock,flags); | 567 | spin_unlock_irqrestore(&dmap->lock,flags); |
567 | return -EINVAL; | 568 | return -EINVAL; |
568 | } else while (dmap->qlen <= 0 && n++ < 10) { | 569 | } else while (dmap->qlen <= 0 && n++ < 10) { |
569 | long timeout = MAX_SCHEDULE_TIMEOUT; | 570 | long timeout = MAX_SCHEDULE_TIMEOUT; |
570 | if (!(adev->enable_bits & PCM_ENABLE_INPUT) || !adev->go) { | 571 | if (!(adev->enable_bits & PCM_ENABLE_INPUT) || !adev->go) { |
571 | spin_unlock_irqrestore(&dmap->lock,flags); | 572 | spin_unlock_irqrestore(&dmap->lock,flags); |
572 | return -EAGAIN; | 573 | return -EAGAIN; |
573 | } | 574 | } |
574 | if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) { | 575 | if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) { |
575 | spin_unlock_irqrestore(&dmap->lock,flags); | 576 | spin_unlock_irqrestore(&dmap->lock,flags); |
576 | return err; | 577 | return err; |
577 | } | 578 | } |
578 | /* Wait for the next block */ | 579 | /* Wait for the next block */ |
579 | 580 | ||
580 | if (dontblock) { | 581 | if (dontblock) { |
581 | spin_unlock_irqrestore(&dmap->lock,flags); | 582 | spin_unlock_irqrestore(&dmap->lock,flags); |
582 | return -EAGAIN; | 583 | return -EAGAIN; |
583 | } | 584 | } |
584 | if ((go = adev->go)) | 585 | if ((go = adev->go)) |
585 | timeout = dmabuf_timeout(dmap); | 586 | timeout = dmabuf_timeout(dmap); |
586 | 587 | ||
587 | spin_unlock_irqrestore(&dmap->lock,flags); | 588 | spin_unlock_irqrestore(&dmap->lock,flags); |
588 | timeout = interruptible_sleep_on_timeout(&adev->in_sleeper, | 589 | timeout = interruptible_sleep_on_timeout(&adev->in_sleeper, |
589 | timeout); | 590 | timeout); |
590 | if (!timeout) { | 591 | if (!timeout) { |
591 | /* FIXME: include device name */ | 592 | /* FIXME: include device name */ |
592 | err = -EIO; | 593 | err = -EIO; |
593 | printk(KERN_WARNING "Sound: DMA (input) timed out - IRQ/DRQ config error?\n"); | 594 | printk(KERN_WARNING "Sound: DMA (input) timed out - IRQ/DRQ config error?\n"); |
594 | dma_reset_input(dev); | 595 | dma_reset_input(dev); |
595 | } else | 596 | } else |
596 | err = -EINTR; | 597 | err = -EINTR; |
597 | spin_lock_irqsave(&dmap->lock,flags); | 598 | spin_lock_irqsave(&dmap->lock,flags); |
598 | } | 599 | } |
599 | spin_unlock_irqrestore(&dmap->lock,flags); | 600 | spin_unlock_irqrestore(&dmap->lock,flags); |
600 | 601 | ||
601 | if (dmap->qlen <= 0) | 602 | if (dmap->qlen <= 0) |
602 | return err ? err : -EINTR; | 603 | return err ? err : -EINTR; |
603 | *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]]; | 604 | *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]]; |
604 | *len = dmap->fragment_size - dmap->counts[dmap->qhead]; | 605 | *len = dmap->fragment_size - dmap->counts[dmap->qhead]; |
605 | 606 | ||
606 | return dmap->qhead; | 607 | return dmap->qhead; |
607 | } | 608 | } |
608 | 609 | ||
609 | int DMAbuf_rmchars(int dev, int buff_no, int c) | 610 | int DMAbuf_rmchars(int dev, int buff_no, int c) |
610 | { | 611 | { |
611 | struct audio_operations *adev = audio_devs[dev]; | 612 | struct audio_operations *adev = audio_devs[dev]; |
612 | struct dma_buffparms *dmap = adev->dmap_in; | 613 | struct dma_buffparms *dmap = adev->dmap_in; |
613 | int p = dmap->counts[dmap->qhead] + c; | 614 | int p = dmap->counts[dmap->qhead] + c; |
614 | 615 | ||
615 | if (dmap->mapping_flags & DMA_MAP_MAPPED) | 616 | if (dmap->mapping_flags & DMA_MAP_MAPPED) |
616 | { | 617 | { |
617 | /* printk("Sound: Can't read from mmapped device (2)\n");*/ | 618 | /* printk("Sound: Can't read from mmapped device (2)\n");*/ |
618 | return -EINVAL; | 619 | return -EINVAL; |
619 | } | 620 | } |
620 | else if (dmap->qlen <= 0) | 621 | else if (dmap->qlen <= 0) |
621 | return -EIO; | 622 | return -EIO; |
622 | else if (p >= dmap->fragment_size) { /* This buffer is completely empty */ | 623 | else if (p >= dmap->fragment_size) { /* This buffer is completely empty */ |
623 | dmap->counts[dmap->qhead] = 0; | 624 | dmap->counts[dmap->qhead] = 0; |
624 | dmap->qlen--; | 625 | dmap->qlen--; |
625 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; | 626 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; |
626 | } | 627 | } |
627 | else dmap->counts[dmap->qhead] = p; | 628 | else dmap->counts[dmap->qhead] = p; |
628 | 629 | ||
629 | return 0; | 630 | return 0; |
630 | } | 631 | } |
631 | /* MUST be called with dmap->lock hold */ | 632 | /* MUST be called with dmap->lock hold */ |
632 | int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction) | 633 | int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction) |
633 | { | 634 | { |
634 | /* | 635 | /* |
635 | * Try to approximate the active byte position of the DMA pointer within the | 636 | * Try to approximate the active byte position of the DMA pointer within the |
636 | * buffer area as well as possible. | 637 | * buffer area as well as possible. |
637 | */ | 638 | */ |
638 | 639 | ||
639 | int pos; | 640 | int pos; |
640 | unsigned long f; | 641 | unsigned long f; |
641 | 642 | ||
642 | if (!(dmap->flags & DMA_ACTIVE)) | 643 | if (!(dmap->flags & DMA_ACTIVE)) |
643 | pos = 0; | 644 | pos = 0; |
644 | else { | 645 | else { |
645 | int chan = dmap->dma; | 646 | int chan = dmap->dma; |
646 | 647 | ||
647 | f=claim_dma_lock(); | 648 | f=claim_dma_lock(); |
648 | clear_dma_ff(chan); | 649 | clear_dma_ff(chan); |
649 | 650 | ||
650 | if(!isa_dma_bridge_buggy) | 651 | if(!isa_dma_bridge_buggy) |
651 | disable_dma(dmap->dma); | 652 | disable_dma(dmap->dma); |
652 | 653 | ||
653 | pos = get_dma_residue(chan); | 654 | pos = get_dma_residue(chan); |
654 | 655 | ||
655 | pos = dmap->bytes_in_use - pos; | 656 | pos = dmap->bytes_in_use - pos; |
656 | 657 | ||
657 | if (!(dmap->mapping_flags & DMA_MAP_MAPPED)) { | 658 | if (!(dmap->mapping_flags & DMA_MAP_MAPPED)) { |
658 | if (direction == DMODE_OUTPUT) { | 659 | if (direction == DMODE_OUTPUT) { |
659 | if (dmap->qhead == 0) | 660 | if (dmap->qhead == 0) |
660 | if (pos > dmap->fragment_size) | 661 | if (pos > dmap->fragment_size) |
661 | pos = 0; | 662 | pos = 0; |
662 | } else { | 663 | } else { |
663 | if (dmap->qtail == 0) | 664 | if (dmap->qtail == 0) |
664 | if (pos > dmap->fragment_size) | 665 | if (pos > dmap->fragment_size) |
665 | pos = 0; | 666 | pos = 0; |
666 | } | 667 | } |
667 | } | 668 | } |
668 | if (pos < 0) | 669 | if (pos < 0) |
669 | pos = 0; | 670 | pos = 0; |
670 | if (pos >= dmap->bytes_in_use) | 671 | if (pos >= dmap->bytes_in_use) |
671 | pos = 0; | 672 | pos = 0; |
672 | 673 | ||
673 | if(!isa_dma_bridge_buggy) | 674 | if(!isa_dma_bridge_buggy) |
674 | enable_dma(dmap->dma); | 675 | enable_dma(dmap->dma); |
675 | 676 | ||
676 | release_dma_lock(f); | 677 | release_dma_lock(f); |
677 | } | 678 | } |
678 | /* printk( "%04x ", pos); */ | 679 | /* printk( "%04x ", pos); */ |
679 | 680 | ||
680 | return pos; | 681 | return pos; |
681 | } | 682 | } |
682 | 683 | ||
683 | /* | 684 | /* |
684 | * DMAbuf_start_devices() is called by the /dev/music driver to start | 685 | * DMAbuf_start_devices() is called by the /dev/music driver to start |
685 | * one or more audio devices at desired moment. | 686 | * one or more audio devices at desired moment. |
686 | */ | 687 | */ |
687 | 688 | ||
688 | void DMAbuf_start_devices(unsigned int devmask) | 689 | void DMAbuf_start_devices(unsigned int devmask) |
689 | { | 690 | { |
690 | struct audio_operations *adev; | 691 | struct audio_operations *adev; |
691 | int dev; | 692 | int dev; |
692 | 693 | ||
693 | for (dev = 0; dev < num_audiodevs; dev++) { | 694 | for (dev = 0; dev < num_audiodevs; dev++) { |
694 | if (!(devmask & (1 << dev))) | 695 | if (!(devmask & (1 << dev))) |
695 | continue; | 696 | continue; |
696 | if (!(adev = audio_devs[dev])) | 697 | if (!(adev = audio_devs[dev])) |
697 | continue; | 698 | continue; |
698 | if (adev->open_mode == 0) | 699 | if (adev->open_mode == 0) |
699 | continue; | 700 | continue; |
700 | if (adev->go) | 701 | if (adev->go) |
701 | continue; | 702 | continue; |
702 | /* OK to start the device */ | 703 | /* OK to start the device */ |
703 | adev->go = 1; | 704 | adev->go = 1; |
704 | if (adev->d->trigger) | 705 | if (adev->d->trigger) |
705 | adev->d->trigger(dev,adev->enable_bits * adev->go); | 706 | adev->d->trigger(dev,adev->enable_bits * adev->go); |
706 | } | 707 | } |
707 | } | 708 | } |
708 | /* via poll called without a lock ?*/ | 709 | /* via poll called without a lock ?*/ |
709 | int DMAbuf_space_in_queue(int dev) | 710 | int DMAbuf_space_in_queue(int dev) |
710 | { | 711 | { |
711 | struct audio_operations *adev = audio_devs[dev]; | 712 | struct audio_operations *adev = audio_devs[dev]; |
712 | int len, max, tmp; | 713 | int len, max, tmp; |
713 | struct dma_buffparms *dmap = adev->dmap_out; | 714 | struct dma_buffparms *dmap = adev->dmap_out; |
714 | int lim = dmap->nbufs; | 715 | int lim = dmap->nbufs; |
715 | 716 | ||
716 | if (lim < 2) | 717 | if (lim < 2) |
717 | lim = 2; | 718 | lim = 2; |
718 | 719 | ||
719 | if (dmap->qlen >= lim) /* No space at all */ | 720 | if (dmap->qlen >= lim) /* No space at all */ |
720 | return 0; | 721 | return 0; |
721 | 722 | ||
722 | /* | 723 | /* |
723 | * Verify that there are no more pending buffers than the limit | 724 | * Verify that there are no more pending buffers than the limit |
724 | * defined by the process. | 725 | * defined by the process. |
725 | */ | 726 | */ |
726 | 727 | ||
727 | max = dmap->max_fragments; | 728 | max = dmap->max_fragments; |
728 | if (max > lim) | 729 | if (max > lim) |
729 | max = lim; | 730 | max = lim; |
730 | len = dmap->qlen; | 731 | len = dmap->qlen; |
731 | 732 | ||
732 | if (adev->d->local_qlen) { | 733 | if (adev->d->local_qlen) { |
733 | tmp = adev->d->local_qlen(dev); | 734 | tmp = adev->d->local_qlen(dev); |
734 | if (tmp && len) | 735 | if (tmp && len) |
735 | tmp--; /* This buffer has been counted twice */ | 736 | tmp--; /* This buffer has been counted twice */ |
736 | len += tmp; | 737 | len += tmp; |
737 | } | 738 | } |
738 | if (dmap->byte_counter % dmap->fragment_size) /* There is a partial fragment */ | 739 | if (dmap->byte_counter % dmap->fragment_size) /* There is a partial fragment */ |
739 | len = len + 1; | 740 | len = len + 1; |
740 | 741 | ||
741 | if (len >= max) | 742 | if (len >= max) |
742 | return 0; | 743 | return 0; |
743 | return max - len; | 744 | return max - len; |
744 | } | 745 | } |
745 | /* MUST not hold the spinlock - this function may sleep */ | 746 | /* MUST not hold the spinlock - this function may sleep */ |
746 | static int output_sleep(int dev, int dontblock) | 747 | static int output_sleep(int dev, int dontblock) |
747 | { | 748 | { |
748 | struct audio_operations *adev = audio_devs[dev]; | 749 | struct audio_operations *adev = audio_devs[dev]; |
749 | int err = 0; | 750 | int err = 0; |
750 | struct dma_buffparms *dmap = adev->dmap_out; | 751 | struct dma_buffparms *dmap = adev->dmap_out; |
751 | long timeout; | 752 | long timeout; |
752 | long timeout_value; | 753 | long timeout_value; |
753 | 754 | ||
754 | if (dontblock) | 755 | if (dontblock) |
755 | return -EAGAIN; | 756 | return -EAGAIN; |
756 | if (!(adev->enable_bits & PCM_ENABLE_OUTPUT)) | 757 | if (!(adev->enable_bits & PCM_ENABLE_OUTPUT)) |
757 | return -EAGAIN; | 758 | return -EAGAIN; |
758 | 759 | ||
759 | /* | 760 | /* |
760 | * Wait for free space | 761 | * Wait for free space |
761 | */ | 762 | */ |
762 | if (signal_pending(current)) | 763 | if (signal_pending(current)) |
763 | return -EINTR; | 764 | return -EINTR; |
764 | timeout = (adev->go && !(dmap->flags & DMA_NOTIMEOUT)); | 765 | timeout = (adev->go && !(dmap->flags & DMA_NOTIMEOUT)); |
765 | if (timeout) | 766 | if (timeout) |
766 | timeout_value = dmabuf_timeout(dmap); | 767 | timeout_value = dmabuf_timeout(dmap); |
767 | else | 768 | else |
768 | timeout_value = MAX_SCHEDULE_TIMEOUT; | 769 | timeout_value = MAX_SCHEDULE_TIMEOUT; |
769 | timeout_value = interruptible_sleep_on_timeout(&adev->out_sleeper, | 770 | timeout_value = interruptible_sleep_on_timeout(&adev->out_sleeper, |
770 | timeout_value); | 771 | timeout_value); |
771 | if (timeout != MAX_SCHEDULE_TIMEOUT && !timeout_value) { | 772 | if (timeout != MAX_SCHEDULE_TIMEOUT && !timeout_value) { |
772 | printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n"); | 773 | printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n"); |
773 | dma_reset_output(dev); | 774 | dma_reset_output(dev); |
774 | } else { | 775 | } else { |
775 | if (signal_pending(current)) | 776 | if (signal_pending(current)) |
776 | err = -EINTR; | 777 | err = -EINTR; |
777 | } | 778 | } |
778 | return err; | 779 | return err; |
779 | } | 780 | } |
780 | /* called with the lock held */ | 781 | /* called with the lock held */ |
781 | static int find_output_space(int dev, char **buf, int *size) | 782 | static int find_output_space(int dev, char **buf, int *size) |
782 | { | 783 | { |
783 | struct audio_operations *adev = audio_devs[dev]; | 784 | struct audio_operations *adev = audio_devs[dev]; |
784 | struct dma_buffparms *dmap = adev->dmap_out; | 785 | struct dma_buffparms *dmap = adev->dmap_out; |
785 | unsigned long active_offs; | 786 | unsigned long active_offs; |
786 | long len, offs; | 787 | long len, offs; |
787 | int maxfrags; | 788 | int maxfrags; |
788 | int occupied_bytes = (dmap->user_counter % dmap->fragment_size); | 789 | int occupied_bytes = (dmap->user_counter % dmap->fragment_size); |
789 | 790 | ||
790 | *buf = dmap->raw_buf; | 791 | *buf = dmap->raw_buf; |
791 | if (!(maxfrags = DMAbuf_space_in_queue(dev)) && !occupied_bytes) | 792 | if (!(maxfrags = DMAbuf_space_in_queue(dev)) && !occupied_bytes) |
792 | return 0; | 793 | return 0; |
793 | 794 | ||
794 | #ifdef BE_CONSERVATIVE | 795 | #ifdef BE_CONSERVATIVE |
795 | active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size; | 796 | active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size; |
796 | #else | 797 | #else |
797 | active_offs = DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT); | 798 | active_offs = DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT); |
798 | /* Check for pointer wrapping situation */ | 799 | /* Check for pointer wrapping situation */ |
799 | if (active_offs < 0 || active_offs >= dmap->bytes_in_use) | 800 | if (active_offs < 0 || active_offs >= dmap->bytes_in_use) |
800 | active_offs = 0; | 801 | active_offs = 0; |
801 | active_offs += dmap->byte_counter; | 802 | active_offs += dmap->byte_counter; |
802 | #endif | 803 | #endif |
803 | 804 | ||
804 | offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP; | 805 | offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP; |
805 | if (offs < 0 || offs >= dmap->bytes_in_use) { | 806 | if (offs < 0 || offs >= dmap->bytes_in_use) { |
806 | printk(KERN_ERR "Sound: Got unexpected offs %ld. Giving up.\n", offs); | 807 | printk(KERN_ERR "Sound: Got unexpected offs %ld. Giving up.\n", offs); |
807 | printk("Counter = %ld, bytes=%d\n", dmap->user_counter, dmap->bytes_in_use); | 808 | printk("Counter = %ld, bytes=%d\n", dmap->user_counter, dmap->bytes_in_use); |
808 | return 0; | 809 | return 0; |
809 | } | 810 | } |
810 | *buf = dmap->raw_buf + offs; | 811 | *buf = dmap->raw_buf + offs; |
811 | 812 | ||
812 | len = active_offs + dmap->bytes_in_use - dmap->user_counter; /* Number of unused bytes in buffer */ | 813 | len = active_offs + dmap->bytes_in_use - dmap->user_counter; /* Number of unused bytes in buffer */ |
813 | 814 | ||
814 | if ((offs + len) > dmap->bytes_in_use) | 815 | if ((offs + len) > dmap->bytes_in_use) |
815 | len = dmap->bytes_in_use - offs; | 816 | len = dmap->bytes_in_use - offs; |
816 | if (len < 0) { | 817 | if (len < 0) { |
817 | return 0; | 818 | return 0; |
818 | } | 819 | } |
819 | if (len > ((maxfrags * dmap->fragment_size) - occupied_bytes)) | 820 | if (len > ((maxfrags * dmap->fragment_size) - occupied_bytes)) |
820 | len = (maxfrags * dmap->fragment_size) - occupied_bytes; | 821 | len = (maxfrags * dmap->fragment_size) - occupied_bytes; |
821 | *size = len & ~SAMPLE_ROUNDUP; | 822 | *size = len & ~SAMPLE_ROUNDUP; |
822 | return (*size > 0); | 823 | return (*size > 0); |
823 | } | 824 | } |
824 | /* acquires lock */ | 825 | /* acquires lock */ |
825 | int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock) | 826 | int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock) |
826 | { | 827 | { |
827 | struct audio_operations *adev = audio_devs[dev]; | 828 | struct audio_operations *adev = audio_devs[dev]; |
828 | unsigned long flags; | 829 | unsigned long flags; |
829 | int err = -EIO; | 830 | int err = -EIO; |
830 | struct dma_buffparms *dmap = adev->dmap_out; | 831 | struct dma_buffparms *dmap = adev->dmap_out; |
831 | 832 | ||
832 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { | 833 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { |
833 | /* printk(KERN_DEBUG "Sound: Can't write to mmapped device (3)\n");*/ | 834 | /* printk(KERN_DEBUG "Sound: Can't write to mmapped device (3)\n");*/ |
834 | return -EINVAL; | 835 | return -EINVAL; |
835 | } | 836 | } |
836 | spin_lock_irqsave(&dmap->lock,flags); | 837 | spin_lock_irqsave(&dmap->lock,flags); |
837 | if (dmap->needs_reorg) | 838 | if (dmap->needs_reorg) |
838 | reorganize_buffers(dev, dmap, 0); | 839 | reorganize_buffers(dev, dmap, 0); |
839 | 840 | ||
840 | if (dmap->dma_mode == DMODE_INPUT) { /* Direction change */ | 841 | if (dmap->dma_mode == DMODE_INPUT) { /* Direction change */ |
841 | spin_unlock_irqrestore(&dmap->lock,flags); | 842 | spin_unlock_irqrestore(&dmap->lock,flags); |
842 | DMAbuf_reset(dev); | 843 | DMAbuf_reset(dev); |
843 | spin_lock_irqsave(&dmap->lock,flags); | 844 | spin_lock_irqsave(&dmap->lock,flags); |
844 | } | 845 | } |
845 | dmap->dma_mode = DMODE_OUTPUT; | 846 | dmap->dma_mode = DMODE_OUTPUT; |
846 | 847 | ||
847 | while (find_output_space(dev, buf, size) <= 0) { | 848 | while (find_output_space(dev, buf, size) <= 0) { |
848 | spin_unlock_irqrestore(&dmap->lock,flags); | 849 | spin_unlock_irqrestore(&dmap->lock,flags); |
849 | if ((err = output_sleep(dev, dontblock)) < 0) { | 850 | if ((err = output_sleep(dev, dontblock)) < 0) { |
850 | return err; | 851 | return err; |
851 | } | 852 | } |
852 | spin_lock_irqsave(&dmap->lock,flags); | 853 | spin_lock_irqsave(&dmap->lock,flags); |
853 | } | 854 | } |
854 | 855 | ||
855 | spin_unlock_irqrestore(&dmap->lock,flags); | 856 | spin_unlock_irqrestore(&dmap->lock,flags); |
856 | return 0; | 857 | return 0; |
857 | } | 858 | } |
858 | /* has to acquire dmap->lock */ | 859 | /* has to acquire dmap->lock */ |
859 | int DMAbuf_move_wrpointer(int dev, int l) | 860 | int DMAbuf_move_wrpointer(int dev, int l) |
860 | { | 861 | { |
861 | struct audio_operations *adev = audio_devs[dev]; | 862 | struct audio_operations *adev = audio_devs[dev]; |
862 | struct dma_buffparms *dmap = adev->dmap_out; | 863 | struct dma_buffparms *dmap = adev->dmap_out; |
863 | unsigned long ptr; | 864 | unsigned long ptr; |
864 | unsigned long end_ptr, p; | 865 | unsigned long end_ptr, p; |
865 | int post; | 866 | int post; |
866 | unsigned long flags; | 867 | unsigned long flags; |
867 | 868 | ||
868 | spin_lock_irqsave(&dmap->lock,flags); | 869 | spin_lock_irqsave(&dmap->lock,flags); |
869 | post= (dmap->flags & DMA_POST); | 870 | post= (dmap->flags & DMA_POST); |
870 | ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; | 871 | ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; |
871 | 872 | ||
872 | dmap->flags &= ~DMA_POST; | 873 | dmap->flags &= ~DMA_POST; |
873 | dmap->cfrag = -1; | 874 | dmap->cfrag = -1; |
874 | dmap->user_counter += l; | 875 | dmap->user_counter += l; |
875 | dmap->flags |= DMA_DIRTY; | 876 | dmap->flags |= DMA_DIRTY; |
876 | 877 | ||
877 | if (dmap->byte_counter >= dmap->max_byte_counter) { | 878 | if (dmap->byte_counter >= dmap->max_byte_counter) { |
878 | /* Wrap the byte counters */ | 879 | /* Wrap the byte counters */ |
879 | long decr = dmap->byte_counter; | 880 | long decr = dmap->byte_counter; |
880 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); | 881 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); |
881 | decr -= dmap->byte_counter; | 882 | decr -= dmap->byte_counter; |
882 | dmap->user_counter -= decr; | 883 | dmap->user_counter -= decr; |
883 | } | 884 | } |
884 | end_ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; | 885 | end_ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; |
885 | 886 | ||
886 | p = (dmap->user_counter - 1) % dmap->bytes_in_use; | 887 | p = (dmap->user_counter - 1) % dmap->bytes_in_use; |
887 | dmap->neutral_byte = dmap->raw_buf[p]; | 888 | dmap->neutral_byte = dmap->raw_buf[p]; |
888 | 889 | ||
889 | /* Update the fragment based bookkeeping too */ | 890 | /* Update the fragment based bookkeeping too */ |
890 | while (ptr < end_ptr) { | 891 | while (ptr < end_ptr) { |
891 | dmap->counts[dmap->qtail] = dmap->fragment_size; | 892 | dmap->counts[dmap->qtail] = dmap->fragment_size; |
892 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; | 893 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; |
893 | dmap->qlen++; | 894 | dmap->qlen++; |
894 | ptr += dmap->fragment_size; | 895 | ptr += dmap->fragment_size; |
895 | } | 896 | } |
896 | 897 | ||
897 | dmap->counts[dmap->qtail] = dmap->user_counter - ptr; | 898 | dmap->counts[dmap->qtail] = dmap->user_counter - ptr; |
898 | 899 | ||
899 | /* | 900 | /* |
900 | * Let the low level driver perform some postprocessing to | 901 | * Let the low level driver perform some postprocessing to |
901 | * the written data. | 902 | * the written data. |
902 | */ | 903 | */ |
903 | if (adev->d->postprocess_write) | 904 | if (adev->d->postprocess_write) |
904 | adev->d->postprocess_write(dev); | 905 | adev->d->postprocess_write(dev); |
905 | 906 | ||
906 | if (!(dmap->flags & DMA_ACTIVE)) | 907 | if (!(dmap->flags & DMA_ACTIVE)) |
907 | if (dmap->qlen > 1 || (dmap->qlen > 0 && (post || dmap->qlen >= dmap->nbufs - 1))) | 908 | if (dmap->qlen > 1 || (dmap->qlen > 0 && (post || dmap->qlen >= dmap->nbufs - 1))) |
908 | DMAbuf_launch_output(dev, dmap); | 909 | DMAbuf_launch_output(dev, dmap); |
909 | 910 | ||
910 | spin_unlock_irqrestore(&dmap->lock,flags); | 911 | spin_unlock_irqrestore(&dmap->lock,flags); |
911 | return 0; | 912 | return 0; |
912 | } | 913 | } |
913 | 914 | ||
914 | int DMAbuf_start_dma(int dev, unsigned long physaddr, int count, int dma_mode) | 915 | int DMAbuf_start_dma(int dev, unsigned long physaddr, int count, int dma_mode) |
915 | { | 916 | { |
916 | struct audio_operations *adev = audio_devs[dev]; | 917 | struct audio_operations *adev = audio_devs[dev]; |
917 | struct dma_buffparms *dmap = (dma_mode == DMA_MODE_WRITE) ? adev->dmap_out : adev->dmap_in; | 918 | struct dma_buffparms *dmap = (dma_mode == DMA_MODE_WRITE) ? adev->dmap_out : adev->dmap_in; |
918 | 919 | ||
919 | if (dmap->raw_buf == NULL) { | 920 | if (dmap->raw_buf == NULL) { |
920 | printk(KERN_ERR "sound: DMA buffer(1) == NULL\n"); | 921 | printk(KERN_ERR "sound: DMA buffer(1) == NULL\n"); |
921 | printk("Device %d, chn=%s\n", dev, (dmap == adev->dmap_out) ? "out" : "in"); | 922 | printk("Device %d, chn=%s\n", dev, (dmap == adev->dmap_out) ? "out" : "in"); |
922 | return 0; | 923 | return 0; |
923 | } | 924 | } |
924 | if (dmap->dma < 0) | 925 | if (dmap->dma < 0) |
925 | return 0; | 926 | return 0; |
926 | sound_start_dma(dmap, physaddr, count, dma_mode); | 927 | sound_start_dma(dmap, physaddr, count, dma_mode); |
927 | return count; | 928 | return count; |
928 | } | 929 | } |
929 | EXPORT_SYMBOL(DMAbuf_start_dma); | 930 | EXPORT_SYMBOL(DMAbuf_start_dma); |
930 | 931 | ||
931 | static int local_start_dma(struct audio_operations *adev, unsigned long physaddr, int count, int dma_mode) | 932 | static int local_start_dma(struct audio_operations *adev, unsigned long physaddr, int count, int dma_mode) |
932 | { | 933 | { |
933 | struct dma_buffparms *dmap = (dma_mode == DMA_MODE_WRITE) ? adev->dmap_out : adev->dmap_in; | 934 | struct dma_buffparms *dmap = (dma_mode == DMA_MODE_WRITE) ? adev->dmap_out : adev->dmap_in; |
934 | 935 | ||
935 | if (dmap->raw_buf == NULL) { | 936 | if (dmap->raw_buf == NULL) { |
936 | printk(KERN_ERR "sound: DMA buffer(2) == NULL\n"); | 937 | printk(KERN_ERR "sound: DMA buffer(2) == NULL\n"); |
937 | printk(KERN_ERR "Device %s, chn=%s\n", adev->name, (dmap == adev->dmap_out) ? "out" : "in"); | 938 | printk(KERN_ERR "Device %s, chn=%s\n", adev->name, (dmap == adev->dmap_out) ? "out" : "in"); |
938 | return 0; | 939 | return 0; |
939 | } | 940 | } |
940 | if (dmap->flags & DMA_NODMA) | 941 | if (dmap->flags & DMA_NODMA) |
941 | return 1; | 942 | return 1; |
942 | if (dmap->dma < 0) | 943 | if (dmap->dma < 0) |
943 | return 0; | 944 | return 0; |
944 | sound_start_dma(dmap, dmap->raw_buf_phys, dmap->bytes_in_use, dma_mode | DMA_AUTOINIT); | 945 | sound_start_dma(dmap, dmap->raw_buf_phys, dmap->bytes_in_use, dma_mode | DMA_AUTOINIT); |
945 | dmap->flags |= DMA_STARTED; | 946 | dmap->flags |= DMA_STARTED; |
946 | return count; | 947 | return count; |
947 | } | 948 | } |
948 | 949 | ||
949 | static void finish_output_interrupt(int dev, struct dma_buffparms *dmap) | 950 | static void finish_output_interrupt(int dev, struct dma_buffparms *dmap) |
950 | { | 951 | { |
951 | struct audio_operations *adev = audio_devs[dev]; | 952 | struct audio_operations *adev = audio_devs[dev]; |
952 | 953 | ||
953 | if (dmap->audio_callback != NULL) | 954 | if (dmap->audio_callback != NULL) |
954 | dmap->audio_callback(dev, dmap->callback_parm); | 955 | dmap->audio_callback(dev, dmap->callback_parm); |
955 | wake_up(&adev->out_sleeper); | 956 | wake_up(&adev->out_sleeper); |
956 | wake_up(&adev->poll_sleeper); | 957 | wake_up(&adev->poll_sleeper); |
957 | } | 958 | } |
958 | /* called with dmap->lock held in irq context*/ | 959 | /* called with dmap->lock held in irq context*/ |
959 | static void do_outputintr(int dev, int dummy) | 960 | static void do_outputintr(int dev, int dummy) |
960 | { | 961 | { |
961 | struct audio_operations *adev = audio_devs[dev]; | 962 | struct audio_operations *adev = audio_devs[dev]; |
962 | struct dma_buffparms *dmap = adev->dmap_out; | 963 | struct dma_buffparms *dmap = adev->dmap_out; |
963 | int this_fragment; | 964 | int this_fragment; |
964 | 965 | ||
965 | if (dmap->raw_buf == NULL) { | 966 | if (dmap->raw_buf == NULL) { |
966 | printk(KERN_ERR "Sound: Error. Audio interrupt (%d) after freeing buffers.\n", dev); | 967 | printk(KERN_ERR "Sound: Error. Audio interrupt (%d) after freeing buffers.\n", dev); |
967 | return; | 968 | return; |
968 | } | 969 | } |
969 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { /* Virtual memory mapped access */ | 970 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { /* Virtual memory mapped access */ |
970 | /* mmapped access */ | 971 | /* mmapped access */ |
971 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; | 972 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; |
972 | if (dmap->qhead == 0) { /* Wrapped */ | 973 | if (dmap->qhead == 0) { /* Wrapped */ |
973 | dmap->byte_counter += dmap->bytes_in_use; | 974 | dmap->byte_counter += dmap->bytes_in_use; |
974 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ | 975 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ |
975 | long decr = dmap->byte_counter; | 976 | long decr = dmap->byte_counter; |
976 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); | 977 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); |
977 | decr -= dmap->byte_counter; | 978 | decr -= dmap->byte_counter; |
978 | dmap->user_counter -= decr; | 979 | dmap->user_counter -= decr; |
979 | } | 980 | } |
980 | } | 981 | } |
981 | dmap->qlen++; /* Yes increment it (don't decrement) */ | 982 | dmap->qlen++; /* Yes increment it (don't decrement) */ |
982 | if (!(adev->flags & DMA_AUTOMODE)) | 983 | if (!(adev->flags & DMA_AUTOMODE)) |
983 | dmap->flags &= ~DMA_ACTIVE; | 984 | dmap->flags &= ~DMA_ACTIVE; |
984 | dmap->counts[dmap->qhead] = dmap->fragment_size; | 985 | dmap->counts[dmap->qhead] = dmap->fragment_size; |
985 | DMAbuf_launch_output(dev, dmap); | 986 | DMAbuf_launch_output(dev, dmap); |
986 | finish_output_interrupt(dev, dmap); | 987 | finish_output_interrupt(dev, dmap); |
987 | return; | 988 | return; |
988 | } | 989 | } |
989 | 990 | ||
990 | dmap->qlen--; | 991 | dmap->qlen--; |
991 | this_fragment = dmap->qhead; | 992 | this_fragment = dmap->qhead; |
992 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; | 993 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; |
993 | 994 | ||
994 | if (dmap->qhead == 0) { /* Wrapped */ | 995 | if (dmap->qhead == 0) { /* Wrapped */ |
995 | dmap->byte_counter += dmap->bytes_in_use; | 996 | dmap->byte_counter += dmap->bytes_in_use; |
996 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ | 997 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ |
997 | long decr = dmap->byte_counter; | 998 | long decr = dmap->byte_counter; |
998 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); | 999 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); |
999 | decr -= dmap->byte_counter; | 1000 | decr -= dmap->byte_counter; |
1000 | dmap->user_counter -= decr; | 1001 | dmap->user_counter -= decr; |
1001 | } | 1002 | } |
1002 | } | 1003 | } |
1003 | if (!(adev->flags & DMA_AUTOMODE)) | 1004 | if (!(adev->flags & DMA_AUTOMODE)) |
1004 | dmap->flags &= ~DMA_ACTIVE; | 1005 | dmap->flags &= ~DMA_ACTIVE; |
1005 | 1006 | ||
1006 | /* | 1007 | /* |
1007 | * This is dmap->qlen <= 0 except when closing when | 1008 | * This is dmap->qlen <= 0 except when closing when |
1008 | * dmap->qlen < 0 | 1009 | * dmap->qlen < 0 |
1009 | */ | 1010 | */ |
1010 | 1011 | ||
1011 | while (dmap->qlen <= -dmap->closing) { | 1012 | while (dmap->qlen <= -dmap->closing) { |
1012 | dmap->underrun_count++; | 1013 | dmap->underrun_count++; |
1013 | dmap->qlen++; | 1014 | dmap->qlen++; |
1014 | if ((dmap->flags & DMA_DIRTY) && dmap->applic_profile != APF_CPUINTENS) { | 1015 | if ((dmap->flags & DMA_DIRTY) && dmap->applic_profile != APF_CPUINTENS) { |
1015 | dmap->flags &= ~DMA_DIRTY; | 1016 | dmap->flags &= ~DMA_DIRTY; |
1016 | memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, | 1017 | memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, |
1017 | adev->dmap_out->buffsize); | 1018 | adev->dmap_out->buffsize); |
1018 | } | 1019 | } |
1019 | dmap->user_counter += dmap->fragment_size; | 1020 | dmap->user_counter += dmap->fragment_size; |
1020 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; | 1021 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; |
1021 | } | 1022 | } |
1022 | if (dmap->qlen > 0) | 1023 | if (dmap->qlen > 0) |
1023 | DMAbuf_launch_output(dev, dmap); | 1024 | DMAbuf_launch_output(dev, dmap); |
1024 | finish_output_interrupt(dev, dmap); | 1025 | finish_output_interrupt(dev, dmap); |
1025 | } | 1026 | } |
1026 | /* called in irq context */ | 1027 | /* called in irq context */ |
1027 | void DMAbuf_outputintr(int dev, int notify_only) | 1028 | void DMAbuf_outputintr(int dev, int notify_only) |
1028 | { | 1029 | { |
1029 | struct audio_operations *adev = audio_devs[dev]; | 1030 | struct audio_operations *adev = audio_devs[dev]; |
1030 | unsigned long flags; | 1031 | unsigned long flags; |
1031 | struct dma_buffparms *dmap = adev->dmap_out; | 1032 | struct dma_buffparms *dmap = adev->dmap_out; |
1032 | 1033 | ||
1033 | spin_lock_irqsave(&dmap->lock,flags); | 1034 | spin_lock_irqsave(&dmap->lock,flags); |
1034 | if (!(dmap->flags & DMA_NODMA)) { | 1035 | if (!(dmap->flags & DMA_NODMA)) { |
1035 | int chan = dmap->dma, pos, n; | 1036 | int chan = dmap->dma, pos, n; |
1036 | unsigned long f; | 1037 | unsigned long f; |
1037 | 1038 | ||
1038 | f=claim_dma_lock(); | 1039 | f=claim_dma_lock(); |
1039 | 1040 | ||
1040 | if(!isa_dma_bridge_buggy) | 1041 | if(!isa_dma_bridge_buggy) |
1041 | disable_dma(dmap->dma); | 1042 | disable_dma(dmap->dma); |
1042 | clear_dma_ff(chan); | 1043 | clear_dma_ff(chan); |
1043 | pos = dmap->bytes_in_use - get_dma_residue(chan); | 1044 | pos = dmap->bytes_in_use - get_dma_residue(chan); |
1044 | if(!isa_dma_bridge_buggy) | 1045 | if(!isa_dma_bridge_buggy) |
1045 | enable_dma(dmap->dma); | 1046 | enable_dma(dmap->dma); |
1046 | release_dma_lock(f); | 1047 | release_dma_lock(f); |
1047 | 1048 | ||
1048 | pos = pos / dmap->fragment_size; /* Actual qhead */ | 1049 | pos = pos / dmap->fragment_size; /* Actual qhead */ |
1049 | if (pos < 0 || pos >= dmap->nbufs) | 1050 | if (pos < 0 || pos >= dmap->nbufs) |
1050 | pos = 0; | 1051 | pos = 0; |
1051 | n = 0; | 1052 | n = 0; |
1052 | while (dmap->qhead != pos && n++ < dmap->nbufs) | 1053 | while (dmap->qhead != pos && n++ < dmap->nbufs) |
1053 | do_outputintr(dev, notify_only); | 1054 | do_outputintr(dev, notify_only); |
1054 | } | 1055 | } |
1055 | else | 1056 | else |
1056 | do_outputintr(dev, notify_only); | 1057 | do_outputintr(dev, notify_only); |
1057 | spin_unlock_irqrestore(&dmap->lock,flags); | 1058 | spin_unlock_irqrestore(&dmap->lock,flags); |
1058 | } | 1059 | } |
1059 | EXPORT_SYMBOL(DMAbuf_outputintr); | 1060 | EXPORT_SYMBOL(DMAbuf_outputintr); |
1060 | 1061 | ||
1061 | /* called with dmap->lock held in irq context */ | 1062 | /* called with dmap->lock held in irq context */ |
1062 | static void do_inputintr(int dev) | 1063 | static void do_inputintr(int dev) |
1063 | { | 1064 | { |
1064 | struct audio_operations *adev = audio_devs[dev]; | 1065 | struct audio_operations *adev = audio_devs[dev]; |
1065 | struct dma_buffparms *dmap = adev->dmap_in; | 1066 | struct dma_buffparms *dmap = adev->dmap_in; |
1066 | 1067 | ||
1067 | if (dmap->raw_buf == NULL) { | 1068 | if (dmap->raw_buf == NULL) { |
1068 | printk(KERN_ERR "Sound: Fatal error. Audio interrupt after freeing buffers.\n"); | 1069 | printk(KERN_ERR "Sound: Fatal error. Audio interrupt after freeing buffers.\n"); |
1069 | return; | 1070 | return; |
1070 | } | 1071 | } |
1071 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { | 1072 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { |
1072 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; | 1073 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; |
1073 | if (dmap->qtail == 0) { /* Wrapped */ | 1074 | if (dmap->qtail == 0) { /* Wrapped */ |
1074 | dmap->byte_counter += dmap->bytes_in_use; | 1075 | dmap->byte_counter += dmap->bytes_in_use; |
1075 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ | 1076 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ |
1076 | long decr = dmap->byte_counter; | 1077 | long decr = dmap->byte_counter; |
1077 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; | 1078 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; |
1078 | decr -= dmap->byte_counter; | 1079 | decr -= dmap->byte_counter; |
1079 | dmap->user_counter -= decr; | 1080 | dmap->user_counter -= decr; |
1080 | } | 1081 | } |
1081 | } | 1082 | } |
1082 | dmap->qlen++; | 1083 | dmap->qlen++; |
1083 | 1084 | ||
1084 | if (!(adev->flags & DMA_AUTOMODE)) { | 1085 | if (!(adev->flags & DMA_AUTOMODE)) { |
1085 | if (dmap->needs_reorg) | 1086 | if (dmap->needs_reorg) |
1086 | reorganize_buffers(dev, dmap, 0); | 1087 | reorganize_buffers(dev, dmap, 0); |
1087 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_READ); | 1088 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_READ); |
1088 | adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, | 1089 | adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, |
1089 | dmap->fragment_size, 1); | 1090 | dmap->fragment_size, 1); |
1090 | if (adev->d->trigger) | 1091 | if (adev->d->trigger) |
1091 | adev->d->trigger(dev, adev->enable_bits * adev->go); | 1092 | adev->d->trigger(dev, adev->enable_bits * adev->go); |
1092 | } | 1093 | } |
1093 | dmap->flags |= DMA_ACTIVE; | 1094 | dmap->flags |= DMA_ACTIVE; |
1094 | } else if (dmap->qlen >= (dmap->nbufs - 1)) { | 1095 | } else if (dmap->qlen >= (dmap->nbufs - 1)) { |
1095 | printk(KERN_WARNING "Sound: Recording overrun\n"); | 1096 | printk(KERN_WARNING "Sound: Recording overrun\n"); |
1096 | dmap->underrun_count++; | 1097 | dmap->underrun_count++; |
1097 | 1098 | ||
1098 | /* Just throw away the oldest fragment but keep the engine running */ | 1099 | /* Just throw away the oldest fragment but keep the engine running */ |
1099 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; | 1100 | dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; |
1100 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; | 1101 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; |
1101 | } else if (dmap->qlen >= 0 && dmap->qlen < dmap->nbufs) { | 1102 | } else if (dmap->qlen >= 0 && dmap->qlen < dmap->nbufs) { |
1102 | dmap->qlen++; | 1103 | dmap->qlen++; |
1103 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; | 1104 | dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; |
1104 | if (dmap->qtail == 0) { /* Wrapped */ | 1105 | if (dmap->qtail == 0) { /* Wrapped */ |
1105 | dmap->byte_counter += dmap->bytes_in_use; | 1106 | dmap->byte_counter += dmap->bytes_in_use; |
1106 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ | 1107 | if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ |
1107 | long decr = dmap->byte_counter; | 1108 | long decr = dmap->byte_counter; |
1108 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; | 1109 | dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; |
1109 | decr -= dmap->byte_counter; | 1110 | decr -= dmap->byte_counter; |
1110 | dmap->user_counter -= decr; | 1111 | dmap->user_counter -= decr; |
1111 | } | 1112 | } |
1112 | } | 1113 | } |
1113 | } | 1114 | } |
1114 | if (!(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) { | 1115 | if (!(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) { |
1115 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); | 1116 | local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); |
1116 | adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, dmap->fragment_size, 1); | 1117 | adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, dmap->fragment_size, 1); |
1117 | if (adev->d->trigger) | 1118 | if (adev->d->trigger) |
1118 | adev->d->trigger(dev,adev->enable_bits * adev->go); | 1119 | adev->d->trigger(dev,adev->enable_bits * adev->go); |
1119 | } | 1120 | } |
1120 | dmap->flags |= DMA_ACTIVE; | 1121 | dmap->flags |= DMA_ACTIVE; |
1121 | if (dmap->qlen > 0) | 1122 | if (dmap->qlen > 0) |
1122 | { | 1123 | { |
1123 | wake_up(&adev->in_sleeper); | 1124 | wake_up(&adev->in_sleeper); |
1124 | wake_up(&adev->poll_sleeper); | 1125 | wake_up(&adev->poll_sleeper); |
1125 | } | 1126 | } |
1126 | } | 1127 | } |
1127 | /* called in irq context */ | 1128 | /* called in irq context */ |
1128 | void DMAbuf_inputintr(int dev) | 1129 | void DMAbuf_inputintr(int dev) |
1129 | { | 1130 | { |
1130 | struct audio_operations *adev = audio_devs[dev]; | 1131 | struct audio_operations *adev = audio_devs[dev]; |
1131 | struct dma_buffparms *dmap = adev->dmap_in; | 1132 | struct dma_buffparms *dmap = adev->dmap_in; |
1132 | unsigned long flags; | 1133 | unsigned long flags; |
1133 | 1134 | ||
1134 | spin_lock_irqsave(&dmap->lock,flags); | 1135 | spin_lock_irqsave(&dmap->lock,flags); |
1135 | 1136 | ||
1136 | if (!(dmap->flags & DMA_NODMA)) { | 1137 | if (!(dmap->flags & DMA_NODMA)) { |
1137 | int chan = dmap->dma, pos, n; | 1138 | int chan = dmap->dma, pos, n; |
1138 | unsigned long f; | 1139 | unsigned long f; |
1139 | 1140 | ||
1140 | f=claim_dma_lock(); | 1141 | f=claim_dma_lock(); |
1141 | if(!isa_dma_bridge_buggy) | 1142 | if(!isa_dma_bridge_buggy) |
1142 | disable_dma(dmap->dma); | 1143 | disable_dma(dmap->dma); |
1143 | clear_dma_ff(chan); | 1144 | clear_dma_ff(chan); |
1144 | pos = dmap->bytes_in_use - get_dma_residue(chan); | 1145 | pos = dmap->bytes_in_use - get_dma_residue(chan); |
1145 | if(!isa_dma_bridge_buggy) | 1146 | if(!isa_dma_bridge_buggy) |
1146 | enable_dma(dmap->dma); | 1147 | enable_dma(dmap->dma); |
1147 | release_dma_lock(f); | 1148 | release_dma_lock(f); |
1148 | 1149 | ||
1149 | pos = pos / dmap->fragment_size; /* Actual qhead */ | 1150 | pos = pos / dmap->fragment_size; /* Actual qhead */ |
1150 | if (pos < 0 || pos >= dmap->nbufs) | 1151 | if (pos < 0 || pos >= dmap->nbufs) |
1151 | pos = 0; | 1152 | pos = 0; |
1152 | 1153 | ||
1153 | n = 0; | 1154 | n = 0; |
1154 | while (dmap->qtail != pos && ++n < dmap->nbufs) | 1155 | while (dmap->qtail != pos && ++n < dmap->nbufs) |
1155 | do_inputintr(dev); | 1156 | do_inputintr(dev); |
1156 | } else | 1157 | } else |
1157 | do_inputintr(dev); | 1158 | do_inputintr(dev); |
1158 | spin_unlock_irqrestore(&dmap->lock,flags); | 1159 | spin_unlock_irqrestore(&dmap->lock,flags); |
1159 | } | 1160 | } |
1160 | EXPORT_SYMBOL(DMAbuf_inputintr); | 1161 | EXPORT_SYMBOL(DMAbuf_inputintr); |
1161 | 1162 | ||
1162 | void DMAbuf_init(int dev, int dma1, int dma2) | 1163 | void DMAbuf_init(int dev, int dma1, int dma2) |
1163 | { | 1164 | { |
1164 | struct audio_operations *adev = audio_devs[dev]; | 1165 | struct audio_operations *adev = audio_devs[dev]; |
1165 | /* | 1166 | /* |
1166 | * NOTE! This routine could be called several times. | 1167 | * NOTE! This routine could be called several times. |
1167 | */ | 1168 | */ |
1168 | 1169 | ||
1169 | if (adev && adev->dmap_out == NULL) { | 1170 | if (adev && adev->dmap_out == NULL) { |
1170 | if (adev->d == NULL) | 1171 | if (adev->d == NULL) |
1171 | panic("OSS: audio_devs[%d]->d == NULL\n", dev); | 1172 | panic("OSS: audio_devs[%d]->d == NULL\n", dev); |
1172 | 1173 | ||
1173 | if (adev->parent_dev) { /* Use DMA map of the parent dev */ | 1174 | if (adev->parent_dev) { /* Use DMA map of the parent dev */ |
1174 | int parent = adev->parent_dev - 1; | 1175 | int parent = adev->parent_dev - 1; |
1175 | adev->dmap_out = audio_devs[parent]->dmap_out; | 1176 | adev->dmap_out = audio_devs[parent]->dmap_out; |
1176 | adev->dmap_in = audio_devs[parent]->dmap_in; | 1177 | adev->dmap_in = audio_devs[parent]->dmap_in; |
1177 | } else { | 1178 | } else { |
1178 | adev->dmap_out = adev->dmap_in = &adev->dmaps[0]; | 1179 | adev->dmap_out = adev->dmap_in = &adev->dmaps[0]; |
1179 | adev->dmap_out->dma = dma1; | 1180 | adev->dmap_out->dma = dma1; |
1180 | if (adev->flags & DMA_DUPLEX) { | 1181 | if (adev->flags & DMA_DUPLEX) { |
1181 | adev->dmap_in = &adev->dmaps[1]; | 1182 | adev->dmap_in = &adev->dmaps[1]; |
1182 | adev->dmap_in->dma = dma2; | 1183 | adev->dmap_in->dma = dma2; |
1183 | } | 1184 | } |
1184 | } | 1185 | } |
1185 | /* Persistent DMA buffers allocated here */ | 1186 | /* Persistent DMA buffers allocated here */ |
1186 | if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { | 1187 | if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { |
1187 | if (adev->dmap_in->raw_buf == NULL) | 1188 | if (adev->dmap_in->raw_buf == NULL) |
1188 | sound_alloc_dmap(adev->dmap_in); | 1189 | sound_alloc_dmap(adev->dmap_in); |
1189 | if (adev->dmap_out->raw_buf == NULL) | 1190 | if (adev->dmap_out->raw_buf == NULL) |
1190 | sound_alloc_dmap(adev->dmap_out); | 1191 | sound_alloc_dmap(adev->dmap_out); |
1191 | } | 1192 | } |
1192 | } | 1193 | } |
1193 | } | 1194 | } |
1194 | 1195 | ||
1195 | /* No kernel lock - DMAbuf_activate_recording protected by global cli/sti */ | 1196 | /* No kernel lock - DMAbuf_activate_recording protected by global cli/sti */ |
1196 | static unsigned int poll_input(struct file * file, int dev, poll_table *wait) | 1197 | static unsigned int poll_input(struct file * file, int dev, poll_table *wait) |
1197 | { | 1198 | { |
1198 | struct audio_operations *adev = audio_devs[dev]; | 1199 | struct audio_operations *adev = audio_devs[dev]; |
1199 | struct dma_buffparms *dmap = adev->dmap_in; | 1200 | struct dma_buffparms *dmap = adev->dmap_in; |
1200 | 1201 | ||
1201 | if (!(adev->open_mode & OPEN_READ)) | 1202 | if (!(adev->open_mode & OPEN_READ)) |
1202 | return 0; | 1203 | return 0; |
1203 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { | 1204 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { |
1204 | if (dmap->qlen) | 1205 | if (dmap->qlen) |
1205 | return POLLIN | POLLRDNORM; | 1206 | return POLLIN | POLLRDNORM; |
1206 | return 0; | 1207 | return 0; |
1207 | } | 1208 | } |
1208 | if (dmap->dma_mode != DMODE_INPUT) { | 1209 | if (dmap->dma_mode != DMODE_INPUT) { |
1209 | if (dmap->dma_mode == DMODE_NONE && | 1210 | if (dmap->dma_mode == DMODE_NONE && |
1210 | adev->enable_bits & PCM_ENABLE_INPUT && | 1211 | adev->enable_bits & PCM_ENABLE_INPUT && |
1211 | !dmap->qlen && adev->go) { | 1212 | !dmap->qlen && adev->go) { |
1212 | unsigned long flags; | 1213 | unsigned long flags; |
1213 | 1214 | ||
1214 | spin_lock_irqsave(&dmap->lock,flags); | 1215 | spin_lock_irqsave(&dmap->lock,flags); |
1215 | DMAbuf_activate_recording(dev, dmap); | 1216 | DMAbuf_activate_recording(dev, dmap); |
1216 | spin_unlock_irqrestore(&dmap->lock,flags); | 1217 | spin_unlock_irqrestore(&dmap->lock,flags); |
1217 | } | 1218 | } |
1218 | return 0; | 1219 | return 0; |
1219 | } | 1220 | } |
1220 | if (!dmap->qlen) | 1221 | if (!dmap->qlen) |
1221 | return 0; | 1222 | return 0; |
1222 | return POLLIN | POLLRDNORM; | 1223 | return POLLIN | POLLRDNORM; |
1223 | } | 1224 | } |
1224 | 1225 | ||
1225 | static unsigned int poll_output(struct file * file, int dev, poll_table *wait) | 1226 | static unsigned int poll_output(struct file * file, int dev, poll_table *wait) |
1226 | { | 1227 | { |
1227 | struct audio_operations *adev = audio_devs[dev]; | 1228 | struct audio_operations *adev = audio_devs[dev]; |
1228 | struct dma_buffparms *dmap = adev->dmap_out; | 1229 | struct dma_buffparms *dmap = adev->dmap_out; |
1229 | 1230 | ||
1230 | if (!(adev->open_mode & OPEN_WRITE)) | 1231 | if (!(adev->open_mode & OPEN_WRITE)) |
1231 | return 0; | 1232 | return 0; |
1232 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { | 1233 | if (dmap->mapping_flags & DMA_MAP_MAPPED) { |
1233 | if (dmap->qlen) | 1234 | if (dmap->qlen) |
1234 | return POLLOUT | POLLWRNORM; | 1235 | return POLLOUT | POLLWRNORM; |
1235 | return 0; | 1236 | return 0; |
1236 | } | 1237 | } |
1237 | if (dmap->dma_mode == DMODE_INPUT) | 1238 | if (dmap->dma_mode == DMODE_INPUT) |
1238 | return 0; | 1239 | return 0; |
1239 | if (dmap->dma_mode == DMODE_NONE) | 1240 | if (dmap->dma_mode == DMODE_NONE) |
1240 | return POLLOUT | POLLWRNORM; | 1241 | return POLLOUT | POLLWRNORM; |
1241 | if (!DMAbuf_space_in_queue(dev)) | 1242 | if (!DMAbuf_space_in_queue(dev)) |
1242 | return 0; | 1243 | return 0; |
1243 | return POLLOUT | POLLWRNORM; | 1244 | return POLLOUT | POLLWRNORM; |
1244 | } | 1245 | } |
1245 | 1246 | ||
1246 | unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait) | 1247 | unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait) |
1247 | { | 1248 | { |
1248 | struct audio_operations *adev = audio_devs[dev]; | 1249 | struct audio_operations *adev = audio_devs[dev]; |
1249 | poll_wait(file, &adev->poll_sleeper, wait); | 1250 | poll_wait(file, &adev->poll_sleeper, wait); |
1250 | return poll_input(file, dev, wait) | poll_output(file, dev, wait); | 1251 | return poll_input(file, dev, wait) | poll_output(file, dev, wait); |
1251 | } | 1252 | } |
1252 | 1253 | ||
1253 | void DMAbuf_deinit(int dev) | 1254 | void DMAbuf_deinit(int dev) |
1254 | { | 1255 | { |
1255 | struct audio_operations *adev = audio_devs[dev]; | 1256 | struct audio_operations *adev = audio_devs[dev]; |
1256 | /* This routine is called when driver is being unloaded */ | 1257 | /* This routine is called when driver is being unloaded */ |
1257 | if (!adev) | 1258 | if (!adev) |
1258 | return; | 1259 | return; |
1259 | 1260 | ||
1260 | /* Persistent DMA buffers deallocated here */ | 1261 | /* Persistent DMA buffers deallocated here */ |
1261 | if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { | 1262 | if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { |
1262 | sound_free_dmap(adev->dmap_out); | 1263 | sound_free_dmap(adev->dmap_out); |
1263 | if (adev->flags & DMA_DUPLEX) | 1264 | if (adev->flags & DMA_DUPLEX) |
1264 | sound_free_dmap(adev->dmap_in); | 1265 | sound_free_dmap(adev->dmap_in); |
1265 | } | 1266 | } |
1266 | } | 1267 | } |
1267 | 1268 |
sound/oss/emu10k1/audio.c
1 | /* | 1 | /* |
2 | ********************************************************************** | 2 | ********************************************************************** |
3 | * audio.c -- /dev/dsp interface for emu10k1 driver | 3 | * audio.c -- /dev/dsp interface for emu10k1 driver |
4 | * Copyright 1999, 2000 Creative Labs, Inc. | 4 | * Copyright 1999, 2000 Creative Labs, Inc. |
5 | * | 5 | * |
6 | ********************************************************************** | 6 | ********************************************************************** |
7 | * | 7 | * |
8 | * Date Author Summary of changes | 8 | * Date Author Summary of changes |
9 | * ---- ------ ------------------ | 9 | * ---- ------ ------------------ |
10 | * October 20, 1999 Bertrand Lee base code release | 10 | * October 20, 1999 Bertrand Lee base code release |
11 | * November 2, 1999 Alan Cox cleaned up types/leaks | 11 | * November 2, 1999 Alan Cox cleaned up types/leaks |
12 | * | 12 | * |
13 | ********************************************************************** | 13 | ********************************************************************** |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
16 | * modify it under the terms of the GNU General Public License as | 16 | * modify it under the terms of the GNU General Public License as |
17 | * published by the Free Software Foundation; either version 2 of | 17 | * published by the Free Software Foundation; either version 2 of |
18 | * the License, or (at your option) any later version. | 18 | * the License, or (at your option) any later version. |
19 | * | 19 | * |
20 | * This program is distributed in the hope that it will be useful, | 20 | * This program is distributed in the hope that it will be useful, |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | * GNU General Public License for more details. | 23 | * GNU General Public License for more details. |
24 | * | 24 | * |
25 | * You should have received a copy of the GNU General Public | 25 | * You should have received a copy of the GNU General Public |
26 | * License along with this program; if not, write to the Free | 26 | * License along with this program; if not, write to the Free |
27 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, | 27 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, |
28 | * USA. | 28 | * USA. |
29 | * | 29 | * |
30 | ********************************************************************** | 30 | ********************************************************************** |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/poll.h> | 34 | #include <linux/poll.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/bitops.h> | 36 | #include <linux/bitops.h> |
37 | #include <asm/io.h> | 37 | #include <asm/io.h> |
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <linux/mm.h> | ||
39 | #include <linux/smp_lock.h> | 40 | #include <linux/smp_lock.h> |
40 | 41 | ||
41 | #include "hwaccess.h" | 42 | #include "hwaccess.h" |
42 | #include "cardwo.h" | 43 | #include "cardwo.h" |
43 | #include "cardwi.h" | 44 | #include "cardwi.h" |
44 | #include "recmgr.h" | 45 | #include "recmgr.h" |
45 | #include "irqmgr.h" | 46 | #include "irqmgr.h" |
46 | #include "audio.h" | 47 | #include "audio.h" |
47 | #include "8010.h" | 48 | #include "8010.h" |
48 | 49 | ||
49 | static void calculate_ofrag(struct woinst *); | 50 | static void calculate_ofrag(struct woinst *); |
50 | static void calculate_ifrag(struct wiinst *); | 51 | static void calculate_ifrag(struct wiinst *); |
51 | 52 | ||
52 | static void emu10k1_waveout_bh(unsigned long refdata); | 53 | static void emu10k1_waveout_bh(unsigned long refdata); |
53 | static void emu10k1_wavein_bh(unsigned long refdata); | 54 | static void emu10k1_wavein_bh(unsigned long refdata); |
54 | 55 | ||
55 | /* Audio file operations */ | 56 | /* Audio file operations */ |
56 | static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) | 57 | static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) |
57 | { | 58 | { |
58 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | 59 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; |
59 | struct wiinst *wiinst = wave_dev->wiinst; | 60 | struct wiinst *wiinst = wave_dev->wiinst; |
60 | ssize_t ret = 0; | 61 | ssize_t ret = 0; |
61 | unsigned long flags; | 62 | unsigned long flags; |
62 | 63 | ||
63 | DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count); | 64 | DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count); |
64 | 65 | ||
65 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 66 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
66 | return -EFAULT; | 67 | return -EFAULT; |
67 | 68 | ||
68 | spin_lock_irqsave(&wiinst->lock, flags); | 69 | spin_lock_irqsave(&wiinst->lock, flags); |
69 | 70 | ||
70 | if (wiinst->mmapped) { | 71 | if (wiinst->mmapped) { |
71 | spin_unlock_irqrestore(&wiinst->lock, flags); | 72 | spin_unlock_irqrestore(&wiinst->lock, flags); |
72 | return -ENXIO; | 73 | return -ENXIO; |
73 | } | 74 | } |
74 | 75 | ||
75 | if (wiinst->state == WAVE_STATE_CLOSED) { | 76 | if (wiinst->state == WAVE_STATE_CLOSED) { |
76 | calculate_ifrag(wiinst); | 77 | calculate_ifrag(wiinst); |
77 | 78 | ||
78 | while (emu10k1_wavein_open(wave_dev) < 0) { | 79 | while (emu10k1_wavein_open(wave_dev) < 0) { |
79 | spin_unlock_irqrestore(&wiinst->lock, flags); | 80 | spin_unlock_irqrestore(&wiinst->lock, flags); |
80 | 81 | ||
81 | if (file->f_flags & O_NONBLOCK) | 82 | if (file->f_flags & O_NONBLOCK) |
82 | return -EAGAIN; | 83 | return -EAGAIN; |
83 | 84 | ||
84 | interruptible_sleep_on(&wave_dev->card->open_wait); | 85 | interruptible_sleep_on(&wave_dev->card->open_wait); |
85 | 86 | ||
86 | if (signal_pending(current)) | 87 | if (signal_pending(current)) |
87 | return -ERESTARTSYS; | 88 | return -ERESTARTSYS; |
88 | 89 | ||
89 | spin_lock_irqsave(&wiinst->lock, flags); | 90 | spin_lock_irqsave(&wiinst->lock, flags); |
90 | } | 91 | } |
91 | } | 92 | } |
92 | 93 | ||
93 | spin_unlock_irqrestore(&wiinst->lock, flags); | 94 | spin_unlock_irqrestore(&wiinst->lock, flags); |
94 | 95 | ||
95 | while (count > 0) { | 96 | while (count > 0) { |
96 | u32 bytestocopy; | 97 | u32 bytestocopy; |
97 | 98 | ||
98 | spin_lock_irqsave(&wiinst->lock, flags); | 99 | spin_lock_irqsave(&wiinst->lock, flags); |
99 | 100 | ||
100 | if (!(wiinst->state & WAVE_STATE_STARTED) | 101 | if (!(wiinst->state & WAVE_STATE_STARTED) |
101 | && (wave_dev->enablebits & PCM_ENABLE_INPUT)) | 102 | && (wave_dev->enablebits & PCM_ENABLE_INPUT)) |
102 | emu10k1_wavein_start(wave_dev); | 103 | emu10k1_wavein_start(wave_dev); |
103 | 104 | ||
104 | emu10k1_wavein_update(wave_dev->card, wiinst); | 105 | emu10k1_wavein_update(wave_dev->card, wiinst); |
105 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | 106 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); |
106 | 107 | ||
107 | spin_unlock_irqrestore(&wiinst->lock, flags); | 108 | spin_unlock_irqrestore(&wiinst->lock, flags); |
108 | 109 | ||
109 | DPD(3, "bytestocopy --> %d\n", bytestocopy); | 110 | DPD(3, "bytestocopy --> %d\n", bytestocopy); |
110 | 111 | ||
111 | if ((bytestocopy >= wiinst->buffer.fragment_size) | 112 | if ((bytestocopy >= wiinst->buffer.fragment_size) |
112 | || (bytestocopy >= count)) { | 113 | || (bytestocopy >= count)) { |
113 | bytestocopy = min_t(u32, bytestocopy, count); | 114 | bytestocopy = min_t(u32, bytestocopy, count); |
114 | 115 | ||
115 | emu10k1_wavein_xferdata(wiinst, (u8 __user *)buffer, &bytestocopy); | 116 | emu10k1_wavein_xferdata(wiinst, (u8 __user *)buffer, &bytestocopy); |
116 | 117 | ||
117 | count -= bytestocopy; | 118 | count -= bytestocopy; |
118 | buffer += bytestocopy; | 119 | buffer += bytestocopy; |
119 | ret += bytestocopy; | 120 | ret += bytestocopy; |
120 | } | 121 | } |
121 | 122 | ||
122 | if (count > 0) { | 123 | if (count > 0) { |
123 | if ((file->f_flags & O_NONBLOCK) | 124 | if ((file->f_flags & O_NONBLOCK) |
124 | || (!(wave_dev->enablebits & PCM_ENABLE_INPUT))) | 125 | || (!(wave_dev->enablebits & PCM_ENABLE_INPUT))) |
125 | return (ret ? ret : -EAGAIN); | 126 | return (ret ? ret : -EAGAIN); |
126 | 127 | ||
127 | interruptible_sleep_on(&wiinst->wait_queue); | 128 | interruptible_sleep_on(&wiinst->wait_queue); |
128 | 129 | ||
129 | if (signal_pending(current)) | 130 | if (signal_pending(current)) |
130 | return (ret ? ret : -ERESTARTSYS); | 131 | return (ret ? ret : -ERESTARTSYS); |
131 | 132 | ||
132 | } | 133 | } |
133 | } | 134 | } |
134 | 135 | ||
135 | DPD(3, "bytes copied -> %d\n", (u32) ret); | 136 | DPD(3, "bytes copied -> %d\n", (u32) ret); |
136 | 137 | ||
137 | return ret; | 138 | return ret; |
138 | } | 139 | } |
139 | 140 | ||
140 | static ssize_t emu10k1_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) | 141 | static ssize_t emu10k1_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) |
141 | { | 142 | { |
142 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | 143 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; |
143 | struct woinst *woinst = wave_dev->woinst; | 144 | struct woinst *woinst = wave_dev->woinst; |
144 | ssize_t ret; | 145 | ssize_t ret; |
145 | unsigned long flags; | 146 | unsigned long flags; |
146 | 147 | ||
147 | DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count); | 148 | DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count); |
148 | 149 | ||
149 | if (!access_ok(VERIFY_READ, buffer, count)) | 150 | if (!access_ok(VERIFY_READ, buffer, count)) |
150 | return -EFAULT; | 151 | return -EFAULT; |
151 | 152 | ||
152 | spin_lock_irqsave(&woinst->lock, flags); | 153 | spin_lock_irqsave(&woinst->lock, flags); |
153 | 154 | ||
154 | if (woinst->mmapped) { | 155 | if (woinst->mmapped) { |
155 | spin_unlock_irqrestore(&woinst->lock, flags); | 156 | spin_unlock_irqrestore(&woinst->lock, flags); |
156 | return -ENXIO; | 157 | return -ENXIO; |
157 | } | 158 | } |
158 | // This is for emu10k1 revs less than 7, we need to go through tram | 159 | // This is for emu10k1 revs less than 7, we need to go through tram |
159 | if (woinst->format.passthrough == 1) { | 160 | if (woinst->format.passthrough == 1) { |
160 | int r; | 161 | int r; |
161 | 162 | ||
162 | woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2; | 163 | woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2; |
163 | woinst->buffer.numfrags = PT_BLOCKCOUNT; | 164 | woinst->buffer.numfrags = PT_BLOCKCOUNT; |
164 | calculate_ofrag(woinst); | 165 | calculate_ofrag(woinst); |
165 | 166 | ||
166 | r = emu10k1_pt_write(file, buffer, count); | 167 | r = emu10k1_pt_write(file, buffer, count); |
167 | spin_unlock_irqrestore(&woinst->lock, flags); | 168 | spin_unlock_irqrestore(&woinst->lock, flags); |
168 | return r; | 169 | return r; |
169 | } | 170 | } |
170 | 171 | ||
171 | if (woinst->state == WAVE_STATE_CLOSED) { | 172 | if (woinst->state == WAVE_STATE_CLOSED) { |
172 | calculate_ofrag(woinst); | 173 | calculate_ofrag(woinst); |
173 | 174 | ||
174 | while (emu10k1_waveout_open(wave_dev) < 0) { | 175 | while (emu10k1_waveout_open(wave_dev) < 0) { |
175 | spin_unlock_irqrestore(&woinst->lock, flags); | 176 | spin_unlock_irqrestore(&woinst->lock, flags); |
176 | 177 | ||
177 | if (file->f_flags & O_NONBLOCK) | 178 | if (file->f_flags & O_NONBLOCK) |
178 | return -EAGAIN; | 179 | return -EAGAIN; |
179 | 180 | ||
180 | interruptible_sleep_on(&wave_dev->card->open_wait); | 181 | interruptible_sleep_on(&wave_dev->card->open_wait); |
181 | 182 | ||
182 | if (signal_pending(current)) | 183 | if (signal_pending(current)) |
183 | return -ERESTARTSYS; | 184 | return -ERESTARTSYS; |
184 | 185 | ||
185 | spin_lock_irqsave(&woinst->lock, flags); | 186 | spin_lock_irqsave(&woinst->lock, flags); |
186 | } | 187 | } |
187 | } | 188 | } |
188 | 189 | ||
189 | spin_unlock_irqrestore(&woinst->lock, flags); | 190 | spin_unlock_irqrestore(&woinst->lock, flags); |
190 | 191 | ||
191 | ret = 0; | 192 | ret = 0; |
192 | if (count % woinst->format.bytespersample) | 193 | if (count % woinst->format.bytespersample) |
193 | return -EINVAL; | 194 | return -EINVAL; |
194 | 195 | ||
195 | count /= woinst->num_voices; | 196 | count /= woinst->num_voices; |
196 | 197 | ||
197 | while (count > 0) { | 198 | while (count > 0) { |
198 | u32 bytestocopy; | 199 | u32 bytestocopy; |
199 | 200 | ||
200 | spin_lock_irqsave(&woinst->lock, flags); | 201 | spin_lock_irqsave(&woinst->lock, flags); |
201 | emu10k1_waveout_update(woinst); | 202 | emu10k1_waveout_update(woinst); |
202 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | 203 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); |
203 | spin_unlock_irqrestore(&woinst->lock, flags); | 204 | spin_unlock_irqrestore(&woinst->lock, flags); |
204 | 205 | ||
205 | DPD(3, "bytestocopy --> %d\n", bytestocopy); | 206 | DPD(3, "bytestocopy --> %d\n", bytestocopy); |
206 | 207 | ||
207 | if ((bytestocopy >= woinst->buffer.fragment_size) | 208 | if ((bytestocopy >= woinst->buffer.fragment_size) |
208 | || (bytestocopy >= count)) { | 209 | || (bytestocopy >= count)) { |
209 | 210 | ||
210 | bytestocopy = min_t(u32, bytestocopy, count); | 211 | bytestocopy = min_t(u32, bytestocopy, count); |
211 | 212 | ||
212 | emu10k1_waveout_xferdata(woinst, (u8 __user *) buffer, &bytestocopy); | 213 | emu10k1_waveout_xferdata(woinst, (u8 __user *) buffer, &bytestocopy); |
213 | 214 | ||
214 | count -= bytestocopy; | 215 | count -= bytestocopy; |
215 | buffer += bytestocopy * woinst->num_voices; | 216 | buffer += bytestocopy * woinst->num_voices; |
216 | ret += bytestocopy * woinst->num_voices; | 217 | ret += bytestocopy * woinst->num_voices; |
217 | 218 | ||
218 | spin_lock_irqsave(&woinst->lock, flags); | 219 | spin_lock_irqsave(&woinst->lock, flags); |
219 | woinst->total_copied += bytestocopy; | 220 | woinst->total_copied += bytestocopy; |
220 | 221 | ||
221 | if (!(woinst->state & WAVE_STATE_STARTED) | 222 | if (!(woinst->state & WAVE_STATE_STARTED) |
222 | && (wave_dev->enablebits & PCM_ENABLE_OUTPUT) | 223 | && (wave_dev->enablebits & PCM_ENABLE_OUTPUT) |
223 | && (woinst->total_copied >= woinst->buffer.fragment_size)) | 224 | && (woinst->total_copied >= woinst->buffer.fragment_size)) |
224 | emu10k1_waveout_start(wave_dev); | 225 | emu10k1_waveout_start(wave_dev); |
225 | 226 | ||
226 | spin_unlock_irqrestore(&woinst->lock, flags); | 227 | spin_unlock_irqrestore(&woinst->lock, flags); |
227 | } | 228 | } |
228 | 229 | ||
229 | if (count > 0) { | 230 | if (count > 0) { |
230 | if ((file->f_flags & O_NONBLOCK) | 231 | if ((file->f_flags & O_NONBLOCK) |
231 | || (!(wave_dev->enablebits & PCM_ENABLE_OUTPUT))) | 232 | || (!(wave_dev->enablebits & PCM_ENABLE_OUTPUT))) |
232 | return (ret ? ret : -EAGAIN); | 233 | return (ret ? ret : -EAGAIN); |
233 | 234 | ||
234 | interruptible_sleep_on(&woinst->wait_queue); | 235 | interruptible_sleep_on(&woinst->wait_queue); |
235 | 236 | ||
236 | if (signal_pending(current)) | 237 | if (signal_pending(current)) |
237 | return (ret ? ret : -ERESTARTSYS); | 238 | return (ret ? ret : -ERESTARTSYS); |
238 | } | 239 | } |
239 | } | 240 | } |
240 | 241 | ||
241 | DPD(3, "bytes copied -> %d\n", (u32) ret); | 242 | DPD(3, "bytes copied -> %d\n", (u32) ret); |
242 | 243 | ||
243 | return ret; | 244 | return ret; |
244 | } | 245 | } |
245 | 246 | ||
246 | static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 247 | static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
247 | { | 248 | { |
248 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | 249 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; |
249 | struct woinst *woinst = NULL; | 250 | struct woinst *woinst = NULL; |
250 | struct wiinst *wiinst = NULL; | 251 | struct wiinst *wiinst = NULL; |
251 | int val = 0; | 252 | int val = 0; |
252 | u32 bytestocopy; | 253 | u32 bytestocopy; |
253 | unsigned long flags; | 254 | unsigned long flags; |
254 | int __user *p = (int __user *)arg; | 255 | int __user *p = (int __user *)arg; |
255 | 256 | ||
256 | DPF(4, "emu10k1_audio_ioctl()\n"); | 257 | DPF(4, "emu10k1_audio_ioctl()\n"); |
257 | 258 | ||
258 | if (file->f_mode & FMODE_WRITE) | 259 | if (file->f_mode & FMODE_WRITE) |
259 | woinst = wave_dev->woinst; | 260 | woinst = wave_dev->woinst; |
260 | 261 | ||
261 | if (file->f_mode & FMODE_READ) | 262 | if (file->f_mode & FMODE_READ) |
262 | wiinst = wave_dev->wiinst; | 263 | wiinst = wave_dev->wiinst; |
263 | 264 | ||
264 | switch (cmd) { | 265 | switch (cmd) { |
265 | case OSS_GETVERSION: | 266 | case OSS_GETVERSION: |
266 | DPF(2, "OSS_GETVERSION:\n"); | 267 | DPF(2, "OSS_GETVERSION:\n"); |
267 | return put_user(SOUND_VERSION, p); | 268 | return put_user(SOUND_VERSION, p); |
268 | 269 | ||
269 | case SNDCTL_DSP_RESET: | 270 | case SNDCTL_DSP_RESET: |
270 | DPF(2, "SNDCTL_DSP_RESET:\n"); | 271 | DPF(2, "SNDCTL_DSP_RESET:\n"); |
271 | wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT; | 272 | wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT; |
272 | 273 | ||
273 | if (file->f_mode & FMODE_WRITE) { | 274 | if (file->f_mode & FMODE_WRITE) { |
274 | spin_lock_irqsave(&woinst->lock, flags); | 275 | spin_lock_irqsave(&woinst->lock, flags); |
275 | 276 | ||
276 | if (woinst->state & WAVE_STATE_OPEN) { | 277 | if (woinst->state & WAVE_STATE_OPEN) { |
277 | emu10k1_waveout_close(wave_dev); | 278 | emu10k1_waveout_close(wave_dev); |
278 | } | 279 | } |
279 | 280 | ||
280 | woinst->mmapped = 0; | 281 | woinst->mmapped = 0; |
281 | woinst->total_copied = 0; | 282 | woinst->total_copied = 0; |
282 | woinst->total_played = 0; | 283 | woinst->total_played = 0; |
283 | woinst->blocks = 0; | 284 | woinst->blocks = 0; |
284 | 285 | ||
285 | spin_unlock_irqrestore(&woinst->lock, flags); | 286 | spin_unlock_irqrestore(&woinst->lock, flags); |
286 | } | 287 | } |
287 | 288 | ||
288 | if (file->f_mode & FMODE_READ) { | 289 | if (file->f_mode & FMODE_READ) { |
289 | spin_lock_irqsave(&wiinst->lock, flags); | 290 | spin_lock_irqsave(&wiinst->lock, flags); |
290 | 291 | ||
291 | if (wiinst->state & WAVE_STATE_OPEN) { | 292 | if (wiinst->state & WAVE_STATE_OPEN) { |
292 | emu10k1_wavein_close(wave_dev); | 293 | emu10k1_wavein_close(wave_dev); |
293 | } | 294 | } |
294 | 295 | ||
295 | wiinst->mmapped = 0; | 296 | wiinst->mmapped = 0; |
296 | wiinst->total_recorded = 0; | 297 | wiinst->total_recorded = 0; |
297 | wiinst->blocks = 0; | 298 | wiinst->blocks = 0; |
298 | spin_unlock_irqrestore(&wiinst->lock, flags); | 299 | spin_unlock_irqrestore(&wiinst->lock, flags); |
299 | } | 300 | } |
300 | 301 | ||
301 | break; | 302 | break; |
302 | 303 | ||
303 | case SNDCTL_DSP_SYNC: | 304 | case SNDCTL_DSP_SYNC: |
304 | DPF(2, "SNDCTL_DSP_SYNC:\n"); | 305 | DPF(2, "SNDCTL_DSP_SYNC:\n"); |
305 | 306 | ||
306 | if (file->f_mode & FMODE_WRITE) { | 307 | if (file->f_mode & FMODE_WRITE) { |
307 | 308 | ||
308 | spin_lock_irqsave(&woinst->lock, flags); | 309 | spin_lock_irqsave(&woinst->lock, flags); |
309 | 310 | ||
310 | if (woinst->state & WAVE_STATE_OPEN) { | 311 | if (woinst->state & WAVE_STATE_OPEN) { |
311 | 312 | ||
312 | if (woinst->state & WAVE_STATE_STARTED) | 313 | if (woinst->state & WAVE_STATE_STARTED) |
313 | while ((woinst->total_played < woinst->total_copied) | 314 | while ((woinst->total_played < woinst->total_copied) |
314 | && !signal_pending(current)) { | 315 | && !signal_pending(current)) { |
315 | spin_unlock_irqrestore(&woinst->lock, flags); | 316 | spin_unlock_irqrestore(&woinst->lock, flags); |
316 | interruptible_sleep_on(&woinst->wait_queue); | 317 | interruptible_sleep_on(&woinst->wait_queue); |
317 | spin_lock_irqsave(&woinst->lock, flags); | 318 | spin_lock_irqsave(&woinst->lock, flags); |
318 | } | 319 | } |
319 | emu10k1_waveout_close(wave_dev); | 320 | emu10k1_waveout_close(wave_dev); |
320 | } | 321 | } |
321 | 322 | ||
322 | woinst->mmapped = 0; | 323 | woinst->mmapped = 0; |
323 | woinst->total_copied = 0; | 324 | woinst->total_copied = 0; |
324 | woinst->total_played = 0; | 325 | woinst->total_played = 0; |
325 | woinst->blocks = 0; | 326 | woinst->blocks = 0; |
326 | 327 | ||
327 | spin_unlock_irqrestore(&woinst->lock, flags); | 328 | spin_unlock_irqrestore(&woinst->lock, flags); |
328 | } | 329 | } |
329 | 330 | ||
330 | if (file->f_mode & FMODE_READ) { | 331 | if (file->f_mode & FMODE_READ) { |
331 | spin_lock_irqsave(&wiinst->lock, flags); | 332 | spin_lock_irqsave(&wiinst->lock, flags); |
332 | 333 | ||
333 | if (wiinst->state & WAVE_STATE_OPEN) { | 334 | if (wiinst->state & WAVE_STATE_OPEN) { |
334 | emu10k1_wavein_close(wave_dev); | 335 | emu10k1_wavein_close(wave_dev); |
335 | } | 336 | } |
336 | 337 | ||
337 | wiinst->mmapped = 0; | 338 | wiinst->mmapped = 0; |
338 | wiinst->total_recorded = 0; | 339 | wiinst->total_recorded = 0; |
339 | wiinst->blocks = 0; | 340 | wiinst->blocks = 0; |
340 | spin_unlock_irqrestore(&wiinst->lock, flags); | 341 | spin_unlock_irqrestore(&wiinst->lock, flags); |
341 | } | 342 | } |
342 | 343 | ||
343 | break; | 344 | break; |
344 | 345 | ||
345 | case SNDCTL_DSP_SETDUPLEX: | 346 | case SNDCTL_DSP_SETDUPLEX: |
346 | DPF(2, "SNDCTL_DSP_SETDUPLEX:\n"); | 347 | DPF(2, "SNDCTL_DSP_SETDUPLEX:\n"); |
347 | break; | 348 | break; |
348 | 349 | ||
349 | case SNDCTL_DSP_GETCAPS: | 350 | case SNDCTL_DSP_GETCAPS: |
350 | DPF(2, "SNDCTL_DSP_GETCAPS:\n"); | 351 | DPF(2, "SNDCTL_DSP_GETCAPS:\n"); |
351 | return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | | 352 | return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | |
352 | DSP_CAP_TRIGGER | DSP_CAP_MMAP | | 353 | DSP_CAP_TRIGGER | DSP_CAP_MMAP | |
353 | DSP_CAP_COPROC| DSP_CAP_MULTI, p); | 354 | DSP_CAP_COPROC| DSP_CAP_MULTI, p); |
354 | case SNDCTL_DSP_SPEED: | 355 | case SNDCTL_DSP_SPEED: |
355 | DPF(2, "SNDCTL_DSP_SPEED:\n"); | 356 | DPF(2, "SNDCTL_DSP_SPEED:\n"); |
356 | 357 | ||
357 | if (get_user(val, p)) | 358 | if (get_user(val, p)) |
358 | return -EFAULT; | 359 | return -EFAULT; |
359 | 360 | ||
360 | DPD(2, "val is %d\n", val); | 361 | DPD(2, "val is %d\n", val); |
361 | 362 | ||
362 | if (val > 0) { | 363 | if (val > 0) { |
363 | if (file->f_mode & FMODE_READ) { | 364 | if (file->f_mode & FMODE_READ) { |
364 | struct wave_format format; | 365 | struct wave_format format; |
365 | 366 | ||
366 | spin_lock_irqsave(&wiinst->lock, flags); | 367 | spin_lock_irqsave(&wiinst->lock, flags); |
367 | 368 | ||
368 | format = wiinst->format; | 369 | format = wiinst->format; |
369 | format.samplingrate = val; | 370 | format.samplingrate = val; |
370 | 371 | ||
371 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | 372 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { |
372 | spin_unlock_irqrestore(&wiinst->lock, flags); | 373 | spin_unlock_irqrestore(&wiinst->lock, flags); |
373 | return -EINVAL; | 374 | return -EINVAL; |
374 | } | 375 | } |
375 | 376 | ||
376 | val = wiinst->format.samplingrate; | 377 | val = wiinst->format.samplingrate; |
377 | 378 | ||
378 | spin_unlock_irqrestore(&wiinst->lock, flags); | 379 | spin_unlock_irqrestore(&wiinst->lock, flags); |
379 | 380 | ||
380 | DPD(2, "set recording sampling rate -> %d\n", val); | 381 | DPD(2, "set recording sampling rate -> %d\n", val); |
381 | } | 382 | } |
382 | 383 | ||
383 | if (file->f_mode & FMODE_WRITE) { | 384 | if (file->f_mode & FMODE_WRITE) { |
384 | struct wave_format format; | 385 | struct wave_format format; |
385 | 386 | ||
386 | spin_lock_irqsave(&woinst->lock, flags); | 387 | spin_lock_irqsave(&woinst->lock, flags); |
387 | 388 | ||
388 | format = woinst->format; | 389 | format = woinst->format; |
389 | format.samplingrate = val; | 390 | format.samplingrate = val; |
390 | 391 | ||
391 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | 392 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { |
392 | spin_unlock_irqrestore(&woinst->lock, flags); | 393 | spin_unlock_irqrestore(&woinst->lock, flags); |
393 | return -EINVAL; | 394 | return -EINVAL; |
394 | } | 395 | } |
395 | 396 | ||
396 | val = woinst->format.samplingrate; | 397 | val = woinst->format.samplingrate; |
397 | 398 | ||
398 | spin_unlock_irqrestore(&woinst->lock, flags); | 399 | spin_unlock_irqrestore(&woinst->lock, flags); |
399 | 400 | ||
400 | DPD(2, "set playback sampling rate -> %d\n", val); | 401 | DPD(2, "set playback sampling rate -> %d\n", val); |
401 | } | 402 | } |
402 | 403 | ||
403 | return put_user(val, p); | 404 | return put_user(val, p); |
404 | } else { | 405 | } else { |
405 | if (file->f_mode & FMODE_READ) | 406 | if (file->f_mode & FMODE_READ) |
406 | val = wiinst->format.samplingrate; | 407 | val = wiinst->format.samplingrate; |
407 | else if (file->f_mode & FMODE_WRITE) | 408 | else if (file->f_mode & FMODE_WRITE) |
408 | val = woinst->format.samplingrate; | 409 | val = woinst->format.samplingrate; |
409 | 410 | ||
410 | return put_user(val, p); | 411 | return put_user(val, p); |
411 | } | 412 | } |
412 | break; | 413 | break; |
413 | 414 | ||
414 | case SNDCTL_DSP_STEREO: | 415 | case SNDCTL_DSP_STEREO: |
415 | DPF(2, "SNDCTL_DSP_STEREO:\n"); | 416 | DPF(2, "SNDCTL_DSP_STEREO:\n"); |
416 | 417 | ||
417 | if (get_user(val, p)) | 418 | if (get_user(val, p)) |
418 | return -EFAULT; | 419 | return -EFAULT; |
419 | 420 | ||
420 | DPD(2, " val is %d\n", val); | 421 | DPD(2, " val is %d\n", val); |
421 | 422 | ||
422 | if (file->f_mode & FMODE_READ) { | 423 | if (file->f_mode & FMODE_READ) { |
423 | struct wave_format format; | 424 | struct wave_format format; |
424 | 425 | ||
425 | spin_lock_irqsave(&wiinst->lock, flags); | 426 | spin_lock_irqsave(&wiinst->lock, flags); |
426 | 427 | ||
427 | format = wiinst->format; | 428 | format = wiinst->format; |
428 | format.channels = val ? 2 : 1; | 429 | format.channels = val ? 2 : 1; |
429 | 430 | ||
430 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | 431 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { |
431 | spin_unlock_irqrestore(&wiinst->lock, flags); | 432 | spin_unlock_irqrestore(&wiinst->lock, flags); |
432 | return -EINVAL; | 433 | return -EINVAL; |
433 | } | 434 | } |
434 | 435 | ||
435 | val = wiinst->format.channels - 1; | 436 | val = wiinst->format.channels - 1; |
436 | 437 | ||
437 | spin_unlock_irqrestore(&wiinst->lock, flags); | 438 | spin_unlock_irqrestore(&wiinst->lock, flags); |
438 | DPD(2, "set recording stereo -> %d\n", val); | 439 | DPD(2, "set recording stereo -> %d\n", val); |
439 | } | 440 | } |
440 | 441 | ||
441 | if (file->f_mode & FMODE_WRITE) { | 442 | if (file->f_mode & FMODE_WRITE) { |
442 | struct wave_format format; | 443 | struct wave_format format; |
443 | 444 | ||
444 | spin_lock_irqsave(&woinst->lock, flags); | 445 | spin_lock_irqsave(&woinst->lock, flags); |
445 | 446 | ||
446 | format = woinst->format; | 447 | format = woinst->format; |
447 | format.channels = val ? 2 : 1; | 448 | format.channels = val ? 2 : 1; |
448 | 449 | ||
449 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | 450 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { |
450 | spin_unlock_irqrestore(&woinst->lock, flags); | 451 | spin_unlock_irqrestore(&woinst->lock, flags); |
451 | return -EINVAL; | 452 | return -EINVAL; |
452 | } | 453 | } |
453 | 454 | ||
454 | val = woinst->format.channels - 1; | 455 | val = woinst->format.channels - 1; |
455 | 456 | ||
456 | spin_unlock_irqrestore(&woinst->lock, flags); | 457 | spin_unlock_irqrestore(&woinst->lock, flags); |
457 | 458 | ||
458 | DPD(2, "set playback stereo -> %d\n", val); | 459 | DPD(2, "set playback stereo -> %d\n", val); |
459 | } | 460 | } |
460 | 461 | ||
461 | return put_user(val, p); | 462 | return put_user(val, p); |
462 | 463 | ||
463 | break; | 464 | break; |
464 | 465 | ||
465 | case SNDCTL_DSP_CHANNELS: | 466 | case SNDCTL_DSP_CHANNELS: |
466 | DPF(2, "SNDCTL_DSP_CHANNELS:\n"); | 467 | DPF(2, "SNDCTL_DSP_CHANNELS:\n"); |
467 | 468 | ||
468 | if (get_user(val, p)) | 469 | if (get_user(val, p)) |
469 | return -EFAULT; | 470 | return -EFAULT; |
470 | 471 | ||
471 | DPD(2, " val is %d\n", val); | 472 | DPD(2, " val is %d\n", val); |
472 | 473 | ||
473 | if (val > 0) { | 474 | if (val > 0) { |
474 | if (file->f_mode & FMODE_READ) { | 475 | if (file->f_mode & FMODE_READ) { |
475 | struct wave_format format; | 476 | struct wave_format format; |
476 | 477 | ||
477 | spin_lock_irqsave(&wiinst->lock, flags); | 478 | spin_lock_irqsave(&wiinst->lock, flags); |
478 | 479 | ||
479 | format = wiinst->format; | 480 | format = wiinst->format; |
480 | format.channels = val; | 481 | format.channels = val; |
481 | 482 | ||
482 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | 483 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { |
483 | spin_unlock_irqrestore(&wiinst->lock, flags); | 484 | spin_unlock_irqrestore(&wiinst->lock, flags); |
484 | return -EINVAL; | 485 | return -EINVAL; |
485 | } | 486 | } |
486 | val = wiinst->format.channels; | 487 | val = wiinst->format.channels; |
487 | 488 | ||
488 | spin_unlock_irqrestore(&wiinst->lock, flags); | 489 | spin_unlock_irqrestore(&wiinst->lock, flags); |
489 | DPD(2, "set recording number of channels -> %d\n", val); | 490 | DPD(2, "set recording number of channels -> %d\n", val); |
490 | } | 491 | } |
491 | 492 | ||
492 | if (file->f_mode & FMODE_WRITE) { | 493 | if (file->f_mode & FMODE_WRITE) { |
493 | struct wave_format format; | 494 | struct wave_format format; |
494 | 495 | ||
495 | spin_lock_irqsave(&woinst->lock, flags); | 496 | spin_lock_irqsave(&woinst->lock, flags); |
496 | 497 | ||
497 | format = woinst->format; | 498 | format = woinst->format; |
498 | format.channels = val; | 499 | format.channels = val; |
499 | 500 | ||
500 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | 501 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { |
501 | spin_unlock_irqrestore(&woinst->lock, flags); | 502 | spin_unlock_irqrestore(&woinst->lock, flags); |
502 | return -EINVAL; | 503 | return -EINVAL; |
503 | } | 504 | } |
504 | 505 | ||
505 | val = woinst->format.channels; | 506 | val = woinst->format.channels; |
506 | 507 | ||
507 | spin_unlock_irqrestore(&woinst->lock, flags); | 508 | spin_unlock_irqrestore(&woinst->lock, flags); |
508 | DPD(2, "set playback number of channels -> %d\n", val); | 509 | DPD(2, "set playback number of channels -> %d\n", val); |
509 | } | 510 | } |
510 | 511 | ||
511 | return put_user(val, p); | 512 | return put_user(val, p); |
512 | } else { | 513 | } else { |
513 | if (file->f_mode & FMODE_READ) | 514 | if (file->f_mode & FMODE_READ) |
514 | val = wiinst->format.channels; | 515 | val = wiinst->format.channels; |
515 | else if (file->f_mode & FMODE_WRITE) | 516 | else if (file->f_mode & FMODE_WRITE) |
516 | val = woinst->format.channels; | 517 | val = woinst->format.channels; |
517 | 518 | ||
518 | return put_user(val, p); | 519 | return put_user(val, p); |
519 | } | 520 | } |
520 | break; | 521 | break; |
521 | 522 | ||
522 | case SNDCTL_DSP_GETFMTS: | 523 | case SNDCTL_DSP_GETFMTS: |
523 | DPF(2, "SNDCTL_DSP_GETFMTS:\n"); | 524 | DPF(2, "SNDCTL_DSP_GETFMTS:\n"); |
524 | 525 | ||
525 | if (file->f_mode & FMODE_READ) | 526 | if (file->f_mode & FMODE_READ) |
526 | val = AFMT_S16_LE; | 527 | val = AFMT_S16_LE; |
527 | else if (file->f_mode & FMODE_WRITE) { | 528 | else if (file->f_mode & FMODE_WRITE) { |
528 | val = AFMT_S16_LE | AFMT_U8; | 529 | val = AFMT_S16_LE | AFMT_U8; |
529 | if (emu10k1_find_control_gpr(&wave_dev->card->mgr, | 530 | if (emu10k1_find_control_gpr(&wave_dev->card->mgr, |
530 | wave_dev->card->pt.patch_name, | 531 | wave_dev->card->pt.patch_name, |
531 | wave_dev->card->pt.enable_gpr_name) >= 0) | 532 | wave_dev->card->pt.enable_gpr_name) >= 0) |
532 | val |= AFMT_AC3; | 533 | val |= AFMT_AC3; |
533 | } | 534 | } |
534 | return put_user(val, p); | 535 | return put_user(val, p); |
535 | 536 | ||
536 | case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */ | 537 | case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */ |
537 | DPF(2, "SNDCTL_DSP_SETFMT:\n"); | 538 | DPF(2, "SNDCTL_DSP_SETFMT:\n"); |
538 | 539 | ||
539 | if (get_user(val, p)) | 540 | if (get_user(val, p)) |
540 | return -EFAULT; | 541 | return -EFAULT; |
541 | 542 | ||
542 | DPD(2, " val is %d\n", val); | 543 | DPD(2, " val is %d\n", val); |
543 | 544 | ||
544 | if (val != AFMT_QUERY) { | 545 | if (val != AFMT_QUERY) { |
545 | if (file->f_mode & FMODE_READ) { | 546 | if (file->f_mode & FMODE_READ) { |
546 | struct wave_format format; | 547 | struct wave_format format; |
547 | 548 | ||
548 | spin_lock_irqsave(&wiinst->lock, flags); | 549 | spin_lock_irqsave(&wiinst->lock, flags); |
549 | 550 | ||
550 | format = wiinst->format; | 551 | format = wiinst->format; |
551 | format.id = val; | 552 | format.id = val; |
552 | 553 | ||
553 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | 554 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { |
554 | spin_unlock_irqrestore(&wiinst->lock, flags); | 555 | spin_unlock_irqrestore(&wiinst->lock, flags); |
555 | return -EINVAL; | 556 | return -EINVAL; |
556 | } | 557 | } |
557 | 558 | ||
558 | val = wiinst->format.id; | 559 | val = wiinst->format.id; |
559 | 560 | ||
560 | spin_unlock_irqrestore(&wiinst->lock, flags); | 561 | spin_unlock_irqrestore(&wiinst->lock, flags); |
561 | DPD(2, "set recording format -> %d\n", val); | 562 | DPD(2, "set recording format -> %d\n", val); |
562 | } | 563 | } |
563 | 564 | ||
564 | if (file->f_mode & FMODE_WRITE) { | 565 | if (file->f_mode & FMODE_WRITE) { |
565 | struct wave_format format; | 566 | struct wave_format format; |
566 | 567 | ||
567 | spin_lock_irqsave(&woinst->lock, flags); | 568 | spin_lock_irqsave(&woinst->lock, flags); |
568 | 569 | ||
569 | format = woinst->format; | 570 | format = woinst->format; |
570 | format.id = val; | 571 | format.id = val; |
571 | 572 | ||
572 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | 573 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { |
573 | spin_unlock_irqrestore(&woinst->lock, flags); | 574 | spin_unlock_irqrestore(&woinst->lock, flags); |
574 | return -EINVAL; | 575 | return -EINVAL; |
575 | } | 576 | } |
576 | 577 | ||
577 | val = woinst->format.id; | 578 | val = woinst->format.id; |
578 | 579 | ||
579 | spin_unlock_irqrestore(&woinst->lock, flags); | 580 | spin_unlock_irqrestore(&woinst->lock, flags); |
580 | DPD(2, "set playback format -> %d\n", val); | 581 | DPD(2, "set playback format -> %d\n", val); |
581 | } | 582 | } |
582 | 583 | ||
583 | return put_user(val, p); | 584 | return put_user(val, p); |
584 | } else { | 585 | } else { |
585 | if (file->f_mode & FMODE_READ) | 586 | if (file->f_mode & FMODE_READ) |
586 | val = wiinst->format.id; | 587 | val = wiinst->format.id; |
587 | else if (file->f_mode & FMODE_WRITE) | 588 | else if (file->f_mode & FMODE_WRITE) |
588 | val = woinst->format.id; | 589 | val = woinst->format.id; |
589 | 590 | ||
590 | return put_user(val, p); | 591 | return put_user(val, p); |
591 | } | 592 | } |
592 | break; | 593 | break; |
593 | 594 | ||
594 | case SOUND_PCM_READ_BITS: | 595 | case SOUND_PCM_READ_BITS: |
595 | 596 | ||
596 | if (file->f_mode & FMODE_READ) | 597 | if (file->f_mode & FMODE_READ) |
597 | val = wiinst->format.bitsperchannel; | 598 | val = wiinst->format.bitsperchannel; |
598 | else if (file->f_mode & FMODE_WRITE) | 599 | else if (file->f_mode & FMODE_WRITE) |
599 | val = woinst->format.bitsperchannel; | 600 | val = woinst->format.bitsperchannel; |
600 | 601 | ||
601 | return put_user(val, p); | 602 | return put_user(val, p); |
602 | 603 | ||
603 | case SOUND_PCM_READ_RATE: | 604 | case SOUND_PCM_READ_RATE: |
604 | 605 | ||
605 | if (file->f_mode & FMODE_READ) | 606 | if (file->f_mode & FMODE_READ) |
606 | val = wiinst->format.samplingrate; | 607 | val = wiinst->format.samplingrate; |
607 | else if (file->f_mode & FMODE_WRITE) | 608 | else if (file->f_mode & FMODE_WRITE) |
608 | val = woinst->format.samplingrate; | 609 | val = woinst->format.samplingrate; |
609 | 610 | ||
610 | return put_user(val, p); | 611 | return put_user(val, p); |
611 | 612 | ||
612 | case SOUND_PCM_READ_CHANNELS: | 613 | case SOUND_PCM_READ_CHANNELS: |
613 | 614 | ||
614 | if (file->f_mode & FMODE_READ) | 615 | if (file->f_mode & FMODE_READ) |
615 | val = wiinst->format.channels; | 616 | val = wiinst->format.channels; |
616 | else if (file->f_mode & FMODE_WRITE) | 617 | else if (file->f_mode & FMODE_WRITE) |
617 | val = woinst->format.channels; | 618 | val = woinst->format.channels; |
618 | 619 | ||
619 | return put_user(val, p); | 620 | return put_user(val, p); |
620 | 621 | ||
621 | case SOUND_PCM_WRITE_FILTER: | 622 | case SOUND_PCM_WRITE_FILTER: |
622 | DPF(2, "SOUND_PCM_WRITE_FILTER: not implemented\n"); | 623 | DPF(2, "SOUND_PCM_WRITE_FILTER: not implemented\n"); |
623 | break; | 624 | break; |
624 | 625 | ||
625 | case SOUND_PCM_READ_FILTER: | 626 | case SOUND_PCM_READ_FILTER: |
626 | DPF(2, "SOUND_PCM_READ_FILTER: not implemented\n"); | 627 | DPF(2, "SOUND_PCM_READ_FILTER: not implemented\n"); |
627 | break; | 628 | break; |
628 | 629 | ||
629 | case SNDCTL_DSP_SETSYNCRO: | 630 | case SNDCTL_DSP_SETSYNCRO: |
630 | DPF(2, "SNDCTL_DSP_SETSYNCRO: not implemented\n"); | 631 | DPF(2, "SNDCTL_DSP_SETSYNCRO: not implemented\n"); |
631 | break; | 632 | break; |
632 | 633 | ||
633 | case SNDCTL_DSP_GETTRIGGER: | 634 | case SNDCTL_DSP_GETTRIGGER: |
634 | DPF(2, "SNDCTL_DSP_GETTRIGGER:\n"); | 635 | DPF(2, "SNDCTL_DSP_GETTRIGGER:\n"); |
635 | 636 | ||
636 | if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)) | 637 | if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)) |
637 | val |= PCM_ENABLE_OUTPUT; | 638 | val |= PCM_ENABLE_OUTPUT; |
638 | 639 | ||
639 | if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT)) | 640 | if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT)) |
640 | val |= PCM_ENABLE_INPUT; | 641 | val |= PCM_ENABLE_INPUT; |
641 | 642 | ||
642 | return put_user(val, p); | 643 | return put_user(val, p); |
643 | 644 | ||
644 | case SNDCTL_DSP_SETTRIGGER: | 645 | case SNDCTL_DSP_SETTRIGGER: |
645 | DPF(2, "SNDCTL_DSP_SETTRIGGER:\n"); | 646 | DPF(2, "SNDCTL_DSP_SETTRIGGER:\n"); |
646 | 647 | ||
647 | if (get_user(val, p)) | 648 | if (get_user(val, p)) |
648 | return -EFAULT; | 649 | return -EFAULT; |
649 | 650 | ||
650 | if (file->f_mode & FMODE_WRITE) { | 651 | if (file->f_mode & FMODE_WRITE) { |
651 | spin_lock_irqsave(&woinst->lock, flags); | 652 | spin_lock_irqsave(&woinst->lock, flags); |
652 | 653 | ||
653 | if (val & PCM_ENABLE_OUTPUT) { | 654 | if (val & PCM_ENABLE_OUTPUT) { |
654 | wave_dev->enablebits |= PCM_ENABLE_OUTPUT; | 655 | wave_dev->enablebits |= PCM_ENABLE_OUTPUT; |
655 | if (woinst->state & WAVE_STATE_OPEN) | 656 | if (woinst->state & WAVE_STATE_OPEN) |
656 | emu10k1_waveout_start(wave_dev); | 657 | emu10k1_waveout_start(wave_dev); |
657 | } else { | 658 | } else { |
658 | wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT; | 659 | wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT; |
659 | if (woinst->state & WAVE_STATE_STARTED) | 660 | if (woinst->state & WAVE_STATE_STARTED) |
660 | emu10k1_waveout_stop(wave_dev); | 661 | emu10k1_waveout_stop(wave_dev); |
661 | } | 662 | } |
662 | 663 | ||
663 | spin_unlock_irqrestore(&woinst->lock, flags); | 664 | spin_unlock_irqrestore(&woinst->lock, flags); |
664 | } | 665 | } |
665 | 666 | ||
666 | if (file->f_mode & FMODE_READ) { | 667 | if (file->f_mode & FMODE_READ) { |
667 | spin_lock_irqsave(&wiinst->lock, flags); | 668 | spin_lock_irqsave(&wiinst->lock, flags); |
668 | 669 | ||
669 | if (val & PCM_ENABLE_INPUT) { | 670 | if (val & PCM_ENABLE_INPUT) { |
670 | wave_dev->enablebits |= PCM_ENABLE_INPUT; | 671 | wave_dev->enablebits |= PCM_ENABLE_INPUT; |
671 | if (wiinst->state & WAVE_STATE_OPEN) | 672 | if (wiinst->state & WAVE_STATE_OPEN) |
672 | emu10k1_wavein_start(wave_dev); | 673 | emu10k1_wavein_start(wave_dev); |
673 | } else { | 674 | } else { |
674 | wave_dev->enablebits &= ~PCM_ENABLE_INPUT; | 675 | wave_dev->enablebits &= ~PCM_ENABLE_INPUT; |
675 | if (wiinst->state & WAVE_STATE_STARTED) | 676 | if (wiinst->state & WAVE_STATE_STARTED) |
676 | emu10k1_wavein_stop(wave_dev); | 677 | emu10k1_wavein_stop(wave_dev); |
677 | } | 678 | } |
678 | 679 | ||
679 | spin_unlock_irqrestore(&wiinst->lock, flags); | 680 | spin_unlock_irqrestore(&wiinst->lock, flags); |
680 | } | 681 | } |
681 | break; | 682 | break; |
682 | 683 | ||
683 | case SNDCTL_DSP_GETOSPACE: | 684 | case SNDCTL_DSP_GETOSPACE: |
684 | { | 685 | { |
685 | audio_buf_info info; | 686 | audio_buf_info info; |
686 | 687 | ||
687 | DPF(4, "SNDCTL_DSP_GETOSPACE:\n"); | 688 | DPF(4, "SNDCTL_DSP_GETOSPACE:\n"); |
688 | 689 | ||
689 | if (!(file->f_mode & FMODE_WRITE)) | 690 | if (!(file->f_mode & FMODE_WRITE)) |
690 | return -EINVAL; | 691 | return -EINVAL; |
691 | 692 | ||
692 | spin_lock_irqsave(&woinst->lock, flags); | 693 | spin_lock_irqsave(&woinst->lock, flags); |
693 | 694 | ||
694 | if (woinst->state & WAVE_STATE_OPEN) { | 695 | if (woinst->state & WAVE_STATE_OPEN) { |
695 | emu10k1_waveout_update(woinst); | 696 | emu10k1_waveout_update(woinst); |
696 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | 697 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); |
697 | info.bytes = bytestocopy; | 698 | info.bytes = bytestocopy; |
698 | } else { | 699 | } else { |
699 | calculate_ofrag(woinst); | 700 | calculate_ofrag(woinst); |
700 | info.bytes = woinst->buffer.size; | 701 | info.bytes = woinst->buffer.size; |
701 | } | 702 | } |
702 | spin_unlock_irqrestore(&woinst->lock, flags); | 703 | spin_unlock_irqrestore(&woinst->lock, flags); |
703 | 704 | ||
704 | info.bytes *= woinst->num_voices; | 705 | info.bytes *= woinst->num_voices; |
705 | info.fragsize = woinst->buffer.fragment_size * woinst->num_voices; | 706 | info.fragsize = woinst->buffer.fragment_size * woinst->num_voices; |
706 | info.fragstotal = woinst->buffer.numfrags * woinst->num_voices; | 707 | info.fragstotal = woinst->buffer.numfrags * woinst->num_voices; |
707 | info.fragments = info.bytes / info.fragsize; | 708 | info.fragments = info.bytes / info.fragsize; |
708 | 709 | ||
709 | if (copy_to_user(p, &info, sizeof(info))) | 710 | if (copy_to_user(p, &info, sizeof(info))) |
710 | return -EFAULT; | 711 | return -EFAULT; |
711 | } | 712 | } |
712 | break; | 713 | break; |
713 | 714 | ||
714 | case SNDCTL_DSP_GETISPACE: | 715 | case SNDCTL_DSP_GETISPACE: |
715 | { | 716 | { |
716 | audio_buf_info info; | 717 | audio_buf_info info; |
717 | 718 | ||
718 | DPF(4, "SNDCTL_DSP_GETISPACE:\n"); | 719 | DPF(4, "SNDCTL_DSP_GETISPACE:\n"); |
719 | 720 | ||
720 | if (!(file->f_mode & FMODE_READ)) | 721 | if (!(file->f_mode & FMODE_READ)) |
721 | return -EINVAL; | 722 | return -EINVAL; |
722 | 723 | ||
723 | spin_lock_irqsave(&wiinst->lock, flags); | 724 | spin_lock_irqsave(&wiinst->lock, flags); |
724 | if (wiinst->state & WAVE_STATE_OPEN) { | 725 | if (wiinst->state & WAVE_STATE_OPEN) { |
725 | emu10k1_wavein_update(wave_dev->card, wiinst); | 726 | emu10k1_wavein_update(wave_dev->card, wiinst); |
726 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | 727 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); |
727 | info.bytes = bytestocopy; | 728 | info.bytes = bytestocopy; |
728 | } else { | 729 | } else { |
729 | calculate_ifrag(wiinst); | 730 | calculate_ifrag(wiinst); |
730 | info.bytes = 0; | 731 | info.bytes = 0; |
731 | } | 732 | } |
732 | spin_unlock_irqrestore(&wiinst->lock, flags); | 733 | spin_unlock_irqrestore(&wiinst->lock, flags); |
733 | 734 | ||
734 | info.fragstotal = wiinst->buffer.numfrags; | 735 | info.fragstotal = wiinst->buffer.numfrags; |
735 | info.fragments = info.bytes / wiinst->buffer.fragment_size; | 736 | info.fragments = info.bytes / wiinst->buffer.fragment_size; |
736 | info.fragsize = wiinst->buffer.fragment_size; | 737 | info.fragsize = wiinst->buffer.fragment_size; |
737 | 738 | ||
738 | if (copy_to_user(p, &info, sizeof(info))) | 739 | if (copy_to_user(p, &info, sizeof(info))) |
739 | return -EFAULT; | 740 | return -EFAULT; |
740 | } | 741 | } |
741 | break; | 742 | break; |
742 | 743 | ||
743 | case SNDCTL_DSP_NONBLOCK: | 744 | case SNDCTL_DSP_NONBLOCK: |
744 | DPF(2, "SNDCTL_DSP_NONBLOCK:\n"); | 745 | DPF(2, "SNDCTL_DSP_NONBLOCK:\n"); |
745 | 746 | ||
746 | file->f_flags |= O_NONBLOCK; | 747 | file->f_flags |= O_NONBLOCK; |
747 | break; | 748 | break; |
748 | 749 | ||
749 | case SNDCTL_DSP_GETODELAY: | 750 | case SNDCTL_DSP_GETODELAY: |
750 | DPF(4, "SNDCTL_DSP_GETODELAY:\n"); | 751 | DPF(4, "SNDCTL_DSP_GETODELAY:\n"); |
751 | 752 | ||
752 | if (!(file->f_mode & FMODE_WRITE)) | 753 | if (!(file->f_mode & FMODE_WRITE)) |
753 | return -EINVAL; | 754 | return -EINVAL; |
754 | 755 | ||
755 | spin_lock_irqsave(&woinst->lock, flags); | 756 | spin_lock_irqsave(&woinst->lock, flags); |
756 | if (woinst->state & WAVE_STATE_OPEN) { | 757 | if (woinst->state & WAVE_STATE_OPEN) { |
757 | emu10k1_waveout_update(woinst); | 758 | emu10k1_waveout_update(woinst); |
758 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | 759 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); |
759 | val = woinst->buffer.size - bytestocopy; | 760 | val = woinst->buffer.size - bytestocopy; |
760 | } else | 761 | } else |
761 | val = 0; | 762 | val = 0; |
762 | 763 | ||
763 | val *= woinst->num_voices; | 764 | val *= woinst->num_voices; |
764 | spin_unlock_irqrestore(&woinst->lock, flags); | 765 | spin_unlock_irqrestore(&woinst->lock, flags); |
765 | 766 | ||
766 | return put_user(val, p); | 767 | return put_user(val, p); |
767 | 768 | ||
768 | case SNDCTL_DSP_GETIPTR: | 769 | case SNDCTL_DSP_GETIPTR: |
769 | { | 770 | { |
770 | count_info cinfo; | 771 | count_info cinfo; |
771 | 772 | ||
772 | DPF(4, "SNDCTL_DSP_GETIPTR: \n"); | 773 | DPF(4, "SNDCTL_DSP_GETIPTR: \n"); |
773 | 774 | ||
774 | if (!(file->f_mode & FMODE_READ)) | 775 | if (!(file->f_mode & FMODE_READ)) |
775 | return -EINVAL; | 776 | return -EINVAL; |
776 | 777 | ||
777 | spin_lock_irqsave(&wiinst->lock, flags); | 778 | spin_lock_irqsave(&wiinst->lock, flags); |
778 | 779 | ||
779 | if (wiinst->state & WAVE_STATE_OPEN) { | 780 | if (wiinst->state & WAVE_STATE_OPEN) { |
780 | emu10k1_wavein_update(wave_dev->card, wiinst); | 781 | emu10k1_wavein_update(wave_dev->card, wiinst); |
781 | cinfo.ptr = wiinst->buffer.hw_pos; | 782 | cinfo.ptr = wiinst->buffer.hw_pos; |
782 | cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size; | 783 | cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size; |
783 | cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks; | 784 | cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks; |
784 | wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size; | 785 | wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size; |
785 | } else { | 786 | } else { |
786 | cinfo.ptr = 0; | 787 | cinfo.ptr = 0; |
787 | cinfo.bytes = 0; | 788 | cinfo.bytes = 0; |
788 | cinfo.blocks = 0; | 789 | cinfo.blocks = 0; |
789 | } | 790 | } |
790 | 791 | ||
791 | if (wiinst->mmapped) | 792 | if (wiinst->mmapped) |
792 | wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size; | 793 | wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size; |
793 | 794 | ||
794 | spin_unlock_irqrestore(&wiinst->lock, flags); | 795 | spin_unlock_irqrestore(&wiinst->lock, flags); |
795 | 796 | ||
796 | if (copy_to_user(p, &cinfo, sizeof(cinfo))) | 797 | if (copy_to_user(p, &cinfo, sizeof(cinfo))) |
797 | return -EFAULT; | 798 | return -EFAULT; |
798 | } | 799 | } |
799 | break; | 800 | break; |
800 | 801 | ||
801 | case SNDCTL_DSP_GETOPTR: | 802 | case SNDCTL_DSP_GETOPTR: |
802 | { | 803 | { |
803 | count_info cinfo; | 804 | count_info cinfo; |
804 | 805 | ||
805 | DPF(4, "SNDCTL_DSP_GETOPTR:\n"); | 806 | DPF(4, "SNDCTL_DSP_GETOPTR:\n"); |
806 | 807 | ||
807 | if (!(file->f_mode & FMODE_WRITE)) | 808 | if (!(file->f_mode & FMODE_WRITE)) |
808 | return -EINVAL; | 809 | return -EINVAL; |
809 | 810 | ||
810 | spin_lock_irqsave(&woinst->lock, flags); | 811 | spin_lock_irqsave(&woinst->lock, flags); |
811 | 812 | ||
812 | if (woinst->state & WAVE_STATE_OPEN || | 813 | if (woinst->state & WAVE_STATE_OPEN || |
813 | ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) { | 814 | ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) { |
814 | int num_fragments; | 815 | int num_fragments; |
815 | 816 | ||
816 | if (woinst->format.passthrough == 1) { | 817 | if (woinst->format.passthrough == 1) { |
817 | emu10k1_pt_waveout_update(wave_dev); | 818 | emu10k1_pt_waveout_update(wave_dev); |
818 | cinfo.bytes = woinst->total_played; | 819 | cinfo.bytes = woinst->total_played; |
819 | } else { | 820 | } else { |
820 | emu10k1_waveout_update(woinst); | 821 | emu10k1_waveout_update(woinst); |
821 | cinfo.bytes = woinst->total_played; | 822 | cinfo.bytes = woinst->total_played; |
822 | } | 823 | } |
823 | 824 | ||
824 | cinfo.ptr = woinst->buffer.hw_pos; | 825 | cinfo.ptr = woinst->buffer.hw_pos; |
825 | num_fragments = cinfo.bytes / woinst->buffer.fragment_size; | 826 | num_fragments = cinfo.bytes / woinst->buffer.fragment_size; |
826 | cinfo.blocks = num_fragments - woinst->blocks; | 827 | cinfo.blocks = num_fragments - woinst->blocks; |
827 | woinst->blocks = num_fragments; | 828 | woinst->blocks = num_fragments; |
828 | 829 | ||
829 | cinfo.bytes *= woinst->num_voices; | 830 | cinfo.bytes *= woinst->num_voices; |
830 | cinfo.ptr *= woinst->num_voices; | 831 | cinfo.ptr *= woinst->num_voices; |
831 | } else { | 832 | } else { |
832 | cinfo.ptr = 0; | 833 | cinfo.ptr = 0; |
833 | cinfo.bytes = 0; | 834 | cinfo.bytes = 0; |
834 | cinfo.blocks = 0; | 835 | cinfo.blocks = 0; |
835 | } | 836 | } |
836 | 837 | ||
837 | if (woinst->mmapped) | 838 | if (woinst->mmapped) |
838 | woinst->buffer.free_bytes %= woinst->buffer.fragment_size; | 839 | woinst->buffer.free_bytes %= woinst->buffer.fragment_size; |
839 | 840 | ||
840 | spin_unlock_irqrestore(&woinst->lock, flags); | 841 | spin_unlock_irqrestore(&woinst->lock, flags); |
841 | 842 | ||
842 | if (copy_to_user(p, &cinfo, sizeof(cinfo))) | 843 | if (copy_to_user(p, &cinfo, sizeof(cinfo))) |
843 | return -EFAULT; | 844 | return -EFAULT; |
844 | } | 845 | } |
845 | break; | 846 | break; |
846 | 847 | ||
847 | case SNDCTL_DSP_GETBLKSIZE: | 848 | case SNDCTL_DSP_GETBLKSIZE: |
848 | DPF(2, "SNDCTL_DSP_GETBLKSIZE:\n"); | 849 | DPF(2, "SNDCTL_DSP_GETBLKSIZE:\n"); |
849 | 850 | ||
850 | if (file->f_mode & FMODE_WRITE) { | 851 | if (file->f_mode & FMODE_WRITE) { |
851 | spin_lock_irqsave(&woinst->lock, flags); | 852 | spin_lock_irqsave(&woinst->lock, flags); |
852 | 853 | ||
853 | calculate_ofrag(woinst); | 854 | calculate_ofrag(woinst); |
854 | val = woinst->buffer.fragment_size * woinst->num_voices; | 855 | val = woinst->buffer.fragment_size * woinst->num_voices; |
855 | 856 | ||
856 | spin_unlock_irqrestore(&woinst->lock, flags); | 857 | spin_unlock_irqrestore(&woinst->lock, flags); |
857 | } | 858 | } |
858 | 859 | ||
859 | if (file->f_mode & FMODE_READ) { | 860 | if (file->f_mode & FMODE_READ) { |
860 | spin_lock_irqsave(&wiinst->lock, flags); | 861 | spin_lock_irqsave(&wiinst->lock, flags); |
861 | 862 | ||
862 | calculate_ifrag(wiinst); | 863 | calculate_ifrag(wiinst); |
863 | val = wiinst->buffer.fragment_size; | 864 | val = wiinst->buffer.fragment_size; |
864 | 865 | ||
865 | spin_unlock_irqrestore(&wiinst->lock, flags); | 866 | spin_unlock_irqrestore(&wiinst->lock, flags); |
866 | } | 867 | } |
867 | 868 | ||
868 | return put_user(val, p); | 869 | return put_user(val, p); |
869 | 870 | ||
870 | break; | 871 | break; |
871 | 872 | ||
872 | case SNDCTL_DSP_POST: | 873 | case SNDCTL_DSP_POST: |
873 | if (file->f_mode & FMODE_WRITE) { | 874 | if (file->f_mode & FMODE_WRITE) { |
874 | spin_lock_irqsave(&woinst->lock, flags); | 875 | spin_lock_irqsave(&woinst->lock, flags); |
875 | 876 | ||
876 | if (!(woinst->state & WAVE_STATE_STARTED) | 877 | if (!(woinst->state & WAVE_STATE_STARTED) |
877 | && (wave_dev->enablebits & PCM_ENABLE_OUTPUT) | 878 | && (wave_dev->enablebits & PCM_ENABLE_OUTPUT) |
878 | && (woinst->total_copied > 0)) | 879 | && (woinst->total_copied > 0)) |
879 | emu10k1_waveout_start(wave_dev); | 880 | emu10k1_waveout_start(wave_dev); |
880 | 881 | ||
881 | spin_unlock_irqrestore(&woinst->lock, flags); | 882 | spin_unlock_irqrestore(&woinst->lock, flags); |
882 | } | 883 | } |
883 | 884 | ||
884 | break; | 885 | break; |
885 | 886 | ||
886 | case SNDCTL_DSP_SUBDIVIDE: | 887 | case SNDCTL_DSP_SUBDIVIDE: |
887 | DPF(2, "SNDCTL_DSP_SUBDIVIDE: not implemented\n"); | 888 | DPF(2, "SNDCTL_DSP_SUBDIVIDE: not implemented\n"); |
888 | break; | 889 | break; |
889 | 890 | ||
890 | case SNDCTL_DSP_SETFRAGMENT: | 891 | case SNDCTL_DSP_SETFRAGMENT: |
891 | DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n"); | 892 | DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n"); |
892 | 893 | ||
893 | if (get_user(val, p)) | 894 | if (get_user(val, p)) |
894 | return -EFAULT; | 895 | return -EFAULT; |
895 | 896 | ||
896 | DPD(2, "val is %#x\n", val); | 897 | DPD(2, "val is %#x\n", val); |
897 | 898 | ||
898 | if (val == 0) | 899 | if (val == 0) |
899 | return -EIO; | 900 | return -EIO; |
900 | 901 | ||
901 | if (file->f_mode & FMODE_WRITE) { | 902 | if (file->f_mode & FMODE_WRITE) { |
902 | /* digital pass-through fragment count and size are fixed values */ | 903 | /* digital pass-through fragment count and size are fixed values */ |
903 | if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough == 1)) | 904 | if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough == 1)) |
904 | return -EINVAL; /* too late to change */ | 905 | return -EINVAL; /* too late to change */ |
905 | 906 | ||
906 | woinst->buffer.ossfragshift = val & 0xffff; | 907 | woinst->buffer.ossfragshift = val & 0xffff; |
907 | woinst->buffer.numfrags = (val >> 16) & 0xffff; | 908 | woinst->buffer.numfrags = (val >> 16) & 0xffff; |
908 | } | 909 | } |
909 | 910 | ||
910 | if (file->f_mode & FMODE_READ) { | 911 | if (file->f_mode & FMODE_READ) { |
911 | if (wiinst->state & WAVE_STATE_OPEN) | 912 | if (wiinst->state & WAVE_STATE_OPEN) |
912 | return -EINVAL; /* too late to change */ | 913 | return -EINVAL; /* too late to change */ |
913 | 914 | ||
914 | wiinst->buffer.ossfragshift = val & 0xffff; | 915 | wiinst->buffer.ossfragshift = val & 0xffff; |
915 | wiinst->buffer.numfrags = (val >> 16) & 0xffff; | 916 | wiinst->buffer.numfrags = (val >> 16) & 0xffff; |
916 | } | 917 | } |
917 | 918 | ||
918 | break; | 919 | break; |
919 | 920 | ||
920 | case SNDCTL_COPR_LOAD: | 921 | case SNDCTL_COPR_LOAD: |
921 | { | 922 | { |
922 | copr_buffer *buf; | 923 | copr_buffer *buf; |
923 | u32 i; | 924 | u32 i; |
924 | 925 | ||
925 | DPF(4, "SNDCTL_COPR_LOAD:\n"); | 926 | DPF(4, "SNDCTL_COPR_LOAD:\n"); |
926 | 927 | ||
927 | buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL); | 928 | buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL); |
928 | if (!buf) | 929 | if (!buf) |
929 | return -ENOMEM; | 930 | return -ENOMEM; |
930 | 931 | ||
931 | if (copy_from_user(buf, p, sizeof(copr_buffer))) { | 932 | if (copy_from_user(buf, p, sizeof(copr_buffer))) { |
932 | kfree (buf); | 933 | kfree (buf); |
933 | return -EFAULT; | 934 | return -EFAULT; |
934 | } | 935 | } |
935 | 936 | ||
936 | if ((buf->command != CMD_READ) && (buf->command != CMD_WRITE)) { | 937 | if ((buf->command != CMD_READ) && (buf->command != CMD_WRITE)) { |
937 | kfree (buf); | 938 | kfree (buf); |
938 | return -EINVAL; | 939 | return -EINVAL; |
939 | } | 940 | } |
940 | 941 | ||
941 | if (buf->command == CMD_WRITE) { | 942 | if (buf->command == CMD_WRITE) { |
942 | 943 | ||
943 | #ifdef DBGEMU | 944 | #ifdef DBGEMU |
944 | if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { | 945 | if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { |
945 | #else | 946 | #else |
946 | if (((buf->offs < 0x100) || (buf->offs + buf->len > (wave_dev->card->is_audigy ? 0xe00 : 0x800)) || (buf->len > 1000) | 947 | if (((buf->offs < 0x100) || (buf->offs + buf->len > (wave_dev->card->is_audigy ? 0xe00 : 0x800)) || (buf->len > 1000) |
947 | ) && !( | 948 | ) && !( |
948 | //any register allowed raw access to users goes here: | 949 | //any register allowed raw access to users goes here: |
949 | (buf->offs == DBG || | 950 | (buf->offs == DBG || |
950 | buf->offs == A_DBG) | 951 | buf->offs == A_DBG) |
951 | && (buf->len == 1))) { | 952 | && (buf->len == 1))) { |
952 | #endif | 953 | #endif |
953 | kfree(buf); | 954 | kfree(buf); |
954 | return -EINVAL; | 955 | return -EINVAL; |
955 | } | 956 | } |
956 | } else { | 957 | } else { |
957 | if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { | 958 | if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { |
958 | kfree(buf); | 959 | kfree(buf); |
959 | return -EINVAL; | 960 | return -EINVAL; |
960 | } | 961 | } |
961 | } | 962 | } |
962 | 963 | ||
963 | if (((unsigned)buf->flags) > 0x3f) | 964 | if (((unsigned)buf->flags) > 0x3f) |
964 | buf->flags = 0; | 965 | buf->flags = 0; |
965 | 966 | ||
966 | if (buf->command == CMD_READ) { | 967 | if (buf->command == CMD_READ) { |
967 | for (i = 0; i < buf->len; i++) | 968 | for (i = 0; i < buf->len; i++) |
968 | ((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags); | 969 | ((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags); |
969 | 970 | ||
970 | if (copy_to_user(p, buf, sizeof(copr_buffer))) { | 971 | if (copy_to_user(p, buf, sizeof(copr_buffer))) { |
971 | kfree(buf); | 972 | kfree(buf); |
972 | return -EFAULT; | 973 | return -EFAULT; |
973 | } | 974 | } |
974 | } else { | 975 | } else { |
975 | for (i = 0; i < buf->len; i++) | 976 | for (i = 0; i < buf->len; i++) |
976 | sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]); | 977 | sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]); |
977 | } | 978 | } |
978 | 979 | ||
979 | kfree (buf); | 980 | kfree (buf); |
980 | break; | 981 | break; |
981 | } | 982 | } |
982 | 983 | ||
983 | default: /* Default is unrecognized command */ | 984 | default: /* Default is unrecognized command */ |
984 | DPD(2, "default: %#x\n", cmd); | 985 | DPD(2, "default: %#x\n", cmd); |
985 | return -EINVAL; | 986 | return -EINVAL; |
986 | } | 987 | } |
987 | return 0; | 988 | return 0; |
988 | } | 989 | } |
989 | 990 | ||
990 | static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type) | 991 | static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type) |
991 | { | 992 | { |
992 | struct emu10k1_wavedevice *wave_dev = vma->vm_private_data; | 993 | struct emu10k1_wavedevice *wave_dev = vma->vm_private_data; |
993 | struct woinst *woinst = wave_dev->woinst; | 994 | struct woinst *woinst = wave_dev->woinst; |
994 | struct wiinst *wiinst = wave_dev->wiinst; | 995 | struct wiinst *wiinst = wave_dev->wiinst; |
995 | struct page *dmapage; | 996 | struct page *dmapage; |
996 | unsigned long pgoff; | 997 | unsigned long pgoff; |
997 | int rd, wr; | 998 | int rd, wr; |
998 | 999 | ||
999 | DPF(3, "emu10k1_mm_nopage()\n"); | 1000 | DPF(3, "emu10k1_mm_nopage()\n"); |
1000 | DPD(3, "addr: %#lx\n", address); | 1001 | DPD(3, "addr: %#lx\n", address); |
1001 | 1002 | ||
1002 | if (address > vma->vm_end) { | 1003 | if (address > vma->vm_end) { |
1003 | DPF(1, "EXIT, returning NOPAGE_SIGBUS\n"); | 1004 | DPF(1, "EXIT, returning NOPAGE_SIGBUS\n"); |
1004 | return NOPAGE_SIGBUS; /* Disallow mremap */ | 1005 | return NOPAGE_SIGBUS; /* Disallow mremap */ |
1005 | } | 1006 | } |
1006 | 1007 | ||
1007 | pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT); | 1008 | pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT); |
1008 | if (woinst != NULL) | 1009 | if (woinst != NULL) |
1009 | wr = woinst->mmapped; | 1010 | wr = woinst->mmapped; |
1010 | else | 1011 | else |
1011 | wr = 0; | 1012 | wr = 0; |
1012 | 1013 | ||
1013 | if (wiinst != NULL) | 1014 | if (wiinst != NULL) |
1014 | rd = wiinst->mmapped; | 1015 | rd = wiinst->mmapped; |
1015 | else | 1016 | else |
1016 | rd = 0; | 1017 | rd = 0; |
1017 | 1018 | ||
1018 | /* if full-duplex (read+write) and we have two sets of bufs, | 1019 | /* if full-duplex (read+write) and we have two sets of bufs, |
1019 | * then the playback buffers come first, sez soundcard.c */ | 1020 | * then the playback buffers come first, sez soundcard.c */ |
1020 | if (wr) { | 1021 | if (wr) { |
1021 | if (pgoff >= woinst->buffer.pages) { | 1022 | if (pgoff >= woinst->buffer.pages) { |
1022 | pgoff -= woinst->buffer.pages; | 1023 | pgoff -= woinst->buffer.pages; |
1023 | dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); | 1024 | dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); |
1024 | } else | 1025 | } else |
1025 | dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]); | 1026 | dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]); |
1026 | } else { | 1027 | } else { |
1027 | dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); | 1028 | dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); |
1028 | } | 1029 | } |
1029 | 1030 | ||
1030 | get_page (dmapage); | 1031 | get_page (dmapage); |
1031 | 1032 | ||
1032 | DPD(3, "page: %#lx\n", (unsigned long) dmapage); | 1033 | DPD(3, "page: %#lx\n", (unsigned long) dmapage); |
1033 | if (type) | 1034 | if (type) |
1034 | *type = VM_FAULT_MINOR; | 1035 | *type = VM_FAULT_MINOR; |
1035 | return dmapage; | 1036 | return dmapage; |
1036 | } | 1037 | } |
1037 | 1038 | ||
1038 | static struct vm_operations_struct emu10k1_mm_ops = { | 1039 | static struct vm_operations_struct emu10k1_mm_ops = { |
1039 | .nopage = emu10k1_mm_nopage, | 1040 | .nopage = emu10k1_mm_nopage, |
1040 | }; | 1041 | }; |
1041 | 1042 | ||
1042 | static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma) | 1043 | static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma) |
1043 | { | 1044 | { |
1044 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | 1045 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; |
1045 | unsigned long max_pages, n_pages, pgoffset; | 1046 | unsigned long max_pages, n_pages, pgoffset; |
1046 | struct woinst *woinst = NULL; | 1047 | struct woinst *woinst = NULL; |
1047 | struct wiinst *wiinst = NULL; | 1048 | struct wiinst *wiinst = NULL; |
1048 | unsigned long flags; | 1049 | unsigned long flags; |
1049 | 1050 | ||
1050 | DPF(2, "emu10k1_audio_mmap()\n"); | 1051 | DPF(2, "emu10k1_audio_mmap()\n"); |
1051 | 1052 | ||
1052 | max_pages = 0; | 1053 | max_pages = 0; |
1053 | if (vma->vm_flags & VM_WRITE) { | 1054 | if (vma->vm_flags & VM_WRITE) { |
1054 | woinst = wave_dev->woinst; | 1055 | woinst = wave_dev->woinst; |
1055 | 1056 | ||
1056 | spin_lock_irqsave(&woinst->lock, flags); | 1057 | spin_lock_irqsave(&woinst->lock, flags); |
1057 | 1058 | ||
1058 | /* No m'mapping possible for multichannel */ | 1059 | /* No m'mapping possible for multichannel */ |
1059 | if (woinst->num_voices > 1) { | 1060 | if (woinst->num_voices > 1) { |
1060 | spin_unlock_irqrestore(&woinst->lock, flags); | 1061 | spin_unlock_irqrestore(&woinst->lock, flags); |
1061 | return -EINVAL; | 1062 | return -EINVAL; |
1062 | } | 1063 | } |
1063 | 1064 | ||
1064 | if (woinst->state == WAVE_STATE_CLOSED) { | 1065 | if (woinst->state == WAVE_STATE_CLOSED) { |
1065 | calculate_ofrag(woinst); | 1066 | calculate_ofrag(woinst); |
1066 | 1067 | ||
1067 | if (emu10k1_waveout_open(wave_dev) < 0) { | 1068 | if (emu10k1_waveout_open(wave_dev) < 0) { |
1068 | spin_unlock_irqrestore(&woinst->lock, flags); | 1069 | spin_unlock_irqrestore(&woinst->lock, flags); |
1069 | ERROR(); | 1070 | ERROR(); |
1070 | return -EINVAL; | 1071 | return -EINVAL; |
1071 | } | 1072 | } |
1072 | } | 1073 | } |
1073 | 1074 | ||
1074 | woinst->mmapped = 1; | 1075 | woinst->mmapped = 1; |
1075 | max_pages += woinst->buffer.pages; | 1076 | max_pages += woinst->buffer.pages; |
1076 | spin_unlock_irqrestore(&woinst->lock, flags); | 1077 | spin_unlock_irqrestore(&woinst->lock, flags); |
1077 | } | 1078 | } |
1078 | 1079 | ||
1079 | if (vma->vm_flags & VM_READ) { | 1080 | if (vma->vm_flags & VM_READ) { |
1080 | wiinst = wave_dev->wiinst; | 1081 | wiinst = wave_dev->wiinst; |
1081 | 1082 | ||
1082 | spin_lock_irqsave(&wiinst->lock, flags); | 1083 | spin_lock_irqsave(&wiinst->lock, flags); |
1083 | if (wiinst->state == WAVE_STATE_CLOSED) { | 1084 | if (wiinst->state == WAVE_STATE_CLOSED) { |
1084 | calculate_ifrag(wiinst); | 1085 | calculate_ifrag(wiinst); |
1085 | 1086 | ||
1086 | if (emu10k1_wavein_open(wave_dev) < 0) { | 1087 | if (emu10k1_wavein_open(wave_dev) < 0) { |
1087 | spin_unlock_irqrestore(&wiinst->lock, flags); | 1088 | spin_unlock_irqrestore(&wiinst->lock, flags); |
1088 | ERROR(); | 1089 | ERROR(); |
1089 | return -EINVAL; | 1090 | return -EINVAL; |
1090 | } | 1091 | } |
1091 | } | 1092 | } |
1092 | 1093 | ||
1093 | wiinst->mmapped = 1; | 1094 | wiinst->mmapped = 1; |
1094 | max_pages += wiinst->buffer.pages; | 1095 | max_pages += wiinst->buffer.pages; |
1095 | spin_unlock_irqrestore(&wiinst->lock, flags); | 1096 | spin_unlock_irqrestore(&wiinst->lock, flags); |
1096 | } | 1097 | } |
1097 | 1098 | ||
1098 | n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT; | 1099 | n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT; |
1099 | pgoffset = vma->vm_pgoff; | 1100 | pgoffset = vma->vm_pgoff; |
1100 | 1101 | ||
1101 | DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset); | 1102 | DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset); |
1102 | DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages); | 1103 | DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages); |
1103 | 1104 | ||
1104 | if (pgoffset + n_pages > max_pages) | 1105 | if (pgoffset + n_pages > max_pages) |
1105 | return -EINVAL; | 1106 | return -EINVAL; |
1106 | 1107 | ||
1107 | vma->vm_flags |= VM_RESERVED; | 1108 | vma->vm_flags |= VM_RESERVED; |
1108 | vma->vm_ops = &emu10k1_mm_ops; | 1109 | vma->vm_ops = &emu10k1_mm_ops; |
1109 | vma->vm_private_data = wave_dev; | 1110 | vma->vm_private_data = wave_dev; |
1110 | return 0; | 1111 | return 0; |
1111 | } | 1112 | } |
1112 | 1113 | ||
1113 | static int emu10k1_audio_open(struct inode *inode, struct file *file) | 1114 | static int emu10k1_audio_open(struct inode *inode, struct file *file) |
1114 | { | 1115 | { |
1115 | int minor = iminor(inode); | 1116 | int minor = iminor(inode); |
1116 | struct emu10k1_card *card = NULL; | 1117 | struct emu10k1_card *card = NULL; |
1117 | struct list_head *entry; | 1118 | struct list_head *entry; |
1118 | struct emu10k1_wavedevice *wave_dev; | 1119 | struct emu10k1_wavedevice *wave_dev; |
1119 | 1120 | ||
1120 | DPF(2, "emu10k1_audio_open()\n"); | 1121 | DPF(2, "emu10k1_audio_open()\n"); |
1121 | 1122 | ||
1122 | /* Check for correct device to open */ | 1123 | /* Check for correct device to open */ |
1123 | 1124 | ||
1124 | list_for_each(entry, &emu10k1_devs) { | 1125 | list_for_each(entry, &emu10k1_devs) { |
1125 | card = list_entry(entry, struct emu10k1_card, list); | 1126 | card = list_entry(entry, struct emu10k1_card, list); |
1126 | 1127 | ||
1127 | if (!((card->audio_dev ^ minor) & ~0xf) || !((card->audio_dev1 ^ minor) & ~0xf)) | 1128 | if (!((card->audio_dev ^ minor) & ~0xf) || !((card->audio_dev1 ^ minor) & ~0xf)) |
1128 | goto match; | 1129 | goto match; |
1129 | } | 1130 | } |
1130 | 1131 | ||
1131 | return -ENODEV; | 1132 | return -ENODEV; |
1132 | 1133 | ||
1133 | match: | 1134 | match: |
1134 | 1135 | ||
1135 | wave_dev = (struct emu10k1_wavedevice *) kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL); | 1136 | wave_dev = (struct emu10k1_wavedevice *) kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL); |
1136 | 1137 | ||
1137 | if (wave_dev == NULL) { | 1138 | if (wave_dev == NULL) { |
1138 | ERROR(); | 1139 | ERROR(); |
1139 | return -ENOMEM; | 1140 | return -ENOMEM; |
1140 | } | 1141 | } |
1141 | 1142 | ||
1142 | wave_dev->card = card; | 1143 | wave_dev->card = card; |
1143 | wave_dev->wiinst = NULL; | 1144 | wave_dev->wiinst = NULL; |
1144 | wave_dev->woinst = NULL; | 1145 | wave_dev->woinst = NULL; |
1145 | wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT; /* Default */ | 1146 | wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT; /* Default */ |
1146 | 1147 | ||
1147 | if (file->f_mode & FMODE_READ) { | 1148 | if (file->f_mode & FMODE_READ) { |
1148 | /* Recording */ | 1149 | /* Recording */ |
1149 | struct wiinst *wiinst; | 1150 | struct wiinst *wiinst; |
1150 | 1151 | ||
1151 | if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) { | 1152 | if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) { |
1152 | ERROR(); | 1153 | ERROR(); |
1153 | kfree(wave_dev); | 1154 | kfree(wave_dev); |
1154 | return -ENOMEM; | 1155 | return -ENOMEM; |
1155 | } | 1156 | } |
1156 | 1157 | ||
1157 | wiinst->recsrc = card->wavein.recsrc; | 1158 | wiinst->recsrc = card->wavein.recsrc; |
1158 | wiinst->fxwc = card->wavein.fxwc; | 1159 | wiinst->fxwc = card->wavein.fxwc; |
1159 | 1160 | ||
1160 | switch (wiinst->recsrc) { | 1161 | switch (wiinst->recsrc) { |
1161 | case WAVERECORD_AC97: | 1162 | case WAVERECORD_AC97: |
1162 | wiinst->format.id = AFMT_S16_LE; | 1163 | wiinst->format.id = AFMT_S16_LE; |
1163 | wiinst->format.samplingrate = 8000; | 1164 | wiinst->format.samplingrate = 8000; |
1164 | wiinst->format.bitsperchannel = 16; | 1165 | wiinst->format.bitsperchannel = 16; |
1165 | wiinst->format.channels = 1; | 1166 | wiinst->format.channels = 1; |
1166 | break; | 1167 | break; |
1167 | case WAVERECORD_MIC: | 1168 | case WAVERECORD_MIC: |
1168 | wiinst->format.id = AFMT_S16_LE; | 1169 | wiinst->format.id = AFMT_S16_LE; |
1169 | wiinst->format.samplingrate = 8000; | 1170 | wiinst->format.samplingrate = 8000; |
1170 | wiinst->format.bitsperchannel = 16; | 1171 | wiinst->format.bitsperchannel = 16; |
1171 | wiinst->format.channels = 1; | 1172 | wiinst->format.channels = 1; |
1172 | break; | 1173 | break; |
1173 | case WAVERECORD_FX: | 1174 | case WAVERECORD_FX: |
1174 | wiinst->format.id = AFMT_S16_LE; | 1175 | wiinst->format.id = AFMT_S16_LE; |
1175 | wiinst->format.samplingrate = 48000; | 1176 | wiinst->format.samplingrate = 48000; |
1176 | wiinst->format.bitsperchannel = 16; | 1177 | wiinst->format.bitsperchannel = 16; |
1177 | wiinst->format.channels = hweight32(wiinst->fxwc); | 1178 | wiinst->format.channels = hweight32(wiinst->fxwc); |
1178 | break; | 1179 | break; |
1179 | default: | 1180 | default: |
1180 | kfree(wave_dev); | 1181 | kfree(wave_dev); |
1181 | kfree(wiinst); | 1182 | kfree(wiinst); |
1182 | BUG(); | 1183 | BUG(); |
1183 | break; | 1184 | break; |
1184 | } | 1185 | } |
1185 | 1186 | ||
1186 | wiinst->state = WAVE_STATE_CLOSED; | 1187 | wiinst->state = WAVE_STATE_CLOSED; |
1187 | 1188 | ||
1188 | wiinst->buffer.ossfragshift = 0; | 1189 | wiinst->buffer.ossfragshift = 0; |
1189 | wiinst->buffer.fragment_size = 0; | 1190 | wiinst->buffer.fragment_size = 0; |
1190 | wiinst->buffer.numfrags = 0; | 1191 | wiinst->buffer.numfrags = 0; |
1191 | 1192 | ||
1192 | init_waitqueue_head(&wiinst->wait_queue); | 1193 | init_waitqueue_head(&wiinst->wait_queue); |
1193 | 1194 | ||
1194 | wiinst->mmapped = 0; | 1195 | wiinst->mmapped = 0; |
1195 | wiinst->total_recorded = 0; | 1196 | wiinst->total_recorded = 0; |
1196 | wiinst->blocks = 0; | 1197 | wiinst->blocks = 0; |
1197 | spin_lock_init(&wiinst->lock); | 1198 | spin_lock_init(&wiinst->lock); |
1198 | tasklet_init(&wiinst->timer.tasklet, emu10k1_wavein_bh, (unsigned long) wave_dev); | 1199 | tasklet_init(&wiinst->timer.tasklet, emu10k1_wavein_bh, (unsigned long) wave_dev); |
1199 | wave_dev->wiinst = wiinst; | 1200 | wave_dev->wiinst = wiinst; |
1200 | emu10k1_wavein_setformat(wave_dev, &wiinst->format); | 1201 | emu10k1_wavein_setformat(wave_dev, &wiinst->format); |
1201 | } | 1202 | } |
1202 | 1203 | ||
1203 | if (file->f_mode & FMODE_WRITE) { | 1204 | if (file->f_mode & FMODE_WRITE) { |
1204 | struct woinst *woinst; | 1205 | struct woinst *woinst; |
1205 | int i; | 1206 | int i; |
1206 | 1207 | ||
1207 | if ((woinst = (struct woinst *) kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) { | 1208 | if ((woinst = (struct woinst *) kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) { |
1208 | ERROR(); | 1209 | ERROR(); |
1209 | kfree(wave_dev); | 1210 | kfree(wave_dev); |
1210 | return -ENOMEM; | 1211 | return -ENOMEM; |
1211 | } | 1212 | } |
1212 | 1213 | ||
1213 | if (wave_dev->wiinst != NULL) { | 1214 | if (wave_dev->wiinst != NULL) { |
1214 | woinst->format = wave_dev->wiinst->format; | 1215 | woinst->format = wave_dev->wiinst->format; |
1215 | } else { | 1216 | } else { |
1216 | woinst->format.id = AFMT_U8; | 1217 | woinst->format.id = AFMT_U8; |
1217 | woinst->format.samplingrate = 8000; | 1218 | woinst->format.samplingrate = 8000; |
1218 | woinst->format.bitsperchannel = 8; | 1219 | woinst->format.bitsperchannel = 8; |
1219 | woinst->format.channels = 1; | 1220 | woinst->format.channels = 1; |
1220 | } | 1221 | } |
1221 | 1222 | ||
1222 | woinst->state = WAVE_STATE_CLOSED; | 1223 | woinst->state = WAVE_STATE_CLOSED; |
1223 | 1224 | ||
1224 | woinst->buffer.fragment_size = 0; | 1225 | woinst->buffer.fragment_size = 0; |
1225 | woinst->buffer.ossfragshift = 0; | 1226 | woinst->buffer.ossfragshift = 0; |
1226 | woinst->buffer.numfrags = 0; | 1227 | woinst->buffer.numfrags = 0; |
1227 | woinst->device = (card->audio_dev1 == minor); | 1228 | woinst->device = (card->audio_dev1 == minor); |
1228 | woinst->timer.state = TIMER_STATE_UNINSTALLED; | 1229 | woinst->timer.state = TIMER_STATE_UNINSTALLED; |
1229 | woinst->num_voices = 1; | 1230 | woinst->num_voices = 1; |
1230 | for (i = 0; i < WAVEOUT_MAXVOICES; i++) { | 1231 | for (i = 0; i < WAVEOUT_MAXVOICES; i++) { |
1231 | woinst->voice[i].usage = VOICE_USAGE_FREE; | 1232 | woinst->voice[i].usage = VOICE_USAGE_FREE; |
1232 | woinst->voice[i].mem.emupageindex = -1; | 1233 | woinst->voice[i].mem.emupageindex = -1; |
1233 | } | 1234 | } |
1234 | 1235 | ||
1235 | init_waitqueue_head(&woinst->wait_queue); | 1236 | init_waitqueue_head(&woinst->wait_queue); |
1236 | 1237 | ||
1237 | woinst->mmapped = 0; | 1238 | woinst->mmapped = 0; |
1238 | woinst->total_copied = 0; | 1239 | woinst->total_copied = 0; |
1239 | woinst->total_played = 0; | 1240 | woinst->total_played = 0; |
1240 | woinst->blocks = 0; | 1241 | woinst->blocks = 0; |
1241 | spin_lock_init(&woinst->lock); | 1242 | spin_lock_init(&woinst->lock); |
1242 | tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev); | 1243 | tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev); |
1243 | wave_dev->woinst = woinst; | 1244 | wave_dev->woinst = woinst; |
1244 | emu10k1_waveout_setformat(wave_dev, &woinst->format); | 1245 | emu10k1_waveout_setformat(wave_dev, &woinst->format); |
1245 | } | 1246 | } |
1246 | 1247 | ||
1247 | file->private_data = (void *) wave_dev; | 1248 | file->private_data = (void *) wave_dev; |
1248 | 1249 | ||
1249 | return nonseekable_open(inode, file); | 1250 | return nonseekable_open(inode, file); |
1250 | } | 1251 | } |
1251 | 1252 | ||
1252 | static int emu10k1_audio_release(struct inode *inode, struct file *file) | 1253 | static int emu10k1_audio_release(struct inode *inode, struct file *file) |
1253 | { | 1254 | { |
1254 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | 1255 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; |
1255 | struct emu10k1_card *card; | 1256 | struct emu10k1_card *card; |
1256 | unsigned long flags; | 1257 | unsigned long flags; |
1257 | 1258 | ||
1258 | card = wave_dev->card; | 1259 | card = wave_dev->card; |
1259 | 1260 | ||
1260 | DPF(2, "emu10k1_audio_release()\n"); | 1261 | DPF(2, "emu10k1_audio_release()\n"); |
1261 | 1262 | ||
1262 | if (file->f_mode & FMODE_WRITE) { | 1263 | if (file->f_mode & FMODE_WRITE) { |
1263 | struct woinst *woinst = wave_dev->woinst; | 1264 | struct woinst *woinst = wave_dev->woinst; |
1264 | 1265 | ||
1265 | spin_lock_irqsave(&woinst->lock, flags); | 1266 | spin_lock_irqsave(&woinst->lock, flags); |
1266 | if(woinst->format.passthrough==2) | 1267 | if(woinst->format.passthrough==2) |
1267 | card->pt.state=PT_STATE_PLAYING; | 1268 | card->pt.state=PT_STATE_PLAYING; |
1268 | if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){ | 1269 | if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){ |
1269 | spin_lock(&card->pt.lock); | 1270 | spin_lock(&card->pt.lock); |
1270 | emu10k1_pt_stop(card); | 1271 | emu10k1_pt_stop(card); |
1271 | spin_unlock(&card->pt.lock); | 1272 | spin_unlock(&card->pt.lock); |
1272 | } | 1273 | } |
1273 | if (woinst->state & WAVE_STATE_OPEN) { | 1274 | if (woinst->state & WAVE_STATE_OPEN) { |
1274 | if (woinst->state & WAVE_STATE_STARTED) { | 1275 | if (woinst->state & WAVE_STATE_STARTED) { |
1275 | if (!(file->f_flags & O_NONBLOCK)) { | 1276 | if (!(file->f_flags & O_NONBLOCK)) { |
1276 | while (!signal_pending(current) | 1277 | while (!signal_pending(current) |
1277 | && (woinst->total_played < woinst->total_copied)) { | 1278 | && (woinst->total_played < woinst->total_copied)) { |
1278 | DPF(4, "Buffer hasn't been totally played, sleep....\n"); | 1279 | DPF(4, "Buffer hasn't been totally played, sleep....\n"); |
1279 | spin_unlock_irqrestore(&woinst->lock, flags); | 1280 | spin_unlock_irqrestore(&woinst->lock, flags); |
1280 | interruptible_sleep_on(&woinst->wait_queue); | 1281 | interruptible_sleep_on(&woinst->wait_queue); |
1281 | spin_lock_irqsave(&woinst->lock, flags); | 1282 | spin_lock_irqsave(&woinst->lock, flags); |
1282 | } | 1283 | } |
1283 | } | 1284 | } |
1284 | } | 1285 | } |
1285 | emu10k1_waveout_close(wave_dev); | 1286 | emu10k1_waveout_close(wave_dev); |
1286 | } | 1287 | } |
1287 | 1288 | ||
1288 | spin_unlock_irqrestore(&woinst->lock, flags); | 1289 | spin_unlock_irqrestore(&woinst->lock, flags); |
1289 | /* remove the tasklet */ | 1290 | /* remove the tasklet */ |
1290 | tasklet_kill(&woinst->timer.tasklet); | 1291 | tasklet_kill(&woinst->timer.tasklet); |
1291 | kfree(wave_dev->woinst); | 1292 | kfree(wave_dev->woinst); |
1292 | } | 1293 | } |
1293 | 1294 | ||
1294 | if (file->f_mode & FMODE_READ) { | 1295 | if (file->f_mode & FMODE_READ) { |
1295 | struct wiinst *wiinst = wave_dev->wiinst; | 1296 | struct wiinst *wiinst = wave_dev->wiinst; |
1296 | 1297 | ||
1297 | spin_lock_irqsave(&wiinst->lock, flags); | 1298 | spin_lock_irqsave(&wiinst->lock, flags); |
1298 | 1299 | ||
1299 | if (wiinst->state & WAVE_STATE_OPEN) { | 1300 | if (wiinst->state & WAVE_STATE_OPEN) { |
1300 | emu10k1_wavein_close(wave_dev); | 1301 | emu10k1_wavein_close(wave_dev); |
1301 | } | 1302 | } |
1302 | 1303 | ||
1303 | spin_unlock_irqrestore(&wiinst->lock, flags); | 1304 | spin_unlock_irqrestore(&wiinst->lock, flags); |
1304 | tasklet_kill(&wiinst->timer.tasklet); | 1305 | tasklet_kill(&wiinst->timer.tasklet); |
1305 | kfree(wave_dev->wiinst); | 1306 | kfree(wave_dev->wiinst); |
1306 | } | 1307 | } |
1307 | 1308 | ||
1308 | kfree(wave_dev); | 1309 | kfree(wave_dev); |
1309 | 1310 | ||
1310 | if (waitqueue_active(&card->open_wait)) | 1311 | if (waitqueue_active(&card->open_wait)) |
1311 | wake_up_interruptible(&card->open_wait); | 1312 | wake_up_interruptible(&card->open_wait); |
1312 | 1313 | ||
1313 | return 0; | 1314 | return 0; |
1314 | } | 1315 | } |
1315 | 1316 | ||
1316 | /* FIXME sort out poll() + mmap() */ | 1317 | /* FIXME sort out poll() + mmap() */ |
1317 | static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_struct *wait) | 1318 | static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_struct *wait) |
1318 | { | 1319 | { |
1319 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | 1320 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; |
1320 | struct woinst *woinst = wave_dev->woinst; | 1321 | struct woinst *woinst = wave_dev->woinst; |
1321 | struct wiinst *wiinst = wave_dev->wiinst; | 1322 | struct wiinst *wiinst = wave_dev->wiinst; |
1322 | unsigned int mask = 0; | 1323 | unsigned int mask = 0; |
1323 | u32 bytestocopy; | 1324 | u32 bytestocopy; |
1324 | unsigned long flags; | 1325 | unsigned long flags; |
1325 | 1326 | ||
1326 | DPF(4, "emu10k1_audio_poll()\n"); | 1327 | DPF(4, "emu10k1_audio_poll()\n"); |
1327 | 1328 | ||
1328 | if (file->f_mode & FMODE_WRITE) | 1329 | if (file->f_mode & FMODE_WRITE) |
1329 | poll_wait(file, &woinst->wait_queue, wait); | 1330 | poll_wait(file, &woinst->wait_queue, wait); |
1330 | 1331 | ||
1331 | if (file->f_mode & FMODE_READ) | 1332 | if (file->f_mode & FMODE_READ) |
1332 | poll_wait(file, &wiinst->wait_queue, wait); | 1333 | poll_wait(file, &wiinst->wait_queue, wait); |
1333 | 1334 | ||
1334 | if (file->f_mode & FMODE_WRITE) { | 1335 | if (file->f_mode & FMODE_WRITE) { |
1335 | spin_lock_irqsave(&woinst->lock, flags); | 1336 | spin_lock_irqsave(&woinst->lock, flags); |
1336 | 1337 | ||
1337 | if (woinst->state & WAVE_STATE_OPEN) { | 1338 | if (woinst->state & WAVE_STATE_OPEN) { |
1338 | emu10k1_waveout_update(woinst); | 1339 | emu10k1_waveout_update(woinst); |
1339 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | 1340 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); |
1340 | 1341 | ||
1341 | if (bytestocopy >= woinst->buffer.fragment_size) | 1342 | if (bytestocopy >= woinst->buffer.fragment_size) |
1342 | mask |= POLLOUT | POLLWRNORM; | 1343 | mask |= POLLOUT | POLLWRNORM; |
1343 | } else | 1344 | } else |
1344 | mask |= POLLOUT | POLLWRNORM; | 1345 | mask |= POLLOUT | POLLWRNORM; |
1345 | 1346 | ||
1346 | spin_unlock_irqrestore(&woinst->lock, flags); | 1347 | spin_unlock_irqrestore(&woinst->lock, flags); |
1347 | } | 1348 | } |
1348 | 1349 | ||
1349 | if (file->f_mode & FMODE_READ) { | 1350 | if (file->f_mode & FMODE_READ) { |
1350 | spin_lock_irqsave(&wiinst->lock, flags); | 1351 | spin_lock_irqsave(&wiinst->lock, flags); |
1351 | 1352 | ||
1352 | if (wiinst->state & WAVE_STATE_OPEN) { | 1353 | if (wiinst->state & WAVE_STATE_OPEN) { |
1353 | emu10k1_wavein_update(wave_dev->card, wiinst); | 1354 | emu10k1_wavein_update(wave_dev->card, wiinst); |
1354 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | 1355 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); |
1355 | 1356 | ||
1356 | if (bytestocopy >= wiinst->buffer.fragment_size) | 1357 | if (bytestocopy >= wiinst->buffer.fragment_size) |
1357 | mask |= POLLIN | POLLRDNORM; | 1358 | mask |= POLLIN | POLLRDNORM; |
1358 | } | 1359 | } |
1359 | 1360 | ||
1360 | spin_unlock_irqrestore(&wiinst->lock, flags); | 1361 | spin_unlock_irqrestore(&wiinst->lock, flags); |
1361 | } | 1362 | } |
1362 | 1363 | ||
1363 | return mask; | 1364 | return mask; |
1364 | } | 1365 | } |
1365 | 1366 | ||
1366 | static void calculate_ofrag(struct woinst *woinst) | 1367 | static void calculate_ofrag(struct woinst *woinst) |
1367 | { | 1368 | { |
1368 | struct waveout_buffer *buffer = &woinst->buffer; | 1369 | struct waveout_buffer *buffer = &woinst->buffer; |
1369 | u32 fragsize; | 1370 | u32 fragsize; |
1370 | 1371 | ||
1371 | if (buffer->fragment_size) | 1372 | if (buffer->fragment_size) |
1372 | return; | 1373 | return; |
1373 | 1374 | ||
1374 | if (!buffer->ossfragshift) { | 1375 | if (!buffer->ossfragshift) { |
1375 | fragsize = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1; | 1376 | fragsize = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1; |
1376 | 1377 | ||
1377 | while (fragsize) { | 1378 | while (fragsize) { |
1378 | fragsize >>= 1; | 1379 | fragsize >>= 1; |
1379 | buffer->ossfragshift++; | 1380 | buffer->ossfragshift++; |
1380 | } | 1381 | } |
1381 | } | 1382 | } |
1382 | 1383 | ||
1383 | if (buffer->ossfragshift < WAVEOUT_MINFRAGSHIFT) | 1384 | if (buffer->ossfragshift < WAVEOUT_MINFRAGSHIFT) |
1384 | buffer->ossfragshift = WAVEOUT_MINFRAGSHIFT; | 1385 | buffer->ossfragshift = WAVEOUT_MINFRAGSHIFT; |
1385 | 1386 | ||
1386 | buffer->fragment_size = 1 << buffer->ossfragshift; | 1387 | buffer->fragment_size = 1 << buffer->ossfragshift; |
1387 | 1388 | ||
1388 | while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE) | 1389 | while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE) |
1389 | buffer->fragment_size >>= 1; | 1390 | buffer->fragment_size >>= 1; |
1390 | 1391 | ||
1391 | /* now we are sure that: | 1392 | /* now we are sure that: |
1392 | (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS) | 1393 | (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS) |
1393 | */ | 1394 | */ |
1394 | 1395 | ||
1395 | if (!buffer->numfrags) { | 1396 | if (!buffer->numfrags) { |
1396 | u32 numfrags; | 1397 | u32 numfrags; |
1397 | 1398 | ||
1398 | numfrags = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTBUFLEN) / | 1399 | numfrags = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTBUFLEN) / |
1399 | (buffer->fragment_size * 1000) - 1; | 1400 | (buffer->fragment_size * 1000) - 1; |
1400 | 1401 | ||
1401 | buffer->numfrags = 1; | 1402 | buffer->numfrags = 1; |
1402 | 1403 | ||
1403 | while (numfrags) { | 1404 | while (numfrags) { |
1404 | numfrags >>= 1; | 1405 | numfrags >>= 1; |
1405 | buffer->numfrags <<= 1; | 1406 | buffer->numfrags <<= 1; |
1406 | } | 1407 | } |
1407 | } | 1408 | } |
1408 | 1409 | ||
1409 | if (buffer->numfrags < WAVEOUT_MINFRAGS) | 1410 | if (buffer->numfrags < WAVEOUT_MINFRAGS) |
1410 | buffer->numfrags = WAVEOUT_MINFRAGS; | 1411 | buffer->numfrags = WAVEOUT_MINFRAGS; |
1411 | 1412 | ||
1412 | if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) | 1413 | if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) |
1413 | buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size; | 1414 | buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size; |
1414 | 1415 | ||
1415 | if (buffer->numfrags < WAVEOUT_MINFRAGS) | 1416 | if (buffer->numfrags < WAVEOUT_MINFRAGS) |
1416 | BUG(); | 1417 | BUG(); |
1417 | 1418 | ||
1418 | buffer->size = buffer->fragment_size * buffer->numfrags; | 1419 | buffer->size = buffer->fragment_size * buffer->numfrags; |
1419 | buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); | 1420 | buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); |
1420 | 1421 | ||
1421 | DPD(2, " calculated playback fragment_size -> %d\n", buffer->fragment_size); | 1422 | DPD(2, " calculated playback fragment_size -> %d\n", buffer->fragment_size); |
1422 | DPD(2, " calculated playback numfrags -> %d\n", buffer->numfrags); | 1423 | DPD(2, " calculated playback numfrags -> %d\n", buffer->numfrags); |
1423 | 1424 | ||
1424 | return; | 1425 | return; |
1425 | } | 1426 | } |
1426 | 1427 | ||
1427 | static void calculate_ifrag(struct wiinst *wiinst) | 1428 | static void calculate_ifrag(struct wiinst *wiinst) |
1428 | { | 1429 | { |
1429 | struct wavein_buffer *buffer = &wiinst->buffer; | 1430 | struct wavein_buffer *buffer = &wiinst->buffer; |
1430 | u32 fragsize, bufsize, size[4]; | 1431 | u32 fragsize, bufsize, size[4]; |
1431 | int i, j; | 1432 | int i, j; |
1432 | 1433 | ||
1433 | if (buffer->fragment_size) | 1434 | if (buffer->fragment_size) |
1434 | return; | 1435 | return; |
1435 | 1436 | ||
1436 | if (!buffer->ossfragshift) { | 1437 | if (!buffer->ossfragshift) { |
1437 | fragsize = (wiinst->format.bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1; | 1438 | fragsize = (wiinst->format.bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1; |
1438 | 1439 | ||
1439 | while (fragsize) { | 1440 | while (fragsize) { |
1440 | fragsize >>= 1; | 1441 | fragsize >>= 1; |
1441 | buffer->ossfragshift++; | 1442 | buffer->ossfragshift++; |
1442 | } | 1443 | } |
1443 | } | 1444 | } |
1444 | 1445 | ||
1445 | if (buffer->ossfragshift < WAVEIN_MINFRAGSHIFT) | 1446 | if (buffer->ossfragshift < WAVEIN_MINFRAGSHIFT) |
1446 | buffer->ossfragshift = WAVEIN_MINFRAGSHIFT; | 1447 | buffer->ossfragshift = WAVEIN_MINFRAGSHIFT; |
1447 | 1448 | ||
1448 | buffer->fragment_size = 1 << buffer->ossfragshift; | 1449 | buffer->fragment_size = 1 << buffer->ossfragshift; |
1449 | 1450 | ||
1450 | while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE) | 1451 | while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE) |
1451 | buffer->fragment_size >>= 1; | 1452 | buffer->fragment_size >>= 1; |
1452 | 1453 | ||
1453 | /* now we are sure that: | 1454 | /* now we are sure that: |
1454 | (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS) | 1455 | (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS) |
1455 | */ | 1456 | */ |
1456 | 1457 | ||
1457 | 1458 | ||
1458 | if (!buffer->numfrags) | 1459 | if (!buffer->numfrags) |
1459 | buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1; | 1460 | buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1; |
1460 | 1461 | ||
1461 | if (buffer->numfrags < WAVEIN_MINFRAGS) | 1462 | if (buffer->numfrags < WAVEIN_MINFRAGS) |
1462 | buffer->numfrags = WAVEIN_MINFRAGS; | 1463 | buffer->numfrags = WAVEIN_MINFRAGS; |
1463 | 1464 | ||
1464 | if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) | 1465 | if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) |
1465 | buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size; | 1466 | buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size; |
1466 | 1467 | ||
1467 | if (buffer->numfrags < WAVEIN_MINFRAGS) | 1468 | if (buffer->numfrags < WAVEIN_MINFRAGS) |
1468 | BUG(); | 1469 | BUG(); |
1469 | 1470 | ||
1470 | bufsize = buffer->fragment_size * buffer->numfrags; | 1471 | bufsize = buffer->fragment_size * buffer->numfrags; |
1471 | 1472 | ||
1472 | /* the buffer size for recording is restricted to certain values, adjust it now */ | 1473 | /* the buffer size for recording is restricted to certain values, adjust it now */ |
1473 | if (bufsize >= 0x10000) { | 1474 | if (bufsize >= 0x10000) { |
1474 | buffer->size = 0x10000; | 1475 | buffer->size = 0x10000; |
1475 | buffer->sizeregval = 0x1f; | 1476 | buffer->sizeregval = 0x1f; |
1476 | } else { | 1477 | } else { |
1477 | buffer->size = 0; | 1478 | buffer->size = 0; |
1478 | size[0] = 384; | 1479 | size[0] = 384; |
1479 | size[1] = 448; | 1480 | size[1] = 448; |
1480 | size[2] = 512; | 1481 | size[2] = 512; |
1481 | size[3] = 640; | 1482 | size[3] = 640; |
1482 | 1483 | ||
1483 | for (i = 0; i < 8; i++) | 1484 | for (i = 0; i < 8; i++) |
1484 | for (j = 0; j < 4; j++) | 1485 | for (j = 0; j < 4; j++) |
1485 | if (bufsize >= size[j]) { | 1486 | if (bufsize >= size[j]) { |
1486 | buffer->size = size[j]; | 1487 | buffer->size = size[j]; |
1487 | size[j] *= 2; | 1488 | size[j] *= 2; |
1488 | buffer->sizeregval = i * 4 + j + 1; | 1489 | buffer->sizeregval = i * 4 + j + 1; |
1489 | } else | 1490 | } else |
1490 | goto exitloop; | 1491 | goto exitloop; |
1491 | exitloop: | 1492 | exitloop: |
1492 | if (buffer->size == 0) { | 1493 | if (buffer->size == 0) { |
1493 | buffer->size = 384; | 1494 | buffer->size = 384; |
1494 | buffer->sizeregval = 0x01; | 1495 | buffer->sizeregval = 0x01; |
1495 | } | 1496 | } |
1496 | } | 1497 | } |
1497 | 1498 | ||
1498 | /* adjust the fragment size so that buffer size is an integer multiple */ | 1499 | /* adjust the fragment size so that buffer size is an integer multiple */ |
1499 | while (buffer->size % buffer->fragment_size) | 1500 | while (buffer->size % buffer->fragment_size) |
1500 | buffer->fragment_size >>= 1; | 1501 | buffer->fragment_size >>= 1; |
1501 | 1502 | ||
1502 | buffer->numfrags = buffer->size / buffer->fragment_size; | 1503 | buffer->numfrags = buffer->size / buffer->fragment_size; |
1503 | buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); | 1504 | buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); |
1504 | 1505 | ||
1505 | DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size); | 1506 | DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size); |
1506 | DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags); | 1507 | DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags); |
1507 | DPD(2, " buffer size register -> %#04x\n", buffer->sizeregval); | 1508 | DPD(2, " buffer size register -> %#04x\n", buffer->sizeregval); |
1508 | 1509 | ||
1509 | return; | 1510 | return; |
1510 | } | 1511 | } |
1511 | 1512 | ||
1512 | static void emu10k1_wavein_bh(unsigned long refdata) | 1513 | static void emu10k1_wavein_bh(unsigned long refdata) |
1513 | { | 1514 | { |
1514 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata; | 1515 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata; |
1515 | struct wiinst *wiinst = wave_dev->wiinst; | 1516 | struct wiinst *wiinst = wave_dev->wiinst; |
1516 | u32 bytestocopy; | 1517 | u32 bytestocopy; |
1517 | unsigned long flags; | 1518 | unsigned long flags; |
1518 | 1519 | ||
1519 | if (!wiinst) | 1520 | if (!wiinst) |
1520 | return; | 1521 | return; |
1521 | 1522 | ||
1522 | spin_lock_irqsave(&wiinst->lock, flags); | 1523 | spin_lock_irqsave(&wiinst->lock, flags); |
1523 | 1524 | ||
1524 | if (!(wiinst->state & WAVE_STATE_STARTED)) { | 1525 | if (!(wiinst->state & WAVE_STATE_STARTED)) { |
1525 | spin_unlock_irqrestore(&wiinst->lock, flags); | 1526 | spin_unlock_irqrestore(&wiinst->lock, flags); |
1526 | return; | 1527 | return; |
1527 | } | 1528 | } |
1528 | 1529 | ||
1529 | emu10k1_wavein_update(wave_dev->card, wiinst); | 1530 | emu10k1_wavein_update(wave_dev->card, wiinst); |
1530 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | 1531 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); |
1531 | 1532 | ||
1532 | spin_unlock_irqrestore(&wiinst->lock, flags); | 1533 | spin_unlock_irqrestore(&wiinst->lock, flags); |
1533 | 1534 | ||
1534 | if (bytestocopy >= wiinst->buffer.fragment_size) { | 1535 | if (bytestocopy >= wiinst->buffer.fragment_size) { |
1535 | if (waitqueue_active(&wiinst->wait_queue)) | 1536 | if (waitqueue_active(&wiinst->wait_queue)) |
1536 | wake_up_interruptible(&wiinst->wait_queue); | 1537 | wake_up_interruptible(&wiinst->wait_queue); |
1537 | } else | 1538 | } else |
1538 | DPD(3, "Not enough transfer size, %d\n", bytestocopy); | 1539 | DPD(3, "Not enough transfer size, %d\n", bytestocopy); |
1539 | 1540 | ||
1540 | return; | 1541 | return; |
1541 | } | 1542 | } |
1542 | 1543 | ||
1543 | static void emu10k1_waveout_bh(unsigned long refdata) | 1544 | static void emu10k1_waveout_bh(unsigned long refdata) |
1544 | { | 1545 | { |
1545 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata; | 1546 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata; |
1546 | struct woinst *woinst = wave_dev->woinst; | 1547 | struct woinst *woinst = wave_dev->woinst; |
1547 | u32 bytestocopy; | 1548 | u32 bytestocopy; |
1548 | unsigned long flags; | 1549 | unsigned long flags; |
1549 | 1550 | ||
1550 | if (!woinst) | 1551 | if (!woinst) |
1551 | return; | 1552 | return; |
1552 | 1553 | ||
1553 | spin_lock_irqsave(&woinst->lock, flags); | 1554 | spin_lock_irqsave(&woinst->lock, flags); |
1554 | 1555 | ||
1555 | if (!(woinst->state & WAVE_STATE_STARTED)) { | 1556 | if (!(woinst->state & WAVE_STATE_STARTED)) { |
1556 | spin_unlock_irqrestore(&woinst->lock, flags); | 1557 | spin_unlock_irqrestore(&woinst->lock, flags); |
1557 | return; | 1558 | return; |
1558 | } | 1559 | } |
1559 | 1560 | ||
1560 | emu10k1_waveout_update(woinst); | 1561 | emu10k1_waveout_update(woinst); |
1561 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | 1562 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); |
1562 | 1563 | ||
1563 | if (woinst->buffer.fill_silence) { | 1564 | if (woinst->buffer.fill_silence) { |
1564 | spin_unlock_irqrestore(&woinst->lock, flags); | 1565 | spin_unlock_irqrestore(&woinst->lock, flags); |
1565 | emu10k1_waveout_fillsilence(woinst); | 1566 | emu10k1_waveout_fillsilence(woinst); |
1566 | } else | 1567 | } else |
1567 | spin_unlock_irqrestore(&woinst->lock, flags); | 1568 | spin_unlock_irqrestore(&woinst->lock, flags); |
1568 | 1569 | ||
1569 | if (bytestocopy >= woinst->buffer.fragment_size) { | 1570 | if (bytestocopy >= woinst->buffer.fragment_size) { |
1570 | if (waitqueue_active(&woinst->wait_queue)) | 1571 | if (waitqueue_active(&woinst->wait_queue)) |
1571 | wake_up_interruptible(&woinst->wait_queue); | 1572 | wake_up_interruptible(&woinst->wait_queue); |
1572 | } else | 1573 | } else |
1573 | DPD(3, "Not enough transfer size -> %d\n", bytestocopy); | 1574 | DPD(3, "Not enough transfer size -> %d\n", bytestocopy); |
1574 | 1575 | ||
1575 | return; | 1576 | return; |
1576 | } | 1577 | } |
1577 | 1578 | ||
1578 | struct file_operations emu10k1_audio_fops = { | 1579 | struct file_operations emu10k1_audio_fops = { |
1579 | .owner = THIS_MODULE, | 1580 | .owner = THIS_MODULE, |
1580 | .llseek = no_llseek, | 1581 | .llseek = no_llseek, |
1581 | .read = emu10k1_audio_read, | 1582 | .read = emu10k1_audio_read, |
1582 | .write = emu10k1_audio_write, | 1583 | .write = emu10k1_audio_write, |
1583 | .poll = emu10k1_audio_poll, | 1584 | .poll = emu10k1_audio_poll, |
1584 | .ioctl = emu10k1_audio_ioctl, | 1585 | .ioctl = emu10k1_audio_ioctl, |
1585 | .mmap = emu10k1_audio_mmap, | 1586 | .mmap = emu10k1_audio_mmap, |
1586 | .open = emu10k1_audio_open, | 1587 | .open = emu10k1_audio_open, |
1587 | .release = emu10k1_audio_release, | 1588 | .release = emu10k1_audio_release, |
1588 | }; | 1589 | }; |
1589 | 1590 |
sound/oss/es1371.c
1 | /*****************************************************************************/ | 1 | /*****************************************************************************/ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * es1371.c -- Creative Ensoniq ES1371. | 4 | * es1371.c -- Creative Ensoniq ES1371. |
5 | * | 5 | * |
6 | * Copyright (C) 1998-2001, 2003 Thomas Sailer (t.sailer@alumni.ethz.ch) | 6 | * Copyright (C) 1998-2001, 2003 Thomas Sailer (t.sailer@alumni.ethz.ch) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | * | 21 | * |
22 | * Special thanks to Ensoniq | 22 | * Special thanks to Ensoniq |
23 | * | 23 | * |
24 | * Supported devices: | 24 | * Supported devices: |
25 | * /dev/dsp standard /dev/dsp device, (mostly) OSS compatible | 25 | * /dev/dsp standard /dev/dsp device, (mostly) OSS compatible |
26 | * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible | 26 | * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible |
27 | * /dev/dsp1 additional DAC, like /dev/dsp, but outputs to mixer "SYNTH" setting | 27 | * /dev/dsp1 additional DAC, like /dev/dsp, but outputs to mixer "SYNTH" setting |
28 | * /dev/midi simple MIDI UART interface, no ioctl | 28 | * /dev/midi simple MIDI UART interface, no ioctl |
29 | * | 29 | * |
30 | * NOTE: the card does not have any FM/Wavetable synthesizer, it is supposed | 30 | * NOTE: the card does not have any FM/Wavetable synthesizer, it is supposed |
31 | * to be done in software. That is what /dev/dac is for. By now (Q2 1998) | 31 | * to be done in software. That is what /dev/dac is for. By now (Q2 1998) |
32 | * there are several MIDI to PCM (WAV) packages, one of them is timidity. | 32 | * there are several MIDI to PCM (WAV) packages, one of them is timidity. |
33 | * | 33 | * |
34 | * Revision history | 34 | * Revision history |
35 | * 04.06.1998 0.1 Initial release | 35 | * 04.06.1998 0.1 Initial release |
36 | * Mixer stuff should be overhauled; especially optional AC97 mixer bits | 36 | * Mixer stuff should be overhauled; especially optional AC97 mixer bits |
37 | * should be detected. This results in strange behaviour of some mixer | 37 | * should be detected. This results in strange behaviour of some mixer |
38 | * settings, like master volume and mic. | 38 | * settings, like master volume and mic. |
39 | * 08.06.1998 0.2 First release using Alan Cox' soundcore instead of miscdevice | 39 | * 08.06.1998 0.2 First release using Alan Cox' soundcore instead of miscdevice |
40 | * 03.08.1998 0.3 Do not include modversions.h | 40 | * 03.08.1998 0.3 Do not include modversions.h |
41 | * Now mixer behaviour can basically be selected between | 41 | * Now mixer behaviour can basically be selected between |
42 | * "OSS documented" and "OSS actual" behaviour | 42 | * "OSS documented" and "OSS actual" behaviour |
43 | * 31.08.1998 0.4 Fix realplayer problems - dac.count issues | 43 | * 31.08.1998 0.4 Fix realplayer problems - dac.count issues |
44 | * 27.10.1998 0.5 Fix joystick support | 44 | * 27.10.1998 0.5 Fix joystick support |
45 | * -- Oliver Neukum (c188@org.chemie.uni-muenchen.de) | 45 | * -- Oliver Neukum (c188@org.chemie.uni-muenchen.de) |
46 | * 10.12.1998 0.6 Fix drain_dac trying to wait on not yet initialized DMA | 46 | * 10.12.1998 0.6 Fix drain_dac trying to wait on not yet initialized DMA |
47 | * 23.12.1998 0.7 Fix a few f_file & FMODE_ bugs | 47 | * 23.12.1998 0.7 Fix a few f_file & FMODE_ bugs |
48 | * Don't wake up app until there are fragsize bytes to read/write | 48 | * Don't wake up app until there are fragsize bytes to read/write |
49 | * 06.01.1999 0.8 remove the silly SA_INTERRUPT flag. | 49 | * 06.01.1999 0.8 remove the silly SA_INTERRUPT flag. |
50 | * hopefully killed the egcs section type conflict | 50 | * hopefully killed the egcs section type conflict |
51 | * 12.03.1999 0.9 cinfo.blocks should be reset after GETxPTR ioctl. | 51 | * 12.03.1999 0.9 cinfo.blocks should be reset after GETxPTR ioctl. |
52 | * reported by Johan Maes <joma@telindus.be> | 52 | * reported by Johan Maes <joma@telindus.be> |
53 | * 22.03.1999 0.10 return EAGAIN instead of EBUSY when O_NONBLOCK | 53 | * 22.03.1999 0.10 return EAGAIN instead of EBUSY when O_NONBLOCK |
54 | * read/write cannot be executed | 54 | * read/write cannot be executed |
55 | * 07.04.1999 0.11 implemented the following ioctl's: SOUND_PCM_READ_RATE, | 55 | * 07.04.1999 0.11 implemented the following ioctl's: SOUND_PCM_READ_RATE, |
56 | * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; | 56 | * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; |
57 | * Alpha fixes reported by Peter Jones <pjones@redhat.com> | 57 | * Alpha fixes reported by Peter Jones <pjones@redhat.com> |
58 | * Another Alpha fix (wait_src_ready in init routine) | 58 | * Another Alpha fix (wait_src_ready in init routine) |
59 | * reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru> | 59 | * reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru> |
60 | * Note: joystick address handling might still be wrong on archs | 60 | * Note: joystick address handling might still be wrong on archs |
61 | * other than i386 | 61 | * other than i386 |
62 | * 15.06.1999 0.12 Fix bad allocation bug. | 62 | * 15.06.1999 0.12 Fix bad allocation bug. |
63 | * Thanks to Deti Fliegl <fliegl@in.tum.de> | 63 | * Thanks to Deti Fliegl <fliegl@in.tum.de> |
64 | * 28.06.1999 0.13 Add pci_set_master | 64 | * 28.06.1999 0.13 Add pci_set_master |
65 | * 03.08.1999 0.14 adapt to Linus' new __setup/__initcall | 65 | * 03.08.1999 0.14 adapt to Linus' new __setup/__initcall |
66 | * added kernel command line option "es1371=joystickaddr" | 66 | * added kernel command line option "es1371=joystickaddr" |
67 | * removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge | 67 | * removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge |
68 | * 10.08.1999 0.15 (Re)added S/PDIF module option for cards revision >= 4. | 68 | * 10.08.1999 0.15 (Re)added S/PDIF module option for cards revision >= 4. |
69 | * Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>. | 69 | * Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>. |
70 | * module_init/__setup fixes | 70 | * module_init/__setup fixes |
71 | * 08.16.1999 0.16 Joe Cotellese <joec@ensoniq.com> | 71 | * 08.16.1999 0.16 Joe Cotellese <joec@ensoniq.com> |
72 | * Added detection for ES1371 revision ID so that we can | 72 | * Added detection for ES1371 revision ID so that we can |
73 | * detect the ES1373 and later parts. | 73 | * detect the ES1373 and later parts. |
74 | * added AC97 #defines for readability | 74 | * added AC97 #defines for readability |
75 | * added a /proc file system for dumping hardware state | 75 | * added a /proc file system for dumping hardware state |
76 | * updated SRC and CODEC w/r functions to accommodate bugs | 76 | * updated SRC and CODEC w/r functions to accommodate bugs |
77 | * in some versions of the ES137x chips. | 77 | * in some versions of the ES137x chips. |
78 | * 31.08.1999 0.17 add spin_lock_init | 78 | * 31.08.1999 0.17 add spin_lock_init |
79 | * replaced current->state = x with set_current_state(x) | 79 | * replaced current->state = x with set_current_state(x) |
80 | * 03.09.1999 0.18 change read semantics for MIDI to match | 80 | * 03.09.1999 0.18 change read semantics for MIDI to match |
81 | * OSS more closely; remove possible wakeup race | 81 | * OSS more closely; remove possible wakeup race |
82 | * 21.10.1999 0.19 Round sampling rates, requested by | 82 | * 21.10.1999 0.19 Round sampling rates, requested by |
83 | * Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp> | 83 | * Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp> |
84 | * 27.10.1999 0.20 Added SigmaTel 3D enhancement string | 84 | * 27.10.1999 0.20 Added SigmaTel 3D enhancement string |
85 | * Codec ID printing changes | 85 | * Codec ID printing changes |
86 | * 28.10.1999 0.21 More waitqueue races fixed | 86 | * 28.10.1999 0.21 More waitqueue races fixed |
87 | * Joe Cotellese <joec@ensoniq.com> | 87 | * Joe Cotellese <joec@ensoniq.com> |
88 | * Changed PCI detection routine so we can more easily | 88 | * Changed PCI detection routine so we can more easily |
89 | * detect ES137x chip and derivatives. | 89 | * detect ES137x chip and derivatives. |
90 | * 05.01.2000 0.22 Should now work with rev7 boards; patch by | 90 | * 05.01.2000 0.22 Should now work with rev7 boards; patch by |
91 | * Eric Lemar, elemar@cs.washington.edu | 91 | * Eric Lemar, elemar@cs.washington.edu |
92 | * 08.01.2000 0.23 Prevent some ioctl's from returning bad count values on underrun/overrun; | 92 | * 08.01.2000 0.23 Prevent some ioctl's from returning bad count values on underrun/overrun; |
93 | * Tim Janik's BSE (Bedevilled Sound Engine) found this | 93 | * Tim Janik's BSE (Bedevilled Sound Engine) found this |
94 | * 07.02.2000 0.24 Use pci_alloc_consistent and pci_register_driver | 94 | * 07.02.2000 0.24 Use pci_alloc_consistent and pci_register_driver |
95 | * 07.02.2000 0.25 Use ac97_codec | 95 | * 07.02.2000 0.25 Use ac97_codec |
96 | * 01.03.2000 0.26 SPDIF patch by Mikael Bouillot <mikael.bouillot@bigfoot.com> | 96 | * 01.03.2000 0.26 SPDIF patch by Mikael Bouillot <mikael.bouillot@bigfoot.com> |
97 | * Use pci_module_init | 97 | * Use pci_module_init |
98 | * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask | 98 | * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask |
99 | * 12.12.2000 0.28 More dma buffer initializations, patch from | 99 | * 12.12.2000 0.28 More dma buffer initializations, patch from |
100 | * Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com> | 100 | * Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com> |
101 | * 05.01.2001 0.29 Hopefully updates will not be required anymore when Creative bumps | 101 | * 05.01.2001 0.29 Hopefully updates will not be required anymore when Creative bumps |
102 | * the CT5880 revision. | 102 | * the CT5880 revision. |
103 | * suggested by Stephan Mรผller <smueller@chronox.de> | 103 | * suggested by Stephan Mรผller <smueller@chronox.de> |
104 | * 31.01.2001 0.30 Register/Unregister gameport | 104 | * 31.01.2001 0.30 Register/Unregister gameport |
105 | * Fix SETTRIGGER non OSS API conformity | 105 | * Fix SETTRIGGER non OSS API conformity |
106 | * 14.07.2001 0.31 Add list of laptops needing amplifier control | 106 | * 14.07.2001 0.31 Add list of laptops needing amplifier control |
107 | * 03.01.2003 0.32 open_mode fixes from Georg Acher <acher@in.tum.de> | 107 | * 03.01.2003 0.32 open_mode fixes from Georg Acher <acher@in.tum.de> |
108 | */ | 108 | */ |
109 | 109 | ||
110 | /*****************************************************************************/ | 110 | /*****************************************************************************/ |
111 | 111 | ||
112 | #include <linux/interrupt.h> | 112 | #include <linux/interrupt.h> |
113 | #include <linux/module.h> | 113 | #include <linux/module.h> |
114 | #include <linux/string.h> | 114 | #include <linux/string.h> |
115 | #include <linux/ioport.h> | 115 | #include <linux/ioport.h> |
116 | #include <linux/sched.h> | 116 | #include <linux/sched.h> |
117 | #include <linux/delay.h> | 117 | #include <linux/delay.h> |
118 | #include <linux/sound.h> | 118 | #include <linux/sound.h> |
119 | #include <linux/slab.h> | 119 | #include <linux/slab.h> |
120 | #include <linux/soundcard.h> | 120 | #include <linux/soundcard.h> |
121 | #include <linux/pci.h> | 121 | #include <linux/pci.h> |
122 | #include <linux/init.h> | 122 | #include <linux/init.h> |
123 | #include <linux/poll.h> | 123 | #include <linux/poll.h> |
124 | #include <linux/bitops.h> | 124 | #include <linux/bitops.h> |
125 | #include <linux/proc_fs.h> | 125 | #include <linux/proc_fs.h> |
126 | #include <linux/spinlock.h> | 126 | #include <linux/spinlock.h> |
127 | #include <linux/smp_lock.h> | 127 | #include <linux/smp_lock.h> |
128 | #include <linux/ac97_codec.h> | 128 | #include <linux/ac97_codec.h> |
129 | #include <linux/gameport.h> | 129 | #include <linux/gameport.h> |
130 | #include <linux/wait.h> | 130 | #include <linux/wait.h> |
131 | #include <linux/dma-mapping.h> | 131 | #include <linux/dma-mapping.h> |
132 | #include <linux/mutex.h> | 132 | #include <linux/mutex.h> |
133 | #include <linux/mm.h> | ||
133 | 134 | ||
134 | #include <asm/io.h> | 135 | #include <asm/io.h> |
135 | #include <asm/page.h> | 136 | #include <asm/page.h> |
136 | #include <asm/uaccess.h> | 137 | #include <asm/uaccess.h> |
137 | 138 | ||
138 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | 139 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) |
139 | #define SUPPORT_JOYSTICK | 140 | #define SUPPORT_JOYSTICK |
140 | #endif | 141 | #endif |
141 | 142 | ||
142 | /* --------------------------------------------------------------------- */ | 143 | /* --------------------------------------------------------------------- */ |
143 | 144 | ||
144 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 145 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS |
145 | #define ES1371_DEBUG | 146 | #define ES1371_DEBUG |
146 | #define DBG(x) {} | 147 | #define DBG(x) {} |
147 | /*#define DBG(x) {x}*/ | 148 | /*#define DBG(x) {x}*/ |
148 | 149 | ||
149 | /* --------------------------------------------------------------------- */ | 150 | /* --------------------------------------------------------------------- */ |
150 | 151 | ||
151 | #ifndef PCI_VENDOR_ID_ENSONIQ | 152 | #ifndef PCI_VENDOR_ID_ENSONIQ |
152 | #define PCI_VENDOR_ID_ENSONIQ 0x1274 | 153 | #define PCI_VENDOR_ID_ENSONIQ 0x1274 |
153 | #endif | 154 | #endif |
154 | 155 | ||
155 | #ifndef PCI_VENDOR_ID_ECTIVA | 156 | #ifndef PCI_VENDOR_ID_ECTIVA |
156 | #define PCI_VENDOR_ID_ECTIVA 0x1102 | 157 | #define PCI_VENDOR_ID_ECTIVA 0x1102 |
157 | #endif | 158 | #endif |
158 | 159 | ||
159 | #ifndef PCI_DEVICE_ID_ENSONIQ_ES1371 | 160 | #ifndef PCI_DEVICE_ID_ENSONIQ_ES1371 |
160 | #define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371 | 161 | #define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371 |
161 | #endif | 162 | #endif |
162 | 163 | ||
163 | #ifndef PCI_DEVICE_ID_ENSONIQ_CT5880 | 164 | #ifndef PCI_DEVICE_ID_ENSONIQ_CT5880 |
164 | #define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880 | 165 | #define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880 |
165 | #endif | 166 | #endif |
166 | 167 | ||
167 | #ifndef PCI_DEVICE_ID_ECTIVA_EV1938 | 168 | #ifndef PCI_DEVICE_ID_ECTIVA_EV1938 |
168 | #define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938 | 169 | #define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938 |
169 | #endif | 170 | #endif |
170 | 171 | ||
171 | /* ES1371 chip ID */ | 172 | /* ES1371 chip ID */ |
172 | /* This is a little confusing because all ES1371 compatible chips have the | 173 | /* This is a little confusing because all ES1371 compatible chips have the |
173 | same DEVICE_ID, the only thing differentiating them is the REV_ID field. | 174 | same DEVICE_ID, the only thing differentiating them is the REV_ID field. |
174 | This is only significant if you want to enable features on the later parts. | 175 | This is only significant if you want to enable features on the later parts. |
175 | Yes, I know it's stupid and why didn't we use the sub IDs? | 176 | Yes, I know it's stupid and why didn't we use the sub IDs? |
176 | */ | 177 | */ |
177 | #define ES1371REV_ES1373_A 0x04 | 178 | #define ES1371REV_ES1373_A 0x04 |
178 | #define ES1371REV_ES1373_B 0x06 | 179 | #define ES1371REV_ES1373_B 0x06 |
179 | #define ES1371REV_CT5880_A 0x07 | 180 | #define ES1371REV_CT5880_A 0x07 |
180 | #define CT5880REV_CT5880_C 0x02 | 181 | #define CT5880REV_CT5880_C 0x02 |
181 | #define CT5880REV_CT5880_D 0x03 | 182 | #define CT5880REV_CT5880_D 0x03 |
182 | #define ES1371REV_ES1371_B 0x09 | 183 | #define ES1371REV_ES1371_B 0x09 |
183 | #define EV1938REV_EV1938_A 0x00 | 184 | #define EV1938REV_EV1938_A 0x00 |
184 | #define ES1371REV_ES1373_8 0x08 | 185 | #define ES1371REV_ES1373_8 0x08 |
185 | 186 | ||
186 | #define ES1371_MAGIC ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371) | 187 | #define ES1371_MAGIC ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371) |
187 | 188 | ||
188 | #define ES1371_EXTENT 0x40 | 189 | #define ES1371_EXTENT 0x40 |
189 | #define JOY_EXTENT 8 | 190 | #define JOY_EXTENT 8 |
190 | 191 | ||
191 | #define ES1371_REG_CONTROL 0x00 | 192 | #define ES1371_REG_CONTROL 0x00 |
192 | #define ES1371_REG_STATUS 0x04 /* on the 5880 it is control/status */ | 193 | #define ES1371_REG_STATUS 0x04 /* on the 5880 it is control/status */ |
193 | #define ES1371_REG_UART_DATA 0x08 | 194 | #define ES1371_REG_UART_DATA 0x08 |
194 | #define ES1371_REG_UART_STATUS 0x09 | 195 | #define ES1371_REG_UART_STATUS 0x09 |
195 | #define ES1371_REG_UART_CONTROL 0x09 | 196 | #define ES1371_REG_UART_CONTROL 0x09 |
196 | #define ES1371_REG_UART_TEST 0x0a | 197 | #define ES1371_REG_UART_TEST 0x0a |
197 | #define ES1371_REG_MEMPAGE 0x0c | 198 | #define ES1371_REG_MEMPAGE 0x0c |
198 | #define ES1371_REG_SRCONV 0x10 | 199 | #define ES1371_REG_SRCONV 0x10 |
199 | #define ES1371_REG_CODEC 0x14 | 200 | #define ES1371_REG_CODEC 0x14 |
200 | #define ES1371_REG_LEGACY 0x18 | 201 | #define ES1371_REG_LEGACY 0x18 |
201 | #define ES1371_REG_SERIAL_CONTROL 0x20 | 202 | #define ES1371_REG_SERIAL_CONTROL 0x20 |
202 | #define ES1371_REG_DAC1_SCOUNT 0x24 | 203 | #define ES1371_REG_DAC1_SCOUNT 0x24 |
203 | #define ES1371_REG_DAC2_SCOUNT 0x28 | 204 | #define ES1371_REG_DAC2_SCOUNT 0x28 |
204 | #define ES1371_REG_ADC_SCOUNT 0x2c | 205 | #define ES1371_REG_ADC_SCOUNT 0x2c |
205 | 206 | ||
206 | #define ES1371_REG_DAC1_FRAMEADR 0xc30 | 207 | #define ES1371_REG_DAC1_FRAMEADR 0xc30 |
207 | #define ES1371_REG_DAC1_FRAMECNT 0xc34 | 208 | #define ES1371_REG_DAC1_FRAMECNT 0xc34 |
208 | #define ES1371_REG_DAC2_FRAMEADR 0xc38 | 209 | #define ES1371_REG_DAC2_FRAMEADR 0xc38 |
209 | #define ES1371_REG_DAC2_FRAMECNT 0xc3c | 210 | #define ES1371_REG_DAC2_FRAMECNT 0xc3c |
210 | #define ES1371_REG_ADC_FRAMEADR 0xd30 | 211 | #define ES1371_REG_ADC_FRAMEADR 0xd30 |
211 | #define ES1371_REG_ADC_FRAMECNT 0xd34 | 212 | #define ES1371_REG_ADC_FRAMECNT 0xd34 |
212 | 213 | ||
213 | #define ES1371_FMT_U8_MONO 0 | 214 | #define ES1371_FMT_U8_MONO 0 |
214 | #define ES1371_FMT_U8_STEREO 1 | 215 | #define ES1371_FMT_U8_STEREO 1 |
215 | #define ES1371_FMT_S16_MONO 2 | 216 | #define ES1371_FMT_S16_MONO 2 |
216 | #define ES1371_FMT_S16_STEREO 3 | 217 | #define ES1371_FMT_S16_STEREO 3 |
217 | #define ES1371_FMT_STEREO 1 | 218 | #define ES1371_FMT_STEREO 1 |
218 | #define ES1371_FMT_S16 2 | 219 | #define ES1371_FMT_S16 2 |
219 | #define ES1371_FMT_MASK 3 | 220 | #define ES1371_FMT_MASK 3 |
220 | 221 | ||
221 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; | 222 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; |
222 | static const unsigned sample_shift[] = { 0, 1, 1, 2 }; | 223 | static const unsigned sample_shift[] = { 0, 1, 1, 2 }; |
223 | 224 | ||
224 | #define CTRL_RECEN_B 0x08000000 /* 1 = don't mix analog in to digital out */ | 225 | #define CTRL_RECEN_B 0x08000000 /* 1 = don't mix analog in to digital out */ |
225 | #define CTRL_SPDIFEN_B 0x04000000 | 226 | #define CTRL_SPDIFEN_B 0x04000000 |
226 | #define CTRL_JOY_SHIFT 24 | 227 | #define CTRL_JOY_SHIFT 24 |
227 | #define CTRL_JOY_MASK 3 | 228 | #define CTRL_JOY_MASK 3 |
228 | #define CTRL_JOY_200 0x00000000 /* joystick base address */ | 229 | #define CTRL_JOY_200 0x00000000 /* joystick base address */ |
229 | #define CTRL_JOY_208 0x01000000 | 230 | #define CTRL_JOY_208 0x01000000 |
230 | #define CTRL_JOY_210 0x02000000 | 231 | #define CTRL_JOY_210 0x02000000 |
231 | #define CTRL_JOY_218 0x03000000 | 232 | #define CTRL_JOY_218 0x03000000 |
232 | #define CTRL_GPIO_IN0 0x00100000 /* general purpose inputs/outputs */ | 233 | #define CTRL_GPIO_IN0 0x00100000 /* general purpose inputs/outputs */ |
233 | #define CTRL_GPIO_IN1 0x00200000 | 234 | #define CTRL_GPIO_IN1 0x00200000 |
234 | #define CTRL_GPIO_IN2 0x00400000 | 235 | #define CTRL_GPIO_IN2 0x00400000 |
235 | #define CTRL_GPIO_IN3 0x00800000 | 236 | #define CTRL_GPIO_IN3 0x00800000 |
236 | #define CTRL_GPIO_OUT0 0x00010000 | 237 | #define CTRL_GPIO_OUT0 0x00010000 |
237 | #define CTRL_GPIO_OUT1 0x00020000 | 238 | #define CTRL_GPIO_OUT1 0x00020000 |
238 | #define CTRL_GPIO_OUT2 0x00040000 | 239 | #define CTRL_GPIO_OUT2 0x00040000 |
239 | #define CTRL_GPIO_OUT3 0x00080000 | 240 | #define CTRL_GPIO_OUT3 0x00080000 |
240 | #define CTRL_MSFMTSEL 0x00008000 /* MPEG serial data fmt: 0 = Sony, 1 = I2S */ | 241 | #define CTRL_MSFMTSEL 0x00008000 /* MPEG serial data fmt: 0 = Sony, 1 = I2S */ |
241 | #define CTRL_SYNCRES 0x00004000 /* AC97 warm reset */ | 242 | #define CTRL_SYNCRES 0x00004000 /* AC97 warm reset */ |
242 | #define CTRL_ADCSTOP 0x00002000 /* stop ADC transfers */ | 243 | #define CTRL_ADCSTOP 0x00002000 /* stop ADC transfers */ |
243 | #define CTRL_PWR_INTRM 0x00001000 /* 1 = power level ints enabled */ | 244 | #define CTRL_PWR_INTRM 0x00001000 /* 1 = power level ints enabled */ |
244 | #define CTRL_M_CB 0x00000800 /* recording source: 0 = ADC, 1 = MPEG */ | 245 | #define CTRL_M_CB 0x00000800 /* recording source: 0 = ADC, 1 = MPEG */ |
245 | #define CTRL_CCB_INTRM 0x00000400 /* 1 = CCB "voice" ints enabled */ | 246 | #define CTRL_CCB_INTRM 0x00000400 /* 1 = CCB "voice" ints enabled */ |
246 | #define CTRL_PDLEV0 0x00000000 /* power down level */ | 247 | #define CTRL_PDLEV0 0x00000000 /* power down level */ |
247 | #define CTRL_PDLEV1 0x00000100 | 248 | #define CTRL_PDLEV1 0x00000100 |
248 | #define CTRL_PDLEV2 0x00000200 | 249 | #define CTRL_PDLEV2 0x00000200 |
249 | #define CTRL_PDLEV3 0x00000300 | 250 | #define CTRL_PDLEV3 0x00000300 |
250 | #define CTRL_BREQ 0x00000080 /* 1 = test mode (internal mem test) */ | 251 | #define CTRL_BREQ 0x00000080 /* 1 = test mode (internal mem test) */ |
251 | #define CTRL_DAC1_EN 0x00000040 /* enable DAC1 */ | 252 | #define CTRL_DAC1_EN 0x00000040 /* enable DAC1 */ |
252 | #define CTRL_DAC2_EN 0x00000020 /* enable DAC2 */ | 253 | #define CTRL_DAC2_EN 0x00000020 /* enable DAC2 */ |
253 | #define CTRL_ADC_EN 0x00000010 /* enable ADC */ | 254 | #define CTRL_ADC_EN 0x00000010 /* enable ADC */ |
254 | #define CTRL_UART_EN 0x00000008 /* enable MIDI uart */ | 255 | #define CTRL_UART_EN 0x00000008 /* enable MIDI uart */ |
255 | #define CTRL_JYSTK_EN 0x00000004 /* enable Joystick port */ | 256 | #define CTRL_JYSTK_EN 0x00000004 /* enable Joystick port */ |
256 | #define CTRL_XTALCLKDIS 0x00000002 /* 1 = disable crystal clock input */ | 257 | #define CTRL_XTALCLKDIS 0x00000002 /* 1 = disable crystal clock input */ |
257 | #define CTRL_PCICLKDIS 0x00000001 /* 1 = disable PCI clock distribution */ | 258 | #define CTRL_PCICLKDIS 0x00000001 /* 1 = disable PCI clock distribution */ |
258 | 259 | ||
259 | 260 | ||
260 | #define STAT_INTR 0x80000000 /* wired or of all interrupt bits */ | 261 | #define STAT_INTR 0x80000000 /* wired or of all interrupt bits */ |
261 | #define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */ | 262 | #define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */ |
262 | #define STAT_EN_SPDIF 0x00040000 /* enable S/PDIF circuitry */ | 263 | #define STAT_EN_SPDIF 0x00040000 /* enable S/PDIF circuitry */ |
263 | #define STAT_TS_SPDIF 0x00020000 /* test S/PDIF circuitry */ | 264 | #define STAT_TS_SPDIF 0x00020000 /* test S/PDIF circuitry */ |
264 | #define STAT_TESTMODE 0x00010000 /* test ASIC */ | 265 | #define STAT_TESTMODE 0x00010000 /* test ASIC */ |
265 | #define STAT_SYNC_ERR 0x00000100 /* 1 = codec sync error */ | 266 | #define STAT_SYNC_ERR 0x00000100 /* 1 = codec sync error */ |
266 | #define STAT_VC 0x000000c0 /* CCB int source, 0=DAC1, 1=DAC2, 2=ADC, 3=undef */ | 267 | #define STAT_VC 0x000000c0 /* CCB int source, 0=DAC1, 1=DAC2, 2=ADC, 3=undef */ |
267 | #define STAT_SH_VC 6 | 268 | #define STAT_SH_VC 6 |
268 | #define STAT_MPWR 0x00000020 /* power level interrupt */ | 269 | #define STAT_MPWR 0x00000020 /* power level interrupt */ |
269 | #define STAT_MCCB 0x00000010 /* CCB int pending */ | 270 | #define STAT_MCCB 0x00000010 /* CCB int pending */ |
270 | #define STAT_UART 0x00000008 /* UART int pending */ | 271 | #define STAT_UART 0x00000008 /* UART int pending */ |
271 | #define STAT_DAC1 0x00000004 /* DAC1 int pending */ | 272 | #define STAT_DAC1 0x00000004 /* DAC1 int pending */ |
272 | #define STAT_DAC2 0x00000002 /* DAC2 int pending */ | 273 | #define STAT_DAC2 0x00000002 /* DAC2 int pending */ |
273 | #define STAT_ADC 0x00000001 /* ADC int pending */ | 274 | #define STAT_ADC 0x00000001 /* ADC int pending */ |
274 | 275 | ||
275 | #define USTAT_RXINT 0x80 /* UART rx int pending */ | 276 | #define USTAT_RXINT 0x80 /* UART rx int pending */ |
276 | #define USTAT_TXINT 0x04 /* UART tx int pending */ | 277 | #define USTAT_TXINT 0x04 /* UART tx int pending */ |
277 | #define USTAT_TXRDY 0x02 /* UART tx ready */ | 278 | #define USTAT_TXRDY 0x02 /* UART tx ready */ |
278 | #define USTAT_RXRDY 0x01 /* UART rx ready */ | 279 | #define USTAT_RXRDY 0x01 /* UART rx ready */ |
279 | 280 | ||
280 | #define UCTRL_RXINTEN 0x80 /* 1 = enable RX ints */ | 281 | #define UCTRL_RXINTEN 0x80 /* 1 = enable RX ints */ |
281 | #define UCTRL_TXINTEN 0x60 /* TX int enable field mask */ | 282 | #define UCTRL_TXINTEN 0x60 /* TX int enable field mask */ |
282 | #define UCTRL_ENA_TXINT 0x20 /* enable TX int */ | 283 | #define UCTRL_ENA_TXINT 0x20 /* enable TX int */ |
283 | #define UCTRL_CNTRL 0x03 /* control field */ | 284 | #define UCTRL_CNTRL 0x03 /* control field */ |
284 | #define UCTRL_CNTRL_SWR 0x03 /* software reset command */ | 285 | #define UCTRL_CNTRL_SWR 0x03 /* software reset command */ |
285 | 286 | ||
286 | /* sample rate converter */ | 287 | /* sample rate converter */ |
287 | #define SRC_OKSTATE 1 | 288 | #define SRC_OKSTATE 1 |
288 | 289 | ||
289 | #define SRC_RAMADDR_MASK 0xfe000000 | 290 | #define SRC_RAMADDR_MASK 0xfe000000 |
290 | #define SRC_RAMADDR_SHIFT 25 | 291 | #define SRC_RAMADDR_SHIFT 25 |
291 | #define SRC_DAC1FREEZE (1UL << 21) | 292 | #define SRC_DAC1FREEZE (1UL << 21) |
292 | #define SRC_DAC2FREEZE (1UL << 20) | 293 | #define SRC_DAC2FREEZE (1UL << 20) |
293 | #define SRC_ADCFREEZE (1UL << 19) | 294 | #define SRC_ADCFREEZE (1UL << 19) |
294 | 295 | ||
295 | 296 | ||
296 | #define SRC_WE 0x01000000 /* read/write control for SRC RAM */ | 297 | #define SRC_WE 0x01000000 /* read/write control for SRC RAM */ |
297 | #define SRC_BUSY 0x00800000 /* SRC busy */ | 298 | #define SRC_BUSY 0x00800000 /* SRC busy */ |
298 | #define SRC_DIS 0x00400000 /* 1 = disable SRC */ | 299 | #define SRC_DIS 0x00400000 /* 1 = disable SRC */ |
299 | #define SRC_DDAC1 0x00200000 /* 1 = disable accum update for DAC1 */ | 300 | #define SRC_DDAC1 0x00200000 /* 1 = disable accum update for DAC1 */ |
300 | #define SRC_DDAC2 0x00100000 /* 1 = disable accum update for DAC2 */ | 301 | #define SRC_DDAC2 0x00100000 /* 1 = disable accum update for DAC2 */ |
301 | #define SRC_DADC 0x00080000 /* 1 = disable accum update for ADC2 */ | 302 | #define SRC_DADC 0x00080000 /* 1 = disable accum update for ADC2 */ |
302 | #define SRC_CTLMASK 0x00780000 | 303 | #define SRC_CTLMASK 0x00780000 |
303 | #define SRC_RAMDATA_MASK 0x0000ffff | 304 | #define SRC_RAMDATA_MASK 0x0000ffff |
304 | #define SRC_RAMDATA_SHIFT 0 | 305 | #define SRC_RAMDATA_SHIFT 0 |
305 | 306 | ||
306 | #define SRCREG_ADC 0x78 | 307 | #define SRCREG_ADC 0x78 |
307 | #define SRCREG_DAC1 0x70 | 308 | #define SRCREG_DAC1 0x70 |
308 | #define SRCREG_DAC2 0x74 | 309 | #define SRCREG_DAC2 0x74 |
309 | #define SRCREG_VOL_ADC 0x6c | 310 | #define SRCREG_VOL_ADC 0x6c |
310 | #define SRCREG_VOL_DAC1 0x7c | 311 | #define SRCREG_VOL_DAC1 0x7c |
311 | #define SRCREG_VOL_DAC2 0x7e | 312 | #define SRCREG_VOL_DAC2 0x7e |
312 | 313 | ||
313 | #define SRCREG_TRUNC_N 0x00 | 314 | #define SRCREG_TRUNC_N 0x00 |
314 | #define SRCREG_INT_REGS 0x01 | 315 | #define SRCREG_INT_REGS 0x01 |
315 | #define SRCREG_ACCUM_FRAC 0x02 | 316 | #define SRCREG_ACCUM_FRAC 0x02 |
316 | #define SRCREG_VFREQ_FRAC 0x03 | 317 | #define SRCREG_VFREQ_FRAC 0x03 |
317 | 318 | ||
318 | #define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */ | 319 | #define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */ |
319 | #define CODEC_PIADD_MASK 0x007f0000 | 320 | #define CODEC_PIADD_MASK 0x007f0000 |
320 | #define CODEC_PIADD_SHIFT 16 | 321 | #define CODEC_PIADD_SHIFT 16 |
321 | #define CODEC_PIDAT_MASK 0x0000ffff | 322 | #define CODEC_PIDAT_MASK 0x0000ffff |
322 | #define CODEC_PIDAT_SHIFT 0 | 323 | #define CODEC_PIDAT_SHIFT 0 |
323 | 324 | ||
324 | #define CODEC_RDY 0x80000000 /* AC97 read data valid */ | 325 | #define CODEC_RDY 0x80000000 /* AC97 read data valid */ |
325 | #define CODEC_WIP 0x40000000 /* AC97 write in progress */ | 326 | #define CODEC_WIP 0x40000000 /* AC97 write in progress */ |
326 | #define CODEC_PORD 0x00800000 /* 0 = write AC97 register */ | 327 | #define CODEC_PORD 0x00800000 /* 0 = write AC97 register */ |
327 | #define CODEC_POADD_MASK 0x007f0000 | 328 | #define CODEC_POADD_MASK 0x007f0000 |
328 | #define CODEC_POADD_SHIFT 16 | 329 | #define CODEC_POADD_SHIFT 16 |
329 | #define CODEC_PODAT_MASK 0x0000ffff | 330 | #define CODEC_PODAT_MASK 0x0000ffff |
330 | #define CODEC_PODAT_SHIFT 0 | 331 | #define CODEC_PODAT_SHIFT 0 |
331 | 332 | ||
332 | 333 | ||
333 | #define LEGACY_JFAST 0x80000000 /* fast joystick timing */ | 334 | #define LEGACY_JFAST 0x80000000 /* fast joystick timing */ |
334 | #define LEGACY_FIRQ 0x01000000 /* force IRQ */ | 335 | #define LEGACY_FIRQ 0x01000000 /* force IRQ */ |
335 | 336 | ||
336 | #define SCTRL_DACTEST 0x00400000 /* 1 = DAC test, test vector generation purposes */ | 337 | #define SCTRL_DACTEST 0x00400000 /* 1 = DAC test, test vector generation purposes */ |
337 | #define SCTRL_P2ENDINC 0x00380000 /* */ | 338 | #define SCTRL_P2ENDINC 0x00380000 /* */ |
338 | #define SCTRL_SH_P2ENDINC 19 | 339 | #define SCTRL_SH_P2ENDINC 19 |
339 | #define SCTRL_P2STINC 0x00070000 /* */ | 340 | #define SCTRL_P2STINC 0x00070000 /* */ |
340 | #define SCTRL_SH_P2STINC 16 | 341 | #define SCTRL_SH_P2STINC 16 |
341 | #define SCTRL_R1LOOPSEL 0x00008000 /* 0 = loop mode */ | 342 | #define SCTRL_R1LOOPSEL 0x00008000 /* 0 = loop mode */ |
342 | #define SCTRL_P2LOOPSEL 0x00004000 /* 0 = loop mode */ | 343 | #define SCTRL_P2LOOPSEL 0x00004000 /* 0 = loop mode */ |
343 | #define SCTRL_P1LOOPSEL 0x00002000 /* 0 = loop mode */ | 344 | #define SCTRL_P1LOOPSEL 0x00002000 /* 0 = loop mode */ |
344 | #define SCTRL_P2PAUSE 0x00001000 /* 1 = pause mode */ | 345 | #define SCTRL_P2PAUSE 0x00001000 /* 1 = pause mode */ |
345 | #define SCTRL_P1PAUSE 0x00000800 /* 1 = pause mode */ | 346 | #define SCTRL_P1PAUSE 0x00000800 /* 1 = pause mode */ |
346 | #define SCTRL_R1INTEN 0x00000400 /* enable interrupt */ | 347 | #define SCTRL_R1INTEN 0x00000400 /* enable interrupt */ |
347 | #define SCTRL_P2INTEN 0x00000200 /* enable interrupt */ | 348 | #define SCTRL_P2INTEN 0x00000200 /* enable interrupt */ |
348 | #define SCTRL_P1INTEN 0x00000100 /* enable interrupt */ | 349 | #define SCTRL_P1INTEN 0x00000100 /* enable interrupt */ |
349 | #define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for DAC1 */ | 350 | #define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for DAC1 */ |
350 | #define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample when disabled */ | 351 | #define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample when disabled */ |
351 | #define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */ | 352 | #define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */ |
352 | #define SCTRL_R1SMB 0x00000010 /* 1 = stereo */ | 353 | #define SCTRL_R1SMB 0x00000010 /* 1 = stereo */ |
353 | #define SCTRL_R1FMT 0x00000030 /* format mask */ | 354 | #define SCTRL_R1FMT 0x00000030 /* format mask */ |
354 | #define SCTRL_SH_R1FMT 4 | 355 | #define SCTRL_SH_R1FMT 4 |
355 | #define SCTRL_P2SEB 0x00000008 /* 1 = 16bit */ | 356 | #define SCTRL_P2SEB 0x00000008 /* 1 = 16bit */ |
356 | #define SCTRL_P2SMB 0x00000004 /* 1 = stereo */ | 357 | #define SCTRL_P2SMB 0x00000004 /* 1 = stereo */ |
357 | #define SCTRL_P2FMT 0x0000000c /* format mask */ | 358 | #define SCTRL_P2FMT 0x0000000c /* format mask */ |
358 | #define SCTRL_SH_P2FMT 2 | 359 | #define SCTRL_SH_P2FMT 2 |
359 | #define SCTRL_P1SEB 0x00000002 /* 1 = 16bit */ | 360 | #define SCTRL_P1SEB 0x00000002 /* 1 = 16bit */ |
360 | #define SCTRL_P1SMB 0x00000001 /* 1 = stereo */ | 361 | #define SCTRL_P1SMB 0x00000001 /* 1 = stereo */ |
361 | #define SCTRL_P1FMT 0x00000003 /* format mask */ | 362 | #define SCTRL_P1FMT 0x00000003 /* format mask */ |
362 | #define SCTRL_SH_P1FMT 0 | 363 | #define SCTRL_SH_P1FMT 0 |
363 | 364 | ||
364 | 365 | ||
365 | /* misc stuff */ | 366 | /* misc stuff */ |
366 | #define POLL_COUNT 0x1000 | 367 | #define POLL_COUNT 0x1000 |
367 | #define FMODE_DAC 4 /* slight misuse of mode_t */ | 368 | #define FMODE_DAC 4 /* slight misuse of mode_t */ |
368 | 369 | ||
369 | /* MIDI buffer sizes */ | 370 | /* MIDI buffer sizes */ |
370 | 371 | ||
371 | #define MIDIINBUF 256 | 372 | #define MIDIINBUF 256 |
372 | #define MIDIOUTBUF 256 | 373 | #define MIDIOUTBUF 256 |
373 | 374 | ||
374 | #define FMODE_MIDI_SHIFT 3 | 375 | #define FMODE_MIDI_SHIFT 3 |
375 | #define FMODE_MIDI_READ (FMODE_READ << FMODE_MIDI_SHIFT) | 376 | #define FMODE_MIDI_READ (FMODE_READ << FMODE_MIDI_SHIFT) |
376 | #define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT) | 377 | #define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT) |
377 | 378 | ||
378 | #define ES1371_MODULE_NAME "es1371" | 379 | #define ES1371_MODULE_NAME "es1371" |
379 | #define PFX ES1371_MODULE_NAME ": " | 380 | #define PFX ES1371_MODULE_NAME ": " |
380 | 381 | ||
381 | /* --------------------------------------------------------------------- */ | 382 | /* --------------------------------------------------------------------- */ |
382 | 383 | ||
383 | struct es1371_state { | 384 | struct es1371_state { |
384 | /* magic */ | 385 | /* magic */ |
385 | unsigned int magic; | 386 | unsigned int magic; |
386 | 387 | ||
387 | /* list of es1371 devices */ | 388 | /* list of es1371 devices */ |
388 | struct list_head devs; | 389 | struct list_head devs; |
389 | 390 | ||
390 | /* the corresponding pci_dev structure */ | 391 | /* the corresponding pci_dev structure */ |
391 | struct pci_dev *dev; | 392 | struct pci_dev *dev; |
392 | 393 | ||
393 | /* soundcore stuff */ | 394 | /* soundcore stuff */ |
394 | int dev_audio; | 395 | int dev_audio; |
395 | int dev_dac; | 396 | int dev_dac; |
396 | int dev_midi; | 397 | int dev_midi; |
397 | 398 | ||
398 | /* hardware resources */ | 399 | /* hardware resources */ |
399 | unsigned long io; /* long for SPARC */ | 400 | unsigned long io; /* long for SPARC */ |
400 | unsigned int irq; | 401 | unsigned int irq; |
401 | 402 | ||
402 | /* PCI ID's */ | 403 | /* PCI ID's */ |
403 | u16 vendor; | 404 | u16 vendor; |
404 | u16 device; | 405 | u16 device; |
405 | u8 rev; /* the chip revision */ | 406 | u8 rev; /* the chip revision */ |
406 | 407 | ||
407 | /* options */ | 408 | /* options */ |
408 | int spdif_volume; /* S/PDIF output is enabled if != -1 */ | 409 | int spdif_volume; /* S/PDIF output is enabled if != -1 */ |
409 | 410 | ||
410 | #ifdef ES1371_DEBUG | 411 | #ifdef ES1371_DEBUG |
411 | /* debug /proc entry */ | 412 | /* debug /proc entry */ |
412 | struct proc_dir_entry *ps; | 413 | struct proc_dir_entry *ps; |
413 | #endif /* ES1371_DEBUG */ | 414 | #endif /* ES1371_DEBUG */ |
414 | 415 | ||
415 | struct ac97_codec *codec; | 416 | struct ac97_codec *codec; |
416 | 417 | ||
417 | /* wave stuff */ | 418 | /* wave stuff */ |
418 | unsigned ctrl; | 419 | unsigned ctrl; |
419 | unsigned sctrl; | 420 | unsigned sctrl; |
420 | unsigned dac1rate, dac2rate, adcrate; | 421 | unsigned dac1rate, dac2rate, adcrate; |
421 | 422 | ||
422 | spinlock_t lock; | 423 | spinlock_t lock; |
423 | struct mutex open_mutex; | 424 | struct mutex open_mutex; |
424 | mode_t open_mode; | 425 | mode_t open_mode; |
425 | wait_queue_head_t open_wait; | 426 | wait_queue_head_t open_wait; |
426 | 427 | ||
427 | struct dmabuf { | 428 | struct dmabuf { |
428 | void *rawbuf; | 429 | void *rawbuf; |
429 | dma_addr_t dmaaddr; | 430 | dma_addr_t dmaaddr; |
430 | unsigned buforder; | 431 | unsigned buforder; |
431 | unsigned numfrag; | 432 | unsigned numfrag; |
432 | unsigned fragshift; | 433 | unsigned fragshift; |
433 | unsigned hwptr, swptr; | 434 | unsigned hwptr, swptr; |
434 | unsigned total_bytes; | 435 | unsigned total_bytes; |
435 | int count; | 436 | int count; |
436 | unsigned error; /* over/underrun */ | 437 | unsigned error; /* over/underrun */ |
437 | wait_queue_head_t wait; | 438 | wait_queue_head_t wait; |
438 | /* redundant, but makes calculations easier */ | 439 | /* redundant, but makes calculations easier */ |
439 | unsigned fragsize; | 440 | unsigned fragsize; |
440 | unsigned dmasize; | 441 | unsigned dmasize; |
441 | unsigned fragsamples; | 442 | unsigned fragsamples; |
442 | /* OSS stuff */ | 443 | /* OSS stuff */ |
443 | unsigned mapped:1; | 444 | unsigned mapped:1; |
444 | unsigned ready:1; | 445 | unsigned ready:1; |
445 | unsigned endcleared:1; | 446 | unsigned endcleared:1; |
446 | unsigned enabled:1; | 447 | unsigned enabled:1; |
447 | unsigned ossfragshift; | 448 | unsigned ossfragshift; |
448 | int ossmaxfrags; | 449 | int ossmaxfrags; |
449 | unsigned subdivision; | 450 | unsigned subdivision; |
450 | } dma_dac1, dma_dac2, dma_adc; | 451 | } dma_dac1, dma_dac2, dma_adc; |
451 | 452 | ||
452 | /* midi stuff */ | 453 | /* midi stuff */ |
453 | struct { | 454 | struct { |
454 | unsigned ird, iwr, icnt; | 455 | unsigned ird, iwr, icnt; |
455 | unsigned ord, owr, ocnt; | 456 | unsigned ord, owr, ocnt; |
456 | wait_queue_head_t iwait; | 457 | wait_queue_head_t iwait; |
457 | wait_queue_head_t owait; | 458 | wait_queue_head_t owait; |
458 | unsigned char ibuf[MIDIINBUF]; | 459 | unsigned char ibuf[MIDIINBUF]; |
459 | unsigned char obuf[MIDIOUTBUF]; | 460 | unsigned char obuf[MIDIOUTBUF]; |
460 | } midi; | 461 | } midi; |
461 | 462 | ||
462 | #ifdef SUPPORT_JOYSTICK | 463 | #ifdef SUPPORT_JOYSTICK |
463 | struct gameport *gameport; | 464 | struct gameport *gameport; |
464 | #endif | 465 | #endif |
465 | 466 | ||
466 | struct mutex sem; | 467 | struct mutex sem; |
467 | }; | 468 | }; |
468 | 469 | ||
469 | /* --------------------------------------------------------------------- */ | 470 | /* --------------------------------------------------------------------- */ |
470 | 471 | ||
471 | static LIST_HEAD(devs); | 472 | static LIST_HEAD(devs); |
472 | 473 | ||
473 | /* --------------------------------------------------------------------- */ | 474 | /* --------------------------------------------------------------------- */ |
474 | 475 | ||
475 | static inline unsigned ld2(unsigned int x) | 476 | static inline unsigned ld2(unsigned int x) |
476 | { | 477 | { |
477 | unsigned r = 0; | 478 | unsigned r = 0; |
478 | 479 | ||
479 | if (x >= 0x10000) { | 480 | if (x >= 0x10000) { |
480 | x >>= 16; | 481 | x >>= 16; |
481 | r += 16; | 482 | r += 16; |
482 | } | 483 | } |
483 | if (x >= 0x100) { | 484 | if (x >= 0x100) { |
484 | x >>= 8; | 485 | x >>= 8; |
485 | r += 8; | 486 | r += 8; |
486 | } | 487 | } |
487 | if (x >= 0x10) { | 488 | if (x >= 0x10) { |
488 | x >>= 4; | 489 | x >>= 4; |
489 | r += 4; | 490 | r += 4; |
490 | } | 491 | } |
491 | if (x >= 4) { | 492 | if (x >= 4) { |
492 | x >>= 2; | 493 | x >>= 2; |
493 | r += 2; | 494 | r += 2; |
494 | } | 495 | } |
495 | if (x >= 2) | 496 | if (x >= 2) |
496 | r++; | 497 | r++; |
497 | return r; | 498 | return r; |
498 | } | 499 | } |
499 | 500 | ||
500 | /* --------------------------------------------------------------------- */ | 501 | /* --------------------------------------------------------------------- */ |
501 | 502 | ||
502 | static unsigned wait_src_ready(struct es1371_state *s) | 503 | static unsigned wait_src_ready(struct es1371_state *s) |
503 | { | 504 | { |
504 | unsigned int t, r; | 505 | unsigned int t, r; |
505 | 506 | ||
506 | for (t = 0; t < POLL_COUNT; t++) { | 507 | for (t = 0; t < POLL_COUNT; t++) { |
507 | if (!((r = inl(s->io + ES1371_REG_SRCONV)) & SRC_BUSY)) | 508 | if (!((r = inl(s->io + ES1371_REG_SRCONV)) & SRC_BUSY)) |
508 | return r; | 509 | return r; |
509 | udelay(1); | 510 | udelay(1); |
510 | } | 511 | } |
511 | printk(KERN_DEBUG PFX "sample rate converter timeout r = 0x%08x\n", r); | 512 | printk(KERN_DEBUG PFX "sample rate converter timeout r = 0x%08x\n", r); |
512 | return r; | 513 | return r; |
513 | } | 514 | } |
514 | 515 | ||
515 | static unsigned src_read(struct es1371_state *s, unsigned reg) | 516 | static unsigned src_read(struct es1371_state *s, unsigned reg) |
516 | { | 517 | { |
517 | unsigned int temp,i,orig; | 518 | unsigned int temp,i,orig; |
518 | 519 | ||
519 | /* wait for ready */ | 520 | /* wait for ready */ |
520 | temp = wait_src_ready (s); | 521 | temp = wait_src_ready (s); |
521 | 522 | ||
522 | /* we can only access the SRC at certain times, make sure | 523 | /* we can only access the SRC at certain times, make sure |
523 | we're allowed to before we read */ | 524 | we're allowed to before we read */ |
524 | 525 | ||
525 | orig = temp; | 526 | orig = temp; |
526 | /* expose the SRC state bits */ | 527 | /* expose the SRC state bits */ |
527 | outl ( (temp & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT) | 0x10000UL, | 528 | outl ( (temp & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT) | 0x10000UL, |
528 | s->io + ES1371_REG_SRCONV); | 529 | s->io + ES1371_REG_SRCONV); |
529 | 530 | ||
530 | /* now, wait for busy and the correct time to read */ | 531 | /* now, wait for busy and the correct time to read */ |
531 | temp = wait_src_ready (s); | 532 | temp = wait_src_ready (s); |
532 | 533 | ||
533 | if ( (temp & 0x00870000UL ) != ( SRC_OKSTATE << 16 )){ | 534 | if ( (temp & 0x00870000UL ) != ( SRC_OKSTATE << 16 )){ |
534 | /* wait for the right state */ | 535 | /* wait for the right state */ |
535 | for (i=0; i<POLL_COUNT; i++){ | 536 | for (i=0; i<POLL_COUNT; i++){ |
536 | temp = inl (s->io + ES1371_REG_SRCONV); | 537 | temp = inl (s->io + ES1371_REG_SRCONV); |
537 | if ( (temp & 0x00870000UL ) == ( SRC_OKSTATE << 16 )) | 538 | if ( (temp & 0x00870000UL ) == ( SRC_OKSTATE << 16 )) |
538 | break; | 539 | break; |
539 | } | 540 | } |
540 | } | 541 | } |
541 | 542 | ||
542 | /* hide the state bits */ | 543 | /* hide the state bits */ |
543 | outl ((orig & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT), s->io + ES1371_REG_SRCONV); | 544 | outl ((orig & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT), s->io + ES1371_REG_SRCONV); |
544 | return temp; | 545 | return temp; |
545 | 546 | ||
546 | 547 | ||
547 | } | 548 | } |
548 | 549 | ||
549 | static void src_write(struct es1371_state *s, unsigned reg, unsigned data) | 550 | static void src_write(struct es1371_state *s, unsigned reg, unsigned data) |
550 | { | 551 | { |
551 | 552 | ||
552 | unsigned int r; | 553 | unsigned int r; |
553 | 554 | ||
554 | r = wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC); | 555 | r = wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC); |
555 | r |= (reg << SRC_RAMADDR_SHIFT) & SRC_RAMADDR_MASK; | 556 | r |= (reg << SRC_RAMADDR_SHIFT) & SRC_RAMADDR_MASK; |
556 | r |= (data << SRC_RAMDATA_SHIFT) & SRC_RAMDATA_MASK; | 557 | r |= (data << SRC_RAMDATA_SHIFT) & SRC_RAMDATA_MASK; |
557 | outl(r | SRC_WE, s->io + ES1371_REG_SRCONV); | 558 | outl(r | SRC_WE, s->io + ES1371_REG_SRCONV); |
558 | 559 | ||
559 | } | 560 | } |
560 | 561 | ||
561 | /* --------------------------------------------------------------------- */ | 562 | /* --------------------------------------------------------------------- */ |
562 | 563 | ||
563 | /* most of the following here is black magic */ | 564 | /* most of the following here is black magic */ |
564 | static void set_adc_rate(struct es1371_state *s, unsigned rate) | 565 | static void set_adc_rate(struct es1371_state *s, unsigned rate) |
565 | { | 566 | { |
566 | unsigned long flags; | 567 | unsigned long flags; |
567 | unsigned int n, truncm, freq; | 568 | unsigned int n, truncm, freq; |
568 | 569 | ||
569 | if (rate > 48000) | 570 | if (rate > 48000) |
570 | rate = 48000; | 571 | rate = 48000; |
571 | if (rate < 4000) | 572 | if (rate < 4000) |
572 | rate = 4000; | 573 | rate = 4000; |
573 | n = rate / 3000; | 574 | n = rate / 3000; |
574 | if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) | 575 | if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) |
575 | n--; | 576 | n--; |
576 | truncm = (21 * n - 1) | 1; | 577 | truncm = (21 * n - 1) | 1; |
577 | freq = ((48000UL << 15) / rate) * n; | 578 | freq = ((48000UL << 15) / rate) * n; |
578 | s->adcrate = (48000UL << 15) / (freq / n); | 579 | s->adcrate = (48000UL << 15) / (freq / n); |
579 | spin_lock_irqsave(&s->lock, flags); | 580 | spin_lock_irqsave(&s->lock, flags); |
580 | if (rate >= 24000) { | 581 | if (rate >= 24000) { |
581 | if (truncm > 239) | 582 | if (truncm > 239) |
582 | truncm = 239; | 583 | truncm = 239; |
583 | src_write(s, SRCREG_ADC+SRCREG_TRUNC_N, | 584 | src_write(s, SRCREG_ADC+SRCREG_TRUNC_N, |
584 | (((239 - truncm) >> 1) << 9) | (n << 4)); | 585 | (((239 - truncm) >> 1) << 9) | (n << 4)); |
585 | } else { | 586 | } else { |
586 | if (truncm > 119) | 587 | if (truncm > 119) |
587 | truncm = 119; | 588 | truncm = 119; |
588 | src_write(s, SRCREG_ADC+SRCREG_TRUNC_N, | 589 | src_write(s, SRCREG_ADC+SRCREG_TRUNC_N, |
589 | 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4)); | 590 | 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4)); |
590 | } | 591 | } |
591 | src_write(s, SRCREG_ADC+SRCREG_INT_REGS, | 592 | src_write(s, SRCREG_ADC+SRCREG_INT_REGS, |
592 | (src_read(s, SRCREG_ADC+SRCREG_INT_REGS) & 0x00ff) | | 593 | (src_read(s, SRCREG_ADC+SRCREG_INT_REGS) & 0x00ff) | |
593 | ((freq >> 5) & 0xfc00)); | 594 | ((freq >> 5) & 0xfc00)); |
594 | src_write(s, SRCREG_ADC+SRCREG_VFREQ_FRAC, freq & 0x7fff); | 595 | src_write(s, SRCREG_ADC+SRCREG_VFREQ_FRAC, freq & 0x7fff); |
595 | src_write(s, SRCREG_VOL_ADC, n << 8); | 596 | src_write(s, SRCREG_VOL_ADC, n << 8); |
596 | src_write(s, SRCREG_VOL_ADC+1, n << 8); | 597 | src_write(s, SRCREG_VOL_ADC+1, n << 8); |
597 | spin_unlock_irqrestore(&s->lock, flags); | 598 | spin_unlock_irqrestore(&s->lock, flags); |
598 | } | 599 | } |
599 | 600 | ||
600 | 601 | ||
601 | static void set_dac1_rate(struct es1371_state *s, unsigned rate) | 602 | static void set_dac1_rate(struct es1371_state *s, unsigned rate) |
602 | { | 603 | { |
603 | unsigned long flags; | 604 | unsigned long flags; |
604 | unsigned int freq, r; | 605 | unsigned int freq, r; |
605 | 606 | ||
606 | if (rate > 48000) | 607 | if (rate > 48000) |
607 | rate = 48000; | 608 | rate = 48000; |
608 | if (rate < 4000) | 609 | if (rate < 4000) |
609 | rate = 4000; | 610 | rate = 4000; |
610 | freq = ((rate << 15) + 1500) / 3000; | 611 | freq = ((rate << 15) + 1500) / 3000; |
611 | s->dac1rate = (freq * 3000 + 16384) >> 15; | 612 | s->dac1rate = (freq * 3000 + 16384) >> 15; |
612 | spin_lock_irqsave(&s->lock, flags); | 613 | spin_lock_irqsave(&s->lock, flags); |
613 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)) | SRC_DDAC1; | 614 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)) | SRC_DDAC1; |
614 | outl(r, s->io + ES1371_REG_SRCONV); | 615 | outl(r, s->io + ES1371_REG_SRCONV); |
615 | src_write(s, SRCREG_DAC1+SRCREG_INT_REGS, | 616 | src_write(s, SRCREG_DAC1+SRCREG_INT_REGS, |
616 | (src_read(s, SRCREG_DAC1+SRCREG_INT_REGS) & 0x00ff) | | 617 | (src_read(s, SRCREG_DAC1+SRCREG_INT_REGS) & 0x00ff) | |
617 | ((freq >> 5) & 0xfc00)); | 618 | ((freq >> 5) & 0xfc00)); |
618 | src_write(s, SRCREG_DAC1+SRCREG_VFREQ_FRAC, freq & 0x7fff); | 619 | src_write(s, SRCREG_DAC1+SRCREG_VFREQ_FRAC, freq & 0x7fff); |
619 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)); | 620 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)); |
620 | outl(r, s->io + ES1371_REG_SRCONV); | 621 | outl(r, s->io + ES1371_REG_SRCONV); |
621 | spin_unlock_irqrestore(&s->lock, flags); | 622 | spin_unlock_irqrestore(&s->lock, flags); |
622 | } | 623 | } |
623 | 624 | ||
624 | static void set_dac2_rate(struct es1371_state *s, unsigned rate) | 625 | static void set_dac2_rate(struct es1371_state *s, unsigned rate) |
625 | { | 626 | { |
626 | unsigned long flags; | 627 | unsigned long flags; |
627 | unsigned int freq, r; | 628 | unsigned int freq, r; |
628 | 629 | ||
629 | if (rate > 48000) | 630 | if (rate > 48000) |
630 | rate = 48000; | 631 | rate = 48000; |
631 | if (rate < 4000) | 632 | if (rate < 4000) |
632 | rate = 4000; | 633 | rate = 4000; |
633 | freq = ((rate << 15) + 1500) / 3000; | 634 | freq = ((rate << 15) + 1500) / 3000; |
634 | s->dac2rate = (freq * 3000 + 16384) >> 15; | 635 | s->dac2rate = (freq * 3000 + 16384) >> 15; |
635 | spin_lock_irqsave(&s->lock, flags); | 636 | spin_lock_irqsave(&s->lock, flags); |
636 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)) | SRC_DDAC2; | 637 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)) | SRC_DDAC2; |
637 | outl(r, s->io + ES1371_REG_SRCONV); | 638 | outl(r, s->io + ES1371_REG_SRCONV); |
638 | src_write(s, SRCREG_DAC2+SRCREG_INT_REGS, | 639 | src_write(s, SRCREG_DAC2+SRCREG_INT_REGS, |
639 | (src_read(s, SRCREG_DAC2+SRCREG_INT_REGS) & 0x00ff) | | 640 | (src_read(s, SRCREG_DAC2+SRCREG_INT_REGS) & 0x00ff) | |
640 | ((freq >> 5) & 0xfc00)); | 641 | ((freq >> 5) & 0xfc00)); |
641 | src_write(s, SRCREG_DAC2+SRCREG_VFREQ_FRAC, freq & 0x7fff); | 642 | src_write(s, SRCREG_DAC2+SRCREG_VFREQ_FRAC, freq & 0x7fff); |
642 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)); | 643 | r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)); |
643 | outl(r, s->io + ES1371_REG_SRCONV); | 644 | outl(r, s->io + ES1371_REG_SRCONV); |
644 | spin_unlock_irqrestore(&s->lock, flags); | 645 | spin_unlock_irqrestore(&s->lock, flags); |
645 | } | 646 | } |
646 | 647 | ||
647 | /* --------------------------------------------------------------------- */ | 648 | /* --------------------------------------------------------------------- */ |
648 | 649 | ||
649 | static void __devinit src_init(struct es1371_state *s) | 650 | static void __devinit src_init(struct es1371_state *s) |
650 | { | 651 | { |
651 | unsigned int i; | 652 | unsigned int i; |
652 | 653 | ||
653 | /* before we enable or disable the SRC we need | 654 | /* before we enable or disable the SRC we need |
654 | to wait for it to become ready */ | 655 | to wait for it to become ready */ |
655 | wait_src_ready(s); | 656 | wait_src_ready(s); |
656 | 657 | ||
657 | outl(SRC_DIS, s->io + ES1371_REG_SRCONV); | 658 | outl(SRC_DIS, s->io + ES1371_REG_SRCONV); |
658 | 659 | ||
659 | for (i = 0; i < 0x80; i++) | 660 | for (i = 0; i < 0x80; i++) |
660 | src_write(s, i, 0); | 661 | src_write(s, i, 0); |
661 | 662 | ||
662 | src_write(s, SRCREG_DAC1+SRCREG_TRUNC_N, 16 << 4); | 663 | src_write(s, SRCREG_DAC1+SRCREG_TRUNC_N, 16 << 4); |
663 | src_write(s, SRCREG_DAC1+SRCREG_INT_REGS, 16 << 10); | 664 | src_write(s, SRCREG_DAC1+SRCREG_INT_REGS, 16 << 10); |
664 | src_write(s, SRCREG_DAC2+SRCREG_TRUNC_N, 16 << 4); | 665 | src_write(s, SRCREG_DAC2+SRCREG_TRUNC_N, 16 << 4); |
665 | src_write(s, SRCREG_DAC2+SRCREG_INT_REGS, 16 << 10); | 666 | src_write(s, SRCREG_DAC2+SRCREG_INT_REGS, 16 << 10); |
666 | src_write(s, SRCREG_VOL_ADC, 1 << 12); | 667 | src_write(s, SRCREG_VOL_ADC, 1 << 12); |
667 | src_write(s, SRCREG_VOL_ADC+1, 1 << 12); | 668 | src_write(s, SRCREG_VOL_ADC+1, 1 << 12); |
668 | src_write(s, SRCREG_VOL_DAC1, 1 << 12); | 669 | src_write(s, SRCREG_VOL_DAC1, 1 << 12); |
669 | src_write(s, SRCREG_VOL_DAC1+1, 1 << 12); | 670 | src_write(s, SRCREG_VOL_DAC1+1, 1 << 12); |
670 | src_write(s, SRCREG_VOL_DAC2, 1 << 12); | 671 | src_write(s, SRCREG_VOL_DAC2, 1 << 12); |
671 | src_write(s, SRCREG_VOL_DAC2+1, 1 << 12); | 672 | src_write(s, SRCREG_VOL_DAC2+1, 1 << 12); |
672 | set_adc_rate(s, 22050); | 673 | set_adc_rate(s, 22050); |
673 | set_dac1_rate(s, 22050); | 674 | set_dac1_rate(s, 22050); |
674 | set_dac2_rate(s, 22050); | 675 | set_dac2_rate(s, 22050); |
675 | 676 | ||
676 | /* WARNING: | 677 | /* WARNING: |
677 | * enabling the sample rate converter without properly programming | 678 | * enabling the sample rate converter without properly programming |
678 | * its parameters causes the chip to lock up (the SRC busy bit will | 679 | * its parameters causes the chip to lock up (the SRC busy bit will |
679 | * be stuck high, and I've found no way to rectify this other than | 680 | * be stuck high, and I've found no way to rectify this other than |
680 | * power cycle) | 681 | * power cycle) |
681 | */ | 682 | */ |
682 | wait_src_ready(s); | 683 | wait_src_ready(s); |
683 | outl(0, s->io+ES1371_REG_SRCONV); | 684 | outl(0, s->io+ES1371_REG_SRCONV); |
684 | } | 685 | } |
685 | 686 | ||
686 | /* --------------------------------------------------------------------- */ | 687 | /* --------------------------------------------------------------------- */ |
687 | 688 | ||
688 | static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data) | 689 | static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data) |
689 | { | 690 | { |
690 | struct es1371_state *s = (struct es1371_state *)codec->private_data; | 691 | struct es1371_state *s = (struct es1371_state *)codec->private_data; |
691 | unsigned long flags; | 692 | unsigned long flags; |
692 | unsigned t, x; | 693 | unsigned t, x; |
693 | 694 | ||
694 | spin_lock_irqsave(&s->lock, flags); | 695 | spin_lock_irqsave(&s->lock, flags); |
695 | for (t = 0; t < POLL_COUNT; t++) | 696 | for (t = 0; t < POLL_COUNT; t++) |
696 | if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) | 697 | if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) |
697 | break; | 698 | break; |
698 | 699 | ||
699 | /* save the current state for later */ | 700 | /* save the current state for later */ |
700 | x = wait_src_ready(s); | 701 | x = wait_src_ready(s); |
701 | 702 | ||
702 | /* enable SRC state data in SRC mux */ | 703 | /* enable SRC state data in SRC mux */ |
703 | outl((x & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)) | 0x00010000, | 704 | outl((x & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)) | 0x00010000, |
704 | s->io+ES1371_REG_SRCONV); | 705 | s->io+ES1371_REG_SRCONV); |
705 | 706 | ||
706 | /* wait for not busy (state 0) first to avoid | 707 | /* wait for not busy (state 0) first to avoid |
707 | transition states */ | 708 | transition states */ |
708 | for (t=0; t<POLL_COUNT; t++){ | 709 | for (t=0; t<POLL_COUNT; t++){ |
709 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 ) | 710 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 ) |
710 | break; | 711 | break; |
711 | udelay(1); | 712 | udelay(1); |
712 | } | 713 | } |
713 | 714 | ||
714 | /* wait for a SAFE time to write addr/data and then do it, dammit */ | 715 | /* wait for a SAFE time to write addr/data and then do it, dammit */ |
715 | for (t=0; t<POLL_COUNT; t++){ | 716 | for (t=0; t<POLL_COUNT; t++){ |
716 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000) | 717 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000) |
717 | break; | 718 | break; |
718 | udelay(1); | 719 | udelay(1); |
719 | } | 720 | } |
720 | 721 | ||
721 | outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | | 722 | outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | |
722 | ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK), s->io+ES1371_REG_CODEC); | 723 | ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK), s->io+ES1371_REG_CODEC); |
723 | 724 | ||
724 | /* restore SRC reg */ | 725 | /* restore SRC reg */ |
725 | wait_src_ready(s); | 726 | wait_src_ready(s); |
726 | outl(x, s->io+ES1371_REG_SRCONV); | 727 | outl(x, s->io+ES1371_REG_SRCONV); |
727 | spin_unlock_irqrestore(&s->lock, flags); | 728 | spin_unlock_irqrestore(&s->lock, flags); |
728 | } | 729 | } |
729 | 730 | ||
730 | static u16 rdcodec(struct ac97_codec *codec, u8 addr) | 731 | static u16 rdcodec(struct ac97_codec *codec, u8 addr) |
731 | { | 732 | { |
732 | struct es1371_state *s = (struct es1371_state *)codec->private_data; | 733 | struct es1371_state *s = (struct es1371_state *)codec->private_data; |
733 | unsigned long flags; | 734 | unsigned long flags; |
734 | unsigned t, x; | 735 | unsigned t, x; |
735 | 736 | ||
736 | spin_lock_irqsave(&s->lock, flags); | 737 | spin_lock_irqsave(&s->lock, flags); |
737 | 738 | ||
738 | /* wait for WIP to go away */ | 739 | /* wait for WIP to go away */ |
739 | for (t = 0; t < 0x1000; t++) | 740 | for (t = 0; t < 0x1000; t++) |
740 | if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) | 741 | if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) |
741 | break; | 742 | break; |
742 | 743 | ||
743 | /* save the current state for later */ | 744 | /* save the current state for later */ |
744 | x = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)); | 745 | x = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)); |
745 | 746 | ||
746 | /* enable SRC state data in SRC mux */ | 747 | /* enable SRC state data in SRC mux */ |
747 | outl( x | 0x00010000, | 748 | outl( x | 0x00010000, |
748 | s->io+ES1371_REG_SRCONV); | 749 | s->io+ES1371_REG_SRCONV); |
749 | 750 | ||
750 | /* wait for not busy (state 0) first to avoid | 751 | /* wait for not busy (state 0) first to avoid |
751 | transition states */ | 752 | transition states */ |
752 | for (t=0; t<POLL_COUNT; t++){ | 753 | for (t=0; t<POLL_COUNT; t++){ |
753 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 ) | 754 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 ) |
754 | break; | 755 | break; |
755 | udelay(1); | 756 | udelay(1); |
756 | } | 757 | } |
757 | 758 | ||
758 | /* wait for a SAFE time to write addr/data and then do it, dammit */ | 759 | /* wait for a SAFE time to write addr/data and then do it, dammit */ |
759 | for (t=0; t<POLL_COUNT; t++){ | 760 | for (t=0; t<POLL_COUNT; t++){ |
760 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000) | 761 | if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000) |
761 | break; | 762 | break; |
762 | udelay(1); | 763 | udelay(1); |
763 | } | 764 | } |
764 | 765 | ||
765 | outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD, s->io+ES1371_REG_CODEC); | 766 | outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD, s->io+ES1371_REG_CODEC); |
766 | /* restore SRC reg */ | 767 | /* restore SRC reg */ |
767 | wait_src_ready(s); | 768 | wait_src_ready(s); |
768 | outl(x, s->io+ES1371_REG_SRCONV); | 769 | outl(x, s->io+ES1371_REG_SRCONV); |
769 | 770 | ||
770 | /* wait for WIP again */ | 771 | /* wait for WIP again */ |
771 | for (t = 0; t < 0x1000; t++) | 772 | for (t = 0; t < 0x1000; t++) |
772 | if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) | 773 | if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP)) |
773 | break; | 774 | break; |
774 | 775 | ||
775 | /* now wait for the stinkin' data (RDY) */ | 776 | /* now wait for the stinkin' data (RDY) */ |
776 | for (t = 0; t < POLL_COUNT; t++) | 777 | for (t = 0; t < POLL_COUNT; t++) |
777 | if ((x = inl(s->io+ES1371_REG_CODEC)) & CODEC_RDY) | 778 | if ((x = inl(s->io+ES1371_REG_CODEC)) & CODEC_RDY) |
778 | break; | 779 | break; |
779 | 780 | ||
780 | spin_unlock_irqrestore(&s->lock, flags); | 781 | spin_unlock_irqrestore(&s->lock, flags); |
781 | return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT); | 782 | return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT); |
782 | } | 783 | } |
783 | 784 | ||
784 | /* --------------------------------------------------------------------- */ | 785 | /* --------------------------------------------------------------------- */ |
785 | 786 | ||
786 | static inline void stop_adc(struct es1371_state *s) | 787 | static inline void stop_adc(struct es1371_state *s) |
787 | { | 788 | { |
788 | unsigned long flags; | 789 | unsigned long flags; |
789 | 790 | ||
790 | spin_lock_irqsave(&s->lock, flags); | 791 | spin_lock_irqsave(&s->lock, flags); |
791 | s->ctrl &= ~CTRL_ADC_EN; | 792 | s->ctrl &= ~CTRL_ADC_EN; |
792 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 793 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
793 | spin_unlock_irqrestore(&s->lock, flags); | 794 | spin_unlock_irqrestore(&s->lock, flags); |
794 | } | 795 | } |
795 | 796 | ||
796 | static inline void stop_dac1(struct es1371_state *s) | 797 | static inline void stop_dac1(struct es1371_state *s) |
797 | { | 798 | { |
798 | unsigned long flags; | 799 | unsigned long flags; |
799 | 800 | ||
800 | spin_lock_irqsave(&s->lock, flags); | 801 | spin_lock_irqsave(&s->lock, flags); |
801 | s->ctrl &= ~CTRL_DAC1_EN; | 802 | s->ctrl &= ~CTRL_DAC1_EN; |
802 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 803 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
803 | spin_unlock_irqrestore(&s->lock, flags); | 804 | spin_unlock_irqrestore(&s->lock, flags); |
804 | } | 805 | } |
805 | 806 | ||
806 | static inline void stop_dac2(struct es1371_state *s) | 807 | static inline void stop_dac2(struct es1371_state *s) |
807 | { | 808 | { |
808 | unsigned long flags; | 809 | unsigned long flags; |
809 | 810 | ||
810 | spin_lock_irqsave(&s->lock, flags); | 811 | spin_lock_irqsave(&s->lock, flags); |
811 | s->ctrl &= ~CTRL_DAC2_EN; | 812 | s->ctrl &= ~CTRL_DAC2_EN; |
812 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 813 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
813 | spin_unlock_irqrestore(&s->lock, flags); | 814 | spin_unlock_irqrestore(&s->lock, flags); |
814 | } | 815 | } |
815 | 816 | ||
816 | static void start_dac1(struct es1371_state *s) | 817 | static void start_dac1(struct es1371_state *s) |
817 | { | 818 | { |
818 | unsigned long flags; | 819 | unsigned long flags; |
819 | unsigned fragremain, fshift; | 820 | unsigned fragremain, fshift; |
820 | 821 | ||
821 | spin_lock_irqsave(&s->lock, flags); | 822 | spin_lock_irqsave(&s->lock, flags); |
822 | if (!(s->ctrl & CTRL_DAC1_EN) && (s->dma_dac1.mapped || s->dma_dac1.count > 0) | 823 | if (!(s->ctrl & CTRL_DAC1_EN) && (s->dma_dac1.mapped || s->dma_dac1.count > 0) |
823 | && s->dma_dac1.ready) { | 824 | && s->dma_dac1.ready) { |
824 | s->ctrl |= CTRL_DAC1_EN; | 825 | s->ctrl |= CTRL_DAC1_EN; |
825 | s->sctrl = (s->sctrl & ~(SCTRL_P1LOOPSEL | SCTRL_P1PAUSE | SCTRL_P1SCTRLD)) | SCTRL_P1INTEN; | 826 | s->sctrl = (s->sctrl & ~(SCTRL_P1LOOPSEL | SCTRL_P1PAUSE | SCTRL_P1SCTRLD)) | SCTRL_P1INTEN; |
826 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 827 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
827 | fragremain = ((- s->dma_dac1.hwptr) & (s->dma_dac1.fragsize-1)); | 828 | fragremain = ((- s->dma_dac1.hwptr) & (s->dma_dac1.fragsize-1)); |
828 | fshift = sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT]; | 829 | fshift = sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT]; |
829 | if (fragremain < 2*fshift) | 830 | if (fragremain < 2*fshift) |
830 | fragremain = s->dma_dac1.fragsize; | 831 | fragremain = s->dma_dac1.fragsize; |
831 | outl((fragremain >> fshift) - 1, s->io+ES1371_REG_DAC1_SCOUNT); | 832 | outl((fragremain >> fshift) - 1, s->io+ES1371_REG_DAC1_SCOUNT); |
832 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 833 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
833 | outl((s->dma_dac1.fragsize >> fshift) - 1, s->io+ES1371_REG_DAC1_SCOUNT); | 834 | outl((s->dma_dac1.fragsize >> fshift) - 1, s->io+ES1371_REG_DAC1_SCOUNT); |
834 | } | 835 | } |
835 | spin_unlock_irqrestore(&s->lock, flags); | 836 | spin_unlock_irqrestore(&s->lock, flags); |
836 | } | 837 | } |
837 | 838 | ||
838 | static void start_dac2(struct es1371_state *s) | 839 | static void start_dac2(struct es1371_state *s) |
839 | { | 840 | { |
840 | unsigned long flags; | 841 | unsigned long flags; |
841 | unsigned fragremain, fshift; | 842 | unsigned fragremain, fshift; |
842 | 843 | ||
843 | spin_lock_irqsave(&s->lock, flags); | 844 | spin_lock_irqsave(&s->lock, flags); |
844 | if (!(s->ctrl & CTRL_DAC2_EN) && (s->dma_dac2.mapped || s->dma_dac2.count > 0) | 845 | if (!(s->ctrl & CTRL_DAC2_EN) && (s->dma_dac2.mapped || s->dma_dac2.count > 0) |
845 | && s->dma_dac2.ready) { | 846 | && s->dma_dac2.ready) { |
846 | s->ctrl |= CTRL_DAC2_EN; | 847 | s->ctrl |= CTRL_DAC2_EN; |
847 | s->sctrl = (s->sctrl & ~(SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | SCTRL_P2DACSEN | | 848 | s->sctrl = (s->sctrl & ~(SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | SCTRL_P2DACSEN | |
848 | SCTRL_P2ENDINC | SCTRL_P2STINC)) | SCTRL_P2INTEN | | 849 | SCTRL_P2ENDINC | SCTRL_P2STINC)) | SCTRL_P2INTEN | |
849 | (((s->sctrl & SCTRL_P2FMT) ? 2 : 1) << SCTRL_SH_P2ENDINC) | | 850 | (((s->sctrl & SCTRL_P2FMT) ? 2 : 1) << SCTRL_SH_P2ENDINC) | |
850 | (0 << SCTRL_SH_P2STINC); | 851 | (0 << SCTRL_SH_P2STINC); |
851 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 852 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
852 | fragremain = ((- s->dma_dac2.hwptr) & (s->dma_dac2.fragsize-1)); | 853 | fragremain = ((- s->dma_dac2.hwptr) & (s->dma_dac2.fragsize-1)); |
853 | fshift = sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT]; | 854 | fshift = sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT]; |
854 | if (fragremain < 2*fshift) | 855 | if (fragremain < 2*fshift) |
855 | fragremain = s->dma_dac2.fragsize; | 856 | fragremain = s->dma_dac2.fragsize; |
856 | outl((fragremain >> fshift) - 1, s->io+ES1371_REG_DAC2_SCOUNT); | 857 | outl((fragremain >> fshift) - 1, s->io+ES1371_REG_DAC2_SCOUNT); |
857 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 858 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
858 | outl((s->dma_dac2.fragsize >> fshift) - 1, s->io+ES1371_REG_DAC2_SCOUNT); | 859 | outl((s->dma_dac2.fragsize >> fshift) - 1, s->io+ES1371_REG_DAC2_SCOUNT); |
859 | } | 860 | } |
860 | spin_unlock_irqrestore(&s->lock, flags); | 861 | spin_unlock_irqrestore(&s->lock, flags); |
861 | } | 862 | } |
862 | 863 | ||
863 | static void start_adc(struct es1371_state *s) | 864 | static void start_adc(struct es1371_state *s) |
864 | { | 865 | { |
865 | unsigned long flags; | 866 | unsigned long flags; |
866 | unsigned fragremain, fshift; | 867 | unsigned fragremain, fshift; |
867 | 868 | ||
868 | spin_lock_irqsave(&s->lock, flags); | 869 | spin_lock_irqsave(&s->lock, flags); |
869 | if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) | 870 | if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) |
870 | && s->dma_adc.ready) { | 871 | && s->dma_adc.ready) { |
871 | s->ctrl |= CTRL_ADC_EN; | 872 | s->ctrl |= CTRL_ADC_EN; |
872 | s->sctrl = (s->sctrl & ~SCTRL_R1LOOPSEL) | SCTRL_R1INTEN; | 873 | s->sctrl = (s->sctrl & ~SCTRL_R1LOOPSEL) | SCTRL_R1INTEN; |
873 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 874 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
874 | fragremain = ((- s->dma_adc.hwptr) & (s->dma_adc.fragsize-1)); | 875 | fragremain = ((- s->dma_adc.hwptr) & (s->dma_adc.fragsize-1)); |
875 | fshift = sample_shift[(s->sctrl & SCTRL_R1FMT) >> SCTRL_SH_R1FMT]; | 876 | fshift = sample_shift[(s->sctrl & SCTRL_R1FMT) >> SCTRL_SH_R1FMT]; |
876 | if (fragremain < 2*fshift) | 877 | if (fragremain < 2*fshift) |
877 | fragremain = s->dma_adc.fragsize; | 878 | fragremain = s->dma_adc.fragsize; |
878 | outl((fragremain >> fshift) - 1, s->io+ES1371_REG_ADC_SCOUNT); | 879 | outl((fragremain >> fshift) - 1, s->io+ES1371_REG_ADC_SCOUNT); |
879 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 880 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
880 | outl((s->dma_adc.fragsize >> fshift) - 1, s->io+ES1371_REG_ADC_SCOUNT); | 881 | outl((s->dma_adc.fragsize >> fshift) - 1, s->io+ES1371_REG_ADC_SCOUNT); |
881 | } | 882 | } |
882 | spin_unlock_irqrestore(&s->lock, flags); | 883 | spin_unlock_irqrestore(&s->lock, flags); |
883 | } | 884 | } |
884 | 885 | ||
885 | /* --------------------------------------------------------------------- */ | 886 | /* --------------------------------------------------------------------- */ |
886 | 887 | ||
887 | #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) | 888 | #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) |
888 | #define DMABUF_MINORDER 1 | 889 | #define DMABUF_MINORDER 1 |
889 | 890 | ||
890 | 891 | ||
891 | static inline void dealloc_dmabuf(struct es1371_state *s, struct dmabuf *db) | 892 | static inline void dealloc_dmabuf(struct es1371_state *s, struct dmabuf *db) |
892 | { | 893 | { |
893 | struct page *page, *pend; | 894 | struct page *page, *pend; |
894 | 895 | ||
895 | if (db->rawbuf) { | 896 | if (db->rawbuf) { |
896 | /* undo marking the pages as reserved */ | 897 | /* undo marking the pages as reserved */ |
897 | pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); | 898 | pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); |
898 | for (page = virt_to_page(db->rawbuf); page <= pend; page++) | 899 | for (page = virt_to_page(db->rawbuf); page <= pend; page++) |
899 | ClearPageReserved(page); | 900 | ClearPageReserved(page); |
900 | pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr); | 901 | pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr); |
901 | } | 902 | } |
902 | db->rawbuf = NULL; | 903 | db->rawbuf = NULL; |
903 | db->mapped = db->ready = 0; | 904 | db->mapped = db->ready = 0; |
904 | } | 905 | } |
905 | 906 | ||
906 | static int prog_dmabuf(struct es1371_state *s, struct dmabuf *db, unsigned rate, unsigned fmt, unsigned reg) | 907 | static int prog_dmabuf(struct es1371_state *s, struct dmabuf *db, unsigned rate, unsigned fmt, unsigned reg) |
907 | { | 908 | { |
908 | int order; | 909 | int order; |
909 | unsigned bytepersec; | 910 | unsigned bytepersec; |
910 | unsigned bufs; | 911 | unsigned bufs; |
911 | struct page *page, *pend; | 912 | struct page *page, *pend; |
912 | 913 | ||
913 | db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; | 914 | db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; |
914 | if (!db->rawbuf) { | 915 | if (!db->rawbuf) { |
915 | db->ready = db->mapped = 0; | 916 | db->ready = db->mapped = 0; |
916 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) | 917 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) |
917 | if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr))) | 918 | if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr))) |
918 | break; | 919 | break; |
919 | if (!db->rawbuf) | 920 | if (!db->rawbuf) |
920 | return -ENOMEM; | 921 | return -ENOMEM; |
921 | db->buforder = order; | 922 | db->buforder = order; |
922 | /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */ | 923 | /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */ |
923 | pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); | 924 | pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); |
924 | for (page = virt_to_page(db->rawbuf); page <= pend; page++) | 925 | for (page = virt_to_page(db->rawbuf); page <= pend; page++) |
925 | SetPageReserved(page); | 926 | SetPageReserved(page); |
926 | } | 927 | } |
927 | fmt &= ES1371_FMT_MASK; | 928 | fmt &= ES1371_FMT_MASK; |
928 | bytepersec = rate << sample_shift[fmt]; | 929 | bytepersec = rate << sample_shift[fmt]; |
929 | bufs = PAGE_SIZE << db->buforder; | 930 | bufs = PAGE_SIZE << db->buforder; |
930 | if (db->ossfragshift) { | 931 | if (db->ossfragshift) { |
931 | if ((1000 << db->ossfragshift) < bytepersec) | 932 | if ((1000 << db->ossfragshift) < bytepersec) |
932 | db->fragshift = ld2(bytepersec/1000); | 933 | db->fragshift = ld2(bytepersec/1000); |
933 | else | 934 | else |
934 | db->fragshift = db->ossfragshift; | 935 | db->fragshift = db->ossfragshift; |
935 | } else { | 936 | } else { |
936 | db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1)); | 937 | db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1)); |
937 | if (db->fragshift < 3) | 938 | if (db->fragshift < 3) |
938 | db->fragshift = 3; | 939 | db->fragshift = 3; |
939 | } | 940 | } |
940 | db->numfrag = bufs >> db->fragshift; | 941 | db->numfrag = bufs >> db->fragshift; |
941 | while (db->numfrag < 4 && db->fragshift > 3) { | 942 | while (db->numfrag < 4 && db->fragshift > 3) { |
942 | db->fragshift--; | 943 | db->fragshift--; |
943 | db->numfrag = bufs >> db->fragshift; | 944 | db->numfrag = bufs >> db->fragshift; |
944 | } | 945 | } |
945 | db->fragsize = 1 << db->fragshift; | 946 | db->fragsize = 1 << db->fragshift; |
946 | if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) | 947 | if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) |
947 | db->numfrag = db->ossmaxfrags; | 948 | db->numfrag = db->ossmaxfrags; |
948 | db->fragsamples = db->fragsize >> sample_shift[fmt]; | 949 | db->fragsamples = db->fragsize >> sample_shift[fmt]; |
949 | db->dmasize = db->numfrag << db->fragshift; | 950 | db->dmasize = db->numfrag << db->fragshift; |
950 | memset(db->rawbuf, (fmt & ES1371_FMT_S16) ? 0 : 0x80, db->dmasize); | 951 | memset(db->rawbuf, (fmt & ES1371_FMT_S16) ? 0 : 0x80, db->dmasize); |
951 | outl((reg >> 8) & 15, s->io+ES1371_REG_MEMPAGE); | 952 | outl((reg >> 8) & 15, s->io+ES1371_REG_MEMPAGE); |
952 | outl(db->dmaaddr, s->io+(reg & 0xff)); | 953 | outl(db->dmaaddr, s->io+(reg & 0xff)); |
953 | outl((db->dmasize >> 2)-1, s->io+((reg + 4) & 0xff)); | 954 | outl((db->dmasize >> 2)-1, s->io+((reg + 4) & 0xff)); |
954 | db->enabled = 1; | 955 | db->enabled = 1; |
955 | db->ready = 1; | 956 | db->ready = 1; |
956 | return 0; | 957 | return 0; |
957 | } | 958 | } |
958 | 959 | ||
959 | static inline int prog_dmabuf_adc(struct es1371_state *s) | 960 | static inline int prog_dmabuf_adc(struct es1371_state *s) |
960 | { | 961 | { |
961 | stop_adc(s); | 962 | stop_adc(s); |
962 | return prog_dmabuf(s, &s->dma_adc, s->adcrate, (s->sctrl >> SCTRL_SH_R1FMT) & ES1371_FMT_MASK, | 963 | return prog_dmabuf(s, &s->dma_adc, s->adcrate, (s->sctrl >> SCTRL_SH_R1FMT) & ES1371_FMT_MASK, |
963 | ES1371_REG_ADC_FRAMEADR); | 964 | ES1371_REG_ADC_FRAMEADR); |
964 | } | 965 | } |
965 | 966 | ||
966 | static inline int prog_dmabuf_dac2(struct es1371_state *s) | 967 | static inline int prog_dmabuf_dac2(struct es1371_state *s) |
967 | { | 968 | { |
968 | stop_dac2(s); | 969 | stop_dac2(s); |
969 | return prog_dmabuf(s, &s->dma_dac2, s->dac2rate, (s->sctrl >> SCTRL_SH_P2FMT) & ES1371_FMT_MASK, | 970 | return prog_dmabuf(s, &s->dma_dac2, s->dac2rate, (s->sctrl >> SCTRL_SH_P2FMT) & ES1371_FMT_MASK, |
970 | ES1371_REG_DAC2_FRAMEADR); | 971 | ES1371_REG_DAC2_FRAMEADR); |
971 | } | 972 | } |
972 | 973 | ||
973 | static inline int prog_dmabuf_dac1(struct es1371_state *s) | 974 | static inline int prog_dmabuf_dac1(struct es1371_state *s) |
974 | { | 975 | { |
975 | stop_dac1(s); | 976 | stop_dac1(s); |
976 | return prog_dmabuf(s, &s->dma_dac1, s->dac1rate, (s->sctrl >> SCTRL_SH_P1FMT) & ES1371_FMT_MASK, | 977 | return prog_dmabuf(s, &s->dma_dac1, s->dac1rate, (s->sctrl >> SCTRL_SH_P1FMT) & ES1371_FMT_MASK, |
977 | ES1371_REG_DAC1_FRAMEADR); | 978 | ES1371_REG_DAC1_FRAMEADR); |
978 | } | 979 | } |
979 | 980 | ||
980 | static inline unsigned get_hwptr(struct es1371_state *s, struct dmabuf *db, unsigned reg) | 981 | static inline unsigned get_hwptr(struct es1371_state *s, struct dmabuf *db, unsigned reg) |
981 | { | 982 | { |
982 | unsigned hwptr, diff; | 983 | unsigned hwptr, diff; |
983 | 984 | ||
984 | outl((reg >> 8) & 15, s->io+ES1371_REG_MEMPAGE); | 985 | outl((reg >> 8) & 15, s->io+ES1371_REG_MEMPAGE); |
985 | hwptr = (inl(s->io+(reg & 0xff)) >> 14) & 0x3fffc; | 986 | hwptr = (inl(s->io+(reg & 0xff)) >> 14) & 0x3fffc; |
986 | diff = (db->dmasize + hwptr - db->hwptr) % db->dmasize; | 987 | diff = (db->dmasize + hwptr - db->hwptr) % db->dmasize; |
987 | db->hwptr = hwptr; | 988 | db->hwptr = hwptr; |
988 | return diff; | 989 | return diff; |
989 | } | 990 | } |
990 | 991 | ||
991 | static inline void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c) | 992 | static inline void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c) |
992 | { | 993 | { |
993 | if (bptr + len > bsize) { | 994 | if (bptr + len > bsize) { |
994 | unsigned x = bsize - bptr; | 995 | unsigned x = bsize - bptr; |
995 | memset(((char *)buf) + bptr, c, x); | 996 | memset(((char *)buf) + bptr, c, x); |
996 | bptr = 0; | 997 | bptr = 0; |
997 | len -= x; | 998 | len -= x; |
998 | } | 999 | } |
999 | memset(((char *)buf) + bptr, c, len); | 1000 | memset(((char *)buf) + bptr, c, len); |
1000 | } | 1001 | } |
1001 | 1002 | ||
1002 | /* call with spinlock held! */ | 1003 | /* call with spinlock held! */ |
1003 | static void es1371_update_ptr(struct es1371_state *s) | 1004 | static void es1371_update_ptr(struct es1371_state *s) |
1004 | { | 1005 | { |
1005 | int diff; | 1006 | int diff; |
1006 | 1007 | ||
1007 | /* update ADC pointer */ | 1008 | /* update ADC pointer */ |
1008 | if (s->ctrl & CTRL_ADC_EN) { | 1009 | if (s->ctrl & CTRL_ADC_EN) { |
1009 | diff = get_hwptr(s, &s->dma_adc, ES1371_REG_ADC_FRAMECNT); | 1010 | diff = get_hwptr(s, &s->dma_adc, ES1371_REG_ADC_FRAMECNT); |
1010 | s->dma_adc.total_bytes += diff; | 1011 | s->dma_adc.total_bytes += diff; |
1011 | s->dma_adc.count += diff; | 1012 | s->dma_adc.count += diff; |
1012 | if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) | 1013 | if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) |
1013 | wake_up(&s->dma_adc.wait); | 1014 | wake_up(&s->dma_adc.wait); |
1014 | if (!s->dma_adc.mapped) { | 1015 | if (!s->dma_adc.mapped) { |
1015 | if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { | 1016 | if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { |
1016 | s->ctrl &= ~CTRL_ADC_EN; | 1017 | s->ctrl &= ~CTRL_ADC_EN; |
1017 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 1018 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
1018 | s->dma_adc.error++; | 1019 | s->dma_adc.error++; |
1019 | } | 1020 | } |
1020 | } | 1021 | } |
1021 | } | 1022 | } |
1022 | /* update DAC1 pointer */ | 1023 | /* update DAC1 pointer */ |
1023 | if (s->ctrl & CTRL_DAC1_EN) { | 1024 | if (s->ctrl & CTRL_DAC1_EN) { |
1024 | diff = get_hwptr(s, &s->dma_dac1, ES1371_REG_DAC1_FRAMECNT); | 1025 | diff = get_hwptr(s, &s->dma_dac1, ES1371_REG_DAC1_FRAMECNT); |
1025 | s->dma_dac1.total_bytes += diff; | 1026 | s->dma_dac1.total_bytes += diff; |
1026 | if (s->dma_dac1.mapped) { | 1027 | if (s->dma_dac1.mapped) { |
1027 | s->dma_dac1.count += diff; | 1028 | s->dma_dac1.count += diff; |
1028 | if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) | 1029 | if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) |
1029 | wake_up(&s->dma_dac1.wait); | 1030 | wake_up(&s->dma_dac1.wait); |
1030 | } else { | 1031 | } else { |
1031 | s->dma_dac1.count -= diff; | 1032 | s->dma_dac1.count -= diff; |
1032 | if (s->dma_dac1.count <= 0) { | 1033 | if (s->dma_dac1.count <= 0) { |
1033 | s->ctrl &= ~CTRL_DAC1_EN; | 1034 | s->ctrl &= ~CTRL_DAC1_EN; |
1034 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 1035 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
1035 | s->dma_dac1.error++; | 1036 | s->dma_dac1.error++; |
1036 | } else if (s->dma_dac1.count <= (signed)s->dma_dac1.fragsize && !s->dma_dac1.endcleared) { | 1037 | } else if (s->dma_dac1.count <= (signed)s->dma_dac1.fragsize && !s->dma_dac1.endcleared) { |
1037 | clear_advance(s->dma_dac1.rawbuf, s->dma_dac1.dmasize, s->dma_dac1.swptr, | 1038 | clear_advance(s->dma_dac1.rawbuf, s->dma_dac1.dmasize, s->dma_dac1.swptr, |
1038 | s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80); | 1039 | s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80); |
1039 | s->dma_dac1.endcleared = 1; | 1040 | s->dma_dac1.endcleared = 1; |
1040 | } | 1041 | } |
1041 | if (s->dma_dac1.count + (signed)s->dma_dac1.fragsize <= (signed)s->dma_dac1.dmasize) | 1042 | if (s->dma_dac1.count + (signed)s->dma_dac1.fragsize <= (signed)s->dma_dac1.dmasize) |
1042 | wake_up(&s->dma_dac1.wait); | 1043 | wake_up(&s->dma_dac1.wait); |
1043 | } | 1044 | } |
1044 | } | 1045 | } |
1045 | /* update DAC2 pointer */ | 1046 | /* update DAC2 pointer */ |
1046 | if (s->ctrl & CTRL_DAC2_EN) { | 1047 | if (s->ctrl & CTRL_DAC2_EN) { |
1047 | diff = get_hwptr(s, &s->dma_dac2, ES1371_REG_DAC2_FRAMECNT); | 1048 | diff = get_hwptr(s, &s->dma_dac2, ES1371_REG_DAC2_FRAMECNT); |
1048 | s->dma_dac2.total_bytes += diff; | 1049 | s->dma_dac2.total_bytes += diff; |
1049 | if (s->dma_dac2.mapped) { | 1050 | if (s->dma_dac2.mapped) { |
1050 | s->dma_dac2.count += diff; | 1051 | s->dma_dac2.count += diff; |
1051 | if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) | 1052 | if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) |
1052 | wake_up(&s->dma_dac2.wait); | 1053 | wake_up(&s->dma_dac2.wait); |
1053 | } else { | 1054 | } else { |
1054 | s->dma_dac2.count -= diff; | 1055 | s->dma_dac2.count -= diff; |
1055 | if (s->dma_dac2.count <= 0) { | 1056 | if (s->dma_dac2.count <= 0) { |
1056 | s->ctrl &= ~CTRL_DAC2_EN; | 1057 | s->ctrl &= ~CTRL_DAC2_EN; |
1057 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 1058 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
1058 | s->dma_dac2.error++; | 1059 | s->dma_dac2.error++; |
1059 | } else if (s->dma_dac2.count <= (signed)s->dma_dac2.fragsize && !s->dma_dac2.endcleared) { | 1060 | } else if (s->dma_dac2.count <= (signed)s->dma_dac2.fragsize && !s->dma_dac2.endcleared) { |
1060 | clear_advance(s->dma_dac2.rawbuf, s->dma_dac2.dmasize, s->dma_dac2.swptr, | 1061 | clear_advance(s->dma_dac2.rawbuf, s->dma_dac2.dmasize, s->dma_dac2.swptr, |
1061 | s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80); | 1062 | s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80); |
1062 | s->dma_dac2.endcleared = 1; | 1063 | s->dma_dac2.endcleared = 1; |
1063 | } | 1064 | } |
1064 | if (s->dma_dac2.count + (signed)s->dma_dac2.fragsize <= (signed)s->dma_dac2.dmasize) | 1065 | if (s->dma_dac2.count + (signed)s->dma_dac2.fragsize <= (signed)s->dma_dac2.dmasize) |
1065 | wake_up(&s->dma_dac2.wait); | 1066 | wake_up(&s->dma_dac2.wait); |
1066 | } | 1067 | } |
1067 | } | 1068 | } |
1068 | } | 1069 | } |
1069 | 1070 | ||
1070 | /* hold spinlock for the following! */ | 1071 | /* hold spinlock for the following! */ |
1071 | static void es1371_handle_midi(struct es1371_state *s) | 1072 | static void es1371_handle_midi(struct es1371_state *s) |
1072 | { | 1073 | { |
1073 | unsigned char ch; | 1074 | unsigned char ch; |
1074 | int wake; | 1075 | int wake; |
1075 | 1076 | ||
1076 | if (!(s->ctrl & CTRL_UART_EN)) | 1077 | if (!(s->ctrl & CTRL_UART_EN)) |
1077 | return; | 1078 | return; |
1078 | wake = 0; | 1079 | wake = 0; |
1079 | while (inb(s->io+ES1371_REG_UART_STATUS) & USTAT_RXRDY) { | 1080 | while (inb(s->io+ES1371_REG_UART_STATUS) & USTAT_RXRDY) { |
1080 | ch = inb(s->io+ES1371_REG_UART_DATA); | 1081 | ch = inb(s->io+ES1371_REG_UART_DATA); |
1081 | if (s->midi.icnt < MIDIINBUF) { | 1082 | if (s->midi.icnt < MIDIINBUF) { |
1082 | s->midi.ibuf[s->midi.iwr] = ch; | 1083 | s->midi.ibuf[s->midi.iwr] = ch; |
1083 | s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF; | 1084 | s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF; |
1084 | s->midi.icnt++; | 1085 | s->midi.icnt++; |
1085 | } | 1086 | } |
1086 | wake = 1; | 1087 | wake = 1; |
1087 | } | 1088 | } |
1088 | if (wake) | 1089 | if (wake) |
1089 | wake_up(&s->midi.iwait); | 1090 | wake_up(&s->midi.iwait); |
1090 | wake = 0; | 1091 | wake = 0; |
1091 | while ((inb(s->io+ES1371_REG_UART_STATUS) & USTAT_TXRDY) && s->midi.ocnt > 0) { | 1092 | while ((inb(s->io+ES1371_REG_UART_STATUS) & USTAT_TXRDY) && s->midi.ocnt > 0) { |
1092 | outb(s->midi.obuf[s->midi.ord], s->io+ES1371_REG_UART_DATA); | 1093 | outb(s->midi.obuf[s->midi.ord], s->io+ES1371_REG_UART_DATA); |
1093 | s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF; | 1094 | s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF; |
1094 | s->midi.ocnt--; | 1095 | s->midi.ocnt--; |
1095 | if (s->midi.ocnt < MIDIOUTBUF-16) | 1096 | if (s->midi.ocnt < MIDIOUTBUF-16) |
1096 | wake = 1; | 1097 | wake = 1; |
1097 | } | 1098 | } |
1098 | if (wake) | 1099 | if (wake) |
1099 | wake_up(&s->midi.owait); | 1100 | wake_up(&s->midi.owait); |
1100 | outb((s->midi.ocnt > 0) ? UCTRL_RXINTEN | UCTRL_ENA_TXINT : UCTRL_RXINTEN, s->io+ES1371_REG_UART_CONTROL); | 1101 | outb((s->midi.ocnt > 0) ? UCTRL_RXINTEN | UCTRL_ENA_TXINT : UCTRL_RXINTEN, s->io+ES1371_REG_UART_CONTROL); |
1101 | } | 1102 | } |
1102 | 1103 | ||
1103 | static irqreturn_t es1371_interrupt(int irq, void *dev_id) | 1104 | static irqreturn_t es1371_interrupt(int irq, void *dev_id) |
1104 | { | 1105 | { |
1105 | struct es1371_state *s = dev_id; | 1106 | struct es1371_state *s = dev_id; |
1106 | unsigned int intsrc, sctl; | 1107 | unsigned int intsrc, sctl; |
1107 | 1108 | ||
1108 | /* fastpath out, to ease interrupt sharing */ | 1109 | /* fastpath out, to ease interrupt sharing */ |
1109 | intsrc = inl(s->io+ES1371_REG_STATUS); | 1110 | intsrc = inl(s->io+ES1371_REG_STATUS); |
1110 | if (!(intsrc & 0x80000000)) | 1111 | if (!(intsrc & 0x80000000)) |
1111 | return IRQ_NONE; | 1112 | return IRQ_NONE; |
1112 | spin_lock(&s->lock); | 1113 | spin_lock(&s->lock); |
1113 | /* clear audio interrupts first */ | 1114 | /* clear audio interrupts first */ |
1114 | sctl = s->sctrl; | 1115 | sctl = s->sctrl; |
1115 | if (intsrc & STAT_ADC) | 1116 | if (intsrc & STAT_ADC) |
1116 | sctl &= ~SCTRL_R1INTEN; | 1117 | sctl &= ~SCTRL_R1INTEN; |
1117 | if (intsrc & STAT_DAC1) | 1118 | if (intsrc & STAT_DAC1) |
1118 | sctl &= ~SCTRL_P1INTEN; | 1119 | sctl &= ~SCTRL_P1INTEN; |
1119 | if (intsrc & STAT_DAC2) | 1120 | if (intsrc & STAT_DAC2) |
1120 | sctl &= ~SCTRL_P2INTEN; | 1121 | sctl &= ~SCTRL_P2INTEN; |
1121 | outl(sctl, s->io+ES1371_REG_SERIAL_CONTROL); | 1122 | outl(sctl, s->io+ES1371_REG_SERIAL_CONTROL); |
1122 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1123 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1123 | es1371_update_ptr(s); | 1124 | es1371_update_ptr(s); |
1124 | es1371_handle_midi(s); | 1125 | es1371_handle_midi(s); |
1125 | spin_unlock(&s->lock); | 1126 | spin_unlock(&s->lock); |
1126 | return IRQ_HANDLED; | 1127 | return IRQ_HANDLED; |
1127 | } | 1128 | } |
1128 | 1129 | ||
1129 | /* --------------------------------------------------------------------- */ | 1130 | /* --------------------------------------------------------------------- */ |
1130 | 1131 | ||
1131 | static const char invalid_magic[] = KERN_CRIT PFX "invalid magic value\n"; | 1132 | static const char invalid_magic[] = KERN_CRIT PFX "invalid magic value\n"; |
1132 | 1133 | ||
1133 | #define VALIDATE_STATE(s) \ | 1134 | #define VALIDATE_STATE(s) \ |
1134 | ({ \ | 1135 | ({ \ |
1135 | if (!(s) || (s)->magic != ES1371_MAGIC) { \ | 1136 | if (!(s) || (s)->magic != ES1371_MAGIC) { \ |
1136 | printk(invalid_magic); \ | 1137 | printk(invalid_magic); \ |
1137 | return -ENXIO; \ | 1138 | return -ENXIO; \ |
1138 | } \ | 1139 | } \ |
1139 | }) | 1140 | }) |
1140 | 1141 | ||
1141 | /* --------------------------------------------------------------------- */ | 1142 | /* --------------------------------------------------------------------- */ |
1142 | 1143 | ||
1143 | /* Conversion table for S/PDIF PCM volume emulation through the SRC */ | 1144 | /* Conversion table for S/PDIF PCM volume emulation through the SRC */ |
1144 | /* dB-linear table of DAC vol values; -0dB to -46.5dB with mute */ | 1145 | /* dB-linear table of DAC vol values; -0dB to -46.5dB with mute */ |
1145 | static const unsigned short DACVolTable[101] = | 1146 | static const unsigned short DACVolTable[101] = |
1146 | { | 1147 | { |
1147 | 0x1000, 0x0f2a, 0x0e60, 0x0da0, 0x0cea, 0x0c3e, 0x0b9a, 0x0aff, | 1148 | 0x1000, 0x0f2a, 0x0e60, 0x0da0, 0x0cea, 0x0c3e, 0x0b9a, 0x0aff, |
1148 | 0x0a6d, 0x09e1, 0x095e, 0x08e1, 0x086a, 0x07fa, 0x078f, 0x072a, | 1149 | 0x0a6d, 0x09e1, 0x095e, 0x08e1, 0x086a, 0x07fa, 0x078f, 0x072a, |
1149 | 0x06cb, 0x0670, 0x061a, 0x05c9, 0x057b, 0x0532, 0x04ed, 0x04ab, | 1150 | 0x06cb, 0x0670, 0x061a, 0x05c9, 0x057b, 0x0532, 0x04ed, 0x04ab, |
1150 | 0x046d, 0x0432, 0x03fa, 0x03c5, 0x0392, 0x0363, 0x0335, 0x030b, | 1151 | 0x046d, 0x0432, 0x03fa, 0x03c5, 0x0392, 0x0363, 0x0335, 0x030b, |
1151 | 0x02e2, 0x02bc, 0x0297, 0x0275, 0x0254, 0x0235, 0x0217, 0x01fb, | 1152 | 0x02e2, 0x02bc, 0x0297, 0x0275, 0x0254, 0x0235, 0x0217, 0x01fb, |
1152 | 0x01e1, 0x01c8, 0x01b0, 0x0199, 0x0184, 0x0170, 0x015d, 0x014b, | 1153 | 0x01e1, 0x01c8, 0x01b0, 0x0199, 0x0184, 0x0170, 0x015d, 0x014b, |
1153 | 0x0139, 0x0129, 0x0119, 0x010b, 0x00fd, 0x00f0, 0x00e3, 0x00d7, | 1154 | 0x0139, 0x0129, 0x0119, 0x010b, 0x00fd, 0x00f0, 0x00e3, 0x00d7, |
1154 | 0x00cc, 0x00c1, 0x00b7, 0x00ae, 0x00a5, 0x009c, 0x0094, 0x008c, | 1155 | 0x00cc, 0x00c1, 0x00b7, 0x00ae, 0x00a5, 0x009c, 0x0094, 0x008c, |
1155 | 0x0085, 0x007e, 0x0077, 0x0071, 0x006b, 0x0066, 0x0060, 0x005b, | 1156 | 0x0085, 0x007e, 0x0077, 0x0071, 0x006b, 0x0066, 0x0060, 0x005b, |
1156 | 0x0057, 0x0052, 0x004e, 0x004a, 0x0046, 0x0042, 0x003f, 0x003c, | 1157 | 0x0057, 0x0052, 0x004e, 0x004a, 0x0046, 0x0042, 0x003f, 0x003c, |
1157 | 0x0038, 0x0036, 0x0033, 0x0030, 0x002e, 0x002b, 0x0029, 0x0027, | 1158 | 0x0038, 0x0036, 0x0033, 0x0030, 0x002e, 0x002b, 0x0029, 0x0027, |
1158 | 0x0025, 0x0023, 0x0021, 0x001f, 0x001e, 0x001c, 0x001b, 0x0019, | 1159 | 0x0025, 0x0023, 0x0021, 0x001f, 0x001e, 0x001c, 0x001b, 0x0019, |
1159 | 0x0018, 0x0017, 0x0016, 0x0014, 0x0000 | 1160 | 0x0018, 0x0017, 0x0016, 0x0014, 0x0000 |
1160 | }; | 1161 | }; |
1161 | 1162 | ||
1162 | /* | 1163 | /* |
1163 | * when we are in S/PDIF mode, we want to disable any analog output so | 1164 | * when we are in S/PDIF mode, we want to disable any analog output so |
1164 | * we filter the mixer ioctls | 1165 | * we filter the mixer ioctls |
1165 | */ | 1166 | */ |
1166 | static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg) | 1167 | static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg) |
1167 | { | 1168 | { |
1168 | struct es1371_state *s = (struct es1371_state *)codec->private_data; | 1169 | struct es1371_state *s = (struct es1371_state *)codec->private_data; |
1169 | int val; | 1170 | int val; |
1170 | unsigned long flags; | 1171 | unsigned long flags; |
1171 | unsigned int left, right; | 1172 | unsigned int left, right; |
1172 | 1173 | ||
1173 | VALIDATE_STATE(s); | 1174 | VALIDATE_STATE(s); |
1174 | /* filter mixer ioctls to catch PCM and MASTER volume when in S/PDIF mode */ | 1175 | /* filter mixer ioctls to catch PCM and MASTER volume when in S/PDIF mode */ |
1175 | if (s->spdif_volume == -1) | 1176 | if (s->spdif_volume == -1) |
1176 | return codec->mixer_ioctl(codec, cmd, arg); | 1177 | return codec->mixer_ioctl(codec, cmd, arg); |
1177 | switch (cmd) { | 1178 | switch (cmd) { |
1178 | case SOUND_MIXER_WRITE_VOLUME: | 1179 | case SOUND_MIXER_WRITE_VOLUME: |
1179 | return 0; | 1180 | return 0; |
1180 | 1181 | ||
1181 | case SOUND_MIXER_WRITE_PCM: /* use SRC for PCM volume */ | 1182 | case SOUND_MIXER_WRITE_PCM: /* use SRC for PCM volume */ |
1182 | if (get_user(val, (int __user *)arg)) | 1183 | if (get_user(val, (int __user *)arg)) |
1183 | return -EFAULT; | 1184 | return -EFAULT; |
1184 | right = ((val >> 8) & 0xff); | 1185 | right = ((val >> 8) & 0xff); |
1185 | left = (val & 0xff); | 1186 | left = (val & 0xff); |
1186 | if (right > 100) | 1187 | if (right > 100) |
1187 | right = 100; | 1188 | right = 100; |
1188 | if (left > 100) | 1189 | if (left > 100) |
1189 | left = 100; | 1190 | left = 100; |
1190 | s->spdif_volume = (right << 8) | left; | 1191 | s->spdif_volume = (right << 8) | left; |
1191 | spin_lock_irqsave(&s->lock, flags); | 1192 | spin_lock_irqsave(&s->lock, flags); |
1192 | src_write(s, SRCREG_VOL_DAC2, DACVolTable[100 - left]); | 1193 | src_write(s, SRCREG_VOL_DAC2, DACVolTable[100 - left]); |
1193 | src_write(s, SRCREG_VOL_DAC2+1, DACVolTable[100 - right]); | 1194 | src_write(s, SRCREG_VOL_DAC2+1, DACVolTable[100 - right]); |
1194 | spin_unlock_irqrestore(&s->lock, flags); | 1195 | spin_unlock_irqrestore(&s->lock, flags); |
1195 | return 0; | 1196 | return 0; |
1196 | 1197 | ||
1197 | case SOUND_MIXER_READ_PCM: | 1198 | case SOUND_MIXER_READ_PCM: |
1198 | return put_user(s->spdif_volume, (int __user *)arg); | 1199 | return put_user(s->spdif_volume, (int __user *)arg); |
1199 | } | 1200 | } |
1200 | return codec->mixer_ioctl(codec, cmd, arg); | 1201 | return codec->mixer_ioctl(codec, cmd, arg); |
1201 | } | 1202 | } |
1202 | 1203 | ||
1203 | /* --------------------------------------------------------------------- */ | 1204 | /* --------------------------------------------------------------------- */ |
1204 | 1205 | ||
1205 | /* | 1206 | /* |
1206 | * AC97 Mixer Register to Connections mapping of the Concert 97 board | 1207 | * AC97 Mixer Register to Connections mapping of the Concert 97 board |
1207 | * | 1208 | * |
1208 | * AC97_MASTER_VOL_STEREO Line Out | 1209 | * AC97_MASTER_VOL_STEREO Line Out |
1209 | * AC97_MASTER_VOL_MONO TAD Output | 1210 | * AC97_MASTER_VOL_MONO TAD Output |
1210 | * AC97_PCBEEP_VOL none | 1211 | * AC97_PCBEEP_VOL none |
1211 | * AC97_PHONE_VOL TAD Input (mono) | 1212 | * AC97_PHONE_VOL TAD Input (mono) |
1212 | * AC97_MIC_VOL MIC Input (mono) | 1213 | * AC97_MIC_VOL MIC Input (mono) |
1213 | * AC97_LINEIN_VOL Line Input (stereo) | 1214 | * AC97_LINEIN_VOL Line Input (stereo) |
1214 | * AC97_CD_VOL CD Input (stereo) | 1215 | * AC97_CD_VOL CD Input (stereo) |
1215 | * AC97_VIDEO_VOL none | 1216 | * AC97_VIDEO_VOL none |
1216 | * AC97_AUX_VOL Aux Input (stereo) | 1217 | * AC97_AUX_VOL Aux Input (stereo) |
1217 | * AC97_PCMOUT_VOL Wave Output (stereo) | 1218 | * AC97_PCMOUT_VOL Wave Output (stereo) |
1218 | */ | 1219 | */ |
1219 | 1220 | ||
1220 | static int es1371_open_mixdev(struct inode *inode, struct file *file) | 1221 | static int es1371_open_mixdev(struct inode *inode, struct file *file) |
1221 | { | 1222 | { |
1222 | int minor = iminor(inode); | 1223 | int minor = iminor(inode); |
1223 | struct list_head *list; | 1224 | struct list_head *list; |
1224 | struct es1371_state *s; | 1225 | struct es1371_state *s; |
1225 | 1226 | ||
1226 | for (list = devs.next; ; list = list->next) { | 1227 | for (list = devs.next; ; list = list->next) { |
1227 | if (list == &devs) | 1228 | if (list == &devs) |
1228 | return -ENODEV; | 1229 | return -ENODEV; |
1229 | s = list_entry(list, struct es1371_state, devs); | 1230 | s = list_entry(list, struct es1371_state, devs); |
1230 | if (s->codec->dev_mixer == minor) | 1231 | if (s->codec->dev_mixer == minor) |
1231 | break; | 1232 | break; |
1232 | } | 1233 | } |
1233 | VALIDATE_STATE(s); | 1234 | VALIDATE_STATE(s); |
1234 | file->private_data = s; | 1235 | file->private_data = s; |
1235 | return nonseekable_open(inode, file); | 1236 | return nonseekable_open(inode, file); |
1236 | } | 1237 | } |
1237 | 1238 | ||
1238 | static int es1371_release_mixdev(struct inode *inode, struct file *file) | 1239 | static int es1371_release_mixdev(struct inode *inode, struct file *file) |
1239 | { | 1240 | { |
1240 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1241 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1241 | 1242 | ||
1242 | VALIDATE_STATE(s); | 1243 | VALIDATE_STATE(s); |
1243 | return 0; | 1244 | return 0; |
1244 | } | 1245 | } |
1245 | 1246 | ||
1246 | static int es1371_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 1247 | static int es1371_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
1247 | { | 1248 | { |
1248 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1249 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1249 | struct ac97_codec *codec = s->codec; | 1250 | struct ac97_codec *codec = s->codec; |
1250 | 1251 | ||
1251 | return mixdev_ioctl(codec, cmd, arg); | 1252 | return mixdev_ioctl(codec, cmd, arg); |
1252 | } | 1253 | } |
1253 | 1254 | ||
1254 | static /*const*/ struct file_operations es1371_mixer_fops = { | 1255 | static /*const*/ struct file_operations es1371_mixer_fops = { |
1255 | .owner = THIS_MODULE, | 1256 | .owner = THIS_MODULE, |
1256 | .llseek = no_llseek, | 1257 | .llseek = no_llseek, |
1257 | .ioctl = es1371_ioctl_mixdev, | 1258 | .ioctl = es1371_ioctl_mixdev, |
1258 | .open = es1371_open_mixdev, | 1259 | .open = es1371_open_mixdev, |
1259 | .release = es1371_release_mixdev, | 1260 | .release = es1371_release_mixdev, |
1260 | }; | 1261 | }; |
1261 | 1262 | ||
1262 | /* --------------------------------------------------------------------- */ | 1263 | /* --------------------------------------------------------------------- */ |
1263 | 1264 | ||
1264 | static int drain_dac1(struct es1371_state *s, int nonblock) | 1265 | static int drain_dac1(struct es1371_state *s, int nonblock) |
1265 | { | 1266 | { |
1266 | DECLARE_WAITQUEUE(wait, current); | 1267 | DECLARE_WAITQUEUE(wait, current); |
1267 | unsigned long flags; | 1268 | unsigned long flags; |
1268 | int count, tmo; | 1269 | int count, tmo; |
1269 | 1270 | ||
1270 | if (s->dma_dac1.mapped || !s->dma_dac1.ready) | 1271 | if (s->dma_dac1.mapped || !s->dma_dac1.ready) |
1271 | return 0; | 1272 | return 0; |
1272 | add_wait_queue(&s->dma_dac1.wait, &wait); | 1273 | add_wait_queue(&s->dma_dac1.wait, &wait); |
1273 | for (;;) { | 1274 | for (;;) { |
1274 | __set_current_state(TASK_INTERRUPTIBLE); | 1275 | __set_current_state(TASK_INTERRUPTIBLE); |
1275 | spin_lock_irqsave(&s->lock, flags); | 1276 | spin_lock_irqsave(&s->lock, flags); |
1276 | count = s->dma_dac1.count; | 1277 | count = s->dma_dac1.count; |
1277 | spin_unlock_irqrestore(&s->lock, flags); | 1278 | spin_unlock_irqrestore(&s->lock, flags); |
1278 | if (count <= 0) | 1279 | if (count <= 0) |
1279 | break; | 1280 | break; |
1280 | if (signal_pending(current)) | 1281 | if (signal_pending(current)) |
1281 | break; | 1282 | break; |
1282 | if (nonblock) { | 1283 | if (nonblock) { |
1283 | remove_wait_queue(&s->dma_dac1.wait, &wait); | 1284 | remove_wait_queue(&s->dma_dac1.wait, &wait); |
1284 | set_current_state(TASK_RUNNING); | 1285 | set_current_state(TASK_RUNNING); |
1285 | return -EBUSY; | 1286 | return -EBUSY; |
1286 | } | 1287 | } |
1287 | tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate; | 1288 | tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate; |
1288 | tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT]; | 1289 | tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT]; |
1289 | if (!schedule_timeout(tmo + 1)) | 1290 | if (!schedule_timeout(tmo + 1)) |
1290 | DBG(printk(KERN_DEBUG PFX "dac1 dma timed out??\n");) | 1291 | DBG(printk(KERN_DEBUG PFX "dac1 dma timed out??\n");) |
1291 | } | 1292 | } |
1292 | remove_wait_queue(&s->dma_dac1.wait, &wait); | 1293 | remove_wait_queue(&s->dma_dac1.wait, &wait); |
1293 | set_current_state(TASK_RUNNING); | 1294 | set_current_state(TASK_RUNNING); |
1294 | if (signal_pending(current)) | 1295 | if (signal_pending(current)) |
1295 | return -ERESTARTSYS; | 1296 | return -ERESTARTSYS; |
1296 | return 0; | 1297 | return 0; |
1297 | } | 1298 | } |
1298 | 1299 | ||
1299 | static int drain_dac2(struct es1371_state *s, int nonblock) | 1300 | static int drain_dac2(struct es1371_state *s, int nonblock) |
1300 | { | 1301 | { |
1301 | DECLARE_WAITQUEUE(wait, current); | 1302 | DECLARE_WAITQUEUE(wait, current); |
1302 | unsigned long flags; | 1303 | unsigned long flags; |
1303 | int count, tmo; | 1304 | int count, tmo; |
1304 | 1305 | ||
1305 | if (s->dma_dac2.mapped || !s->dma_dac2.ready) | 1306 | if (s->dma_dac2.mapped || !s->dma_dac2.ready) |
1306 | return 0; | 1307 | return 0; |
1307 | add_wait_queue(&s->dma_dac2.wait, &wait); | 1308 | add_wait_queue(&s->dma_dac2.wait, &wait); |
1308 | for (;;) { | 1309 | for (;;) { |
1309 | __set_current_state(TASK_UNINTERRUPTIBLE); | 1310 | __set_current_state(TASK_UNINTERRUPTIBLE); |
1310 | spin_lock_irqsave(&s->lock, flags); | 1311 | spin_lock_irqsave(&s->lock, flags); |
1311 | count = s->dma_dac2.count; | 1312 | count = s->dma_dac2.count; |
1312 | spin_unlock_irqrestore(&s->lock, flags); | 1313 | spin_unlock_irqrestore(&s->lock, flags); |
1313 | if (count <= 0) | 1314 | if (count <= 0) |
1314 | break; | 1315 | break; |
1315 | if (signal_pending(current)) | 1316 | if (signal_pending(current)) |
1316 | break; | 1317 | break; |
1317 | if (nonblock) { | 1318 | if (nonblock) { |
1318 | remove_wait_queue(&s->dma_dac2.wait, &wait); | 1319 | remove_wait_queue(&s->dma_dac2.wait, &wait); |
1319 | set_current_state(TASK_RUNNING); | 1320 | set_current_state(TASK_RUNNING); |
1320 | return -EBUSY; | 1321 | return -EBUSY; |
1321 | } | 1322 | } |
1322 | tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate; | 1323 | tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate; |
1323 | tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT]; | 1324 | tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT]; |
1324 | if (!schedule_timeout(tmo + 1)) | 1325 | if (!schedule_timeout(tmo + 1)) |
1325 | DBG(printk(KERN_DEBUG PFX "dac2 dma timed out??\n");) | 1326 | DBG(printk(KERN_DEBUG PFX "dac2 dma timed out??\n");) |
1326 | } | 1327 | } |
1327 | remove_wait_queue(&s->dma_dac2.wait, &wait); | 1328 | remove_wait_queue(&s->dma_dac2.wait, &wait); |
1328 | set_current_state(TASK_RUNNING); | 1329 | set_current_state(TASK_RUNNING); |
1329 | if (signal_pending(current)) | 1330 | if (signal_pending(current)) |
1330 | return -ERESTARTSYS; | 1331 | return -ERESTARTSYS; |
1331 | return 0; | 1332 | return 0; |
1332 | } | 1333 | } |
1333 | 1334 | ||
1334 | /* --------------------------------------------------------------------- */ | 1335 | /* --------------------------------------------------------------------- */ |
1335 | 1336 | ||
1336 | static ssize_t es1371_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 1337 | static ssize_t es1371_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
1337 | { | 1338 | { |
1338 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1339 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1339 | DECLARE_WAITQUEUE(wait, current); | 1340 | DECLARE_WAITQUEUE(wait, current); |
1340 | ssize_t ret = 0; | 1341 | ssize_t ret = 0; |
1341 | unsigned long flags; | 1342 | unsigned long flags; |
1342 | unsigned swptr; | 1343 | unsigned swptr; |
1343 | int cnt; | 1344 | int cnt; |
1344 | 1345 | ||
1345 | VALIDATE_STATE(s); | 1346 | VALIDATE_STATE(s); |
1346 | if (s->dma_adc.mapped) | 1347 | if (s->dma_adc.mapped) |
1347 | return -ENXIO; | 1348 | return -ENXIO; |
1348 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 1349 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
1349 | return -EFAULT; | 1350 | return -EFAULT; |
1350 | mutex_lock(&s->sem); | 1351 | mutex_lock(&s->sem); |
1351 | if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) | 1352 | if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) |
1352 | goto out2; | 1353 | goto out2; |
1353 | 1354 | ||
1354 | add_wait_queue(&s->dma_adc.wait, &wait); | 1355 | add_wait_queue(&s->dma_adc.wait, &wait); |
1355 | while (count > 0) { | 1356 | while (count > 0) { |
1356 | spin_lock_irqsave(&s->lock, flags); | 1357 | spin_lock_irqsave(&s->lock, flags); |
1357 | swptr = s->dma_adc.swptr; | 1358 | swptr = s->dma_adc.swptr; |
1358 | cnt = s->dma_adc.dmasize-swptr; | 1359 | cnt = s->dma_adc.dmasize-swptr; |
1359 | if (s->dma_adc.count < cnt) | 1360 | if (s->dma_adc.count < cnt) |
1360 | cnt = s->dma_adc.count; | 1361 | cnt = s->dma_adc.count; |
1361 | if (cnt <= 0) | 1362 | if (cnt <= 0) |
1362 | __set_current_state(TASK_INTERRUPTIBLE); | 1363 | __set_current_state(TASK_INTERRUPTIBLE); |
1363 | spin_unlock_irqrestore(&s->lock, flags); | 1364 | spin_unlock_irqrestore(&s->lock, flags); |
1364 | if (cnt > count) | 1365 | if (cnt > count) |
1365 | cnt = count; | 1366 | cnt = count; |
1366 | if (cnt <= 0) { | 1367 | if (cnt <= 0) { |
1367 | if (s->dma_adc.enabled) | 1368 | if (s->dma_adc.enabled) |
1368 | start_adc(s); | 1369 | start_adc(s); |
1369 | if (file->f_flags & O_NONBLOCK) { | 1370 | if (file->f_flags & O_NONBLOCK) { |
1370 | if (!ret) | 1371 | if (!ret) |
1371 | ret = -EAGAIN; | 1372 | ret = -EAGAIN; |
1372 | goto out; | 1373 | goto out; |
1373 | } | 1374 | } |
1374 | mutex_unlock(&s->sem); | 1375 | mutex_unlock(&s->sem); |
1375 | schedule(); | 1376 | schedule(); |
1376 | if (signal_pending(current)) { | 1377 | if (signal_pending(current)) { |
1377 | if (!ret) | 1378 | if (!ret) |
1378 | ret = -ERESTARTSYS; | 1379 | ret = -ERESTARTSYS; |
1379 | goto out2; | 1380 | goto out2; |
1380 | } | 1381 | } |
1381 | mutex_lock(&s->sem); | 1382 | mutex_lock(&s->sem); |
1382 | if (s->dma_adc.mapped) | 1383 | if (s->dma_adc.mapped) |
1383 | { | 1384 | { |
1384 | ret = -ENXIO; | 1385 | ret = -ENXIO; |
1385 | goto out; | 1386 | goto out; |
1386 | } | 1387 | } |
1387 | continue; | 1388 | continue; |
1388 | } | 1389 | } |
1389 | if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) { | 1390 | if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) { |
1390 | if (!ret) | 1391 | if (!ret) |
1391 | ret = -EFAULT; | 1392 | ret = -EFAULT; |
1392 | goto out; | 1393 | goto out; |
1393 | } | 1394 | } |
1394 | swptr = (swptr + cnt) % s->dma_adc.dmasize; | 1395 | swptr = (swptr + cnt) % s->dma_adc.dmasize; |
1395 | spin_lock_irqsave(&s->lock, flags); | 1396 | spin_lock_irqsave(&s->lock, flags); |
1396 | s->dma_adc.swptr = swptr; | 1397 | s->dma_adc.swptr = swptr; |
1397 | s->dma_adc.count -= cnt; | 1398 | s->dma_adc.count -= cnt; |
1398 | spin_unlock_irqrestore(&s->lock, flags); | 1399 | spin_unlock_irqrestore(&s->lock, flags); |
1399 | count -= cnt; | 1400 | count -= cnt; |
1400 | buffer += cnt; | 1401 | buffer += cnt; |
1401 | ret += cnt; | 1402 | ret += cnt; |
1402 | if (s->dma_adc.enabled) | 1403 | if (s->dma_adc.enabled) |
1403 | start_adc(s); | 1404 | start_adc(s); |
1404 | } | 1405 | } |
1405 | out: | 1406 | out: |
1406 | mutex_unlock(&s->sem); | 1407 | mutex_unlock(&s->sem); |
1407 | out2: | 1408 | out2: |
1408 | remove_wait_queue(&s->dma_adc.wait, &wait); | 1409 | remove_wait_queue(&s->dma_adc.wait, &wait); |
1409 | set_current_state(TASK_RUNNING); | 1410 | set_current_state(TASK_RUNNING); |
1410 | return ret; | 1411 | return ret; |
1411 | } | 1412 | } |
1412 | 1413 | ||
1413 | static ssize_t es1371_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 1414 | static ssize_t es1371_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
1414 | { | 1415 | { |
1415 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1416 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1416 | DECLARE_WAITQUEUE(wait, current); | 1417 | DECLARE_WAITQUEUE(wait, current); |
1417 | ssize_t ret; | 1418 | ssize_t ret; |
1418 | unsigned long flags; | 1419 | unsigned long flags; |
1419 | unsigned swptr; | 1420 | unsigned swptr; |
1420 | int cnt; | 1421 | int cnt; |
1421 | 1422 | ||
1422 | VALIDATE_STATE(s); | 1423 | VALIDATE_STATE(s); |
1423 | if (s->dma_dac2.mapped) | 1424 | if (s->dma_dac2.mapped) |
1424 | return -ENXIO; | 1425 | return -ENXIO; |
1425 | if (!access_ok(VERIFY_READ, buffer, count)) | 1426 | if (!access_ok(VERIFY_READ, buffer, count)) |
1426 | return -EFAULT; | 1427 | return -EFAULT; |
1427 | mutex_lock(&s->sem); | 1428 | mutex_lock(&s->sem); |
1428 | if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s))) | 1429 | if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s))) |
1429 | goto out3; | 1430 | goto out3; |
1430 | ret = 0; | 1431 | ret = 0; |
1431 | add_wait_queue(&s->dma_dac2.wait, &wait); | 1432 | add_wait_queue(&s->dma_dac2.wait, &wait); |
1432 | while (count > 0) { | 1433 | while (count > 0) { |
1433 | spin_lock_irqsave(&s->lock, flags); | 1434 | spin_lock_irqsave(&s->lock, flags); |
1434 | if (s->dma_dac2.count < 0) { | 1435 | if (s->dma_dac2.count < 0) { |
1435 | s->dma_dac2.count = 0; | 1436 | s->dma_dac2.count = 0; |
1436 | s->dma_dac2.swptr = s->dma_dac2.hwptr; | 1437 | s->dma_dac2.swptr = s->dma_dac2.hwptr; |
1437 | } | 1438 | } |
1438 | swptr = s->dma_dac2.swptr; | 1439 | swptr = s->dma_dac2.swptr; |
1439 | cnt = s->dma_dac2.dmasize-swptr; | 1440 | cnt = s->dma_dac2.dmasize-swptr; |
1440 | if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize) | 1441 | if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize) |
1441 | cnt = s->dma_dac2.dmasize - s->dma_dac2.count; | 1442 | cnt = s->dma_dac2.dmasize - s->dma_dac2.count; |
1442 | if (cnt <= 0) | 1443 | if (cnt <= 0) |
1443 | __set_current_state(TASK_INTERRUPTIBLE); | 1444 | __set_current_state(TASK_INTERRUPTIBLE); |
1444 | spin_unlock_irqrestore(&s->lock, flags); | 1445 | spin_unlock_irqrestore(&s->lock, flags); |
1445 | if (cnt > count) | 1446 | if (cnt > count) |
1446 | cnt = count; | 1447 | cnt = count; |
1447 | if (cnt <= 0) { | 1448 | if (cnt <= 0) { |
1448 | if (s->dma_dac2.enabled) | 1449 | if (s->dma_dac2.enabled) |
1449 | start_dac2(s); | 1450 | start_dac2(s); |
1450 | if (file->f_flags & O_NONBLOCK) { | 1451 | if (file->f_flags & O_NONBLOCK) { |
1451 | if (!ret) | 1452 | if (!ret) |
1452 | ret = -EAGAIN; | 1453 | ret = -EAGAIN; |
1453 | goto out; | 1454 | goto out; |
1454 | } | 1455 | } |
1455 | mutex_unlock(&s->sem); | 1456 | mutex_unlock(&s->sem); |
1456 | schedule(); | 1457 | schedule(); |
1457 | if (signal_pending(current)) { | 1458 | if (signal_pending(current)) { |
1458 | if (!ret) | 1459 | if (!ret) |
1459 | ret = -ERESTARTSYS; | 1460 | ret = -ERESTARTSYS; |
1460 | goto out2; | 1461 | goto out2; |
1461 | } | 1462 | } |
1462 | mutex_lock(&s->sem); | 1463 | mutex_lock(&s->sem); |
1463 | if (s->dma_dac2.mapped) | 1464 | if (s->dma_dac2.mapped) |
1464 | { | 1465 | { |
1465 | ret = -ENXIO; | 1466 | ret = -ENXIO; |
1466 | goto out; | 1467 | goto out; |
1467 | } | 1468 | } |
1468 | continue; | 1469 | continue; |
1469 | } | 1470 | } |
1470 | if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) { | 1471 | if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) { |
1471 | if (!ret) | 1472 | if (!ret) |
1472 | ret = -EFAULT; | 1473 | ret = -EFAULT; |
1473 | goto out; | 1474 | goto out; |
1474 | } | 1475 | } |
1475 | swptr = (swptr + cnt) % s->dma_dac2.dmasize; | 1476 | swptr = (swptr + cnt) % s->dma_dac2.dmasize; |
1476 | spin_lock_irqsave(&s->lock, flags); | 1477 | spin_lock_irqsave(&s->lock, flags); |
1477 | s->dma_dac2.swptr = swptr; | 1478 | s->dma_dac2.swptr = swptr; |
1478 | s->dma_dac2.count += cnt; | 1479 | s->dma_dac2.count += cnt; |
1479 | s->dma_dac2.endcleared = 0; | 1480 | s->dma_dac2.endcleared = 0; |
1480 | spin_unlock_irqrestore(&s->lock, flags); | 1481 | spin_unlock_irqrestore(&s->lock, flags); |
1481 | count -= cnt; | 1482 | count -= cnt; |
1482 | buffer += cnt; | 1483 | buffer += cnt; |
1483 | ret += cnt; | 1484 | ret += cnt; |
1484 | if (s->dma_dac2.enabled) | 1485 | if (s->dma_dac2.enabled) |
1485 | start_dac2(s); | 1486 | start_dac2(s); |
1486 | } | 1487 | } |
1487 | out: | 1488 | out: |
1488 | mutex_unlock(&s->sem); | 1489 | mutex_unlock(&s->sem); |
1489 | out2: | 1490 | out2: |
1490 | remove_wait_queue(&s->dma_dac2.wait, &wait); | 1491 | remove_wait_queue(&s->dma_dac2.wait, &wait); |
1491 | out3: | 1492 | out3: |
1492 | set_current_state(TASK_RUNNING); | 1493 | set_current_state(TASK_RUNNING); |
1493 | return ret; | 1494 | return ret; |
1494 | } | 1495 | } |
1495 | 1496 | ||
1496 | /* No kernel lock - we have our own spinlock */ | 1497 | /* No kernel lock - we have our own spinlock */ |
1497 | static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wait) | 1498 | static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wait) |
1498 | { | 1499 | { |
1499 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1500 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1500 | unsigned long flags; | 1501 | unsigned long flags; |
1501 | unsigned int mask = 0; | 1502 | unsigned int mask = 0; |
1502 | 1503 | ||
1503 | VALIDATE_STATE(s); | 1504 | VALIDATE_STATE(s); |
1504 | if (file->f_mode & FMODE_WRITE) { | 1505 | if (file->f_mode & FMODE_WRITE) { |
1505 | if (!s->dma_dac2.ready && prog_dmabuf_dac2(s)) | 1506 | if (!s->dma_dac2.ready && prog_dmabuf_dac2(s)) |
1506 | return 0; | 1507 | return 0; |
1507 | poll_wait(file, &s->dma_dac2.wait, wait); | 1508 | poll_wait(file, &s->dma_dac2.wait, wait); |
1508 | } | 1509 | } |
1509 | if (file->f_mode & FMODE_READ) { | 1510 | if (file->f_mode & FMODE_READ) { |
1510 | if (!s->dma_adc.ready && prog_dmabuf_adc(s)) | 1511 | if (!s->dma_adc.ready && prog_dmabuf_adc(s)) |
1511 | return 0; | 1512 | return 0; |
1512 | poll_wait(file, &s->dma_adc.wait, wait); | 1513 | poll_wait(file, &s->dma_adc.wait, wait); |
1513 | } | 1514 | } |
1514 | spin_lock_irqsave(&s->lock, flags); | 1515 | spin_lock_irqsave(&s->lock, flags); |
1515 | es1371_update_ptr(s); | 1516 | es1371_update_ptr(s); |
1516 | if (file->f_mode & FMODE_READ) { | 1517 | if (file->f_mode & FMODE_READ) { |
1517 | if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) | 1518 | if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) |
1518 | mask |= POLLIN | POLLRDNORM; | 1519 | mask |= POLLIN | POLLRDNORM; |
1519 | } | 1520 | } |
1520 | if (file->f_mode & FMODE_WRITE) { | 1521 | if (file->f_mode & FMODE_WRITE) { |
1521 | if (s->dma_dac2.mapped) { | 1522 | if (s->dma_dac2.mapped) { |
1522 | if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) | 1523 | if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) |
1523 | mask |= POLLOUT | POLLWRNORM; | 1524 | mask |= POLLOUT | POLLWRNORM; |
1524 | } else { | 1525 | } else { |
1525 | if ((signed)s->dma_dac2.dmasize >= s->dma_dac2.count + (signed)s->dma_dac2.fragsize) | 1526 | if ((signed)s->dma_dac2.dmasize >= s->dma_dac2.count + (signed)s->dma_dac2.fragsize) |
1526 | mask |= POLLOUT | POLLWRNORM; | 1527 | mask |= POLLOUT | POLLWRNORM; |
1527 | } | 1528 | } |
1528 | } | 1529 | } |
1529 | spin_unlock_irqrestore(&s->lock, flags); | 1530 | spin_unlock_irqrestore(&s->lock, flags); |
1530 | return mask; | 1531 | return mask; |
1531 | } | 1532 | } |
1532 | 1533 | ||
1533 | static int es1371_mmap(struct file *file, struct vm_area_struct *vma) | 1534 | static int es1371_mmap(struct file *file, struct vm_area_struct *vma) |
1534 | { | 1535 | { |
1535 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1536 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1536 | struct dmabuf *db; | 1537 | struct dmabuf *db; |
1537 | int ret = 0; | 1538 | int ret = 0; |
1538 | unsigned long size; | 1539 | unsigned long size; |
1539 | 1540 | ||
1540 | VALIDATE_STATE(s); | 1541 | VALIDATE_STATE(s); |
1541 | lock_kernel(); | 1542 | lock_kernel(); |
1542 | mutex_lock(&s->sem); | 1543 | mutex_lock(&s->sem); |
1543 | 1544 | ||
1544 | if (vma->vm_flags & VM_WRITE) { | 1545 | if (vma->vm_flags & VM_WRITE) { |
1545 | if ((ret = prog_dmabuf_dac2(s)) != 0) { | 1546 | if ((ret = prog_dmabuf_dac2(s)) != 0) { |
1546 | goto out; | 1547 | goto out; |
1547 | } | 1548 | } |
1548 | db = &s->dma_dac2; | 1549 | db = &s->dma_dac2; |
1549 | } else if (vma->vm_flags & VM_READ) { | 1550 | } else if (vma->vm_flags & VM_READ) { |
1550 | if ((ret = prog_dmabuf_adc(s)) != 0) { | 1551 | if ((ret = prog_dmabuf_adc(s)) != 0) { |
1551 | goto out; | 1552 | goto out; |
1552 | } | 1553 | } |
1553 | db = &s->dma_adc; | 1554 | db = &s->dma_adc; |
1554 | } else { | 1555 | } else { |
1555 | ret = -EINVAL; | 1556 | ret = -EINVAL; |
1556 | goto out; | 1557 | goto out; |
1557 | } | 1558 | } |
1558 | if (vma->vm_pgoff != 0) { | 1559 | if (vma->vm_pgoff != 0) { |
1559 | ret = -EINVAL; | 1560 | ret = -EINVAL; |
1560 | goto out; | 1561 | goto out; |
1561 | } | 1562 | } |
1562 | size = vma->vm_end - vma->vm_start; | 1563 | size = vma->vm_end - vma->vm_start; |
1563 | if (size > (PAGE_SIZE << db->buforder)) { | 1564 | if (size > (PAGE_SIZE << db->buforder)) { |
1564 | ret = -EINVAL; | 1565 | ret = -EINVAL; |
1565 | goto out; | 1566 | goto out; |
1566 | } | 1567 | } |
1567 | if (remap_pfn_range(vma, vma->vm_start, | 1568 | if (remap_pfn_range(vma, vma->vm_start, |
1568 | virt_to_phys(db->rawbuf) >> PAGE_SHIFT, | 1569 | virt_to_phys(db->rawbuf) >> PAGE_SHIFT, |
1569 | size, vma->vm_page_prot)) { | 1570 | size, vma->vm_page_prot)) { |
1570 | ret = -EAGAIN; | 1571 | ret = -EAGAIN; |
1571 | goto out; | 1572 | goto out; |
1572 | } | 1573 | } |
1573 | db->mapped = 1; | 1574 | db->mapped = 1; |
1574 | out: | 1575 | out: |
1575 | mutex_unlock(&s->sem); | 1576 | mutex_unlock(&s->sem); |
1576 | unlock_kernel(); | 1577 | unlock_kernel(); |
1577 | return ret; | 1578 | return ret; |
1578 | } | 1579 | } |
1579 | 1580 | ||
1580 | static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 1581 | static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
1581 | { | 1582 | { |
1582 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1583 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1583 | unsigned long flags; | 1584 | unsigned long flags; |
1584 | audio_buf_info abinfo; | 1585 | audio_buf_info abinfo; |
1585 | count_info cinfo; | 1586 | count_info cinfo; |
1586 | int count; | 1587 | int count; |
1587 | int val, mapped, ret; | 1588 | int val, mapped, ret; |
1588 | void __user *argp = (void __user *)arg; | 1589 | void __user *argp = (void __user *)arg; |
1589 | int __user *p = argp; | 1590 | int __user *p = argp; |
1590 | 1591 | ||
1591 | VALIDATE_STATE(s); | 1592 | VALIDATE_STATE(s); |
1592 | mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac2.mapped) || | 1593 | mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac2.mapped) || |
1593 | ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); | 1594 | ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); |
1594 | switch (cmd) { | 1595 | switch (cmd) { |
1595 | case OSS_GETVERSION: | 1596 | case OSS_GETVERSION: |
1596 | return put_user(SOUND_VERSION, p); | 1597 | return put_user(SOUND_VERSION, p); |
1597 | 1598 | ||
1598 | case SNDCTL_DSP_SYNC: | 1599 | case SNDCTL_DSP_SYNC: |
1599 | if (file->f_mode & FMODE_WRITE) | 1600 | if (file->f_mode & FMODE_WRITE) |
1600 | return drain_dac2(s, 0/*file->f_flags & O_NONBLOCK*/); | 1601 | return drain_dac2(s, 0/*file->f_flags & O_NONBLOCK*/); |
1601 | return 0; | 1602 | return 0; |
1602 | 1603 | ||
1603 | case SNDCTL_DSP_SETDUPLEX: | 1604 | case SNDCTL_DSP_SETDUPLEX: |
1604 | return 0; | 1605 | return 0; |
1605 | 1606 | ||
1606 | case SNDCTL_DSP_GETCAPS: | 1607 | case SNDCTL_DSP_GETCAPS: |
1607 | return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p); | 1608 | return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p); |
1608 | 1609 | ||
1609 | case SNDCTL_DSP_RESET: | 1610 | case SNDCTL_DSP_RESET: |
1610 | if (file->f_mode & FMODE_WRITE) { | 1611 | if (file->f_mode & FMODE_WRITE) { |
1611 | stop_dac2(s); | 1612 | stop_dac2(s); |
1612 | synchronize_irq(s->irq); | 1613 | synchronize_irq(s->irq); |
1613 | s->dma_dac2.swptr = s->dma_dac2.hwptr = s->dma_dac2.count = s->dma_dac2.total_bytes = 0; | 1614 | s->dma_dac2.swptr = s->dma_dac2.hwptr = s->dma_dac2.count = s->dma_dac2.total_bytes = 0; |
1614 | } | 1615 | } |
1615 | if (file->f_mode & FMODE_READ) { | 1616 | if (file->f_mode & FMODE_READ) { |
1616 | stop_adc(s); | 1617 | stop_adc(s); |
1617 | synchronize_irq(s->irq); | 1618 | synchronize_irq(s->irq); |
1618 | s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; | 1619 | s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; |
1619 | } | 1620 | } |
1620 | return 0; | 1621 | return 0; |
1621 | 1622 | ||
1622 | case SNDCTL_DSP_SPEED: | 1623 | case SNDCTL_DSP_SPEED: |
1623 | if (get_user(val, p)) | 1624 | if (get_user(val, p)) |
1624 | return -EFAULT; | 1625 | return -EFAULT; |
1625 | if (val >= 0) { | 1626 | if (val >= 0) { |
1626 | if (file->f_mode & FMODE_READ) { | 1627 | if (file->f_mode & FMODE_READ) { |
1627 | stop_adc(s); | 1628 | stop_adc(s); |
1628 | s->dma_adc.ready = 0; | 1629 | s->dma_adc.ready = 0; |
1629 | set_adc_rate(s, val); | 1630 | set_adc_rate(s, val); |
1630 | } | 1631 | } |
1631 | if (file->f_mode & FMODE_WRITE) { | 1632 | if (file->f_mode & FMODE_WRITE) { |
1632 | stop_dac2(s); | 1633 | stop_dac2(s); |
1633 | s->dma_dac2.ready = 0; | 1634 | s->dma_dac2.ready = 0; |
1634 | set_dac2_rate(s, val); | 1635 | set_dac2_rate(s, val); |
1635 | } | 1636 | } |
1636 | } | 1637 | } |
1637 | return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p); | 1638 | return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p); |
1638 | 1639 | ||
1639 | case SNDCTL_DSP_STEREO: | 1640 | case SNDCTL_DSP_STEREO: |
1640 | if (get_user(val, p)) | 1641 | if (get_user(val, p)) |
1641 | return -EFAULT; | 1642 | return -EFAULT; |
1642 | if (file->f_mode & FMODE_READ) { | 1643 | if (file->f_mode & FMODE_READ) { |
1643 | stop_adc(s); | 1644 | stop_adc(s); |
1644 | s->dma_adc.ready = 0; | 1645 | s->dma_adc.ready = 0; |
1645 | spin_lock_irqsave(&s->lock, flags); | 1646 | spin_lock_irqsave(&s->lock, flags); |
1646 | if (val) | 1647 | if (val) |
1647 | s->sctrl |= SCTRL_R1SMB; | 1648 | s->sctrl |= SCTRL_R1SMB; |
1648 | else | 1649 | else |
1649 | s->sctrl &= ~SCTRL_R1SMB; | 1650 | s->sctrl &= ~SCTRL_R1SMB; |
1650 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1651 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1651 | spin_unlock_irqrestore(&s->lock, flags); | 1652 | spin_unlock_irqrestore(&s->lock, flags); |
1652 | } | 1653 | } |
1653 | if (file->f_mode & FMODE_WRITE) { | 1654 | if (file->f_mode & FMODE_WRITE) { |
1654 | stop_dac2(s); | 1655 | stop_dac2(s); |
1655 | s->dma_dac2.ready = 0; | 1656 | s->dma_dac2.ready = 0; |
1656 | spin_lock_irqsave(&s->lock, flags); | 1657 | spin_lock_irqsave(&s->lock, flags); |
1657 | if (val) | 1658 | if (val) |
1658 | s->sctrl |= SCTRL_P2SMB; | 1659 | s->sctrl |= SCTRL_P2SMB; |
1659 | else | 1660 | else |
1660 | s->sctrl &= ~SCTRL_P2SMB; | 1661 | s->sctrl &= ~SCTRL_P2SMB; |
1661 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1662 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1662 | spin_unlock_irqrestore(&s->lock, flags); | 1663 | spin_unlock_irqrestore(&s->lock, flags); |
1663 | } | 1664 | } |
1664 | return 0; | 1665 | return 0; |
1665 | 1666 | ||
1666 | case SNDCTL_DSP_CHANNELS: | 1667 | case SNDCTL_DSP_CHANNELS: |
1667 | if (get_user(val, p)) | 1668 | if (get_user(val, p)) |
1668 | return -EFAULT; | 1669 | return -EFAULT; |
1669 | if (val != 0) { | 1670 | if (val != 0) { |
1670 | if (file->f_mode & FMODE_READ) { | 1671 | if (file->f_mode & FMODE_READ) { |
1671 | stop_adc(s); | 1672 | stop_adc(s); |
1672 | s->dma_adc.ready = 0; | 1673 | s->dma_adc.ready = 0; |
1673 | spin_lock_irqsave(&s->lock, flags); | 1674 | spin_lock_irqsave(&s->lock, flags); |
1674 | if (val >= 2) | 1675 | if (val >= 2) |
1675 | s->sctrl |= SCTRL_R1SMB; | 1676 | s->sctrl |= SCTRL_R1SMB; |
1676 | else | 1677 | else |
1677 | s->sctrl &= ~SCTRL_R1SMB; | 1678 | s->sctrl &= ~SCTRL_R1SMB; |
1678 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1679 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1679 | spin_unlock_irqrestore(&s->lock, flags); | 1680 | spin_unlock_irqrestore(&s->lock, flags); |
1680 | } | 1681 | } |
1681 | if (file->f_mode & FMODE_WRITE) { | 1682 | if (file->f_mode & FMODE_WRITE) { |
1682 | stop_dac2(s); | 1683 | stop_dac2(s); |
1683 | s->dma_dac2.ready = 0; | 1684 | s->dma_dac2.ready = 0; |
1684 | spin_lock_irqsave(&s->lock, flags); | 1685 | spin_lock_irqsave(&s->lock, flags); |
1685 | if (val >= 2) | 1686 | if (val >= 2) |
1686 | s->sctrl |= SCTRL_P2SMB; | 1687 | s->sctrl |= SCTRL_P2SMB; |
1687 | else | 1688 | else |
1688 | s->sctrl &= ~SCTRL_P2SMB; | 1689 | s->sctrl &= ~SCTRL_P2SMB; |
1689 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1690 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1690 | spin_unlock_irqrestore(&s->lock, flags); | 1691 | spin_unlock_irqrestore(&s->lock, flags); |
1691 | } | 1692 | } |
1692 | } | 1693 | } |
1693 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p); | 1694 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p); |
1694 | 1695 | ||
1695 | case SNDCTL_DSP_GETFMTS: /* Returns a mask */ | 1696 | case SNDCTL_DSP_GETFMTS: /* Returns a mask */ |
1696 | return put_user(AFMT_S16_LE|AFMT_U8, p); | 1697 | return put_user(AFMT_S16_LE|AFMT_U8, p); |
1697 | 1698 | ||
1698 | case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ | 1699 | case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ |
1699 | if (get_user(val, p)) | 1700 | if (get_user(val, p)) |
1700 | return -EFAULT; | 1701 | return -EFAULT; |
1701 | if (val != AFMT_QUERY) { | 1702 | if (val != AFMT_QUERY) { |
1702 | if (file->f_mode & FMODE_READ) { | 1703 | if (file->f_mode & FMODE_READ) { |
1703 | stop_adc(s); | 1704 | stop_adc(s); |
1704 | s->dma_adc.ready = 0; | 1705 | s->dma_adc.ready = 0; |
1705 | spin_lock_irqsave(&s->lock, flags); | 1706 | spin_lock_irqsave(&s->lock, flags); |
1706 | if (val == AFMT_S16_LE) | 1707 | if (val == AFMT_S16_LE) |
1707 | s->sctrl |= SCTRL_R1SEB; | 1708 | s->sctrl |= SCTRL_R1SEB; |
1708 | else | 1709 | else |
1709 | s->sctrl &= ~SCTRL_R1SEB; | 1710 | s->sctrl &= ~SCTRL_R1SEB; |
1710 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1711 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1711 | spin_unlock_irqrestore(&s->lock, flags); | 1712 | spin_unlock_irqrestore(&s->lock, flags); |
1712 | } | 1713 | } |
1713 | if (file->f_mode & FMODE_WRITE) { | 1714 | if (file->f_mode & FMODE_WRITE) { |
1714 | stop_dac2(s); | 1715 | stop_dac2(s); |
1715 | s->dma_dac2.ready = 0; | 1716 | s->dma_dac2.ready = 0; |
1716 | spin_lock_irqsave(&s->lock, flags); | 1717 | spin_lock_irqsave(&s->lock, flags); |
1717 | if (val == AFMT_S16_LE) | 1718 | if (val == AFMT_S16_LE) |
1718 | s->sctrl |= SCTRL_P2SEB; | 1719 | s->sctrl |= SCTRL_P2SEB; |
1719 | else | 1720 | else |
1720 | s->sctrl &= ~SCTRL_P2SEB; | 1721 | s->sctrl &= ~SCTRL_P2SEB; |
1721 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1722 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1722 | spin_unlock_irqrestore(&s->lock, flags); | 1723 | spin_unlock_irqrestore(&s->lock, flags); |
1723 | } | 1724 | } |
1724 | } | 1725 | } |
1725 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? | 1726 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? |
1726 | AFMT_S16_LE : AFMT_U8, p); | 1727 | AFMT_S16_LE : AFMT_U8, p); |
1727 | 1728 | ||
1728 | case SNDCTL_DSP_POST: | 1729 | case SNDCTL_DSP_POST: |
1729 | return 0; | 1730 | return 0; |
1730 | 1731 | ||
1731 | case SNDCTL_DSP_GETTRIGGER: | 1732 | case SNDCTL_DSP_GETTRIGGER: |
1732 | val = 0; | 1733 | val = 0; |
1733 | if (file->f_mode & FMODE_READ && s->ctrl & CTRL_ADC_EN) | 1734 | if (file->f_mode & FMODE_READ && s->ctrl & CTRL_ADC_EN) |
1734 | val |= PCM_ENABLE_INPUT; | 1735 | val |= PCM_ENABLE_INPUT; |
1735 | if (file->f_mode & FMODE_WRITE && s->ctrl & CTRL_DAC2_EN) | 1736 | if (file->f_mode & FMODE_WRITE && s->ctrl & CTRL_DAC2_EN) |
1736 | val |= PCM_ENABLE_OUTPUT; | 1737 | val |= PCM_ENABLE_OUTPUT; |
1737 | return put_user(val, p); | 1738 | return put_user(val, p); |
1738 | 1739 | ||
1739 | case SNDCTL_DSP_SETTRIGGER: | 1740 | case SNDCTL_DSP_SETTRIGGER: |
1740 | if (get_user(val, p)) | 1741 | if (get_user(val, p)) |
1741 | return -EFAULT; | 1742 | return -EFAULT; |
1742 | if (file->f_mode & FMODE_READ) { | 1743 | if (file->f_mode & FMODE_READ) { |
1743 | if (val & PCM_ENABLE_INPUT) { | 1744 | if (val & PCM_ENABLE_INPUT) { |
1744 | if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) | 1745 | if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) |
1745 | return ret; | 1746 | return ret; |
1746 | s->dma_adc.enabled = 1; | 1747 | s->dma_adc.enabled = 1; |
1747 | start_adc(s); | 1748 | start_adc(s); |
1748 | } else { | 1749 | } else { |
1749 | s->dma_adc.enabled = 0; | 1750 | s->dma_adc.enabled = 0; |
1750 | stop_adc(s); | 1751 | stop_adc(s); |
1751 | } | 1752 | } |
1752 | } | 1753 | } |
1753 | if (file->f_mode & FMODE_WRITE) { | 1754 | if (file->f_mode & FMODE_WRITE) { |
1754 | if (val & PCM_ENABLE_OUTPUT) { | 1755 | if (val & PCM_ENABLE_OUTPUT) { |
1755 | if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s))) | 1756 | if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s))) |
1756 | return ret; | 1757 | return ret; |
1757 | s->dma_dac2.enabled = 1; | 1758 | s->dma_dac2.enabled = 1; |
1758 | start_dac2(s); | 1759 | start_dac2(s); |
1759 | } else { | 1760 | } else { |
1760 | s->dma_dac2.enabled = 0; | 1761 | s->dma_dac2.enabled = 0; |
1761 | stop_dac2(s); | 1762 | stop_dac2(s); |
1762 | } | 1763 | } |
1763 | } | 1764 | } |
1764 | return 0; | 1765 | return 0; |
1765 | 1766 | ||
1766 | case SNDCTL_DSP_GETOSPACE: | 1767 | case SNDCTL_DSP_GETOSPACE: |
1767 | if (!(file->f_mode & FMODE_WRITE)) | 1768 | if (!(file->f_mode & FMODE_WRITE)) |
1768 | return -EINVAL; | 1769 | return -EINVAL; |
1769 | if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) | 1770 | if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) |
1770 | return val; | 1771 | return val; |
1771 | spin_lock_irqsave(&s->lock, flags); | 1772 | spin_lock_irqsave(&s->lock, flags); |
1772 | es1371_update_ptr(s); | 1773 | es1371_update_ptr(s); |
1773 | abinfo.fragsize = s->dma_dac2.fragsize; | 1774 | abinfo.fragsize = s->dma_dac2.fragsize; |
1774 | count = s->dma_dac2.count; | 1775 | count = s->dma_dac2.count; |
1775 | if (count < 0) | 1776 | if (count < 0) |
1776 | count = 0; | 1777 | count = 0; |
1777 | abinfo.bytes = s->dma_dac2.dmasize - count; | 1778 | abinfo.bytes = s->dma_dac2.dmasize - count; |
1778 | abinfo.fragstotal = s->dma_dac2.numfrag; | 1779 | abinfo.fragstotal = s->dma_dac2.numfrag; |
1779 | abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift; | 1780 | abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift; |
1780 | spin_unlock_irqrestore(&s->lock, flags); | 1781 | spin_unlock_irqrestore(&s->lock, flags); |
1781 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 1782 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; |
1782 | 1783 | ||
1783 | case SNDCTL_DSP_GETISPACE: | 1784 | case SNDCTL_DSP_GETISPACE: |
1784 | if (!(file->f_mode & FMODE_READ)) | 1785 | if (!(file->f_mode & FMODE_READ)) |
1785 | return -EINVAL; | 1786 | return -EINVAL; |
1786 | if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) | 1787 | if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) |
1787 | return val; | 1788 | return val; |
1788 | spin_lock_irqsave(&s->lock, flags); | 1789 | spin_lock_irqsave(&s->lock, flags); |
1789 | es1371_update_ptr(s); | 1790 | es1371_update_ptr(s); |
1790 | abinfo.fragsize = s->dma_adc.fragsize; | 1791 | abinfo.fragsize = s->dma_adc.fragsize; |
1791 | count = s->dma_adc.count; | 1792 | count = s->dma_adc.count; |
1792 | if (count < 0) | 1793 | if (count < 0) |
1793 | count = 0; | 1794 | count = 0; |
1794 | abinfo.bytes = count; | 1795 | abinfo.bytes = count; |
1795 | abinfo.fragstotal = s->dma_adc.numfrag; | 1796 | abinfo.fragstotal = s->dma_adc.numfrag; |
1796 | abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; | 1797 | abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; |
1797 | spin_unlock_irqrestore(&s->lock, flags); | 1798 | spin_unlock_irqrestore(&s->lock, flags); |
1798 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 1799 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; |
1799 | 1800 | ||
1800 | case SNDCTL_DSP_NONBLOCK: | 1801 | case SNDCTL_DSP_NONBLOCK: |
1801 | file->f_flags |= O_NONBLOCK; | 1802 | file->f_flags |= O_NONBLOCK; |
1802 | return 0; | 1803 | return 0; |
1803 | 1804 | ||
1804 | case SNDCTL_DSP_GETODELAY: | 1805 | case SNDCTL_DSP_GETODELAY: |
1805 | if (!(file->f_mode & FMODE_WRITE)) | 1806 | if (!(file->f_mode & FMODE_WRITE)) |
1806 | return -EINVAL; | 1807 | return -EINVAL; |
1807 | if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) | 1808 | if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) |
1808 | return val; | 1809 | return val; |
1809 | spin_lock_irqsave(&s->lock, flags); | 1810 | spin_lock_irqsave(&s->lock, flags); |
1810 | es1371_update_ptr(s); | 1811 | es1371_update_ptr(s); |
1811 | count = s->dma_dac2.count; | 1812 | count = s->dma_dac2.count; |
1812 | spin_unlock_irqrestore(&s->lock, flags); | 1813 | spin_unlock_irqrestore(&s->lock, flags); |
1813 | if (count < 0) | 1814 | if (count < 0) |
1814 | count = 0; | 1815 | count = 0; |
1815 | return put_user(count, p); | 1816 | return put_user(count, p); |
1816 | 1817 | ||
1817 | case SNDCTL_DSP_GETIPTR: | 1818 | case SNDCTL_DSP_GETIPTR: |
1818 | if (!(file->f_mode & FMODE_READ)) | 1819 | if (!(file->f_mode & FMODE_READ)) |
1819 | return -EINVAL; | 1820 | return -EINVAL; |
1820 | if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) | 1821 | if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) |
1821 | return val; | 1822 | return val; |
1822 | spin_lock_irqsave(&s->lock, flags); | 1823 | spin_lock_irqsave(&s->lock, flags); |
1823 | es1371_update_ptr(s); | 1824 | es1371_update_ptr(s); |
1824 | cinfo.bytes = s->dma_adc.total_bytes; | 1825 | cinfo.bytes = s->dma_adc.total_bytes; |
1825 | count = s->dma_adc.count; | 1826 | count = s->dma_adc.count; |
1826 | if (count < 0) | 1827 | if (count < 0) |
1827 | count = 0; | 1828 | count = 0; |
1828 | cinfo.blocks = count >> s->dma_adc.fragshift; | 1829 | cinfo.blocks = count >> s->dma_adc.fragshift; |
1829 | cinfo.ptr = s->dma_adc.hwptr; | 1830 | cinfo.ptr = s->dma_adc.hwptr; |
1830 | if (s->dma_adc.mapped) | 1831 | if (s->dma_adc.mapped) |
1831 | s->dma_adc.count &= s->dma_adc.fragsize-1; | 1832 | s->dma_adc.count &= s->dma_adc.fragsize-1; |
1832 | spin_unlock_irqrestore(&s->lock, flags); | 1833 | spin_unlock_irqrestore(&s->lock, flags); |
1833 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) | 1834 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) |
1834 | return -EFAULT; | 1835 | return -EFAULT; |
1835 | return 0; | 1836 | return 0; |
1836 | 1837 | ||
1837 | case SNDCTL_DSP_GETOPTR: | 1838 | case SNDCTL_DSP_GETOPTR: |
1838 | if (!(file->f_mode & FMODE_WRITE)) | 1839 | if (!(file->f_mode & FMODE_WRITE)) |
1839 | return -EINVAL; | 1840 | return -EINVAL; |
1840 | if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) | 1841 | if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) |
1841 | return val; | 1842 | return val; |
1842 | spin_lock_irqsave(&s->lock, flags); | 1843 | spin_lock_irqsave(&s->lock, flags); |
1843 | es1371_update_ptr(s); | 1844 | es1371_update_ptr(s); |
1844 | cinfo.bytes = s->dma_dac2.total_bytes; | 1845 | cinfo.bytes = s->dma_dac2.total_bytes; |
1845 | count = s->dma_dac2.count; | 1846 | count = s->dma_dac2.count; |
1846 | if (count < 0) | 1847 | if (count < 0) |
1847 | count = 0; | 1848 | count = 0; |
1848 | cinfo.blocks = count >> s->dma_dac2.fragshift; | 1849 | cinfo.blocks = count >> s->dma_dac2.fragshift; |
1849 | cinfo.ptr = s->dma_dac2.hwptr; | 1850 | cinfo.ptr = s->dma_dac2.hwptr; |
1850 | if (s->dma_dac2.mapped) | 1851 | if (s->dma_dac2.mapped) |
1851 | s->dma_dac2.count &= s->dma_dac2.fragsize-1; | 1852 | s->dma_dac2.count &= s->dma_dac2.fragsize-1; |
1852 | spin_unlock_irqrestore(&s->lock, flags); | 1853 | spin_unlock_irqrestore(&s->lock, flags); |
1853 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) | 1854 | if (copy_to_user(argp, &cinfo, sizeof(cinfo))) |
1854 | return -EFAULT; | 1855 | return -EFAULT; |
1855 | return 0; | 1856 | return 0; |
1856 | 1857 | ||
1857 | case SNDCTL_DSP_GETBLKSIZE: | 1858 | case SNDCTL_DSP_GETBLKSIZE: |
1858 | if (file->f_mode & FMODE_WRITE) { | 1859 | if (file->f_mode & FMODE_WRITE) { |
1859 | if ((val = prog_dmabuf_dac2(s))) | 1860 | if ((val = prog_dmabuf_dac2(s))) |
1860 | return val; | 1861 | return val; |
1861 | return put_user(s->dma_dac2.fragsize, p); | 1862 | return put_user(s->dma_dac2.fragsize, p); |
1862 | } | 1863 | } |
1863 | if ((val = prog_dmabuf_adc(s))) | 1864 | if ((val = prog_dmabuf_adc(s))) |
1864 | return val; | 1865 | return val; |
1865 | return put_user(s->dma_adc.fragsize, p); | 1866 | return put_user(s->dma_adc.fragsize, p); |
1866 | 1867 | ||
1867 | case SNDCTL_DSP_SETFRAGMENT: | 1868 | case SNDCTL_DSP_SETFRAGMENT: |
1868 | if (get_user(val, p)) | 1869 | if (get_user(val, p)) |
1869 | return -EFAULT; | 1870 | return -EFAULT; |
1870 | if (file->f_mode & FMODE_READ) { | 1871 | if (file->f_mode & FMODE_READ) { |
1871 | s->dma_adc.ossfragshift = val & 0xffff; | 1872 | s->dma_adc.ossfragshift = val & 0xffff; |
1872 | s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; | 1873 | s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; |
1873 | if (s->dma_adc.ossfragshift < 4) | 1874 | if (s->dma_adc.ossfragshift < 4) |
1874 | s->dma_adc.ossfragshift = 4; | 1875 | s->dma_adc.ossfragshift = 4; |
1875 | if (s->dma_adc.ossfragshift > 15) | 1876 | if (s->dma_adc.ossfragshift > 15) |
1876 | s->dma_adc.ossfragshift = 15; | 1877 | s->dma_adc.ossfragshift = 15; |
1877 | if (s->dma_adc.ossmaxfrags < 4) | 1878 | if (s->dma_adc.ossmaxfrags < 4) |
1878 | s->dma_adc.ossmaxfrags = 4; | 1879 | s->dma_adc.ossmaxfrags = 4; |
1879 | } | 1880 | } |
1880 | if (file->f_mode & FMODE_WRITE) { | 1881 | if (file->f_mode & FMODE_WRITE) { |
1881 | s->dma_dac2.ossfragshift = val & 0xffff; | 1882 | s->dma_dac2.ossfragshift = val & 0xffff; |
1882 | s->dma_dac2.ossmaxfrags = (val >> 16) & 0xffff; | 1883 | s->dma_dac2.ossmaxfrags = (val >> 16) & 0xffff; |
1883 | if (s->dma_dac2.ossfragshift < 4) | 1884 | if (s->dma_dac2.ossfragshift < 4) |
1884 | s->dma_dac2.ossfragshift = 4; | 1885 | s->dma_dac2.ossfragshift = 4; |
1885 | if (s->dma_dac2.ossfragshift > 15) | 1886 | if (s->dma_dac2.ossfragshift > 15) |
1886 | s->dma_dac2.ossfragshift = 15; | 1887 | s->dma_dac2.ossfragshift = 15; |
1887 | if (s->dma_dac2.ossmaxfrags < 4) | 1888 | if (s->dma_dac2.ossmaxfrags < 4) |
1888 | s->dma_dac2.ossmaxfrags = 4; | 1889 | s->dma_dac2.ossmaxfrags = 4; |
1889 | } | 1890 | } |
1890 | return 0; | 1891 | return 0; |
1891 | 1892 | ||
1892 | case SNDCTL_DSP_SUBDIVIDE: | 1893 | case SNDCTL_DSP_SUBDIVIDE: |
1893 | if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || | 1894 | if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || |
1894 | (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision)) | 1895 | (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision)) |
1895 | return -EINVAL; | 1896 | return -EINVAL; |
1896 | if (get_user(val, p)) | 1897 | if (get_user(val, p)) |
1897 | return -EFAULT; | 1898 | return -EFAULT; |
1898 | if (val != 1 && val != 2 && val != 4) | 1899 | if (val != 1 && val != 2 && val != 4) |
1899 | return -EINVAL; | 1900 | return -EINVAL; |
1900 | if (file->f_mode & FMODE_READ) | 1901 | if (file->f_mode & FMODE_READ) |
1901 | s->dma_adc.subdivision = val; | 1902 | s->dma_adc.subdivision = val; |
1902 | if (file->f_mode & FMODE_WRITE) | 1903 | if (file->f_mode & FMODE_WRITE) |
1903 | s->dma_dac2.subdivision = val; | 1904 | s->dma_dac2.subdivision = val; |
1904 | return 0; | 1905 | return 0; |
1905 | 1906 | ||
1906 | case SOUND_PCM_READ_RATE: | 1907 | case SOUND_PCM_READ_RATE: |
1907 | return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p); | 1908 | return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p); |
1908 | 1909 | ||
1909 | case SOUND_PCM_READ_CHANNELS: | 1910 | case SOUND_PCM_READ_CHANNELS: |
1910 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p); | 1911 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p); |
1911 | 1912 | ||
1912 | case SOUND_PCM_READ_BITS: | 1913 | case SOUND_PCM_READ_BITS: |
1913 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, p); | 1914 | return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, p); |
1914 | 1915 | ||
1915 | case SOUND_PCM_WRITE_FILTER: | 1916 | case SOUND_PCM_WRITE_FILTER: |
1916 | case SNDCTL_DSP_SETSYNCRO: | 1917 | case SNDCTL_DSP_SETSYNCRO: |
1917 | case SOUND_PCM_READ_FILTER: | 1918 | case SOUND_PCM_READ_FILTER: |
1918 | return -EINVAL; | 1919 | return -EINVAL; |
1919 | 1920 | ||
1920 | } | 1921 | } |
1921 | return mixdev_ioctl(s->codec, cmd, arg); | 1922 | return mixdev_ioctl(s->codec, cmd, arg); |
1922 | } | 1923 | } |
1923 | 1924 | ||
1924 | static int es1371_open(struct inode *inode, struct file *file) | 1925 | static int es1371_open(struct inode *inode, struct file *file) |
1925 | { | 1926 | { |
1926 | int minor = iminor(inode); | 1927 | int minor = iminor(inode); |
1927 | DECLARE_WAITQUEUE(wait, current); | 1928 | DECLARE_WAITQUEUE(wait, current); |
1928 | unsigned long flags; | 1929 | unsigned long flags; |
1929 | struct list_head *list; | 1930 | struct list_head *list; |
1930 | struct es1371_state *s; | 1931 | struct es1371_state *s; |
1931 | 1932 | ||
1932 | for (list = devs.next; ; list = list->next) { | 1933 | for (list = devs.next; ; list = list->next) { |
1933 | if (list == &devs) | 1934 | if (list == &devs) |
1934 | return -ENODEV; | 1935 | return -ENODEV; |
1935 | s = list_entry(list, struct es1371_state, devs); | 1936 | s = list_entry(list, struct es1371_state, devs); |
1936 | if (!((s->dev_audio ^ minor) & ~0xf)) | 1937 | if (!((s->dev_audio ^ minor) & ~0xf)) |
1937 | break; | 1938 | break; |
1938 | } | 1939 | } |
1939 | VALIDATE_STATE(s); | 1940 | VALIDATE_STATE(s); |
1940 | file->private_data = s; | 1941 | file->private_data = s; |
1941 | /* wait for device to become free */ | 1942 | /* wait for device to become free */ |
1942 | mutex_lock(&s->open_mutex); | 1943 | mutex_lock(&s->open_mutex); |
1943 | while (s->open_mode & file->f_mode) { | 1944 | while (s->open_mode & file->f_mode) { |
1944 | if (file->f_flags & O_NONBLOCK) { | 1945 | if (file->f_flags & O_NONBLOCK) { |
1945 | mutex_unlock(&s->open_mutex); | 1946 | mutex_unlock(&s->open_mutex); |
1946 | return -EBUSY; | 1947 | return -EBUSY; |
1947 | } | 1948 | } |
1948 | add_wait_queue(&s->open_wait, &wait); | 1949 | add_wait_queue(&s->open_wait, &wait); |
1949 | __set_current_state(TASK_INTERRUPTIBLE); | 1950 | __set_current_state(TASK_INTERRUPTIBLE); |
1950 | mutex_unlock(&s->open_mutex); | 1951 | mutex_unlock(&s->open_mutex); |
1951 | schedule(); | 1952 | schedule(); |
1952 | remove_wait_queue(&s->open_wait, &wait); | 1953 | remove_wait_queue(&s->open_wait, &wait); |
1953 | set_current_state(TASK_RUNNING); | 1954 | set_current_state(TASK_RUNNING); |
1954 | if (signal_pending(current)) | 1955 | if (signal_pending(current)) |
1955 | return -ERESTARTSYS; | 1956 | return -ERESTARTSYS; |
1956 | mutex_lock(&s->open_mutex); | 1957 | mutex_lock(&s->open_mutex); |
1957 | } | 1958 | } |
1958 | if (file->f_mode & FMODE_READ) { | 1959 | if (file->f_mode & FMODE_READ) { |
1959 | s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; | 1960 | s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; |
1960 | s->dma_adc.enabled = 1; | 1961 | s->dma_adc.enabled = 1; |
1961 | set_adc_rate(s, 8000); | 1962 | set_adc_rate(s, 8000); |
1962 | } | 1963 | } |
1963 | if (file->f_mode & FMODE_WRITE) { | 1964 | if (file->f_mode & FMODE_WRITE) { |
1964 | s->dma_dac2.ossfragshift = s->dma_dac2.ossmaxfrags = s->dma_dac2.subdivision = 0; | 1965 | s->dma_dac2.ossfragshift = s->dma_dac2.ossmaxfrags = s->dma_dac2.subdivision = 0; |
1965 | s->dma_dac2.enabled = 1; | 1966 | s->dma_dac2.enabled = 1; |
1966 | set_dac2_rate(s, 8000); | 1967 | set_dac2_rate(s, 8000); |
1967 | } | 1968 | } |
1968 | spin_lock_irqsave(&s->lock, flags); | 1969 | spin_lock_irqsave(&s->lock, flags); |
1969 | if (file->f_mode & FMODE_READ) { | 1970 | if (file->f_mode & FMODE_READ) { |
1970 | s->sctrl &= ~SCTRL_R1FMT; | 1971 | s->sctrl &= ~SCTRL_R1FMT; |
1971 | if ((minor & 0xf) == SND_DEV_DSP16) | 1972 | if ((minor & 0xf) == SND_DEV_DSP16) |
1972 | s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_R1FMT; | 1973 | s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_R1FMT; |
1973 | else | 1974 | else |
1974 | s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_R1FMT; | 1975 | s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_R1FMT; |
1975 | } | 1976 | } |
1976 | if (file->f_mode & FMODE_WRITE) { | 1977 | if (file->f_mode & FMODE_WRITE) { |
1977 | s->sctrl &= ~SCTRL_P2FMT; | 1978 | s->sctrl &= ~SCTRL_P2FMT; |
1978 | if ((minor & 0xf) == SND_DEV_DSP16) | 1979 | if ((minor & 0xf) == SND_DEV_DSP16) |
1979 | s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_P2FMT; | 1980 | s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_P2FMT; |
1980 | else | 1981 | else |
1981 | s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_P2FMT; | 1982 | s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_P2FMT; |
1982 | } | 1983 | } |
1983 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 1984 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
1984 | spin_unlock_irqrestore(&s->lock, flags); | 1985 | spin_unlock_irqrestore(&s->lock, flags); |
1985 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | 1986 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); |
1986 | mutex_unlock(&s->open_mutex); | 1987 | mutex_unlock(&s->open_mutex); |
1987 | mutex_init(&s->sem); | 1988 | mutex_init(&s->sem); |
1988 | return nonseekable_open(inode, file); | 1989 | return nonseekable_open(inode, file); |
1989 | } | 1990 | } |
1990 | 1991 | ||
1991 | static int es1371_release(struct inode *inode, struct file *file) | 1992 | static int es1371_release(struct inode *inode, struct file *file) |
1992 | { | 1993 | { |
1993 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 1994 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
1994 | 1995 | ||
1995 | VALIDATE_STATE(s); | 1996 | VALIDATE_STATE(s); |
1996 | lock_kernel(); | 1997 | lock_kernel(); |
1997 | if (file->f_mode & FMODE_WRITE) | 1998 | if (file->f_mode & FMODE_WRITE) |
1998 | drain_dac2(s, file->f_flags & O_NONBLOCK); | 1999 | drain_dac2(s, file->f_flags & O_NONBLOCK); |
1999 | mutex_lock(&s->open_mutex); | 2000 | mutex_lock(&s->open_mutex); |
2000 | if (file->f_mode & FMODE_WRITE) { | 2001 | if (file->f_mode & FMODE_WRITE) { |
2001 | stop_dac2(s); | 2002 | stop_dac2(s); |
2002 | dealloc_dmabuf(s, &s->dma_dac2); | 2003 | dealloc_dmabuf(s, &s->dma_dac2); |
2003 | } | 2004 | } |
2004 | if (file->f_mode & FMODE_READ) { | 2005 | if (file->f_mode & FMODE_READ) { |
2005 | stop_adc(s); | 2006 | stop_adc(s); |
2006 | dealloc_dmabuf(s, &s->dma_adc); | 2007 | dealloc_dmabuf(s, &s->dma_adc); |
2007 | } | 2008 | } |
2008 | s->open_mode &= ~(file->f_mode & (FMODE_READ|FMODE_WRITE)); | 2009 | s->open_mode &= ~(file->f_mode & (FMODE_READ|FMODE_WRITE)); |
2009 | mutex_unlock(&s->open_mutex); | 2010 | mutex_unlock(&s->open_mutex); |
2010 | wake_up(&s->open_wait); | 2011 | wake_up(&s->open_wait); |
2011 | unlock_kernel(); | 2012 | unlock_kernel(); |
2012 | return 0; | 2013 | return 0; |
2013 | } | 2014 | } |
2014 | 2015 | ||
2015 | static /*const*/ struct file_operations es1371_audio_fops = { | 2016 | static /*const*/ struct file_operations es1371_audio_fops = { |
2016 | .owner = THIS_MODULE, | 2017 | .owner = THIS_MODULE, |
2017 | .llseek = no_llseek, | 2018 | .llseek = no_llseek, |
2018 | .read = es1371_read, | 2019 | .read = es1371_read, |
2019 | .write = es1371_write, | 2020 | .write = es1371_write, |
2020 | .poll = es1371_poll, | 2021 | .poll = es1371_poll, |
2021 | .ioctl = es1371_ioctl, | 2022 | .ioctl = es1371_ioctl, |
2022 | .mmap = es1371_mmap, | 2023 | .mmap = es1371_mmap, |
2023 | .open = es1371_open, | 2024 | .open = es1371_open, |
2024 | .release = es1371_release, | 2025 | .release = es1371_release, |
2025 | }; | 2026 | }; |
2026 | 2027 | ||
2027 | /* --------------------------------------------------------------------- */ | 2028 | /* --------------------------------------------------------------------- */ |
2028 | 2029 | ||
2029 | static ssize_t es1371_write_dac(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 2030 | static ssize_t es1371_write_dac(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
2030 | { | 2031 | { |
2031 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2032 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2032 | DECLARE_WAITQUEUE(wait, current); | 2033 | DECLARE_WAITQUEUE(wait, current); |
2033 | ssize_t ret = 0; | 2034 | ssize_t ret = 0; |
2034 | unsigned long flags; | 2035 | unsigned long flags; |
2035 | unsigned swptr; | 2036 | unsigned swptr; |
2036 | int cnt; | 2037 | int cnt; |
2037 | 2038 | ||
2038 | VALIDATE_STATE(s); | 2039 | VALIDATE_STATE(s); |
2039 | if (s->dma_dac1.mapped) | 2040 | if (s->dma_dac1.mapped) |
2040 | return -ENXIO; | 2041 | return -ENXIO; |
2041 | if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) | 2042 | if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) |
2042 | return ret; | 2043 | return ret; |
2043 | if (!access_ok(VERIFY_READ, buffer, count)) | 2044 | if (!access_ok(VERIFY_READ, buffer, count)) |
2044 | return -EFAULT; | 2045 | return -EFAULT; |
2045 | add_wait_queue(&s->dma_dac1.wait, &wait); | 2046 | add_wait_queue(&s->dma_dac1.wait, &wait); |
2046 | while (count > 0) { | 2047 | while (count > 0) { |
2047 | spin_lock_irqsave(&s->lock, flags); | 2048 | spin_lock_irqsave(&s->lock, flags); |
2048 | if (s->dma_dac1.count < 0) { | 2049 | if (s->dma_dac1.count < 0) { |
2049 | s->dma_dac1.count = 0; | 2050 | s->dma_dac1.count = 0; |
2050 | s->dma_dac1.swptr = s->dma_dac1.hwptr; | 2051 | s->dma_dac1.swptr = s->dma_dac1.hwptr; |
2051 | } | 2052 | } |
2052 | swptr = s->dma_dac1.swptr; | 2053 | swptr = s->dma_dac1.swptr; |
2053 | cnt = s->dma_dac1.dmasize-swptr; | 2054 | cnt = s->dma_dac1.dmasize-swptr; |
2054 | if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize) | 2055 | if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize) |
2055 | cnt = s->dma_dac1.dmasize - s->dma_dac1.count; | 2056 | cnt = s->dma_dac1.dmasize - s->dma_dac1.count; |
2056 | if (cnt <= 0) | 2057 | if (cnt <= 0) |
2057 | __set_current_state(TASK_INTERRUPTIBLE); | 2058 | __set_current_state(TASK_INTERRUPTIBLE); |
2058 | spin_unlock_irqrestore(&s->lock, flags); | 2059 | spin_unlock_irqrestore(&s->lock, flags); |
2059 | if (cnt > count) | 2060 | if (cnt > count) |
2060 | cnt = count; | 2061 | cnt = count; |
2061 | if (cnt <= 0) { | 2062 | if (cnt <= 0) { |
2062 | if (s->dma_dac1.enabled) | 2063 | if (s->dma_dac1.enabled) |
2063 | start_dac1(s); | 2064 | start_dac1(s); |
2064 | if (file->f_flags & O_NONBLOCK) { | 2065 | if (file->f_flags & O_NONBLOCK) { |
2065 | if (!ret) | 2066 | if (!ret) |
2066 | ret = -EAGAIN; | 2067 | ret = -EAGAIN; |
2067 | break; | 2068 | break; |
2068 | } | 2069 | } |
2069 | schedule(); | 2070 | schedule(); |
2070 | if (signal_pending(current)) { | 2071 | if (signal_pending(current)) { |
2071 | if (!ret) | 2072 | if (!ret) |
2072 | ret = -ERESTARTSYS; | 2073 | ret = -ERESTARTSYS; |
2073 | break; | 2074 | break; |
2074 | } | 2075 | } |
2075 | continue; | 2076 | continue; |
2076 | } | 2077 | } |
2077 | if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) { | 2078 | if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) { |
2078 | if (!ret) | 2079 | if (!ret) |
2079 | ret = -EFAULT; | 2080 | ret = -EFAULT; |
2080 | break; | 2081 | break; |
2081 | } | 2082 | } |
2082 | swptr = (swptr + cnt) % s->dma_dac1.dmasize; | 2083 | swptr = (swptr + cnt) % s->dma_dac1.dmasize; |
2083 | spin_lock_irqsave(&s->lock, flags); | 2084 | spin_lock_irqsave(&s->lock, flags); |
2084 | s->dma_dac1.swptr = swptr; | 2085 | s->dma_dac1.swptr = swptr; |
2085 | s->dma_dac1.count += cnt; | 2086 | s->dma_dac1.count += cnt; |
2086 | s->dma_dac1.endcleared = 0; | 2087 | s->dma_dac1.endcleared = 0; |
2087 | spin_unlock_irqrestore(&s->lock, flags); | 2088 | spin_unlock_irqrestore(&s->lock, flags); |
2088 | count -= cnt; | 2089 | count -= cnt; |
2089 | buffer += cnt; | 2090 | buffer += cnt; |
2090 | ret += cnt; | 2091 | ret += cnt; |
2091 | if (s->dma_dac1.enabled) | 2092 | if (s->dma_dac1.enabled) |
2092 | start_dac1(s); | 2093 | start_dac1(s); |
2093 | } | 2094 | } |
2094 | remove_wait_queue(&s->dma_dac1.wait, &wait); | 2095 | remove_wait_queue(&s->dma_dac1.wait, &wait); |
2095 | set_current_state(TASK_RUNNING); | 2096 | set_current_state(TASK_RUNNING); |
2096 | return ret; | 2097 | return ret; |
2097 | } | 2098 | } |
2098 | 2099 | ||
2099 | /* No kernel lock - we have our own spinlock */ | 2100 | /* No kernel lock - we have our own spinlock */ |
2100 | static unsigned int es1371_poll_dac(struct file *file, struct poll_table_struct *wait) | 2101 | static unsigned int es1371_poll_dac(struct file *file, struct poll_table_struct *wait) |
2101 | { | 2102 | { |
2102 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2103 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2103 | unsigned long flags; | 2104 | unsigned long flags; |
2104 | unsigned int mask = 0; | 2105 | unsigned int mask = 0; |
2105 | 2106 | ||
2106 | VALIDATE_STATE(s); | 2107 | VALIDATE_STATE(s); |
2107 | if (!s->dma_dac1.ready && prog_dmabuf_dac1(s)) | 2108 | if (!s->dma_dac1.ready && prog_dmabuf_dac1(s)) |
2108 | return 0; | 2109 | return 0; |
2109 | poll_wait(file, &s->dma_dac1.wait, wait); | 2110 | poll_wait(file, &s->dma_dac1.wait, wait); |
2110 | spin_lock_irqsave(&s->lock, flags); | 2111 | spin_lock_irqsave(&s->lock, flags); |
2111 | es1371_update_ptr(s); | 2112 | es1371_update_ptr(s); |
2112 | if (s->dma_dac1.mapped) { | 2113 | if (s->dma_dac1.mapped) { |
2113 | if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) | 2114 | if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) |
2114 | mask |= POLLOUT | POLLWRNORM; | 2115 | mask |= POLLOUT | POLLWRNORM; |
2115 | } else { | 2116 | } else { |
2116 | if ((signed)s->dma_dac1.dmasize >= s->dma_dac1.count + (signed)s->dma_dac1.fragsize) | 2117 | if ((signed)s->dma_dac1.dmasize >= s->dma_dac1.count + (signed)s->dma_dac1.fragsize) |
2117 | mask |= POLLOUT | POLLWRNORM; | 2118 | mask |= POLLOUT | POLLWRNORM; |
2118 | } | 2119 | } |
2119 | spin_unlock_irqrestore(&s->lock, flags); | 2120 | spin_unlock_irqrestore(&s->lock, flags); |
2120 | return mask; | 2121 | return mask; |
2121 | } | 2122 | } |
2122 | 2123 | ||
2123 | static int es1371_mmap_dac(struct file *file, struct vm_area_struct *vma) | 2124 | static int es1371_mmap_dac(struct file *file, struct vm_area_struct *vma) |
2124 | { | 2125 | { |
2125 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2126 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2126 | int ret; | 2127 | int ret; |
2127 | unsigned long size; | 2128 | unsigned long size; |
2128 | 2129 | ||
2129 | VALIDATE_STATE(s); | 2130 | VALIDATE_STATE(s); |
2130 | if (!(vma->vm_flags & VM_WRITE)) | 2131 | if (!(vma->vm_flags & VM_WRITE)) |
2131 | return -EINVAL; | 2132 | return -EINVAL; |
2132 | lock_kernel(); | 2133 | lock_kernel(); |
2133 | if ((ret = prog_dmabuf_dac1(s)) != 0) | 2134 | if ((ret = prog_dmabuf_dac1(s)) != 0) |
2134 | goto out; | 2135 | goto out; |
2135 | ret = -EINVAL; | 2136 | ret = -EINVAL; |
2136 | if (vma->vm_pgoff != 0) | 2137 | if (vma->vm_pgoff != 0) |
2137 | goto out; | 2138 | goto out; |
2138 | size = vma->vm_end - vma->vm_start; | 2139 | size = vma->vm_end - vma->vm_start; |
2139 | if (size > (PAGE_SIZE << s->dma_dac1.buforder)) | 2140 | if (size > (PAGE_SIZE << s->dma_dac1.buforder)) |
2140 | goto out; | 2141 | goto out; |
2141 | ret = -EAGAIN; | 2142 | ret = -EAGAIN; |
2142 | if (remap_pfn_range(vma, vma->vm_start, | 2143 | if (remap_pfn_range(vma, vma->vm_start, |
2143 | virt_to_phys(s->dma_dac1.rawbuf) >> PAGE_SHIFT, | 2144 | virt_to_phys(s->dma_dac1.rawbuf) >> PAGE_SHIFT, |
2144 | size, vma->vm_page_prot)) | 2145 | size, vma->vm_page_prot)) |
2145 | goto out; | 2146 | goto out; |
2146 | s->dma_dac1.mapped = 1; | 2147 | s->dma_dac1.mapped = 1; |
2147 | ret = 0; | 2148 | ret = 0; |
2148 | out: | 2149 | out: |
2149 | unlock_kernel(); | 2150 | unlock_kernel(); |
2150 | return ret; | 2151 | return ret; |
2151 | } | 2152 | } |
2152 | 2153 | ||
2153 | static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 2154 | static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
2154 | { | 2155 | { |
2155 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2156 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2156 | unsigned long flags; | 2157 | unsigned long flags; |
2157 | audio_buf_info abinfo; | 2158 | audio_buf_info abinfo; |
2158 | count_info cinfo; | 2159 | count_info cinfo; |
2159 | int count; | 2160 | int count; |
2160 | int val, ret; | 2161 | int val, ret; |
2161 | int __user *p = (int __user *)arg; | 2162 | int __user *p = (int __user *)arg; |
2162 | 2163 | ||
2163 | VALIDATE_STATE(s); | 2164 | VALIDATE_STATE(s); |
2164 | switch (cmd) { | 2165 | switch (cmd) { |
2165 | case OSS_GETVERSION: | 2166 | case OSS_GETVERSION: |
2166 | return put_user(SOUND_VERSION, p); | 2167 | return put_user(SOUND_VERSION, p); |
2167 | 2168 | ||
2168 | case SNDCTL_DSP_SYNC: | 2169 | case SNDCTL_DSP_SYNC: |
2169 | return drain_dac1(s, 0/*file->f_flags & O_NONBLOCK*/); | 2170 | return drain_dac1(s, 0/*file->f_flags & O_NONBLOCK*/); |
2170 | 2171 | ||
2171 | case SNDCTL_DSP_SETDUPLEX: | 2172 | case SNDCTL_DSP_SETDUPLEX: |
2172 | return -EINVAL; | 2173 | return -EINVAL; |
2173 | 2174 | ||
2174 | case SNDCTL_DSP_GETCAPS: | 2175 | case SNDCTL_DSP_GETCAPS: |
2175 | return put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p); | 2176 | return put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p); |
2176 | 2177 | ||
2177 | case SNDCTL_DSP_RESET: | 2178 | case SNDCTL_DSP_RESET: |
2178 | stop_dac1(s); | 2179 | stop_dac1(s); |
2179 | synchronize_irq(s->irq); | 2180 | synchronize_irq(s->irq); |
2180 | s->dma_dac1.swptr = s->dma_dac1.hwptr = s->dma_dac1.count = s->dma_dac1.total_bytes = 0; | 2181 | s->dma_dac1.swptr = s->dma_dac1.hwptr = s->dma_dac1.count = s->dma_dac1.total_bytes = 0; |
2181 | return 0; | 2182 | return 0; |
2182 | 2183 | ||
2183 | case SNDCTL_DSP_SPEED: | 2184 | case SNDCTL_DSP_SPEED: |
2184 | if (get_user(val, p)) | 2185 | if (get_user(val, p)) |
2185 | return -EFAULT; | 2186 | return -EFAULT; |
2186 | if (val >= 0) { | 2187 | if (val >= 0) { |
2187 | stop_dac1(s); | 2188 | stop_dac1(s); |
2188 | s->dma_dac1.ready = 0; | 2189 | s->dma_dac1.ready = 0; |
2189 | set_dac1_rate(s, val); | 2190 | set_dac1_rate(s, val); |
2190 | } | 2191 | } |
2191 | return put_user(s->dac1rate, p); | 2192 | return put_user(s->dac1rate, p); |
2192 | 2193 | ||
2193 | case SNDCTL_DSP_STEREO: | 2194 | case SNDCTL_DSP_STEREO: |
2194 | if (get_user(val, p)) | 2195 | if (get_user(val, p)) |
2195 | return -EFAULT; | 2196 | return -EFAULT; |
2196 | stop_dac1(s); | 2197 | stop_dac1(s); |
2197 | s->dma_dac1.ready = 0; | 2198 | s->dma_dac1.ready = 0; |
2198 | spin_lock_irqsave(&s->lock, flags); | 2199 | spin_lock_irqsave(&s->lock, flags); |
2199 | if (val) | 2200 | if (val) |
2200 | s->sctrl |= SCTRL_P1SMB; | 2201 | s->sctrl |= SCTRL_P1SMB; |
2201 | else | 2202 | else |
2202 | s->sctrl &= ~SCTRL_P1SMB; | 2203 | s->sctrl &= ~SCTRL_P1SMB; |
2203 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 2204 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
2204 | spin_unlock_irqrestore(&s->lock, flags); | 2205 | spin_unlock_irqrestore(&s->lock, flags); |
2205 | return 0; | 2206 | return 0; |
2206 | 2207 | ||
2207 | case SNDCTL_DSP_CHANNELS: | 2208 | case SNDCTL_DSP_CHANNELS: |
2208 | if (get_user(val, p)) | 2209 | if (get_user(val, p)) |
2209 | return -EFAULT; | 2210 | return -EFAULT; |
2210 | if (val != 0) { | 2211 | if (val != 0) { |
2211 | stop_dac1(s); | 2212 | stop_dac1(s); |
2212 | s->dma_dac1.ready = 0; | 2213 | s->dma_dac1.ready = 0; |
2213 | spin_lock_irqsave(&s->lock, flags); | 2214 | spin_lock_irqsave(&s->lock, flags); |
2214 | if (val >= 2) | 2215 | if (val >= 2) |
2215 | s->sctrl |= SCTRL_P1SMB; | 2216 | s->sctrl |= SCTRL_P1SMB; |
2216 | else | 2217 | else |
2217 | s->sctrl &= ~SCTRL_P1SMB; | 2218 | s->sctrl &= ~SCTRL_P1SMB; |
2218 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 2219 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
2219 | spin_unlock_irqrestore(&s->lock, flags); | 2220 | spin_unlock_irqrestore(&s->lock, flags); |
2220 | } | 2221 | } |
2221 | return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p); | 2222 | return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p); |
2222 | 2223 | ||
2223 | case SNDCTL_DSP_GETFMTS: /* Returns a mask */ | 2224 | case SNDCTL_DSP_GETFMTS: /* Returns a mask */ |
2224 | return put_user(AFMT_S16_LE|AFMT_U8, p); | 2225 | return put_user(AFMT_S16_LE|AFMT_U8, p); |
2225 | 2226 | ||
2226 | case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ | 2227 | case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ |
2227 | if (get_user(val, p)) | 2228 | if (get_user(val, p)) |
2228 | return -EFAULT; | 2229 | return -EFAULT; |
2229 | if (val != AFMT_QUERY) { | 2230 | if (val != AFMT_QUERY) { |
2230 | stop_dac1(s); | 2231 | stop_dac1(s); |
2231 | s->dma_dac1.ready = 0; | 2232 | s->dma_dac1.ready = 0; |
2232 | spin_lock_irqsave(&s->lock, flags); | 2233 | spin_lock_irqsave(&s->lock, flags); |
2233 | if (val == AFMT_S16_LE) | 2234 | if (val == AFMT_S16_LE) |
2234 | s->sctrl |= SCTRL_P1SEB; | 2235 | s->sctrl |= SCTRL_P1SEB; |
2235 | else | 2236 | else |
2236 | s->sctrl &= ~SCTRL_P1SEB; | 2237 | s->sctrl &= ~SCTRL_P1SEB; |
2237 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 2238 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
2238 | spin_unlock_irqrestore(&s->lock, flags); | 2239 | spin_unlock_irqrestore(&s->lock, flags); |
2239 | } | 2240 | } |
2240 | return put_user((s->sctrl & SCTRL_P1SEB) ? AFMT_S16_LE : AFMT_U8, p); | 2241 | return put_user((s->sctrl & SCTRL_P1SEB) ? AFMT_S16_LE : AFMT_U8, p); |
2241 | 2242 | ||
2242 | case SNDCTL_DSP_POST: | 2243 | case SNDCTL_DSP_POST: |
2243 | return 0; | 2244 | return 0; |
2244 | 2245 | ||
2245 | case SNDCTL_DSP_GETTRIGGER: | 2246 | case SNDCTL_DSP_GETTRIGGER: |
2246 | return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, p); | 2247 | return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, p); |
2247 | 2248 | ||
2248 | case SNDCTL_DSP_SETTRIGGER: | 2249 | case SNDCTL_DSP_SETTRIGGER: |
2249 | if (get_user(val, p)) | 2250 | if (get_user(val, p)) |
2250 | return -EFAULT; | 2251 | return -EFAULT; |
2251 | if (val & PCM_ENABLE_OUTPUT) { | 2252 | if (val & PCM_ENABLE_OUTPUT) { |
2252 | if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) | 2253 | if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) |
2253 | return ret; | 2254 | return ret; |
2254 | s->dma_dac1.enabled = 1; | 2255 | s->dma_dac1.enabled = 1; |
2255 | start_dac1(s); | 2256 | start_dac1(s); |
2256 | } else { | 2257 | } else { |
2257 | s->dma_dac1.enabled = 0; | 2258 | s->dma_dac1.enabled = 0; |
2258 | stop_dac1(s); | 2259 | stop_dac1(s); |
2259 | } | 2260 | } |
2260 | return 0; | 2261 | return 0; |
2261 | 2262 | ||
2262 | case SNDCTL_DSP_GETOSPACE: | 2263 | case SNDCTL_DSP_GETOSPACE: |
2263 | if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) | 2264 | if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) |
2264 | return val; | 2265 | return val; |
2265 | spin_lock_irqsave(&s->lock, flags); | 2266 | spin_lock_irqsave(&s->lock, flags); |
2266 | es1371_update_ptr(s); | 2267 | es1371_update_ptr(s); |
2267 | abinfo.fragsize = s->dma_dac1.fragsize; | 2268 | abinfo.fragsize = s->dma_dac1.fragsize; |
2268 | count = s->dma_dac1.count; | 2269 | count = s->dma_dac1.count; |
2269 | if (count < 0) | 2270 | if (count < 0) |
2270 | count = 0; | 2271 | count = 0; |
2271 | abinfo.bytes = s->dma_dac1.dmasize - count; | 2272 | abinfo.bytes = s->dma_dac1.dmasize - count; |
2272 | abinfo.fragstotal = s->dma_dac1.numfrag; | 2273 | abinfo.fragstotal = s->dma_dac1.numfrag; |
2273 | abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift; | 2274 | abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift; |
2274 | spin_unlock_irqrestore(&s->lock, flags); | 2275 | spin_unlock_irqrestore(&s->lock, flags); |
2275 | return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 2276 | return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; |
2276 | 2277 | ||
2277 | case SNDCTL_DSP_NONBLOCK: | 2278 | case SNDCTL_DSP_NONBLOCK: |
2278 | file->f_flags |= O_NONBLOCK; | 2279 | file->f_flags |= O_NONBLOCK; |
2279 | return 0; | 2280 | return 0; |
2280 | 2281 | ||
2281 | case SNDCTL_DSP_GETODELAY: | 2282 | case SNDCTL_DSP_GETODELAY: |
2282 | if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) | 2283 | if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) |
2283 | return val; | 2284 | return val; |
2284 | spin_lock_irqsave(&s->lock, flags); | 2285 | spin_lock_irqsave(&s->lock, flags); |
2285 | es1371_update_ptr(s); | 2286 | es1371_update_ptr(s); |
2286 | count = s->dma_dac1.count; | 2287 | count = s->dma_dac1.count; |
2287 | spin_unlock_irqrestore(&s->lock, flags); | 2288 | spin_unlock_irqrestore(&s->lock, flags); |
2288 | if (count < 0) | 2289 | if (count < 0) |
2289 | count = 0; | 2290 | count = 0; |
2290 | return put_user(count, p); | 2291 | return put_user(count, p); |
2291 | 2292 | ||
2292 | case SNDCTL_DSP_GETOPTR: | 2293 | case SNDCTL_DSP_GETOPTR: |
2293 | if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) | 2294 | if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) |
2294 | return val; | 2295 | return val; |
2295 | spin_lock_irqsave(&s->lock, flags); | 2296 | spin_lock_irqsave(&s->lock, flags); |
2296 | es1371_update_ptr(s); | 2297 | es1371_update_ptr(s); |
2297 | cinfo.bytes = s->dma_dac1.total_bytes; | 2298 | cinfo.bytes = s->dma_dac1.total_bytes; |
2298 | count = s->dma_dac1.count; | 2299 | count = s->dma_dac1.count; |
2299 | if (count < 0) | 2300 | if (count < 0) |
2300 | count = 0; | 2301 | count = 0; |
2301 | cinfo.blocks = count >> s->dma_dac1.fragshift; | 2302 | cinfo.blocks = count >> s->dma_dac1.fragshift; |
2302 | cinfo.ptr = s->dma_dac1.hwptr; | 2303 | cinfo.ptr = s->dma_dac1.hwptr; |
2303 | if (s->dma_dac1.mapped) | 2304 | if (s->dma_dac1.mapped) |
2304 | s->dma_dac1.count &= s->dma_dac1.fragsize-1; | 2305 | s->dma_dac1.count &= s->dma_dac1.fragsize-1; |
2305 | spin_unlock_irqrestore(&s->lock, flags); | 2306 | spin_unlock_irqrestore(&s->lock, flags); |
2306 | if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo))) | 2307 | if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo))) |
2307 | return -EFAULT; | 2308 | return -EFAULT; |
2308 | return 0; | 2309 | return 0; |
2309 | 2310 | ||
2310 | case SNDCTL_DSP_GETBLKSIZE: | 2311 | case SNDCTL_DSP_GETBLKSIZE: |
2311 | if ((val = prog_dmabuf_dac1(s))) | 2312 | if ((val = prog_dmabuf_dac1(s))) |
2312 | return val; | 2313 | return val; |
2313 | return put_user(s->dma_dac1.fragsize, p); | 2314 | return put_user(s->dma_dac1.fragsize, p); |
2314 | 2315 | ||
2315 | case SNDCTL_DSP_SETFRAGMENT: | 2316 | case SNDCTL_DSP_SETFRAGMENT: |
2316 | if (get_user(val, p)) | 2317 | if (get_user(val, p)) |
2317 | return -EFAULT; | 2318 | return -EFAULT; |
2318 | s->dma_dac1.ossfragshift = val & 0xffff; | 2319 | s->dma_dac1.ossfragshift = val & 0xffff; |
2319 | s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff; | 2320 | s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff; |
2320 | if (s->dma_dac1.ossfragshift < 4) | 2321 | if (s->dma_dac1.ossfragshift < 4) |
2321 | s->dma_dac1.ossfragshift = 4; | 2322 | s->dma_dac1.ossfragshift = 4; |
2322 | if (s->dma_dac1.ossfragshift > 15) | 2323 | if (s->dma_dac1.ossfragshift > 15) |
2323 | s->dma_dac1.ossfragshift = 15; | 2324 | s->dma_dac1.ossfragshift = 15; |
2324 | if (s->dma_dac1.ossmaxfrags < 4) | 2325 | if (s->dma_dac1.ossmaxfrags < 4) |
2325 | s->dma_dac1.ossmaxfrags = 4; | 2326 | s->dma_dac1.ossmaxfrags = 4; |
2326 | return 0; | 2327 | return 0; |
2327 | 2328 | ||
2328 | case SNDCTL_DSP_SUBDIVIDE: | 2329 | case SNDCTL_DSP_SUBDIVIDE: |
2329 | if (s->dma_dac1.subdivision) | 2330 | if (s->dma_dac1.subdivision) |
2330 | return -EINVAL; | 2331 | return -EINVAL; |
2331 | if (get_user(val, p)) | 2332 | if (get_user(val, p)) |
2332 | return -EFAULT; | 2333 | return -EFAULT; |
2333 | if (val != 1 && val != 2 && val != 4) | 2334 | if (val != 1 && val != 2 && val != 4) |
2334 | return -EINVAL; | 2335 | return -EINVAL; |
2335 | s->dma_dac1.subdivision = val; | 2336 | s->dma_dac1.subdivision = val; |
2336 | return 0; | 2337 | return 0; |
2337 | 2338 | ||
2338 | case SOUND_PCM_READ_RATE: | 2339 | case SOUND_PCM_READ_RATE: |
2339 | return put_user(s->dac1rate, p); | 2340 | return put_user(s->dac1rate, p); |
2340 | 2341 | ||
2341 | case SOUND_PCM_READ_CHANNELS: | 2342 | case SOUND_PCM_READ_CHANNELS: |
2342 | return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p); | 2343 | return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p); |
2343 | 2344 | ||
2344 | case SOUND_PCM_READ_BITS: | 2345 | case SOUND_PCM_READ_BITS: |
2345 | return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, p); | 2346 | return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, p); |
2346 | 2347 | ||
2347 | case SOUND_PCM_WRITE_FILTER: | 2348 | case SOUND_PCM_WRITE_FILTER: |
2348 | case SNDCTL_DSP_SETSYNCRO: | 2349 | case SNDCTL_DSP_SETSYNCRO: |
2349 | case SOUND_PCM_READ_FILTER: | 2350 | case SOUND_PCM_READ_FILTER: |
2350 | return -EINVAL; | 2351 | return -EINVAL; |
2351 | 2352 | ||
2352 | } | 2353 | } |
2353 | return mixdev_ioctl(s->codec, cmd, arg); | 2354 | return mixdev_ioctl(s->codec, cmd, arg); |
2354 | } | 2355 | } |
2355 | 2356 | ||
2356 | static int es1371_open_dac(struct inode *inode, struct file *file) | 2357 | static int es1371_open_dac(struct inode *inode, struct file *file) |
2357 | { | 2358 | { |
2358 | int minor = iminor(inode); | 2359 | int minor = iminor(inode); |
2359 | DECLARE_WAITQUEUE(wait, current); | 2360 | DECLARE_WAITQUEUE(wait, current); |
2360 | unsigned long flags; | 2361 | unsigned long flags; |
2361 | struct list_head *list; | 2362 | struct list_head *list; |
2362 | struct es1371_state *s; | 2363 | struct es1371_state *s; |
2363 | 2364 | ||
2364 | for (list = devs.next; ; list = list->next) { | 2365 | for (list = devs.next; ; list = list->next) { |
2365 | if (list == &devs) | 2366 | if (list == &devs) |
2366 | return -ENODEV; | 2367 | return -ENODEV; |
2367 | s = list_entry(list, struct es1371_state, devs); | 2368 | s = list_entry(list, struct es1371_state, devs); |
2368 | if (!((s->dev_dac ^ minor) & ~0xf)) | 2369 | if (!((s->dev_dac ^ minor) & ~0xf)) |
2369 | break; | 2370 | break; |
2370 | } | 2371 | } |
2371 | VALIDATE_STATE(s); | 2372 | VALIDATE_STATE(s); |
2372 | /* we allow opening with O_RDWR, most programs do it although they will only write */ | 2373 | /* we allow opening with O_RDWR, most programs do it although they will only write */ |
2373 | #if 0 | 2374 | #if 0 |
2374 | if (file->f_mode & FMODE_READ) | 2375 | if (file->f_mode & FMODE_READ) |
2375 | return -EPERM; | 2376 | return -EPERM; |
2376 | #endif | 2377 | #endif |
2377 | if (!(file->f_mode & FMODE_WRITE)) | 2378 | if (!(file->f_mode & FMODE_WRITE)) |
2378 | return -EINVAL; | 2379 | return -EINVAL; |
2379 | file->private_data = s; | 2380 | file->private_data = s; |
2380 | /* wait for device to become free */ | 2381 | /* wait for device to become free */ |
2381 | mutex_lock(&s->open_mutex); | 2382 | mutex_lock(&s->open_mutex); |
2382 | while (s->open_mode & FMODE_DAC) { | 2383 | while (s->open_mode & FMODE_DAC) { |
2383 | if (file->f_flags & O_NONBLOCK) { | 2384 | if (file->f_flags & O_NONBLOCK) { |
2384 | mutex_unlock(&s->open_mutex); | 2385 | mutex_unlock(&s->open_mutex); |
2385 | return -EBUSY; | 2386 | return -EBUSY; |
2386 | } | 2387 | } |
2387 | add_wait_queue(&s->open_wait, &wait); | 2388 | add_wait_queue(&s->open_wait, &wait); |
2388 | __set_current_state(TASK_INTERRUPTIBLE); | 2389 | __set_current_state(TASK_INTERRUPTIBLE); |
2389 | mutex_unlock(&s->open_mutex); | 2390 | mutex_unlock(&s->open_mutex); |
2390 | schedule(); | 2391 | schedule(); |
2391 | remove_wait_queue(&s->open_wait, &wait); | 2392 | remove_wait_queue(&s->open_wait, &wait); |
2392 | set_current_state(TASK_RUNNING); | 2393 | set_current_state(TASK_RUNNING); |
2393 | if (signal_pending(current)) | 2394 | if (signal_pending(current)) |
2394 | return -ERESTARTSYS; | 2395 | return -ERESTARTSYS; |
2395 | mutex_lock(&s->open_mutex); | 2396 | mutex_lock(&s->open_mutex); |
2396 | } | 2397 | } |
2397 | s->dma_dac1.ossfragshift = s->dma_dac1.ossmaxfrags = s->dma_dac1.subdivision = 0; | 2398 | s->dma_dac1.ossfragshift = s->dma_dac1.ossmaxfrags = s->dma_dac1.subdivision = 0; |
2398 | s->dma_dac1.enabled = 1; | 2399 | s->dma_dac1.enabled = 1; |
2399 | set_dac1_rate(s, 8000); | 2400 | set_dac1_rate(s, 8000); |
2400 | spin_lock_irqsave(&s->lock, flags); | 2401 | spin_lock_irqsave(&s->lock, flags); |
2401 | s->sctrl &= ~SCTRL_P1FMT; | 2402 | s->sctrl &= ~SCTRL_P1FMT; |
2402 | if ((minor & 0xf) == SND_DEV_DSP16) | 2403 | if ((minor & 0xf) == SND_DEV_DSP16) |
2403 | s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_P1FMT; | 2404 | s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_P1FMT; |
2404 | else | 2405 | else |
2405 | s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_P1FMT; | 2406 | s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_P1FMT; |
2406 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 2407 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
2407 | spin_unlock_irqrestore(&s->lock, flags); | 2408 | spin_unlock_irqrestore(&s->lock, flags); |
2408 | s->open_mode |= FMODE_DAC; | 2409 | s->open_mode |= FMODE_DAC; |
2409 | mutex_unlock(&s->open_mutex); | 2410 | mutex_unlock(&s->open_mutex); |
2410 | return nonseekable_open(inode, file); | 2411 | return nonseekable_open(inode, file); |
2411 | } | 2412 | } |
2412 | 2413 | ||
2413 | static int es1371_release_dac(struct inode *inode, struct file *file) | 2414 | static int es1371_release_dac(struct inode *inode, struct file *file) |
2414 | { | 2415 | { |
2415 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2416 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2416 | 2417 | ||
2417 | VALIDATE_STATE(s); | 2418 | VALIDATE_STATE(s); |
2418 | lock_kernel(); | 2419 | lock_kernel(); |
2419 | drain_dac1(s, file->f_flags & O_NONBLOCK); | 2420 | drain_dac1(s, file->f_flags & O_NONBLOCK); |
2420 | mutex_lock(&s->open_mutex); | 2421 | mutex_lock(&s->open_mutex); |
2421 | stop_dac1(s); | 2422 | stop_dac1(s); |
2422 | dealloc_dmabuf(s, &s->dma_dac1); | 2423 | dealloc_dmabuf(s, &s->dma_dac1); |
2423 | s->open_mode &= ~FMODE_DAC; | 2424 | s->open_mode &= ~FMODE_DAC; |
2424 | mutex_unlock(&s->open_mutex); | 2425 | mutex_unlock(&s->open_mutex); |
2425 | wake_up(&s->open_wait); | 2426 | wake_up(&s->open_wait); |
2426 | unlock_kernel(); | 2427 | unlock_kernel(); |
2427 | return 0; | 2428 | return 0; |
2428 | } | 2429 | } |
2429 | 2430 | ||
2430 | static /*const*/ struct file_operations es1371_dac_fops = { | 2431 | static /*const*/ struct file_operations es1371_dac_fops = { |
2431 | .owner = THIS_MODULE, | 2432 | .owner = THIS_MODULE, |
2432 | .llseek = no_llseek, | 2433 | .llseek = no_llseek, |
2433 | .write = es1371_write_dac, | 2434 | .write = es1371_write_dac, |
2434 | .poll = es1371_poll_dac, | 2435 | .poll = es1371_poll_dac, |
2435 | .ioctl = es1371_ioctl_dac, | 2436 | .ioctl = es1371_ioctl_dac, |
2436 | .mmap = es1371_mmap_dac, | 2437 | .mmap = es1371_mmap_dac, |
2437 | .open = es1371_open_dac, | 2438 | .open = es1371_open_dac, |
2438 | .release = es1371_release_dac, | 2439 | .release = es1371_release_dac, |
2439 | }; | 2440 | }; |
2440 | 2441 | ||
2441 | /* --------------------------------------------------------------------- */ | 2442 | /* --------------------------------------------------------------------- */ |
2442 | 2443 | ||
2443 | static ssize_t es1371_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 2444 | static ssize_t es1371_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
2444 | { | 2445 | { |
2445 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2446 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2446 | DECLARE_WAITQUEUE(wait, current); | 2447 | DECLARE_WAITQUEUE(wait, current); |
2447 | ssize_t ret; | 2448 | ssize_t ret; |
2448 | unsigned long flags; | 2449 | unsigned long flags; |
2449 | unsigned ptr; | 2450 | unsigned ptr; |
2450 | int cnt; | 2451 | int cnt; |
2451 | 2452 | ||
2452 | VALIDATE_STATE(s); | 2453 | VALIDATE_STATE(s); |
2453 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 2454 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
2454 | return -EFAULT; | 2455 | return -EFAULT; |
2455 | if (count == 0) | 2456 | if (count == 0) |
2456 | return 0; | 2457 | return 0; |
2457 | ret = 0; | 2458 | ret = 0; |
2458 | add_wait_queue(&s->midi.iwait, &wait); | 2459 | add_wait_queue(&s->midi.iwait, &wait); |
2459 | while (count > 0) { | 2460 | while (count > 0) { |
2460 | spin_lock_irqsave(&s->lock, flags); | 2461 | spin_lock_irqsave(&s->lock, flags); |
2461 | ptr = s->midi.ird; | 2462 | ptr = s->midi.ird; |
2462 | cnt = MIDIINBUF - ptr; | 2463 | cnt = MIDIINBUF - ptr; |
2463 | if (s->midi.icnt < cnt) | 2464 | if (s->midi.icnt < cnt) |
2464 | cnt = s->midi.icnt; | 2465 | cnt = s->midi.icnt; |
2465 | if (cnt <= 0) | 2466 | if (cnt <= 0) |
2466 | __set_current_state(TASK_INTERRUPTIBLE); | 2467 | __set_current_state(TASK_INTERRUPTIBLE); |
2467 | spin_unlock_irqrestore(&s->lock, flags); | 2468 | spin_unlock_irqrestore(&s->lock, flags); |
2468 | if (cnt > count) | 2469 | if (cnt > count) |
2469 | cnt = count; | 2470 | cnt = count; |
2470 | if (cnt <= 0) { | 2471 | if (cnt <= 0) { |
2471 | if (file->f_flags & O_NONBLOCK) { | 2472 | if (file->f_flags & O_NONBLOCK) { |
2472 | if (!ret) | 2473 | if (!ret) |
2473 | ret = -EAGAIN; | 2474 | ret = -EAGAIN; |
2474 | break; | 2475 | break; |
2475 | } | 2476 | } |
2476 | schedule(); | 2477 | schedule(); |
2477 | if (signal_pending(current)) { | 2478 | if (signal_pending(current)) { |
2478 | if (!ret) | 2479 | if (!ret) |
2479 | ret = -ERESTARTSYS; | 2480 | ret = -ERESTARTSYS; |
2480 | break; | 2481 | break; |
2481 | } | 2482 | } |
2482 | continue; | 2483 | continue; |
2483 | } | 2484 | } |
2484 | if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) { | 2485 | if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) { |
2485 | if (!ret) | 2486 | if (!ret) |
2486 | ret = -EFAULT; | 2487 | ret = -EFAULT; |
2487 | break; | 2488 | break; |
2488 | } | 2489 | } |
2489 | ptr = (ptr + cnt) % MIDIINBUF; | 2490 | ptr = (ptr + cnt) % MIDIINBUF; |
2490 | spin_lock_irqsave(&s->lock, flags); | 2491 | spin_lock_irqsave(&s->lock, flags); |
2491 | s->midi.ird = ptr; | 2492 | s->midi.ird = ptr; |
2492 | s->midi.icnt -= cnt; | 2493 | s->midi.icnt -= cnt; |
2493 | spin_unlock_irqrestore(&s->lock, flags); | 2494 | spin_unlock_irqrestore(&s->lock, flags); |
2494 | count -= cnt; | 2495 | count -= cnt; |
2495 | buffer += cnt; | 2496 | buffer += cnt; |
2496 | ret += cnt; | 2497 | ret += cnt; |
2497 | break; | 2498 | break; |
2498 | } | 2499 | } |
2499 | __set_current_state(TASK_RUNNING); | 2500 | __set_current_state(TASK_RUNNING); |
2500 | remove_wait_queue(&s->midi.iwait, &wait); | 2501 | remove_wait_queue(&s->midi.iwait, &wait); |
2501 | return ret; | 2502 | return ret; |
2502 | } | 2503 | } |
2503 | 2504 | ||
2504 | static ssize_t es1371_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 2505 | static ssize_t es1371_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
2505 | { | 2506 | { |
2506 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2507 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2507 | DECLARE_WAITQUEUE(wait, current); | 2508 | DECLARE_WAITQUEUE(wait, current); |
2508 | ssize_t ret; | 2509 | ssize_t ret; |
2509 | unsigned long flags; | 2510 | unsigned long flags; |
2510 | unsigned ptr; | 2511 | unsigned ptr; |
2511 | int cnt; | 2512 | int cnt; |
2512 | 2513 | ||
2513 | VALIDATE_STATE(s); | 2514 | VALIDATE_STATE(s); |
2514 | if (!access_ok(VERIFY_READ, buffer, count)) | 2515 | if (!access_ok(VERIFY_READ, buffer, count)) |
2515 | return -EFAULT; | 2516 | return -EFAULT; |
2516 | if (count == 0) | 2517 | if (count == 0) |
2517 | return 0; | 2518 | return 0; |
2518 | ret = 0; | 2519 | ret = 0; |
2519 | add_wait_queue(&s->midi.owait, &wait); | 2520 | add_wait_queue(&s->midi.owait, &wait); |
2520 | while (count > 0) { | 2521 | while (count > 0) { |
2521 | spin_lock_irqsave(&s->lock, flags); | 2522 | spin_lock_irqsave(&s->lock, flags); |
2522 | ptr = s->midi.owr; | 2523 | ptr = s->midi.owr; |
2523 | cnt = MIDIOUTBUF - ptr; | 2524 | cnt = MIDIOUTBUF - ptr; |
2524 | if (s->midi.ocnt + cnt > MIDIOUTBUF) | 2525 | if (s->midi.ocnt + cnt > MIDIOUTBUF) |
2525 | cnt = MIDIOUTBUF - s->midi.ocnt; | 2526 | cnt = MIDIOUTBUF - s->midi.ocnt; |
2526 | if (cnt <= 0) { | 2527 | if (cnt <= 0) { |
2527 | __set_current_state(TASK_INTERRUPTIBLE); | 2528 | __set_current_state(TASK_INTERRUPTIBLE); |
2528 | es1371_handle_midi(s); | 2529 | es1371_handle_midi(s); |
2529 | } | 2530 | } |
2530 | spin_unlock_irqrestore(&s->lock, flags); | 2531 | spin_unlock_irqrestore(&s->lock, flags); |
2531 | if (cnt > count) | 2532 | if (cnt > count) |
2532 | cnt = count; | 2533 | cnt = count; |
2533 | if (cnt <= 0) { | 2534 | if (cnt <= 0) { |
2534 | if (file->f_flags & O_NONBLOCK) { | 2535 | if (file->f_flags & O_NONBLOCK) { |
2535 | if (!ret) | 2536 | if (!ret) |
2536 | ret = -EAGAIN; | 2537 | ret = -EAGAIN; |
2537 | break; | 2538 | break; |
2538 | } | 2539 | } |
2539 | schedule(); | 2540 | schedule(); |
2540 | if (signal_pending(current)) { | 2541 | if (signal_pending(current)) { |
2541 | if (!ret) | 2542 | if (!ret) |
2542 | ret = -ERESTARTSYS; | 2543 | ret = -ERESTARTSYS; |
2543 | break; | 2544 | break; |
2544 | } | 2545 | } |
2545 | continue; | 2546 | continue; |
2546 | } | 2547 | } |
2547 | if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) { | 2548 | if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) { |
2548 | if (!ret) | 2549 | if (!ret) |
2549 | ret = -EFAULT; | 2550 | ret = -EFAULT; |
2550 | break; | 2551 | break; |
2551 | } | 2552 | } |
2552 | ptr = (ptr + cnt) % MIDIOUTBUF; | 2553 | ptr = (ptr + cnt) % MIDIOUTBUF; |
2553 | spin_lock_irqsave(&s->lock, flags); | 2554 | spin_lock_irqsave(&s->lock, flags); |
2554 | s->midi.owr = ptr; | 2555 | s->midi.owr = ptr; |
2555 | s->midi.ocnt += cnt; | 2556 | s->midi.ocnt += cnt; |
2556 | spin_unlock_irqrestore(&s->lock, flags); | 2557 | spin_unlock_irqrestore(&s->lock, flags); |
2557 | count -= cnt; | 2558 | count -= cnt; |
2558 | buffer += cnt; | 2559 | buffer += cnt; |
2559 | ret += cnt; | 2560 | ret += cnt; |
2560 | spin_lock_irqsave(&s->lock, flags); | 2561 | spin_lock_irqsave(&s->lock, flags); |
2561 | es1371_handle_midi(s); | 2562 | es1371_handle_midi(s); |
2562 | spin_unlock_irqrestore(&s->lock, flags); | 2563 | spin_unlock_irqrestore(&s->lock, flags); |
2563 | } | 2564 | } |
2564 | __set_current_state(TASK_RUNNING); | 2565 | __set_current_state(TASK_RUNNING); |
2565 | remove_wait_queue(&s->midi.owait, &wait); | 2566 | remove_wait_queue(&s->midi.owait, &wait); |
2566 | return ret; | 2567 | return ret; |
2567 | } | 2568 | } |
2568 | 2569 | ||
2569 | /* No kernel lock - we have our own spinlock */ | 2570 | /* No kernel lock - we have our own spinlock */ |
2570 | static unsigned int es1371_midi_poll(struct file *file, struct poll_table_struct *wait) | 2571 | static unsigned int es1371_midi_poll(struct file *file, struct poll_table_struct *wait) |
2571 | { | 2572 | { |
2572 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2573 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2573 | unsigned long flags; | 2574 | unsigned long flags; |
2574 | unsigned int mask = 0; | 2575 | unsigned int mask = 0; |
2575 | 2576 | ||
2576 | VALIDATE_STATE(s); | 2577 | VALIDATE_STATE(s); |
2577 | if (file->f_mode & FMODE_WRITE) | 2578 | if (file->f_mode & FMODE_WRITE) |
2578 | poll_wait(file, &s->midi.owait, wait); | 2579 | poll_wait(file, &s->midi.owait, wait); |
2579 | if (file->f_mode & FMODE_READ) | 2580 | if (file->f_mode & FMODE_READ) |
2580 | poll_wait(file, &s->midi.iwait, wait); | 2581 | poll_wait(file, &s->midi.iwait, wait); |
2581 | spin_lock_irqsave(&s->lock, flags); | 2582 | spin_lock_irqsave(&s->lock, flags); |
2582 | if (file->f_mode & FMODE_READ) { | 2583 | if (file->f_mode & FMODE_READ) { |
2583 | if (s->midi.icnt > 0) | 2584 | if (s->midi.icnt > 0) |
2584 | mask |= POLLIN | POLLRDNORM; | 2585 | mask |= POLLIN | POLLRDNORM; |
2585 | } | 2586 | } |
2586 | if (file->f_mode & FMODE_WRITE) { | 2587 | if (file->f_mode & FMODE_WRITE) { |
2587 | if (s->midi.ocnt < MIDIOUTBUF) | 2588 | if (s->midi.ocnt < MIDIOUTBUF) |
2588 | mask |= POLLOUT | POLLWRNORM; | 2589 | mask |= POLLOUT | POLLWRNORM; |
2589 | } | 2590 | } |
2590 | spin_unlock_irqrestore(&s->lock, flags); | 2591 | spin_unlock_irqrestore(&s->lock, flags); |
2591 | return mask; | 2592 | return mask; |
2592 | } | 2593 | } |
2593 | 2594 | ||
2594 | static int es1371_midi_open(struct inode *inode, struct file *file) | 2595 | static int es1371_midi_open(struct inode *inode, struct file *file) |
2595 | { | 2596 | { |
2596 | int minor = iminor(inode); | 2597 | int minor = iminor(inode); |
2597 | DECLARE_WAITQUEUE(wait, current); | 2598 | DECLARE_WAITQUEUE(wait, current); |
2598 | unsigned long flags; | 2599 | unsigned long flags; |
2599 | struct list_head *list; | 2600 | struct list_head *list; |
2600 | struct es1371_state *s; | 2601 | struct es1371_state *s; |
2601 | 2602 | ||
2602 | for (list = devs.next; ; list = list->next) { | 2603 | for (list = devs.next; ; list = list->next) { |
2603 | if (list == &devs) | 2604 | if (list == &devs) |
2604 | return -ENODEV; | 2605 | return -ENODEV; |
2605 | s = list_entry(list, struct es1371_state, devs); | 2606 | s = list_entry(list, struct es1371_state, devs); |
2606 | if (s->dev_midi == minor) | 2607 | if (s->dev_midi == minor) |
2607 | break; | 2608 | break; |
2608 | } | 2609 | } |
2609 | VALIDATE_STATE(s); | 2610 | VALIDATE_STATE(s); |
2610 | file->private_data = s; | 2611 | file->private_data = s; |
2611 | /* wait for device to become free */ | 2612 | /* wait for device to become free */ |
2612 | mutex_lock(&s->open_mutex); | 2613 | mutex_lock(&s->open_mutex); |
2613 | while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) { | 2614 | while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) { |
2614 | if (file->f_flags & O_NONBLOCK) { | 2615 | if (file->f_flags & O_NONBLOCK) { |
2615 | mutex_unlock(&s->open_mutex); | 2616 | mutex_unlock(&s->open_mutex); |
2616 | return -EBUSY; | 2617 | return -EBUSY; |
2617 | } | 2618 | } |
2618 | add_wait_queue(&s->open_wait, &wait); | 2619 | add_wait_queue(&s->open_wait, &wait); |
2619 | __set_current_state(TASK_INTERRUPTIBLE); | 2620 | __set_current_state(TASK_INTERRUPTIBLE); |
2620 | mutex_unlock(&s->open_mutex); | 2621 | mutex_unlock(&s->open_mutex); |
2621 | schedule(); | 2622 | schedule(); |
2622 | remove_wait_queue(&s->open_wait, &wait); | 2623 | remove_wait_queue(&s->open_wait, &wait); |
2623 | set_current_state(TASK_RUNNING); | 2624 | set_current_state(TASK_RUNNING); |
2624 | if (signal_pending(current)) | 2625 | if (signal_pending(current)) |
2625 | return -ERESTARTSYS; | 2626 | return -ERESTARTSYS; |
2626 | mutex_lock(&s->open_mutex); | 2627 | mutex_lock(&s->open_mutex); |
2627 | } | 2628 | } |
2628 | spin_lock_irqsave(&s->lock, flags); | 2629 | spin_lock_irqsave(&s->lock, flags); |
2629 | if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { | 2630 | if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { |
2630 | s->midi.ird = s->midi.iwr = s->midi.icnt = 0; | 2631 | s->midi.ird = s->midi.iwr = s->midi.icnt = 0; |
2631 | s->midi.ord = s->midi.owr = s->midi.ocnt = 0; | 2632 | s->midi.ord = s->midi.owr = s->midi.ocnt = 0; |
2632 | outb(UCTRL_CNTRL_SWR, s->io+ES1371_REG_UART_CONTROL); | 2633 | outb(UCTRL_CNTRL_SWR, s->io+ES1371_REG_UART_CONTROL); |
2633 | outb(0, s->io+ES1371_REG_UART_CONTROL); | 2634 | outb(0, s->io+ES1371_REG_UART_CONTROL); |
2634 | outb(0, s->io+ES1371_REG_UART_TEST); | 2635 | outb(0, s->io+ES1371_REG_UART_TEST); |
2635 | } | 2636 | } |
2636 | if (file->f_mode & FMODE_READ) { | 2637 | if (file->f_mode & FMODE_READ) { |
2637 | s->midi.ird = s->midi.iwr = s->midi.icnt = 0; | 2638 | s->midi.ird = s->midi.iwr = s->midi.icnt = 0; |
2638 | } | 2639 | } |
2639 | if (file->f_mode & FMODE_WRITE) { | 2640 | if (file->f_mode & FMODE_WRITE) { |
2640 | s->midi.ord = s->midi.owr = s->midi.ocnt = 0; | 2641 | s->midi.ord = s->midi.owr = s->midi.ocnt = 0; |
2641 | } | 2642 | } |
2642 | s->ctrl |= CTRL_UART_EN; | 2643 | s->ctrl |= CTRL_UART_EN; |
2643 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 2644 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
2644 | es1371_handle_midi(s); | 2645 | es1371_handle_midi(s); |
2645 | spin_unlock_irqrestore(&s->lock, flags); | 2646 | spin_unlock_irqrestore(&s->lock, flags); |
2646 | s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); | 2647 | s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); |
2647 | mutex_unlock(&s->open_mutex); | 2648 | mutex_unlock(&s->open_mutex); |
2648 | return nonseekable_open(inode, file); | 2649 | return nonseekable_open(inode, file); |
2649 | } | 2650 | } |
2650 | 2651 | ||
2651 | static int es1371_midi_release(struct inode *inode, struct file *file) | 2652 | static int es1371_midi_release(struct inode *inode, struct file *file) |
2652 | { | 2653 | { |
2653 | struct es1371_state *s = (struct es1371_state *)file->private_data; | 2654 | struct es1371_state *s = (struct es1371_state *)file->private_data; |
2654 | DECLARE_WAITQUEUE(wait, current); | 2655 | DECLARE_WAITQUEUE(wait, current); |
2655 | unsigned long flags; | 2656 | unsigned long flags; |
2656 | unsigned count, tmo; | 2657 | unsigned count, tmo; |
2657 | 2658 | ||
2658 | VALIDATE_STATE(s); | 2659 | VALIDATE_STATE(s); |
2659 | lock_kernel(); | 2660 | lock_kernel(); |
2660 | if (file->f_mode & FMODE_WRITE) { | 2661 | if (file->f_mode & FMODE_WRITE) { |
2661 | add_wait_queue(&s->midi.owait, &wait); | 2662 | add_wait_queue(&s->midi.owait, &wait); |
2662 | for (;;) { | 2663 | for (;;) { |
2663 | __set_current_state(TASK_INTERRUPTIBLE); | 2664 | __set_current_state(TASK_INTERRUPTIBLE); |
2664 | spin_lock_irqsave(&s->lock, flags); | 2665 | spin_lock_irqsave(&s->lock, flags); |
2665 | count = s->midi.ocnt; | 2666 | count = s->midi.ocnt; |
2666 | spin_unlock_irqrestore(&s->lock, flags); | 2667 | spin_unlock_irqrestore(&s->lock, flags); |
2667 | if (count <= 0) | 2668 | if (count <= 0) |
2668 | break; | 2669 | break; |
2669 | if (signal_pending(current)) | 2670 | if (signal_pending(current)) |
2670 | break; | 2671 | break; |
2671 | if (file->f_flags & O_NONBLOCK) | 2672 | if (file->f_flags & O_NONBLOCK) |
2672 | break; | 2673 | break; |
2673 | tmo = (count * HZ) / 3100; | 2674 | tmo = (count * HZ) / 3100; |
2674 | if (!schedule_timeout(tmo ? : 1) && tmo) | 2675 | if (!schedule_timeout(tmo ? : 1) && tmo) |
2675 | printk(KERN_DEBUG PFX "midi timed out??\n"); | 2676 | printk(KERN_DEBUG PFX "midi timed out??\n"); |
2676 | } | 2677 | } |
2677 | remove_wait_queue(&s->midi.owait, &wait); | 2678 | remove_wait_queue(&s->midi.owait, &wait); |
2678 | set_current_state(TASK_RUNNING); | 2679 | set_current_state(TASK_RUNNING); |
2679 | } | 2680 | } |
2680 | mutex_lock(&s->open_mutex); | 2681 | mutex_lock(&s->open_mutex); |
2681 | s->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE)); | 2682 | s->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE)); |
2682 | spin_lock_irqsave(&s->lock, flags); | 2683 | spin_lock_irqsave(&s->lock, flags); |
2683 | if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { | 2684 | if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { |
2684 | s->ctrl &= ~CTRL_UART_EN; | 2685 | s->ctrl &= ~CTRL_UART_EN; |
2685 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 2686 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
2686 | } | 2687 | } |
2687 | spin_unlock_irqrestore(&s->lock, flags); | 2688 | spin_unlock_irqrestore(&s->lock, flags); |
2688 | mutex_unlock(&s->open_mutex); | 2689 | mutex_unlock(&s->open_mutex); |
2689 | wake_up(&s->open_wait); | 2690 | wake_up(&s->open_wait); |
2690 | unlock_kernel(); | 2691 | unlock_kernel(); |
2691 | return 0; | 2692 | return 0; |
2692 | } | 2693 | } |
2693 | 2694 | ||
2694 | static /*const*/ struct file_operations es1371_midi_fops = { | 2695 | static /*const*/ struct file_operations es1371_midi_fops = { |
2695 | .owner = THIS_MODULE, | 2696 | .owner = THIS_MODULE, |
2696 | .llseek = no_llseek, | 2697 | .llseek = no_llseek, |
2697 | .read = es1371_midi_read, | 2698 | .read = es1371_midi_read, |
2698 | .write = es1371_midi_write, | 2699 | .write = es1371_midi_write, |
2699 | .poll = es1371_midi_poll, | 2700 | .poll = es1371_midi_poll, |
2700 | .open = es1371_midi_open, | 2701 | .open = es1371_midi_open, |
2701 | .release = es1371_midi_release, | 2702 | .release = es1371_midi_release, |
2702 | }; | 2703 | }; |
2703 | 2704 | ||
2704 | /* --------------------------------------------------------------------- */ | 2705 | /* --------------------------------------------------------------------- */ |
2705 | 2706 | ||
2706 | /* | 2707 | /* |
2707 | * for debugging purposes, we'll create a proc device that dumps the | 2708 | * for debugging purposes, we'll create a proc device that dumps the |
2708 | * CODEC chipstate | 2709 | * CODEC chipstate |
2709 | */ | 2710 | */ |
2710 | 2711 | ||
2711 | #ifdef ES1371_DEBUG | 2712 | #ifdef ES1371_DEBUG |
2712 | static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, int *eof, void *data) | 2713 | static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, int *eof, void *data) |
2713 | { | 2714 | { |
2714 | struct es1371_state *s; | 2715 | struct es1371_state *s; |
2715 | int cnt, len = 0; | 2716 | int cnt, len = 0; |
2716 | 2717 | ||
2717 | if (list_empty(&devs)) | 2718 | if (list_empty(&devs)) |
2718 | return 0; | 2719 | return 0; |
2719 | s = list_entry(devs.next, struct es1371_state, devs); | 2720 | s = list_entry(devs.next, struct es1371_state, devs); |
2720 | /* print out header */ | 2721 | /* print out header */ |
2721 | len += sprintf(buf + len, "\t\tCreative ES137x Debug Dump-o-matic\n"); | 2722 | len += sprintf(buf + len, "\t\tCreative ES137x Debug Dump-o-matic\n"); |
2722 | 2723 | ||
2723 | /* print out CODEC state */ | 2724 | /* print out CODEC state */ |
2724 | len += sprintf (buf + len, "AC97 CODEC state\n"); | 2725 | len += sprintf (buf + len, "AC97 CODEC state\n"); |
2725 | for (cnt=0; cnt <= 0x7e; cnt = cnt +2) | 2726 | for (cnt=0; cnt <= 0x7e; cnt = cnt +2) |
2726 | len+= sprintf (buf + len, "reg:0x%02x val:0x%04x\n", cnt, rdcodec(s->codec, cnt)); | 2727 | len+= sprintf (buf + len, "reg:0x%02x val:0x%04x\n", cnt, rdcodec(s->codec, cnt)); |
2727 | 2728 | ||
2728 | if (fpos >=len){ | 2729 | if (fpos >=len){ |
2729 | *start = buf; | 2730 | *start = buf; |
2730 | *eof =1; | 2731 | *eof =1; |
2731 | return 0; | 2732 | return 0; |
2732 | } | 2733 | } |
2733 | *start = buf + fpos; | 2734 | *start = buf + fpos; |
2734 | if ((len -= fpos) > length) | 2735 | if ((len -= fpos) > length) |
2735 | return length; | 2736 | return length; |
2736 | *eof =1; | 2737 | *eof =1; |
2737 | return len; | 2738 | return len; |
2738 | 2739 | ||
2739 | } | 2740 | } |
2740 | #endif /* ES1371_DEBUG */ | 2741 | #endif /* ES1371_DEBUG */ |
2741 | 2742 | ||
2742 | /* --------------------------------------------------------------------- */ | 2743 | /* --------------------------------------------------------------------- */ |
2743 | 2744 | ||
2744 | /* maximum number of devices; only used for command line params */ | 2745 | /* maximum number of devices; only used for command line params */ |
2745 | #define NR_DEVICE 5 | 2746 | #define NR_DEVICE 5 |
2746 | 2747 | ||
2747 | static int spdif[NR_DEVICE]; | 2748 | static int spdif[NR_DEVICE]; |
2748 | static int nomix[NR_DEVICE]; | 2749 | static int nomix[NR_DEVICE]; |
2749 | static int amplifier[NR_DEVICE]; | 2750 | static int amplifier[NR_DEVICE]; |
2750 | 2751 | ||
2751 | static unsigned int devindex; | 2752 | static unsigned int devindex; |
2752 | 2753 | ||
2753 | module_param_array(spdif, bool, NULL, 0); | 2754 | module_param_array(spdif, bool, NULL, 0); |
2754 | MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode"); | 2755 | MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode"); |
2755 | module_param_array(nomix, bool, NULL, 0); | 2756 | module_param_array(nomix, bool, NULL, 0); |
2756 | MODULE_PARM_DESC(nomix, "if 1 no analog audio is mixed to the digital output"); | 2757 | MODULE_PARM_DESC(nomix, "if 1 no analog audio is mixed to the digital output"); |
2757 | module_param_array(amplifier, bool, NULL, 0); | 2758 | module_param_array(amplifier, bool, NULL, 0); |
2758 | MODULE_PARM_DESC(amplifier, "Set to 1 if the machine needs the amp control enabling (many laptops)"); | 2759 | MODULE_PARM_DESC(amplifier, "Set to 1 if the machine needs the amp control enabling (many laptops)"); |
2759 | 2760 | ||
2760 | MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); | 2761 | MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); |
2761 | MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver"); | 2762 | MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver"); |
2762 | MODULE_LICENSE("GPL"); | 2763 | MODULE_LICENSE("GPL"); |
2763 | 2764 | ||
2764 | 2765 | ||
2765 | /* --------------------------------------------------------------------- */ | 2766 | /* --------------------------------------------------------------------- */ |
2766 | 2767 | ||
2767 | static struct initvol { | 2768 | static struct initvol { |
2768 | int mixch; | 2769 | int mixch; |
2769 | int vol; | 2770 | int vol; |
2770 | } initvol[] __devinitdata = { | 2771 | } initvol[] __devinitdata = { |
2771 | { SOUND_MIXER_WRITE_LINE, 0x4040 }, | 2772 | { SOUND_MIXER_WRITE_LINE, 0x4040 }, |
2772 | { SOUND_MIXER_WRITE_CD, 0x4040 }, | 2773 | { SOUND_MIXER_WRITE_CD, 0x4040 }, |
2773 | { MIXER_WRITE(SOUND_MIXER_VIDEO), 0x4040 }, | 2774 | { MIXER_WRITE(SOUND_MIXER_VIDEO), 0x4040 }, |
2774 | { SOUND_MIXER_WRITE_LINE1, 0x4040 }, | 2775 | { SOUND_MIXER_WRITE_LINE1, 0x4040 }, |
2775 | { SOUND_MIXER_WRITE_PCM, 0x4040 }, | 2776 | { SOUND_MIXER_WRITE_PCM, 0x4040 }, |
2776 | { SOUND_MIXER_WRITE_VOLUME, 0x4040 }, | 2777 | { SOUND_MIXER_WRITE_VOLUME, 0x4040 }, |
2777 | { MIXER_WRITE(SOUND_MIXER_PHONEOUT), 0x4040 }, | 2778 | { MIXER_WRITE(SOUND_MIXER_PHONEOUT), 0x4040 }, |
2778 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 }, | 2779 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 }, |
2779 | { MIXER_WRITE(SOUND_MIXER_PHONEIN), 0x4040 }, | 2780 | { MIXER_WRITE(SOUND_MIXER_PHONEIN), 0x4040 }, |
2780 | { SOUND_MIXER_WRITE_SPEAKER, 0x4040 }, | 2781 | { SOUND_MIXER_WRITE_SPEAKER, 0x4040 }, |
2781 | { SOUND_MIXER_WRITE_MIC, 0x4040 }, | 2782 | { SOUND_MIXER_WRITE_MIC, 0x4040 }, |
2782 | { SOUND_MIXER_WRITE_RECLEV, 0x4040 }, | 2783 | { SOUND_MIXER_WRITE_RECLEV, 0x4040 }, |
2783 | { SOUND_MIXER_WRITE_IGAIN, 0x4040 } | 2784 | { SOUND_MIXER_WRITE_IGAIN, 0x4040 } |
2784 | }; | 2785 | }; |
2785 | 2786 | ||
2786 | static struct | 2787 | static struct |
2787 | { | 2788 | { |
2788 | short svid, sdid; | 2789 | short svid, sdid; |
2789 | } amplifier_needed[] = | 2790 | } amplifier_needed[] = |
2790 | { | 2791 | { |
2791 | { 0x107B, 0x2150 }, /* Gateway Solo 2150 */ | 2792 | { 0x107B, 0x2150 }, /* Gateway Solo 2150 */ |
2792 | { 0x13BD, 0x100C }, /* Mebius PC-MJ100V */ | 2793 | { 0x13BD, 0x100C }, /* Mebius PC-MJ100V */ |
2793 | { 0x1102, 0x5938 }, /* Targa Xtender 300 */ | 2794 | { 0x1102, 0x5938 }, /* Targa Xtender 300 */ |
2794 | { 0x1102, 0x8938 }, /* IPC notebook */ | 2795 | { 0x1102, 0x8938 }, /* IPC notebook */ |
2795 | { PCI_ANY_ID, PCI_ANY_ID } | 2796 | { PCI_ANY_ID, PCI_ANY_ID } |
2796 | }; | 2797 | }; |
2797 | 2798 | ||
2798 | #ifdef SUPPORT_JOYSTICK | 2799 | #ifdef SUPPORT_JOYSTICK |
2799 | 2800 | ||
2800 | static int __devinit es1371_register_gameport(struct es1371_state *s) | 2801 | static int __devinit es1371_register_gameport(struct es1371_state *s) |
2801 | { | 2802 | { |
2802 | struct gameport *gp; | 2803 | struct gameport *gp; |
2803 | int gpio; | 2804 | int gpio; |
2804 | 2805 | ||
2805 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) | 2806 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) |
2806 | if (request_region(gpio, JOY_EXTENT, "es1371")) | 2807 | if (request_region(gpio, JOY_EXTENT, "es1371")) |
2807 | break; | 2808 | break; |
2808 | 2809 | ||
2809 | if (gpio < 0x200) { | 2810 | if (gpio < 0x200) { |
2810 | printk(KERN_ERR PFX "no free joystick address found\n"); | 2811 | printk(KERN_ERR PFX "no free joystick address found\n"); |
2811 | return -EBUSY; | 2812 | return -EBUSY; |
2812 | } | 2813 | } |
2813 | 2814 | ||
2814 | s->gameport = gp = gameport_allocate_port(); | 2815 | s->gameport = gp = gameport_allocate_port(); |
2815 | if (!gp) { | 2816 | if (!gp) { |
2816 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); | 2817 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); |
2817 | release_region(gpio, JOY_EXTENT); | 2818 | release_region(gpio, JOY_EXTENT); |
2818 | return -ENOMEM; | 2819 | return -ENOMEM; |
2819 | } | 2820 | } |
2820 | 2821 | ||
2821 | gameport_set_name(gp, "ESS1371 Gameport"); | 2822 | gameport_set_name(gp, "ESS1371 Gameport"); |
2822 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); | 2823 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); |
2823 | gp->dev.parent = &s->dev->dev; | 2824 | gp->dev.parent = &s->dev->dev; |
2824 | gp->io = gpio; | 2825 | gp->io = gpio; |
2825 | 2826 | ||
2826 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); | 2827 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); |
2827 | outl(s->ctrl, s->io + ES1371_REG_CONTROL); | 2828 | outl(s->ctrl, s->io + ES1371_REG_CONTROL); |
2828 | 2829 | ||
2829 | gameport_register_port(gp); | 2830 | gameport_register_port(gp); |
2830 | 2831 | ||
2831 | return 0; | 2832 | return 0; |
2832 | } | 2833 | } |
2833 | 2834 | ||
2834 | static inline void es1371_unregister_gameport(struct es1371_state *s) | 2835 | static inline void es1371_unregister_gameport(struct es1371_state *s) |
2835 | { | 2836 | { |
2836 | if (s->gameport) { | 2837 | if (s->gameport) { |
2837 | int gpio = s->gameport->io; | 2838 | int gpio = s->gameport->io; |
2838 | gameport_unregister_port(s->gameport); | 2839 | gameport_unregister_port(s->gameport); |
2839 | release_region(gpio, JOY_EXTENT); | 2840 | release_region(gpio, JOY_EXTENT); |
2840 | 2841 | ||
2841 | } | 2842 | } |
2842 | } | 2843 | } |
2843 | 2844 | ||
2844 | #else | 2845 | #else |
2845 | static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; } | 2846 | static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; } |
2846 | static inline void es1371_unregister_gameport(struct es1371_state *s) { } | 2847 | static inline void es1371_unregister_gameport(struct es1371_state *s) { } |
2847 | #endif /* SUPPORT_JOYSTICK */ | 2848 | #endif /* SUPPORT_JOYSTICK */ |
2848 | 2849 | ||
2849 | 2850 | ||
2850 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2851 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2851 | { | 2852 | { |
2852 | struct es1371_state *s; | 2853 | struct es1371_state *s; |
2853 | mm_segment_t fs; | 2854 | mm_segment_t fs; |
2854 | int i, val, res = -1; | 2855 | int i, val, res = -1; |
2855 | int idx; | 2856 | int idx; |
2856 | unsigned long tmo; | 2857 | unsigned long tmo; |
2857 | signed long tmo2; | 2858 | signed long tmo2; |
2858 | unsigned int cssr; | 2859 | unsigned int cssr; |
2859 | 2860 | ||
2860 | if ((res=pci_enable_device(pcidev))) | 2861 | if ((res=pci_enable_device(pcidev))) |
2861 | return res; | 2862 | return res; |
2862 | 2863 | ||
2863 | if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO)) | 2864 | if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO)) |
2864 | return -ENODEV; | 2865 | return -ENODEV; |
2865 | if (pcidev->irq == 0) | 2866 | if (pcidev->irq == 0) |
2866 | return -ENODEV; | 2867 | return -ENODEV; |
2867 | i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); | 2868 | i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); |
2868 | if (i) { | 2869 | if (i) { |
2869 | printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n"); | 2870 | printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n"); |
2870 | return i; | 2871 | return i; |
2871 | } | 2872 | } |
2872 | if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) { | 2873 | if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) { |
2873 | printk(KERN_WARNING PFX "out of memory\n"); | 2874 | printk(KERN_WARNING PFX "out of memory\n"); |
2874 | return -ENOMEM; | 2875 | return -ENOMEM; |
2875 | } | 2876 | } |
2876 | memset(s, 0, sizeof(struct es1371_state)); | 2877 | memset(s, 0, sizeof(struct es1371_state)); |
2877 | 2878 | ||
2878 | s->codec = ac97_alloc_codec(); | 2879 | s->codec = ac97_alloc_codec(); |
2879 | if(s->codec == NULL) | 2880 | if(s->codec == NULL) |
2880 | goto err_codec; | 2881 | goto err_codec; |
2881 | 2882 | ||
2882 | init_waitqueue_head(&s->dma_adc.wait); | 2883 | init_waitqueue_head(&s->dma_adc.wait); |
2883 | init_waitqueue_head(&s->dma_dac1.wait); | 2884 | init_waitqueue_head(&s->dma_dac1.wait); |
2884 | init_waitqueue_head(&s->dma_dac2.wait); | 2885 | init_waitqueue_head(&s->dma_dac2.wait); |
2885 | init_waitqueue_head(&s->open_wait); | 2886 | init_waitqueue_head(&s->open_wait); |
2886 | init_waitqueue_head(&s->midi.iwait); | 2887 | init_waitqueue_head(&s->midi.iwait); |
2887 | init_waitqueue_head(&s->midi.owait); | 2888 | init_waitqueue_head(&s->midi.owait); |
2888 | mutex_init(&s->open_mutex); | 2889 | mutex_init(&s->open_mutex); |
2889 | spin_lock_init(&s->lock); | 2890 | spin_lock_init(&s->lock); |
2890 | s->magic = ES1371_MAGIC; | 2891 | s->magic = ES1371_MAGIC; |
2891 | s->dev = pcidev; | 2892 | s->dev = pcidev; |
2892 | s->io = pci_resource_start(pcidev, 0); | 2893 | s->io = pci_resource_start(pcidev, 0); |
2893 | s->irq = pcidev->irq; | 2894 | s->irq = pcidev->irq; |
2894 | s->vendor = pcidev->vendor; | 2895 | s->vendor = pcidev->vendor; |
2895 | s->device = pcidev->device; | 2896 | s->device = pcidev->device; |
2896 | pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev); | 2897 | pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev); |
2897 | s->codec->private_data = s; | 2898 | s->codec->private_data = s; |
2898 | s->codec->id = 0; | 2899 | s->codec->id = 0; |
2899 | s->codec->codec_read = rdcodec; | 2900 | s->codec->codec_read = rdcodec; |
2900 | s->codec->codec_write = wrcodec; | 2901 | s->codec->codec_write = wrcodec; |
2901 | printk(KERN_INFO PFX "found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n", | 2902 | printk(KERN_INFO PFX "found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n", |
2902 | s->vendor, s->device, s->rev); | 2903 | s->vendor, s->device, s->rev); |
2903 | if (!request_region(s->io, ES1371_EXTENT, "es1371")) { | 2904 | if (!request_region(s->io, ES1371_EXTENT, "es1371")) { |
2904 | printk(KERN_ERR PFX "io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1); | 2905 | printk(KERN_ERR PFX "io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1); |
2905 | res = -EBUSY; | 2906 | res = -EBUSY; |
2906 | goto err_region; | 2907 | goto err_region; |
2907 | } | 2908 | } |
2908 | if ((res=request_irq(s->irq, es1371_interrupt, IRQF_SHARED, "es1371",s))) { | 2909 | if ((res=request_irq(s->irq, es1371_interrupt, IRQF_SHARED, "es1371",s))) { |
2909 | printk(KERN_ERR PFX "irq %u in use\n", s->irq); | 2910 | printk(KERN_ERR PFX "irq %u in use\n", s->irq); |
2910 | goto err_irq; | 2911 | goto err_irq; |
2911 | } | 2912 | } |
2912 | printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n", | 2913 | printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n", |
2913 | s->rev, s->io, s->irq); | 2914 | s->rev, s->io, s->irq); |
2914 | /* register devices */ | 2915 | /* register devices */ |
2915 | if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0) | 2916 | if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0) |
2916 | goto err_dev1; | 2917 | goto err_dev1; |
2917 | if ((res=(s->codec->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1))) < 0) | 2918 | if ((res=(s->codec->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1))) < 0) |
2918 | goto err_dev2; | 2919 | goto err_dev2; |
2919 | if ((res=(s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1))) < 0) | 2920 | if ((res=(s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1))) < 0) |
2920 | goto err_dev3; | 2921 | goto err_dev3; |
2921 | if ((res=(s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)))<0 ) | 2922 | if ((res=(s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)))<0 ) |
2922 | goto err_dev4; | 2923 | goto err_dev4; |
2923 | #ifdef ES1371_DEBUG | 2924 | #ifdef ES1371_DEBUG |
2924 | /* initialize the debug proc device */ | 2925 | /* initialize the debug proc device */ |
2925 | s->ps = create_proc_read_entry("es1371",0,NULL,proc_es1371_dump,NULL); | 2926 | s->ps = create_proc_read_entry("es1371",0,NULL,proc_es1371_dump,NULL); |
2926 | #endif /* ES1371_DEBUG */ | 2927 | #endif /* ES1371_DEBUG */ |
2927 | 2928 | ||
2928 | /* initialize codec registers */ | 2929 | /* initialize codec registers */ |
2929 | s->ctrl = 0; | 2930 | s->ctrl = 0; |
2930 | 2931 | ||
2931 | /* Check amplifier requirements */ | 2932 | /* Check amplifier requirements */ |
2932 | 2933 | ||
2933 | if (amplifier[devindex]) | 2934 | if (amplifier[devindex]) |
2934 | s->ctrl |= CTRL_GPIO_OUT0; | 2935 | s->ctrl |= CTRL_GPIO_OUT0; |
2935 | else for(idx = 0; amplifier_needed[idx].svid != PCI_ANY_ID; idx++) | 2936 | else for(idx = 0; amplifier_needed[idx].svid != PCI_ANY_ID; idx++) |
2936 | { | 2937 | { |
2937 | if(pcidev->subsystem_vendor == amplifier_needed[idx].svid && | 2938 | if(pcidev->subsystem_vendor == amplifier_needed[idx].svid && |
2938 | pcidev->subsystem_device == amplifier_needed[idx].sdid) | 2939 | pcidev->subsystem_device == amplifier_needed[idx].sdid) |
2939 | { | 2940 | { |
2940 | s->ctrl |= CTRL_GPIO_OUT0; /* turn internal amplifier on */ | 2941 | s->ctrl |= CTRL_GPIO_OUT0; /* turn internal amplifier on */ |
2941 | printk(KERN_INFO PFX "Enabling internal amplifier.\n"); | 2942 | printk(KERN_INFO PFX "Enabling internal amplifier.\n"); |
2942 | } | 2943 | } |
2943 | } | 2944 | } |
2944 | 2945 | ||
2945 | s->sctrl = 0; | 2946 | s->sctrl = 0; |
2946 | cssr = 0; | 2947 | cssr = 0; |
2947 | s->spdif_volume = -1; | 2948 | s->spdif_volume = -1; |
2948 | /* check to see if s/pdif mode is being requested */ | 2949 | /* check to see if s/pdif mode is being requested */ |
2949 | if (spdif[devindex]) { | 2950 | if (spdif[devindex]) { |
2950 | if (s->rev >= 4) { | 2951 | if (s->rev >= 4) { |
2951 | printk(KERN_INFO PFX "enabling S/PDIF output\n"); | 2952 | printk(KERN_INFO PFX "enabling S/PDIF output\n"); |
2952 | s->spdif_volume = 0; | 2953 | s->spdif_volume = 0; |
2953 | cssr |= STAT_EN_SPDIF; | 2954 | cssr |= STAT_EN_SPDIF; |
2954 | s->ctrl |= CTRL_SPDIFEN_B; | 2955 | s->ctrl |= CTRL_SPDIFEN_B; |
2955 | if (nomix[devindex]) /* don't mix analog inputs to s/pdif output */ | 2956 | if (nomix[devindex]) /* don't mix analog inputs to s/pdif output */ |
2956 | s->ctrl |= CTRL_RECEN_B; | 2957 | s->ctrl |= CTRL_RECEN_B; |
2957 | } else { | 2958 | } else { |
2958 | printk(KERN_ERR PFX "revision %d does not support S/PDIF\n", s->rev); | 2959 | printk(KERN_ERR PFX "revision %d does not support S/PDIF\n", s->rev); |
2959 | } | 2960 | } |
2960 | } | 2961 | } |
2961 | /* initialize the chips */ | 2962 | /* initialize the chips */ |
2962 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 2963 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
2963 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); | 2964 | outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); |
2964 | outl(LEGACY_JFAST, s->io+ES1371_REG_LEGACY); | 2965 | outl(LEGACY_JFAST, s->io+ES1371_REG_LEGACY); |
2965 | pci_set_master(pcidev); /* enable bus mastering */ | 2966 | pci_set_master(pcidev); /* enable bus mastering */ |
2966 | /* if we are a 5880 turn on the AC97 */ | 2967 | /* if we are a 5880 turn on the AC97 */ |
2967 | if (s->vendor == PCI_VENDOR_ID_ENSONIQ && | 2968 | if (s->vendor == PCI_VENDOR_ID_ENSONIQ && |
2968 | ((s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 && s->rev >= CT5880REV_CT5880_C) || | 2969 | ((s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 && s->rev >= CT5880REV_CT5880_C) || |
2969 | (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A) || | 2970 | (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A) || |
2970 | (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_ES1373_8))) { | 2971 | (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_ES1373_8))) { |
2971 | cssr |= CSTAT_5880_AC97_RST; | 2972 | cssr |= CSTAT_5880_AC97_RST; |
2972 | outl(cssr, s->io+ES1371_REG_STATUS); | 2973 | outl(cssr, s->io+ES1371_REG_STATUS); |
2973 | /* need to delay around 20ms(bleech) to give | 2974 | /* need to delay around 20ms(bleech) to give |
2974 | some CODECs enough time to wakeup */ | 2975 | some CODECs enough time to wakeup */ |
2975 | tmo = jiffies + (HZ / 50) + 1; | 2976 | tmo = jiffies + (HZ / 50) + 1; |
2976 | for (;;) { | 2977 | for (;;) { |
2977 | tmo2 = tmo - jiffies; | 2978 | tmo2 = tmo - jiffies; |
2978 | if (tmo2 <= 0) | 2979 | if (tmo2 <= 0) |
2979 | break; | 2980 | break; |
2980 | schedule_timeout(tmo2); | 2981 | schedule_timeout(tmo2); |
2981 | } | 2982 | } |
2982 | } | 2983 | } |
2983 | /* AC97 warm reset to start the bitclk */ | 2984 | /* AC97 warm reset to start the bitclk */ |
2984 | outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL); | 2985 | outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL); |
2985 | udelay(2); | 2986 | udelay(2); |
2986 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); | 2987 | outl(s->ctrl, s->io+ES1371_REG_CONTROL); |
2987 | /* init the sample rate converter */ | 2988 | /* init the sample rate converter */ |
2988 | src_init(s); | 2989 | src_init(s); |
2989 | /* codec init */ | 2990 | /* codec init */ |
2990 | if (!ac97_probe_codec(s->codec)) { | 2991 | if (!ac97_probe_codec(s->codec)) { |
2991 | res = -ENODEV; | 2992 | res = -ENODEV; |
2992 | goto err_gp; | 2993 | goto err_gp; |
2993 | } | 2994 | } |
2994 | /* set default values */ | 2995 | /* set default values */ |
2995 | 2996 | ||
2996 | fs = get_fs(); | 2997 | fs = get_fs(); |
2997 | set_fs(KERNEL_DS); | 2998 | set_fs(KERNEL_DS); |
2998 | val = SOUND_MASK_LINE; | 2999 | val = SOUND_MASK_LINE; |
2999 | mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); | 3000 | mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); |
3000 | for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { | 3001 | for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { |
3001 | val = initvol[i].vol; | 3002 | val = initvol[i].vol; |
3002 | mixdev_ioctl(s->codec, initvol[i].mixch, (unsigned long)&val); | 3003 | mixdev_ioctl(s->codec, initvol[i].mixch, (unsigned long)&val); |
3003 | } | 3004 | } |
3004 | /* mute master and PCM when in S/PDIF mode */ | 3005 | /* mute master and PCM when in S/PDIF mode */ |
3005 | if (s->spdif_volume != -1) { | 3006 | if (s->spdif_volume != -1) { |
3006 | val = 0x0000; | 3007 | val = 0x0000; |
3007 | s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_VOLUME, (unsigned long)&val); | 3008 | s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_VOLUME, (unsigned long)&val); |
3008 | s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_PCM, (unsigned long)&val); | 3009 | s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_PCM, (unsigned long)&val); |
3009 | } | 3010 | } |
3010 | set_fs(fs); | 3011 | set_fs(fs); |
3011 | /* turn on S/PDIF output driver if requested */ | 3012 | /* turn on S/PDIF output driver if requested */ |
3012 | outl(cssr, s->io+ES1371_REG_STATUS); | 3013 | outl(cssr, s->io+ES1371_REG_STATUS); |
3013 | 3014 | ||
3014 | es1371_register_gameport(s); | 3015 | es1371_register_gameport(s); |
3015 | 3016 | ||
3016 | /* store it in the driver field */ | 3017 | /* store it in the driver field */ |
3017 | pci_set_drvdata(pcidev, s); | 3018 | pci_set_drvdata(pcidev, s); |
3018 | /* put it into driver list */ | 3019 | /* put it into driver list */ |
3019 | list_add_tail(&s->devs, &devs); | 3020 | list_add_tail(&s->devs, &devs); |
3020 | /* increment devindex */ | 3021 | /* increment devindex */ |
3021 | if (devindex < NR_DEVICE-1) | 3022 | if (devindex < NR_DEVICE-1) |
3022 | devindex++; | 3023 | devindex++; |
3023 | return 0; | 3024 | return 0; |
3024 | 3025 | ||
3025 | err_gp: | 3026 | err_gp: |
3026 | #ifdef ES1371_DEBUG | 3027 | #ifdef ES1371_DEBUG |
3027 | if (s->ps) | 3028 | if (s->ps) |
3028 | remove_proc_entry("es1371", NULL); | 3029 | remove_proc_entry("es1371", NULL); |
3029 | #endif | 3030 | #endif |
3030 | unregister_sound_midi(s->dev_midi); | 3031 | unregister_sound_midi(s->dev_midi); |
3031 | err_dev4: | 3032 | err_dev4: |
3032 | unregister_sound_dsp(s->dev_dac); | 3033 | unregister_sound_dsp(s->dev_dac); |
3033 | err_dev3: | 3034 | err_dev3: |
3034 | unregister_sound_mixer(s->codec->dev_mixer); | 3035 | unregister_sound_mixer(s->codec->dev_mixer); |
3035 | err_dev2: | 3036 | err_dev2: |
3036 | unregister_sound_dsp(s->dev_audio); | 3037 | unregister_sound_dsp(s->dev_audio); |
3037 | err_dev1: | 3038 | err_dev1: |
3038 | printk(KERN_ERR PFX "cannot register misc device\n"); | 3039 | printk(KERN_ERR PFX "cannot register misc device\n"); |
3039 | free_irq(s->irq, s); | 3040 | free_irq(s->irq, s); |
3040 | err_irq: | 3041 | err_irq: |
3041 | release_region(s->io, ES1371_EXTENT); | 3042 | release_region(s->io, ES1371_EXTENT); |
3042 | err_region: | 3043 | err_region: |
3043 | err_codec: | 3044 | err_codec: |
3044 | ac97_release_codec(s->codec); | 3045 | ac97_release_codec(s->codec); |
3045 | kfree(s); | 3046 | kfree(s); |
3046 | return res; | 3047 | return res; |
3047 | } | 3048 | } |
3048 | 3049 | ||
3049 | static void __devexit es1371_remove(struct pci_dev *dev) | 3050 | static void __devexit es1371_remove(struct pci_dev *dev) |
3050 | { | 3051 | { |
3051 | struct es1371_state *s = pci_get_drvdata(dev); | 3052 | struct es1371_state *s = pci_get_drvdata(dev); |
3052 | 3053 | ||
3053 | if (!s) | 3054 | if (!s) |
3054 | return; | 3055 | return; |
3055 | list_del(&s->devs); | 3056 | list_del(&s->devs); |
3056 | #ifdef ES1371_DEBUG | 3057 | #ifdef ES1371_DEBUG |
3057 | if (s->ps) | 3058 | if (s->ps) |
3058 | remove_proc_entry("es1371", NULL); | 3059 | remove_proc_entry("es1371", NULL); |
3059 | #endif /* ES1371_DEBUG */ | 3060 | #endif /* ES1371_DEBUG */ |
3060 | outl(0, s->io+ES1371_REG_CONTROL); /* switch everything off */ | 3061 | outl(0, s->io+ES1371_REG_CONTROL); /* switch everything off */ |
3061 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ | 3062 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ |
3062 | synchronize_irq(s->irq); | 3063 | synchronize_irq(s->irq); |
3063 | free_irq(s->irq, s); | 3064 | free_irq(s->irq, s); |
3064 | es1371_unregister_gameport(s); | 3065 | es1371_unregister_gameport(s); |
3065 | release_region(s->io, ES1371_EXTENT); | 3066 | release_region(s->io, ES1371_EXTENT); |
3066 | unregister_sound_dsp(s->dev_audio); | 3067 | unregister_sound_dsp(s->dev_audio); |
3067 | unregister_sound_mixer(s->codec->dev_mixer); | 3068 | unregister_sound_mixer(s->codec->dev_mixer); |
3068 | unregister_sound_dsp(s->dev_dac); | 3069 | unregister_sound_dsp(s->dev_dac); |
3069 | unregister_sound_midi(s->dev_midi); | 3070 | unregister_sound_midi(s->dev_midi); |
3070 | ac97_release_codec(s->codec); | 3071 | ac97_release_codec(s->codec); |
3071 | kfree(s); | 3072 | kfree(s); |
3072 | pci_set_drvdata(dev, NULL); | 3073 | pci_set_drvdata(dev, NULL); |
3073 | } | 3074 | } |
3074 | 3075 | ||
3075 | static struct pci_device_id id_table[] = { | 3076 | static struct pci_device_id id_table[] = { |
3076 | { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, | 3077 | { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, |
3077 | { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_CT5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, | 3078 | { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_CT5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, |
3078 | { PCI_VENDOR_ID_ECTIVA, PCI_DEVICE_ID_ECTIVA_EV1938, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, | 3079 | { PCI_VENDOR_ID_ECTIVA, PCI_DEVICE_ID_ECTIVA_EV1938, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, |
3079 | { 0, } | 3080 | { 0, } |
3080 | }; | 3081 | }; |
3081 | 3082 | ||
3082 | MODULE_DEVICE_TABLE(pci, id_table); | 3083 | MODULE_DEVICE_TABLE(pci, id_table); |
3083 | 3084 | ||
3084 | static struct pci_driver es1371_driver = { | 3085 | static struct pci_driver es1371_driver = { |
3085 | .name = "es1371", | 3086 | .name = "es1371", |
3086 | .id_table = id_table, | 3087 | .id_table = id_table, |
3087 | .probe = es1371_probe, | 3088 | .probe = es1371_probe, |
3088 | .remove = __devexit_p(es1371_remove), | 3089 | .remove = __devexit_p(es1371_remove), |
3089 | }; | 3090 | }; |
3090 | 3091 | ||
3091 | static int __init init_es1371(void) | 3092 | static int __init init_es1371(void) |
3092 | { | 3093 | { |
3093 | printk(KERN_INFO PFX "version v0.32 time " __TIME__ " " __DATE__ "\n"); | 3094 | printk(KERN_INFO PFX "version v0.32 time " __TIME__ " " __DATE__ "\n"); |
3094 | return pci_register_driver(&es1371_driver); | 3095 | return pci_register_driver(&es1371_driver); |
3095 | } | 3096 | } |
3096 | 3097 | ||
3097 | static void __exit cleanup_es1371(void) | 3098 | static void __exit cleanup_es1371(void) |
3098 | { | 3099 | { |
3099 | printk(KERN_INFO PFX "unloading\n"); | 3100 | printk(KERN_INFO PFX "unloading\n"); |
3100 | pci_unregister_driver(&es1371_driver); | 3101 | pci_unregister_driver(&es1371_driver); |
3101 | } | 3102 | } |
3102 | 3103 | ||
3103 | module_init(init_es1371); | 3104 | module_init(init_es1371); |
3104 | module_exit(cleanup_es1371); | 3105 | module_exit(cleanup_es1371); |
3105 | 3106 | ||
3106 | /* --------------------------------------------------------------------- */ | 3107 | /* --------------------------------------------------------------------- */ |
3107 | 3108 | ||
3108 | #ifndef MODULE | 3109 | #ifndef MODULE |
3109 | 3110 | ||
3110 | /* format is: es1371=[spdif,[nomix,[amplifier]]] */ | 3111 | /* format is: es1371=[spdif,[nomix,[amplifier]]] */ |
3111 | 3112 | ||
3112 | static int __init es1371_setup(char *str) | 3113 | static int __init es1371_setup(char *str) |
3113 | { | 3114 | { |
3114 | static unsigned __initdata nr_dev = 0; | 3115 | static unsigned __initdata nr_dev = 0; |
3115 | 3116 | ||
3116 | if (nr_dev >= NR_DEVICE) | 3117 | if (nr_dev >= NR_DEVICE) |
3117 | return 0; | 3118 | return 0; |
3118 | 3119 | ||
3119 | (void) | 3120 | (void) |
3120 | ((get_option(&str, &spdif[nr_dev]) == 2) | 3121 | ((get_option(&str, &spdif[nr_dev]) == 2) |
3121 | && (get_option(&str, &nomix[nr_dev]) == 2) | 3122 | && (get_option(&str, &nomix[nr_dev]) == 2) |
3122 | && (get_option(&str, &lifier[nr_dev]))); | 3123 | && (get_option(&str, &lifier[nr_dev]))); |
3123 | 3124 | ||
3124 | nr_dev++; | 3125 | nr_dev++; |
3125 | return 1; | 3126 | return 1; |
3126 | } | 3127 | } |
3127 | 3128 | ||
3128 | __setup("es1371=", es1371_setup); | 3129 | __setup("es1371=", es1371_setup); |
3129 | 3130 | ||
3130 | #endif /* MODULE */ | 3131 | #endif /* MODULE */ |
3131 | 3132 |
sound/oss/i810_audio.c
1 | /* | 1 | /* |
2 | * Intel i810 and friends ICH driver for Linux | 2 | * Intel i810 and friends ICH driver for Linux |
3 | * Alan Cox <alan@redhat.com> | 3 | * Alan Cox <alan@redhat.com> |
4 | * | 4 | * |
5 | * Built from: | 5 | * Built from: |
6 | * Low level code: Zach Brown (original nonworking i810 OSS driver) | 6 | * Low level code: Zach Brown (original nonworking i810 OSS driver) |
7 | * Jaroslav Kysela <perex@suse.cz> (working ALSA driver) | 7 | * Jaroslav Kysela <perex@suse.cz> (working ALSA driver) |
8 | * | 8 | * |
9 | * Framework: Thomas Sailer <sailer@ife.ee.ethz.ch> | 9 | * Framework: Thomas Sailer <sailer@ife.ee.ethz.ch> |
10 | * Extended by: Zach Brown <zab@redhat.com> | 10 | * Extended by: Zach Brown <zab@redhat.com> |
11 | * and others.. | 11 | * and others.. |
12 | * | 12 | * |
13 | * Hardware Provided By: | 13 | * Hardware Provided By: |
14 | * Analog Devices (A major AC97 codec maker) | 14 | * Analog Devices (A major AC97 codec maker) |
15 | * Intel Corp (you've probably heard of them already) | 15 | * Intel Corp (you've probably heard of them already) |
16 | * | 16 | * |
17 | * AC97 clues and assistance provided by | 17 | * AC97 clues and assistance provided by |
18 | * Analog Devices | 18 | * Analog Devices |
19 | * Zach 'Fufu' Brown | 19 | * Zach 'Fufu' Brown |
20 | * Jeff Garzik | 20 | * Jeff Garzik |
21 | * | 21 | * |
22 | * This program is free software; you can redistribute it and/or modify | 22 | * This program is free software; you can redistribute it and/or modify |
23 | * it under the terms of the GNU General Public License as published by | 23 | * it under the terms of the GNU General Public License as published by |
24 | * the Free Software Foundation; either version 2 of the License, or | 24 | * the Free Software Foundation; either version 2 of the License, or |
25 | * (at your option) any later version. | 25 | * (at your option) any later version. |
26 | * | 26 | * |
27 | * This program is distributed in the hope that it will be useful, | 27 | * This program is distributed in the hope that it will be useful, |
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
30 | * GNU General Public License for more details. | 30 | * GNU General Public License for more details. |
31 | * | 31 | * |
32 | * You should have received a copy of the GNU General Public License | 32 | * You should have received a copy of the GNU General Public License |
33 | * along with this program; if not, write to the Free Software | 33 | * along with this program; if not, write to the Free Software |
34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
35 | * | 35 | * |
36 | * | 36 | * |
37 | * Intel 810 theory of operation | 37 | * Intel 810 theory of operation |
38 | * | 38 | * |
39 | * The chipset provides three DMA channels that talk to an AC97 | 39 | * The chipset provides three DMA channels that talk to an AC97 |
40 | * CODEC (AC97 is a digital/analog mixer standard). At its simplest | 40 | * CODEC (AC97 is a digital/analog mixer standard). At its simplest |
41 | * you get 48Khz audio with basic volume and mixer controls. At the | 41 | * you get 48Khz audio with basic volume and mixer controls. At the |
42 | * best you get rate adaption in the codec. We set the card up so | 42 | * best you get rate adaption in the codec. We set the card up so |
43 | * that we never take completion interrupts but instead keep the card | 43 | * that we never take completion interrupts but instead keep the card |
44 | * chasing its tail around a ring buffer. This is needed for mmap | 44 | * chasing its tail around a ring buffer. This is needed for mmap |
45 | * mode audio and happens to work rather well for non-mmap modes too. | 45 | * mode audio and happens to work rather well for non-mmap modes too. |
46 | * | 46 | * |
47 | * The board has one output channel for PCM audio (supported) and | 47 | * The board has one output channel for PCM audio (supported) and |
48 | * a stereo line in and mono microphone input. Again these are normally | 48 | * a stereo line in and mono microphone input. Again these are normally |
49 | * locked to 48Khz only. Right now recording is not finished. | 49 | * locked to 48Khz only. Right now recording is not finished. |
50 | * | 50 | * |
51 | * There is no midi support, no synth support. Use timidity. To get | 51 | * There is no midi support, no synth support. Use timidity. To get |
52 | * esd working you need to use esd -r 48000 as it won't probe 48KHz | 52 | * esd working you need to use esd -r 48000 as it won't probe 48KHz |
53 | * by default. mpg123 can't handle 48Khz only audio so use xmms. | 53 | * by default. mpg123 can't handle 48Khz only audio so use xmms. |
54 | * | 54 | * |
55 | * Fix The Sound On Dell | 55 | * Fix The Sound On Dell |
56 | * | 56 | * |
57 | * Not everyone uses 48KHz. We know of no way to detect this reliably | 57 | * Not everyone uses 48KHz. We know of no way to detect this reliably |
58 | * and certainly not to get the right data. If your i810 audio sounds | 58 | * and certainly not to get the right data. If your i810 audio sounds |
59 | * stupid you may need to investigate other speeds. According to Analog | 59 | * stupid you may need to investigate other speeds. According to Analog |
60 | * they tend to use a 14.318MHz clock which gives you a base rate of | 60 | * they tend to use a 14.318MHz clock which gives you a base rate of |
61 | * 41194Hz. | 61 | * 41194Hz. |
62 | * | 62 | * |
63 | * This is available via the 'ftsodell=1' option. | 63 | * This is available via the 'ftsodell=1' option. |
64 | * | 64 | * |
65 | * If you need to force a specific rate set the clocking= option | 65 | * If you need to force a specific rate set the clocking= option |
66 | * | 66 | * |
67 | * This driver is cursed. (Ben LaHaise) | 67 | * This driver is cursed. (Ben LaHaise) |
68 | * | 68 | * |
69 | * ICH 3 caveats | 69 | * ICH 3 caveats |
70 | * Intel errata #7 for ICH3 IO. We need to disable SMI stuff | 70 | * Intel errata #7 for ICH3 IO. We need to disable SMI stuff |
71 | * when codec probing. [Not Yet Done] | 71 | * when codec probing. [Not Yet Done] |
72 | * | 72 | * |
73 | * ICH 4 caveats | 73 | * ICH 4 caveats |
74 | * | 74 | * |
75 | * The ICH4 has the feature, that the codec ID doesn't have to be | 75 | * The ICH4 has the feature, that the codec ID doesn't have to be |
76 | * congruent with the IO connection. | 76 | * congruent with the IO connection. |
77 | * | 77 | * |
78 | * Therefore, from driver version 0.23 on, there is a "codec ID" <-> | 78 | * Therefore, from driver version 0.23 on, there is a "codec ID" <-> |
79 | * "IO register base offset" mapping (card->ac97_id_map) field. | 79 | * "IO register base offset" mapping (card->ac97_id_map) field. |
80 | * | 80 | * |
81 | * Juergen "George" Sawinski (jsaw) | 81 | * Juergen "George" Sawinski (jsaw) |
82 | */ | 82 | */ |
83 | 83 | ||
84 | #include <linux/module.h> | 84 | #include <linux/module.h> |
85 | #include <linux/string.h> | 85 | #include <linux/string.h> |
86 | #include <linux/ctype.h> | 86 | #include <linux/ctype.h> |
87 | #include <linux/ioport.h> | 87 | #include <linux/ioport.h> |
88 | #include <linux/sched.h> | 88 | #include <linux/sched.h> |
89 | #include <linux/delay.h> | 89 | #include <linux/delay.h> |
90 | #include <linux/sound.h> | 90 | #include <linux/sound.h> |
91 | #include <linux/slab.h> | 91 | #include <linux/slab.h> |
92 | #include <linux/soundcard.h> | 92 | #include <linux/soundcard.h> |
93 | #include <linux/pci.h> | 93 | #include <linux/pci.h> |
94 | #include <linux/interrupt.h> | 94 | #include <linux/interrupt.h> |
95 | #include <asm/io.h> | 95 | #include <asm/io.h> |
96 | #include <asm/dma.h> | 96 | #include <asm/dma.h> |
97 | #include <linux/init.h> | 97 | #include <linux/init.h> |
98 | #include <linux/poll.h> | 98 | #include <linux/poll.h> |
99 | #include <linux/spinlock.h> | 99 | #include <linux/spinlock.h> |
100 | #include <linux/smp_lock.h> | 100 | #include <linux/smp_lock.h> |
101 | #include <linux/ac97_codec.h> | 101 | #include <linux/ac97_codec.h> |
102 | #include <linux/bitops.h> | 102 | #include <linux/bitops.h> |
103 | #include <linux/mutex.h> | 103 | #include <linux/mutex.h> |
104 | #include <linux/mm.h> | ||
104 | 105 | ||
105 | #include <asm/uaccess.h> | 106 | #include <asm/uaccess.h> |
106 | 107 | ||
107 | #define DRIVER_VERSION "1.01" | 108 | #define DRIVER_VERSION "1.01" |
108 | 109 | ||
109 | #define MODULOP2(a, b) ((a) & ((b) - 1)) | 110 | #define MODULOP2(a, b) ((a) & ((b) - 1)) |
110 | #define MASKP2(a, b) ((a) & ~((b) - 1)) | 111 | #define MASKP2(a, b) ((a) & ~((b) - 1)) |
111 | 112 | ||
112 | static int ftsodell; | 113 | static int ftsodell; |
113 | static int strict_clocking; | 114 | static int strict_clocking; |
114 | static unsigned int clocking; | 115 | static unsigned int clocking; |
115 | static int spdif_locked; | 116 | static int spdif_locked; |
116 | static int ac97_quirk = AC97_TUNE_DEFAULT; | 117 | static int ac97_quirk = AC97_TUNE_DEFAULT; |
117 | 118 | ||
118 | //#define DEBUG | 119 | //#define DEBUG |
119 | //#define DEBUG2 | 120 | //#define DEBUG2 |
120 | //#define DEBUG_INTERRUPTS | 121 | //#define DEBUG_INTERRUPTS |
121 | //#define DEBUG_MMAP | 122 | //#define DEBUG_MMAP |
122 | //#define DEBUG_MMIO | 123 | //#define DEBUG_MMIO |
123 | 124 | ||
124 | #define ADC_RUNNING 1 | 125 | #define ADC_RUNNING 1 |
125 | #define DAC_RUNNING 2 | 126 | #define DAC_RUNNING 2 |
126 | 127 | ||
127 | #define I810_FMT_16BIT 1 | 128 | #define I810_FMT_16BIT 1 |
128 | #define I810_FMT_STEREO 2 | 129 | #define I810_FMT_STEREO 2 |
129 | #define I810_FMT_MASK 3 | 130 | #define I810_FMT_MASK 3 |
130 | 131 | ||
131 | #define SPDIF_ON 0x0004 | 132 | #define SPDIF_ON 0x0004 |
132 | #define SURR_ON 0x0010 | 133 | #define SURR_ON 0x0010 |
133 | #define CENTER_LFE_ON 0x0020 | 134 | #define CENTER_LFE_ON 0x0020 |
134 | #define VOL_MUTED 0x8000 | 135 | #define VOL_MUTED 0x8000 |
135 | 136 | ||
136 | /* the 810's array of pointers to data buffers */ | 137 | /* the 810's array of pointers to data buffers */ |
137 | 138 | ||
138 | struct sg_item { | 139 | struct sg_item { |
139 | #define BUSADDR_MASK 0xFFFFFFFE | 140 | #define BUSADDR_MASK 0xFFFFFFFE |
140 | u32 busaddr; | 141 | u32 busaddr; |
141 | #define CON_IOC 0x80000000 /* interrupt on completion */ | 142 | #define CON_IOC 0x80000000 /* interrupt on completion */ |
142 | #define CON_BUFPAD 0x40000000 /* pad underrun with last sample, else 0 */ | 143 | #define CON_BUFPAD 0x40000000 /* pad underrun with last sample, else 0 */ |
143 | #define CON_BUFLEN_MASK 0x0000ffff /* buffer length in samples */ | 144 | #define CON_BUFLEN_MASK 0x0000ffff /* buffer length in samples */ |
144 | u32 control; | 145 | u32 control; |
145 | }; | 146 | }; |
146 | 147 | ||
147 | /* an instance of the i810 channel */ | 148 | /* an instance of the i810 channel */ |
148 | #define SG_LEN 32 | 149 | #define SG_LEN 32 |
149 | struct i810_channel | 150 | struct i810_channel |
150 | { | 151 | { |
151 | /* these sg guys should probably be allocated | 152 | /* these sg guys should probably be allocated |
152 | separately as nocache. Must be 8 byte aligned */ | 153 | separately as nocache. Must be 8 byte aligned */ |
153 | struct sg_item sg[SG_LEN]; /* 32*8 */ | 154 | struct sg_item sg[SG_LEN]; /* 32*8 */ |
154 | u32 offset; /* 4 */ | 155 | u32 offset; /* 4 */ |
155 | u32 port; /* 4 */ | 156 | u32 port; /* 4 */ |
156 | u32 used; | 157 | u32 used; |
157 | u32 num; | 158 | u32 num; |
158 | }; | 159 | }; |
159 | 160 | ||
160 | /* | 161 | /* |
161 | * we have 3 separate dma engines. pcm in, pcm out, and mic. | 162 | * we have 3 separate dma engines. pcm in, pcm out, and mic. |
162 | * each dma engine has controlling registers. These goofy | 163 | * each dma engine has controlling registers. These goofy |
163 | * names are from the datasheet, but make it easy to write | 164 | * names are from the datasheet, but make it easy to write |
164 | * code while leafing through it. | 165 | * code while leafing through it. |
165 | * | 166 | * |
166 | * ICH4 has 6 dma engines, pcm in, pcm out, mic, pcm in 2, | 167 | * ICH4 has 6 dma engines, pcm in, pcm out, mic, pcm in 2, |
167 | * mic in 2, s/pdif. Of special interest is the fact that | 168 | * mic in 2, s/pdif. Of special interest is the fact that |
168 | * the upper 3 DMA engines on the ICH4 *must* be accessed | 169 | * the upper 3 DMA engines on the ICH4 *must* be accessed |
169 | * via mmio access instead of pio access. | 170 | * via mmio access instead of pio access. |
170 | */ | 171 | */ |
171 | 172 | ||
172 | #define ENUM_ENGINE(PRE,DIG) \ | 173 | #define ENUM_ENGINE(PRE,DIG) \ |
173 | enum { \ | 174 | enum { \ |
174 | PRE##_BASE = 0x##DIG##0, /* Base Address */ \ | 175 | PRE##_BASE = 0x##DIG##0, /* Base Address */ \ |
175 | PRE##_BDBAR = 0x##DIG##0, /* Buffer Descriptor list Base Address */ \ | 176 | PRE##_BDBAR = 0x##DIG##0, /* Buffer Descriptor list Base Address */ \ |
176 | PRE##_CIV = 0x##DIG##4, /* Current Index Value */ \ | 177 | PRE##_CIV = 0x##DIG##4, /* Current Index Value */ \ |
177 | PRE##_LVI = 0x##DIG##5, /* Last Valid Index */ \ | 178 | PRE##_LVI = 0x##DIG##5, /* Last Valid Index */ \ |
178 | PRE##_SR = 0x##DIG##6, /* Status Register */ \ | 179 | PRE##_SR = 0x##DIG##6, /* Status Register */ \ |
179 | PRE##_PICB = 0x##DIG##8, /* Position In Current Buffer */ \ | 180 | PRE##_PICB = 0x##DIG##8, /* Position In Current Buffer */ \ |
180 | PRE##_PIV = 0x##DIG##a, /* Prefetched Index Value */ \ | 181 | PRE##_PIV = 0x##DIG##a, /* Prefetched Index Value */ \ |
181 | PRE##_CR = 0x##DIG##b /* Control Register */ \ | 182 | PRE##_CR = 0x##DIG##b /* Control Register */ \ |
182 | } | 183 | } |
183 | 184 | ||
184 | ENUM_ENGINE(OFF,0); /* Offsets */ | 185 | ENUM_ENGINE(OFF,0); /* Offsets */ |
185 | ENUM_ENGINE(PI,0); /* PCM In */ | 186 | ENUM_ENGINE(PI,0); /* PCM In */ |
186 | ENUM_ENGINE(PO,1); /* PCM Out */ | 187 | ENUM_ENGINE(PO,1); /* PCM Out */ |
187 | ENUM_ENGINE(MC,2); /* Mic In */ | 188 | ENUM_ENGINE(MC,2); /* Mic In */ |
188 | 189 | ||
189 | enum { | 190 | enum { |
190 | GLOB_CNT = 0x2c, /* Global Control */ | 191 | GLOB_CNT = 0x2c, /* Global Control */ |
191 | GLOB_STA = 0x30, /* Global Status */ | 192 | GLOB_STA = 0x30, /* Global Status */ |
192 | CAS = 0x34 /* Codec Write Semaphore Register */ | 193 | CAS = 0x34 /* Codec Write Semaphore Register */ |
193 | }; | 194 | }; |
194 | 195 | ||
195 | ENUM_ENGINE(MC2,4); /* Mic In 2 */ | 196 | ENUM_ENGINE(MC2,4); /* Mic In 2 */ |
196 | ENUM_ENGINE(PI2,5); /* PCM In 2 */ | 197 | ENUM_ENGINE(PI2,5); /* PCM In 2 */ |
197 | ENUM_ENGINE(SP,6); /* S/PDIF */ | 198 | ENUM_ENGINE(SP,6); /* S/PDIF */ |
198 | 199 | ||
199 | enum { | 200 | enum { |
200 | SDM = 0x80 /* SDATA_IN Map Register */ | 201 | SDM = 0x80 /* SDATA_IN Map Register */ |
201 | }; | 202 | }; |
202 | 203 | ||
203 | /* interrupts for a dma engine */ | 204 | /* interrupts for a dma engine */ |
204 | #define DMA_INT_FIFO (1<<4) /* fifo under/over flow */ | 205 | #define DMA_INT_FIFO (1<<4) /* fifo under/over flow */ |
205 | #define DMA_INT_COMPLETE (1<<3) /* buffer read/write complete and ioc set */ | 206 | #define DMA_INT_COMPLETE (1<<3) /* buffer read/write complete and ioc set */ |
206 | #define DMA_INT_LVI (1<<2) /* last valid done */ | 207 | #define DMA_INT_LVI (1<<2) /* last valid done */ |
207 | #define DMA_INT_CELV (1<<1) /* last valid is current */ | 208 | #define DMA_INT_CELV (1<<1) /* last valid is current */ |
208 | #define DMA_INT_DCH (1) /* DMA Controller Halted (happens on LVI interrupts) */ | 209 | #define DMA_INT_DCH (1) /* DMA Controller Halted (happens on LVI interrupts) */ |
209 | #define DMA_INT_MASK (DMA_INT_FIFO|DMA_INT_COMPLETE|DMA_INT_LVI) | 210 | #define DMA_INT_MASK (DMA_INT_FIFO|DMA_INT_COMPLETE|DMA_INT_LVI) |
210 | 211 | ||
211 | /* interrupts for the whole chip */ | 212 | /* interrupts for the whole chip */ |
212 | #define INT_SEC (1<<11) | 213 | #define INT_SEC (1<<11) |
213 | #define INT_PRI (1<<10) | 214 | #define INT_PRI (1<<10) |
214 | #define INT_MC (1<<7) | 215 | #define INT_MC (1<<7) |
215 | #define INT_PO (1<<6) | 216 | #define INT_PO (1<<6) |
216 | #define INT_PI (1<<5) | 217 | #define INT_PI (1<<5) |
217 | #define INT_MO (1<<2) | 218 | #define INT_MO (1<<2) |
218 | #define INT_NI (1<<1) | 219 | #define INT_NI (1<<1) |
219 | #define INT_GPI (1<<0) | 220 | #define INT_GPI (1<<0) |
220 | #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) | 221 | #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) |
221 | 222 | ||
222 | /* magic numbers to protect our data structures */ | 223 | /* magic numbers to protect our data structures */ |
223 | #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ | 224 | #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ |
224 | #define I810_STATE_MAGIC 0x63657373 /* "cess" */ | 225 | #define I810_STATE_MAGIC 0x63657373 /* "cess" */ |
225 | #define I810_DMA_MASK 0xffffffff /* DMA buffer mask for pci_alloc_consist */ | 226 | #define I810_DMA_MASK 0xffffffff /* DMA buffer mask for pci_alloc_consist */ |
226 | #define NR_HW_CH 3 | 227 | #define NR_HW_CH 3 |
227 | 228 | ||
228 | /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ | 229 | /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ |
229 | #define NR_AC97 4 | 230 | #define NR_AC97 4 |
230 | 231 | ||
231 | /* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit */ | 232 | /* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit */ |
232 | /* stream at a minimum for this card to be happy */ | 233 | /* stream at a minimum for this card to be happy */ |
233 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; | 234 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; |
234 | /* Samples are 16bit values, so we are shifting to a word, not to a byte, hence shift */ | 235 | /* Samples are 16bit values, so we are shifting to a word, not to a byte, hence shift */ |
235 | /* values are one less than might be expected */ | 236 | /* values are one less than might be expected */ |
236 | static const unsigned sample_shift[] = { -1, 0, 0, 1 }; | 237 | static const unsigned sample_shift[] = { -1, 0, 0, 1 }; |
237 | 238 | ||
238 | enum { | 239 | enum { |
239 | ICH82801AA = 0, | 240 | ICH82801AA = 0, |
240 | ICH82901AB, | 241 | ICH82901AB, |
241 | INTEL440MX, | 242 | INTEL440MX, |
242 | INTELICH2, | 243 | INTELICH2, |
243 | INTELICH3, | 244 | INTELICH3, |
244 | INTELICH4, | 245 | INTELICH4, |
245 | INTELICH5, | 246 | INTELICH5, |
246 | SI7012, | 247 | SI7012, |
247 | NVIDIA_NFORCE, | 248 | NVIDIA_NFORCE, |
248 | AMD768, | 249 | AMD768, |
249 | AMD8111 | 250 | AMD8111 |
250 | }; | 251 | }; |
251 | 252 | ||
252 | static char * card_names[] = { | 253 | static char * card_names[] = { |
253 | "Intel ICH 82801AA", | 254 | "Intel ICH 82801AA", |
254 | "Intel ICH 82901AB", | 255 | "Intel ICH 82901AB", |
255 | "Intel 440MX", | 256 | "Intel 440MX", |
256 | "Intel ICH2", | 257 | "Intel ICH2", |
257 | "Intel ICH3", | 258 | "Intel ICH3", |
258 | "Intel ICH4", | 259 | "Intel ICH4", |
259 | "Intel ICH5", | 260 | "Intel ICH5", |
260 | "SiS 7012", | 261 | "SiS 7012", |
261 | "NVIDIA nForce Audio", | 262 | "NVIDIA nForce Audio", |
262 | "AMD 768", | 263 | "AMD 768", |
263 | "AMD-8111 IOHub" | 264 | "AMD-8111 IOHub" |
264 | }; | 265 | }; |
265 | 266 | ||
266 | /* These are capabilities (and bugs) the chipsets _can_ have */ | 267 | /* These are capabilities (and bugs) the chipsets _can_ have */ |
267 | static struct { | 268 | static struct { |
268 | int16_t nr_ac97; | 269 | int16_t nr_ac97; |
269 | #define CAP_MMIO 0x0001 | 270 | #define CAP_MMIO 0x0001 |
270 | #define CAP_20BIT_AUDIO_SUPPORT 0x0002 | 271 | #define CAP_20BIT_AUDIO_SUPPORT 0x0002 |
271 | u_int16_t flags; | 272 | u_int16_t flags; |
272 | } card_cap[] = { | 273 | } card_cap[] = { |
273 | { 1, 0x0000 }, /* ICH82801AA */ | 274 | { 1, 0x0000 }, /* ICH82801AA */ |
274 | { 1, 0x0000 }, /* ICH82901AB */ | 275 | { 1, 0x0000 }, /* ICH82901AB */ |
275 | { 1, 0x0000 }, /* INTEL440MX */ | 276 | { 1, 0x0000 }, /* INTEL440MX */ |
276 | { 1, 0x0000 }, /* INTELICH2 */ | 277 | { 1, 0x0000 }, /* INTELICH2 */ |
277 | { 2, 0x0000 }, /* INTELICH3 */ | 278 | { 2, 0x0000 }, /* INTELICH3 */ |
278 | { 3, 0x0003 }, /* INTELICH4 */ | 279 | { 3, 0x0003 }, /* INTELICH4 */ |
279 | { 3, 0x0003 }, /* INTELICH5 */ | 280 | { 3, 0x0003 }, /* INTELICH5 */ |
280 | /*@FIXME to be verified*/ { 2, 0x0000 }, /* SI7012 */ | 281 | /*@FIXME to be verified*/ { 2, 0x0000 }, /* SI7012 */ |
281 | /*@FIXME to be verified*/ { 2, 0x0000 }, /* NVIDIA_NFORCE */ | 282 | /*@FIXME to be verified*/ { 2, 0x0000 }, /* NVIDIA_NFORCE */ |
282 | /*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD768 */ | 283 | /*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD768 */ |
283 | /*@FIXME to be verified*/ { 3, 0x0001 }, /* AMD8111 */ | 284 | /*@FIXME to be verified*/ { 3, 0x0001 }, /* AMD8111 */ |
284 | }; | 285 | }; |
285 | 286 | ||
286 | static struct pci_device_id i810_pci_tbl [] = { | 287 | static struct pci_device_id i810_pci_tbl [] = { |
287 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_5, | 288 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_5, |
288 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA}, | 289 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA}, |
289 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_5, | 290 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_5, |
290 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB}, | 291 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB}, |
291 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX, | 292 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX, |
292 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX}, | 293 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX}, |
293 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_4, | 294 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_4, |
294 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2}, | 295 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2}, |
295 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_5, | 296 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_5, |
296 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3}, | 297 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3}, |
297 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_5, | 298 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_5, |
298 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4}, | 299 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4}, |
299 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_5, | 300 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_5, |
300 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5}, | 301 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5}, |
301 | {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012, | 302 | {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012, |
302 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012}, | 303 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012}, |
303 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, | 304 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, |
304 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, | 305 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, |
305 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, | 306 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, |
306 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, | 307 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, |
307 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, | 308 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, |
308 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, | 309 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, |
309 | {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445, | 310 | {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445, |
310 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768}, | 311 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768}, |
311 | {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO, | 312 | {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO, |
312 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111}, | 313 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111}, |
313 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5, | 314 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5, |
314 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4}, | 315 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4}, |
315 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18, | 316 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18, |
316 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4}, | 317 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4}, |
317 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_AUDIO, | 318 | {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_AUDIO, |
318 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, | 319 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, |
319 | {0,} | 320 | {0,} |
320 | }; | 321 | }; |
321 | 322 | ||
322 | MODULE_DEVICE_TABLE (pci, i810_pci_tbl); | 323 | MODULE_DEVICE_TABLE (pci, i810_pci_tbl); |
323 | 324 | ||
324 | #ifdef CONFIG_PM | 325 | #ifdef CONFIG_PM |
325 | #define PM_SUSPENDED(card) (card->pm_suspended) | 326 | #define PM_SUSPENDED(card) (card->pm_suspended) |
326 | #else | 327 | #else |
327 | #define PM_SUSPENDED(card) (0) | 328 | #define PM_SUSPENDED(card) (0) |
328 | #endif | 329 | #endif |
329 | 330 | ||
330 | /* "software" or virtual channel, an instance of opened /dev/dsp */ | 331 | /* "software" or virtual channel, an instance of opened /dev/dsp */ |
331 | struct i810_state { | 332 | struct i810_state { |
332 | unsigned int magic; | 333 | unsigned int magic; |
333 | struct i810_card *card; /* Card info */ | 334 | struct i810_card *card; /* Card info */ |
334 | 335 | ||
335 | /* single open lock mechanism, only used for recording */ | 336 | /* single open lock mechanism, only used for recording */ |
336 | struct mutex open_mutex; | 337 | struct mutex open_mutex; |
337 | wait_queue_head_t open_wait; | 338 | wait_queue_head_t open_wait; |
338 | 339 | ||
339 | /* file mode */ | 340 | /* file mode */ |
340 | mode_t open_mode; | 341 | mode_t open_mode; |
341 | 342 | ||
342 | /* virtual channel number */ | 343 | /* virtual channel number */ |
343 | int virt; | 344 | int virt; |
344 | 345 | ||
345 | #ifdef CONFIG_PM | 346 | #ifdef CONFIG_PM |
346 | unsigned int pm_saved_dac_rate,pm_saved_adc_rate; | 347 | unsigned int pm_saved_dac_rate,pm_saved_adc_rate; |
347 | #endif | 348 | #endif |
348 | struct dmabuf { | 349 | struct dmabuf { |
349 | /* wave sample stuff */ | 350 | /* wave sample stuff */ |
350 | unsigned int rate; | 351 | unsigned int rate; |
351 | unsigned char fmt, enable, trigger; | 352 | unsigned char fmt, enable, trigger; |
352 | 353 | ||
353 | /* hardware channel */ | 354 | /* hardware channel */ |
354 | struct i810_channel *read_channel; | 355 | struct i810_channel *read_channel; |
355 | struct i810_channel *write_channel; | 356 | struct i810_channel *write_channel; |
356 | 357 | ||
357 | /* OSS buffer management stuff */ | 358 | /* OSS buffer management stuff */ |
358 | void *rawbuf; | 359 | void *rawbuf; |
359 | dma_addr_t dma_handle; | 360 | dma_addr_t dma_handle; |
360 | unsigned buforder; | 361 | unsigned buforder; |
361 | unsigned numfrag; | 362 | unsigned numfrag; |
362 | unsigned fragshift; | 363 | unsigned fragshift; |
363 | 364 | ||
364 | /* our buffer acts like a circular ring */ | 365 | /* our buffer acts like a circular ring */ |
365 | unsigned hwptr; /* where dma last started, updated by update_ptr */ | 366 | unsigned hwptr; /* where dma last started, updated by update_ptr */ |
366 | unsigned swptr; /* where driver last clear/filled, updated by read/write */ | 367 | unsigned swptr; /* where driver last clear/filled, updated by read/write */ |
367 | int count; /* bytes to be consumed or been generated by dma machine */ | 368 | int count; /* bytes to be consumed or been generated by dma machine */ |
368 | unsigned total_bytes; /* total bytes dmaed by hardware */ | 369 | unsigned total_bytes; /* total bytes dmaed by hardware */ |
369 | 370 | ||
370 | unsigned error; /* number of over/underruns */ | 371 | unsigned error; /* number of over/underruns */ |
371 | wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */ | 372 | wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */ |
372 | 373 | ||
373 | /* redundant, but makes calculations easier */ | 374 | /* redundant, but makes calculations easier */ |
374 | /* what the hardware uses */ | 375 | /* what the hardware uses */ |
375 | unsigned dmasize; | 376 | unsigned dmasize; |
376 | unsigned fragsize; | 377 | unsigned fragsize; |
377 | unsigned fragsamples; | 378 | unsigned fragsamples; |
378 | 379 | ||
379 | /* what we tell the user to expect */ | 380 | /* what we tell the user to expect */ |
380 | unsigned userfrags; | 381 | unsigned userfrags; |
381 | unsigned userfragsize; | 382 | unsigned userfragsize; |
382 | 383 | ||
383 | /* OSS stuff */ | 384 | /* OSS stuff */ |
384 | unsigned mapped:1; | 385 | unsigned mapped:1; |
385 | unsigned ready:1; | 386 | unsigned ready:1; |
386 | unsigned update_flag; | 387 | unsigned update_flag; |
387 | unsigned ossfragsize; | 388 | unsigned ossfragsize; |
388 | unsigned ossmaxfrags; | 389 | unsigned ossmaxfrags; |
389 | unsigned subdivision; | 390 | unsigned subdivision; |
390 | } dmabuf; | 391 | } dmabuf; |
391 | }; | 392 | }; |
392 | 393 | ||
393 | 394 | ||
394 | struct i810_card { | 395 | struct i810_card { |
395 | unsigned int magic; | 396 | unsigned int magic; |
396 | 397 | ||
397 | /* We keep i810 cards in a linked list */ | 398 | /* We keep i810 cards in a linked list */ |
398 | struct i810_card *next; | 399 | struct i810_card *next; |
399 | 400 | ||
400 | /* The i810 has a certain amount of cross channel interaction | 401 | /* The i810 has a certain amount of cross channel interaction |
401 | so we use a single per card lock */ | 402 | so we use a single per card lock */ |
402 | spinlock_t lock; | 403 | spinlock_t lock; |
403 | 404 | ||
404 | /* Control AC97 access serialization */ | 405 | /* Control AC97 access serialization */ |
405 | spinlock_t ac97_lock; | 406 | spinlock_t ac97_lock; |
406 | 407 | ||
407 | /* PCI device stuff */ | 408 | /* PCI device stuff */ |
408 | struct pci_dev * pci_dev; | 409 | struct pci_dev * pci_dev; |
409 | u16 pci_id; | 410 | u16 pci_id; |
410 | u16 pci_id_internal; /* used to access card_cap[] */ | 411 | u16 pci_id_internal; /* used to access card_cap[] */ |
411 | #ifdef CONFIG_PM | 412 | #ifdef CONFIG_PM |
412 | u16 pm_suspended; | 413 | u16 pm_suspended; |
413 | int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97]; | 414 | int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97]; |
414 | #endif | 415 | #endif |
415 | /* soundcore stuff */ | 416 | /* soundcore stuff */ |
416 | int dev_audio; | 417 | int dev_audio; |
417 | 418 | ||
418 | /* structures for abstraction of hardware facilities, codecs, banks and channels*/ | 419 | /* structures for abstraction of hardware facilities, codecs, banks and channels*/ |
419 | u16 ac97_id_map[NR_AC97]; | 420 | u16 ac97_id_map[NR_AC97]; |
420 | struct ac97_codec *ac97_codec[NR_AC97]; | 421 | struct ac97_codec *ac97_codec[NR_AC97]; |
421 | struct i810_state *states[NR_HW_CH]; | 422 | struct i810_state *states[NR_HW_CH]; |
422 | struct i810_channel *channel; /* 1:1 to states[] but diff. lifetime */ | 423 | struct i810_channel *channel; /* 1:1 to states[] but diff. lifetime */ |
423 | dma_addr_t chandma; | 424 | dma_addr_t chandma; |
424 | 425 | ||
425 | u16 ac97_features; | 426 | u16 ac97_features; |
426 | u16 ac97_status; | 427 | u16 ac97_status; |
427 | u16 channels; | 428 | u16 channels; |
428 | 429 | ||
429 | /* hardware resources */ | 430 | /* hardware resources */ |
430 | unsigned long ac97base; | 431 | unsigned long ac97base; |
431 | unsigned long iobase; | 432 | unsigned long iobase; |
432 | u32 irq; | 433 | u32 irq; |
433 | 434 | ||
434 | unsigned long ac97base_mmio_phys; | 435 | unsigned long ac97base_mmio_phys; |
435 | unsigned long iobase_mmio_phys; | 436 | unsigned long iobase_mmio_phys; |
436 | u_int8_t __iomem *ac97base_mmio; | 437 | u_int8_t __iomem *ac97base_mmio; |
437 | u_int8_t __iomem *iobase_mmio; | 438 | u_int8_t __iomem *iobase_mmio; |
438 | 439 | ||
439 | int use_mmio; | 440 | int use_mmio; |
440 | 441 | ||
441 | /* Function support */ | 442 | /* Function support */ |
442 | struct i810_channel *(*alloc_pcm_channel)(struct i810_card *); | 443 | struct i810_channel *(*alloc_pcm_channel)(struct i810_card *); |
443 | struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *); | 444 | struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *); |
444 | struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *); | 445 | struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *); |
445 | void (*free_pcm_channel)(struct i810_card *, int chan); | 446 | void (*free_pcm_channel)(struct i810_card *, int chan); |
446 | 447 | ||
447 | /* We have a *very* long init time possibly, so use this to block */ | 448 | /* We have a *very* long init time possibly, so use this to block */ |
448 | /* attempts to open our devices before we are ready (stops oops'es) */ | 449 | /* attempts to open our devices before we are ready (stops oops'es) */ |
449 | int initializing; | 450 | int initializing; |
450 | }; | 451 | }; |
451 | 452 | ||
452 | /* extract register offset from codec struct */ | 453 | /* extract register offset from codec struct */ |
453 | #define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id]) | 454 | #define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id]) |
454 | 455 | ||
455 | #define I810_IOREAD(size, type, card, off) \ | 456 | #define I810_IOREAD(size, type, card, off) \ |
456 | ({ \ | 457 | ({ \ |
457 | type val; \ | 458 | type val; \ |
458 | if (card->use_mmio) \ | 459 | if (card->use_mmio) \ |
459 | val=read##size(card->iobase_mmio+off); \ | 460 | val=read##size(card->iobase_mmio+off); \ |
460 | else \ | 461 | else \ |
461 | val=in##size(card->iobase+off); \ | 462 | val=in##size(card->iobase+off); \ |
462 | val; \ | 463 | val; \ |
463 | }) | 464 | }) |
464 | 465 | ||
465 | #define I810_IOREADL(card, off) I810_IOREAD(l, u32, card, off) | 466 | #define I810_IOREADL(card, off) I810_IOREAD(l, u32, card, off) |
466 | #define I810_IOREADW(card, off) I810_IOREAD(w, u16, card, off) | 467 | #define I810_IOREADW(card, off) I810_IOREAD(w, u16, card, off) |
467 | #define I810_IOREADB(card, off) I810_IOREAD(b, u8, card, off) | 468 | #define I810_IOREADB(card, off) I810_IOREAD(b, u8, card, off) |
468 | 469 | ||
469 | #define I810_IOWRITE(size, val, card, off) \ | 470 | #define I810_IOWRITE(size, val, card, off) \ |
470 | ({ \ | 471 | ({ \ |
471 | if (card->use_mmio) \ | 472 | if (card->use_mmio) \ |
472 | write##size(val, card->iobase_mmio+off); \ | 473 | write##size(val, card->iobase_mmio+off); \ |
473 | else \ | 474 | else \ |
474 | out##size(val, card->iobase+off); \ | 475 | out##size(val, card->iobase+off); \ |
475 | }) | 476 | }) |
476 | 477 | ||
477 | #define I810_IOWRITEL(val, card, off) I810_IOWRITE(l, val, card, off) | 478 | #define I810_IOWRITEL(val, card, off) I810_IOWRITE(l, val, card, off) |
478 | #define I810_IOWRITEW(val, card, off) I810_IOWRITE(w, val, card, off) | 479 | #define I810_IOWRITEW(val, card, off) I810_IOWRITE(w, val, card, off) |
479 | #define I810_IOWRITEB(val, card, off) I810_IOWRITE(b, val, card, off) | 480 | #define I810_IOWRITEB(val, card, off) I810_IOWRITE(b, val, card, off) |
480 | 481 | ||
481 | #define GET_CIV(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_CIV), SG_LEN) | 482 | #define GET_CIV(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_CIV), SG_LEN) |
482 | #define GET_LVI(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_LVI), SG_LEN) | 483 | #define GET_LVI(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_LVI), SG_LEN) |
483 | 484 | ||
484 | /* set LVI from CIV */ | 485 | /* set LVI from CIV */ |
485 | #define CIV_TO_LVI(card, port, off) \ | 486 | #define CIV_TO_LVI(card, port, off) \ |
486 | I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI) | 487 | I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI) |
487 | 488 | ||
488 | static struct ac97_quirk ac97_quirks[] __devinitdata = { | 489 | static struct ac97_quirk ac97_quirks[] __devinitdata = { |
489 | { | 490 | { |
490 | .vendor = 0x0e11, | 491 | .vendor = 0x0e11, |
491 | .device = 0x00b8, | 492 | .device = 0x00b8, |
492 | .name = "Compaq Evo D510C", | 493 | .name = "Compaq Evo D510C", |
493 | .type = AC97_TUNE_HP_ONLY | 494 | .type = AC97_TUNE_HP_ONLY |
494 | }, | 495 | }, |
495 | { | 496 | { |
496 | .vendor = 0x1028, | 497 | .vendor = 0x1028, |
497 | .device = 0x00d8, | 498 | .device = 0x00d8, |
498 | .name = "Dell Precision 530", /* AD1885 */ | 499 | .name = "Dell Precision 530", /* AD1885 */ |
499 | .type = AC97_TUNE_HP_ONLY | 500 | .type = AC97_TUNE_HP_ONLY |
500 | }, | 501 | }, |
501 | { | 502 | { |
502 | .vendor = 0x1028, | 503 | .vendor = 0x1028, |
503 | .device = 0x0126, | 504 | .device = 0x0126, |
504 | .name = "Dell Optiplex GX260", /* AD1981A */ | 505 | .name = "Dell Optiplex GX260", /* AD1981A */ |
505 | .type = AC97_TUNE_HP_ONLY | 506 | .type = AC97_TUNE_HP_ONLY |
506 | }, | 507 | }, |
507 | { | 508 | { |
508 | .vendor = 0x1028, | 509 | .vendor = 0x1028, |
509 | .device = 0x012d, | 510 | .device = 0x012d, |
510 | .name = "Dell Precision 450", /* AD1981B*/ | 511 | .name = "Dell Precision 450", /* AD1981B*/ |
511 | .type = AC97_TUNE_HP_ONLY | 512 | .type = AC97_TUNE_HP_ONLY |
512 | }, | 513 | }, |
513 | { /* FIXME: which codec? */ | 514 | { /* FIXME: which codec? */ |
514 | .vendor = 0x103c, | 515 | .vendor = 0x103c, |
515 | .device = 0x00c3, | 516 | .device = 0x00c3, |
516 | .name = "Hewlett-Packard onboard", | 517 | .name = "Hewlett-Packard onboard", |
517 | .type = AC97_TUNE_HP_ONLY | 518 | .type = AC97_TUNE_HP_ONLY |
518 | }, | 519 | }, |
519 | { | 520 | { |
520 | .vendor = 0x103c, | 521 | .vendor = 0x103c, |
521 | .device = 0x12f1, | 522 | .device = 0x12f1, |
522 | .name = "HP xw8200", /* AD1981B*/ | 523 | .name = "HP xw8200", /* AD1981B*/ |
523 | .type = AC97_TUNE_HP_ONLY | 524 | .type = AC97_TUNE_HP_ONLY |
524 | }, | 525 | }, |
525 | { | 526 | { |
526 | .vendor = 0x103c, | 527 | .vendor = 0x103c, |
527 | .device = 0x3008, | 528 | .device = 0x3008, |
528 | .name = "HP xw4200", /* AD1981B*/ | 529 | .name = "HP xw4200", /* AD1981B*/ |
529 | .type = AC97_TUNE_HP_ONLY | 530 | .type = AC97_TUNE_HP_ONLY |
530 | }, | 531 | }, |
531 | { | 532 | { |
532 | .vendor = 0x10f1, | 533 | .vendor = 0x10f1, |
533 | .device = 0x2665, | 534 | .device = 0x2665, |
534 | .name = "Fujitsu-Siemens Celsius", /* AD1981? */ | 535 | .name = "Fujitsu-Siemens Celsius", /* AD1981? */ |
535 | .type = AC97_TUNE_HP_ONLY | 536 | .type = AC97_TUNE_HP_ONLY |
536 | }, | 537 | }, |
537 | { | 538 | { |
538 | .vendor = 0x10f1, | 539 | .vendor = 0x10f1, |
539 | .device = 0x2885, | 540 | .device = 0x2885, |
540 | .name = "AMD64 Mobo", /* ALC650 */ | 541 | .name = "AMD64 Mobo", /* ALC650 */ |
541 | .type = AC97_TUNE_HP_ONLY | 542 | .type = AC97_TUNE_HP_ONLY |
542 | }, | 543 | }, |
543 | { | 544 | { |
544 | .vendor = 0x110a, | 545 | .vendor = 0x110a, |
545 | .device = 0x0056, | 546 | .device = 0x0056, |
546 | .name = "Fujitsu-Siemens Scenic", /* AD1981? */ | 547 | .name = "Fujitsu-Siemens Scenic", /* AD1981? */ |
547 | .type = AC97_TUNE_HP_ONLY | 548 | .type = AC97_TUNE_HP_ONLY |
548 | }, | 549 | }, |
549 | { | 550 | { |
550 | .vendor = 0x11d4, | 551 | .vendor = 0x11d4, |
551 | .device = 0x5375, | 552 | .device = 0x5375, |
552 | .name = "ADI AD1985 (discrete)", | 553 | .name = "ADI AD1985 (discrete)", |
553 | .type = AC97_TUNE_HP_ONLY | 554 | .type = AC97_TUNE_HP_ONLY |
554 | }, | 555 | }, |
555 | { | 556 | { |
556 | .vendor = 0x1462, | 557 | .vendor = 0x1462, |
557 | .device = 0x5470, | 558 | .device = 0x5470, |
558 | .name = "MSI P4 ATX 645 Ultra", | 559 | .name = "MSI P4 ATX 645 Ultra", |
559 | .type = AC97_TUNE_HP_ONLY | 560 | .type = AC97_TUNE_HP_ONLY |
560 | }, | 561 | }, |
561 | { | 562 | { |
562 | .vendor = 0x1734, | 563 | .vendor = 0x1734, |
563 | .device = 0x0088, | 564 | .device = 0x0088, |
564 | .name = "Fujitsu-Siemens D1522", /* AD1981 */ | 565 | .name = "Fujitsu-Siemens D1522", /* AD1981 */ |
565 | .type = AC97_TUNE_HP_ONLY | 566 | .type = AC97_TUNE_HP_ONLY |
566 | }, | 567 | }, |
567 | { | 568 | { |
568 | .vendor = 0x8086, | 569 | .vendor = 0x8086, |
569 | .device = 0x4856, | 570 | .device = 0x4856, |
570 | .name = "Intel D845WN (82801BA)", | 571 | .name = "Intel D845WN (82801BA)", |
571 | .type = AC97_TUNE_SWAP_HP | 572 | .type = AC97_TUNE_SWAP_HP |
572 | }, | 573 | }, |
573 | { | 574 | { |
574 | .vendor = 0x8086, | 575 | .vendor = 0x8086, |
575 | .device = 0x4d44, | 576 | .device = 0x4d44, |
576 | .name = "Intel D850EMV2", /* AD1885 */ | 577 | .name = "Intel D850EMV2", /* AD1885 */ |
577 | .type = AC97_TUNE_HP_ONLY | 578 | .type = AC97_TUNE_HP_ONLY |
578 | }, | 579 | }, |
579 | { | 580 | { |
580 | .vendor = 0x8086, | 581 | .vendor = 0x8086, |
581 | .device = 0x4d56, | 582 | .device = 0x4d56, |
582 | .name = "Intel ICH/AD1885", | 583 | .name = "Intel ICH/AD1885", |
583 | .type = AC97_TUNE_HP_ONLY | 584 | .type = AC97_TUNE_HP_ONLY |
584 | }, | 585 | }, |
585 | { | 586 | { |
586 | .vendor = 0x1028, | 587 | .vendor = 0x1028, |
587 | .device = 0x012d, | 588 | .device = 0x012d, |
588 | .name = "Dell Precision 450", /* AD1981B*/ | 589 | .name = "Dell Precision 450", /* AD1981B*/ |
589 | .type = AC97_TUNE_HP_ONLY | 590 | .type = AC97_TUNE_HP_ONLY |
590 | }, | 591 | }, |
591 | { | 592 | { |
592 | .vendor = 0x103c, | 593 | .vendor = 0x103c, |
593 | .device = 0x3008, | 594 | .device = 0x3008, |
594 | .name = "HP xw4200", /* AD1981B*/ | 595 | .name = "HP xw4200", /* AD1981B*/ |
595 | .type = AC97_TUNE_HP_ONLY | 596 | .type = AC97_TUNE_HP_ONLY |
596 | }, | 597 | }, |
597 | { | 598 | { |
598 | .vendor = 0x103c, | 599 | .vendor = 0x103c, |
599 | .device = 0x12f1, | 600 | .device = 0x12f1, |
600 | .name = "HP xw8200", /* AD1981B*/ | 601 | .name = "HP xw8200", /* AD1981B*/ |
601 | .type = AC97_TUNE_HP_ONLY | 602 | .type = AC97_TUNE_HP_ONLY |
602 | }, | 603 | }, |
603 | { } /* terminator */ | 604 | { } /* terminator */ |
604 | }; | 605 | }; |
605 | 606 | ||
606 | static struct i810_card *devs = NULL; | 607 | static struct i810_card *devs = NULL; |
607 | 608 | ||
608 | static int i810_open_mixdev(struct inode *inode, struct file *file); | 609 | static int i810_open_mixdev(struct inode *inode, struct file *file); |
609 | static int i810_ioctl_mixdev(struct inode *inode, struct file *file, | 610 | static int i810_ioctl_mixdev(struct inode *inode, struct file *file, |
610 | unsigned int cmd, unsigned long arg); | 611 | unsigned int cmd, unsigned long arg); |
611 | static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg); | 612 | static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg); |
612 | static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data); | 613 | static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data); |
613 | static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg); | 614 | static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg); |
614 | static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data); | 615 | static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data); |
615 | static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg); | 616 | static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg); |
616 | static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data); | 617 | static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data); |
617 | 618 | ||
618 | static struct i810_channel *i810_alloc_pcm_channel(struct i810_card *card) | 619 | static struct i810_channel *i810_alloc_pcm_channel(struct i810_card *card) |
619 | { | 620 | { |
620 | if(card->channel[1].used==1) | 621 | if(card->channel[1].used==1) |
621 | return NULL; | 622 | return NULL; |
622 | card->channel[1].used=1; | 623 | card->channel[1].used=1; |
623 | return &card->channel[1]; | 624 | return &card->channel[1]; |
624 | } | 625 | } |
625 | 626 | ||
626 | static struct i810_channel *i810_alloc_rec_pcm_channel(struct i810_card *card) | 627 | static struct i810_channel *i810_alloc_rec_pcm_channel(struct i810_card *card) |
627 | { | 628 | { |
628 | if(card->channel[0].used==1) | 629 | if(card->channel[0].used==1) |
629 | return NULL; | 630 | return NULL; |
630 | card->channel[0].used=1; | 631 | card->channel[0].used=1; |
631 | return &card->channel[0]; | 632 | return &card->channel[0]; |
632 | } | 633 | } |
633 | 634 | ||
634 | static struct i810_channel *i810_alloc_rec_mic_channel(struct i810_card *card) | 635 | static struct i810_channel *i810_alloc_rec_mic_channel(struct i810_card *card) |
635 | { | 636 | { |
636 | if(card->channel[2].used==1) | 637 | if(card->channel[2].used==1) |
637 | return NULL; | 638 | return NULL; |
638 | card->channel[2].used=1; | 639 | card->channel[2].used=1; |
639 | return &card->channel[2]; | 640 | return &card->channel[2]; |
640 | } | 641 | } |
641 | 642 | ||
642 | static void i810_free_pcm_channel(struct i810_card *card, int channel) | 643 | static void i810_free_pcm_channel(struct i810_card *card, int channel) |
643 | { | 644 | { |
644 | card->channel[channel].used=0; | 645 | card->channel[channel].used=0; |
645 | } | 646 | } |
646 | 647 | ||
647 | static int i810_valid_spdif_rate ( struct ac97_codec *codec, int rate ) | 648 | static int i810_valid_spdif_rate ( struct ac97_codec *codec, int rate ) |
648 | { | 649 | { |
649 | unsigned long id = 0L; | 650 | unsigned long id = 0L; |
650 | 651 | ||
651 | id = (i810_ac97_get(codec, AC97_VENDOR_ID1) << 16); | 652 | id = (i810_ac97_get(codec, AC97_VENDOR_ID1) << 16); |
652 | id |= i810_ac97_get(codec, AC97_VENDOR_ID2) & 0xffff; | 653 | id |= i810_ac97_get(codec, AC97_VENDOR_ID2) & 0xffff; |
653 | #ifdef DEBUG | 654 | #ifdef DEBUG |
654 | printk ( "i810_audio: codec = %s, codec_id = 0x%08lx\n", codec->name, id); | 655 | printk ( "i810_audio: codec = %s, codec_id = 0x%08lx\n", codec->name, id); |
655 | #endif | 656 | #endif |
656 | switch ( id ) { | 657 | switch ( id ) { |
657 | case 0x41445361: /* AD1886 */ | 658 | case 0x41445361: /* AD1886 */ |
658 | if (rate == 48000) { | 659 | if (rate == 48000) { |
659 | return 1; | 660 | return 1; |
660 | } | 661 | } |
661 | break; | 662 | break; |
662 | default: /* all other codecs, until we know otherwiae */ | 663 | default: /* all other codecs, until we know otherwiae */ |
663 | if (rate == 48000 || rate == 44100 || rate == 32000) { | 664 | if (rate == 48000 || rate == 44100 || rate == 32000) { |
664 | return 1; | 665 | return 1; |
665 | } | 666 | } |
666 | break; | 667 | break; |
667 | } | 668 | } |
668 | return (0); | 669 | return (0); |
669 | } | 670 | } |
670 | 671 | ||
671 | /* i810_set_spdif_output | 672 | /* i810_set_spdif_output |
672 | * | 673 | * |
673 | * Configure the S/PDIF output transmitter. When we turn on | 674 | * Configure the S/PDIF output transmitter. When we turn on |
674 | * S/PDIF, we turn off the analog output. This may not be | 675 | * S/PDIF, we turn off the analog output. This may not be |
675 | * the right thing to do. | 676 | * the right thing to do. |
676 | * | 677 | * |
677 | * Assumptions: | 678 | * Assumptions: |
678 | * The DSP sample rate must already be set to a supported | 679 | * The DSP sample rate must already be set to a supported |
679 | * S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort. | 680 | * S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort. |
680 | */ | 681 | */ |
681 | static int i810_set_spdif_output(struct i810_state *state, int slots, int rate) | 682 | static int i810_set_spdif_output(struct i810_state *state, int slots, int rate) |
682 | { | 683 | { |
683 | int vol; | 684 | int vol; |
684 | int aud_reg; | 685 | int aud_reg; |
685 | int r = 0; | 686 | int r = 0; |
686 | struct ac97_codec *codec = state->card->ac97_codec[0]; | 687 | struct ac97_codec *codec = state->card->ac97_codec[0]; |
687 | 688 | ||
688 | if(!codec->codec_ops->digital) { | 689 | if(!codec->codec_ops->digital) { |
689 | state->card->ac97_status &= ~SPDIF_ON; | 690 | state->card->ac97_status &= ~SPDIF_ON; |
690 | } else { | 691 | } else { |
691 | if ( slots == -1 ) { /* Turn off S/PDIF */ | 692 | if ( slots == -1 ) { /* Turn off S/PDIF */ |
692 | codec->codec_ops->digital(codec, 0, 0, 0); | 693 | codec->codec_ops->digital(codec, 0, 0, 0); |
693 | /* If the volume wasn't muted before we turned on S/PDIF, unmute it */ | 694 | /* If the volume wasn't muted before we turned on S/PDIF, unmute it */ |
694 | if ( !(state->card->ac97_status & VOL_MUTED) ) { | 695 | if ( !(state->card->ac97_status & VOL_MUTED) ) { |
695 | aud_reg = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO); | 696 | aud_reg = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO); |
696 | i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (aud_reg & ~VOL_MUTED)); | 697 | i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (aud_reg & ~VOL_MUTED)); |
697 | } | 698 | } |
698 | state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON); | 699 | state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON); |
699 | return 0; | 700 | return 0; |
700 | } | 701 | } |
701 | 702 | ||
702 | vol = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO); | 703 | vol = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO); |
703 | state->card->ac97_status = vol & VOL_MUTED; | 704 | state->card->ac97_status = vol & VOL_MUTED; |
704 | 705 | ||
705 | r = codec->codec_ops->digital(codec, slots, rate, 0); | 706 | r = codec->codec_ops->digital(codec, slots, rate, 0); |
706 | 707 | ||
707 | if(r) | 708 | if(r) |
708 | state->card->ac97_status |= SPDIF_ON; | 709 | state->card->ac97_status |= SPDIF_ON; |
709 | else | 710 | else |
710 | state->card->ac97_status &= ~SPDIF_ON; | 711 | state->card->ac97_status &= ~SPDIF_ON; |
711 | 712 | ||
712 | /* Mute the analog output */ | 713 | /* Mute the analog output */ |
713 | /* Should this only mute the PCM volume??? */ | 714 | /* Should this only mute the PCM volume??? */ |
714 | i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (vol | VOL_MUTED)); | 715 | i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (vol | VOL_MUTED)); |
715 | } | 716 | } |
716 | return r; | 717 | return r; |
717 | } | 718 | } |
718 | 719 | ||
719 | /* i810_set_dac_channels | 720 | /* i810_set_dac_channels |
720 | * | 721 | * |
721 | * Configure the codec's multi-channel DACs | 722 | * Configure the codec's multi-channel DACs |
722 | * | 723 | * |
723 | * The logic is backwards. Setting the bit to 1 turns off the DAC. | 724 | * The logic is backwards. Setting the bit to 1 turns off the DAC. |
724 | * | 725 | * |
725 | * What about the ICH? We currently configure it using the | 726 | * What about the ICH? We currently configure it using the |
726 | * SNDCTL_DSP_CHANNELS ioctl. If we're turnning on the DAC, | 727 | * SNDCTL_DSP_CHANNELS ioctl. If we're turnning on the DAC, |
727 | * does that imply that we want the ICH set to support | 728 | * does that imply that we want the ICH set to support |
728 | * these channels? | 729 | * these channels? |
729 | * | 730 | * |
730 | * TODO: | 731 | * TODO: |
731 | * vailidate that the codec really supports these DACs | 732 | * vailidate that the codec really supports these DACs |
732 | * before turning them on. | 733 | * before turning them on. |
733 | */ | 734 | */ |
734 | static void i810_set_dac_channels(struct i810_state *state, int channel) | 735 | static void i810_set_dac_channels(struct i810_state *state, int channel) |
735 | { | 736 | { |
736 | int aud_reg; | 737 | int aud_reg; |
737 | struct ac97_codec *codec = state->card->ac97_codec[0]; | 738 | struct ac97_codec *codec = state->card->ac97_codec[0]; |
738 | 739 | ||
739 | /* No codec, no setup */ | 740 | /* No codec, no setup */ |
740 | 741 | ||
741 | if(codec == NULL) | 742 | if(codec == NULL) |
742 | return; | 743 | return; |
743 | 744 | ||
744 | aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS); | 745 | aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS); |
745 | aud_reg |= AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK; | 746 | aud_reg |= AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK; |
746 | state->card->ac97_status &= ~(SURR_ON | CENTER_LFE_ON); | 747 | state->card->ac97_status &= ~(SURR_ON | CENTER_LFE_ON); |
747 | 748 | ||
748 | switch ( channel ) { | 749 | switch ( channel ) { |
749 | case 2: /* always enabled */ | 750 | case 2: /* always enabled */ |
750 | break; | 751 | break; |
751 | case 4: | 752 | case 4: |
752 | aud_reg &= ~AC97_EA_PRJ; | 753 | aud_reg &= ~AC97_EA_PRJ; |
753 | state->card->ac97_status |= SURR_ON; | 754 | state->card->ac97_status |= SURR_ON; |
754 | break; | 755 | break; |
755 | case 6: | 756 | case 6: |
756 | aud_reg &= ~(AC97_EA_PRJ | AC97_EA_PRI | AC97_EA_PRK); | 757 | aud_reg &= ~(AC97_EA_PRJ | AC97_EA_PRI | AC97_EA_PRK); |
757 | state->card->ac97_status |= SURR_ON | CENTER_LFE_ON; | 758 | state->card->ac97_status |= SURR_ON | CENTER_LFE_ON; |
758 | break; | 759 | break; |
759 | default: | 760 | default: |
760 | break; | 761 | break; |
761 | } | 762 | } |
762 | i810_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg); | 763 | i810_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg); |
763 | 764 | ||
764 | } | 765 | } |
765 | 766 | ||
766 | 767 | ||
767 | /* set playback sample rate */ | 768 | /* set playback sample rate */ |
768 | static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int rate) | 769 | static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int rate) |
769 | { | 770 | { |
770 | struct dmabuf *dmabuf = &state->dmabuf; | 771 | struct dmabuf *dmabuf = &state->dmabuf; |
771 | u32 new_rate; | 772 | u32 new_rate; |
772 | struct ac97_codec *codec=state->card->ac97_codec[0]; | 773 | struct ac97_codec *codec=state->card->ac97_codec[0]; |
773 | 774 | ||
774 | if(!(state->card->ac97_features&0x0001)) | 775 | if(!(state->card->ac97_features&0x0001)) |
775 | { | 776 | { |
776 | dmabuf->rate = clocking; | 777 | dmabuf->rate = clocking; |
777 | #ifdef DEBUG | 778 | #ifdef DEBUG |
778 | printk("Asked for %d Hz, but ac97_features says we only do %dHz. Sorry!\n", | 779 | printk("Asked for %d Hz, but ac97_features says we only do %dHz. Sorry!\n", |
779 | rate,clocking); | 780 | rate,clocking); |
780 | #endif | 781 | #endif |
781 | return clocking; | 782 | return clocking; |
782 | } | 783 | } |
783 | 784 | ||
784 | if (rate > 48000) | 785 | if (rate > 48000) |
785 | rate = 48000; | 786 | rate = 48000; |
786 | if (rate < 8000) | 787 | if (rate < 8000) |
787 | rate = 8000; | 788 | rate = 8000; |
788 | dmabuf->rate = rate; | 789 | dmabuf->rate = rate; |
789 | 790 | ||
790 | /* | 791 | /* |
791 | * Adjust for misclocked crap | 792 | * Adjust for misclocked crap |
792 | */ | 793 | */ |
793 | rate = ( rate * clocking)/48000; | 794 | rate = ( rate * clocking)/48000; |
794 | if(strict_clocking && rate < 8000) { | 795 | if(strict_clocking && rate < 8000) { |
795 | rate = 8000; | 796 | rate = 8000; |
796 | dmabuf->rate = (rate * 48000)/clocking; | 797 | dmabuf->rate = (rate * 48000)/clocking; |
797 | } | 798 | } |
798 | 799 | ||
799 | new_rate=ac97_set_dac_rate(codec, rate); | 800 | new_rate=ac97_set_dac_rate(codec, rate); |
800 | if(new_rate != rate) { | 801 | if(new_rate != rate) { |
801 | dmabuf->rate = (new_rate * 48000)/clocking; | 802 | dmabuf->rate = (new_rate * 48000)/clocking; |
802 | } | 803 | } |
803 | #ifdef DEBUG | 804 | #ifdef DEBUG |
804 | printk("i810_audio: called i810_set_dac_rate : asked for %d, got %d\n", rate, dmabuf->rate); | 805 | printk("i810_audio: called i810_set_dac_rate : asked for %d, got %d\n", rate, dmabuf->rate); |
805 | #endif | 806 | #endif |
806 | rate = new_rate; | 807 | rate = new_rate; |
807 | return dmabuf->rate; | 808 | return dmabuf->rate; |
808 | } | 809 | } |
809 | 810 | ||
810 | /* set recording sample rate */ | 811 | /* set recording sample rate */ |
811 | static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int rate) | 812 | static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int rate) |
812 | { | 813 | { |
813 | struct dmabuf *dmabuf = &state->dmabuf; | 814 | struct dmabuf *dmabuf = &state->dmabuf; |
814 | u32 new_rate; | 815 | u32 new_rate; |
815 | struct ac97_codec *codec=state->card->ac97_codec[0]; | 816 | struct ac97_codec *codec=state->card->ac97_codec[0]; |
816 | 817 | ||
817 | if(!(state->card->ac97_features&0x0001)) | 818 | if(!(state->card->ac97_features&0x0001)) |
818 | { | 819 | { |
819 | dmabuf->rate = clocking; | 820 | dmabuf->rate = clocking; |
820 | return clocking; | 821 | return clocking; |
821 | } | 822 | } |
822 | 823 | ||
823 | if (rate > 48000) | 824 | if (rate > 48000) |
824 | rate = 48000; | 825 | rate = 48000; |
825 | if (rate < 8000) | 826 | if (rate < 8000) |
826 | rate = 8000; | 827 | rate = 8000; |
827 | dmabuf->rate = rate; | 828 | dmabuf->rate = rate; |
828 | 829 | ||
829 | /* | 830 | /* |
830 | * Adjust for misclocked crap | 831 | * Adjust for misclocked crap |
831 | */ | 832 | */ |
832 | 833 | ||
833 | rate = ( rate * clocking)/48000; | 834 | rate = ( rate * clocking)/48000; |
834 | if(strict_clocking && rate < 8000) { | 835 | if(strict_clocking && rate < 8000) { |
835 | rate = 8000; | 836 | rate = 8000; |
836 | dmabuf->rate = (rate * 48000)/clocking; | 837 | dmabuf->rate = (rate * 48000)/clocking; |
837 | } | 838 | } |
838 | 839 | ||
839 | new_rate = ac97_set_adc_rate(codec, rate); | 840 | new_rate = ac97_set_adc_rate(codec, rate); |
840 | 841 | ||
841 | if(new_rate != rate) { | 842 | if(new_rate != rate) { |
842 | dmabuf->rate = (new_rate * 48000)/clocking; | 843 | dmabuf->rate = (new_rate * 48000)/clocking; |
843 | rate = new_rate; | 844 | rate = new_rate; |
844 | } | 845 | } |
845 | #ifdef DEBUG | 846 | #ifdef DEBUG |
846 | printk("i810_audio: called i810_set_adc_rate : rate = %d/%d\n", dmabuf->rate, rate); | 847 | printk("i810_audio: called i810_set_adc_rate : rate = %d/%d\n", dmabuf->rate, rate); |
847 | #endif | 848 | #endif |
848 | return dmabuf->rate; | 849 | return dmabuf->rate; |
849 | } | 850 | } |
850 | 851 | ||
851 | /* get current playback/recording dma buffer pointer (byte offset from LBA), | 852 | /* get current playback/recording dma buffer pointer (byte offset from LBA), |
852 | called with spinlock held! */ | 853 | called with spinlock held! */ |
853 | 854 | ||
854 | static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec) | 855 | static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec) |
855 | { | 856 | { |
856 | struct dmabuf *dmabuf = &state->dmabuf; | 857 | struct dmabuf *dmabuf = &state->dmabuf; |
857 | unsigned int civ, offset, port, port_picb, bytes = 2; | 858 | unsigned int civ, offset, port, port_picb, bytes = 2; |
858 | 859 | ||
859 | if (!dmabuf->enable) | 860 | if (!dmabuf->enable) |
860 | return 0; | 861 | return 0; |
861 | 862 | ||
862 | if (rec) | 863 | if (rec) |
863 | port = dmabuf->read_channel->port; | 864 | port = dmabuf->read_channel->port; |
864 | else | 865 | else |
865 | port = dmabuf->write_channel->port; | 866 | port = dmabuf->write_channel->port; |
866 | 867 | ||
867 | if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) { | 868 | if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) { |
868 | port_picb = port + OFF_SR; | 869 | port_picb = port + OFF_SR; |
869 | bytes = 1; | 870 | bytes = 1; |
870 | } else | 871 | } else |
871 | port_picb = port + OFF_PICB; | 872 | port_picb = port + OFF_PICB; |
872 | 873 | ||
873 | do { | 874 | do { |
874 | civ = GET_CIV(state->card, port); | 875 | civ = GET_CIV(state->card, port); |
875 | offset = I810_IOREADW(state->card, port_picb); | 876 | offset = I810_IOREADW(state->card, port_picb); |
876 | /* Must have a delay here! */ | 877 | /* Must have a delay here! */ |
877 | if(offset == 0) | 878 | if(offset == 0) |
878 | udelay(1); | 879 | udelay(1); |
879 | /* Reread both registers and make sure that that total | 880 | /* Reread both registers and make sure that that total |
880 | * offset from the first reading to the second is 0. | 881 | * offset from the first reading to the second is 0. |
881 | * There is an issue with SiS hardware where it will count | 882 | * There is an issue with SiS hardware where it will count |
882 | * picb down to 0, then update civ to the next value, | 883 | * picb down to 0, then update civ to the next value, |
883 | * then set the new picb to fragsize bytes. We can catch | 884 | * then set the new picb to fragsize bytes. We can catch |
884 | * it between the civ update and the picb update, making | 885 | * it between the civ update and the picb update, making |
885 | * it look as though we are 1 fragsize ahead of where we | 886 | * it look as though we are 1 fragsize ahead of where we |
886 | * are. The next to we get the address though, it will | 887 | * are. The next to we get the address though, it will |
887 | * be back in the right place, and we will suddenly think | 888 | * be back in the right place, and we will suddenly think |
888 | * we just went forward dmasize - fragsize bytes, causing | 889 | * we just went forward dmasize - fragsize bytes, causing |
889 | * totally stupid *huge* dma overrun messages. We are | 890 | * totally stupid *huge* dma overrun messages. We are |
890 | * assuming that the 1us delay is more than long enough | 891 | * assuming that the 1us delay is more than long enough |
891 | * that we won't have to worry about the chip still being | 892 | * that we won't have to worry about the chip still being |
892 | * out of sync with reality ;-) | 893 | * out of sync with reality ;-) |
893 | */ | 894 | */ |
894 | } while (civ != GET_CIV(state->card, port) || offset != I810_IOREADW(state->card, port_picb)); | 895 | } while (civ != GET_CIV(state->card, port) || offset != I810_IOREADW(state->card, port_picb)); |
895 | 896 | ||
896 | return (((civ + 1) * dmabuf->fragsize - (bytes * offset)) | 897 | return (((civ + 1) * dmabuf->fragsize - (bytes * offset)) |
897 | % dmabuf->dmasize); | 898 | % dmabuf->dmasize); |
898 | } | 899 | } |
899 | 900 | ||
900 | /* Stop recording (lock held) */ | 901 | /* Stop recording (lock held) */ |
901 | static inline void __stop_adc(struct i810_state *state) | 902 | static inline void __stop_adc(struct i810_state *state) |
902 | { | 903 | { |
903 | struct dmabuf *dmabuf = &state->dmabuf; | 904 | struct dmabuf *dmabuf = &state->dmabuf; |
904 | struct i810_card *card = state->card; | 905 | struct i810_card *card = state->card; |
905 | 906 | ||
906 | dmabuf->enable &= ~ADC_RUNNING; | 907 | dmabuf->enable &= ~ADC_RUNNING; |
907 | I810_IOWRITEB(0, card, PI_CR); | 908 | I810_IOWRITEB(0, card, PI_CR); |
908 | // wait for the card to acknowledge shutdown | 909 | // wait for the card to acknowledge shutdown |
909 | while( I810_IOREADB(card, PI_CR) != 0 ) ; | 910 | while( I810_IOREADB(card, PI_CR) != 0 ) ; |
910 | // now clear any latent interrupt bits (like the halt bit) | 911 | // now clear any latent interrupt bits (like the halt bit) |
911 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) | 912 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) |
912 | I810_IOWRITEB( I810_IOREADB(card, PI_PICB), card, PI_PICB ); | 913 | I810_IOWRITEB( I810_IOREADB(card, PI_PICB), card, PI_PICB ); |
913 | else | 914 | else |
914 | I810_IOWRITEB( I810_IOREADB(card, PI_SR), card, PI_SR ); | 915 | I810_IOWRITEB( I810_IOREADB(card, PI_SR), card, PI_SR ); |
915 | I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PI, card, GLOB_STA); | 916 | I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PI, card, GLOB_STA); |
916 | } | 917 | } |
917 | 918 | ||
918 | static void stop_adc(struct i810_state *state) | 919 | static void stop_adc(struct i810_state *state) |
919 | { | 920 | { |
920 | struct i810_card *card = state->card; | 921 | struct i810_card *card = state->card; |
921 | unsigned long flags; | 922 | unsigned long flags; |
922 | 923 | ||
923 | spin_lock_irqsave(&card->lock, flags); | 924 | spin_lock_irqsave(&card->lock, flags); |
924 | __stop_adc(state); | 925 | __stop_adc(state); |
925 | spin_unlock_irqrestore(&card->lock, flags); | 926 | spin_unlock_irqrestore(&card->lock, flags); |
926 | } | 927 | } |
927 | 928 | ||
928 | static inline void __start_adc(struct i810_state *state) | 929 | static inline void __start_adc(struct i810_state *state) |
929 | { | 930 | { |
930 | struct dmabuf *dmabuf = &state->dmabuf; | 931 | struct dmabuf *dmabuf = &state->dmabuf; |
931 | 932 | ||
932 | if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable && | 933 | if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable && |
933 | (dmabuf->trigger & PCM_ENABLE_INPUT)) { | 934 | (dmabuf->trigger & PCM_ENABLE_INPUT)) { |
934 | dmabuf->enable |= ADC_RUNNING; | 935 | dmabuf->enable |= ADC_RUNNING; |
935 | // Interrupt enable, LVI enable, DMA enable | 936 | // Interrupt enable, LVI enable, DMA enable |
936 | I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PI_CR); | 937 | I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PI_CR); |
937 | } | 938 | } |
938 | } | 939 | } |
939 | 940 | ||
940 | static void start_adc(struct i810_state *state) | 941 | static void start_adc(struct i810_state *state) |
941 | { | 942 | { |
942 | struct i810_card *card = state->card; | 943 | struct i810_card *card = state->card; |
943 | unsigned long flags; | 944 | unsigned long flags; |
944 | 945 | ||
945 | spin_lock_irqsave(&card->lock, flags); | 946 | spin_lock_irqsave(&card->lock, flags); |
946 | __start_adc(state); | 947 | __start_adc(state); |
947 | spin_unlock_irqrestore(&card->lock, flags); | 948 | spin_unlock_irqrestore(&card->lock, flags); |
948 | } | 949 | } |
949 | 950 | ||
950 | /* stop playback (lock held) */ | 951 | /* stop playback (lock held) */ |
951 | static inline void __stop_dac(struct i810_state *state) | 952 | static inline void __stop_dac(struct i810_state *state) |
952 | { | 953 | { |
953 | struct dmabuf *dmabuf = &state->dmabuf; | 954 | struct dmabuf *dmabuf = &state->dmabuf; |
954 | struct i810_card *card = state->card; | 955 | struct i810_card *card = state->card; |
955 | 956 | ||
956 | dmabuf->enable &= ~DAC_RUNNING; | 957 | dmabuf->enable &= ~DAC_RUNNING; |
957 | I810_IOWRITEB(0, card, PO_CR); | 958 | I810_IOWRITEB(0, card, PO_CR); |
958 | // wait for the card to acknowledge shutdown | 959 | // wait for the card to acknowledge shutdown |
959 | while( I810_IOREADB(card, PO_CR) != 0 ) ; | 960 | while( I810_IOREADB(card, PO_CR) != 0 ) ; |
960 | // now clear any latent interrupt bits (like the halt bit) | 961 | // now clear any latent interrupt bits (like the halt bit) |
961 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) | 962 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) |
962 | I810_IOWRITEB( I810_IOREADB(card, PO_PICB), card, PO_PICB ); | 963 | I810_IOWRITEB( I810_IOREADB(card, PO_PICB), card, PO_PICB ); |
963 | else | 964 | else |
964 | I810_IOWRITEB( I810_IOREADB(card, PO_SR), card, PO_SR ); | 965 | I810_IOWRITEB( I810_IOREADB(card, PO_SR), card, PO_SR ); |
965 | I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PO, card, GLOB_STA); | 966 | I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PO, card, GLOB_STA); |
966 | } | 967 | } |
967 | 968 | ||
968 | static void stop_dac(struct i810_state *state) | 969 | static void stop_dac(struct i810_state *state) |
969 | { | 970 | { |
970 | struct i810_card *card = state->card; | 971 | struct i810_card *card = state->card; |
971 | unsigned long flags; | 972 | unsigned long flags; |
972 | 973 | ||
973 | spin_lock_irqsave(&card->lock, flags); | 974 | spin_lock_irqsave(&card->lock, flags); |
974 | __stop_dac(state); | 975 | __stop_dac(state); |
975 | spin_unlock_irqrestore(&card->lock, flags); | 976 | spin_unlock_irqrestore(&card->lock, flags); |
976 | } | 977 | } |
977 | 978 | ||
978 | static inline void __start_dac(struct i810_state *state) | 979 | static inline void __start_dac(struct i810_state *state) |
979 | { | 980 | { |
980 | struct dmabuf *dmabuf = &state->dmabuf; | 981 | struct dmabuf *dmabuf = &state->dmabuf; |
981 | 982 | ||
982 | if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && | 983 | if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && |
983 | (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { | 984 | (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { |
984 | dmabuf->enable |= DAC_RUNNING; | 985 | dmabuf->enable |= DAC_RUNNING; |
985 | // Interrupt enable, LVI enable, DMA enable | 986 | // Interrupt enable, LVI enable, DMA enable |
986 | I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PO_CR); | 987 | I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PO_CR); |
987 | } | 988 | } |
988 | } | 989 | } |
989 | static void start_dac(struct i810_state *state) | 990 | static void start_dac(struct i810_state *state) |
990 | { | 991 | { |
991 | struct i810_card *card = state->card; | 992 | struct i810_card *card = state->card; |
992 | unsigned long flags; | 993 | unsigned long flags; |
993 | 994 | ||
994 | spin_lock_irqsave(&card->lock, flags); | 995 | spin_lock_irqsave(&card->lock, flags); |
995 | __start_dac(state); | 996 | __start_dac(state); |
996 | spin_unlock_irqrestore(&card->lock, flags); | 997 | spin_unlock_irqrestore(&card->lock, flags); |
997 | } | 998 | } |
998 | 999 | ||
999 | #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) | 1000 | #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) |
1000 | #define DMABUF_MINORDER 1 | 1001 | #define DMABUF_MINORDER 1 |
1001 | 1002 | ||
1002 | /* allocate DMA buffer, playback and recording buffer should be allocated separately */ | 1003 | /* allocate DMA buffer, playback and recording buffer should be allocated separately */ |
1003 | static int alloc_dmabuf(struct i810_state *state) | 1004 | static int alloc_dmabuf(struct i810_state *state) |
1004 | { | 1005 | { |
1005 | struct dmabuf *dmabuf = &state->dmabuf; | 1006 | struct dmabuf *dmabuf = &state->dmabuf; |
1006 | void *rawbuf= NULL; | 1007 | void *rawbuf= NULL; |
1007 | int order, size; | 1008 | int order, size; |
1008 | struct page *page, *pend; | 1009 | struct page *page, *pend; |
1009 | 1010 | ||
1010 | /* If we don't have any oss frag params, then use our default ones */ | 1011 | /* If we don't have any oss frag params, then use our default ones */ |
1011 | if(dmabuf->ossmaxfrags == 0) | 1012 | if(dmabuf->ossmaxfrags == 0) |
1012 | dmabuf->ossmaxfrags = 4; | 1013 | dmabuf->ossmaxfrags = 4; |
1013 | if(dmabuf->ossfragsize == 0) | 1014 | if(dmabuf->ossfragsize == 0) |
1014 | dmabuf->ossfragsize = (PAGE_SIZE<<DMABUF_DEFAULTORDER)/dmabuf->ossmaxfrags; | 1015 | dmabuf->ossfragsize = (PAGE_SIZE<<DMABUF_DEFAULTORDER)/dmabuf->ossmaxfrags; |
1015 | size = dmabuf->ossfragsize * dmabuf->ossmaxfrags; | 1016 | size = dmabuf->ossfragsize * dmabuf->ossmaxfrags; |
1016 | 1017 | ||
1017 | if(dmabuf->rawbuf && (PAGE_SIZE << dmabuf->buforder) == size) | 1018 | if(dmabuf->rawbuf && (PAGE_SIZE << dmabuf->buforder) == size) |
1018 | return 0; | 1019 | return 0; |
1019 | /* alloc enough to satisfy the oss params */ | 1020 | /* alloc enough to satisfy the oss params */ |
1020 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { | 1021 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { |
1021 | if ( (PAGE_SIZE<<order) > size ) | 1022 | if ( (PAGE_SIZE<<order) > size ) |
1022 | continue; | 1023 | continue; |
1023 | if ((rawbuf = pci_alloc_consistent(state->card->pci_dev, | 1024 | if ((rawbuf = pci_alloc_consistent(state->card->pci_dev, |
1024 | PAGE_SIZE << order, | 1025 | PAGE_SIZE << order, |
1025 | &dmabuf->dma_handle))) | 1026 | &dmabuf->dma_handle))) |
1026 | break; | 1027 | break; |
1027 | } | 1028 | } |
1028 | if (!rawbuf) | 1029 | if (!rawbuf) |
1029 | return -ENOMEM; | 1030 | return -ENOMEM; |
1030 | 1031 | ||
1031 | 1032 | ||
1032 | #ifdef DEBUG | 1033 | #ifdef DEBUG |
1033 | printk("i810_audio: allocated %ld (order = %d) bytes at %p\n", | 1034 | printk("i810_audio: allocated %ld (order = %d) bytes at %p\n", |
1034 | PAGE_SIZE << order, order, rawbuf); | 1035 | PAGE_SIZE << order, order, rawbuf); |
1035 | #endif | 1036 | #endif |
1036 | 1037 | ||
1037 | dmabuf->ready = dmabuf->mapped = 0; | 1038 | dmabuf->ready = dmabuf->mapped = 0; |
1038 | dmabuf->rawbuf = rawbuf; | 1039 | dmabuf->rawbuf = rawbuf; |
1039 | dmabuf->buforder = order; | 1040 | dmabuf->buforder = order; |
1040 | 1041 | ||
1041 | /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */ | 1042 | /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */ |
1042 | pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); | 1043 | pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); |
1043 | for (page = virt_to_page(rawbuf); page <= pend; page++) | 1044 | for (page = virt_to_page(rawbuf); page <= pend; page++) |
1044 | SetPageReserved(page); | 1045 | SetPageReserved(page); |
1045 | 1046 | ||
1046 | return 0; | 1047 | return 0; |
1047 | } | 1048 | } |
1048 | 1049 | ||
1049 | /* free DMA buffer */ | 1050 | /* free DMA buffer */ |
1050 | static void dealloc_dmabuf(struct i810_state *state) | 1051 | static void dealloc_dmabuf(struct i810_state *state) |
1051 | { | 1052 | { |
1052 | struct dmabuf *dmabuf = &state->dmabuf; | 1053 | struct dmabuf *dmabuf = &state->dmabuf; |
1053 | struct page *page, *pend; | 1054 | struct page *page, *pend; |
1054 | 1055 | ||
1055 | if (dmabuf->rawbuf) { | 1056 | if (dmabuf->rawbuf) { |
1056 | /* undo marking the pages as reserved */ | 1057 | /* undo marking the pages as reserved */ |
1057 | pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); | 1058 | pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); |
1058 | for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) | 1059 | for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) |
1059 | ClearPageReserved(page); | 1060 | ClearPageReserved(page); |
1060 | pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, | 1061 | pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, |
1061 | dmabuf->rawbuf, dmabuf->dma_handle); | 1062 | dmabuf->rawbuf, dmabuf->dma_handle); |
1062 | } | 1063 | } |
1063 | dmabuf->rawbuf = NULL; | 1064 | dmabuf->rawbuf = NULL; |
1064 | dmabuf->mapped = dmabuf->ready = 0; | 1065 | dmabuf->mapped = dmabuf->ready = 0; |
1065 | } | 1066 | } |
1066 | 1067 | ||
1067 | static int prog_dmabuf(struct i810_state *state, unsigned rec) | 1068 | static int prog_dmabuf(struct i810_state *state, unsigned rec) |
1068 | { | 1069 | { |
1069 | struct dmabuf *dmabuf = &state->dmabuf; | 1070 | struct dmabuf *dmabuf = &state->dmabuf; |
1070 | struct i810_channel *c; | 1071 | struct i810_channel *c; |
1071 | struct sg_item *sg; | 1072 | struct sg_item *sg; |
1072 | unsigned long flags; | 1073 | unsigned long flags; |
1073 | int ret; | 1074 | int ret; |
1074 | unsigned fragint; | 1075 | unsigned fragint; |
1075 | int i; | 1076 | int i; |
1076 | 1077 | ||
1077 | spin_lock_irqsave(&state->card->lock, flags); | 1078 | spin_lock_irqsave(&state->card->lock, flags); |
1078 | if(dmabuf->enable & DAC_RUNNING) | 1079 | if(dmabuf->enable & DAC_RUNNING) |
1079 | __stop_dac(state); | 1080 | __stop_dac(state); |
1080 | if(dmabuf->enable & ADC_RUNNING) | 1081 | if(dmabuf->enable & ADC_RUNNING) |
1081 | __stop_adc(state); | 1082 | __stop_adc(state); |
1082 | dmabuf->total_bytes = 0; | 1083 | dmabuf->total_bytes = 0; |
1083 | dmabuf->count = dmabuf->error = 0; | 1084 | dmabuf->count = dmabuf->error = 0; |
1084 | dmabuf->swptr = dmabuf->hwptr = 0; | 1085 | dmabuf->swptr = dmabuf->hwptr = 0; |
1085 | spin_unlock_irqrestore(&state->card->lock, flags); | 1086 | spin_unlock_irqrestore(&state->card->lock, flags); |
1086 | 1087 | ||
1087 | /* allocate DMA buffer, let alloc_dmabuf determine if we are already | 1088 | /* allocate DMA buffer, let alloc_dmabuf determine if we are already |
1088 | * allocated well enough or if we should replace the current buffer | 1089 | * allocated well enough or if we should replace the current buffer |
1089 | * (assuming one is already allocated, if it isn't, then allocate it). | 1090 | * (assuming one is already allocated, if it isn't, then allocate it). |
1090 | */ | 1091 | */ |
1091 | if ((ret = alloc_dmabuf(state))) | 1092 | if ((ret = alloc_dmabuf(state))) |
1092 | return ret; | 1093 | return ret; |
1093 | 1094 | ||
1094 | /* FIXME: figure out all this OSS fragment stuff */ | 1095 | /* FIXME: figure out all this OSS fragment stuff */ |
1095 | /* I did, it now does what it should according to the OSS API. DL */ | 1096 | /* I did, it now does what it should according to the OSS API. DL */ |
1096 | /* We may not have realloced our dmabuf, but the fragment size to | 1097 | /* We may not have realloced our dmabuf, but the fragment size to |
1097 | * fragment number ratio may have changed, so go ahead and reprogram | 1098 | * fragment number ratio may have changed, so go ahead and reprogram |
1098 | * things | 1099 | * things |
1099 | */ | 1100 | */ |
1100 | dmabuf->dmasize = PAGE_SIZE << dmabuf->buforder; | 1101 | dmabuf->dmasize = PAGE_SIZE << dmabuf->buforder; |
1101 | dmabuf->numfrag = SG_LEN; | 1102 | dmabuf->numfrag = SG_LEN; |
1102 | dmabuf->fragsize = dmabuf->dmasize/dmabuf->numfrag; | 1103 | dmabuf->fragsize = dmabuf->dmasize/dmabuf->numfrag; |
1103 | dmabuf->fragsamples = dmabuf->fragsize >> 1; | 1104 | dmabuf->fragsamples = dmabuf->fragsize >> 1; |
1104 | dmabuf->fragshift = ffs(dmabuf->fragsize) - 1; | 1105 | dmabuf->fragshift = ffs(dmabuf->fragsize) - 1; |
1105 | dmabuf->userfragsize = dmabuf->ossfragsize; | 1106 | dmabuf->userfragsize = dmabuf->ossfragsize; |
1106 | dmabuf->userfrags = dmabuf->dmasize/dmabuf->ossfragsize; | 1107 | dmabuf->userfrags = dmabuf->dmasize/dmabuf->ossfragsize; |
1107 | 1108 | ||
1108 | memset(dmabuf->rawbuf, 0, dmabuf->dmasize); | 1109 | memset(dmabuf->rawbuf, 0, dmabuf->dmasize); |
1109 | 1110 | ||
1110 | if(dmabuf->ossmaxfrags == 4) { | 1111 | if(dmabuf->ossmaxfrags == 4) { |
1111 | fragint = 8; | 1112 | fragint = 8; |
1112 | } else if (dmabuf->ossmaxfrags == 8) { | 1113 | } else if (dmabuf->ossmaxfrags == 8) { |
1113 | fragint = 4; | 1114 | fragint = 4; |
1114 | } else if (dmabuf->ossmaxfrags == 16) { | 1115 | } else if (dmabuf->ossmaxfrags == 16) { |
1115 | fragint = 2; | 1116 | fragint = 2; |
1116 | } else { | 1117 | } else { |
1117 | fragint = 1; | 1118 | fragint = 1; |
1118 | } | 1119 | } |
1119 | /* | 1120 | /* |
1120 | * Now set up the ring | 1121 | * Now set up the ring |
1121 | */ | 1122 | */ |
1122 | if(dmabuf->read_channel) | 1123 | if(dmabuf->read_channel) |
1123 | c = dmabuf->read_channel; | 1124 | c = dmabuf->read_channel; |
1124 | else | 1125 | else |
1125 | c = dmabuf->write_channel; | 1126 | c = dmabuf->write_channel; |
1126 | while(c != NULL) { | 1127 | while(c != NULL) { |
1127 | sg=&c->sg[0]; | 1128 | sg=&c->sg[0]; |
1128 | /* | 1129 | /* |
1129 | * Load up 32 sg entries and take an interrupt at half | 1130 | * Load up 32 sg entries and take an interrupt at half |
1130 | * way (we might want more interrupts later..) | 1131 | * way (we might want more interrupts later..) |
1131 | */ | 1132 | */ |
1132 | 1133 | ||
1133 | for(i=0;i<dmabuf->numfrag;i++) | 1134 | for(i=0;i<dmabuf->numfrag;i++) |
1134 | { | 1135 | { |
1135 | sg->busaddr=(u32)dmabuf->dma_handle+dmabuf->fragsize*i; | 1136 | sg->busaddr=(u32)dmabuf->dma_handle+dmabuf->fragsize*i; |
1136 | // the card will always be doing 16bit stereo | 1137 | // the card will always be doing 16bit stereo |
1137 | sg->control=dmabuf->fragsamples; | 1138 | sg->control=dmabuf->fragsamples; |
1138 | if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) | 1139 | if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) |
1139 | sg->control <<= 1; | 1140 | sg->control <<= 1; |
1140 | sg->control|=CON_BUFPAD; | 1141 | sg->control|=CON_BUFPAD; |
1141 | // set us up to get IOC interrupts as often as needed to | 1142 | // set us up to get IOC interrupts as often as needed to |
1142 | // satisfy numfrag requirements, no more | 1143 | // satisfy numfrag requirements, no more |
1143 | if( ((i+1) % fragint) == 0) { | 1144 | if( ((i+1) % fragint) == 0) { |
1144 | sg->control|=CON_IOC; | 1145 | sg->control|=CON_IOC; |
1145 | } | 1146 | } |
1146 | sg++; | 1147 | sg++; |
1147 | } | 1148 | } |
1148 | spin_lock_irqsave(&state->card->lock, flags); | 1149 | spin_lock_irqsave(&state->card->lock, flags); |
1149 | I810_IOWRITEB(2, state->card, c->port+OFF_CR); /* reset DMA machine */ | 1150 | I810_IOWRITEB(2, state->card, c->port+OFF_CR); /* reset DMA machine */ |
1150 | while( I810_IOREADB(state->card, c->port+OFF_CR) & 0x02 ) ; | 1151 | while( I810_IOREADB(state->card, c->port+OFF_CR) & 0x02 ) ; |
1151 | I810_IOWRITEL((u32)state->card->chandma + | 1152 | I810_IOWRITEL((u32)state->card->chandma + |
1152 | c->num*sizeof(struct i810_channel), | 1153 | c->num*sizeof(struct i810_channel), |
1153 | state->card, c->port+OFF_BDBAR); | 1154 | state->card, c->port+OFF_BDBAR); |
1154 | CIV_TO_LVI(state->card, c->port, 0); | 1155 | CIV_TO_LVI(state->card, c->port, 0); |
1155 | 1156 | ||
1156 | spin_unlock_irqrestore(&state->card->lock, flags); | 1157 | spin_unlock_irqrestore(&state->card->lock, flags); |
1157 | 1158 | ||
1158 | if(c != dmabuf->write_channel) | 1159 | if(c != dmabuf->write_channel) |
1159 | c = dmabuf->write_channel; | 1160 | c = dmabuf->write_channel; |
1160 | else | 1161 | else |
1161 | c = NULL; | 1162 | c = NULL; |
1162 | } | 1163 | } |
1163 | 1164 | ||
1164 | /* set the ready flag for the dma buffer */ | 1165 | /* set the ready flag for the dma buffer */ |
1165 | dmabuf->ready = 1; | 1166 | dmabuf->ready = 1; |
1166 | 1167 | ||
1167 | #ifdef DEBUG | 1168 | #ifdef DEBUG |
1168 | printk("i810_audio: prog_dmabuf, sample rate = %d, format = %d,\n\tnumfrag = %d, " | 1169 | printk("i810_audio: prog_dmabuf, sample rate = %d, format = %d,\n\tnumfrag = %d, " |
1169 | "fragsize = %d dmasize = %d\n", | 1170 | "fragsize = %d dmasize = %d\n", |
1170 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, | 1171 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, |
1171 | dmabuf->fragsize, dmabuf->dmasize); | 1172 | dmabuf->fragsize, dmabuf->dmasize); |
1172 | #endif | 1173 | #endif |
1173 | 1174 | ||
1174 | return 0; | 1175 | return 0; |
1175 | } | 1176 | } |
1176 | 1177 | ||
1177 | static void __i810_update_lvi(struct i810_state *state, int rec) | 1178 | static void __i810_update_lvi(struct i810_state *state, int rec) |
1178 | { | 1179 | { |
1179 | struct dmabuf *dmabuf = &state->dmabuf; | 1180 | struct dmabuf *dmabuf = &state->dmabuf; |
1180 | int x, port; | 1181 | int x, port; |
1181 | int trigger; | 1182 | int trigger; |
1182 | int count, fragsize; | 1183 | int count, fragsize; |
1183 | void (*start)(struct i810_state *); | 1184 | void (*start)(struct i810_state *); |
1184 | 1185 | ||
1185 | count = dmabuf->count; | 1186 | count = dmabuf->count; |
1186 | if (rec) { | 1187 | if (rec) { |
1187 | port = dmabuf->read_channel->port; | 1188 | port = dmabuf->read_channel->port; |
1188 | trigger = PCM_ENABLE_INPUT; | 1189 | trigger = PCM_ENABLE_INPUT; |
1189 | start = __start_adc; | 1190 | start = __start_adc; |
1190 | count = dmabuf->dmasize - count; | 1191 | count = dmabuf->dmasize - count; |
1191 | } else { | 1192 | } else { |
1192 | port = dmabuf->write_channel->port; | 1193 | port = dmabuf->write_channel->port; |
1193 | trigger = PCM_ENABLE_OUTPUT; | 1194 | trigger = PCM_ENABLE_OUTPUT; |
1194 | start = __start_dac; | 1195 | start = __start_dac; |
1195 | } | 1196 | } |
1196 | 1197 | ||
1197 | /* Do not process partial fragments. */ | 1198 | /* Do not process partial fragments. */ |
1198 | fragsize = dmabuf->fragsize; | 1199 | fragsize = dmabuf->fragsize; |
1199 | if (count < fragsize) | 1200 | if (count < fragsize) |
1200 | return; | 1201 | return; |
1201 | 1202 | ||
1202 | /* if we are currently stopped, then our CIV is actually set to our | 1203 | /* if we are currently stopped, then our CIV is actually set to our |
1203 | * *last* sg segment and we are ready to wrap to the next. However, | 1204 | * *last* sg segment and we are ready to wrap to the next. However, |
1204 | * if we set our LVI to the last sg segment, then it won't wrap to | 1205 | * if we set our LVI to the last sg segment, then it won't wrap to |
1205 | * the next sg segment, it won't even get a start. So, instead, when | 1206 | * the next sg segment, it won't even get a start. So, instead, when |
1206 | * we are stopped, we set both the LVI value and also we increment | 1207 | * we are stopped, we set both the LVI value and also we increment |
1207 | * the CIV value to the next sg segment to be played so that when | 1208 | * the CIV value to the next sg segment to be played so that when |
1208 | * we call start, things will operate properly. Since the CIV can't | 1209 | * we call start, things will operate properly. Since the CIV can't |
1209 | * be written to directly for this purpose, we set the LVI to CIV + 1 | 1210 | * be written to directly for this purpose, we set the LVI to CIV + 1 |
1210 | * temporarily. Once the engine has started we set the LVI to its | 1211 | * temporarily. Once the engine has started we set the LVI to its |
1211 | * final value. | 1212 | * final value. |
1212 | */ | 1213 | */ |
1213 | if (!dmabuf->enable && dmabuf->ready) { | 1214 | if (!dmabuf->enable && dmabuf->ready) { |
1214 | if (!(dmabuf->trigger & trigger)) | 1215 | if (!(dmabuf->trigger & trigger)) |
1215 | return; | 1216 | return; |
1216 | 1217 | ||
1217 | CIV_TO_LVI(state->card, port, 1); | 1218 | CIV_TO_LVI(state->card, port, 1); |
1218 | 1219 | ||
1219 | start(state); | 1220 | start(state); |
1220 | while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2)))) | 1221 | while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2)))) |
1221 | ; | 1222 | ; |
1222 | } | 1223 | } |
1223 | 1224 | ||
1224 | /* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */ | 1225 | /* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */ |
1225 | x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize); | 1226 | x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize); |
1226 | x >>= dmabuf->fragshift; | 1227 | x >>= dmabuf->fragshift; |
1227 | I810_IOWRITEB(x, state->card, port + OFF_LVI); | 1228 | I810_IOWRITEB(x, state->card, port + OFF_LVI); |
1228 | } | 1229 | } |
1229 | 1230 | ||
1230 | static void i810_update_lvi(struct i810_state *state, int rec) | 1231 | static void i810_update_lvi(struct i810_state *state, int rec) |
1231 | { | 1232 | { |
1232 | struct dmabuf *dmabuf = &state->dmabuf; | 1233 | struct dmabuf *dmabuf = &state->dmabuf; |
1233 | unsigned long flags; | 1234 | unsigned long flags; |
1234 | 1235 | ||
1235 | if(!dmabuf->ready) | 1236 | if(!dmabuf->ready) |
1236 | return; | 1237 | return; |
1237 | spin_lock_irqsave(&state->card->lock, flags); | 1238 | spin_lock_irqsave(&state->card->lock, flags); |
1238 | __i810_update_lvi(state, rec); | 1239 | __i810_update_lvi(state, rec); |
1239 | spin_unlock_irqrestore(&state->card->lock, flags); | 1240 | spin_unlock_irqrestore(&state->card->lock, flags); |
1240 | } | 1241 | } |
1241 | 1242 | ||
1242 | /* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */ | 1243 | /* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */ |
1243 | static void i810_update_ptr(struct i810_state *state) | 1244 | static void i810_update_ptr(struct i810_state *state) |
1244 | { | 1245 | { |
1245 | struct dmabuf *dmabuf = &state->dmabuf; | 1246 | struct dmabuf *dmabuf = &state->dmabuf; |
1246 | unsigned hwptr; | 1247 | unsigned hwptr; |
1247 | unsigned fragmask, dmamask; | 1248 | unsigned fragmask, dmamask; |
1248 | int diff; | 1249 | int diff; |
1249 | 1250 | ||
1250 | fragmask = MASKP2(~0, dmabuf->fragsize); | 1251 | fragmask = MASKP2(~0, dmabuf->fragsize); |
1251 | dmamask = MODULOP2(~0, dmabuf->dmasize); | 1252 | dmamask = MODULOP2(~0, dmabuf->dmasize); |
1252 | 1253 | ||
1253 | /* error handling and process wake up for ADC */ | 1254 | /* error handling and process wake up for ADC */ |
1254 | if (dmabuf->enable == ADC_RUNNING) { | 1255 | if (dmabuf->enable == ADC_RUNNING) { |
1255 | /* update hardware pointer */ | 1256 | /* update hardware pointer */ |
1256 | hwptr = i810_get_dma_addr(state, 1) & fragmask; | 1257 | hwptr = i810_get_dma_addr(state, 1) & fragmask; |
1257 | diff = (hwptr - dmabuf->hwptr) & dmamask; | 1258 | diff = (hwptr - dmabuf->hwptr) & dmamask; |
1258 | #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) | 1259 | #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) |
1259 | printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); | 1260 | printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); |
1260 | #endif | 1261 | #endif |
1261 | dmabuf->hwptr = hwptr; | 1262 | dmabuf->hwptr = hwptr; |
1262 | dmabuf->total_bytes += diff; | 1263 | dmabuf->total_bytes += diff; |
1263 | dmabuf->count += diff; | 1264 | dmabuf->count += diff; |
1264 | if (dmabuf->count > dmabuf->dmasize) { | 1265 | if (dmabuf->count > dmabuf->dmasize) { |
1265 | /* buffer underrun or buffer overrun */ | 1266 | /* buffer underrun or buffer overrun */ |
1266 | /* this is normal for the end of a read */ | 1267 | /* this is normal for the end of a read */ |
1267 | /* only give an error if we went past the */ | 1268 | /* only give an error if we went past the */ |
1268 | /* last valid sg entry */ | 1269 | /* last valid sg entry */ |
1269 | if (GET_CIV(state->card, PI_BASE) != | 1270 | if (GET_CIV(state->card, PI_BASE) != |
1270 | GET_LVI(state->card, PI_BASE)) { | 1271 | GET_LVI(state->card, PI_BASE)) { |
1271 | printk(KERN_WARNING "i810_audio: DMA overrun on read\n"); | 1272 | printk(KERN_WARNING "i810_audio: DMA overrun on read\n"); |
1272 | dmabuf->error++; | 1273 | dmabuf->error++; |
1273 | } | 1274 | } |
1274 | } | 1275 | } |
1275 | if (diff) | 1276 | if (diff) |
1276 | wake_up(&dmabuf->wait); | 1277 | wake_up(&dmabuf->wait); |
1277 | } | 1278 | } |
1278 | /* error handling and process wake up for DAC */ | 1279 | /* error handling and process wake up for DAC */ |
1279 | if (dmabuf->enable == DAC_RUNNING) { | 1280 | if (dmabuf->enable == DAC_RUNNING) { |
1280 | /* update hardware pointer */ | 1281 | /* update hardware pointer */ |
1281 | hwptr = i810_get_dma_addr(state, 0) & fragmask; | 1282 | hwptr = i810_get_dma_addr(state, 0) & fragmask; |
1282 | diff = (hwptr - dmabuf->hwptr) & dmamask; | 1283 | diff = (hwptr - dmabuf->hwptr) & dmamask; |
1283 | #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) | 1284 | #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) |
1284 | printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); | 1285 | printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); |
1285 | #endif | 1286 | #endif |
1286 | dmabuf->hwptr = hwptr; | 1287 | dmabuf->hwptr = hwptr; |
1287 | dmabuf->total_bytes += diff; | 1288 | dmabuf->total_bytes += diff; |
1288 | dmabuf->count -= diff; | 1289 | dmabuf->count -= diff; |
1289 | if (dmabuf->count < 0) { | 1290 | if (dmabuf->count < 0) { |
1290 | /* buffer underrun or buffer overrun */ | 1291 | /* buffer underrun or buffer overrun */ |
1291 | /* this is normal for the end of a write */ | 1292 | /* this is normal for the end of a write */ |
1292 | /* only give an error if we went past the */ | 1293 | /* only give an error if we went past the */ |
1293 | /* last valid sg entry */ | 1294 | /* last valid sg entry */ |
1294 | if (GET_CIV(state->card, PO_BASE) != | 1295 | if (GET_CIV(state->card, PO_BASE) != |
1295 | GET_LVI(state->card, PO_BASE)) { | 1296 | GET_LVI(state->card, PO_BASE)) { |
1296 | printk(KERN_WARNING "i810_audio: DMA overrun on write\n"); | 1297 | printk(KERN_WARNING "i810_audio: DMA overrun on write\n"); |
1297 | printk("i810_audio: CIV %d, LVI %d, hwptr %x, " | 1298 | printk("i810_audio: CIV %d, LVI %d, hwptr %x, " |
1298 | "count %d\n", | 1299 | "count %d\n", |
1299 | GET_CIV(state->card, PO_BASE), | 1300 | GET_CIV(state->card, PO_BASE), |
1300 | GET_LVI(state->card, PO_BASE), | 1301 | GET_LVI(state->card, PO_BASE), |
1301 | dmabuf->hwptr, dmabuf->count); | 1302 | dmabuf->hwptr, dmabuf->count); |
1302 | dmabuf->error++; | 1303 | dmabuf->error++; |
1303 | } | 1304 | } |
1304 | } | 1305 | } |
1305 | if (diff) | 1306 | if (diff) |
1306 | wake_up(&dmabuf->wait); | 1307 | wake_up(&dmabuf->wait); |
1307 | } | 1308 | } |
1308 | } | 1309 | } |
1309 | 1310 | ||
1310 | static inline int i810_get_free_write_space(struct i810_state *state) | 1311 | static inline int i810_get_free_write_space(struct i810_state *state) |
1311 | { | 1312 | { |
1312 | struct dmabuf *dmabuf = &state->dmabuf; | 1313 | struct dmabuf *dmabuf = &state->dmabuf; |
1313 | int free; | 1314 | int free; |
1314 | 1315 | ||
1315 | i810_update_ptr(state); | 1316 | i810_update_ptr(state); |
1316 | // catch underruns during playback | 1317 | // catch underruns during playback |
1317 | if (dmabuf->count < 0) { | 1318 | if (dmabuf->count < 0) { |
1318 | dmabuf->count = 0; | 1319 | dmabuf->count = 0; |
1319 | dmabuf->swptr = dmabuf->hwptr; | 1320 | dmabuf->swptr = dmabuf->hwptr; |
1320 | } | 1321 | } |
1321 | free = dmabuf->dmasize - dmabuf->count; | 1322 | free = dmabuf->dmasize - dmabuf->count; |
1322 | if(free < 0) | 1323 | if(free < 0) |
1323 | return(0); | 1324 | return(0); |
1324 | return(free); | 1325 | return(free); |
1325 | } | 1326 | } |
1326 | 1327 | ||
1327 | static inline int i810_get_available_read_data(struct i810_state *state) | 1328 | static inline int i810_get_available_read_data(struct i810_state *state) |
1328 | { | 1329 | { |
1329 | struct dmabuf *dmabuf = &state->dmabuf; | 1330 | struct dmabuf *dmabuf = &state->dmabuf; |
1330 | int avail; | 1331 | int avail; |
1331 | 1332 | ||
1332 | i810_update_ptr(state); | 1333 | i810_update_ptr(state); |
1333 | // catch overruns during record | 1334 | // catch overruns during record |
1334 | if (dmabuf->count > dmabuf->dmasize) { | 1335 | if (dmabuf->count > dmabuf->dmasize) { |
1335 | dmabuf->count = dmabuf->dmasize; | 1336 | dmabuf->count = dmabuf->dmasize; |
1336 | dmabuf->swptr = dmabuf->hwptr; | 1337 | dmabuf->swptr = dmabuf->hwptr; |
1337 | } | 1338 | } |
1338 | avail = dmabuf->count; | 1339 | avail = dmabuf->count; |
1339 | if(avail < 0) | 1340 | if(avail < 0) |
1340 | return(0); | 1341 | return(0); |
1341 | return(avail); | 1342 | return(avail); |
1342 | } | 1343 | } |
1343 | 1344 | ||
1344 | static inline void fill_partial_frag(struct dmabuf *dmabuf) | 1345 | static inline void fill_partial_frag(struct dmabuf *dmabuf) |
1345 | { | 1346 | { |
1346 | unsigned fragsize; | 1347 | unsigned fragsize; |
1347 | unsigned swptr, len; | 1348 | unsigned swptr, len; |
1348 | 1349 | ||
1349 | fragsize = dmabuf->fragsize; | 1350 | fragsize = dmabuf->fragsize; |
1350 | swptr = dmabuf->swptr; | 1351 | swptr = dmabuf->swptr; |
1351 | len = fragsize - MODULOP2(dmabuf->swptr, fragsize); | 1352 | len = fragsize - MODULOP2(dmabuf->swptr, fragsize); |
1352 | if (len == fragsize) | 1353 | if (len == fragsize) |
1353 | return; | 1354 | return; |
1354 | 1355 | ||
1355 | memset(dmabuf->rawbuf + swptr, '\0', len); | 1356 | memset(dmabuf->rawbuf + swptr, '\0', len); |
1356 | dmabuf->swptr = MODULOP2(swptr + len, dmabuf->dmasize); | 1357 | dmabuf->swptr = MODULOP2(swptr + len, dmabuf->dmasize); |
1357 | dmabuf->count += len; | 1358 | dmabuf->count += len; |
1358 | } | 1359 | } |
1359 | 1360 | ||
1360 | static int drain_dac(struct i810_state *state, int signals_allowed) | 1361 | static int drain_dac(struct i810_state *state, int signals_allowed) |
1361 | { | 1362 | { |
1362 | DECLARE_WAITQUEUE(wait, current); | 1363 | DECLARE_WAITQUEUE(wait, current); |
1363 | struct dmabuf *dmabuf = &state->dmabuf; | 1364 | struct dmabuf *dmabuf = &state->dmabuf; |
1364 | unsigned long flags; | 1365 | unsigned long flags; |
1365 | unsigned long tmo; | 1366 | unsigned long tmo; |
1366 | int count; | 1367 | int count; |
1367 | 1368 | ||
1368 | if (!dmabuf->ready) | 1369 | if (!dmabuf->ready) |
1369 | return 0; | 1370 | return 0; |
1370 | if(dmabuf->mapped) { | 1371 | if(dmabuf->mapped) { |
1371 | stop_dac(state); | 1372 | stop_dac(state); |
1372 | return 0; | 1373 | return 0; |
1373 | } | 1374 | } |
1374 | 1375 | ||
1375 | spin_lock_irqsave(&state->card->lock, flags); | 1376 | spin_lock_irqsave(&state->card->lock, flags); |
1376 | 1377 | ||
1377 | fill_partial_frag(dmabuf); | 1378 | fill_partial_frag(dmabuf); |
1378 | 1379 | ||
1379 | /* | 1380 | /* |
1380 | * This will make sure that our LVI is correct, that our | 1381 | * This will make sure that our LVI is correct, that our |
1381 | * pointer is updated, and that the DAC is running. We | 1382 | * pointer is updated, and that the DAC is running. We |
1382 | * have to force the setting of dmabuf->trigger to avoid | 1383 | * have to force the setting of dmabuf->trigger to avoid |
1383 | * any possible deadlocks. | 1384 | * any possible deadlocks. |
1384 | */ | 1385 | */ |
1385 | dmabuf->trigger = PCM_ENABLE_OUTPUT; | 1386 | dmabuf->trigger = PCM_ENABLE_OUTPUT; |
1386 | __i810_update_lvi(state, 0); | 1387 | __i810_update_lvi(state, 0); |
1387 | 1388 | ||
1388 | spin_unlock_irqrestore(&state->card->lock, flags); | 1389 | spin_unlock_irqrestore(&state->card->lock, flags); |
1389 | 1390 | ||
1390 | add_wait_queue(&dmabuf->wait, &wait); | 1391 | add_wait_queue(&dmabuf->wait, &wait); |
1391 | for (;;) { | 1392 | for (;;) { |
1392 | 1393 | ||
1393 | spin_lock_irqsave(&state->card->lock, flags); | 1394 | spin_lock_irqsave(&state->card->lock, flags); |
1394 | i810_update_ptr(state); | 1395 | i810_update_ptr(state); |
1395 | count = dmabuf->count; | 1396 | count = dmabuf->count; |
1396 | 1397 | ||
1397 | /* It seems that we have to set the current state to | 1398 | /* It seems that we have to set the current state to |
1398 | * TASK_INTERRUPTIBLE every time to make the process | 1399 | * TASK_INTERRUPTIBLE every time to make the process |
1399 | * really go to sleep. This also has to be *after* the | 1400 | * really go to sleep. This also has to be *after* the |
1400 | * update_ptr() call because update_ptr is likely to | 1401 | * update_ptr() call because update_ptr is likely to |
1401 | * do a wake_up() which will unset this before we ever | 1402 | * do a wake_up() which will unset this before we ever |
1402 | * try to sleep, resuling in a tight loop in this code | 1403 | * try to sleep, resuling in a tight loop in this code |
1403 | * instead of actually sleeping and waiting for an | 1404 | * instead of actually sleeping and waiting for an |
1404 | * interrupt to wake us up! | 1405 | * interrupt to wake us up! |
1405 | */ | 1406 | */ |
1406 | __set_current_state(signals_allowed ? | 1407 | __set_current_state(signals_allowed ? |
1407 | TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | 1408 | TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); |
1408 | spin_unlock_irqrestore(&state->card->lock, flags); | 1409 | spin_unlock_irqrestore(&state->card->lock, flags); |
1409 | 1410 | ||
1410 | if (count <= 0) | 1411 | if (count <= 0) |
1411 | break; | 1412 | break; |
1412 | 1413 | ||
1413 | if (signal_pending(current) && signals_allowed) { | 1414 | if (signal_pending(current) && signals_allowed) { |
1414 | break; | 1415 | break; |
1415 | } | 1416 | } |
1416 | 1417 | ||
1417 | /* | 1418 | /* |
1418 | * set the timeout to significantly longer than it *should* | 1419 | * set the timeout to significantly longer than it *should* |
1419 | * take for the DAC to drain the DMA buffer | 1420 | * take for the DAC to drain the DMA buffer |
1420 | */ | 1421 | */ |
1421 | tmo = (count * HZ) / (dmabuf->rate); | 1422 | tmo = (count * HZ) / (dmabuf->rate); |
1422 | if (!schedule_timeout(tmo >= 2 ? tmo : 2)){ | 1423 | if (!schedule_timeout(tmo >= 2 ? tmo : 2)){ |
1423 | printk(KERN_ERR "i810_audio: drain_dac, dma timeout?\n"); | 1424 | printk(KERN_ERR "i810_audio: drain_dac, dma timeout?\n"); |
1424 | count = 0; | 1425 | count = 0; |
1425 | break; | 1426 | break; |
1426 | } | 1427 | } |
1427 | } | 1428 | } |
1428 | set_current_state(TASK_RUNNING); | 1429 | set_current_state(TASK_RUNNING); |
1429 | remove_wait_queue(&dmabuf->wait, &wait); | 1430 | remove_wait_queue(&dmabuf->wait, &wait); |
1430 | if(count > 0 && signal_pending(current) && signals_allowed) | 1431 | if(count > 0 && signal_pending(current) && signals_allowed) |
1431 | return -ERESTARTSYS; | 1432 | return -ERESTARTSYS; |
1432 | stop_dac(state); | 1433 | stop_dac(state); |
1433 | return 0; | 1434 | return 0; |
1434 | } | 1435 | } |
1435 | 1436 | ||
1436 | static void i810_channel_interrupt(struct i810_card *card) | 1437 | static void i810_channel_interrupt(struct i810_card *card) |
1437 | { | 1438 | { |
1438 | int i, count; | 1439 | int i, count; |
1439 | 1440 | ||
1440 | #ifdef DEBUG_INTERRUPTS | 1441 | #ifdef DEBUG_INTERRUPTS |
1441 | printk("CHANNEL "); | 1442 | printk("CHANNEL "); |
1442 | #endif | 1443 | #endif |
1443 | for(i=0;i<NR_HW_CH;i++) | 1444 | for(i=0;i<NR_HW_CH;i++) |
1444 | { | 1445 | { |
1445 | struct i810_state *state = card->states[i]; | 1446 | struct i810_state *state = card->states[i]; |
1446 | struct i810_channel *c; | 1447 | struct i810_channel *c; |
1447 | struct dmabuf *dmabuf; | 1448 | struct dmabuf *dmabuf; |
1448 | unsigned long port; | 1449 | unsigned long port; |
1449 | u16 status; | 1450 | u16 status; |
1450 | 1451 | ||
1451 | if(!state) | 1452 | if(!state) |
1452 | continue; | 1453 | continue; |
1453 | if(!state->dmabuf.ready) | 1454 | if(!state->dmabuf.ready) |
1454 | continue; | 1455 | continue; |
1455 | dmabuf = &state->dmabuf; | 1456 | dmabuf = &state->dmabuf; |
1456 | if(dmabuf->enable & DAC_RUNNING) { | 1457 | if(dmabuf->enable & DAC_RUNNING) { |
1457 | c=dmabuf->write_channel; | 1458 | c=dmabuf->write_channel; |
1458 | } else if(dmabuf->enable & ADC_RUNNING) { | 1459 | } else if(dmabuf->enable & ADC_RUNNING) { |
1459 | c=dmabuf->read_channel; | 1460 | c=dmabuf->read_channel; |
1460 | } else /* This can occur going from R/W to close */ | 1461 | } else /* This can occur going from R/W to close */ |
1461 | continue; | 1462 | continue; |
1462 | 1463 | ||
1463 | port = c->port; | 1464 | port = c->port; |
1464 | 1465 | ||
1465 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) | 1466 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) |
1466 | status = I810_IOREADW(card, port + OFF_PICB); | 1467 | status = I810_IOREADW(card, port + OFF_PICB); |
1467 | else | 1468 | else |
1468 | status = I810_IOREADW(card, port + OFF_SR); | 1469 | status = I810_IOREADW(card, port + OFF_SR); |
1469 | 1470 | ||
1470 | #ifdef DEBUG_INTERRUPTS | 1471 | #ifdef DEBUG_INTERRUPTS |
1471 | printk("NUM %d PORT %X IRQ ( ST%d ", c->num, c->port, status); | 1472 | printk("NUM %d PORT %X IRQ ( ST%d ", c->num, c->port, status); |
1472 | #endif | 1473 | #endif |
1473 | if(status & DMA_INT_COMPLETE) | 1474 | if(status & DMA_INT_COMPLETE) |
1474 | { | 1475 | { |
1475 | /* only wake_up() waiters if this interrupt signals | 1476 | /* only wake_up() waiters if this interrupt signals |
1476 | * us being beyond a userfragsize of data open or | 1477 | * us being beyond a userfragsize of data open or |
1477 | * available, and i810_update_ptr() does that for | 1478 | * available, and i810_update_ptr() does that for |
1478 | * us | 1479 | * us |
1479 | */ | 1480 | */ |
1480 | i810_update_ptr(state); | 1481 | i810_update_ptr(state); |
1481 | #ifdef DEBUG_INTERRUPTS | 1482 | #ifdef DEBUG_INTERRUPTS |
1482 | printk("COMP %d ", dmabuf->hwptr / | 1483 | printk("COMP %d ", dmabuf->hwptr / |
1483 | dmabuf->fragsize); | 1484 | dmabuf->fragsize); |
1484 | #endif | 1485 | #endif |
1485 | } | 1486 | } |
1486 | if(status & (DMA_INT_LVI | DMA_INT_DCH)) | 1487 | if(status & (DMA_INT_LVI | DMA_INT_DCH)) |
1487 | { | 1488 | { |
1488 | /* wake_up() unconditionally on LVI and DCH */ | 1489 | /* wake_up() unconditionally on LVI and DCH */ |
1489 | i810_update_ptr(state); | 1490 | i810_update_ptr(state); |
1490 | wake_up(&dmabuf->wait); | 1491 | wake_up(&dmabuf->wait); |
1491 | #ifdef DEBUG_INTERRUPTS | 1492 | #ifdef DEBUG_INTERRUPTS |
1492 | if(status & DMA_INT_LVI) | 1493 | if(status & DMA_INT_LVI) |
1493 | printk("LVI "); | 1494 | printk("LVI "); |
1494 | if(status & DMA_INT_DCH) | 1495 | if(status & DMA_INT_DCH) |
1495 | printk("DCH -"); | 1496 | printk("DCH -"); |
1496 | #endif | 1497 | #endif |
1497 | count = dmabuf->count; | 1498 | count = dmabuf->count; |
1498 | if(dmabuf->enable & ADC_RUNNING) | 1499 | if(dmabuf->enable & ADC_RUNNING) |
1499 | count = dmabuf->dmasize - count; | 1500 | count = dmabuf->dmasize - count; |
1500 | if (count >= (int)dmabuf->fragsize) { | 1501 | if (count >= (int)dmabuf->fragsize) { |
1501 | I810_IOWRITEB(I810_IOREADB(card, port+OFF_CR) | 1, card, port+OFF_CR); | 1502 | I810_IOWRITEB(I810_IOREADB(card, port+OFF_CR) | 1, card, port+OFF_CR); |
1502 | #ifdef DEBUG_INTERRUPTS | 1503 | #ifdef DEBUG_INTERRUPTS |
1503 | printk(" CONTINUE "); | 1504 | printk(" CONTINUE "); |
1504 | #endif | 1505 | #endif |
1505 | } else { | 1506 | } else { |
1506 | if (dmabuf->enable & DAC_RUNNING) | 1507 | if (dmabuf->enable & DAC_RUNNING) |
1507 | __stop_dac(state); | 1508 | __stop_dac(state); |
1508 | if (dmabuf->enable & ADC_RUNNING) | 1509 | if (dmabuf->enable & ADC_RUNNING) |
1509 | __stop_adc(state); | 1510 | __stop_adc(state); |
1510 | dmabuf->enable = 0; | 1511 | dmabuf->enable = 0; |
1511 | #ifdef DEBUG_INTERRUPTS | 1512 | #ifdef DEBUG_INTERRUPTS |
1512 | printk(" STOP "); | 1513 | printk(" STOP "); |
1513 | #endif | 1514 | #endif |
1514 | } | 1515 | } |
1515 | } | 1516 | } |
1516 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) | 1517 | if(card->pci_id == PCI_DEVICE_ID_SI_7012) |
1517 | I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_PICB); | 1518 | I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_PICB); |
1518 | else | 1519 | else |
1519 | I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_SR); | 1520 | I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_SR); |
1520 | } | 1521 | } |
1521 | #ifdef DEBUG_INTERRUPTS | 1522 | #ifdef DEBUG_INTERRUPTS |
1522 | printk(")\n"); | 1523 | printk(")\n"); |
1523 | #endif | 1524 | #endif |
1524 | } | 1525 | } |
1525 | 1526 | ||
1526 | static irqreturn_t i810_interrupt(int irq, void *dev_id) | 1527 | static irqreturn_t i810_interrupt(int irq, void *dev_id) |
1527 | { | 1528 | { |
1528 | struct i810_card *card = dev_id; | 1529 | struct i810_card *card = dev_id; |
1529 | u32 status; | 1530 | u32 status; |
1530 | 1531 | ||
1531 | spin_lock(&card->lock); | 1532 | spin_lock(&card->lock); |
1532 | 1533 | ||
1533 | status = I810_IOREADL(card, GLOB_STA); | 1534 | status = I810_IOREADL(card, GLOB_STA); |
1534 | 1535 | ||
1535 | if(!(status & INT_MASK)) | 1536 | if(!(status & INT_MASK)) |
1536 | { | 1537 | { |
1537 | spin_unlock(&card->lock); | 1538 | spin_unlock(&card->lock); |
1538 | return IRQ_NONE; /* not for us */ | 1539 | return IRQ_NONE; /* not for us */ |
1539 | } | 1540 | } |
1540 | 1541 | ||
1541 | if(status & (INT_PO|INT_PI|INT_MC)) | 1542 | if(status & (INT_PO|INT_PI|INT_MC)) |
1542 | i810_channel_interrupt(card); | 1543 | i810_channel_interrupt(card); |
1543 | 1544 | ||
1544 | /* clear 'em */ | 1545 | /* clear 'em */ |
1545 | I810_IOWRITEL(status & INT_MASK, card, GLOB_STA); | 1546 | I810_IOWRITEL(status & INT_MASK, card, GLOB_STA); |
1546 | spin_unlock(&card->lock); | 1547 | spin_unlock(&card->lock); |
1547 | return IRQ_HANDLED; | 1548 | return IRQ_HANDLED; |
1548 | } | 1549 | } |
1549 | 1550 | ||
1550 | /* in this loop, dmabuf.count signifies the amount of data that is | 1551 | /* in this loop, dmabuf.count signifies the amount of data that is |
1551 | waiting to be copied to the user's buffer. It is filled by the dma | 1552 | waiting to be copied to the user's buffer. It is filled by the dma |
1552 | machine and drained by this loop. */ | 1553 | machine and drained by this loop. */ |
1553 | 1554 | ||
1554 | static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 1555 | static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
1555 | { | 1556 | { |
1556 | struct i810_state *state = (struct i810_state *)file->private_data; | 1557 | struct i810_state *state = (struct i810_state *)file->private_data; |
1557 | struct i810_card *card=state ? state->card : NULL; | 1558 | struct i810_card *card=state ? state->card : NULL; |
1558 | struct dmabuf *dmabuf = &state->dmabuf; | 1559 | struct dmabuf *dmabuf = &state->dmabuf; |
1559 | ssize_t ret; | 1560 | ssize_t ret; |
1560 | unsigned long flags; | 1561 | unsigned long flags; |
1561 | unsigned int swptr; | 1562 | unsigned int swptr; |
1562 | int cnt; | 1563 | int cnt; |
1563 | int pending; | 1564 | int pending; |
1564 | DECLARE_WAITQUEUE(waita, current); | 1565 | DECLARE_WAITQUEUE(waita, current); |
1565 | 1566 | ||
1566 | #ifdef DEBUG2 | 1567 | #ifdef DEBUG2 |
1567 | printk("i810_audio: i810_read called, count = %d\n", count); | 1568 | printk("i810_audio: i810_read called, count = %d\n", count); |
1568 | #endif | 1569 | #endif |
1569 | 1570 | ||
1570 | if (dmabuf->mapped) | 1571 | if (dmabuf->mapped) |
1571 | return -ENXIO; | 1572 | return -ENXIO; |
1572 | if (dmabuf->enable & DAC_RUNNING) | 1573 | if (dmabuf->enable & DAC_RUNNING) |
1573 | return -ENODEV; | 1574 | return -ENODEV; |
1574 | if (!dmabuf->read_channel) { | 1575 | if (!dmabuf->read_channel) { |
1575 | dmabuf->ready = 0; | 1576 | dmabuf->ready = 0; |
1576 | dmabuf->read_channel = card->alloc_rec_pcm_channel(card); | 1577 | dmabuf->read_channel = card->alloc_rec_pcm_channel(card); |
1577 | if (!dmabuf->read_channel) { | 1578 | if (!dmabuf->read_channel) { |
1578 | return -EBUSY; | 1579 | return -EBUSY; |
1579 | } | 1580 | } |
1580 | } | 1581 | } |
1581 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) | 1582 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) |
1582 | return ret; | 1583 | return ret; |
1583 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 1584 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
1584 | return -EFAULT; | 1585 | return -EFAULT; |
1585 | ret = 0; | 1586 | ret = 0; |
1586 | 1587 | ||
1587 | pending = 0; | 1588 | pending = 0; |
1588 | 1589 | ||
1589 | add_wait_queue(&dmabuf->wait, &waita); | 1590 | add_wait_queue(&dmabuf->wait, &waita); |
1590 | while (count > 0) { | 1591 | while (count > 0) { |
1591 | set_current_state(TASK_INTERRUPTIBLE); | 1592 | set_current_state(TASK_INTERRUPTIBLE); |
1592 | spin_lock_irqsave(&card->lock, flags); | 1593 | spin_lock_irqsave(&card->lock, flags); |
1593 | if (PM_SUSPENDED(card)) { | 1594 | if (PM_SUSPENDED(card)) { |
1594 | spin_unlock_irqrestore(&card->lock, flags); | 1595 | spin_unlock_irqrestore(&card->lock, flags); |
1595 | schedule(); | 1596 | schedule(); |
1596 | if (signal_pending(current)) { | 1597 | if (signal_pending(current)) { |
1597 | if (!ret) ret = -EAGAIN; | 1598 | if (!ret) ret = -EAGAIN; |
1598 | break; | 1599 | break; |
1599 | } | 1600 | } |
1600 | continue; | 1601 | continue; |
1601 | } | 1602 | } |
1602 | cnt = i810_get_available_read_data(state); | 1603 | cnt = i810_get_available_read_data(state); |
1603 | swptr = dmabuf->swptr; | 1604 | swptr = dmabuf->swptr; |
1604 | // this is to make the copy_to_user simpler below | 1605 | // this is to make the copy_to_user simpler below |
1605 | if(cnt > (dmabuf->dmasize - swptr)) | 1606 | if(cnt > (dmabuf->dmasize - swptr)) |
1606 | cnt = dmabuf->dmasize - swptr; | 1607 | cnt = dmabuf->dmasize - swptr; |
1607 | spin_unlock_irqrestore(&card->lock, flags); | 1608 | spin_unlock_irqrestore(&card->lock, flags); |
1608 | 1609 | ||
1609 | if (cnt > count) | 1610 | if (cnt > count) |
1610 | cnt = count; | 1611 | cnt = count; |
1611 | if (cnt <= 0) { | 1612 | if (cnt <= 0) { |
1612 | unsigned long tmo; | 1613 | unsigned long tmo; |
1613 | /* | 1614 | /* |
1614 | * Don't let us deadlock. The ADC won't start if | 1615 | * Don't let us deadlock. The ADC won't start if |
1615 | * dmabuf->trigger isn't set. A call to SETTRIGGER | 1616 | * dmabuf->trigger isn't set. A call to SETTRIGGER |
1616 | * could have turned it off after we set it to on | 1617 | * could have turned it off after we set it to on |
1617 | * previously. | 1618 | * previously. |
1618 | */ | 1619 | */ |
1619 | dmabuf->trigger = PCM_ENABLE_INPUT; | 1620 | dmabuf->trigger = PCM_ENABLE_INPUT; |
1620 | /* | 1621 | /* |
1621 | * This does three things. Updates LVI to be correct, | 1622 | * This does three things. Updates LVI to be correct, |
1622 | * makes sure the ADC is running, and updates the | 1623 | * makes sure the ADC is running, and updates the |
1623 | * hwptr. | 1624 | * hwptr. |
1624 | */ | 1625 | */ |
1625 | i810_update_lvi(state,1); | 1626 | i810_update_lvi(state,1); |
1626 | if (file->f_flags & O_NONBLOCK) { | 1627 | if (file->f_flags & O_NONBLOCK) { |
1627 | if (!ret) ret = -EAGAIN; | 1628 | if (!ret) ret = -EAGAIN; |
1628 | goto done; | 1629 | goto done; |
1629 | } | 1630 | } |
1630 | /* Set the timeout to how long it would take to fill | 1631 | /* Set the timeout to how long it would take to fill |
1631 | * two of our buffers. If we haven't been woke up | 1632 | * two of our buffers. If we haven't been woke up |
1632 | * by then, then we know something is wrong. | 1633 | * by then, then we know something is wrong. |
1633 | */ | 1634 | */ |
1634 | tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4); | 1635 | tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4); |
1635 | /* There are two situations when sleep_on_timeout returns, one is when | 1636 | /* There are two situations when sleep_on_timeout returns, one is when |
1636 | the interrupt is serviced correctly and the process is waked up by | 1637 | the interrupt is serviced correctly and the process is waked up by |
1637 | ISR ON TIME. Another is when timeout is expired, which means that | 1638 | ISR ON TIME. Another is when timeout is expired, which means that |
1638 | either interrupt is NOT serviced correctly (pending interrupt) or it | 1639 | either interrupt is NOT serviced correctly (pending interrupt) or it |
1639 | is TOO LATE for the process to be scheduled to run (scheduler latency) | 1640 | is TOO LATE for the process to be scheduled to run (scheduler latency) |
1640 | which results in a (potential) buffer overrun. And worse, there is | 1641 | which results in a (potential) buffer overrun. And worse, there is |
1641 | NOTHING we can do to prevent it. */ | 1642 | NOTHING we can do to prevent it. */ |
1642 | if (!schedule_timeout(tmo >= 2 ? tmo : 2)) { | 1643 | if (!schedule_timeout(tmo >= 2 ? tmo : 2)) { |
1643 | #ifdef DEBUG | 1644 | #ifdef DEBUG |
1644 | printk(KERN_ERR "i810_audio: recording schedule timeout, " | 1645 | printk(KERN_ERR "i810_audio: recording schedule timeout, " |
1645 | "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", | 1646 | "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", |
1646 | dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, | 1647 | dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, |
1647 | dmabuf->hwptr, dmabuf->swptr); | 1648 | dmabuf->hwptr, dmabuf->swptr); |
1648 | #endif | 1649 | #endif |
1649 | /* a buffer overrun, we delay the recovery until next time the | 1650 | /* a buffer overrun, we delay the recovery until next time the |
1650 | while loop begin and we REALLY have space to record */ | 1651 | while loop begin and we REALLY have space to record */ |
1651 | } | 1652 | } |
1652 | if (signal_pending(current)) { | 1653 | if (signal_pending(current)) { |
1653 | ret = ret ? ret : -ERESTARTSYS; | 1654 | ret = ret ? ret : -ERESTARTSYS; |
1654 | goto done; | 1655 | goto done; |
1655 | } | 1656 | } |
1656 | continue; | 1657 | continue; |
1657 | } | 1658 | } |
1658 | 1659 | ||
1659 | if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { | 1660 | if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { |
1660 | if (!ret) ret = -EFAULT; | 1661 | if (!ret) ret = -EFAULT; |
1661 | goto done; | 1662 | goto done; |
1662 | } | 1663 | } |
1663 | 1664 | ||
1664 | swptr = MODULOP2(swptr + cnt, dmabuf->dmasize); | 1665 | swptr = MODULOP2(swptr + cnt, dmabuf->dmasize); |
1665 | 1666 | ||
1666 | spin_lock_irqsave(&card->lock, flags); | 1667 | spin_lock_irqsave(&card->lock, flags); |
1667 | 1668 | ||
1668 | if (PM_SUSPENDED(card)) { | 1669 | if (PM_SUSPENDED(card)) { |
1669 | spin_unlock_irqrestore(&card->lock, flags); | 1670 | spin_unlock_irqrestore(&card->lock, flags); |
1670 | continue; | 1671 | continue; |
1671 | } | 1672 | } |
1672 | dmabuf->swptr = swptr; | 1673 | dmabuf->swptr = swptr; |
1673 | pending = dmabuf->count -= cnt; | 1674 | pending = dmabuf->count -= cnt; |
1674 | spin_unlock_irqrestore(&card->lock, flags); | 1675 | spin_unlock_irqrestore(&card->lock, flags); |
1675 | 1676 | ||
1676 | count -= cnt; | 1677 | count -= cnt; |
1677 | buffer += cnt; | 1678 | buffer += cnt; |
1678 | ret += cnt; | 1679 | ret += cnt; |
1679 | } | 1680 | } |
1680 | done: | 1681 | done: |
1681 | pending = dmabuf->dmasize - pending; | 1682 | pending = dmabuf->dmasize - pending; |
1682 | if (dmabuf->enable || pending >= dmabuf->userfragsize) | 1683 | if (dmabuf->enable || pending >= dmabuf->userfragsize) |
1683 | i810_update_lvi(state, 1); | 1684 | i810_update_lvi(state, 1); |
1684 | set_current_state(TASK_RUNNING); | 1685 | set_current_state(TASK_RUNNING); |
1685 | remove_wait_queue(&dmabuf->wait, &waita); | 1686 | remove_wait_queue(&dmabuf->wait, &waita); |
1686 | 1687 | ||
1687 | return ret; | 1688 | return ret; |
1688 | } | 1689 | } |
1689 | 1690 | ||
1690 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to | 1691 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to |
1691 | the soundcard. it is drained by the dma machine and filled by this loop. */ | 1692 | the soundcard. it is drained by the dma machine and filled by this loop. */ |
1692 | static ssize_t i810_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 1693 | static ssize_t i810_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
1693 | { | 1694 | { |
1694 | struct i810_state *state = (struct i810_state *)file->private_data; | 1695 | struct i810_state *state = (struct i810_state *)file->private_data; |
1695 | struct i810_card *card=state ? state->card : NULL; | 1696 | struct i810_card *card=state ? state->card : NULL; |
1696 | struct dmabuf *dmabuf = &state->dmabuf; | 1697 | struct dmabuf *dmabuf = &state->dmabuf; |
1697 | ssize_t ret; | 1698 | ssize_t ret; |
1698 | unsigned long flags; | 1699 | unsigned long flags; |
1699 | unsigned int swptr = 0; | 1700 | unsigned int swptr = 0; |
1700 | int pending; | 1701 | int pending; |
1701 | int cnt; | 1702 | int cnt; |
1702 | DECLARE_WAITQUEUE(waita, current); | 1703 | DECLARE_WAITQUEUE(waita, current); |
1703 | 1704 | ||
1704 | #ifdef DEBUG2 | 1705 | #ifdef DEBUG2 |
1705 | printk("i810_audio: i810_write called, count = %d\n", count); | 1706 | printk("i810_audio: i810_write called, count = %d\n", count); |
1706 | #endif | 1707 | #endif |
1707 | 1708 | ||
1708 | if (dmabuf->mapped) | 1709 | if (dmabuf->mapped) |
1709 | return -ENXIO; | 1710 | return -ENXIO; |
1710 | if (dmabuf->enable & ADC_RUNNING) | 1711 | if (dmabuf->enable & ADC_RUNNING) |
1711 | return -ENODEV; | 1712 | return -ENODEV; |
1712 | if (!dmabuf->write_channel) { | 1713 | if (!dmabuf->write_channel) { |
1713 | dmabuf->ready = 0; | 1714 | dmabuf->ready = 0; |
1714 | dmabuf->write_channel = card->alloc_pcm_channel(card); | 1715 | dmabuf->write_channel = card->alloc_pcm_channel(card); |
1715 | if(!dmabuf->write_channel) | 1716 | if(!dmabuf->write_channel) |
1716 | return -EBUSY; | 1717 | return -EBUSY; |
1717 | } | 1718 | } |
1718 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) | 1719 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) |
1719 | return ret; | 1720 | return ret; |
1720 | if (!access_ok(VERIFY_READ, buffer, count)) | 1721 | if (!access_ok(VERIFY_READ, buffer, count)) |
1721 | return -EFAULT; | 1722 | return -EFAULT; |
1722 | ret = 0; | 1723 | ret = 0; |
1723 | 1724 | ||
1724 | pending = 0; | 1725 | pending = 0; |
1725 | 1726 | ||
1726 | add_wait_queue(&dmabuf->wait, &waita); | 1727 | add_wait_queue(&dmabuf->wait, &waita); |
1727 | while (count > 0) { | 1728 | while (count > 0) { |
1728 | set_current_state(TASK_INTERRUPTIBLE); | 1729 | set_current_state(TASK_INTERRUPTIBLE); |
1729 | spin_lock_irqsave(&state->card->lock, flags); | 1730 | spin_lock_irqsave(&state->card->lock, flags); |
1730 | if (PM_SUSPENDED(card)) { | 1731 | if (PM_SUSPENDED(card)) { |
1731 | spin_unlock_irqrestore(&card->lock, flags); | 1732 | spin_unlock_irqrestore(&card->lock, flags); |
1732 | schedule(); | 1733 | schedule(); |
1733 | if (signal_pending(current)) { | 1734 | if (signal_pending(current)) { |
1734 | if (!ret) ret = -EAGAIN; | 1735 | if (!ret) ret = -EAGAIN; |
1735 | break; | 1736 | break; |
1736 | } | 1737 | } |
1737 | continue; | 1738 | continue; |
1738 | } | 1739 | } |
1739 | 1740 | ||
1740 | cnt = i810_get_free_write_space(state); | 1741 | cnt = i810_get_free_write_space(state); |
1741 | swptr = dmabuf->swptr; | 1742 | swptr = dmabuf->swptr; |
1742 | /* Bound the maximum size to how much we can copy to the | 1743 | /* Bound the maximum size to how much we can copy to the |
1743 | * dma buffer before we hit the end. If we have more to | 1744 | * dma buffer before we hit the end. If we have more to |
1744 | * copy then it will get done in a second pass of this | 1745 | * copy then it will get done in a second pass of this |
1745 | * loop starting from the beginning of the buffer. | 1746 | * loop starting from the beginning of the buffer. |
1746 | */ | 1747 | */ |
1747 | if(cnt > (dmabuf->dmasize - swptr)) | 1748 | if(cnt > (dmabuf->dmasize - swptr)) |
1748 | cnt = dmabuf->dmasize - swptr; | 1749 | cnt = dmabuf->dmasize - swptr; |
1749 | spin_unlock_irqrestore(&state->card->lock, flags); | 1750 | spin_unlock_irqrestore(&state->card->lock, flags); |
1750 | 1751 | ||
1751 | #ifdef DEBUG2 | 1752 | #ifdef DEBUG2 |
1752 | printk(KERN_INFO "i810_audio: i810_write: %d bytes available space\n", cnt); | 1753 | printk(KERN_INFO "i810_audio: i810_write: %d bytes available space\n", cnt); |
1753 | #endif | 1754 | #endif |
1754 | if (cnt > count) | 1755 | if (cnt > count) |
1755 | cnt = count; | 1756 | cnt = count; |
1756 | if (cnt <= 0) { | 1757 | if (cnt <= 0) { |
1757 | unsigned long tmo; | 1758 | unsigned long tmo; |
1758 | // There is data waiting to be played | 1759 | // There is data waiting to be played |
1759 | /* | 1760 | /* |
1760 | * Force the trigger setting since we would | 1761 | * Force the trigger setting since we would |
1761 | * deadlock with it set any other way | 1762 | * deadlock with it set any other way |
1762 | */ | 1763 | */ |
1763 | dmabuf->trigger = PCM_ENABLE_OUTPUT; | 1764 | dmabuf->trigger = PCM_ENABLE_OUTPUT; |
1764 | i810_update_lvi(state,0); | 1765 | i810_update_lvi(state,0); |
1765 | if (file->f_flags & O_NONBLOCK) { | 1766 | if (file->f_flags & O_NONBLOCK) { |
1766 | if (!ret) ret = -EAGAIN; | 1767 | if (!ret) ret = -EAGAIN; |
1767 | goto ret; | 1768 | goto ret; |
1768 | } | 1769 | } |
1769 | /* Not strictly correct but works */ | 1770 | /* Not strictly correct but works */ |
1770 | tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4); | 1771 | tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4); |
1771 | /* There are two situations when sleep_on_timeout returns, one is when | 1772 | /* There are two situations when sleep_on_timeout returns, one is when |
1772 | the interrupt is serviced correctly and the process is waked up by | 1773 | the interrupt is serviced correctly and the process is waked up by |
1773 | ISR ON TIME. Another is when timeout is expired, which means that | 1774 | ISR ON TIME. Another is when timeout is expired, which means that |
1774 | either interrupt is NOT serviced correctly (pending interrupt) or it | 1775 | either interrupt is NOT serviced correctly (pending interrupt) or it |
1775 | is TOO LATE for the process to be scheduled to run (scheduler latency) | 1776 | is TOO LATE for the process to be scheduled to run (scheduler latency) |
1776 | which results in a (potential) buffer underrun. And worse, there is | 1777 | which results in a (potential) buffer underrun. And worse, there is |
1777 | NOTHING we can do to prevent it. */ | 1778 | NOTHING we can do to prevent it. */ |
1778 | if (!schedule_timeout(tmo >= 2 ? tmo : 2)) { | 1779 | if (!schedule_timeout(tmo >= 2 ? tmo : 2)) { |
1779 | #ifdef DEBUG | 1780 | #ifdef DEBUG |
1780 | printk(KERN_ERR "i810_audio: playback schedule timeout, " | 1781 | printk(KERN_ERR "i810_audio: playback schedule timeout, " |
1781 | "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", | 1782 | "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", |
1782 | dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, | 1783 | dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, |
1783 | dmabuf->hwptr, dmabuf->swptr); | 1784 | dmabuf->hwptr, dmabuf->swptr); |
1784 | #endif | 1785 | #endif |
1785 | /* a buffer underrun, we delay the recovery until next time the | 1786 | /* a buffer underrun, we delay the recovery until next time the |
1786 | while loop begin and we REALLY have data to play */ | 1787 | while loop begin and we REALLY have data to play */ |
1787 | //return ret; | 1788 | //return ret; |
1788 | } | 1789 | } |
1789 | if (signal_pending(current)) { | 1790 | if (signal_pending(current)) { |
1790 | if (!ret) ret = -ERESTARTSYS; | 1791 | if (!ret) ret = -ERESTARTSYS; |
1791 | goto ret; | 1792 | goto ret; |
1792 | } | 1793 | } |
1793 | continue; | 1794 | continue; |
1794 | } | 1795 | } |
1795 | if (copy_from_user(dmabuf->rawbuf+swptr,buffer,cnt)) { | 1796 | if (copy_from_user(dmabuf->rawbuf+swptr,buffer,cnt)) { |
1796 | if (!ret) ret = -EFAULT; | 1797 | if (!ret) ret = -EFAULT; |
1797 | goto ret; | 1798 | goto ret; |
1798 | } | 1799 | } |
1799 | 1800 | ||
1800 | swptr = MODULOP2(swptr + cnt, dmabuf->dmasize); | 1801 | swptr = MODULOP2(swptr + cnt, dmabuf->dmasize); |
1801 | 1802 | ||
1802 | spin_lock_irqsave(&state->card->lock, flags); | 1803 | spin_lock_irqsave(&state->card->lock, flags); |
1803 | if (PM_SUSPENDED(card)) { | 1804 | if (PM_SUSPENDED(card)) { |
1804 | spin_unlock_irqrestore(&card->lock, flags); | 1805 | spin_unlock_irqrestore(&card->lock, flags); |
1805 | continue; | 1806 | continue; |
1806 | } | 1807 | } |
1807 | 1808 | ||
1808 | dmabuf->swptr = swptr; | 1809 | dmabuf->swptr = swptr; |
1809 | pending = dmabuf->count += cnt; | 1810 | pending = dmabuf->count += cnt; |
1810 | 1811 | ||
1811 | count -= cnt; | 1812 | count -= cnt; |
1812 | buffer += cnt; | 1813 | buffer += cnt; |
1813 | ret += cnt; | 1814 | ret += cnt; |
1814 | spin_unlock_irqrestore(&state->card->lock, flags); | 1815 | spin_unlock_irqrestore(&state->card->lock, flags); |
1815 | } | 1816 | } |
1816 | ret: | 1817 | ret: |
1817 | if (dmabuf->enable || pending >= dmabuf->userfragsize) | 1818 | if (dmabuf->enable || pending >= dmabuf->userfragsize) |
1818 | i810_update_lvi(state, 0); | 1819 | i810_update_lvi(state, 0); |
1819 | set_current_state(TASK_RUNNING); | 1820 | set_current_state(TASK_RUNNING); |
1820 | remove_wait_queue(&dmabuf->wait, &waita); | 1821 | remove_wait_queue(&dmabuf->wait, &waita); |
1821 | 1822 | ||
1822 | return ret; | 1823 | return ret; |
1823 | } | 1824 | } |
1824 | 1825 | ||
1825 | /* No kernel lock - we have our own spinlock */ | 1826 | /* No kernel lock - we have our own spinlock */ |
1826 | static unsigned int i810_poll(struct file *file, struct poll_table_struct *wait) | 1827 | static unsigned int i810_poll(struct file *file, struct poll_table_struct *wait) |
1827 | { | 1828 | { |
1828 | struct i810_state *state = (struct i810_state *)file->private_data; | 1829 | struct i810_state *state = (struct i810_state *)file->private_data; |
1829 | struct dmabuf *dmabuf = &state->dmabuf; | 1830 | struct dmabuf *dmabuf = &state->dmabuf; |
1830 | unsigned long flags; | 1831 | unsigned long flags; |
1831 | unsigned int mask = 0; | 1832 | unsigned int mask = 0; |
1832 | 1833 | ||
1833 | if(!dmabuf->ready) | 1834 | if(!dmabuf->ready) |
1834 | return 0; | 1835 | return 0; |
1835 | poll_wait(file, &dmabuf->wait, wait); | 1836 | poll_wait(file, &dmabuf->wait, wait); |
1836 | spin_lock_irqsave(&state->card->lock, flags); | 1837 | spin_lock_irqsave(&state->card->lock, flags); |
1837 | if (dmabuf->enable & ADC_RUNNING || | 1838 | if (dmabuf->enable & ADC_RUNNING || |
1838 | dmabuf->trigger & PCM_ENABLE_INPUT) { | 1839 | dmabuf->trigger & PCM_ENABLE_INPUT) { |
1839 | if (i810_get_available_read_data(state) >= | 1840 | if (i810_get_available_read_data(state) >= |
1840 | (signed)dmabuf->userfragsize) | 1841 | (signed)dmabuf->userfragsize) |
1841 | mask |= POLLIN | POLLRDNORM; | 1842 | mask |= POLLIN | POLLRDNORM; |
1842 | } | 1843 | } |
1843 | if (dmabuf->enable & DAC_RUNNING || | 1844 | if (dmabuf->enable & DAC_RUNNING || |
1844 | dmabuf->trigger & PCM_ENABLE_OUTPUT) { | 1845 | dmabuf->trigger & PCM_ENABLE_OUTPUT) { |
1845 | if (i810_get_free_write_space(state) >= | 1846 | if (i810_get_free_write_space(state) >= |
1846 | (signed)dmabuf->userfragsize) | 1847 | (signed)dmabuf->userfragsize) |
1847 | mask |= POLLOUT | POLLWRNORM; | 1848 | mask |= POLLOUT | POLLWRNORM; |
1848 | } | 1849 | } |
1849 | spin_unlock_irqrestore(&state->card->lock, flags); | 1850 | spin_unlock_irqrestore(&state->card->lock, flags); |
1850 | return mask; | 1851 | return mask; |
1851 | } | 1852 | } |
1852 | 1853 | ||
1853 | static int i810_mmap(struct file *file, struct vm_area_struct *vma) | 1854 | static int i810_mmap(struct file *file, struct vm_area_struct *vma) |
1854 | { | 1855 | { |
1855 | struct i810_state *state = (struct i810_state *)file->private_data; | 1856 | struct i810_state *state = (struct i810_state *)file->private_data; |
1856 | struct dmabuf *dmabuf = &state->dmabuf; | 1857 | struct dmabuf *dmabuf = &state->dmabuf; |
1857 | int ret = -EINVAL; | 1858 | int ret = -EINVAL; |
1858 | unsigned long size; | 1859 | unsigned long size; |
1859 | 1860 | ||
1860 | lock_kernel(); | 1861 | lock_kernel(); |
1861 | if (vma->vm_flags & VM_WRITE) { | 1862 | if (vma->vm_flags & VM_WRITE) { |
1862 | if (!dmabuf->write_channel && | 1863 | if (!dmabuf->write_channel && |
1863 | (dmabuf->write_channel = | 1864 | (dmabuf->write_channel = |
1864 | state->card->alloc_pcm_channel(state->card)) == NULL) { | 1865 | state->card->alloc_pcm_channel(state->card)) == NULL) { |
1865 | ret = -EBUSY; | 1866 | ret = -EBUSY; |
1866 | goto out; | 1867 | goto out; |
1867 | } | 1868 | } |
1868 | } | 1869 | } |
1869 | if (vma->vm_flags & VM_READ) { | 1870 | if (vma->vm_flags & VM_READ) { |
1870 | if (!dmabuf->read_channel && | 1871 | if (!dmabuf->read_channel && |
1871 | (dmabuf->read_channel = | 1872 | (dmabuf->read_channel = |
1872 | state->card->alloc_rec_pcm_channel(state->card)) == NULL) { | 1873 | state->card->alloc_rec_pcm_channel(state->card)) == NULL) { |
1873 | ret = -EBUSY; | 1874 | ret = -EBUSY; |
1874 | goto out; | 1875 | goto out; |
1875 | } | 1876 | } |
1876 | } | 1877 | } |
1877 | if ((ret = prog_dmabuf(state, 0)) != 0) | 1878 | if ((ret = prog_dmabuf(state, 0)) != 0) |
1878 | goto out; | 1879 | goto out; |
1879 | 1880 | ||
1880 | ret = -EINVAL; | 1881 | ret = -EINVAL; |
1881 | if (vma->vm_pgoff != 0) | 1882 | if (vma->vm_pgoff != 0) |
1882 | goto out; | 1883 | goto out; |
1883 | size = vma->vm_end - vma->vm_start; | 1884 | size = vma->vm_end - vma->vm_start; |
1884 | if (size > (PAGE_SIZE << dmabuf->buforder)) | 1885 | if (size > (PAGE_SIZE << dmabuf->buforder)) |
1885 | goto out; | 1886 | goto out; |
1886 | ret = -EAGAIN; | 1887 | ret = -EAGAIN; |
1887 | if (remap_pfn_range(vma, vma->vm_start, | 1888 | if (remap_pfn_range(vma, vma->vm_start, |
1888 | virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT, | 1889 | virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT, |
1889 | size, vma->vm_page_prot)) | 1890 | size, vma->vm_page_prot)) |
1890 | goto out; | 1891 | goto out; |
1891 | dmabuf->mapped = 1; | 1892 | dmabuf->mapped = 1; |
1892 | dmabuf->trigger = 0; | 1893 | dmabuf->trigger = 0; |
1893 | ret = 0; | 1894 | ret = 0; |
1894 | #ifdef DEBUG_MMAP | 1895 | #ifdef DEBUG_MMAP |
1895 | printk("i810_audio: mmap'ed %ld bytes of data space\n", size); | 1896 | printk("i810_audio: mmap'ed %ld bytes of data space\n", size); |
1896 | #endif | 1897 | #endif |
1897 | out: | 1898 | out: |
1898 | unlock_kernel(); | 1899 | unlock_kernel(); |
1899 | return ret; | 1900 | return ret; |
1900 | } | 1901 | } |
1901 | 1902 | ||
1902 | static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 1903 | static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
1903 | { | 1904 | { |
1904 | struct i810_state *state = (struct i810_state *)file->private_data; | 1905 | struct i810_state *state = (struct i810_state *)file->private_data; |
1905 | struct i810_channel *c = NULL; | 1906 | struct i810_channel *c = NULL; |
1906 | struct dmabuf *dmabuf = &state->dmabuf; | 1907 | struct dmabuf *dmabuf = &state->dmabuf; |
1907 | unsigned long flags; | 1908 | unsigned long flags; |
1908 | audio_buf_info abinfo; | 1909 | audio_buf_info abinfo; |
1909 | count_info cinfo; | 1910 | count_info cinfo; |
1910 | unsigned int i_glob_cnt; | 1911 | unsigned int i_glob_cnt; |
1911 | int val = 0, ret; | 1912 | int val = 0, ret; |
1912 | struct ac97_codec *codec = state->card->ac97_codec[0]; | 1913 | struct ac97_codec *codec = state->card->ac97_codec[0]; |
1913 | void __user *argp = (void __user *)arg; | 1914 | void __user *argp = (void __user *)arg; |
1914 | int __user *p = argp; | 1915 | int __user *p = argp; |
1915 | 1916 | ||
1916 | #ifdef DEBUG | 1917 | #ifdef DEBUG |
1917 | printk("i810_audio: i810_ioctl, arg=0x%x, cmd=", arg ? *p : 0); | 1918 | printk("i810_audio: i810_ioctl, arg=0x%x, cmd=", arg ? *p : 0); |
1918 | #endif | 1919 | #endif |
1919 | 1920 | ||
1920 | switch (cmd) | 1921 | switch (cmd) |
1921 | { | 1922 | { |
1922 | case OSS_GETVERSION: | 1923 | case OSS_GETVERSION: |
1923 | #ifdef DEBUG | 1924 | #ifdef DEBUG |
1924 | printk("OSS_GETVERSION\n"); | 1925 | printk("OSS_GETVERSION\n"); |
1925 | #endif | 1926 | #endif |
1926 | return put_user(SOUND_VERSION, p); | 1927 | return put_user(SOUND_VERSION, p); |
1927 | 1928 | ||
1928 | case SNDCTL_DSP_RESET: | 1929 | case SNDCTL_DSP_RESET: |
1929 | #ifdef DEBUG | 1930 | #ifdef DEBUG |
1930 | printk("SNDCTL_DSP_RESET\n"); | 1931 | printk("SNDCTL_DSP_RESET\n"); |
1931 | #endif | 1932 | #endif |
1932 | spin_lock_irqsave(&state->card->lock, flags); | 1933 | spin_lock_irqsave(&state->card->lock, flags); |
1933 | if (dmabuf->enable == DAC_RUNNING) { | 1934 | if (dmabuf->enable == DAC_RUNNING) { |
1934 | c = dmabuf->write_channel; | 1935 | c = dmabuf->write_channel; |
1935 | __stop_dac(state); | 1936 | __stop_dac(state); |
1936 | } | 1937 | } |
1937 | if (dmabuf->enable == ADC_RUNNING) { | 1938 | if (dmabuf->enable == ADC_RUNNING) { |
1938 | c = dmabuf->read_channel; | 1939 | c = dmabuf->read_channel; |
1939 | __stop_adc(state); | 1940 | __stop_adc(state); |
1940 | } | 1941 | } |
1941 | if (c != NULL) { | 1942 | if (c != NULL) { |
1942 | I810_IOWRITEB(2, state->card, c->port+OFF_CR); /* reset DMA machine */ | 1943 | I810_IOWRITEB(2, state->card, c->port+OFF_CR); /* reset DMA machine */ |
1943 | while ( I810_IOREADB(state->card, c->port+OFF_CR) & 2 ) | 1944 | while ( I810_IOREADB(state->card, c->port+OFF_CR) & 2 ) |
1944 | cpu_relax(); | 1945 | cpu_relax(); |
1945 | I810_IOWRITEL((u32)state->card->chandma + | 1946 | I810_IOWRITEL((u32)state->card->chandma + |
1946 | c->num*sizeof(struct i810_channel), | 1947 | c->num*sizeof(struct i810_channel), |
1947 | state->card, c->port+OFF_BDBAR); | 1948 | state->card, c->port+OFF_BDBAR); |
1948 | CIV_TO_LVI(state->card, c->port, 0); | 1949 | CIV_TO_LVI(state->card, c->port, 0); |
1949 | } | 1950 | } |
1950 | 1951 | ||
1951 | spin_unlock_irqrestore(&state->card->lock, flags); | 1952 | spin_unlock_irqrestore(&state->card->lock, flags); |
1952 | synchronize_irq(state->card->pci_dev->irq); | 1953 | synchronize_irq(state->card->pci_dev->irq); |
1953 | dmabuf->ready = 0; | 1954 | dmabuf->ready = 0; |
1954 | dmabuf->swptr = dmabuf->hwptr = 0; | 1955 | dmabuf->swptr = dmabuf->hwptr = 0; |
1955 | dmabuf->count = dmabuf->total_bytes = 0; | 1956 | dmabuf->count = dmabuf->total_bytes = 0; |
1956 | return 0; | 1957 | return 0; |
1957 | 1958 | ||
1958 | case SNDCTL_DSP_SYNC: | 1959 | case SNDCTL_DSP_SYNC: |
1959 | #ifdef DEBUG | 1960 | #ifdef DEBUG |
1960 | printk("SNDCTL_DSP_SYNC\n"); | 1961 | printk("SNDCTL_DSP_SYNC\n"); |
1961 | #endif | 1962 | #endif |
1962 | if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK) | 1963 | if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK) |
1963 | return 0; | 1964 | return 0; |
1964 | if((val = drain_dac(state, 1))) | 1965 | if((val = drain_dac(state, 1))) |
1965 | return val; | 1966 | return val; |
1966 | dmabuf->total_bytes = 0; | 1967 | dmabuf->total_bytes = 0; |
1967 | return 0; | 1968 | return 0; |
1968 | 1969 | ||
1969 | case SNDCTL_DSP_SPEED: /* set smaple rate */ | 1970 | case SNDCTL_DSP_SPEED: /* set smaple rate */ |
1970 | #ifdef DEBUG | 1971 | #ifdef DEBUG |
1971 | printk("SNDCTL_DSP_SPEED\n"); | 1972 | printk("SNDCTL_DSP_SPEED\n"); |
1972 | #endif | 1973 | #endif |
1973 | if (get_user(val, p)) | 1974 | if (get_user(val, p)) |
1974 | return -EFAULT; | 1975 | return -EFAULT; |
1975 | if (val >= 0) { | 1976 | if (val >= 0) { |
1976 | if (file->f_mode & FMODE_WRITE) { | 1977 | if (file->f_mode & FMODE_WRITE) { |
1977 | if ( (state->card->ac97_status & SPDIF_ON) ) { /* S/PDIF Enabled */ | 1978 | if ( (state->card->ac97_status & SPDIF_ON) ) { /* S/PDIF Enabled */ |
1978 | /* AD1886 only supports 48000, need to check that */ | 1979 | /* AD1886 only supports 48000, need to check that */ |
1979 | if ( i810_valid_spdif_rate ( codec, val ) ) { | 1980 | if ( i810_valid_spdif_rate ( codec, val ) ) { |
1980 | /* Set DAC rate */ | 1981 | /* Set DAC rate */ |
1981 | i810_set_spdif_output ( state, -1, 0 ); | 1982 | i810_set_spdif_output ( state, -1, 0 ); |
1982 | stop_dac(state); | 1983 | stop_dac(state); |
1983 | dmabuf->ready = 0; | 1984 | dmabuf->ready = 0; |
1984 | spin_lock_irqsave(&state->card->lock, flags); | 1985 | spin_lock_irqsave(&state->card->lock, flags); |
1985 | i810_set_dac_rate(state, val); | 1986 | i810_set_dac_rate(state, val); |
1986 | spin_unlock_irqrestore(&state->card->lock, flags); | 1987 | spin_unlock_irqrestore(&state->card->lock, flags); |
1987 | /* Set S/PDIF transmitter rate. */ | 1988 | /* Set S/PDIF transmitter rate. */ |
1988 | i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, val ); | 1989 | i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, val ); |
1989 | if ( ! (state->card->ac97_status & SPDIF_ON) ) { | 1990 | if ( ! (state->card->ac97_status & SPDIF_ON) ) { |
1990 | val = dmabuf->rate; | 1991 | val = dmabuf->rate; |
1991 | } | 1992 | } |
1992 | } else { /* Not a valid rate for S/PDIF, ignore it */ | 1993 | } else { /* Not a valid rate for S/PDIF, ignore it */ |
1993 | val = dmabuf->rate; | 1994 | val = dmabuf->rate; |
1994 | } | 1995 | } |
1995 | } else { | 1996 | } else { |
1996 | stop_dac(state); | 1997 | stop_dac(state); |
1997 | dmabuf->ready = 0; | 1998 | dmabuf->ready = 0; |
1998 | spin_lock_irqsave(&state->card->lock, flags); | 1999 | spin_lock_irqsave(&state->card->lock, flags); |
1999 | i810_set_dac_rate(state, val); | 2000 | i810_set_dac_rate(state, val); |
2000 | spin_unlock_irqrestore(&state->card->lock, flags); | 2001 | spin_unlock_irqrestore(&state->card->lock, flags); |
2001 | } | 2002 | } |
2002 | } | 2003 | } |
2003 | if (file->f_mode & FMODE_READ) { | 2004 | if (file->f_mode & FMODE_READ) { |
2004 | stop_adc(state); | 2005 | stop_adc(state); |
2005 | dmabuf->ready = 0; | 2006 | dmabuf->ready = 0; |
2006 | spin_lock_irqsave(&state->card->lock, flags); | 2007 | spin_lock_irqsave(&state->card->lock, flags); |
2007 | i810_set_adc_rate(state, val); | 2008 | i810_set_adc_rate(state, val); |
2008 | spin_unlock_irqrestore(&state->card->lock, flags); | 2009 | spin_unlock_irqrestore(&state->card->lock, flags); |
2009 | } | 2010 | } |
2010 | } | 2011 | } |
2011 | return put_user(dmabuf->rate, p); | 2012 | return put_user(dmabuf->rate, p); |
2012 | 2013 | ||
2013 | case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ | 2014 | case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ |
2014 | #ifdef DEBUG | 2015 | #ifdef DEBUG |
2015 | printk("SNDCTL_DSP_STEREO\n"); | 2016 | printk("SNDCTL_DSP_STEREO\n"); |
2016 | #endif | 2017 | #endif |
2017 | if (dmabuf->enable & DAC_RUNNING) { | 2018 | if (dmabuf->enable & DAC_RUNNING) { |
2018 | stop_dac(state); | 2019 | stop_dac(state); |
2019 | } | 2020 | } |
2020 | if (dmabuf->enable & ADC_RUNNING) { | 2021 | if (dmabuf->enable & ADC_RUNNING) { |
2021 | stop_adc(state); | 2022 | stop_adc(state); |
2022 | } | 2023 | } |
2023 | return put_user(1, p); | 2024 | return put_user(1, p); |
2024 | 2025 | ||
2025 | case SNDCTL_DSP_GETBLKSIZE: | 2026 | case SNDCTL_DSP_GETBLKSIZE: |
2026 | if (file->f_mode & FMODE_WRITE) { | 2027 | if (file->f_mode & FMODE_WRITE) { |
2027 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0))) | 2028 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0))) |
2028 | return val; | 2029 | return val; |
2029 | } | 2030 | } |
2030 | if (file->f_mode & FMODE_READ) { | 2031 | if (file->f_mode & FMODE_READ) { |
2031 | if (!dmabuf->ready && (val = prog_dmabuf(state, 1))) | 2032 | if (!dmabuf->ready && (val = prog_dmabuf(state, 1))) |
2032 | return val; | 2033 | return val; |
2033 | } | 2034 | } |
2034 | #ifdef DEBUG | 2035 | #ifdef DEBUG |
2035 | printk("SNDCTL_DSP_GETBLKSIZE %d\n", dmabuf->userfragsize); | 2036 | printk("SNDCTL_DSP_GETBLKSIZE %d\n", dmabuf->userfragsize); |
2036 | #endif | 2037 | #endif |
2037 | return put_user(dmabuf->userfragsize, p); | 2038 | return put_user(dmabuf->userfragsize, p); |
2038 | 2039 | ||
2039 | case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ | 2040 | case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ |
2040 | #ifdef DEBUG | 2041 | #ifdef DEBUG |
2041 | printk("SNDCTL_DSP_GETFMTS\n"); | 2042 | printk("SNDCTL_DSP_GETFMTS\n"); |
2042 | #endif | 2043 | #endif |
2043 | return put_user(AFMT_S16_LE, p); | 2044 | return put_user(AFMT_S16_LE, p); |
2044 | 2045 | ||
2045 | case SNDCTL_DSP_SETFMT: /* Select sample format */ | 2046 | case SNDCTL_DSP_SETFMT: /* Select sample format */ |
2046 | #ifdef DEBUG | 2047 | #ifdef DEBUG |
2047 | printk("SNDCTL_DSP_SETFMT\n"); | 2048 | printk("SNDCTL_DSP_SETFMT\n"); |
2048 | #endif | 2049 | #endif |
2049 | return put_user(AFMT_S16_LE, p); | 2050 | return put_user(AFMT_S16_LE, p); |
2050 | 2051 | ||
2051 | case SNDCTL_DSP_CHANNELS: | 2052 | case SNDCTL_DSP_CHANNELS: |
2052 | #ifdef DEBUG | 2053 | #ifdef DEBUG |
2053 | printk("SNDCTL_DSP_CHANNELS\n"); | 2054 | printk("SNDCTL_DSP_CHANNELS\n"); |
2054 | #endif | 2055 | #endif |
2055 | if (get_user(val, p)) | 2056 | if (get_user(val, p)) |
2056 | return -EFAULT; | 2057 | return -EFAULT; |
2057 | 2058 | ||
2058 | if (val > 0) { | 2059 | if (val > 0) { |
2059 | if (dmabuf->enable & DAC_RUNNING) { | 2060 | if (dmabuf->enable & DAC_RUNNING) { |
2060 | stop_dac(state); | 2061 | stop_dac(state); |
2061 | } | 2062 | } |
2062 | if (dmabuf->enable & ADC_RUNNING) { | 2063 | if (dmabuf->enable & ADC_RUNNING) { |
2063 | stop_adc(state); | 2064 | stop_adc(state); |
2064 | } | 2065 | } |
2065 | } else { | 2066 | } else { |
2066 | return put_user(state->card->channels, p); | 2067 | return put_user(state->card->channels, p); |
2067 | } | 2068 | } |
2068 | 2069 | ||
2069 | /* ICH and ICH0 only support 2 channels */ | 2070 | /* ICH and ICH0 only support 2 channels */ |
2070 | if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AA_5 | 2071 | if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AA_5 |
2071 | || state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AB_5) | 2072 | || state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AB_5) |
2072 | return put_user(2, p); | 2073 | return put_user(2, p); |
2073 | 2074 | ||
2074 | /* Multi-channel support was added with ICH2. Bits in */ | 2075 | /* Multi-channel support was added with ICH2. Bits in */ |
2075 | /* Global Status and Global Control register are now */ | 2076 | /* Global Status and Global Control register are now */ |
2076 | /* used to indicate this. */ | 2077 | /* used to indicate this. */ |
2077 | 2078 | ||
2078 | i_glob_cnt = I810_IOREADL(state->card, GLOB_CNT); | 2079 | i_glob_cnt = I810_IOREADL(state->card, GLOB_CNT); |
2079 | 2080 | ||
2080 | /* Current # of channels enabled */ | 2081 | /* Current # of channels enabled */ |
2081 | if ( i_glob_cnt & 0x0100000 ) | 2082 | if ( i_glob_cnt & 0x0100000 ) |
2082 | ret = 4; | 2083 | ret = 4; |
2083 | else if ( i_glob_cnt & 0x0200000 ) | 2084 | else if ( i_glob_cnt & 0x0200000 ) |
2084 | ret = 6; | 2085 | ret = 6; |
2085 | else | 2086 | else |
2086 | ret = 2; | 2087 | ret = 2; |
2087 | 2088 | ||
2088 | switch ( val ) { | 2089 | switch ( val ) { |
2089 | case 2: /* 2 channels is always supported */ | 2090 | case 2: /* 2 channels is always supported */ |
2090 | I810_IOWRITEL(i_glob_cnt & 0xffcfffff, | 2091 | I810_IOWRITEL(i_glob_cnt & 0xffcfffff, |
2091 | state->card, GLOB_CNT); | 2092 | state->card, GLOB_CNT); |
2092 | /* Do we need to change mixer settings???? */ | 2093 | /* Do we need to change mixer settings???? */ |
2093 | break; | 2094 | break; |
2094 | case 4: /* Supported on some chipsets, better check first */ | 2095 | case 4: /* Supported on some chipsets, better check first */ |
2095 | if ( state->card->channels >= 4 ) { | 2096 | if ( state->card->channels >= 4 ) { |
2096 | I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x100000, | 2097 | I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x100000, |
2097 | state->card, GLOB_CNT); | 2098 | state->card, GLOB_CNT); |
2098 | /* Do we need to change mixer settings??? */ | 2099 | /* Do we need to change mixer settings??? */ |
2099 | } else { | 2100 | } else { |
2100 | val = ret; | 2101 | val = ret; |
2101 | } | 2102 | } |
2102 | break; | 2103 | break; |
2103 | case 6: /* Supported on some chipsets, better check first */ | 2104 | case 6: /* Supported on some chipsets, better check first */ |
2104 | if ( state->card->channels >= 6 ) { | 2105 | if ( state->card->channels >= 6 ) { |
2105 | I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x200000, | 2106 | I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x200000, |
2106 | state->card, GLOB_CNT); | 2107 | state->card, GLOB_CNT); |
2107 | /* Do we need to change mixer settings??? */ | 2108 | /* Do we need to change mixer settings??? */ |
2108 | } else { | 2109 | } else { |
2109 | val = ret; | 2110 | val = ret; |
2110 | } | 2111 | } |
2111 | break; | 2112 | break; |
2112 | default: /* nothing else is ever supported by the chipset */ | 2113 | default: /* nothing else is ever supported by the chipset */ |
2113 | val = ret; | 2114 | val = ret; |
2114 | break; | 2115 | break; |
2115 | } | 2116 | } |
2116 | 2117 | ||
2117 | return put_user(val, p); | 2118 | return put_user(val, p); |
2118 | 2119 | ||
2119 | case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */ | 2120 | case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */ |
2120 | /* we update the swptr to the end of the last sg segment then return */ | 2121 | /* we update the swptr to the end of the last sg segment then return */ |
2121 | #ifdef DEBUG | 2122 | #ifdef DEBUG |
2122 | printk("SNDCTL_DSP_POST\n"); | 2123 | printk("SNDCTL_DSP_POST\n"); |
2123 | #endif | 2124 | #endif |
2124 | if(!dmabuf->ready || (dmabuf->enable != DAC_RUNNING)) | 2125 | if(!dmabuf->ready || (dmabuf->enable != DAC_RUNNING)) |
2125 | return 0; | 2126 | return 0; |
2126 | if((dmabuf->swptr % dmabuf->fragsize) != 0) { | 2127 | if((dmabuf->swptr % dmabuf->fragsize) != 0) { |
2127 | val = dmabuf->fragsize - (dmabuf->swptr % dmabuf->fragsize); | 2128 | val = dmabuf->fragsize - (dmabuf->swptr % dmabuf->fragsize); |
2128 | dmabuf->swptr += val; | 2129 | dmabuf->swptr += val; |
2129 | dmabuf->count += val; | 2130 | dmabuf->count += val; |
2130 | } | 2131 | } |
2131 | return 0; | 2132 | return 0; |
2132 | 2133 | ||
2133 | case SNDCTL_DSP_SUBDIVIDE: | 2134 | case SNDCTL_DSP_SUBDIVIDE: |
2134 | if (dmabuf->subdivision) | 2135 | if (dmabuf->subdivision) |
2135 | return -EINVAL; | 2136 | return -EINVAL; |
2136 | if (get_user(val, p)) | 2137 | if (get_user(val, p)) |
2137 | return -EFAULT; | 2138 | return -EFAULT; |
2138 | if (val != 1 && val != 2 && val != 4) | 2139 | if (val != 1 && val != 2 && val != 4) |
2139 | return -EINVAL; | 2140 | return -EINVAL; |
2140 | #ifdef DEBUG | 2141 | #ifdef DEBUG |
2141 | printk("SNDCTL_DSP_SUBDIVIDE %d\n", val); | 2142 | printk("SNDCTL_DSP_SUBDIVIDE %d\n", val); |
2142 | #endif | 2143 | #endif |
2143 | dmabuf->subdivision = val; | 2144 | dmabuf->subdivision = val; |
2144 | dmabuf->ready = 0; | 2145 | dmabuf->ready = 0; |
2145 | return 0; | 2146 | return 0; |
2146 | 2147 | ||
2147 | case SNDCTL_DSP_SETFRAGMENT: | 2148 | case SNDCTL_DSP_SETFRAGMENT: |
2148 | if (get_user(val, p)) | 2149 | if (get_user(val, p)) |
2149 | return -EFAULT; | 2150 | return -EFAULT; |
2150 | 2151 | ||
2151 | dmabuf->ossfragsize = 1<<(val & 0xffff); | 2152 | dmabuf->ossfragsize = 1<<(val & 0xffff); |
2152 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; | 2153 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; |
2153 | if (!dmabuf->ossfragsize || !dmabuf->ossmaxfrags) | 2154 | if (!dmabuf->ossfragsize || !dmabuf->ossmaxfrags) |
2154 | return -EINVAL; | 2155 | return -EINVAL; |
2155 | /* | 2156 | /* |
2156 | * Bound the frag size into our allowed range of 256 - 4096 | 2157 | * Bound the frag size into our allowed range of 256 - 4096 |
2157 | */ | 2158 | */ |
2158 | if (dmabuf->ossfragsize < 256) | 2159 | if (dmabuf->ossfragsize < 256) |
2159 | dmabuf->ossfragsize = 256; | 2160 | dmabuf->ossfragsize = 256; |
2160 | else if (dmabuf->ossfragsize > 4096) | 2161 | else if (dmabuf->ossfragsize > 4096) |
2161 | dmabuf->ossfragsize = 4096; | 2162 | dmabuf->ossfragsize = 4096; |
2162 | /* | 2163 | /* |
2163 | * The numfrags could be something reasonable, or it could | 2164 | * The numfrags could be something reasonable, or it could |
2164 | * be 0xffff meaning "Give me as much as possible". So, | 2165 | * be 0xffff meaning "Give me as much as possible". So, |
2165 | * we check the numfrags * fragsize doesn't exceed our | 2166 | * we check the numfrags * fragsize doesn't exceed our |
2166 | * 64k buffer limit, nor is it less than our 8k minimum. | 2167 | * 64k buffer limit, nor is it less than our 8k minimum. |
2167 | * If it fails either one of these checks, then adjust the | 2168 | * If it fails either one of these checks, then adjust the |
2168 | * number of fragments, not the size of them. It's OK if | 2169 | * number of fragments, not the size of them. It's OK if |
2169 | * our number of fragments doesn't equal 32 or anything | 2170 | * our number of fragments doesn't equal 32 or anything |
2170 | * like our hardware based number now since we are using | 2171 | * like our hardware based number now since we are using |
2171 | * a different frag count for the hardware. Before we get | 2172 | * a different frag count for the hardware. Before we get |
2172 | * into this though, bound the maxfrags to avoid overflow | 2173 | * into this though, bound the maxfrags to avoid overflow |
2173 | * issues. A reasonable bound would be 64k / 256 since our | 2174 | * issues. A reasonable bound would be 64k / 256 since our |
2174 | * maximum buffer size is 64k and our minimum frag size is | 2175 | * maximum buffer size is 64k and our minimum frag size is |
2175 | * 256. On the other end, our minimum buffer size is 8k and | 2176 | * 256. On the other end, our minimum buffer size is 8k and |
2176 | * our maximum frag size is 4k, so the lower bound should | 2177 | * our maximum frag size is 4k, so the lower bound should |
2177 | * be 2. | 2178 | * be 2. |
2178 | */ | 2179 | */ |
2179 | 2180 | ||
2180 | if(dmabuf->ossmaxfrags > 256) | 2181 | if(dmabuf->ossmaxfrags > 256) |
2181 | dmabuf->ossmaxfrags = 256; | 2182 | dmabuf->ossmaxfrags = 256; |
2182 | else if (dmabuf->ossmaxfrags < 2) | 2183 | else if (dmabuf->ossmaxfrags < 2) |
2183 | dmabuf->ossmaxfrags = 2; | 2184 | dmabuf->ossmaxfrags = 2; |
2184 | 2185 | ||
2185 | val = dmabuf->ossfragsize * dmabuf->ossmaxfrags; | 2186 | val = dmabuf->ossfragsize * dmabuf->ossmaxfrags; |
2186 | while (val < 8192) { | 2187 | while (val < 8192) { |
2187 | val <<= 1; | 2188 | val <<= 1; |
2188 | dmabuf->ossmaxfrags <<= 1; | 2189 | dmabuf->ossmaxfrags <<= 1; |
2189 | } | 2190 | } |
2190 | while (val > 65536) { | 2191 | while (val > 65536) { |
2191 | val >>= 1; | 2192 | val >>= 1; |
2192 | dmabuf->ossmaxfrags >>= 1; | 2193 | dmabuf->ossmaxfrags >>= 1; |
2193 | } | 2194 | } |
2194 | dmabuf->ready = 0; | 2195 | dmabuf->ready = 0; |
2195 | #ifdef DEBUG | 2196 | #ifdef DEBUG |
2196 | printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val, | 2197 | printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val, |
2197 | dmabuf->ossfragsize, dmabuf->ossmaxfrags); | 2198 | dmabuf->ossfragsize, dmabuf->ossmaxfrags); |
2198 | #endif | 2199 | #endif |
2199 | 2200 | ||
2200 | return 0; | 2201 | return 0; |
2201 | 2202 | ||
2202 | case SNDCTL_DSP_GETOSPACE: | 2203 | case SNDCTL_DSP_GETOSPACE: |
2203 | if (!(file->f_mode & FMODE_WRITE)) | 2204 | if (!(file->f_mode & FMODE_WRITE)) |
2204 | return -EINVAL; | 2205 | return -EINVAL; |
2205 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) | 2206 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) |
2206 | return val; | 2207 | return val; |
2207 | spin_lock_irqsave(&state->card->lock, flags); | 2208 | spin_lock_irqsave(&state->card->lock, flags); |
2208 | i810_update_ptr(state); | 2209 | i810_update_ptr(state); |
2209 | abinfo.fragsize = dmabuf->userfragsize; | 2210 | abinfo.fragsize = dmabuf->userfragsize; |
2210 | abinfo.fragstotal = dmabuf->userfrags; | 2211 | abinfo.fragstotal = dmabuf->userfrags; |
2211 | if (dmabuf->mapped) | 2212 | if (dmabuf->mapped) |
2212 | abinfo.bytes = dmabuf->dmasize; | 2213 | abinfo.bytes = dmabuf->dmasize; |
2213 | else | 2214 | else |
2214 | abinfo.bytes = i810_get_free_write_space(state); | 2215 | abinfo.bytes = i810_get_free_write_space(state); |
2215 | abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; | 2216 | abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; |
2216 | spin_unlock_irqrestore(&state->card->lock, flags); | 2217 | spin_unlock_irqrestore(&state->card->lock, flags); |
2217 | #if defined(DEBUG) || defined(DEBUG_MMAP) | 2218 | #if defined(DEBUG) || defined(DEBUG_MMAP) |
2218 | printk("SNDCTL_DSP_GETOSPACE %d, %d, %d, %d\n", abinfo.bytes, | 2219 | printk("SNDCTL_DSP_GETOSPACE %d, %d, %d, %d\n", abinfo.bytes, |
2219 | abinfo.fragsize, abinfo.fragments, abinfo.fragstotal); | 2220 | abinfo.fragsize, abinfo.fragments, abinfo.fragstotal); |
2220 | #endif | 2221 | #endif |
2221 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 2222 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; |
2222 | 2223 | ||
2223 | case SNDCTL_DSP_GETOPTR: | 2224 | case SNDCTL_DSP_GETOPTR: |
2224 | if (!(file->f_mode & FMODE_WRITE)) | 2225 | if (!(file->f_mode & FMODE_WRITE)) |
2225 | return -EINVAL; | 2226 | return -EINVAL; |
2226 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) | 2227 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) |
2227 | return val; | 2228 | return val; |
2228 | spin_lock_irqsave(&state->card->lock, flags); | 2229 | spin_lock_irqsave(&state->card->lock, flags); |
2229 | val = i810_get_free_write_space(state); | 2230 | val = i810_get_free_write_space(state); |
2230 | cinfo.bytes = dmabuf->total_bytes; | 2231 | cinfo.bytes = dmabuf->total_bytes; |
2231 | cinfo.ptr = dmabuf->hwptr; | 2232 | cinfo.ptr = dmabuf->hwptr; |
2232 | cinfo.blocks = val/dmabuf->userfragsize; | 2233 | cinfo.blocks = val/dmabuf->userfragsize; |
2233 | if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { | 2234 | if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { |
2234 | dmabuf->count += val; | 2235 | dmabuf->count += val; |
2235 | dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; | 2236 | dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; |
2236 | __i810_update_lvi(state, 0); | 2237 | __i810_update_lvi(state, 0); |
2237 | } | 2238 | } |
2238 | spin_unlock_irqrestore(&state->card->lock, flags); | 2239 | spin_unlock_irqrestore(&state->card->lock, flags); |
2239 | #if defined(DEBUG) || defined(DEBUG_MMAP) | 2240 | #if defined(DEBUG) || defined(DEBUG_MMAP) |
2240 | printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes, | 2241 | printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes, |
2241 | cinfo.blocks, cinfo.ptr, dmabuf->count); | 2242 | cinfo.blocks, cinfo.ptr, dmabuf->count); |
2242 | #endif | 2243 | #endif |
2243 | return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; | 2244 | return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; |
2244 | 2245 | ||
2245 | case SNDCTL_DSP_GETISPACE: | 2246 | case SNDCTL_DSP_GETISPACE: |
2246 | if (!(file->f_mode & FMODE_READ)) | 2247 | if (!(file->f_mode & FMODE_READ)) |
2247 | return -EINVAL; | 2248 | return -EINVAL; |
2248 | if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0) | 2249 | if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0) |
2249 | return val; | 2250 | return val; |
2250 | spin_lock_irqsave(&state->card->lock, flags); | 2251 | spin_lock_irqsave(&state->card->lock, flags); |
2251 | abinfo.bytes = i810_get_available_read_data(state); | 2252 | abinfo.bytes = i810_get_available_read_data(state); |
2252 | abinfo.fragsize = dmabuf->userfragsize; | 2253 | abinfo.fragsize = dmabuf->userfragsize; |
2253 | abinfo.fragstotal = dmabuf->userfrags; | 2254 | abinfo.fragstotal = dmabuf->userfrags; |
2254 | abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; | 2255 | abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; |
2255 | spin_unlock_irqrestore(&state->card->lock, flags); | 2256 | spin_unlock_irqrestore(&state->card->lock, flags); |
2256 | #if defined(DEBUG) || defined(DEBUG_MMAP) | 2257 | #if defined(DEBUG) || defined(DEBUG_MMAP) |
2257 | printk("SNDCTL_DSP_GETISPACE %d, %d, %d, %d\n", abinfo.bytes, | 2258 | printk("SNDCTL_DSP_GETISPACE %d, %d, %d, %d\n", abinfo.bytes, |
2258 | abinfo.fragsize, abinfo.fragments, abinfo.fragstotal); | 2259 | abinfo.fragsize, abinfo.fragments, abinfo.fragstotal); |
2259 | #endif | 2260 | #endif |
2260 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 2261 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; |
2261 | 2262 | ||
2262 | case SNDCTL_DSP_GETIPTR: | 2263 | case SNDCTL_DSP_GETIPTR: |
2263 | if (!(file->f_mode & FMODE_READ)) | 2264 | if (!(file->f_mode & FMODE_READ)) |
2264 | return -EINVAL; | 2265 | return -EINVAL; |
2265 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) | 2266 | if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) |
2266 | return val; | 2267 | return val; |
2267 | spin_lock_irqsave(&state->card->lock, flags); | 2268 | spin_lock_irqsave(&state->card->lock, flags); |
2268 | val = i810_get_available_read_data(state); | 2269 | val = i810_get_available_read_data(state); |
2269 | cinfo.bytes = dmabuf->total_bytes; | 2270 | cinfo.bytes = dmabuf->total_bytes; |
2270 | cinfo.blocks = val/dmabuf->userfragsize; | 2271 | cinfo.blocks = val/dmabuf->userfragsize; |
2271 | cinfo.ptr = dmabuf->hwptr; | 2272 | cinfo.ptr = dmabuf->hwptr; |
2272 | if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_INPUT)) { | 2273 | if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_INPUT)) { |
2273 | dmabuf->count -= val; | 2274 | dmabuf->count -= val; |
2274 | dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; | 2275 | dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; |
2275 | __i810_update_lvi(state, 1); | 2276 | __i810_update_lvi(state, 1); |
2276 | } | 2277 | } |
2277 | spin_unlock_irqrestore(&state->card->lock, flags); | 2278 | spin_unlock_irqrestore(&state->card->lock, flags); |
2278 | #if defined(DEBUG) || defined(DEBUG_MMAP) | 2279 | #if defined(DEBUG) || defined(DEBUG_MMAP) |
2279 | printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes, | 2280 | printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes, |
2280 | cinfo.blocks, cinfo.ptr, dmabuf->count); | 2281 | cinfo.blocks, cinfo.ptr, dmabuf->count); |
2281 | #endif | 2282 | #endif |
2282 | return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; | 2283 | return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; |
2283 | 2284 | ||
2284 | case SNDCTL_DSP_NONBLOCK: | 2285 | case SNDCTL_DSP_NONBLOCK: |
2285 | #ifdef DEBUG | 2286 | #ifdef DEBUG |
2286 | printk("SNDCTL_DSP_NONBLOCK\n"); | 2287 | printk("SNDCTL_DSP_NONBLOCK\n"); |
2287 | #endif | 2288 | #endif |
2288 | file->f_flags |= O_NONBLOCK; | 2289 | file->f_flags |= O_NONBLOCK; |
2289 | return 0; | 2290 | return 0; |
2290 | 2291 | ||
2291 | case SNDCTL_DSP_GETCAPS: | 2292 | case SNDCTL_DSP_GETCAPS: |
2292 | #ifdef DEBUG | 2293 | #ifdef DEBUG |
2293 | printk("SNDCTL_DSP_GETCAPS\n"); | 2294 | printk("SNDCTL_DSP_GETCAPS\n"); |
2294 | #endif | 2295 | #endif |
2295 | return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP|DSP_CAP_BIND, | 2296 | return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP|DSP_CAP_BIND, |
2296 | p); | 2297 | p); |
2297 | 2298 | ||
2298 | case SNDCTL_DSP_GETTRIGGER: | 2299 | case SNDCTL_DSP_GETTRIGGER: |
2299 | val = 0; | 2300 | val = 0; |
2300 | #ifdef DEBUG | 2301 | #ifdef DEBUG |
2301 | printk("SNDCTL_DSP_GETTRIGGER 0x%x\n", dmabuf->trigger); | 2302 | printk("SNDCTL_DSP_GETTRIGGER 0x%x\n", dmabuf->trigger); |
2302 | #endif | 2303 | #endif |
2303 | return put_user(dmabuf->trigger, p); | 2304 | return put_user(dmabuf->trigger, p); |
2304 | 2305 | ||
2305 | case SNDCTL_DSP_SETTRIGGER: | 2306 | case SNDCTL_DSP_SETTRIGGER: |
2306 | if (get_user(val, p)) | 2307 | if (get_user(val, p)) |
2307 | return -EFAULT; | 2308 | return -EFAULT; |
2308 | #if defined(DEBUG) || defined(DEBUG_MMAP) | 2309 | #if defined(DEBUG) || defined(DEBUG_MMAP) |
2309 | printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val); | 2310 | printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val); |
2310 | #endif | 2311 | #endif |
2311 | /* silently ignore invalid PCM_ENABLE_xxx bits, | 2312 | /* silently ignore invalid PCM_ENABLE_xxx bits, |
2312 | * like the other drivers do | 2313 | * like the other drivers do |
2313 | */ | 2314 | */ |
2314 | if (!(file->f_mode & FMODE_READ )) | 2315 | if (!(file->f_mode & FMODE_READ )) |
2315 | val &= ~PCM_ENABLE_INPUT; | 2316 | val &= ~PCM_ENABLE_INPUT; |
2316 | if (!(file->f_mode & FMODE_WRITE )) | 2317 | if (!(file->f_mode & FMODE_WRITE )) |
2317 | val &= ~PCM_ENABLE_OUTPUT; | 2318 | val &= ~PCM_ENABLE_OUTPUT; |
2318 | if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) { | 2319 | if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) { |
2319 | stop_adc(state); | 2320 | stop_adc(state); |
2320 | } | 2321 | } |
2321 | if((file->f_mode & FMODE_WRITE) && !(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) { | 2322 | if((file->f_mode & FMODE_WRITE) && !(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) { |
2322 | stop_dac(state); | 2323 | stop_dac(state); |
2323 | } | 2324 | } |
2324 | dmabuf->trigger = val; | 2325 | dmabuf->trigger = val; |
2325 | if((val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) { | 2326 | if((val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) { |
2326 | if (!dmabuf->write_channel) { | 2327 | if (!dmabuf->write_channel) { |
2327 | dmabuf->ready = 0; | 2328 | dmabuf->ready = 0; |
2328 | dmabuf->write_channel = state->card->alloc_pcm_channel(state->card); | 2329 | dmabuf->write_channel = state->card->alloc_pcm_channel(state->card); |
2329 | if (!dmabuf->write_channel) | 2330 | if (!dmabuf->write_channel) |
2330 | return -EBUSY; | 2331 | return -EBUSY; |
2331 | } | 2332 | } |
2332 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) | 2333 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) |
2333 | return ret; | 2334 | return ret; |
2334 | if (dmabuf->mapped) { | 2335 | if (dmabuf->mapped) { |
2335 | spin_lock_irqsave(&state->card->lock, flags); | 2336 | spin_lock_irqsave(&state->card->lock, flags); |
2336 | i810_update_ptr(state); | 2337 | i810_update_ptr(state); |
2337 | dmabuf->count = 0; | 2338 | dmabuf->count = 0; |
2338 | dmabuf->swptr = dmabuf->hwptr; | 2339 | dmabuf->swptr = dmabuf->hwptr; |
2339 | dmabuf->count = i810_get_free_write_space(state); | 2340 | dmabuf->count = i810_get_free_write_space(state); |
2340 | dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize; | 2341 | dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize; |
2341 | spin_unlock_irqrestore(&state->card->lock, flags); | 2342 | spin_unlock_irqrestore(&state->card->lock, flags); |
2342 | } | 2343 | } |
2343 | i810_update_lvi(state, 0); | 2344 | i810_update_lvi(state, 0); |
2344 | start_dac(state); | 2345 | start_dac(state); |
2345 | } | 2346 | } |
2346 | if((val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) { | 2347 | if((val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) { |
2347 | if (!dmabuf->read_channel) { | 2348 | if (!dmabuf->read_channel) { |
2348 | dmabuf->ready = 0; | 2349 | dmabuf->ready = 0; |
2349 | dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card); | 2350 | dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card); |
2350 | if (!dmabuf->read_channel) | 2351 | if (!dmabuf->read_channel) |
2351 | return -EBUSY; | 2352 | return -EBUSY; |
2352 | } | 2353 | } |
2353 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) | 2354 | if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) |
2354 | return ret; | 2355 | return ret; |
2355 | if (dmabuf->mapped) { | 2356 | if (dmabuf->mapped) { |
2356 | spin_lock_irqsave(&state->card->lock, flags); | 2357 | spin_lock_irqsave(&state->card->lock, flags); |
2357 | i810_update_ptr(state); | 2358 | i810_update_ptr(state); |
2358 | dmabuf->swptr = dmabuf->hwptr; | 2359 | dmabuf->swptr = dmabuf->hwptr; |
2359 | dmabuf->count = 0; | 2360 | dmabuf->count = 0; |
2360 | spin_unlock_irqrestore(&state->card->lock, flags); | 2361 | spin_unlock_irqrestore(&state->card->lock, flags); |
2361 | } | 2362 | } |
2362 | i810_update_lvi(state, 1); | 2363 | i810_update_lvi(state, 1); |
2363 | start_adc(state); | 2364 | start_adc(state); |
2364 | } | 2365 | } |
2365 | return 0; | 2366 | return 0; |
2366 | 2367 | ||
2367 | case SNDCTL_DSP_SETDUPLEX: | 2368 | case SNDCTL_DSP_SETDUPLEX: |
2368 | #ifdef DEBUG | 2369 | #ifdef DEBUG |
2369 | printk("SNDCTL_DSP_SETDUPLEX\n"); | 2370 | printk("SNDCTL_DSP_SETDUPLEX\n"); |
2370 | #endif | 2371 | #endif |
2371 | return -EINVAL; | 2372 | return -EINVAL; |
2372 | 2373 | ||
2373 | case SNDCTL_DSP_GETODELAY: | 2374 | case SNDCTL_DSP_GETODELAY: |
2374 | if (!(file->f_mode & FMODE_WRITE)) | 2375 | if (!(file->f_mode & FMODE_WRITE)) |
2375 | return -EINVAL; | 2376 | return -EINVAL; |
2376 | spin_lock_irqsave(&state->card->lock, flags); | 2377 | spin_lock_irqsave(&state->card->lock, flags); |
2377 | i810_update_ptr(state); | 2378 | i810_update_ptr(state); |
2378 | val = dmabuf->count; | 2379 | val = dmabuf->count; |
2379 | spin_unlock_irqrestore(&state->card->lock, flags); | 2380 | spin_unlock_irqrestore(&state->card->lock, flags); |
2380 | #ifdef DEBUG | 2381 | #ifdef DEBUG |
2381 | printk("SNDCTL_DSP_GETODELAY %d\n", dmabuf->count); | 2382 | printk("SNDCTL_DSP_GETODELAY %d\n", dmabuf->count); |
2382 | #endif | 2383 | #endif |
2383 | return put_user(val, p); | 2384 | return put_user(val, p); |
2384 | 2385 | ||
2385 | case SOUND_PCM_READ_RATE: | 2386 | case SOUND_PCM_READ_RATE: |
2386 | #ifdef DEBUG | 2387 | #ifdef DEBUG |
2387 | printk("SOUND_PCM_READ_RATE %d\n", dmabuf->rate); | 2388 | printk("SOUND_PCM_READ_RATE %d\n", dmabuf->rate); |
2388 | #endif | 2389 | #endif |
2389 | return put_user(dmabuf->rate, p); | 2390 | return put_user(dmabuf->rate, p); |
2390 | 2391 | ||
2391 | case SOUND_PCM_READ_CHANNELS: | 2392 | case SOUND_PCM_READ_CHANNELS: |
2392 | #ifdef DEBUG | 2393 | #ifdef DEBUG |
2393 | printk("SOUND_PCM_READ_CHANNELS\n"); | 2394 | printk("SOUND_PCM_READ_CHANNELS\n"); |
2394 | #endif | 2395 | #endif |
2395 | return put_user(2, p); | 2396 | return put_user(2, p); |
2396 | 2397 | ||
2397 | case SOUND_PCM_READ_BITS: | 2398 | case SOUND_PCM_READ_BITS: |
2398 | #ifdef DEBUG | 2399 | #ifdef DEBUG |
2399 | printk("SOUND_PCM_READ_BITS\n"); | 2400 | printk("SOUND_PCM_READ_BITS\n"); |
2400 | #endif | 2401 | #endif |
2401 | return put_user(AFMT_S16_LE, p); | 2402 | return put_user(AFMT_S16_LE, p); |
2402 | 2403 | ||
2403 | case SNDCTL_DSP_SETSPDIF: /* Set S/PDIF Control register */ | 2404 | case SNDCTL_DSP_SETSPDIF: /* Set S/PDIF Control register */ |
2404 | #ifdef DEBUG | 2405 | #ifdef DEBUG |
2405 | printk("SNDCTL_DSP_SETSPDIF\n"); | 2406 | printk("SNDCTL_DSP_SETSPDIF\n"); |
2406 | #endif | 2407 | #endif |
2407 | if (get_user(val, p)) | 2408 | if (get_user(val, p)) |
2408 | return -EFAULT; | 2409 | return -EFAULT; |
2409 | 2410 | ||
2410 | /* Check to make sure the codec supports S/PDIF transmitter */ | 2411 | /* Check to make sure the codec supports S/PDIF transmitter */ |
2411 | 2412 | ||
2412 | if((state->card->ac97_features & 4)) { | 2413 | if((state->card->ac97_features & 4)) { |
2413 | /* mask out the transmitter speed bits so the user can't set them */ | 2414 | /* mask out the transmitter speed bits so the user can't set them */ |
2414 | val &= ~0x3000; | 2415 | val &= ~0x3000; |
2415 | 2416 | ||
2416 | /* Add the current transmitter speed bits to the passed value */ | 2417 | /* Add the current transmitter speed bits to the passed value */ |
2417 | ret = i810_ac97_get(codec, AC97_SPDIF_CONTROL); | 2418 | ret = i810_ac97_get(codec, AC97_SPDIF_CONTROL); |
2418 | val |= (ret & 0x3000); | 2419 | val |= (ret & 0x3000); |
2419 | 2420 | ||
2420 | i810_ac97_set(codec, AC97_SPDIF_CONTROL, val); | 2421 | i810_ac97_set(codec, AC97_SPDIF_CONTROL, val); |
2421 | if(i810_ac97_get(codec, AC97_SPDIF_CONTROL) != val ) { | 2422 | if(i810_ac97_get(codec, AC97_SPDIF_CONTROL) != val ) { |
2422 | printk(KERN_ERR "i810_audio: Unable to set S/PDIF configuration to 0x%04x.\n", val); | 2423 | printk(KERN_ERR "i810_audio: Unable to set S/PDIF configuration to 0x%04x.\n", val); |
2423 | return -EFAULT; | 2424 | return -EFAULT; |
2424 | } | 2425 | } |
2425 | } | 2426 | } |
2426 | #ifdef DEBUG | 2427 | #ifdef DEBUG |
2427 | else | 2428 | else |
2428 | printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n"); | 2429 | printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n"); |
2429 | #endif | 2430 | #endif |
2430 | return put_user(val, p); | 2431 | return put_user(val, p); |
2431 | 2432 | ||
2432 | case SNDCTL_DSP_GETSPDIF: /* Get S/PDIF Control register */ | 2433 | case SNDCTL_DSP_GETSPDIF: /* Get S/PDIF Control register */ |
2433 | #ifdef DEBUG | 2434 | #ifdef DEBUG |
2434 | printk("SNDCTL_DSP_GETSPDIF\n"); | 2435 | printk("SNDCTL_DSP_GETSPDIF\n"); |
2435 | #endif | 2436 | #endif |
2436 | if (get_user(val, p)) | 2437 | if (get_user(val, p)) |
2437 | return -EFAULT; | 2438 | return -EFAULT; |
2438 | 2439 | ||
2439 | /* Check to make sure the codec supports S/PDIF transmitter */ | 2440 | /* Check to make sure the codec supports S/PDIF transmitter */ |
2440 | 2441 | ||
2441 | if(!(state->card->ac97_features & 4)) { | 2442 | if(!(state->card->ac97_features & 4)) { |
2442 | #ifdef DEBUG | 2443 | #ifdef DEBUG |
2443 | printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n"); | 2444 | printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n"); |
2444 | #endif | 2445 | #endif |
2445 | val = 0; | 2446 | val = 0; |
2446 | } else { | 2447 | } else { |
2447 | val = i810_ac97_get(codec, AC97_SPDIF_CONTROL); | 2448 | val = i810_ac97_get(codec, AC97_SPDIF_CONTROL); |
2448 | } | 2449 | } |
2449 | //return put_user((val & 0xcfff), p); | 2450 | //return put_user((val & 0xcfff), p); |
2450 | return put_user(val, p); | 2451 | return put_user(val, p); |
2451 | 2452 | ||
2452 | case SNDCTL_DSP_GETCHANNELMASK: | 2453 | case SNDCTL_DSP_GETCHANNELMASK: |
2453 | #ifdef DEBUG | 2454 | #ifdef DEBUG |
2454 | printk("SNDCTL_DSP_GETCHANNELMASK\n"); | 2455 | printk("SNDCTL_DSP_GETCHANNELMASK\n"); |
2455 | #endif | 2456 | #endif |
2456 | if (get_user(val, p)) | 2457 | if (get_user(val, p)) |
2457 | return -EFAULT; | 2458 | return -EFAULT; |
2458 | 2459 | ||
2459 | /* Based on AC'97 DAC support, not ICH hardware */ | 2460 | /* Based on AC'97 DAC support, not ICH hardware */ |
2460 | val = DSP_BIND_FRONT; | 2461 | val = DSP_BIND_FRONT; |
2461 | if ( state->card->ac97_features & 0x0004 ) | 2462 | if ( state->card->ac97_features & 0x0004 ) |
2462 | val |= DSP_BIND_SPDIF; | 2463 | val |= DSP_BIND_SPDIF; |
2463 | 2464 | ||
2464 | if ( state->card->ac97_features & 0x0080 ) | 2465 | if ( state->card->ac97_features & 0x0080 ) |
2465 | val |= DSP_BIND_SURR; | 2466 | val |= DSP_BIND_SURR; |
2466 | if ( state->card->ac97_features & 0x0140 ) | 2467 | if ( state->card->ac97_features & 0x0140 ) |
2467 | val |= DSP_BIND_CENTER_LFE; | 2468 | val |= DSP_BIND_CENTER_LFE; |
2468 | 2469 | ||
2469 | return put_user(val, p); | 2470 | return put_user(val, p); |
2470 | 2471 | ||
2471 | case SNDCTL_DSP_BIND_CHANNEL: | 2472 | case SNDCTL_DSP_BIND_CHANNEL: |
2472 | #ifdef DEBUG | 2473 | #ifdef DEBUG |
2473 | printk("SNDCTL_DSP_BIND_CHANNEL\n"); | 2474 | printk("SNDCTL_DSP_BIND_CHANNEL\n"); |
2474 | #endif | 2475 | #endif |
2475 | if (get_user(val, p)) | 2476 | if (get_user(val, p)) |
2476 | return -EFAULT; | 2477 | return -EFAULT; |
2477 | if ( val == DSP_BIND_QUERY ) { | 2478 | if ( val == DSP_BIND_QUERY ) { |
2478 | val = DSP_BIND_FRONT; /* Always report this as being enabled */ | 2479 | val = DSP_BIND_FRONT; /* Always report this as being enabled */ |
2479 | if ( state->card->ac97_status & SPDIF_ON ) | 2480 | if ( state->card->ac97_status & SPDIF_ON ) |
2480 | val |= DSP_BIND_SPDIF; | 2481 | val |= DSP_BIND_SPDIF; |
2481 | else { | 2482 | else { |
2482 | if ( state->card->ac97_status & SURR_ON ) | 2483 | if ( state->card->ac97_status & SURR_ON ) |
2483 | val |= DSP_BIND_SURR; | 2484 | val |= DSP_BIND_SURR; |
2484 | if ( state->card->ac97_status & CENTER_LFE_ON ) | 2485 | if ( state->card->ac97_status & CENTER_LFE_ON ) |
2485 | val |= DSP_BIND_CENTER_LFE; | 2486 | val |= DSP_BIND_CENTER_LFE; |
2486 | } | 2487 | } |
2487 | } else { /* Not a query, set it */ | 2488 | } else { /* Not a query, set it */ |
2488 | if (!(file->f_mode & FMODE_WRITE)) | 2489 | if (!(file->f_mode & FMODE_WRITE)) |
2489 | return -EINVAL; | 2490 | return -EINVAL; |
2490 | if ( dmabuf->enable == DAC_RUNNING ) { | 2491 | if ( dmabuf->enable == DAC_RUNNING ) { |
2491 | stop_dac(state); | 2492 | stop_dac(state); |
2492 | } | 2493 | } |
2493 | if ( val & DSP_BIND_SPDIF ) { /* Turn on SPDIF */ | 2494 | if ( val & DSP_BIND_SPDIF ) { /* Turn on SPDIF */ |
2494 | /* Ok, this should probably define what slots | 2495 | /* Ok, this should probably define what slots |
2495 | * to use. For now, we'll only set it to the | 2496 | * to use. For now, we'll only set it to the |
2496 | * defaults: | 2497 | * defaults: |
2497 | * | 2498 | * |
2498 | * non multichannel codec maps to slots 3&4 | 2499 | * non multichannel codec maps to slots 3&4 |
2499 | * 2 channel codec maps to slots 7&8 | 2500 | * 2 channel codec maps to slots 7&8 |
2500 | * 4 channel codec maps to slots 6&9 | 2501 | * 4 channel codec maps to slots 6&9 |
2501 | * 6 channel codec maps to slots 10&11 | 2502 | * 6 channel codec maps to slots 10&11 |
2502 | * | 2503 | * |
2503 | * there should be some way for the app to | 2504 | * there should be some way for the app to |
2504 | * select the slot assignment. | 2505 | * select the slot assignment. |
2505 | */ | 2506 | */ |
2506 | 2507 | ||
2507 | i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, dmabuf->rate ); | 2508 | i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, dmabuf->rate ); |
2508 | if ( !(state->card->ac97_status & SPDIF_ON) ) | 2509 | if ( !(state->card->ac97_status & SPDIF_ON) ) |
2509 | val &= ~DSP_BIND_SPDIF; | 2510 | val &= ~DSP_BIND_SPDIF; |
2510 | } else { | 2511 | } else { |
2511 | int mask; | 2512 | int mask; |
2512 | int channels; | 2513 | int channels; |
2513 | 2514 | ||
2514 | /* Turn off S/PDIF if it was on */ | 2515 | /* Turn off S/PDIF if it was on */ |
2515 | if ( state->card->ac97_status & SPDIF_ON ) | 2516 | if ( state->card->ac97_status & SPDIF_ON ) |
2516 | i810_set_spdif_output ( state, -1, 0 ); | 2517 | i810_set_spdif_output ( state, -1, 0 ); |
2517 | 2518 | ||
2518 | mask = val & (DSP_BIND_FRONT | DSP_BIND_SURR | DSP_BIND_CENTER_LFE); | 2519 | mask = val & (DSP_BIND_FRONT | DSP_BIND_SURR | DSP_BIND_CENTER_LFE); |
2519 | switch (mask) { | 2520 | switch (mask) { |
2520 | case DSP_BIND_FRONT: | 2521 | case DSP_BIND_FRONT: |
2521 | channels = 2; | 2522 | channels = 2; |
2522 | break; | 2523 | break; |
2523 | case DSP_BIND_FRONT|DSP_BIND_SURR: | 2524 | case DSP_BIND_FRONT|DSP_BIND_SURR: |
2524 | channels = 4; | 2525 | channels = 4; |
2525 | break; | 2526 | break; |
2526 | case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE: | 2527 | case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE: |
2527 | channels = 6; | 2528 | channels = 6; |
2528 | break; | 2529 | break; |
2529 | default: | 2530 | default: |
2530 | val = DSP_BIND_FRONT; | 2531 | val = DSP_BIND_FRONT; |
2531 | channels = 2; | 2532 | channels = 2; |
2532 | break; | 2533 | break; |
2533 | } | 2534 | } |
2534 | i810_set_dac_channels ( state, channels ); | 2535 | i810_set_dac_channels ( state, channels ); |
2535 | 2536 | ||
2536 | /* check that they really got turned on */ | 2537 | /* check that they really got turned on */ |
2537 | if (!(state->card->ac97_status & SURR_ON)) | 2538 | if (!(state->card->ac97_status & SURR_ON)) |
2538 | val &= ~DSP_BIND_SURR; | 2539 | val &= ~DSP_BIND_SURR; |
2539 | if (!(state->card->ac97_status & CENTER_LFE_ON)) | 2540 | if (!(state->card->ac97_status & CENTER_LFE_ON)) |
2540 | val &= ~DSP_BIND_CENTER_LFE; | 2541 | val &= ~DSP_BIND_CENTER_LFE; |
2541 | } | 2542 | } |
2542 | } | 2543 | } |
2543 | return put_user(val, p); | 2544 | return put_user(val, p); |
2544 | 2545 | ||
2545 | case SNDCTL_DSP_MAPINBUF: | 2546 | case SNDCTL_DSP_MAPINBUF: |
2546 | case SNDCTL_DSP_MAPOUTBUF: | 2547 | case SNDCTL_DSP_MAPOUTBUF: |
2547 | case SNDCTL_DSP_SETSYNCRO: | 2548 | case SNDCTL_DSP_SETSYNCRO: |
2548 | case SOUND_PCM_WRITE_FILTER: | 2549 | case SOUND_PCM_WRITE_FILTER: |
2549 | case SOUND_PCM_READ_FILTER: | 2550 | case SOUND_PCM_READ_FILTER: |
2550 | #ifdef DEBUG | 2551 | #ifdef DEBUG |
2551 | printk("SNDCTL_* -EINVAL\n"); | 2552 | printk("SNDCTL_* -EINVAL\n"); |
2552 | #endif | 2553 | #endif |
2553 | return -EINVAL; | 2554 | return -EINVAL; |
2554 | } | 2555 | } |
2555 | return -EINVAL; | 2556 | return -EINVAL; |
2556 | } | 2557 | } |
2557 | 2558 | ||
2558 | static int i810_open(struct inode *inode, struct file *file) | 2559 | static int i810_open(struct inode *inode, struct file *file) |
2559 | { | 2560 | { |
2560 | int i = 0; | 2561 | int i = 0; |
2561 | struct i810_card *card = devs; | 2562 | struct i810_card *card = devs; |
2562 | struct i810_state *state = NULL; | 2563 | struct i810_state *state = NULL; |
2563 | struct dmabuf *dmabuf = NULL; | 2564 | struct dmabuf *dmabuf = NULL; |
2564 | 2565 | ||
2565 | /* find an avaiable virtual channel (instance of /dev/dsp) */ | 2566 | /* find an avaiable virtual channel (instance of /dev/dsp) */ |
2566 | while (card != NULL) { | 2567 | while (card != NULL) { |
2567 | /* | 2568 | /* |
2568 | * If we are initializing and then fail, card could go | 2569 | * If we are initializing and then fail, card could go |
2569 | * away unuexpectedly while we are in the for() loop. | 2570 | * away unuexpectedly while we are in the for() loop. |
2570 | * So, check for card on each iteration before we check | 2571 | * So, check for card on each iteration before we check |
2571 | * for card->initializing to avoid a possible oops. | 2572 | * for card->initializing to avoid a possible oops. |
2572 | * This usually only matters for times when the driver is | 2573 | * This usually only matters for times when the driver is |
2573 | * autoloaded by kmod. | 2574 | * autoloaded by kmod. |
2574 | */ | 2575 | */ |
2575 | for (i = 0; i < 50 && card && card->initializing; i++) { | 2576 | for (i = 0; i < 50 && card && card->initializing; i++) { |
2576 | set_current_state(TASK_UNINTERRUPTIBLE); | 2577 | set_current_state(TASK_UNINTERRUPTIBLE); |
2577 | schedule_timeout(HZ/20); | 2578 | schedule_timeout(HZ/20); |
2578 | } | 2579 | } |
2579 | for (i = 0; i < NR_HW_CH && card && !card->initializing; i++) { | 2580 | for (i = 0; i < NR_HW_CH && card && !card->initializing; i++) { |
2580 | if (card->states[i] == NULL) { | 2581 | if (card->states[i] == NULL) { |
2581 | state = card->states[i] = (struct i810_state *) | 2582 | state = card->states[i] = (struct i810_state *) |
2582 | kmalloc(sizeof(struct i810_state), GFP_KERNEL); | 2583 | kmalloc(sizeof(struct i810_state), GFP_KERNEL); |
2583 | if (state == NULL) | 2584 | if (state == NULL) |
2584 | return -ENOMEM; | 2585 | return -ENOMEM; |
2585 | memset(state, 0, sizeof(struct i810_state)); | 2586 | memset(state, 0, sizeof(struct i810_state)); |
2586 | dmabuf = &state->dmabuf; | 2587 | dmabuf = &state->dmabuf; |
2587 | goto found_virt; | 2588 | goto found_virt; |
2588 | } | 2589 | } |
2589 | } | 2590 | } |
2590 | card = card->next; | 2591 | card = card->next; |
2591 | } | 2592 | } |
2592 | /* no more virtual channel avaiable */ | 2593 | /* no more virtual channel avaiable */ |
2593 | if (!state) | 2594 | if (!state) |
2594 | return -ENODEV; | 2595 | return -ENODEV; |
2595 | 2596 | ||
2596 | found_virt: | 2597 | found_virt: |
2597 | /* initialize the virtual channel */ | 2598 | /* initialize the virtual channel */ |
2598 | state->virt = i; | 2599 | state->virt = i; |
2599 | state->card = card; | 2600 | state->card = card; |
2600 | state->magic = I810_STATE_MAGIC; | 2601 | state->magic = I810_STATE_MAGIC; |
2601 | init_waitqueue_head(&dmabuf->wait); | 2602 | init_waitqueue_head(&dmabuf->wait); |
2602 | mutex_init(&state->open_mutex); | 2603 | mutex_init(&state->open_mutex); |
2603 | file->private_data = state; | 2604 | file->private_data = state; |
2604 | dmabuf->trigger = 0; | 2605 | dmabuf->trigger = 0; |
2605 | 2606 | ||
2606 | /* allocate hardware channels */ | 2607 | /* allocate hardware channels */ |
2607 | if(file->f_mode & FMODE_READ) { | 2608 | if(file->f_mode & FMODE_READ) { |
2608 | if((dmabuf->read_channel = card->alloc_rec_pcm_channel(card)) == NULL) { | 2609 | if((dmabuf->read_channel = card->alloc_rec_pcm_channel(card)) == NULL) { |
2609 | kfree (card->states[i]); | 2610 | kfree (card->states[i]); |
2610 | card->states[i] = NULL; | 2611 | card->states[i] = NULL; |
2611 | return -EBUSY; | 2612 | return -EBUSY; |
2612 | } | 2613 | } |
2613 | dmabuf->trigger |= PCM_ENABLE_INPUT; | 2614 | dmabuf->trigger |= PCM_ENABLE_INPUT; |
2614 | i810_set_adc_rate(state, 8000); | 2615 | i810_set_adc_rate(state, 8000); |
2615 | } | 2616 | } |
2616 | if(file->f_mode & FMODE_WRITE) { | 2617 | if(file->f_mode & FMODE_WRITE) { |
2617 | if((dmabuf->write_channel = card->alloc_pcm_channel(card)) == NULL) { | 2618 | if((dmabuf->write_channel = card->alloc_pcm_channel(card)) == NULL) { |
2618 | /* make sure we free the record channel allocated above */ | 2619 | /* make sure we free the record channel allocated above */ |
2619 | if(file->f_mode & FMODE_READ) | 2620 | if(file->f_mode & FMODE_READ) |
2620 | card->free_pcm_channel(card,dmabuf->read_channel->num); | 2621 | card->free_pcm_channel(card,dmabuf->read_channel->num); |
2621 | kfree (card->states[i]); | 2622 | kfree (card->states[i]); |
2622 | card->states[i] = NULL; | 2623 | card->states[i] = NULL; |
2623 | return -EBUSY; | 2624 | return -EBUSY; |
2624 | } | 2625 | } |
2625 | /* Initialize to 8kHz? What if we don't support 8kHz? */ | 2626 | /* Initialize to 8kHz? What if we don't support 8kHz? */ |
2626 | /* Let's change this to check for S/PDIF stuff */ | 2627 | /* Let's change this to check for S/PDIF stuff */ |
2627 | 2628 | ||
2628 | dmabuf->trigger |= PCM_ENABLE_OUTPUT; | 2629 | dmabuf->trigger |= PCM_ENABLE_OUTPUT; |
2629 | if ( spdif_locked ) { | 2630 | if ( spdif_locked ) { |
2630 | i810_set_dac_rate(state, spdif_locked); | 2631 | i810_set_dac_rate(state, spdif_locked); |
2631 | i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked); | 2632 | i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked); |
2632 | } else { | 2633 | } else { |
2633 | i810_set_dac_rate(state, 8000); | 2634 | i810_set_dac_rate(state, 8000); |
2634 | /* Put the ACLink in 2 channel mode by default */ | 2635 | /* Put the ACLink in 2 channel mode by default */ |
2635 | i = I810_IOREADL(card, GLOB_CNT); | 2636 | i = I810_IOREADL(card, GLOB_CNT); |
2636 | I810_IOWRITEL(i & 0xffcfffff, card, GLOB_CNT); | 2637 | I810_IOWRITEL(i & 0xffcfffff, card, GLOB_CNT); |
2637 | } | 2638 | } |
2638 | } | 2639 | } |
2639 | 2640 | ||
2640 | /* set default sample format. According to OSS Programmer's Guide /dev/dsp | 2641 | /* set default sample format. According to OSS Programmer's Guide /dev/dsp |
2641 | should be default to unsigned 8-bits, mono, with sample rate 8kHz and | 2642 | should be default to unsigned 8-bits, mono, with sample rate 8kHz and |
2642 | /dev/dspW will accept 16-bits sample, but we don't support those so we | 2643 | /dev/dspW will accept 16-bits sample, but we don't support those so we |
2643 | set it immediately to stereo and 16bit, which is all we do support */ | 2644 | set it immediately to stereo and 16bit, which is all we do support */ |
2644 | dmabuf->fmt |= I810_FMT_16BIT | I810_FMT_STEREO; | 2645 | dmabuf->fmt |= I810_FMT_16BIT | I810_FMT_STEREO; |
2645 | dmabuf->ossfragsize = 0; | 2646 | dmabuf->ossfragsize = 0; |
2646 | dmabuf->ossmaxfrags = 0; | 2647 | dmabuf->ossmaxfrags = 0; |
2647 | dmabuf->subdivision = 0; | 2648 | dmabuf->subdivision = 0; |
2648 | 2649 | ||
2649 | state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | 2650 | state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); |
2650 | 2651 | ||
2651 | return nonseekable_open(inode, file); | 2652 | return nonseekable_open(inode, file); |
2652 | } | 2653 | } |
2653 | 2654 | ||
2654 | static int i810_release(struct inode *inode, struct file *file) | 2655 | static int i810_release(struct inode *inode, struct file *file) |
2655 | { | 2656 | { |
2656 | struct i810_state *state = (struct i810_state *)file->private_data; | 2657 | struct i810_state *state = (struct i810_state *)file->private_data; |
2657 | struct i810_card *card = state->card; | 2658 | struct i810_card *card = state->card; |
2658 | struct dmabuf *dmabuf = &state->dmabuf; | 2659 | struct dmabuf *dmabuf = &state->dmabuf; |
2659 | unsigned long flags; | 2660 | unsigned long flags; |
2660 | 2661 | ||
2661 | lock_kernel(); | 2662 | lock_kernel(); |
2662 | 2663 | ||
2663 | /* stop DMA state machine and free DMA buffers/channels */ | 2664 | /* stop DMA state machine and free DMA buffers/channels */ |
2664 | if(dmabuf->trigger & PCM_ENABLE_OUTPUT) { | 2665 | if(dmabuf->trigger & PCM_ENABLE_OUTPUT) { |
2665 | drain_dac(state, 0); | 2666 | drain_dac(state, 0); |
2666 | } | 2667 | } |
2667 | if(dmabuf->trigger & PCM_ENABLE_INPUT) { | 2668 | if(dmabuf->trigger & PCM_ENABLE_INPUT) { |
2668 | stop_adc(state); | 2669 | stop_adc(state); |
2669 | } | 2670 | } |
2670 | spin_lock_irqsave(&card->lock, flags); | 2671 | spin_lock_irqsave(&card->lock, flags); |
2671 | dealloc_dmabuf(state); | 2672 | dealloc_dmabuf(state); |
2672 | if (file->f_mode & FMODE_WRITE) { | 2673 | if (file->f_mode & FMODE_WRITE) { |
2673 | state->card->free_pcm_channel(state->card, dmabuf->write_channel->num); | 2674 | state->card->free_pcm_channel(state->card, dmabuf->write_channel->num); |
2674 | } | 2675 | } |
2675 | if (file->f_mode & FMODE_READ) { | 2676 | if (file->f_mode & FMODE_READ) { |
2676 | state->card->free_pcm_channel(state->card, dmabuf->read_channel->num); | 2677 | state->card->free_pcm_channel(state->card, dmabuf->read_channel->num); |
2677 | } | 2678 | } |
2678 | 2679 | ||
2679 | state->card->states[state->virt] = NULL; | 2680 | state->card->states[state->virt] = NULL; |
2680 | kfree(state); | 2681 | kfree(state); |
2681 | spin_unlock_irqrestore(&card->lock, flags); | 2682 | spin_unlock_irqrestore(&card->lock, flags); |
2682 | unlock_kernel(); | 2683 | unlock_kernel(); |
2683 | 2684 | ||
2684 | return 0; | 2685 | return 0; |
2685 | } | 2686 | } |
2686 | 2687 | ||
2687 | static /*const*/ struct file_operations i810_audio_fops = { | 2688 | static /*const*/ struct file_operations i810_audio_fops = { |
2688 | .owner = THIS_MODULE, | 2689 | .owner = THIS_MODULE, |
2689 | .llseek = no_llseek, | 2690 | .llseek = no_llseek, |
2690 | .read = i810_read, | 2691 | .read = i810_read, |
2691 | .write = i810_write, | 2692 | .write = i810_write, |
2692 | .poll = i810_poll, | 2693 | .poll = i810_poll, |
2693 | .ioctl = i810_ioctl, | 2694 | .ioctl = i810_ioctl, |
2694 | .mmap = i810_mmap, | 2695 | .mmap = i810_mmap, |
2695 | .open = i810_open, | 2696 | .open = i810_open, |
2696 | .release = i810_release, | 2697 | .release = i810_release, |
2697 | }; | 2698 | }; |
2698 | 2699 | ||
2699 | /* Write AC97 codec registers */ | 2700 | /* Write AC97 codec registers */ |
2700 | 2701 | ||
2701 | static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg) | 2702 | static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg) |
2702 | { | 2703 | { |
2703 | struct i810_card *card = dev->private_data; | 2704 | struct i810_card *card = dev->private_data; |
2704 | int count = 100; | 2705 | int count = 100; |
2705 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); | 2706 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); |
2706 | 2707 | ||
2707 | while(count-- && (readb(card->iobase_mmio + CAS) & 1)) | 2708 | while(count-- && (readb(card->iobase_mmio + CAS) & 1)) |
2708 | udelay(1); | 2709 | udelay(1); |
2709 | 2710 | ||
2710 | #ifdef DEBUG_MMIO | 2711 | #ifdef DEBUG_MMIO |
2711 | { | 2712 | { |
2712 | u16 ans = readw(card->ac97base_mmio + reg_set); | 2713 | u16 ans = readw(card->ac97base_mmio + reg_set); |
2713 | printk(KERN_DEBUG "i810_audio: ac97_get_mmio(%d) -> 0x%04X\n", ((int) reg_set) & 0xffff, (u32) ans); | 2714 | printk(KERN_DEBUG "i810_audio: ac97_get_mmio(%d) -> 0x%04X\n", ((int) reg_set) & 0xffff, (u32) ans); |
2714 | return ans; | 2715 | return ans; |
2715 | } | 2716 | } |
2716 | #else | 2717 | #else |
2717 | return readw(card->ac97base_mmio + reg_set); | 2718 | return readw(card->ac97base_mmio + reg_set); |
2718 | #endif | 2719 | #endif |
2719 | } | 2720 | } |
2720 | 2721 | ||
2721 | static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg) | 2722 | static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg) |
2722 | { | 2723 | { |
2723 | struct i810_card *card = dev->private_data; | 2724 | struct i810_card *card = dev->private_data; |
2724 | int count = 100; | 2725 | int count = 100; |
2725 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); | 2726 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); |
2726 | 2727 | ||
2727 | while(count-- && (I810_IOREADB(card, CAS) & 1)) | 2728 | while(count-- && (I810_IOREADB(card, CAS) & 1)) |
2728 | udelay(1); | 2729 | udelay(1); |
2729 | 2730 | ||
2730 | return inw(card->ac97base + reg_set); | 2731 | return inw(card->ac97base + reg_set); |
2731 | } | 2732 | } |
2732 | 2733 | ||
2733 | static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data) | 2734 | static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data) |
2734 | { | 2735 | { |
2735 | struct i810_card *card = dev->private_data; | 2736 | struct i810_card *card = dev->private_data; |
2736 | int count = 100; | 2737 | int count = 100; |
2737 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); | 2738 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); |
2738 | 2739 | ||
2739 | while(count-- && (readb(card->iobase_mmio + CAS) & 1)) | 2740 | while(count-- && (readb(card->iobase_mmio + CAS) & 1)) |
2740 | udelay(1); | 2741 | udelay(1); |
2741 | 2742 | ||
2742 | writew(data, card->ac97base_mmio + reg_set); | 2743 | writew(data, card->ac97base_mmio + reg_set); |
2743 | 2744 | ||
2744 | #ifdef DEBUG_MMIO | 2745 | #ifdef DEBUG_MMIO |
2745 | printk(KERN_DEBUG "i810_audio: ac97_set_mmio(0x%04X, %d)\n", (u32) data, ((int) reg_set) & 0xffff); | 2746 | printk(KERN_DEBUG "i810_audio: ac97_set_mmio(0x%04X, %d)\n", (u32) data, ((int) reg_set) & 0xffff); |
2746 | #endif | 2747 | #endif |
2747 | } | 2748 | } |
2748 | 2749 | ||
2749 | static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data) | 2750 | static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data) |
2750 | { | 2751 | { |
2751 | struct i810_card *card = dev->private_data; | 2752 | struct i810_card *card = dev->private_data; |
2752 | int count = 100; | 2753 | int count = 100; |
2753 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); | 2754 | u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); |
2754 | 2755 | ||
2755 | while(count-- && (I810_IOREADB(card, CAS) & 1)) | 2756 | while(count-- && (I810_IOREADB(card, CAS) & 1)) |
2756 | udelay(1); | 2757 | udelay(1); |
2757 | 2758 | ||
2758 | outw(data, card->ac97base + reg_set); | 2759 | outw(data, card->ac97base + reg_set); |
2759 | } | 2760 | } |
2760 | 2761 | ||
2761 | static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg) | 2762 | static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg) |
2762 | { | 2763 | { |
2763 | struct i810_card *card = dev->private_data; | 2764 | struct i810_card *card = dev->private_data; |
2764 | u16 ret; | 2765 | u16 ret; |
2765 | 2766 | ||
2766 | spin_lock(&card->ac97_lock); | 2767 | spin_lock(&card->ac97_lock); |
2767 | if (card->use_mmio) { | 2768 | if (card->use_mmio) { |
2768 | ret = i810_ac97_get_mmio(dev, reg); | 2769 | ret = i810_ac97_get_mmio(dev, reg); |
2769 | } | 2770 | } |
2770 | else { | 2771 | else { |
2771 | ret = i810_ac97_get_io(dev, reg); | 2772 | ret = i810_ac97_get_io(dev, reg); |
2772 | } | 2773 | } |
2773 | spin_unlock(&card->ac97_lock); | 2774 | spin_unlock(&card->ac97_lock); |
2774 | 2775 | ||
2775 | return ret; | 2776 | return ret; |
2776 | } | 2777 | } |
2777 | 2778 | ||
2778 | static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data) | 2779 | static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data) |
2779 | { | 2780 | { |
2780 | struct i810_card *card = dev->private_data; | 2781 | struct i810_card *card = dev->private_data; |
2781 | 2782 | ||
2782 | spin_lock(&card->ac97_lock); | 2783 | spin_lock(&card->ac97_lock); |
2783 | if (card->use_mmio) { | 2784 | if (card->use_mmio) { |
2784 | i810_ac97_set_mmio(dev, reg, data); | 2785 | i810_ac97_set_mmio(dev, reg, data); |
2785 | } | 2786 | } |
2786 | else { | 2787 | else { |
2787 | i810_ac97_set_io(dev, reg, data); | 2788 | i810_ac97_set_io(dev, reg, data); |
2788 | } | 2789 | } |
2789 | spin_unlock(&card->ac97_lock); | 2790 | spin_unlock(&card->ac97_lock); |
2790 | } | 2791 | } |
2791 | 2792 | ||
2792 | 2793 | ||
2793 | /* OSS /dev/mixer file operation methods */ | 2794 | /* OSS /dev/mixer file operation methods */ |
2794 | 2795 | ||
2795 | static int i810_open_mixdev(struct inode *inode, struct file *file) | 2796 | static int i810_open_mixdev(struct inode *inode, struct file *file) |
2796 | { | 2797 | { |
2797 | int i; | 2798 | int i; |
2798 | int minor = iminor(inode); | 2799 | int minor = iminor(inode); |
2799 | struct i810_card *card = devs; | 2800 | struct i810_card *card = devs; |
2800 | 2801 | ||
2801 | for (card = devs; card != NULL; card = card->next) { | 2802 | for (card = devs; card != NULL; card = card->next) { |
2802 | /* | 2803 | /* |
2803 | * If we are initializing and then fail, card could go | 2804 | * If we are initializing and then fail, card could go |
2804 | * away unuexpectedly while we are in the for() loop. | 2805 | * away unuexpectedly while we are in the for() loop. |
2805 | * So, check for card on each iteration before we check | 2806 | * So, check for card on each iteration before we check |
2806 | * for card->initializing to avoid a possible oops. | 2807 | * for card->initializing to avoid a possible oops. |
2807 | * This usually only matters for times when the driver is | 2808 | * This usually only matters for times when the driver is |
2808 | * autoloaded by kmod. | 2809 | * autoloaded by kmod. |
2809 | */ | 2810 | */ |
2810 | for (i = 0; i < 50 && card && card->initializing; i++) { | 2811 | for (i = 0; i < 50 && card && card->initializing; i++) { |
2811 | set_current_state(TASK_UNINTERRUPTIBLE); | 2812 | set_current_state(TASK_UNINTERRUPTIBLE); |
2812 | schedule_timeout(HZ/20); | 2813 | schedule_timeout(HZ/20); |
2813 | } | 2814 | } |
2814 | for (i = 0; i < NR_AC97 && card && !card->initializing; i++) | 2815 | for (i = 0; i < NR_AC97 && card && !card->initializing; i++) |
2815 | if (card->ac97_codec[i] != NULL && | 2816 | if (card->ac97_codec[i] != NULL && |
2816 | card->ac97_codec[i]->dev_mixer == minor) { | 2817 | card->ac97_codec[i]->dev_mixer == minor) { |
2817 | file->private_data = card->ac97_codec[i]; | 2818 | file->private_data = card->ac97_codec[i]; |
2818 | return nonseekable_open(inode, file); | 2819 | return nonseekable_open(inode, file); |
2819 | } | 2820 | } |
2820 | } | 2821 | } |
2821 | return -ENODEV; | 2822 | return -ENODEV; |
2822 | } | 2823 | } |
2823 | 2824 | ||
2824 | static int i810_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, | 2825 | static int i810_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, |
2825 | unsigned long arg) | 2826 | unsigned long arg) |
2826 | { | 2827 | { |
2827 | struct ac97_codec *codec = (struct ac97_codec *)file->private_data; | 2828 | struct ac97_codec *codec = (struct ac97_codec *)file->private_data; |
2828 | 2829 | ||
2829 | return codec->mixer_ioctl(codec, cmd, arg); | 2830 | return codec->mixer_ioctl(codec, cmd, arg); |
2830 | } | 2831 | } |
2831 | 2832 | ||
2832 | static /*const*/ struct file_operations i810_mixer_fops = { | 2833 | static /*const*/ struct file_operations i810_mixer_fops = { |
2833 | .owner = THIS_MODULE, | 2834 | .owner = THIS_MODULE, |
2834 | .llseek = no_llseek, | 2835 | .llseek = no_llseek, |
2835 | .ioctl = i810_ioctl_mixdev, | 2836 | .ioctl = i810_ioctl_mixdev, |
2836 | .open = i810_open_mixdev, | 2837 | .open = i810_open_mixdev, |
2837 | }; | 2838 | }; |
2838 | 2839 | ||
2839 | /* AC97 codec initialisation. These small functions exist so we don't | 2840 | /* AC97 codec initialisation. These small functions exist so we don't |
2840 | duplicate code between module init and apm resume */ | 2841 | duplicate code between module init and apm resume */ |
2841 | 2842 | ||
2842 | static inline int i810_ac97_exists(struct i810_card *card, int ac97_number) | 2843 | static inline int i810_ac97_exists(struct i810_card *card, int ac97_number) |
2843 | { | 2844 | { |
2844 | u32 reg = I810_IOREADL(card, GLOB_STA); | 2845 | u32 reg = I810_IOREADL(card, GLOB_STA); |
2845 | switch (ac97_number) { | 2846 | switch (ac97_number) { |
2846 | case 0: | 2847 | case 0: |
2847 | return reg & (1<<8); | 2848 | return reg & (1<<8); |
2848 | case 1: | 2849 | case 1: |
2849 | return reg & (1<<9); | 2850 | return reg & (1<<9); |
2850 | case 2: | 2851 | case 2: |
2851 | return reg & (1<<28); | 2852 | return reg & (1<<28); |
2852 | } | 2853 | } |
2853 | return 0; | 2854 | return 0; |
2854 | } | 2855 | } |
2855 | 2856 | ||
2856 | static inline int i810_ac97_enable_variable_rate(struct ac97_codec *codec) | 2857 | static inline int i810_ac97_enable_variable_rate(struct ac97_codec *codec) |
2857 | { | 2858 | { |
2858 | i810_ac97_set(codec, AC97_EXTENDED_STATUS, 9); | 2859 | i810_ac97_set(codec, AC97_EXTENDED_STATUS, 9); |
2859 | i810_ac97_set(codec,AC97_EXTENDED_STATUS, | 2860 | i810_ac97_set(codec,AC97_EXTENDED_STATUS, |
2860 | i810_ac97_get(codec, AC97_EXTENDED_STATUS)|0xE800); | 2861 | i810_ac97_get(codec, AC97_EXTENDED_STATUS)|0xE800); |
2861 | 2862 | ||
2862 | return (i810_ac97_get(codec, AC97_EXTENDED_STATUS)&1); | 2863 | return (i810_ac97_get(codec, AC97_EXTENDED_STATUS)&1); |
2863 | } | 2864 | } |
2864 | 2865 | ||
2865 | 2866 | ||
2866 | static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec *codec) | 2867 | static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec *codec) |
2867 | { | 2868 | { |
2868 | /* Returns 0 on failure */ | 2869 | /* Returns 0 on failure */ |
2869 | int i; | 2870 | int i; |
2870 | 2871 | ||
2871 | if (ac97_probe_codec(codec) == 0) return 0; | 2872 | if (ac97_probe_codec(codec) == 0) return 0; |
2872 | 2873 | ||
2873 | /* power it all up */ | 2874 | /* power it all up */ |
2874 | i810_ac97_set(codec, AC97_POWER_CONTROL, | 2875 | i810_ac97_set(codec, AC97_POWER_CONTROL, |
2875 | i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00); | 2876 | i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00); |
2876 | 2877 | ||
2877 | /* wait for analog ready */ | 2878 | /* wait for analog ready */ |
2878 | for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) | 2879 | for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) |
2879 | { | 2880 | { |
2880 | set_current_state(TASK_UNINTERRUPTIBLE); | 2881 | set_current_state(TASK_UNINTERRUPTIBLE); |
2881 | schedule_timeout(HZ/20); | 2882 | schedule_timeout(HZ/20); |
2882 | } | 2883 | } |
2883 | return i; | 2884 | return i; |
2884 | } | 2885 | } |
2885 | 2886 | ||
2886 | static int is_new_ich(u16 pci_id) | 2887 | static int is_new_ich(u16 pci_id) |
2887 | { | 2888 | { |
2888 | switch (pci_id) { | 2889 | switch (pci_id) { |
2889 | case PCI_DEVICE_ID_INTEL_82801DB_5: | 2890 | case PCI_DEVICE_ID_INTEL_82801DB_5: |
2890 | case PCI_DEVICE_ID_INTEL_82801EB_5: | 2891 | case PCI_DEVICE_ID_INTEL_82801EB_5: |
2891 | case PCI_DEVICE_ID_INTEL_ESB_5: | 2892 | case PCI_DEVICE_ID_INTEL_ESB_5: |
2892 | case PCI_DEVICE_ID_INTEL_ICH6_18: | 2893 | case PCI_DEVICE_ID_INTEL_ICH6_18: |
2893 | return 1; | 2894 | return 1; |
2894 | default: | 2895 | default: |
2895 | break; | 2896 | break; |
2896 | } | 2897 | } |
2897 | 2898 | ||
2898 | return 0; | 2899 | return 0; |
2899 | } | 2900 | } |
2900 | 2901 | ||
2901 | static inline int ich_use_mmio(struct i810_card *card) | 2902 | static inline int ich_use_mmio(struct i810_card *card) |
2902 | { | 2903 | { |
2903 | return is_new_ich(card->pci_id) && card->use_mmio; | 2904 | return is_new_ich(card->pci_id) && card->use_mmio; |
2904 | } | 2905 | } |
2905 | 2906 | ||
2906 | /** | 2907 | /** |
2907 | * i810_ac97_power_up_bus - bring up AC97 link | 2908 | * i810_ac97_power_up_bus - bring up AC97 link |
2908 | * @card : ICH audio device to power up | 2909 | * @card : ICH audio device to power up |
2909 | * | 2910 | * |
2910 | * Bring up the ACLink AC97 codec bus | 2911 | * Bring up the ACLink AC97 codec bus |
2911 | */ | 2912 | */ |
2912 | 2913 | ||
2913 | static int i810_ac97_power_up_bus(struct i810_card *card) | 2914 | static int i810_ac97_power_up_bus(struct i810_card *card) |
2914 | { | 2915 | { |
2915 | u32 reg = I810_IOREADL(card, GLOB_CNT); | 2916 | u32 reg = I810_IOREADL(card, GLOB_CNT); |
2916 | int i; | 2917 | int i; |
2917 | int primary_codec_id = 0; | 2918 | int primary_codec_id = 0; |
2918 | 2919 | ||
2919 | if((reg&2)==0) /* Cold required */ | 2920 | if((reg&2)==0) /* Cold required */ |
2920 | reg|=2; | 2921 | reg|=2; |
2921 | else | 2922 | else |
2922 | reg|=4; /* Warm */ | 2923 | reg|=4; /* Warm */ |
2923 | 2924 | ||
2924 | reg&=~8; /* ACLink on */ | 2925 | reg&=~8; /* ACLink on */ |
2925 | 2926 | ||
2926 | /* At this point we deassert AC_RESET # */ | 2927 | /* At this point we deassert AC_RESET # */ |
2927 | I810_IOWRITEL(reg , card, GLOB_CNT); | 2928 | I810_IOWRITEL(reg , card, GLOB_CNT); |
2928 | 2929 | ||
2929 | /* We must now allow time for the Codec initialisation. | 2930 | /* We must now allow time for the Codec initialisation. |
2930 | 600mS is the specified time */ | 2931 | 600mS is the specified time */ |
2931 | 2932 | ||
2932 | for(i=0;i<10;i++) | 2933 | for(i=0;i<10;i++) |
2933 | { | 2934 | { |
2934 | if((I810_IOREADL(card, GLOB_CNT)&4)==0) | 2935 | if((I810_IOREADL(card, GLOB_CNT)&4)==0) |
2935 | break; | 2936 | break; |
2936 | 2937 | ||
2937 | set_current_state(TASK_UNINTERRUPTIBLE); | 2938 | set_current_state(TASK_UNINTERRUPTIBLE); |
2938 | schedule_timeout(HZ/20); | 2939 | schedule_timeout(HZ/20); |
2939 | } | 2940 | } |
2940 | if(i==10) | 2941 | if(i==10) |
2941 | { | 2942 | { |
2942 | printk(KERN_ERR "i810_audio: AC'97 reset failed.\n"); | 2943 | printk(KERN_ERR "i810_audio: AC'97 reset failed.\n"); |
2943 | return 0; | 2944 | return 0; |
2944 | } | 2945 | } |
2945 | 2946 | ||
2946 | set_current_state(TASK_UNINTERRUPTIBLE); | 2947 | set_current_state(TASK_UNINTERRUPTIBLE); |
2947 | schedule_timeout(HZ/2); | 2948 | schedule_timeout(HZ/2); |
2948 | 2949 | ||
2949 | /* | 2950 | /* |
2950 | * See if the primary codec comes ready. This must happen | 2951 | * See if the primary codec comes ready. This must happen |
2951 | * before we start doing DMA stuff | 2952 | * before we start doing DMA stuff |
2952 | */ | 2953 | */ |
2953 | /* see i810_ac97_init for the next 10 lines (jsaw) */ | 2954 | /* see i810_ac97_init for the next 10 lines (jsaw) */ |
2954 | if (card->use_mmio) | 2955 | if (card->use_mmio) |
2955 | readw(card->ac97base_mmio); | 2956 | readw(card->ac97base_mmio); |
2956 | else | 2957 | else |
2957 | inw(card->ac97base); | 2958 | inw(card->ac97base); |
2958 | if (ich_use_mmio(card)) { | 2959 | if (ich_use_mmio(card)) { |
2959 | primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3; | 2960 | primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3; |
2960 | printk(KERN_INFO "i810_audio: Primary codec has ID %d\n", | 2961 | printk(KERN_INFO "i810_audio: Primary codec has ID %d\n", |
2961 | primary_codec_id); | 2962 | primary_codec_id); |
2962 | } | 2963 | } |
2963 | 2964 | ||
2964 | if(! i810_ac97_exists(card, primary_codec_id)) | 2965 | if(! i810_ac97_exists(card, primary_codec_id)) |
2965 | { | 2966 | { |
2966 | printk(KERN_INFO "i810_audio: Codec not ready.. wait.. "); | 2967 | printk(KERN_INFO "i810_audio: Codec not ready.. wait.. "); |
2967 | set_current_state(TASK_UNINTERRUPTIBLE); | 2968 | set_current_state(TASK_UNINTERRUPTIBLE); |
2968 | schedule_timeout(HZ); /* actually 600mS by the spec */ | 2969 | schedule_timeout(HZ); /* actually 600mS by the spec */ |
2969 | 2970 | ||
2970 | if(i810_ac97_exists(card, primary_codec_id)) | 2971 | if(i810_ac97_exists(card, primary_codec_id)) |
2971 | printk("OK\n"); | 2972 | printk("OK\n"); |
2972 | else | 2973 | else |
2973 | printk("no response.\n"); | 2974 | printk("no response.\n"); |
2974 | } | 2975 | } |
2975 | if (card->use_mmio) | 2976 | if (card->use_mmio) |
2976 | readw(card->ac97base_mmio); | 2977 | readw(card->ac97base_mmio); |
2977 | else | 2978 | else |
2978 | inw(card->ac97base); | 2979 | inw(card->ac97base); |
2979 | return 1; | 2980 | return 1; |
2980 | } | 2981 | } |
2981 | 2982 | ||
2982 | static int __devinit i810_ac97_init(struct i810_card *card) | 2983 | static int __devinit i810_ac97_init(struct i810_card *card) |
2983 | { | 2984 | { |
2984 | int num_ac97 = 0; | 2985 | int num_ac97 = 0; |
2985 | int ac97_id; | 2986 | int ac97_id; |
2986 | int total_channels = 0; | 2987 | int total_channels = 0; |
2987 | int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97; | 2988 | int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97; |
2988 | struct ac97_codec *codec; | 2989 | struct ac97_codec *codec; |
2989 | u16 eid; | 2990 | u16 eid; |
2990 | u32 reg; | 2991 | u32 reg; |
2991 | 2992 | ||
2992 | if(!i810_ac97_power_up_bus(card)) return 0; | 2993 | if(!i810_ac97_power_up_bus(card)) return 0; |
2993 | 2994 | ||
2994 | /* Number of channels supported */ | 2995 | /* Number of channels supported */ |
2995 | /* What about the codec? Just because the ICH supports */ | 2996 | /* What about the codec? Just because the ICH supports */ |
2996 | /* multiple channels doesn't mean the codec does. */ | 2997 | /* multiple channels doesn't mean the codec does. */ |
2997 | /* we'll have to modify this in the codec section below */ | 2998 | /* we'll have to modify this in the codec section below */ |
2998 | /* to reflect what the codec has. */ | 2999 | /* to reflect what the codec has. */ |
2999 | /* ICH and ICH0 only support 2 channels so don't bother */ | 3000 | /* ICH and ICH0 only support 2 channels so don't bother */ |
3000 | /* to check.... */ | 3001 | /* to check.... */ |
3001 | 3002 | ||
3002 | card->channels = 2; | 3003 | card->channels = 2; |
3003 | reg = I810_IOREADL(card, GLOB_STA); | 3004 | reg = I810_IOREADL(card, GLOB_STA); |
3004 | if ( reg & 0x0200000 ) | 3005 | if ( reg & 0x0200000 ) |
3005 | card->channels = 6; | 3006 | card->channels = 6; |
3006 | else if ( reg & 0x0100000 ) | 3007 | else if ( reg & 0x0100000 ) |
3007 | card->channels = 4; | 3008 | card->channels = 4; |
3008 | printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels); | 3009 | printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels); |
3009 | printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n"); | 3010 | printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n"); |
3010 | reg = I810_IOREADL(card, GLOB_CNT); | 3011 | reg = I810_IOREADL(card, GLOB_CNT); |
3011 | I810_IOWRITEL(reg & 0xffcfffff, card, GLOB_CNT); | 3012 | I810_IOWRITEL(reg & 0xffcfffff, card, GLOB_CNT); |
3012 | 3013 | ||
3013 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) | 3014 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) |
3014 | card->ac97_codec[num_ac97] = NULL; | 3015 | card->ac97_codec[num_ac97] = NULL; |
3015 | 3016 | ||
3016 | /*@FIXME I don't know, if I'm playing to safe here... (jsaw) */ | 3017 | /*@FIXME I don't know, if I'm playing to safe here... (jsaw) */ |
3017 | if ((nr_ac97_max > 2) && !card->use_mmio) nr_ac97_max = 2; | 3018 | if ((nr_ac97_max > 2) && !card->use_mmio) nr_ac97_max = 2; |
3018 | 3019 | ||
3019 | for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) { | 3020 | for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) { |
3020 | /* codec reset */ | 3021 | /* codec reset */ |
3021 | printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97); | 3022 | printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97); |
3022 | if (card->use_mmio) | 3023 | if (card->use_mmio) |
3023 | readw(card->ac97base_mmio + 0x80*num_ac97); | 3024 | readw(card->ac97base_mmio + 0x80*num_ac97); |
3024 | else | 3025 | else |
3025 | inw(card->ac97base + 0x80*num_ac97); | 3026 | inw(card->ac97base + 0x80*num_ac97); |
3026 | 3027 | ||
3027 | /* If we have the SDATA_IN Map Register, as on ICH4, we | 3028 | /* If we have the SDATA_IN Map Register, as on ICH4, we |
3028 | do not loop thru all possible codec IDs but thru all | 3029 | do not loop thru all possible codec IDs but thru all |
3029 | possible IO channels. Bit 0:1 of SDM then holds the | 3030 | possible IO channels. Bit 0:1 of SDM then holds the |
3030 | last codec ID spoken to. | 3031 | last codec ID spoken to. |
3031 | */ | 3032 | */ |
3032 | if (ich_use_mmio(card)) { | 3033 | if (ich_use_mmio(card)) { |
3033 | ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3; | 3034 | ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3; |
3034 | printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n", | 3035 | printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n", |
3035 | num_ac97, ac97_id); | 3036 | num_ac97, ac97_id); |
3036 | } | 3037 | } |
3037 | else { | 3038 | else { |
3038 | ac97_id = num_ac97; | 3039 | ac97_id = num_ac97; |
3039 | } | 3040 | } |
3040 | 3041 | ||
3041 | /* The ICH programmer's reference says you should */ | 3042 | /* The ICH programmer's reference says you should */ |
3042 | /* check the ready status before probing. So we chk */ | 3043 | /* check the ready status before probing. So we chk */ |
3043 | /* What do we do if it's not ready? Wait and try */ | 3044 | /* What do we do if it's not ready? Wait and try */ |
3044 | /* again, or abort? */ | 3045 | /* again, or abort? */ |
3045 | if (!i810_ac97_exists(card, ac97_id)) { | 3046 | if (!i810_ac97_exists(card, ac97_id)) { |
3046 | if(num_ac97 == 0) | 3047 | if(num_ac97 == 0) |
3047 | printk(KERN_ERR "i810_audio: Primary codec not ready.\n"); | 3048 | printk(KERN_ERR "i810_audio: Primary codec not ready.\n"); |
3048 | } | 3049 | } |
3049 | 3050 | ||
3050 | if ((codec = ac97_alloc_codec()) == NULL) | 3051 | if ((codec = ac97_alloc_codec()) == NULL) |
3051 | return -ENOMEM; | 3052 | return -ENOMEM; |
3052 | 3053 | ||
3053 | /* initialize some basic codec information, other fields will be filled | 3054 | /* initialize some basic codec information, other fields will be filled |
3054 | in ac97_probe_codec */ | 3055 | in ac97_probe_codec */ |
3055 | codec->private_data = card; | 3056 | codec->private_data = card; |
3056 | codec->id = ac97_id; | 3057 | codec->id = ac97_id; |
3057 | card->ac97_id_map[ac97_id] = num_ac97 * 0x80; | 3058 | card->ac97_id_map[ac97_id] = num_ac97 * 0x80; |
3058 | 3059 | ||
3059 | if (card->use_mmio) { | 3060 | if (card->use_mmio) { |
3060 | codec->codec_read = i810_ac97_get_mmio; | 3061 | codec->codec_read = i810_ac97_get_mmio; |
3061 | codec->codec_write = i810_ac97_set_mmio; | 3062 | codec->codec_write = i810_ac97_set_mmio; |
3062 | } | 3063 | } |
3063 | else { | 3064 | else { |
3064 | codec->codec_read = i810_ac97_get_io; | 3065 | codec->codec_read = i810_ac97_get_io; |
3065 | codec->codec_write = i810_ac97_set_io; | 3066 | codec->codec_write = i810_ac97_set_io; |
3066 | } | 3067 | } |
3067 | 3068 | ||
3068 | if(!i810_ac97_probe_and_powerup(card,codec)) { | 3069 | if(!i810_ac97_probe_and_powerup(card,codec)) { |
3069 | printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", ac97_id); | 3070 | printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", ac97_id); |
3070 | ac97_release_codec(codec); | 3071 | ac97_release_codec(codec); |
3071 | break; /* it didn't work */ | 3072 | break; /* it didn't work */ |
3072 | } | 3073 | } |
3073 | /* Store state information about S/PDIF transmitter */ | 3074 | /* Store state information about S/PDIF transmitter */ |
3074 | card->ac97_status = 0; | 3075 | card->ac97_status = 0; |
3075 | 3076 | ||
3076 | /* Don't attempt to get eid until powerup is complete */ | 3077 | /* Don't attempt to get eid until powerup is complete */ |
3077 | eid = i810_ac97_get(codec, AC97_EXTENDED_ID); | 3078 | eid = i810_ac97_get(codec, AC97_EXTENDED_ID); |
3078 | 3079 | ||
3079 | if(eid==0xFFFF) | 3080 | if(eid==0xFFFF) |
3080 | { | 3081 | { |
3081 | printk(KERN_WARNING "i810_audio: no codec attached ?\n"); | 3082 | printk(KERN_WARNING "i810_audio: no codec attached ?\n"); |
3082 | ac97_release_codec(codec); | 3083 | ac97_release_codec(codec); |
3083 | break; | 3084 | break; |
3084 | } | 3085 | } |
3085 | 3086 | ||
3086 | /* Check for an AC97 1.0 soft modem (ID1) */ | 3087 | /* Check for an AC97 1.0 soft modem (ID1) */ |
3087 | 3088 | ||
3088 | if(codec->modem) | 3089 | if(codec->modem) |
3089 | { | 3090 | { |
3090 | printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", ac97_id); | 3091 | printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", ac97_id); |
3091 | ac97_release_codec(codec); | 3092 | ac97_release_codec(codec); |
3092 | continue; | 3093 | continue; |
3093 | } | 3094 | } |
3094 | 3095 | ||
3095 | card->ac97_features = eid; | 3096 | card->ac97_features = eid; |
3096 | 3097 | ||
3097 | /* Now check the codec for useful features to make up for | 3098 | /* Now check the codec for useful features to make up for |
3098 | the dumbness of the 810 hardware engine */ | 3099 | the dumbness of the 810 hardware engine */ |
3099 | 3100 | ||
3100 | if(!(eid&0x0001)) | 3101 | if(!(eid&0x0001)) |
3101 | printk(KERN_WARNING "i810_audio: only 48Khz playback available.\n"); | 3102 | printk(KERN_WARNING "i810_audio: only 48Khz playback available.\n"); |
3102 | else | 3103 | else |
3103 | { | 3104 | { |
3104 | if(!i810_ac97_enable_variable_rate(codec)) { | 3105 | if(!i810_ac97_enable_variable_rate(codec)) { |
3105 | printk(KERN_WARNING "i810_audio: Codec refused to allow VRA, using 48Khz only.\n"); | 3106 | printk(KERN_WARNING "i810_audio: Codec refused to allow VRA, using 48Khz only.\n"); |
3106 | card->ac97_features&=~1; | 3107 | card->ac97_features&=~1; |
3107 | } | 3108 | } |
3108 | } | 3109 | } |
3109 | 3110 | ||
3110 | /* Turn on the amplifier */ | 3111 | /* Turn on the amplifier */ |
3111 | 3112 | ||
3112 | codec->codec_write(codec, AC97_POWER_CONTROL, | 3113 | codec->codec_write(codec, AC97_POWER_CONTROL, |
3113 | codec->codec_read(codec, AC97_POWER_CONTROL) & ~0x8000); | 3114 | codec->codec_read(codec, AC97_POWER_CONTROL) & ~0x8000); |
3114 | 3115 | ||
3115 | /* Determine how many channels the codec(s) support */ | 3116 | /* Determine how many channels the codec(s) support */ |
3116 | /* - The primary codec always supports 2 */ | 3117 | /* - The primary codec always supports 2 */ |
3117 | /* - If the codec supports AMAP, surround DACs will */ | 3118 | /* - If the codec supports AMAP, surround DACs will */ |
3118 | /* automaticlly get assigned to slots. */ | 3119 | /* automaticlly get assigned to slots. */ |
3119 | /* * Check for surround DACs and increment if */ | 3120 | /* * Check for surround DACs and increment if */ |
3120 | /* found. */ | 3121 | /* found. */ |
3121 | /* - Else check if the codec is revision 2.2 */ | 3122 | /* - Else check if the codec is revision 2.2 */ |
3122 | /* * If surround DACs exist, assign them to slots */ | 3123 | /* * If surround DACs exist, assign them to slots */ |
3123 | /* and increment channel count. */ | 3124 | /* and increment channel count. */ |
3124 | 3125 | ||
3125 | /* All of this only applies to ICH2 and above. ICH */ | 3126 | /* All of this only applies to ICH2 and above. ICH */ |
3126 | /* and ICH0 only support 2 channels. ICH2 will only */ | 3127 | /* and ICH0 only support 2 channels. ICH2 will only */ |
3127 | /* support multiple codecs in a "split audio" config. */ | 3128 | /* support multiple codecs in a "split audio" config. */ |
3128 | /* as described above. */ | 3129 | /* as described above. */ |
3129 | 3130 | ||
3130 | /* TODO: Remove all the debugging messages! */ | 3131 | /* TODO: Remove all the debugging messages! */ |
3131 | 3132 | ||
3132 | if((eid & 0xc000) == 0) /* primary codec */ | 3133 | if((eid & 0xc000) == 0) /* primary codec */ |
3133 | total_channels += 2; | 3134 | total_channels += 2; |
3134 | 3135 | ||
3135 | if(eid & 0x200) { /* GOOD, AMAP support */ | 3136 | if(eid & 0x200) { /* GOOD, AMAP support */ |
3136 | if (eid & 0x0080) /* L/R Surround channels */ | 3137 | if (eid & 0x0080) /* L/R Surround channels */ |
3137 | total_channels += 2; | 3138 | total_channels += 2; |
3138 | if (eid & 0x0140) /* LFE and Center channels */ | 3139 | if (eid & 0x0140) /* LFE and Center channels */ |
3139 | total_channels += 2; | 3140 | total_channels += 2; |
3140 | printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", ac97_id, total_channels); | 3141 | printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", ac97_id, total_channels); |
3141 | } else if (eid & 0x0400) { /* this only works on 2.2 compliant codecs */ | 3142 | } else if (eid & 0x0400) { /* this only works on 2.2 compliant codecs */ |
3142 | eid &= 0xffcf; | 3143 | eid &= 0xffcf; |
3143 | if((eid & 0xc000) != 0) { | 3144 | if((eid & 0xc000) != 0) { |
3144 | switch ( total_channels ) { | 3145 | switch ( total_channels ) { |
3145 | case 2: | 3146 | case 2: |
3146 | /* Set dsa1, dsa0 to 01 */ | 3147 | /* Set dsa1, dsa0 to 01 */ |
3147 | eid |= 0x0010; | 3148 | eid |= 0x0010; |
3148 | break; | 3149 | break; |
3149 | case 4: | 3150 | case 4: |
3150 | /* Set dsa1, dsa0 to 10 */ | 3151 | /* Set dsa1, dsa0 to 10 */ |
3151 | eid |= 0x0020; | 3152 | eid |= 0x0020; |
3152 | break; | 3153 | break; |
3153 | case 6: | 3154 | case 6: |
3154 | /* Set dsa1, dsa0 to 11 */ | 3155 | /* Set dsa1, dsa0 to 11 */ |
3155 | eid |= 0x0030; | 3156 | eid |= 0x0030; |
3156 | break; | 3157 | break; |
3157 | } | 3158 | } |
3158 | total_channels += 2; | 3159 | total_channels += 2; |
3159 | } | 3160 | } |
3160 | i810_ac97_set(codec, AC97_EXTENDED_ID, eid); | 3161 | i810_ac97_set(codec, AC97_EXTENDED_ID, eid); |
3161 | eid = i810_ac97_get(codec, AC97_EXTENDED_ID); | 3162 | eid = i810_ac97_get(codec, AC97_EXTENDED_ID); |
3162 | printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", ac97_id, eid); | 3163 | printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", ac97_id, eid); |
3163 | if (eid & 0x0080) /* L/R Surround channels */ | 3164 | if (eid & 0x0080) /* L/R Surround channels */ |
3164 | total_channels += 2; | 3165 | total_channels += 2; |
3165 | if (eid & 0x0140) /* LFE and Center channels */ | 3166 | if (eid & 0x0140) /* LFE and Center channels */ |
3166 | total_channels += 2; | 3167 | total_channels += 2; |
3167 | printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", ac97_id, total_channels); | 3168 | printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", ac97_id, total_channels); |
3168 | } else { | 3169 | } else { |
3169 | printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", ac97_id, total_channels); | 3170 | printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", ac97_id, total_channels); |
3170 | } | 3171 | } |
3171 | 3172 | ||
3172 | if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) { | 3173 | if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) { |
3173 | printk(KERN_ERR "i810_audio: couldn't register mixer!\n"); | 3174 | printk(KERN_ERR "i810_audio: couldn't register mixer!\n"); |
3174 | ac97_release_codec(codec); | 3175 | ac97_release_codec(codec); |
3175 | break; | 3176 | break; |
3176 | } | 3177 | } |
3177 | 3178 | ||
3178 | card->ac97_codec[num_ac97] = codec; | 3179 | card->ac97_codec[num_ac97] = codec; |
3179 | } | 3180 | } |
3180 | 3181 | ||
3181 | /* tune up the primary codec */ | 3182 | /* tune up the primary codec */ |
3182 | ac97_tune_hardware(card->pci_dev, ac97_quirks, ac97_quirk); | 3183 | ac97_tune_hardware(card->pci_dev, ac97_quirks, ac97_quirk); |
3183 | 3184 | ||
3184 | /* pick the minimum of channels supported by ICHx or codec(s) */ | 3185 | /* pick the minimum of channels supported by ICHx or codec(s) */ |
3185 | card->channels = (card->channels > total_channels)?total_channels:card->channels; | 3186 | card->channels = (card->channels > total_channels)?total_channels:card->channels; |
3186 | 3187 | ||
3187 | return num_ac97; | 3188 | return num_ac97; |
3188 | } | 3189 | } |
3189 | 3190 | ||
3190 | static void __devinit i810_configure_clocking (void) | 3191 | static void __devinit i810_configure_clocking (void) |
3191 | { | 3192 | { |
3192 | struct i810_card *card; | 3193 | struct i810_card *card; |
3193 | struct i810_state *state; | 3194 | struct i810_state *state; |
3194 | struct dmabuf *dmabuf; | 3195 | struct dmabuf *dmabuf; |
3195 | unsigned int i, offset, new_offset; | 3196 | unsigned int i, offset, new_offset; |
3196 | unsigned long flags; | 3197 | unsigned long flags; |
3197 | 3198 | ||
3198 | card = devs; | 3199 | card = devs; |
3199 | /* We could try to set the clocking for multiple cards, but can you even have | 3200 | /* We could try to set the clocking for multiple cards, but can you even have |
3200 | * more than one i810 in a machine? Besides, clocking is global, so unless | 3201 | * more than one i810 in a machine? Besides, clocking is global, so unless |
3201 | * someone actually thinks more than one i810 in a machine is possible and | 3202 | * someone actually thinks more than one i810 in a machine is possible and |
3202 | * decides to rewrite that little bit, setting the rate for more than one card | 3203 | * decides to rewrite that little bit, setting the rate for more than one card |
3203 | * is a waste of time. | 3204 | * is a waste of time. |
3204 | */ | 3205 | */ |
3205 | if(card != NULL) { | 3206 | if(card != NULL) { |
3206 | state = card->states[0] = (struct i810_state *) | 3207 | state = card->states[0] = (struct i810_state *) |
3207 | kmalloc(sizeof(struct i810_state), GFP_KERNEL); | 3208 | kmalloc(sizeof(struct i810_state), GFP_KERNEL); |
3208 | if (state == NULL) | 3209 | if (state == NULL) |
3209 | return; | 3210 | return; |
3210 | memset(state, 0, sizeof(struct i810_state)); | 3211 | memset(state, 0, sizeof(struct i810_state)); |
3211 | dmabuf = &state->dmabuf; | 3212 | dmabuf = &state->dmabuf; |
3212 | 3213 | ||
3213 | dmabuf->write_channel = card->alloc_pcm_channel(card); | 3214 | dmabuf->write_channel = card->alloc_pcm_channel(card); |
3214 | state->virt = 0; | 3215 | state->virt = 0; |
3215 | state->card = card; | 3216 | state->card = card; |
3216 | state->magic = I810_STATE_MAGIC; | 3217 | state->magic = I810_STATE_MAGIC; |
3217 | init_waitqueue_head(&dmabuf->wait); | 3218 | init_waitqueue_head(&dmabuf->wait); |
3218 | mutex_init(&state->open_mutex); | 3219 | mutex_init(&state->open_mutex); |
3219 | dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT; | 3220 | dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT; |
3220 | dmabuf->trigger = PCM_ENABLE_OUTPUT; | 3221 | dmabuf->trigger = PCM_ENABLE_OUTPUT; |
3221 | i810_set_spdif_output(state, -1, 0); | 3222 | i810_set_spdif_output(state, -1, 0); |
3222 | i810_set_dac_channels(state, 2); | 3223 | i810_set_dac_channels(state, 2); |
3223 | i810_set_dac_rate(state, 48000); | 3224 | i810_set_dac_rate(state, 48000); |
3224 | if(prog_dmabuf(state, 0) != 0) { | 3225 | if(prog_dmabuf(state, 0) != 0) { |
3225 | goto config_out_nodmabuf; | 3226 | goto config_out_nodmabuf; |
3226 | } | 3227 | } |
3227 | if(dmabuf->dmasize < 16384) { | 3228 | if(dmabuf->dmasize < 16384) { |
3228 | goto config_out; | 3229 | goto config_out; |
3229 | } | 3230 | } |
3230 | dmabuf->count = dmabuf->dmasize; | 3231 | dmabuf->count = dmabuf->dmasize; |
3231 | CIV_TO_LVI(card, dmabuf->write_channel->port, -1); | 3232 | CIV_TO_LVI(card, dmabuf->write_channel->port, -1); |
3232 | local_irq_save(flags); | 3233 | local_irq_save(flags); |
3233 | start_dac(state); | 3234 | start_dac(state); |
3234 | offset = i810_get_dma_addr(state, 0); | 3235 | offset = i810_get_dma_addr(state, 0); |
3235 | mdelay(50); | 3236 | mdelay(50); |
3236 | new_offset = i810_get_dma_addr(state, 0); | 3237 | new_offset = i810_get_dma_addr(state, 0); |
3237 | stop_dac(state); | 3238 | stop_dac(state); |
3238 | local_irq_restore(flags); | 3239 | local_irq_restore(flags); |
3239 | i = new_offset - offset; | 3240 | i = new_offset - offset; |
3240 | #ifdef DEBUG_INTERRUPTS | 3241 | #ifdef DEBUG_INTERRUPTS |
3241 | printk("i810_audio: %d bytes in 50 milliseconds\n", i); | 3242 | printk("i810_audio: %d bytes in 50 milliseconds\n", i); |
3242 | #endif | 3243 | #endif |
3243 | if(i == 0) | 3244 | if(i == 0) |
3244 | goto config_out; | 3245 | goto config_out; |
3245 | i = i / 4 * 20; | 3246 | i = i / 4 * 20; |
3246 | if (i > 48500 || i < 47500) { | 3247 | if (i > 48500 || i < 47500) { |
3247 | clocking = clocking * clocking / i; | 3248 | clocking = clocking * clocking / i; |
3248 | printk("i810_audio: setting clocking to %d\n", clocking); | 3249 | printk("i810_audio: setting clocking to %d\n", clocking); |
3249 | } | 3250 | } |
3250 | config_out: | 3251 | config_out: |
3251 | dealloc_dmabuf(state); | 3252 | dealloc_dmabuf(state); |
3252 | config_out_nodmabuf: | 3253 | config_out_nodmabuf: |
3253 | state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num); | 3254 | state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num); |
3254 | kfree(state); | 3255 | kfree(state); |
3255 | card->states[0] = NULL; | 3256 | card->states[0] = NULL; |
3256 | } | 3257 | } |
3257 | } | 3258 | } |
3258 | 3259 | ||
3259 | /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered | 3260 | /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered |
3260 | until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */ | 3261 | until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */ |
3261 | 3262 | ||
3262 | static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) | 3263 | static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) |
3263 | { | 3264 | { |
3264 | struct i810_card *card; | 3265 | struct i810_card *card; |
3265 | 3266 | ||
3266 | if (pci_enable_device(pci_dev)) | 3267 | if (pci_enable_device(pci_dev)) |
3267 | return -EIO; | 3268 | return -EIO; |
3268 | 3269 | ||
3269 | if (pci_set_dma_mask(pci_dev, I810_DMA_MASK)) { | 3270 | if (pci_set_dma_mask(pci_dev, I810_DMA_MASK)) { |
3270 | printk(KERN_ERR "i810_audio: architecture does not support" | 3271 | printk(KERN_ERR "i810_audio: architecture does not support" |
3271 | " 32bit PCI busmaster DMA\n"); | 3272 | " 32bit PCI busmaster DMA\n"); |
3272 | return -ENODEV; | 3273 | return -ENODEV; |
3273 | } | 3274 | } |
3274 | 3275 | ||
3275 | if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) { | 3276 | if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) { |
3276 | printk(KERN_ERR "i810_audio: out of memory\n"); | 3277 | printk(KERN_ERR "i810_audio: out of memory\n"); |
3277 | return -ENOMEM; | 3278 | return -ENOMEM; |
3278 | } | 3279 | } |
3279 | memset(card, 0, sizeof(*card)); | 3280 | memset(card, 0, sizeof(*card)); |
3280 | 3281 | ||
3281 | card->initializing = 1; | 3282 | card->initializing = 1; |
3282 | card->pci_dev = pci_dev; | 3283 | card->pci_dev = pci_dev; |
3283 | card->pci_id = pci_id->device; | 3284 | card->pci_id = pci_id->device; |
3284 | card->ac97base = pci_resource_start (pci_dev, 0); | 3285 | card->ac97base = pci_resource_start (pci_dev, 0); |
3285 | card->iobase = pci_resource_start (pci_dev, 1); | 3286 | card->iobase = pci_resource_start (pci_dev, 1); |
3286 | 3287 | ||
3287 | if (!(card->ac97base) || !(card->iobase)) { | 3288 | if (!(card->ac97base) || !(card->iobase)) { |
3288 | card->ac97base = 0; | 3289 | card->ac97base = 0; |
3289 | card->iobase = 0; | 3290 | card->iobase = 0; |
3290 | } | 3291 | } |
3291 | 3292 | ||
3292 | /* if chipset could have mmio capability, check it */ | 3293 | /* if chipset could have mmio capability, check it */ |
3293 | if (card_cap[pci_id->driver_data].flags & CAP_MMIO) { | 3294 | if (card_cap[pci_id->driver_data].flags & CAP_MMIO) { |
3294 | card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2); | 3295 | card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2); |
3295 | card->iobase_mmio_phys = pci_resource_start (pci_dev, 3); | 3296 | card->iobase_mmio_phys = pci_resource_start (pci_dev, 3); |
3296 | 3297 | ||
3297 | if ((card->ac97base_mmio_phys) && (card->iobase_mmio_phys)) { | 3298 | if ((card->ac97base_mmio_phys) && (card->iobase_mmio_phys)) { |
3298 | card->use_mmio = 1; | 3299 | card->use_mmio = 1; |
3299 | } | 3300 | } |
3300 | else { | 3301 | else { |
3301 | card->ac97base_mmio_phys = 0; | 3302 | card->ac97base_mmio_phys = 0; |
3302 | card->iobase_mmio_phys = 0; | 3303 | card->iobase_mmio_phys = 0; |
3303 | } | 3304 | } |
3304 | } | 3305 | } |
3305 | 3306 | ||
3306 | if (!(card->use_mmio) && (!(card->iobase) || !(card->ac97base))) { | 3307 | if (!(card->use_mmio) && (!(card->iobase) || !(card->ac97base))) { |
3307 | printk(KERN_ERR "i810_audio: No I/O resources available.\n"); | 3308 | printk(KERN_ERR "i810_audio: No I/O resources available.\n"); |
3308 | goto out_mem; | 3309 | goto out_mem; |
3309 | } | 3310 | } |
3310 | 3311 | ||
3311 | card->irq = pci_dev->irq; | 3312 | card->irq = pci_dev->irq; |
3312 | card->next = devs; | 3313 | card->next = devs; |
3313 | card->magic = I810_CARD_MAGIC; | 3314 | card->magic = I810_CARD_MAGIC; |
3314 | #ifdef CONFIG_PM | 3315 | #ifdef CONFIG_PM |
3315 | card->pm_suspended=0; | 3316 | card->pm_suspended=0; |
3316 | #endif | 3317 | #endif |
3317 | spin_lock_init(&card->lock); | 3318 | spin_lock_init(&card->lock); |
3318 | spin_lock_init(&card->ac97_lock); | 3319 | spin_lock_init(&card->ac97_lock); |
3319 | devs = card; | 3320 | devs = card; |
3320 | 3321 | ||
3321 | pci_set_master(pci_dev); | 3322 | pci_set_master(pci_dev); |
3322 | 3323 | ||
3323 | printk(KERN_INFO "i810: %s found at IO 0x%04lx and 0x%04lx, " | 3324 | printk(KERN_INFO "i810: %s found at IO 0x%04lx and 0x%04lx, " |
3324 | "MEM 0x%04lx and 0x%04lx, IRQ %d\n", | 3325 | "MEM 0x%04lx and 0x%04lx, IRQ %d\n", |
3325 | card_names[pci_id->driver_data], | 3326 | card_names[pci_id->driver_data], |
3326 | card->iobase, card->ac97base, | 3327 | card->iobase, card->ac97base, |
3327 | card->ac97base_mmio_phys, card->iobase_mmio_phys, | 3328 | card->ac97base_mmio_phys, card->iobase_mmio_phys, |
3328 | card->irq); | 3329 | card->irq); |
3329 | 3330 | ||
3330 | card->alloc_pcm_channel = i810_alloc_pcm_channel; | 3331 | card->alloc_pcm_channel = i810_alloc_pcm_channel; |
3331 | card->alloc_rec_pcm_channel = i810_alloc_rec_pcm_channel; | 3332 | card->alloc_rec_pcm_channel = i810_alloc_rec_pcm_channel; |
3332 | card->alloc_rec_mic_channel = i810_alloc_rec_mic_channel; | 3333 | card->alloc_rec_mic_channel = i810_alloc_rec_mic_channel; |
3333 | card->free_pcm_channel = i810_free_pcm_channel; | 3334 | card->free_pcm_channel = i810_free_pcm_channel; |
3334 | 3335 | ||
3335 | if ((card->channel = pci_alloc_consistent(pci_dev, | 3336 | if ((card->channel = pci_alloc_consistent(pci_dev, |
3336 | sizeof(struct i810_channel)*NR_HW_CH, &card->chandma)) == NULL) { | 3337 | sizeof(struct i810_channel)*NR_HW_CH, &card->chandma)) == NULL) { |
3337 | printk(KERN_ERR "i810: cannot allocate channel DMA memory\n"); | 3338 | printk(KERN_ERR "i810: cannot allocate channel DMA memory\n"); |
3338 | goto out_mem; | 3339 | goto out_mem; |
3339 | } | 3340 | } |
3340 | 3341 | ||
3341 | { /* We may dispose of this altogether some time soon, so... */ | 3342 | { /* We may dispose of this altogether some time soon, so... */ |
3342 | struct i810_channel *cp = card->channel; | 3343 | struct i810_channel *cp = card->channel; |
3343 | 3344 | ||
3344 | cp[0].offset = 0; | 3345 | cp[0].offset = 0; |
3345 | cp[0].port = 0x00; | 3346 | cp[0].port = 0x00; |
3346 | cp[0].num = 0; | 3347 | cp[0].num = 0; |
3347 | cp[1].offset = 0; | 3348 | cp[1].offset = 0; |
3348 | cp[1].port = 0x10; | 3349 | cp[1].port = 0x10; |
3349 | cp[1].num = 1; | 3350 | cp[1].num = 1; |
3350 | cp[2].offset = 0; | 3351 | cp[2].offset = 0; |
3351 | cp[2].port = 0x20; | 3352 | cp[2].port = 0x20; |
3352 | cp[2].num = 2; | 3353 | cp[2].num = 2; |
3353 | } | 3354 | } |
3354 | 3355 | ||
3355 | /* claim our iospace and irq */ | 3356 | /* claim our iospace and irq */ |
3356 | if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) { | 3357 | if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) { |
3357 | printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase); | 3358 | printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase); |
3358 | goto out_region1; | 3359 | goto out_region1; |
3359 | } | 3360 | } |
3360 | if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) { | 3361 | if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) { |
3361 | printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base); | 3362 | printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base); |
3362 | goto out_region2; | 3363 | goto out_region2; |
3363 | } | 3364 | } |
3364 | 3365 | ||
3365 | if (card->use_mmio) { | 3366 | if (card->use_mmio) { |
3366 | if (request_mem_region(card->ac97base_mmio_phys, 512, "ich_audio MMBAR")) { | 3367 | if (request_mem_region(card->ac97base_mmio_phys, 512, "ich_audio MMBAR")) { |
3367 | if ((card->ac97base_mmio = ioremap(card->ac97base_mmio_phys, 512))) { /*@FIXME can ioremap fail? don't know (jsaw) */ | 3368 | if ((card->ac97base_mmio = ioremap(card->ac97base_mmio_phys, 512))) { /*@FIXME can ioremap fail? don't know (jsaw) */ |
3368 | if (request_mem_region(card->iobase_mmio_phys, 256, "ich_audio MBBAR")) { | 3369 | if (request_mem_region(card->iobase_mmio_phys, 256, "ich_audio MBBAR")) { |
3369 | if ((card->iobase_mmio = ioremap(card->iobase_mmio_phys, 256))) { | 3370 | if ((card->iobase_mmio = ioremap(card->iobase_mmio_phys, 256))) { |
3370 | printk(KERN_INFO "i810: %s mmio at 0x%04lx and 0x%04lx\n", | 3371 | printk(KERN_INFO "i810: %s mmio at 0x%04lx and 0x%04lx\n", |
3371 | card_names[pci_id->driver_data], | 3372 | card_names[pci_id->driver_data], |
3372 | (unsigned long) card->ac97base_mmio, | 3373 | (unsigned long) card->ac97base_mmio, |
3373 | (unsigned long) card->iobase_mmio); | 3374 | (unsigned long) card->iobase_mmio); |
3374 | } | 3375 | } |
3375 | else { | 3376 | else { |
3376 | iounmap(card->ac97base_mmio); | 3377 | iounmap(card->ac97base_mmio); |
3377 | release_mem_region(card->ac97base_mmio_phys, 512); | 3378 | release_mem_region(card->ac97base_mmio_phys, 512); |
3378 | release_mem_region(card->iobase_mmio_phys, 512); | 3379 | release_mem_region(card->iobase_mmio_phys, 512); |
3379 | card->use_mmio = 0; | 3380 | card->use_mmio = 0; |
3380 | } | 3381 | } |
3381 | } | 3382 | } |
3382 | else { | 3383 | else { |
3383 | iounmap(card->ac97base_mmio); | 3384 | iounmap(card->ac97base_mmio); |
3384 | release_mem_region(card->ac97base_mmio_phys, 512); | 3385 | release_mem_region(card->ac97base_mmio_phys, 512); |
3385 | card->use_mmio = 0; | 3386 | card->use_mmio = 0; |
3386 | } | 3387 | } |
3387 | } | 3388 | } |
3388 | } | 3389 | } |
3389 | else { | 3390 | else { |
3390 | card->use_mmio = 0; | 3391 | card->use_mmio = 0; |
3391 | } | 3392 | } |
3392 | } | 3393 | } |
3393 | 3394 | ||
3394 | /* initialize AC97 codec and register /dev/mixer */ | 3395 | /* initialize AC97 codec and register /dev/mixer */ |
3395 | if (i810_ac97_init(card) <= 0) | 3396 | if (i810_ac97_init(card) <= 0) |
3396 | goto out_iospace; | 3397 | goto out_iospace; |
3397 | pci_set_drvdata(pci_dev, card); | 3398 | pci_set_drvdata(pci_dev, card); |
3398 | 3399 | ||
3399 | if(clocking == 0) { | 3400 | if(clocking == 0) { |
3400 | clocking = 48000; | 3401 | clocking = 48000; |
3401 | i810_configure_clocking(); | 3402 | i810_configure_clocking(); |
3402 | } | 3403 | } |
3403 | 3404 | ||
3404 | /* register /dev/dsp */ | 3405 | /* register /dev/dsp */ |
3405 | if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) { | 3406 | if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) { |
3406 | int i; | 3407 | int i; |
3407 | printk(KERN_ERR "i810_audio: couldn't register DSP device!\n"); | 3408 | printk(KERN_ERR "i810_audio: couldn't register DSP device!\n"); |
3408 | for (i = 0; i < NR_AC97; i++) | 3409 | for (i = 0; i < NR_AC97; i++) |
3409 | if (card->ac97_codec[i] != NULL) { | 3410 | if (card->ac97_codec[i] != NULL) { |
3410 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); | 3411 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); |
3411 | ac97_release_codec(card->ac97_codec[i]); | 3412 | ac97_release_codec(card->ac97_codec[i]); |
3412 | } | 3413 | } |
3413 | goto out_iospace; | 3414 | goto out_iospace; |
3414 | } | 3415 | } |
3415 | 3416 | ||
3416 | if (request_irq(card->irq, &i810_interrupt, IRQF_SHARED, | 3417 | if (request_irq(card->irq, &i810_interrupt, IRQF_SHARED, |
3417 | card_names[pci_id->driver_data], card)) { | 3418 | card_names[pci_id->driver_data], card)) { |
3418 | printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq); | 3419 | printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq); |
3419 | goto out_iospace; | 3420 | goto out_iospace; |
3420 | } | 3421 | } |
3421 | 3422 | ||
3422 | 3423 | ||
3423 | card->initializing = 0; | 3424 | card->initializing = 0; |
3424 | return 0; | 3425 | return 0; |
3425 | 3426 | ||
3426 | out_iospace: | 3427 | out_iospace: |
3427 | if (card->use_mmio) { | 3428 | if (card->use_mmio) { |
3428 | iounmap(card->ac97base_mmio); | 3429 | iounmap(card->ac97base_mmio); |
3429 | iounmap(card->iobase_mmio); | 3430 | iounmap(card->iobase_mmio); |
3430 | release_mem_region(card->ac97base_mmio_phys, 512); | 3431 | release_mem_region(card->ac97base_mmio_phys, 512); |
3431 | release_mem_region(card->iobase_mmio_phys, 256); | 3432 | release_mem_region(card->iobase_mmio_phys, 256); |
3432 | } | 3433 | } |
3433 | release_region(card->ac97base, 256); | 3434 | release_region(card->ac97base, 256); |
3434 | out_region2: | 3435 | out_region2: |
3435 | release_region(card->iobase, 64); | 3436 | release_region(card->iobase, 64); |
3436 | out_region1: | 3437 | out_region1: |
3437 | pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH, | 3438 | pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH, |
3438 | card->channel, card->chandma); | 3439 | card->channel, card->chandma); |
3439 | out_mem: | 3440 | out_mem: |
3440 | kfree(card); | 3441 | kfree(card); |
3441 | return -ENODEV; | 3442 | return -ENODEV; |
3442 | } | 3443 | } |
3443 | 3444 | ||
3444 | static void __devexit i810_remove(struct pci_dev *pci_dev) | 3445 | static void __devexit i810_remove(struct pci_dev *pci_dev) |
3445 | { | 3446 | { |
3446 | int i; | 3447 | int i; |
3447 | struct i810_card *card = pci_get_drvdata(pci_dev); | 3448 | struct i810_card *card = pci_get_drvdata(pci_dev); |
3448 | /* free hardware resources */ | 3449 | /* free hardware resources */ |
3449 | free_irq(card->irq, devs); | 3450 | free_irq(card->irq, devs); |
3450 | release_region(card->iobase, 64); | 3451 | release_region(card->iobase, 64); |
3451 | release_region(card->ac97base, 256); | 3452 | release_region(card->ac97base, 256); |
3452 | pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH, | 3453 | pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH, |
3453 | card->channel, card->chandma); | 3454 | card->channel, card->chandma); |
3454 | if (card->use_mmio) { | 3455 | if (card->use_mmio) { |
3455 | iounmap(card->ac97base_mmio); | 3456 | iounmap(card->ac97base_mmio); |
3456 | iounmap(card->iobase_mmio); | 3457 | iounmap(card->iobase_mmio); |
3457 | release_mem_region(card->ac97base_mmio_phys, 512); | 3458 | release_mem_region(card->ac97base_mmio_phys, 512); |
3458 | release_mem_region(card->iobase_mmio_phys, 256); | 3459 | release_mem_region(card->iobase_mmio_phys, 256); |
3459 | } | 3460 | } |
3460 | 3461 | ||
3461 | /* unregister audio devices */ | 3462 | /* unregister audio devices */ |
3462 | for (i = 0; i < NR_AC97; i++) | 3463 | for (i = 0; i < NR_AC97; i++) |
3463 | if (card->ac97_codec[i] != NULL) { | 3464 | if (card->ac97_codec[i] != NULL) { |
3464 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); | 3465 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); |
3465 | ac97_release_codec(card->ac97_codec[i]); | 3466 | ac97_release_codec(card->ac97_codec[i]); |
3466 | card->ac97_codec[i] = NULL; | 3467 | card->ac97_codec[i] = NULL; |
3467 | } | 3468 | } |
3468 | unregister_sound_dsp(card->dev_audio); | 3469 | unregister_sound_dsp(card->dev_audio); |
3469 | kfree(card); | 3470 | kfree(card); |
3470 | } | 3471 | } |
3471 | 3472 | ||
3472 | #ifdef CONFIG_PM | 3473 | #ifdef CONFIG_PM |
3473 | static int i810_pm_suspend(struct pci_dev *dev, pm_message_t pm_state) | 3474 | static int i810_pm_suspend(struct pci_dev *dev, pm_message_t pm_state) |
3474 | { | 3475 | { |
3475 | struct i810_card *card = pci_get_drvdata(dev); | 3476 | struct i810_card *card = pci_get_drvdata(dev); |
3476 | struct i810_state *state; | 3477 | struct i810_state *state; |
3477 | unsigned long flags; | 3478 | unsigned long flags; |
3478 | struct dmabuf *dmabuf; | 3479 | struct dmabuf *dmabuf; |
3479 | int i,num_ac97; | 3480 | int i,num_ac97; |
3480 | #ifdef DEBUG | 3481 | #ifdef DEBUG |
3481 | printk("i810_audio: i810_pm_suspend called\n"); | 3482 | printk("i810_audio: i810_pm_suspend called\n"); |
3482 | #endif | 3483 | #endif |
3483 | if(!card) return 0; | 3484 | if(!card) return 0; |
3484 | spin_lock_irqsave(&card->lock, flags); | 3485 | spin_lock_irqsave(&card->lock, flags); |
3485 | card->pm_suspended=1; | 3486 | card->pm_suspended=1; |
3486 | for(i=0;i<NR_HW_CH;i++) { | 3487 | for(i=0;i<NR_HW_CH;i++) { |
3487 | state = card->states[i]; | 3488 | state = card->states[i]; |
3488 | if(!state) continue; | 3489 | if(!state) continue; |
3489 | /* this happens only if there are open files */ | 3490 | /* this happens only if there are open files */ |
3490 | dmabuf = &state->dmabuf; | 3491 | dmabuf = &state->dmabuf; |
3491 | if(dmabuf->enable & DAC_RUNNING || | 3492 | if(dmabuf->enable & DAC_RUNNING || |
3492 | (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { | 3493 | (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { |
3493 | state->pm_saved_dac_rate=dmabuf->rate; | 3494 | state->pm_saved_dac_rate=dmabuf->rate; |
3494 | stop_dac(state); | 3495 | stop_dac(state); |
3495 | } else { | 3496 | } else { |
3496 | state->pm_saved_dac_rate=0; | 3497 | state->pm_saved_dac_rate=0; |
3497 | } | 3498 | } |
3498 | if(dmabuf->enable & ADC_RUNNING) { | 3499 | if(dmabuf->enable & ADC_RUNNING) { |
3499 | state->pm_saved_adc_rate=dmabuf->rate; | 3500 | state->pm_saved_adc_rate=dmabuf->rate; |
3500 | stop_adc(state); | 3501 | stop_adc(state); |
3501 | } else { | 3502 | } else { |
3502 | state->pm_saved_adc_rate=0; | 3503 | state->pm_saved_adc_rate=0; |
3503 | } | 3504 | } |
3504 | dmabuf->ready = 0; | 3505 | dmabuf->ready = 0; |
3505 | dmabuf->swptr = dmabuf->hwptr = 0; | 3506 | dmabuf->swptr = dmabuf->hwptr = 0; |
3506 | dmabuf->count = dmabuf->total_bytes = 0; | 3507 | dmabuf->count = dmabuf->total_bytes = 0; |
3507 | } | 3508 | } |
3508 | 3509 | ||
3509 | spin_unlock_irqrestore(&card->lock, flags); | 3510 | spin_unlock_irqrestore(&card->lock, flags); |
3510 | 3511 | ||
3511 | /* save mixer settings */ | 3512 | /* save mixer settings */ |
3512 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { | 3513 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { |
3513 | struct ac97_codec *codec = card->ac97_codec[num_ac97]; | 3514 | struct ac97_codec *codec = card->ac97_codec[num_ac97]; |
3514 | if(!codec) continue; | 3515 | if(!codec) continue; |
3515 | for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) { | 3516 | for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) { |
3516 | if((supported_mixer(codec,i)) && | 3517 | if((supported_mixer(codec,i)) && |
3517 | (codec->read_mixer)) { | 3518 | (codec->read_mixer)) { |
3518 | card->pm_saved_mixer_settings[i][num_ac97]= | 3519 | card->pm_saved_mixer_settings[i][num_ac97]= |
3519 | codec->read_mixer(codec,i); | 3520 | codec->read_mixer(codec,i); |
3520 | } | 3521 | } |
3521 | } | 3522 | } |
3522 | } | 3523 | } |
3523 | pci_save_state(dev); /* XXX do we need this? */ | 3524 | pci_save_state(dev); /* XXX do we need this? */ |
3524 | pci_disable_device(dev); /* disable busmastering */ | 3525 | pci_disable_device(dev); /* disable busmastering */ |
3525 | pci_set_power_state(dev,3); /* Zzz. */ | 3526 | pci_set_power_state(dev,3); /* Zzz. */ |
3526 | 3527 | ||
3527 | return 0; | 3528 | return 0; |
3528 | } | 3529 | } |
3529 | 3530 | ||
3530 | 3531 | ||
3531 | static int i810_pm_resume(struct pci_dev *dev) | 3532 | static int i810_pm_resume(struct pci_dev *dev) |
3532 | { | 3533 | { |
3533 | int num_ac97,i=0; | 3534 | int num_ac97,i=0; |
3534 | struct i810_card *card=pci_get_drvdata(dev); | 3535 | struct i810_card *card=pci_get_drvdata(dev); |
3535 | pci_enable_device(dev); | 3536 | pci_enable_device(dev); |
3536 | pci_restore_state (dev); | 3537 | pci_restore_state (dev); |
3537 | 3538 | ||
3538 | /* observation of a toshiba portege 3440ct suggests that the | 3539 | /* observation of a toshiba portege 3440ct suggests that the |
3539 | hardware has to be more or less completely reinitialized from | 3540 | hardware has to be more or less completely reinitialized from |
3540 | scratch after an apm suspend. Works For Me. -dan */ | 3541 | scratch after an apm suspend. Works For Me. -dan */ |
3541 | 3542 | ||
3542 | i810_ac97_power_up_bus(card); | 3543 | i810_ac97_power_up_bus(card); |
3543 | 3544 | ||
3544 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { | 3545 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { |
3545 | struct ac97_codec *codec = card->ac97_codec[num_ac97]; | 3546 | struct ac97_codec *codec = card->ac97_codec[num_ac97]; |
3546 | /* check they haven't stolen the hardware while we were | 3547 | /* check they haven't stolen the hardware while we were |
3547 | away */ | 3548 | away */ |
3548 | if(!codec || !i810_ac97_exists(card,num_ac97)) { | 3549 | if(!codec || !i810_ac97_exists(card,num_ac97)) { |
3549 | if(num_ac97) continue; | 3550 | if(num_ac97) continue; |
3550 | else BUG(); | 3551 | else BUG(); |
3551 | } | 3552 | } |
3552 | if(!i810_ac97_probe_and_powerup(card,codec)) BUG(); | 3553 | if(!i810_ac97_probe_and_powerup(card,codec)) BUG(); |
3553 | 3554 | ||
3554 | if((card->ac97_features&0x0001)) { | 3555 | if((card->ac97_features&0x0001)) { |
3555 | /* at probe time we found we could do variable | 3556 | /* at probe time we found we could do variable |
3556 | rates, but APM suspend has made it forget | 3557 | rates, but APM suspend has made it forget |
3557 | its magical powers */ | 3558 | its magical powers */ |
3558 | if(!i810_ac97_enable_variable_rate(codec)) BUG(); | 3559 | if(!i810_ac97_enable_variable_rate(codec)) BUG(); |
3559 | } | 3560 | } |
3560 | /* we lost our mixer settings, so restore them */ | 3561 | /* we lost our mixer settings, so restore them */ |
3561 | for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) { | 3562 | for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) { |
3562 | if(supported_mixer(codec,i)){ | 3563 | if(supported_mixer(codec,i)){ |
3563 | int val=card-> | 3564 | int val=card-> |
3564 | pm_saved_mixer_settings[i][num_ac97]; | 3565 | pm_saved_mixer_settings[i][num_ac97]; |
3565 | codec->mixer_state[i]=val; | 3566 | codec->mixer_state[i]=val; |
3566 | codec->write_mixer(codec,i, | 3567 | codec->write_mixer(codec,i, |
3567 | (val & 0xff) , | 3568 | (val & 0xff) , |
3568 | ((val >> 8) & 0xff) ); | 3569 | ((val >> 8) & 0xff) ); |
3569 | } | 3570 | } |
3570 | } | 3571 | } |
3571 | } | 3572 | } |
3572 | 3573 | ||
3573 | /* we need to restore the sample rate from whatever it was */ | 3574 | /* we need to restore the sample rate from whatever it was */ |
3574 | for(i=0;i<NR_HW_CH;i++) { | 3575 | for(i=0;i<NR_HW_CH;i++) { |
3575 | struct i810_state * state=card->states[i]; | 3576 | struct i810_state * state=card->states[i]; |
3576 | if(state) { | 3577 | if(state) { |
3577 | if(state->pm_saved_adc_rate) | 3578 | if(state->pm_saved_adc_rate) |
3578 | i810_set_adc_rate(state,state->pm_saved_adc_rate); | 3579 | i810_set_adc_rate(state,state->pm_saved_adc_rate); |
3579 | if(state->pm_saved_dac_rate) | 3580 | if(state->pm_saved_dac_rate) |
3580 | i810_set_dac_rate(state,state->pm_saved_dac_rate); | 3581 | i810_set_dac_rate(state,state->pm_saved_dac_rate); |
3581 | } | 3582 | } |
3582 | } | 3583 | } |
3583 | 3584 | ||
3584 | 3585 | ||
3585 | card->pm_suspended = 0; | 3586 | card->pm_suspended = 0; |
3586 | 3587 | ||
3587 | /* any processes that were reading/writing during the suspend | 3588 | /* any processes that were reading/writing during the suspend |
3588 | probably ended up here */ | 3589 | probably ended up here */ |
3589 | for(i=0;i<NR_HW_CH;i++) { | 3590 | for(i=0;i<NR_HW_CH;i++) { |
3590 | struct i810_state *state = card->states[i]; | 3591 | struct i810_state *state = card->states[i]; |
3591 | if(state) wake_up(&state->dmabuf.wait); | 3592 | if(state) wake_up(&state->dmabuf.wait); |
3592 | } | 3593 | } |
3593 | 3594 | ||
3594 | return 0; | 3595 | return 0; |
3595 | } | 3596 | } |
3596 | #endif /* CONFIG_PM */ | 3597 | #endif /* CONFIG_PM */ |
3597 | 3598 | ||
3598 | MODULE_AUTHOR("The Linux kernel team"); | 3599 | MODULE_AUTHOR("The Linux kernel team"); |
3599 | MODULE_DESCRIPTION("Intel 810 audio support"); | 3600 | MODULE_DESCRIPTION("Intel 810 audio support"); |
3600 | MODULE_LICENSE("GPL"); | 3601 | MODULE_LICENSE("GPL"); |
3601 | module_param(ftsodell, int, 0444); | 3602 | module_param(ftsodell, int, 0444); |
3602 | module_param(clocking, uint, 0444); | 3603 | module_param(clocking, uint, 0444); |
3603 | module_param(strict_clocking, int, 0444); | 3604 | module_param(strict_clocking, int, 0444); |
3604 | module_param(spdif_locked, int, 0444); | 3605 | module_param(spdif_locked, int, 0444); |
3605 | 3606 | ||
3606 | #define I810_MODULE_NAME "i810_audio" | 3607 | #define I810_MODULE_NAME "i810_audio" |
3607 | 3608 | ||
3608 | static struct pci_driver i810_pci_driver = { | 3609 | static struct pci_driver i810_pci_driver = { |
3609 | .name = I810_MODULE_NAME, | 3610 | .name = I810_MODULE_NAME, |
3610 | .id_table = i810_pci_tbl, | 3611 | .id_table = i810_pci_tbl, |
3611 | .probe = i810_probe, | 3612 | .probe = i810_probe, |
3612 | .remove = __devexit_p(i810_remove), | 3613 | .remove = __devexit_p(i810_remove), |
3613 | #ifdef CONFIG_PM | 3614 | #ifdef CONFIG_PM |
3614 | .suspend = i810_pm_suspend, | 3615 | .suspend = i810_pm_suspend, |
3615 | .resume = i810_pm_resume, | 3616 | .resume = i810_pm_resume, |
3616 | #endif /* CONFIG_PM */ | 3617 | #endif /* CONFIG_PM */ |
3617 | }; | 3618 | }; |
3618 | 3619 | ||
3619 | 3620 | ||
3620 | static int __init i810_init_module (void) | 3621 | static int __init i810_init_module (void) |
3621 | { | 3622 | { |
3622 | int retval; | 3623 | int retval; |
3623 | 3624 | ||
3624 | printk(KERN_INFO "Intel 810 + AC97 Audio, version " | 3625 | printk(KERN_INFO "Intel 810 + AC97 Audio, version " |
3625 | DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); | 3626 | DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); |
3626 | 3627 | ||
3627 | retval = pci_register_driver(&i810_pci_driver); | 3628 | retval = pci_register_driver(&i810_pci_driver); |
3628 | if (retval) | 3629 | if (retval) |
3629 | return retval; | 3630 | return retval; |
3630 | 3631 | ||
3631 | if(ftsodell != 0) { | 3632 | if(ftsodell != 0) { |
3632 | printk("i810_audio: ftsodell is now a deprecated option.\n"); | 3633 | printk("i810_audio: ftsodell is now a deprecated option.\n"); |
3633 | } | 3634 | } |
3634 | if(spdif_locked > 0 ) { | 3635 | if(spdif_locked > 0 ) { |
3635 | if(spdif_locked == 32000 || spdif_locked == 44100 || spdif_locked == 48000) { | 3636 | if(spdif_locked == 32000 || spdif_locked == 44100 || spdif_locked == 48000) { |
3636 | printk("i810_audio: Enabling S/PDIF at sample rate %dHz.\n", spdif_locked); | 3637 | printk("i810_audio: Enabling S/PDIF at sample rate %dHz.\n", spdif_locked); |
3637 | } else { | 3638 | } else { |
3638 | printk("i810_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n"); | 3639 | printk("i810_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n"); |
3639 | spdif_locked = 0; | 3640 | spdif_locked = 0; |
3640 | } | 3641 | } |
3641 | } | 3642 | } |
3642 | 3643 | ||
3643 | return 0; | 3644 | return 0; |
3644 | } | 3645 | } |
3645 | 3646 | ||
3646 | static void __exit i810_cleanup_module (void) | 3647 | static void __exit i810_cleanup_module (void) |
3647 | { | 3648 | { |
3648 | pci_unregister_driver(&i810_pci_driver); | 3649 | pci_unregister_driver(&i810_pci_driver); |
3649 | } | 3650 | } |
3650 | 3651 | ||
3651 | module_init(i810_init_module); | 3652 | module_init(i810_init_module); |
3652 | module_exit(i810_cleanup_module); | 3653 | module_exit(i810_cleanup_module); |
3653 | 3654 | ||
3654 | /* | 3655 | /* |
3655 | Local Variables: | 3656 | Local Variables: |
3656 | c-basic-offset: 8 | 3657 | c-basic-offset: 8 |
3657 | End: | 3658 | End: |
3658 | */ | 3659 | */ |
3659 | 3660 |
sound/oss/soundcard.c
1 | /* | 1 | /* |
2 | * linux/sound/oss/soundcard.c | 2 | * linux/sound/oss/soundcard.c |
3 | * | 3 | * |
4 | * Sound card driver for Linux | 4 | * Sound card driver for Linux |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * Copyright (C) by Hannu Savolainen 1993-1997 | 7 | * Copyright (C) by Hannu Savolainen 1993-1997 |
8 | * | 8 | * |
9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) | 9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) |
10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software | 10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software |
11 | * for more info. | 11 | * for more info. |
12 | * | 12 | * |
13 | * | 13 | * |
14 | * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) | 14 | * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) |
15 | * integrated sound_switch.c | 15 | * integrated sound_switch.c |
16 | * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, | 16 | * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, |
17 | * which should disappear in the near future) | 17 | * which should disappear in the near future) |
18 | * Eric Dumas : devfs support (22-Jan-98) <dumas@linux.eu.org> with | 18 | * Eric Dumas : devfs support (22-Jan-98) <dumas@linux.eu.org> with |
19 | * fixups by C. Scott Ananian <cananian@alumni.princeton.edu> | 19 | * fixups by C. Scott Ananian <cananian@alumni.princeton.edu> |
20 | * Richard Gooch : moved common (non OSS-specific) devices to sound_core.c | 20 | * Richard Gooch : moved common (non OSS-specific) devices to sound_core.c |
21 | * Rob Riggs : Added persistent DMA buffers support (1998/10/17) | 21 | * Rob Riggs : Added persistent DMA buffers support (1998/10/17) |
22 | * Christoph Hellwig : Some cleanup work (2000/03/01) | 22 | * Christoph Hellwig : Some cleanup work (2000/03/01) |
23 | */ | 23 | */ |
24 | 24 | ||
25 | 25 | ||
26 | #include "sound_config.h" | 26 | #include "sound_config.h" |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/signal.h> | 30 | #include <linux/signal.h> |
31 | #include <linux/fcntl.h> | 31 | #include <linux/fcntl.h> |
32 | #include <linux/ctype.h> | 32 | #include <linux/ctype.h> |
33 | #include <linux/stddef.h> | 33 | #include <linux/stddef.h> |
34 | #include <linux/kmod.h> | 34 | #include <linux/kmod.h> |
35 | #include <asm/dma.h> | 35 | #include <asm/dma.h> |
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | #include <linux/wait.h> | 37 | #include <linux/wait.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
40 | #include <linux/major.h> | 40 | #include <linux/major.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
43 | #include <linux/smp_lock.h> | 43 | #include <linux/smp_lock.h> |
44 | #include <linux/module.h> | 44 | #include <linux/module.h> |
45 | #include <linux/mm.h> | ||
45 | 46 | ||
46 | /* | 47 | /* |
47 | * This ought to be moved into include/asm/dma.h | 48 | * This ought to be moved into include/asm/dma.h |
48 | */ | 49 | */ |
49 | #ifndef valid_dma | 50 | #ifndef valid_dma |
50 | #define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4) | 51 | #define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4) |
51 | #endif | 52 | #endif |
52 | 53 | ||
53 | /* | 54 | /* |
54 | * Table for permanently allocated memory (used when unloading the module) | 55 | * Table for permanently allocated memory (used when unloading the module) |
55 | */ | 56 | */ |
56 | void * sound_mem_blocks[1024]; | 57 | void * sound_mem_blocks[1024]; |
57 | int sound_nblocks = 0; | 58 | int sound_nblocks = 0; |
58 | 59 | ||
59 | /* Persistent DMA buffers */ | 60 | /* Persistent DMA buffers */ |
60 | #ifdef CONFIG_SOUND_DMAP | 61 | #ifdef CONFIG_SOUND_DMAP |
61 | int sound_dmap_flag = 1; | 62 | int sound_dmap_flag = 1; |
62 | #else | 63 | #else |
63 | int sound_dmap_flag = 0; | 64 | int sound_dmap_flag = 0; |
64 | #endif | 65 | #endif |
65 | 66 | ||
66 | static char dma_alloc_map[MAX_DMA_CHANNELS]; | 67 | static char dma_alloc_map[MAX_DMA_CHANNELS]; |
67 | 68 | ||
68 | #define DMA_MAP_UNAVAIL 0 | 69 | #define DMA_MAP_UNAVAIL 0 |
69 | #define DMA_MAP_FREE 1 | 70 | #define DMA_MAP_FREE 1 |
70 | #define DMA_MAP_BUSY 2 | 71 | #define DMA_MAP_BUSY 2 |
71 | 72 | ||
72 | 73 | ||
73 | unsigned long seq_time = 0; /* Time for /dev/sequencer */ | 74 | unsigned long seq_time = 0; /* Time for /dev/sequencer */ |
74 | extern struct class *sound_class; | 75 | extern struct class *sound_class; |
75 | 76 | ||
76 | /* | 77 | /* |
77 | * Table for configurable mixer volume handling | 78 | * Table for configurable mixer volume handling |
78 | */ | 79 | */ |
79 | static mixer_vol_table mixer_vols[MAX_MIXER_DEV]; | 80 | static mixer_vol_table mixer_vols[MAX_MIXER_DEV]; |
80 | static int num_mixer_volumes; | 81 | static int num_mixer_volumes; |
81 | 82 | ||
82 | int *load_mixer_volumes(char *name, int *levels, int present) | 83 | int *load_mixer_volumes(char *name, int *levels, int present) |
83 | { | 84 | { |
84 | int i, n; | 85 | int i, n; |
85 | 86 | ||
86 | for (i = 0; i < num_mixer_volumes; i++) { | 87 | for (i = 0; i < num_mixer_volumes; i++) { |
87 | if (strcmp(name, mixer_vols[i].name) == 0) { | 88 | if (strcmp(name, mixer_vols[i].name) == 0) { |
88 | if (present) | 89 | if (present) |
89 | mixer_vols[i].num = i; | 90 | mixer_vols[i].num = i; |
90 | return mixer_vols[i].levels; | 91 | return mixer_vols[i].levels; |
91 | } | 92 | } |
92 | } | 93 | } |
93 | if (num_mixer_volumes >= MAX_MIXER_DEV) { | 94 | if (num_mixer_volumes >= MAX_MIXER_DEV) { |
94 | printk(KERN_ERR "Sound: Too many mixers (%s)\n", name); | 95 | printk(KERN_ERR "Sound: Too many mixers (%s)\n", name); |
95 | return levels; | 96 | return levels; |
96 | } | 97 | } |
97 | n = num_mixer_volumes++; | 98 | n = num_mixer_volumes++; |
98 | 99 | ||
99 | strcpy(mixer_vols[n].name, name); | 100 | strcpy(mixer_vols[n].name, name); |
100 | 101 | ||
101 | if (present) | 102 | if (present) |
102 | mixer_vols[n].num = n; | 103 | mixer_vols[n].num = n; |
103 | else | 104 | else |
104 | mixer_vols[n].num = -1; | 105 | mixer_vols[n].num = -1; |
105 | 106 | ||
106 | for (i = 0; i < 32; i++) | 107 | for (i = 0; i < 32; i++) |
107 | mixer_vols[n].levels[i] = levels[i]; | 108 | mixer_vols[n].levels[i] = levels[i]; |
108 | return mixer_vols[n].levels; | 109 | return mixer_vols[n].levels; |
109 | } | 110 | } |
110 | EXPORT_SYMBOL(load_mixer_volumes); | 111 | EXPORT_SYMBOL(load_mixer_volumes); |
111 | 112 | ||
112 | static int set_mixer_levels(void __user * arg) | 113 | static int set_mixer_levels(void __user * arg) |
113 | { | 114 | { |
114 | /* mixer_vol_table is 174 bytes, so IMHO no reason to not allocate it on the stack */ | 115 | /* mixer_vol_table is 174 bytes, so IMHO no reason to not allocate it on the stack */ |
115 | mixer_vol_table buf; | 116 | mixer_vol_table buf; |
116 | 117 | ||
117 | if (__copy_from_user(&buf, arg, sizeof(buf))) | 118 | if (__copy_from_user(&buf, arg, sizeof(buf))) |
118 | return -EFAULT; | 119 | return -EFAULT; |
119 | load_mixer_volumes(buf.name, buf.levels, 0); | 120 | load_mixer_volumes(buf.name, buf.levels, 0); |
120 | if (__copy_to_user(arg, &buf, sizeof(buf))) | 121 | if (__copy_to_user(arg, &buf, sizeof(buf))) |
121 | return -EFAULT; | 122 | return -EFAULT; |
122 | return 0; | 123 | return 0; |
123 | } | 124 | } |
124 | 125 | ||
125 | static int get_mixer_levels(void __user * arg) | 126 | static int get_mixer_levels(void __user * arg) |
126 | { | 127 | { |
127 | int n; | 128 | int n; |
128 | 129 | ||
129 | if (__get_user(n, (int __user *)(&(((mixer_vol_table __user *)arg)->num)))) | 130 | if (__get_user(n, (int __user *)(&(((mixer_vol_table __user *)arg)->num)))) |
130 | return -EFAULT; | 131 | return -EFAULT; |
131 | if (n < 0 || n >= num_mixer_volumes) | 132 | if (n < 0 || n >= num_mixer_volumes) |
132 | return -EINVAL; | 133 | return -EINVAL; |
133 | if (__copy_to_user(arg, &mixer_vols[n], sizeof(mixer_vol_table))) | 134 | if (__copy_to_user(arg, &mixer_vols[n], sizeof(mixer_vol_table))) |
134 | return -EFAULT; | 135 | return -EFAULT; |
135 | return 0; | 136 | return 0; |
136 | } | 137 | } |
137 | 138 | ||
138 | /* 4K page size but our output routines use some slack for overruns */ | 139 | /* 4K page size but our output routines use some slack for overruns */ |
139 | #define PROC_BLOCK_SIZE (3*1024) | 140 | #define PROC_BLOCK_SIZE (3*1024) |
140 | 141 | ||
141 | static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 142 | static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
142 | { | 143 | { |
143 | int dev = iminor(file->f_dentry->d_inode); | 144 | int dev = iminor(file->f_dentry->d_inode); |
144 | int ret = -EINVAL; | 145 | int ret = -EINVAL; |
145 | 146 | ||
146 | /* | 147 | /* |
147 | * The OSS drivers aren't remotely happy without this locking, | 148 | * The OSS drivers aren't remotely happy without this locking, |
148 | * and unless someone fixes them when they are about to bite the | 149 | * and unless someone fixes them when they are about to bite the |
149 | * big one anyway, we might as well bandage here.. | 150 | * big one anyway, we might as well bandage here.. |
150 | */ | 151 | */ |
151 | 152 | ||
152 | lock_kernel(); | 153 | lock_kernel(); |
153 | 154 | ||
154 | DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); | 155 | DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); |
155 | switch (dev & 0x0f) { | 156 | switch (dev & 0x0f) { |
156 | case SND_DEV_DSP: | 157 | case SND_DEV_DSP: |
157 | case SND_DEV_DSP16: | 158 | case SND_DEV_DSP16: |
158 | case SND_DEV_AUDIO: | 159 | case SND_DEV_AUDIO: |
159 | ret = audio_read(dev, file, buf, count); | 160 | ret = audio_read(dev, file, buf, count); |
160 | break; | 161 | break; |
161 | 162 | ||
162 | case SND_DEV_SEQ: | 163 | case SND_DEV_SEQ: |
163 | case SND_DEV_SEQ2: | 164 | case SND_DEV_SEQ2: |
164 | ret = sequencer_read(dev, file, buf, count); | 165 | ret = sequencer_read(dev, file, buf, count); |
165 | break; | 166 | break; |
166 | 167 | ||
167 | case SND_DEV_MIDIN: | 168 | case SND_DEV_MIDIN: |
168 | ret = MIDIbuf_read(dev, file, buf, count); | 169 | ret = MIDIbuf_read(dev, file, buf, count); |
169 | } | 170 | } |
170 | unlock_kernel(); | 171 | unlock_kernel(); |
171 | return ret; | 172 | return ret; |
172 | } | 173 | } |
173 | 174 | ||
174 | static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 175 | static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) |
175 | { | 176 | { |
176 | int dev = iminor(file->f_dentry->d_inode); | 177 | int dev = iminor(file->f_dentry->d_inode); |
177 | int ret = -EINVAL; | 178 | int ret = -EINVAL; |
178 | 179 | ||
179 | lock_kernel(); | 180 | lock_kernel(); |
180 | DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count)); | 181 | DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count)); |
181 | switch (dev & 0x0f) { | 182 | switch (dev & 0x0f) { |
182 | case SND_DEV_SEQ: | 183 | case SND_DEV_SEQ: |
183 | case SND_DEV_SEQ2: | 184 | case SND_DEV_SEQ2: |
184 | ret = sequencer_write(dev, file, buf, count); | 185 | ret = sequencer_write(dev, file, buf, count); |
185 | break; | 186 | break; |
186 | 187 | ||
187 | case SND_DEV_DSP: | 188 | case SND_DEV_DSP: |
188 | case SND_DEV_DSP16: | 189 | case SND_DEV_DSP16: |
189 | case SND_DEV_AUDIO: | 190 | case SND_DEV_AUDIO: |
190 | ret = audio_write(dev, file, buf, count); | 191 | ret = audio_write(dev, file, buf, count); |
191 | break; | 192 | break; |
192 | 193 | ||
193 | case SND_DEV_MIDIN: | 194 | case SND_DEV_MIDIN: |
194 | ret = MIDIbuf_write(dev, file, buf, count); | 195 | ret = MIDIbuf_write(dev, file, buf, count); |
195 | break; | 196 | break; |
196 | } | 197 | } |
197 | unlock_kernel(); | 198 | unlock_kernel(); |
198 | return ret; | 199 | return ret; |
199 | } | 200 | } |
200 | 201 | ||
201 | static int sound_open(struct inode *inode, struct file *file) | 202 | static int sound_open(struct inode *inode, struct file *file) |
202 | { | 203 | { |
203 | int dev = iminor(inode); | 204 | int dev = iminor(inode); |
204 | int retval; | 205 | int retval; |
205 | 206 | ||
206 | DEB(printk("sound_open(dev=%d)\n", dev)); | 207 | DEB(printk("sound_open(dev=%d)\n", dev)); |
207 | if ((dev >= SND_NDEVS) || (dev < 0)) { | 208 | if ((dev >= SND_NDEVS) || (dev < 0)) { |
208 | printk(KERN_ERR "Invalid minor device %d\n", dev); | 209 | printk(KERN_ERR "Invalid minor device %d\n", dev); |
209 | return -ENXIO; | 210 | return -ENXIO; |
210 | } | 211 | } |
211 | switch (dev & 0x0f) { | 212 | switch (dev & 0x0f) { |
212 | case SND_DEV_CTL: | 213 | case SND_DEV_CTL: |
213 | dev >>= 4; | 214 | dev >>= 4; |
214 | if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { | 215 | if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { |
215 | request_module("mixer%d", dev); | 216 | request_module("mixer%d", dev); |
216 | } | 217 | } |
217 | if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL)) | 218 | if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL)) |
218 | return -ENXIO; | 219 | return -ENXIO; |
219 | 220 | ||
220 | if (!try_module_get(mixer_devs[dev]->owner)) | 221 | if (!try_module_get(mixer_devs[dev]->owner)) |
221 | return -ENXIO; | 222 | return -ENXIO; |
222 | break; | 223 | break; |
223 | 224 | ||
224 | case SND_DEV_SEQ: | 225 | case SND_DEV_SEQ: |
225 | case SND_DEV_SEQ2: | 226 | case SND_DEV_SEQ2: |
226 | if ((retval = sequencer_open(dev, file)) < 0) | 227 | if ((retval = sequencer_open(dev, file)) < 0) |
227 | return retval; | 228 | return retval; |
228 | break; | 229 | break; |
229 | 230 | ||
230 | case SND_DEV_MIDIN: | 231 | case SND_DEV_MIDIN: |
231 | if ((retval = MIDIbuf_open(dev, file)) < 0) | 232 | if ((retval = MIDIbuf_open(dev, file)) < 0) |
232 | return retval; | 233 | return retval; |
233 | break; | 234 | break; |
234 | 235 | ||
235 | case SND_DEV_DSP: | 236 | case SND_DEV_DSP: |
236 | case SND_DEV_DSP16: | 237 | case SND_DEV_DSP16: |
237 | case SND_DEV_AUDIO: | 238 | case SND_DEV_AUDIO: |
238 | if ((retval = audio_open(dev, file)) < 0) | 239 | if ((retval = audio_open(dev, file)) < 0) |
239 | return retval; | 240 | return retval; |
240 | break; | 241 | break; |
241 | 242 | ||
242 | default: | 243 | default: |
243 | printk(KERN_ERR "Invalid minor device %d\n", dev); | 244 | printk(KERN_ERR "Invalid minor device %d\n", dev); |
244 | return -ENXIO; | 245 | return -ENXIO; |
245 | } | 246 | } |
246 | 247 | ||
247 | return 0; | 248 | return 0; |
248 | } | 249 | } |
249 | 250 | ||
250 | static int sound_release(struct inode *inode, struct file *file) | 251 | static int sound_release(struct inode *inode, struct file *file) |
251 | { | 252 | { |
252 | int dev = iminor(inode); | 253 | int dev = iminor(inode); |
253 | 254 | ||
254 | lock_kernel(); | 255 | lock_kernel(); |
255 | DEB(printk("sound_release(dev=%d)\n", dev)); | 256 | DEB(printk("sound_release(dev=%d)\n", dev)); |
256 | switch (dev & 0x0f) { | 257 | switch (dev & 0x0f) { |
257 | case SND_DEV_CTL: | 258 | case SND_DEV_CTL: |
258 | module_put(mixer_devs[dev >> 4]->owner); | 259 | module_put(mixer_devs[dev >> 4]->owner); |
259 | break; | 260 | break; |
260 | 261 | ||
261 | case SND_DEV_SEQ: | 262 | case SND_DEV_SEQ: |
262 | case SND_DEV_SEQ2: | 263 | case SND_DEV_SEQ2: |
263 | sequencer_release(dev, file); | 264 | sequencer_release(dev, file); |
264 | break; | 265 | break; |
265 | 266 | ||
266 | case SND_DEV_MIDIN: | 267 | case SND_DEV_MIDIN: |
267 | MIDIbuf_release(dev, file); | 268 | MIDIbuf_release(dev, file); |
268 | break; | 269 | break; |
269 | 270 | ||
270 | case SND_DEV_DSP: | 271 | case SND_DEV_DSP: |
271 | case SND_DEV_DSP16: | 272 | case SND_DEV_DSP16: |
272 | case SND_DEV_AUDIO: | 273 | case SND_DEV_AUDIO: |
273 | audio_release(dev, file); | 274 | audio_release(dev, file); |
274 | break; | 275 | break; |
275 | 276 | ||
276 | default: | 277 | default: |
277 | printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev); | 278 | printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev); |
278 | } | 279 | } |
279 | unlock_kernel(); | 280 | unlock_kernel(); |
280 | 281 | ||
281 | return 0; | 282 | return 0; |
282 | } | 283 | } |
283 | 284 | ||
284 | static int get_mixer_info(int dev, void __user *arg) | 285 | static int get_mixer_info(int dev, void __user *arg) |
285 | { | 286 | { |
286 | mixer_info info; | 287 | mixer_info info; |
287 | memset(&info, 0, sizeof(info)); | 288 | memset(&info, 0, sizeof(info)); |
288 | strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id)); | 289 | strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id)); |
289 | strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name)); | 290 | strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name)); |
290 | info.modify_counter = mixer_devs[dev]->modify_counter; | 291 | info.modify_counter = mixer_devs[dev]->modify_counter; |
291 | if (__copy_to_user(arg, &info, sizeof(info))) | 292 | if (__copy_to_user(arg, &info, sizeof(info))) |
292 | return -EFAULT; | 293 | return -EFAULT; |
293 | return 0; | 294 | return 0; |
294 | } | 295 | } |
295 | 296 | ||
296 | static int get_old_mixer_info(int dev, void __user *arg) | 297 | static int get_old_mixer_info(int dev, void __user *arg) |
297 | { | 298 | { |
298 | _old_mixer_info info; | 299 | _old_mixer_info info; |
299 | memset(&info, 0, sizeof(info)); | 300 | memset(&info, 0, sizeof(info)); |
300 | strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id)); | 301 | strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id)); |
301 | strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name)); | 302 | strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name)); |
302 | if (copy_to_user(arg, &info, sizeof(info))) | 303 | if (copy_to_user(arg, &info, sizeof(info))) |
303 | return -EFAULT; | 304 | return -EFAULT; |
304 | return 0; | 305 | return 0; |
305 | } | 306 | } |
306 | 307 | ||
307 | static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg) | 308 | static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg) |
308 | { | 309 | { |
309 | if (mixdev < 0 || mixdev >= MAX_MIXER_DEV) | 310 | if (mixdev < 0 || mixdev >= MAX_MIXER_DEV) |
310 | return -ENXIO; | 311 | return -ENXIO; |
311 | /* Try to load the mixer... */ | 312 | /* Try to load the mixer... */ |
312 | if (mixer_devs[mixdev] == NULL) { | 313 | if (mixer_devs[mixdev] == NULL) { |
313 | request_module("mixer%d", mixdev); | 314 | request_module("mixer%d", mixdev); |
314 | } | 315 | } |
315 | if (mixdev >= num_mixers || !mixer_devs[mixdev]) | 316 | if (mixdev >= num_mixers || !mixer_devs[mixdev]) |
316 | return -ENXIO; | 317 | return -ENXIO; |
317 | if (cmd == SOUND_MIXER_INFO) | 318 | if (cmd == SOUND_MIXER_INFO) |
318 | return get_mixer_info(mixdev, arg); | 319 | return get_mixer_info(mixdev, arg); |
319 | if (cmd == SOUND_OLD_MIXER_INFO) | 320 | if (cmd == SOUND_OLD_MIXER_INFO) |
320 | return get_old_mixer_info(mixdev, arg); | 321 | return get_old_mixer_info(mixdev, arg); |
321 | if (_SIOC_DIR(cmd) & _SIOC_WRITE) | 322 | if (_SIOC_DIR(cmd) & _SIOC_WRITE) |
322 | mixer_devs[mixdev]->modify_counter++; | 323 | mixer_devs[mixdev]->modify_counter++; |
323 | if (!mixer_devs[mixdev]->ioctl) | 324 | if (!mixer_devs[mixdev]->ioctl) |
324 | return -EINVAL; | 325 | return -EINVAL; |
325 | return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg); | 326 | return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg); |
326 | } | 327 | } |
327 | 328 | ||
328 | static int sound_ioctl(struct inode *inode, struct file *file, | 329 | static int sound_ioctl(struct inode *inode, struct file *file, |
329 | unsigned int cmd, unsigned long arg) | 330 | unsigned int cmd, unsigned long arg) |
330 | { | 331 | { |
331 | int len = 0, dtype; | 332 | int len = 0, dtype; |
332 | int dev = iminor(inode); | 333 | int dev = iminor(inode); |
333 | void __user *p = (void __user *)arg; | 334 | void __user *p = (void __user *)arg; |
334 | 335 | ||
335 | if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) { | 336 | if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) { |
336 | /* | 337 | /* |
337 | * Have to validate the address given by the process. | 338 | * Have to validate the address given by the process. |
338 | */ | 339 | */ |
339 | len = _SIOC_SIZE(cmd); | 340 | len = _SIOC_SIZE(cmd); |
340 | if (len < 1 || len > 65536 || !p) | 341 | if (len < 1 || len > 65536 || !p) |
341 | return -EFAULT; | 342 | return -EFAULT; |
342 | if (_SIOC_DIR(cmd) & _SIOC_WRITE) | 343 | if (_SIOC_DIR(cmd) & _SIOC_WRITE) |
343 | if (!access_ok(VERIFY_READ, p, len)) | 344 | if (!access_ok(VERIFY_READ, p, len)) |
344 | return -EFAULT; | 345 | return -EFAULT; |
345 | if (_SIOC_DIR(cmd) & _SIOC_READ) | 346 | if (_SIOC_DIR(cmd) & _SIOC_READ) |
346 | if (!access_ok(VERIFY_WRITE, p, len)) | 347 | if (!access_ok(VERIFY_WRITE, p, len)) |
347 | return -EFAULT; | 348 | return -EFAULT; |
348 | } | 349 | } |
349 | DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); | 350 | DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); |
350 | if (cmd == OSS_GETVERSION) | 351 | if (cmd == OSS_GETVERSION) |
351 | return __put_user(SOUND_VERSION, (int __user *)p); | 352 | return __put_user(SOUND_VERSION, (int __user *)p); |
352 | 353 | ||
353 | if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ | 354 | if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ |
354 | (dev & 0x0f) != SND_DEV_CTL) { | 355 | (dev & 0x0f) != SND_DEV_CTL) { |
355 | dtype = dev & 0x0f; | 356 | dtype = dev & 0x0f; |
356 | switch (dtype) { | 357 | switch (dtype) { |
357 | case SND_DEV_DSP: | 358 | case SND_DEV_DSP: |
358 | case SND_DEV_DSP16: | 359 | case SND_DEV_DSP16: |
359 | case SND_DEV_AUDIO: | 360 | case SND_DEV_AUDIO: |
360 | return sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev, | 361 | return sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev, |
361 | cmd, p); | 362 | cmd, p); |
362 | 363 | ||
363 | default: | 364 | default: |
364 | return sound_mixer_ioctl(dev >> 4, cmd, p); | 365 | return sound_mixer_ioctl(dev >> 4, cmd, p); |
365 | } | 366 | } |
366 | } | 367 | } |
367 | switch (dev & 0x0f) { | 368 | switch (dev & 0x0f) { |
368 | case SND_DEV_CTL: | 369 | case SND_DEV_CTL: |
369 | if (cmd == SOUND_MIXER_GETLEVELS) | 370 | if (cmd == SOUND_MIXER_GETLEVELS) |
370 | return get_mixer_levels(p); | 371 | return get_mixer_levels(p); |
371 | if (cmd == SOUND_MIXER_SETLEVELS) | 372 | if (cmd == SOUND_MIXER_SETLEVELS) |
372 | return set_mixer_levels(p); | 373 | return set_mixer_levels(p); |
373 | return sound_mixer_ioctl(dev >> 4, cmd, p); | 374 | return sound_mixer_ioctl(dev >> 4, cmd, p); |
374 | 375 | ||
375 | case SND_DEV_SEQ: | 376 | case SND_DEV_SEQ: |
376 | case SND_DEV_SEQ2: | 377 | case SND_DEV_SEQ2: |
377 | return sequencer_ioctl(dev, file, cmd, p); | 378 | return sequencer_ioctl(dev, file, cmd, p); |
378 | 379 | ||
379 | case SND_DEV_DSP: | 380 | case SND_DEV_DSP: |
380 | case SND_DEV_DSP16: | 381 | case SND_DEV_DSP16: |
381 | case SND_DEV_AUDIO: | 382 | case SND_DEV_AUDIO: |
382 | return audio_ioctl(dev, file, cmd, p); | 383 | return audio_ioctl(dev, file, cmd, p); |
383 | break; | 384 | break; |
384 | 385 | ||
385 | case SND_DEV_MIDIN: | 386 | case SND_DEV_MIDIN: |
386 | return MIDIbuf_ioctl(dev, file, cmd, p); | 387 | return MIDIbuf_ioctl(dev, file, cmd, p); |
387 | break; | 388 | break; |
388 | 389 | ||
389 | } | 390 | } |
390 | return -EINVAL; | 391 | return -EINVAL; |
391 | } | 392 | } |
392 | 393 | ||
393 | static unsigned int sound_poll(struct file *file, poll_table * wait) | 394 | static unsigned int sound_poll(struct file *file, poll_table * wait) |
394 | { | 395 | { |
395 | struct inode *inode = file->f_dentry->d_inode; | 396 | struct inode *inode = file->f_dentry->d_inode; |
396 | int dev = iminor(inode); | 397 | int dev = iminor(inode); |
397 | 398 | ||
398 | DEB(printk("sound_poll(dev=%d)\n", dev)); | 399 | DEB(printk("sound_poll(dev=%d)\n", dev)); |
399 | switch (dev & 0x0f) { | 400 | switch (dev & 0x0f) { |
400 | case SND_DEV_SEQ: | 401 | case SND_DEV_SEQ: |
401 | case SND_DEV_SEQ2: | 402 | case SND_DEV_SEQ2: |
402 | return sequencer_poll(dev, file, wait); | 403 | return sequencer_poll(dev, file, wait); |
403 | 404 | ||
404 | case SND_DEV_MIDIN: | 405 | case SND_DEV_MIDIN: |
405 | return MIDIbuf_poll(dev, file, wait); | 406 | return MIDIbuf_poll(dev, file, wait); |
406 | 407 | ||
407 | case SND_DEV_DSP: | 408 | case SND_DEV_DSP: |
408 | case SND_DEV_DSP16: | 409 | case SND_DEV_DSP16: |
409 | case SND_DEV_AUDIO: | 410 | case SND_DEV_AUDIO: |
410 | return DMAbuf_poll(file, dev >> 4, wait); | 411 | return DMAbuf_poll(file, dev >> 4, wait); |
411 | } | 412 | } |
412 | return 0; | 413 | return 0; |
413 | } | 414 | } |
414 | 415 | ||
415 | static int sound_mmap(struct file *file, struct vm_area_struct *vma) | 416 | static int sound_mmap(struct file *file, struct vm_area_struct *vma) |
416 | { | 417 | { |
417 | int dev_class; | 418 | int dev_class; |
418 | unsigned long size; | 419 | unsigned long size; |
419 | struct dma_buffparms *dmap = NULL; | 420 | struct dma_buffparms *dmap = NULL; |
420 | int dev = iminor(file->f_dentry->d_inode); | 421 | int dev = iminor(file->f_dentry->d_inode); |
421 | 422 | ||
422 | dev_class = dev & 0x0f; | 423 | dev_class = dev & 0x0f; |
423 | dev >>= 4; | 424 | dev >>= 4; |
424 | 425 | ||
425 | if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) { | 426 | if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) { |
426 | printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); | 427 | printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); |
427 | return -EINVAL; | 428 | return -EINVAL; |
428 | } | 429 | } |
429 | lock_kernel(); | 430 | lock_kernel(); |
430 | if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ | 431 | if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ |
431 | dmap = audio_devs[dev]->dmap_out; | 432 | dmap = audio_devs[dev]->dmap_out; |
432 | else if (vma->vm_flags & VM_READ) | 433 | else if (vma->vm_flags & VM_READ) |
433 | dmap = audio_devs[dev]->dmap_in; | 434 | dmap = audio_devs[dev]->dmap_in; |
434 | else { | 435 | else { |
435 | printk(KERN_ERR "Sound: Undefined mmap() access\n"); | 436 | printk(KERN_ERR "Sound: Undefined mmap() access\n"); |
436 | unlock_kernel(); | 437 | unlock_kernel(); |
437 | return -EINVAL; | 438 | return -EINVAL; |
438 | } | 439 | } |
439 | 440 | ||
440 | if (dmap == NULL) { | 441 | if (dmap == NULL) { |
441 | printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); | 442 | printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); |
442 | unlock_kernel(); | 443 | unlock_kernel(); |
443 | return -EIO; | 444 | return -EIO; |
444 | } | 445 | } |
445 | if (dmap->raw_buf == NULL) { | 446 | if (dmap->raw_buf == NULL) { |
446 | printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); | 447 | printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); |
447 | unlock_kernel(); | 448 | unlock_kernel(); |
448 | return -EIO; | 449 | return -EIO; |
449 | } | 450 | } |
450 | if (dmap->mapping_flags) { | 451 | if (dmap->mapping_flags) { |
451 | printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); | 452 | printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); |
452 | unlock_kernel(); | 453 | unlock_kernel(); |
453 | return -EIO; | 454 | return -EIO; |
454 | } | 455 | } |
455 | if (vma->vm_pgoff != 0) { | 456 | if (vma->vm_pgoff != 0) { |
456 | printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); | 457 | printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); |
457 | unlock_kernel(); | 458 | unlock_kernel(); |
458 | return -EINVAL; | 459 | return -EINVAL; |
459 | } | 460 | } |
460 | size = vma->vm_end - vma->vm_start; | 461 | size = vma->vm_end - vma->vm_start; |
461 | 462 | ||
462 | if (size != dmap->bytes_in_use) { | 463 | if (size != dmap->bytes_in_use) { |
463 | printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use); | 464 | printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use); |
464 | } | 465 | } |
465 | if (remap_pfn_range(vma, vma->vm_start, | 466 | if (remap_pfn_range(vma, vma->vm_start, |
466 | virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT, | 467 | virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT, |
467 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) { | 468 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) { |
468 | unlock_kernel(); | 469 | unlock_kernel(); |
469 | return -EAGAIN; | 470 | return -EAGAIN; |
470 | } | 471 | } |
471 | 472 | ||
472 | dmap->mapping_flags |= DMA_MAP_MAPPED; | 473 | dmap->mapping_flags |= DMA_MAP_MAPPED; |
473 | 474 | ||
474 | if( audio_devs[dev]->d->mmap) | 475 | if( audio_devs[dev]->d->mmap) |
475 | audio_devs[dev]->d->mmap(dev); | 476 | audio_devs[dev]->d->mmap(dev); |
476 | 477 | ||
477 | memset(dmap->raw_buf, | 478 | memset(dmap->raw_buf, |
478 | dmap->neutral_byte, | 479 | dmap->neutral_byte, |
479 | dmap->bytes_in_use); | 480 | dmap->bytes_in_use); |
480 | unlock_kernel(); | 481 | unlock_kernel(); |
481 | return 0; | 482 | return 0; |
482 | } | 483 | } |
483 | 484 | ||
484 | struct file_operations oss_sound_fops = { | 485 | struct file_operations oss_sound_fops = { |
485 | .owner = THIS_MODULE, | 486 | .owner = THIS_MODULE, |
486 | .llseek = no_llseek, | 487 | .llseek = no_llseek, |
487 | .read = sound_read, | 488 | .read = sound_read, |
488 | .write = sound_write, | 489 | .write = sound_write, |
489 | .poll = sound_poll, | 490 | .poll = sound_poll, |
490 | .ioctl = sound_ioctl, | 491 | .ioctl = sound_ioctl, |
491 | .mmap = sound_mmap, | 492 | .mmap = sound_mmap, |
492 | .open = sound_open, | 493 | .open = sound_open, |
493 | .release = sound_release, | 494 | .release = sound_release, |
494 | }; | 495 | }; |
495 | 496 | ||
496 | /* | 497 | /* |
497 | * Create the required special subdevices | 498 | * Create the required special subdevices |
498 | */ | 499 | */ |
499 | 500 | ||
500 | static int create_special_devices(void) | 501 | static int create_special_devices(void) |
501 | { | 502 | { |
502 | int seq1,seq2; | 503 | int seq1,seq2; |
503 | seq1=register_sound_special(&oss_sound_fops, 1); | 504 | seq1=register_sound_special(&oss_sound_fops, 1); |
504 | if(seq1==-1) | 505 | if(seq1==-1) |
505 | goto bad; | 506 | goto bad; |
506 | seq2=register_sound_special(&oss_sound_fops, 8); | 507 | seq2=register_sound_special(&oss_sound_fops, 8); |
507 | if(seq2!=-1) | 508 | if(seq2!=-1) |
508 | return 0; | 509 | return 0; |
509 | unregister_sound_special(1); | 510 | unregister_sound_special(1); |
510 | bad: | 511 | bad: |
511 | return -1; | 512 | return -1; |
512 | } | 513 | } |
513 | 514 | ||
514 | 515 | ||
515 | /* These device names follow the official Linux device list, | 516 | /* These device names follow the official Linux device list, |
516 | * Documentation/devices.txt. Let us know if there are other | 517 | * Documentation/devices.txt. Let us know if there are other |
517 | * common names we should support for compatibility. | 518 | * common names we should support for compatibility. |
518 | * Only those devices not created by the generic code in sound_core.c are | 519 | * Only those devices not created by the generic code in sound_core.c are |
519 | * registered here. | 520 | * registered here. |
520 | */ | 521 | */ |
521 | static const struct { | 522 | static const struct { |
522 | unsigned short minor; | 523 | unsigned short minor; |
523 | char *name; | 524 | char *name; |
524 | umode_t mode; | 525 | umode_t mode; |
525 | int *num; | 526 | int *num; |
526 | } dev_list[] = { /* list of minor devices */ | 527 | } dev_list[] = { /* list of minor devices */ |
527 | /* seems to be some confusion here -- this device is not in the device list */ | 528 | /* seems to be some confusion here -- this device is not in the device list */ |
528 | {SND_DEV_DSP16, "dspW", S_IWUGO | S_IRUSR | S_IRGRP, | 529 | {SND_DEV_DSP16, "dspW", S_IWUGO | S_IRUSR | S_IRGRP, |
529 | &num_audiodevs}, | 530 | &num_audiodevs}, |
530 | {SND_DEV_AUDIO, "audio", S_IWUGO | S_IRUSR | S_IRGRP, | 531 | {SND_DEV_AUDIO, "audio", S_IWUGO | S_IRUSR | S_IRGRP, |
531 | &num_audiodevs}, | 532 | &num_audiodevs}, |
532 | }; | 533 | }; |
533 | 534 | ||
534 | static int dmabuf; | 535 | static int dmabuf; |
535 | static int dmabug; | 536 | static int dmabug; |
536 | 537 | ||
537 | module_param(dmabuf, int, 0444); | 538 | module_param(dmabuf, int, 0444); |
538 | module_param(dmabug, int, 0444); | 539 | module_param(dmabug, int, 0444); |
539 | 540 | ||
540 | static int __init oss_init(void) | 541 | static int __init oss_init(void) |
541 | { | 542 | { |
542 | int err; | 543 | int err; |
543 | int i, j; | 544 | int i, j; |
544 | 545 | ||
545 | #ifdef CONFIG_PCI | 546 | #ifdef CONFIG_PCI |
546 | if(dmabug) | 547 | if(dmabug) |
547 | isa_dma_bridge_buggy = dmabug; | 548 | isa_dma_bridge_buggy = dmabug; |
548 | #endif | 549 | #endif |
549 | 550 | ||
550 | err = create_special_devices(); | 551 | err = create_special_devices(); |
551 | if (err) { | 552 | if (err) { |
552 | printk(KERN_ERR "sound: driver already loaded/included in kernel\n"); | 553 | printk(KERN_ERR "sound: driver already loaded/included in kernel\n"); |
553 | return err; | 554 | return err; |
554 | } | 555 | } |
555 | 556 | ||
556 | /* Protecting the innocent */ | 557 | /* Protecting the innocent */ |
557 | sound_dmap_flag = (dmabuf > 0 ? 1 : 0); | 558 | sound_dmap_flag = (dmabuf > 0 ? 1 : 0); |
558 | 559 | ||
559 | for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { | 560 | for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { |
560 | device_create(sound_class, NULL, | 561 | device_create(sound_class, NULL, |
561 | MKDEV(SOUND_MAJOR, dev_list[i].minor), | 562 | MKDEV(SOUND_MAJOR, dev_list[i].minor), |
562 | "%s", dev_list[i].name); | 563 | "%s", dev_list[i].name); |
563 | 564 | ||
564 | if (!dev_list[i].num) | 565 | if (!dev_list[i].num) |
565 | continue; | 566 | continue; |
566 | 567 | ||
567 | for (j = 1; j < *dev_list[i].num; j++) | 568 | for (j = 1; j < *dev_list[i].num; j++) |
568 | device_create(sound_class, NULL, | 569 | device_create(sound_class, NULL, |
569 | MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), | 570 | MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), |
570 | "%s%d", dev_list[i].name, j); | 571 | "%s%d", dev_list[i].name, j); |
571 | } | 572 | } |
572 | 573 | ||
573 | if (sound_nblocks >= 1024) | 574 | if (sound_nblocks >= 1024) |
574 | printk(KERN_ERR "Sound warning: Deallocation table was too small.\n"); | 575 | printk(KERN_ERR "Sound warning: Deallocation table was too small.\n"); |
575 | 576 | ||
576 | return 0; | 577 | return 0; |
577 | } | 578 | } |
578 | 579 | ||
579 | static void __exit oss_cleanup(void) | 580 | static void __exit oss_cleanup(void) |
580 | { | 581 | { |
581 | int i, j; | 582 | int i, j; |
582 | 583 | ||
583 | for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { | 584 | for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { |
584 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); | 585 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); |
585 | if (!dev_list[i].num) | 586 | if (!dev_list[i].num) |
586 | continue; | 587 | continue; |
587 | for (j = 1; j < *dev_list[i].num; j++) | 588 | for (j = 1; j < *dev_list[i].num; j++) |
588 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); | 589 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); |
589 | } | 590 | } |
590 | 591 | ||
591 | unregister_sound_special(1); | 592 | unregister_sound_special(1); |
592 | unregister_sound_special(8); | 593 | unregister_sound_special(8); |
593 | 594 | ||
594 | sound_stop_timer(); | 595 | sound_stop_timer(); |
595 | 596 | ||
596 | sequencer_unload(); | 597 | sequencer_unload(); |
597 | 598 | ||
598 | for (i = 0; i < MAX_DMA_CHANNELS; i++) | 599 | for (i = 0; i < MAX_DMA_CHANNELS; i++) |
599 | if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) { | 600 | if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) { |
600 | printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i); | 601 | printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i); |
601 | sound_free_dma(i); | 602 | sound_free_dma(i); |
602 | } | 603 | } |
603 | 604 | ||
604 | for (i = 0; i < sound_nblocks; i++) | 605 | for (i = 0; i < sound_nblocks; i++) |
605 | vfree(sound_mem_blocks[i]); | 606 | vfree(sound_mem_blocks[i]); |
606 | 607 | ||
607 | } | 608 | } |
608 | 609 | ||
609 | module_init(oss_init); | 610 | module_init(oss_init); |
610 | module_exit(oss_cleanup); | 611 | module_exit(oss_cleanup); |
611 | MODULE_LICENSE("GPL"); | 612 | MODULE_LICENSE("GPL"); |
612 | MODULE_DESCRIPTION("OSS Sound subsystem"); | 613 | MODULE_DESCRIPTION("OSS Sound subsystem"); |
613 | MODULE_AUTHOR("Hannu Savolainen, et al."); | 614 | MODULE_AUTHOR("Hannu Savolainen, et al."); |
614 | 615 | ||
615 | 616 | ||
616 | int sound_alloc_dma(int chn, char *deviceID) | 617 | int sound_alloc_dma(int chn, char *deviceID) |
617 | { | 618 | { |
618 | int err; | 619 | int err; |
619 | 620 | ||
620 | if ((err = request_dma(chn, deviceID)) != 0) | 621 | if ((err = request_dma(chn, deviceID)) != 0) |
621 | return err; | 622 | return err; |
622 | 623 | ||
623 | dma_alloc_map[chn] = DMA_MAP_FREE; | 624 | dma_alloc_map[chn] = DMA_MAP_FREE; |
624 | 625 | ||
625 | return 0; | 626 | return 0; |
626 | } | 627 | } |
627 | EXPORT_SYMBOL(sound_alloc_dma); | 628 | EXPORT_SYMBOL(sound_alloc_dma); |
628 | 629 | ||
629 | int sound_open_dma(int chn, char *deviceID) | 630 | int sound_open_dma(int chn, char *deviceID) |
630 | { | 631 | { |
631 | if (!valid_dma(chn)) { | 632 | if (!valid_dma(chn)) { |
632 | printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn); | 633 | printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn); |
633 | return 1; | 634 | return 1; |
634 | } | 635 | } |
635 | 636 | ||
636 | if (dma_alloc_map[chn] != DMA_MAP_FREE) { | 637 | if (dma_alloc_map[chn] != DMA_MAP_FREE) { |
637 | printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]); | 638 | printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]); |
638 | return 1; | 639 | return 1; |
639 | } | 640 | } |
640 | dma_alloc_map[chn] = DMA_MAP_BUSY; | 641 | dma_alloc_map[chn] = DMA_MAP_BUSY; |
641 | return 0; | 642 | return 0; |
642 | } | 643 | } |
643 | EXPORT_SYMBOL(sound_open_dma); | 644 | EXPORT_SYMBOL(sound_open_dma); |
644 | 645 | ||
645 | void sound_free_dma(int chn) | 646 | void sound_free_dma(int chn) |
646 | { | 647 | { |
647 | if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) { | 648 | if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) { |
648 | /* printk( "sound_free_dma: Bad access to DMA channel %d\n", chn); */ | 649 | /* printk( "sound_free_dma: Bad access to DMA channel %d\n", chn); */ |
649 | return; | 650 | return; |
650 | } | 651 | } |
651 | free_dma(chn); | 652 | free_dma(chn); |
652 | dma_alloc_map[chn] = DMA_MAP_UNAVAIL; | 653 | dma_alloc_map[chn] = DMA_MAP_UNAVAIL; |
653 | } | 654 | } |
654 | EXPORT_SYMBOL(sound_free_dma); | 655 | EXPORT_SYMBOL(sound_free_dma); |
655 | 656 | ||
656 | void sound_close_dma(int chn) | 657 | void sound_close_dma(int chn) |
657 | { | 658 | { |
658 | if (dma_alloc_map[chn] != DMA_MAP_BUSY) { | 659 | if (dma_alloc_map[chn] != DMA_MAP_BUSY) { |
659 | printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn); | 660 | printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn); |
660 | return; | 661 | return; |
661 | } | 662 | } |
662 | dma_alloc_map[chn] = DMA_MAP_FREE; | 663 | dma_alloc_map[chn] = DMA_MAP_FREE; |
663 | } | 664 | } |
664 | EXPORT_SYMBOL(sound_close_dma); | 665 | EXPORT_SYMBOL(sound_close_dma); |
665 | 666 | ||
666 | static void do_sequencer_timer(unsigned long dummy) | 667 | static void do_sequencer_timer(unsigned long dummy) |
667 | { | 668 | { |
668 | sequencer_timer(0); | 669 | sequencer_timer(0); |
669 | } | 670 | } |
670 | 671 | ||
671 | 672 | ||
672 | static DEFINE_TIMER(seq_timer, do_sequencer_timer, 0, 0); | 673 | static DEFINE_TIMER(seq_timer, do_sequencer_timer, 0, 0); |
673 | 674 | ||
674 | void request_sound_timer(int count) | 675 | void request_sound_timer(int count) |
675 | { | 676 | { |
676 | extern unsigned long seq_time; | 677 | extern unsigned long seq_time; |
677 | 678 | ||
678 | if (count < 0) { | 679 | if (count < 0) { |
679 | seq_timer.expires = (-count) + jiffies; | 680 | seq_timer.expires = (-count) + jiffies; |
680 | add_timer(&seq_timer); | 681 | add_timer(&seq_timer); |
681 | return; | 682 | return; |
682 | } | 683 | } |
683 | count += seq_time; | 684 | count += seq_time; |
684 | 685 | ||
685 | count -= jiffies; | 686 | count -= jiffies; |
686 | 687 | ||
687 | if (count < 1) | 688 | if (count < 1) |
688 | count = 1; | 689 | count = 1; |
689 | 690 | ||
690 | seq_timer.expires = (count) + jiffies; | 691 | seq_timer.expires = (count) + jiffies; |
691 | add_timer(&seq_timer); | 692 | add_timer(&seq_timer); |
692 | } | 693 | } |
693 | 694 | ||
694 | void sound_stop_timer(void) | 695 | void sound_stop_timer(void) |
695 | { | 696 | { |
696 | del_timer(&seq_timer); | 697 | del_timer(&seq_timer); |
697 | } | 698 | } |
698 | 699 | ||
699 | void conf_printf(char *name, struct address_info *hw_config) | 700 | void conf_printf(char *name, struct address_info *hw_config) |
700 | { | 701 | { |
701 | #ifndef CONFIG_SOUND_TRACEINIT | 702 | #ifndef CONFIG_SOUND_TRACEINIT |
702 | return; | 703 | return; |
703 | #else | 704 | #else |
704 | printk("<%s> at 0x%03x", name, hw_config->io_base); | 705 | printk("<%s> at 0x%03x", name, hw_config->io_base); |
705 | 706 | ||
706 | if (hw_config->irq) | 707 | if (hw_config->irq) |
707 | printk(" irq %d", (hw_config->irq > 0) ? hw_config->irq : -hw_config->irq); | 708 | printk(" irq %d", (hw_config->irq > 0) ? hw_config->irq : -hw_config->irq); |
708 | 709 | ||
709 | if (hw_config->dma != -1 || hw_config->dma2 != -1) | 710 | if (hw_config->dma != -1 || hw_config->dma2 != -1) |
710 | { | 711 | { |
711 | printk(" dma %d", hw_config->dma); | 712 | printk(" dma %d", hw_config->dma); |
712 | if (hw_config->dma2 != -1) | 713 | if (hw_config->dma2 != -1) |
713 | printk(",%d", hw_config->dma2); | 714 | printk(",%d", hw_config->dma2); |
714 | } | 715 | } |
715 | printk("\n"); | 716 | printk("\n"); |
716 | #endif | 717 | #endif |
717 | } | 718 | } |
718 | EXPORT_SYMBOL(conf_printf); | 719 | EXPORT_SYMBOL(conf_printf); |
719 | 720 | ||
720 | void conf_printf2(char *name, int base, int irq, int dma, int dma2) | 721 | void conf_printf2(char *name, int base, int irq, int dma, int dma2) |
721 | { | 722 | { |
722 | #ifndef CONFIG_SOUND_TRACEINIT | 723 | #ifndef CONFIG_SOUND_TRACEINIT |
723 | return; | 724 | return; |
724 | #else | 725 | #else |
725 | printk("<%s> at 0x%03x", name, base); | 726 | printk("<%s> at 0x%03x", name, base); |
726 | 727 | ||
727 | if (irq) | 728 | if (irq) |
728 | printk(" irq %d", (irq > 0) ? irq : -irq); | 729 | printk(" irq %d", (irq > 0) ? irq : -irq); |
729 | 730 | ||
730 | if (dma != -1 || dma2 != -1) | 731 | if (dma != -1 || dma2 != -1) |
731 | { | 732 | { |
732 | printk(" dma %d", dma); | 733 | printk(" dma %d", dma); |
733 | if (dma2 != -1) | 734 | if (dma2 != -1) |
734 | printk(",%d", dma2); | 735 | printk(",%d", dma2); |
735 | } | 736 | } |
736 | printk("\n"); | 737 | printk("\n"); |
737 | #endif | 738 | #endif |
738 | } | 739 | } |
739 | EXPORT_SYMBOL(conf_printf2); | 740 | EXPORT_SYMBOL(conf_printf2); |
740 | 741 | ||
741 | 742 |
sound/oss/sscape.c
1 | /* | 1 | /* |
2 | * sound/oss/sscape.c | 2 | * sound/oss/sscape.c |
3 | * | 3 | * |
4 | * Low level driver for Ensoniq SoundScape | 4 | * Low level driver for Ensoniq SoundScape |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * Copyright (C) by Hannu Savolainen 1993-1997 | 7 | * Copyright (C) by Hannu Savolainen 1993-1997 |
8 | * | 8 | * |
9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) | 9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) |
10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software | 10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software |
11 | * for more info. | 11 | * for more info. |
12 | * | 12 | * |
13 | * | 13 | * |
14 | * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) | 14 | * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) |
15 | * Sergey Smitienko : ensoniq p'n'p support | 15 | * Sergey Smitienko : ensoniq p'n'p support |
16 | * Christoph Hellwig : adapted to module_init/module_exit | 16 | * Christoph Hellwig : adapted to module_init/module_exit |
17 | * Bartlomiej Zolnierkiewicz : added __init to attach_sscape() | 17 | * Bartlomiej Zolnierkiewicz : added __init to attach_sscape() |
18 | * Chris Rankin : Specify that this module owns the coprocessor | 18 | * Chris Rankin : Specify that this module owns the coprocessor |
19 | * Arnaldo C. de Melo : added missing restore_flags in sscape_pnp_upload_file | 19 | * Arnaldo C. de Melo : added missing restore_flags in sscape_pnp_upload_file |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | 24 | ||
25 | #include "sound_config.h" | 25 | #include "sound_config.h" |
26 | #include "sound_firmware.h" | 26 | #include "sound_firmware.h" |
27 | 27 | ||
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/signal.h> | 30 | #include <linux/signal.h> |
31 | #include <linux/fcntl.h> | 31 | #include <linux/fcntl.h> |
32 | #include <linux/ctype.h> | 32 | #include <linux/ctype.h> |
33 | #include <linux/stddef.h> | 33 | #include <linux/stddef.h> |
34 | #include <linux/kmod.h> | 34 | #include <linux/kmod.h> |
35 | #include <asm/dma.h> | 35 | #include <asm/dma.h> |
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | #include <linux/wait.h> | 37 | #include <linux/wait.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
41 | #include <linux/proc_fs.h> | 41 | #include <linux/proc_fs.h> |
42 | #include <linux/mm.h> | ||
42 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
43 | 44 | ||
44 | #include "coproc.h" | 45 | #include "coproc.h" |
45 | 46 | ||
46 | #include "ad1848.h" | 47 | #include "ad1848.h" |
47 | #include "mpu401.h" | 48 | #include "mpu401.h" |
48 | 49 | ||
49 | /* | 50 | /* |
50 | * I/O ports | 51 | * I/O ports |
51 | */ | 52 | */ |
52 | #define MIDI_DATA 0 | 53 | #define MIDI_DATA 0 |
53 | #define MIDI_CTRL 1 | 54 | #define MIDI_CTRL 1 |
54 | #define HOST_CTRL 2 | 55 | #define HOST_CTRL 2 |
55 | #define TX_READY 0x02 | 56 | #define TX_READY 0x02 |
56 | #define RX_READY 0x01 | 57 | #define RX_READY 0x01 |
57 | #define HOST_DATA 3 | 58 | #define HOST_DATA 3 |
58 | #define ODIE_ADDR 4 | 59 | #define ODIE_ADDR 4 |
59 | #define ODIE_DATA 5 | 60 | #define ODIE_DATA 5 |
60 | 61 | ||
61 | /* | 62 | /* |
62 | * Indirect registers | 63 | * Indirect registers |
63 | */ | 64 | */ |
64 | 65 | ||
65 | #define GA_INTSTAT_REG 0 | 66 | #define GA_INTSTAT_REG 0 |
66 | #define GA_INTENA_REG 1 | 67 | #define GA_INTENA_REG 1 |
67 | #define GA_DMAA_REG 2 | 68 | #define GA_DMAA_REG 2 |
68 | #define GA_DMAB_REG 3 | 69 | #define GA_DMAB_REG 3 |
69 | #define GA_INTCFG_REG 4 | 70 | #define GA_INTCFG_REG 4 |
70 | #define GA_DMACFG_REG 5 | 71 | #define GA_DMACFG_REG 5 |
71 | #define GA_CDCFG_REG 6 | 72 | #define GA_CDCFG_REG 6 |
72 | #define GA_SMCFGA_REG 7 | 73 | #define GA_SMCFGA_REG 7 |
73 | #define GA_SMCFGB_REG 8 | 74 | #define GA_SMCFGB_REG 8 |
74 | #define GA_HMCTL_REG 9 | 75 | #define GA_HMCTL_REG 9 |
75 | 76 | ||
76 | /* | 77 | /* |
77 | * DMA channel identifiers (A and B) | 78 | * DMA channel identifiers (A and B) |
78 | */ | 79 | */ |
79 | 80 | ||
80 | #define SSCAPE_DMA_A 0 | 81 | #define SSCAPE_DMA_A 0 |
81 | #define SSCAPE_DMA_B 1 | 82 | #define SSCAPE_DMA_B 1 |
82 | 83 | ||
83 | #define PORT(name) (devc->base+name) | 84 | #define PORT(name) (devc->base+name) |
84 | 85 | ||
85 | /* | 86 | /* |
86 | * Host commands recognized by the OBP microcode | 87 | * Host commands recognized by the OBP microcode |
87 | */ | 88 | */ |
88 | 89 | ||
89 | #define CMD_GEN_HOST_ACK 0x80 | 90 | #define CMD_GEN_HOST_ACK 0x80 |
90 | #define CMD_GEN_MPU_ACK 0x81 | 91 | #define CMD_GEN_MPU_ACK 0x81 |
91 | #define CMD_GET_BOARD_TYPE 0x82 | 92 | #define CMD_GET_BOARD_TYPE 0x82 |
92 | #define CMD_SET_CONTROL 0x88 /* Old firmware only */ | 93 | #define CMD_SET_CONTROL 0x88 /* Old firmware only */ |
93 | #define CMD_GET_CONTROL 0x89 /* Old firmware only */ | 94 | #define CMD_GET_CONTROL 0x89 /* Old firmware only */ |
94 | #define CTL_MASTER_VOL 0 | 95 | #define CTL_MASTER_VOL 0 |
95 | #define CTL_MIC_MODE 2 | 96 | #define CTL_MIC_MODE 2 |
96 | #define CTL_SYNTH_VOL 4 | 97 | #define CTL_SYNTH_VOL 4 |
97 | #define CTL_WAVE_VOL 7 | 98 | #define CTL_WAVE_VOL 7 |
98 | #define CMD_SET_EXTMIDI 0x8a | 99 | #define CMD_SET_EXTMIDI 0x8a |
99 | #define CMD_GET_EXTMIDI 0x8b | 100 | #define CMD_GET_EXTMIDI 0x8b |
100 | #define CMD_SET_MT32 0x8c | 101 | #define CMD_SET_MT32 0x8c |
101 | #define CMD_GET_MT32 0x8d | 102 | #define CMD_GET_MT32 0x8d |
102 | 103 | ||
103 | #define CMD_ACK 0x80 | 104 | #define CMD_ACK 0x80 |
104 | 105 | ||
105 | #define IC_ODIE 1 | 106 | #define IC_ODIE 1 |
106 | #define IC_OPUS 2 | 107 | #define IC_OPUS 2 |
107 | 108 | ||
108 | typedef struct sscape_info | 109 | typedef struct sscape_info |
109 | { | 110 | { |
110 | int base, irq, dma; | 111 | int base, irq, dma; |
111 | 112 | ||
112 | int codec, codec_irq; /* required to setup pnp cards*/ | 113 | int codec, codec_irq; /* required to setup pnp cards*/ |
113 | int codec_type; | 114 | int codec_type; |
114 | int ic_type; | 115 | int ic_type; |
115 | char* raw_buf; | 116 | char* raw_buf; |
116 | unsigned long raw_buf_phys; | 117 | unsigned long raw_buf_phys; |
117 | int buffsize; /* -------------------------- */ | 118 | int buffsize; /* -------------------------- */ |
118 | spinlock_t lock; | 119 | spinlock_t lock; |
119 | int ok; /* Properly detected */ | 120 | int ok; /* Properly detected */ |
120 | int failed; | 121 | int failed; |
121 | int dma_allocated; | 122 | int dma_allocated; |
122 | int codec_audiodev; | 123 | int codec_audiodev; |
123 | int opened; | 124 | int opened; |
124 | int *osp; | 125 | int *osp; |
125 | int my_audiodev; | 126 | int my_audiodev; |
126 | } sscape_info; | 127 | } sscape_info; |
127 | 128 | ||
128 | static struct sscape_info adev_info = { | 129 | static struct sscape_info adev_info = { |
129 | 0 | 130 | 0 |
130 | }; | 131 | }; |
131 | 132 | ||
132 | static struct sscape_info *devc = &adev_info; | 133 | static struct sscape_info *devc = &adev_info; |
133 | static int sscape_mididev = -1; | 134 | static int sscape_mididev = -1; |
134 | 135 | ||
135 | /* Some older cards have assigned interrupt bits differently than new ones */ | 136 | /* Some older cards have assigned interrupt bits differently than new ones */ |
136 | static char valid_interrupts_old[] = { | 137 | static char valid_interrupts_old[] = { |
137 | 9, 7, 5, 15 | 138 | 9, 7, 5, 15 |
138 | }; | 139 | }; |
139 | 140 | ||
140 | static char valid_interrupts_new[] = { | 141 | static char valid_interrupts_new[] = { |
141 | 9, 5, 7, 10 | 142 | 9, 5, 7, 10 |
142 | }; | 143 | }; |
143 | 144 | ||
144 | static char *valid_interrupts = valid_interrupts_new; | 145 | static char *valid_interrupts = valid_interrupts_new; |
145 | 146 | ||
146 | /* | 147 | /* |
147 | * See the bottom of the driver. This can be set by spea =0/1. | 148 | * See the bottom of the driver. This can be set by spea =0/1. |
148 | */ | 149 | */ |
149 | 150 | ||
150 | #ifdef REVEAL_SPEA | 151 | #ifdef REVEAL_SPEA |
151 | static char old_hardware = 1; | 152 | static char old_hardware = 1; |
152 | #else | 153 | #else |
153 | static char old_hardware; | 154 | static char old_hardware; |
154 | #endif | 155 | #endif |
155 | 156 | ||
156 | static void sleep(unsigned howlong) | 157 | static void sleep(unsigned howlong) |
157 | { | 158 | { |
158 | current->state = TASK_INTERRUPTIBLE; | 159 | current->state = TASK_INTERRUPTIBLE; |
159 | schedule_timeout(howlong); | 160 | schedule_timeout(howlong); |
160 | } | 161 | } |
161 | 162 | ||
162 | static unsigned char sscape_read(struct sscape_info *devc, int reg) | 163 | static unsigned char sscape_read(struct sscape_info *devc, int reg) |
163 | { | 164 | { |
164 | unsigned long flags; | 165 | unsigned long flags; |
165 | unsigned char val; | 166 | unsigned char val; |
166 | 167 | ||
167 | spin_lock_irqsave(&devc->lock,flags); | 168 | spin_lock_irqsave(&devc->lock,flags); |
168 | outb(reg, PORT(ODIE_ADDR)); | 169 | outb(reg, PORT(ODIE_ADDR)); |
169 | val = inb(PORT(ODIE_DATA)); | 170 | val = inb(PORT(ODIE_DATA)); |
170 | spin_unlock_irqrestore(&devc->lock,flags); | 171 | spin_unlock_irqrestore(&devc->lock,flags); |
171 | return val; | 172 | return val; |
172 | } | 173 | } |
173 | 174 | ||
174 | static void __sscape_write(int reg, int data) | 175 | static void __sscape_write(int reg, int data) |
175 | { | 176 | { |
176 | outb(reg, PORT(ODIE_ADDR)); | 177 | outb(reg, PORT(ODIE_ADDR)); |
177 | outb(data, PORT(ODIE_DATA)); | 178 | outb(data, PORT(ODIE_DATA)); |
178 | } | 179 | } |
179 | 180 | ||
180 | static void sscape_write(struct sscape_info *devc, int reg, int data) | 181 | static void sscape_write(struct sscape_info *devc, int reg, int data) |
181 | { | 182 | { |
182 | unsigned long flags; | 183 | unsigned long flags; |
183 | 184 | ||
184 | spin_lock_irqsave(&devc->lock,flags); | 185 | spin_lock_irqsave(&devc->lock,flags); |
185 | __sscape_write(reg, data); | 186 | __sscape_write(reg, data); |
186 | spin_unlock_irqrestore(&devc->lock,flags); | 187 | spin_unlock_irqrestore(&devc->lock,flags); |
187 | } | 188 | } |
188 | 189 | ||
189 | static unsigned char sscape_pnp_read_codec(sscape_info* devc, unsigned char reg) | 190 | static unsigned char sscape_pnp_read_codec(sscape_info* devc, unsigned char reg) |
190 | { | 191 | { |
191 | unsigned char res; | 192 | unsigned char res; |
192 | unsigned long flags; | 193 | unsigned long flags; |
193 | 194 | ||
194 | spin_lock_irqsave(&devc->lock,flags); | 195 | spin_lock_irqsave(&devc->lock,flags); |
195 | outb( reg, devc -> codec); | 196 | outb( reg, devc -> codec); |
196 | res = inb (devc -> codec + 1); | 197 | res = inb (devc -> codec + 1); |
197 | spin_unlock_irqrestore(&devc->lock,flags); | 198 | spin_unlock_irqrestore(&devc->lock,flags); |
198 | return res; | 199 | return res; |
199 | 200 | ||
200 | } | 201 | } |
201 | 202 | ||
202 | static void sscape_pnp_write_codec(sscape_info* devc, unsigned char reg, unsigned char data) | 203 | static void sscape_pnp_write_codec(sscape_info* devc, unsigned char reg, unsigned char data) |
203 | { | 204 | { |
204 | unsigned long flags; | 205 | unsigned long flags; |
205 | 206 | ||
206 | spin_lock_irqsave(&devc->lock,flags); | 207 | spin_lock_irqsave(&devc->lock,flags); |
207 | outb( reg, devc -> codec); | 208 | outb( reg, devc -> codec); |
208 | outb( data, devc -> codec + 1); | 209 | outb( data, devc -> codec + 1); |
209 | spin_unlock_irqrestore(&devc->lock,flags); | 210 | spin_unlock_irqrestore(&devc->lock,flags); |
210 | } | 211 | } |
211 | 212 | ||
212 | static void host_open(struct sscape_info *devc) | 213 | static void host_open(struct sscape_info *devc) |
213 | { | 214 | { |
214 | outb((0x00), PORT(HOST_CTRL)); /* Put the board to the host mode */ | 215 | outb((0x00), PORT(HOST_CTRL)); /* Put the board to the host mode */ |
215 | } | 216 | } |
216 | 217 | ||
217 | static void host_close(struct sscape_info *devc) | 218 | static void host_close(struct sscape_info *devc) |
218 | { | 219 | { |
219 | outb((0x03), PORT(HOST_CTRL)); /* Put the board to the MIDI mode */ | 220 | outb((0x03), PORT(HOST_CTRL)); /* Put the board to the MIDI mode */ |
220 | } | 221 | } |
221 | 222 | ||
222 | static int host_write(struct sscape_info *devc, unsigned char *data, int count) | 223 | static int host_write(struct sscape_info *devc, unsigned char *data, int count) |
223 | { | 224 | { |
224 | unsigned long flags; | 225 | unsigned long flags; |
225 | int i, timeout_val; | 226 | int i, timeout_val; |
226 | 227 | ||
227 | spin_lock_irqsave(&devc->lock,flags); | 228 | spin_lock_irqsave(&devc->lock,flags); |
228 | /* | 229 | /* |
229 | * Send the command and data bytes | 230 | * Send the command and data bytes |
230 | */ | 231 | */ |
231 | 232 | ||
232 | for (i = 0; i < count; i++) | 233 | for (i = 0; i < count; i++) |
233 | { | 234 | { |
234 | for (timeout_val = 10000; timeout_val > 0; timeout_val--) | 235 | for (timeout_val = 10000; timeout_val > 0; timeout_val--) |
235 | if (inb(PORT(HOST_CTRL)) & TX_READY) | 236 | if (inb(PORT(HOST_CTRL)) & TX_READY) |
236 | break; | 237 | break; |
237 | 238 | ||
238 | if (timeout_val <= 0) | 239 | if (timeout_val <= 0) |
239 | { | 240 | { |
240 | spin_unlock_irqrestore(&devc->lock,flags); | 241 | spin_unlock_irqrestore(&devc->lock,flags); |
241 | return 0; | 242 | return 0; |
242 | } | 243 | } |
243 | outb(data[i], PORT(HOST_DATA)); | 244 | outb(data[i], PORT(HOST_DATA)); |
244 | } | 245 | } |
245 | spin_unlock_irqrestore(&devc->lock,flags); | 246 | spin_unlock_irqrestore(&devc->lock,flags); |
246 | return 1; | 247 | return 1; |
247 | } | 248 | } |
248 | 249 | ||
249 | static int host_read(struct sscape_info *devc) | 250 | static int host_read(struct sscape_info *devc) |
250 | { | 251 | { |
251 | unsigned long flags; | 252 | unsigned long flags; |
252 | int timeout_val; | 253 | int timeout_val; |
253 | unsigned char data; | 254 | unsigned char data; |
254 | 255 | ||
255 | spin_lock_irqsave(&devc->lock,flags); | 256 | spin_lock_irqsave(&devc->lock,flags); |
256 | /* | 257 | /* |
257 | * Read a byte | 258 | * Read a byte |
258 | */ | 259 | */ |
259 | 260 | ||
260 | for (timeout_val = 10000; timeout_val > 0; timeout_val--) | 261 | for (timeout_val = 10000; timeout_val > 0; timeout_val--) |
261 | if (inb(PORT(HOST_CTRL)) & RX_READY) | 262 | if (inb(PORT(HOST_CTRL)) & RX_READY) |
262 | break; | 263 | break; |
263 | 264 | ||
264 | if (timeout_val <= 0) | 265 | if (timeout_val <= 0) |
265 | { | 266 | { |
266 | spin_unlock_irqrestore(&devc->lock,flags); | 267 | spin_unlock_irqrestore(&devc->lock,flags); |
267 | return -1; | 268 | return -1; |
268 | } | 269 | } |
269 | data = inb(PORT(HOST_DATA)); | 270 | data = inb(PORT(HOST_DATA)); |
270 | spin_unlock_irqrestore(&devc->lock,flags); | 271 | spin_unlock_irqrestore(&devc->lock,flags); |
271 | return data; | 272 | return data; |
272 | } | 273 | } |
273 | 274 | ||
274 | #if 0 /* unused */ | 275 | #if 0 /* unused */ |
275 | static int host_command1(struct sscape_info *devc, int cmd) | 276 | static int host_command1(struct sscape_info *devc, int cmd) |
276 | { | 277 | { |
277 | unsigned char buf[10]; | 278 | unsigned char buf[10]; |
278 | buf[0] = (unsigned char) (cmd & 0xff); | 279 | buf[0] = (unsigned char) (cmd & 0xff); |
279 | return host_write(devc, buf, 1); | 280 | return host_write(devc, buf, 1); |
280 | } | 281 | } |
281 | #endif /* unused */ | 282 | #endif /* unused */ |
282 | 283 | ||
283 | 284 | ||
284 | static int host_command2(struct sscape_info *devc, int cmd, int parm1) | 285 | static int host_command2(struct sscape_info *devc, int cmd, int parm1) |
285 | { | 286 | { |
286 | unsigned char buf[10]; | 287 | unsigned char buf[10]; |
287 | 288 | ||
288 | buf[0] = (unsigned char) (cmd & 0xff); | 289 | buf[0] = (unsigned char) (cmd & 0xff); |
289 | buf[1] = (unsigned char) (parm1 & 0xff); | 290 | buf[1] = (unsigned char) (parm1 & 0xff); |
290 | 291 | ||
291 | return host_write(devc, buf, 2); | 292 | return host_write(devc, buf, 2); |
292 | } | 293 | } |
293 | 294 | ||
294 | static int host_command3(struct sscape_info *devc, int cmd, int parm1, int parm2) | 295 | static int host_command3(struct sscape_info *devc, int cmd, int parm1, int parm2) |
295 | { | 296 | { |
296 | unsigned char buf[10]; | 297 | unsigned char buf[10]; |
297 | 298 | ||
298 | buf[0] = (unsigned char) (cmd & 0xff); | 299 | buf[0] = (unsigned char) (cmd & 0xff); |
299 | buf[1] = (unsigned char) (parm1 & 0xff); | 300 | buf[1] = (unsigned char) (parm1 & 0xff); |
300 | buf[2] = (unsigned char) (parm2 & 0xff); | 301 | buf[2] = (unsigned char) (parm2 & 0xff); |
301 | return host_write(devc, buf, 3); | 302 | return host_write(devc, buf, 3); |
302 | } | 303 | } |
303 | 304 | ||
304 | static void set_mt32(struct sscape_info *devc, int value) | 305 | static void set_mt32(struct sscape_info *devc, int value) |
305 | { | 306 | { |
306 | host_open(devc); | 307 | host_open(devc); |
307 | host_command2(devc, CMD_SET_MT32, value ? 1 : 0); | 308 | host_command2(devc, CMD_SET_MT32, value ? 1 : 0); |
308 | if (host_read(devc) != CMD_ACK) | 309 | if (host_read(devc) != CMD_ACK) |
309 | { | 310 | { |
310 | /* printk( "SNDSCAPE: Setting MT32 mode failed\n"); */ | 311 | /* printk( "SNDSCAPE: Setting MT32 mode failed\n"); */ |
311 | } | 312 | } |
312 | host_close(devc); | 313 | host_close(devc); |
313 | } | 314 | } |
314 | 315 | ||
315 | static void set_control(struct sscape_info *devc, int ctrl, int value) | 316 | static void set_control(struct sscape_info *devc, int ctrl, int value) |
316 | { | 317 | { |
317 | host_open(devc); | 318 | host_open(devc); |
318 | host_command3(devc, CMD_SET_CONTROL, ctrl, value); | 319 | host_command3(devc, CMD_SET_CONTROL, ctrl, value); |
319 | if (host_read(devc) != CMD_ACK) | 320 | if (host_read(devc) != CMD_ACK) |
320 | { | 321 | { |
321 | /* printk( "SNDSCAPE: Setting control (%d) failed\n", ctrl); */ | 322 | /* printk( "SNDSCAPE: Setting control (%d) failed\n", ctrl); */ |
322 | } | 323 | } |
323 | host_close(devc); | 324 | host_close(devc); |
324 | } | 325 | } |
325 | 326 | ||
326 | static void do_dma(struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode) | 327 | static void do_dma(struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode) |
327 | { | 328 | { |
328 | unsigned char temp; | 329 | unsigned char temp; |
329 | 330 | ||
330 | if (dma_chan != SSCAPE_DMA_A) | 331 | if (dma_chan != SSCAPE_DMA_A) |
331 | { | 332 | { |
332 | printk(KERN_WARNING "soundscape: Tried to use DMA channel != A. Why?\n"); | 333 | printk(KERN_WARNING "soundscape: Tried to use DMA channel != A. Why?\n"); |
333 | return; | 334 | return; |
334 | } | 335 | } |
335 | audio_devs[devc->codec_audiodev]->flags &= ~DMA_AUTOMODE; | 336 | audio_devs[devc->codec_audiodev]->flags &= ~DMA_AUTOMODE; |
336 | DMAbuf_start_dma(devc->codec_audiodev, buf, blk_size, mode); | 337 | DMAbuf_start_dma(devc->codec_audiodev, buf, blk_size, mode); |
337 | audio_devs[devc->codec_audiodev]->flags |= DMA_AUTOMODE; | 338 | audio_devs[devc->codec_audiodev]->flags |= DMA_AUTOMODE; |
338 | 339 | ||
339 | temp = devc->dma << 4; /* Setup DMA channel select bits */ | 340 | temp = devc->dma << 4; /* Setup DMA channel select bits */ |
340 | if (devc->dma <= 3) | 341 | if (devc->dma <= 3) |
341 | temp |= 0x80; /* 8 bit DMA channel */ | 342 | temp |= 0x80; /* 8 bit DMA channel */ |
342 | 343 | ||
343 | temp |= 1; /* Trigger DMA */ | 344 | temp |= 1; /* Trigger DMA */ |
344 | sscape_write(devc, GA_DMAA_REG, temp); | 345 | sscape_write(devc, GA_DMAA_REG, temp); |
345 | temp &= 0xfe; /* Clear DMA trigger */ | 346 | temp &= 0xfe; /* Clear DMA trigger */ |
346 | sscape_write(devc, GA_DMAA_REG, temp); | 347 | sscape_write(devc, GA_DMAA_REG, temp); |
347 | } | 348 | } |
348 | 349 | ||
349 | static int verify_mpu(struct sscape_info *devc) | 350 | static int verify_mpu(struct sscape_info *devc) |
350 | { | 351 | { |
351 | /* | 352 | /* |
352 | * The SoundScape board could be in three modes (MPU, 8250 and host). | 353 | * The SoundScape board could be in three modes (MPU, 8250 and host). |
353 | * If the card is not in the MPU mode, enabling the MPU driver will | 354 | * If the card is not in the MPU mode, enabling the MPU driver will |
354 | * cause infinite loop (the driver believes that there is always some | 355 | * cause infinite loop (the driver believes that there is always some |
355 | * received data in the buffer. | 356 | * received data in the buffer. |
356 | * | 357 | * |
357 | * Detect this by looking if there are more than 10 received MIDI bytes | 358 | * Detect this by looking if there are more than 10 received MIDI bytes |
358 | * (0x00) in the buffer. | 359 | * (0x00) in the buffer. |
359 | */ | 360 | */ |
360 | 361 | ||
361 | int i; | 362 | int i; |
362 | 363 | ||
363 | for (i = 0; i < 10; i++) | 364 | for (i = 0; i < 10; i++) |
364 | { | 365 | { |
365 | if (inb(devc->base + HOST_CTRL) & 0x80) | 366 | if (inb(devc->base + HOST_CTRL) & 0x80) |
366 | return 1; | 367 | return 1; |
367 | 368 | ||
368 | if (inb(devc->base) != 0x00) | 369 | if (inb(devc->base) != 0x00) |
369 | return 1; | 370 | return 1; |
370 | } | 371 | } |
371 | printk(KERN_WARNING "SoundScape: The device is not in the MPU-401 mode\n"); | 372 | printk(KERN_WARNING "SoundScape: The device is not in the MPU-401 mode\n"); |
372 | return 0; | 373 | return 0; |
373 | } | 374 | } |
374 | 375 | ||
375 | static int sscape_coproc_open(void *dev_info, int sub_device) | 376 | static int sscape_coproc_open(void *dev_info, int sub_device) |
376 | { | 377 | { |
377 | if (sub_device == COPR_MIDI) | 378 | if (sub_device == COPR_MIDI) |
378 | { | 379 | { |
379 | set_mt32(devc, 0); | 380 | set_mt32(devc, 0); |
380 | if (!verify_mpu(devc)) | 381 | if (!verify_mpu(devc)) |
381 | return -EIO; | 382 | return -EIO; |
382 | } | 383 | } |
383 | return 0; | 384 | return 0; |
384 | } | 385 | } |
385 | 386 | ||
386 | static void sscape_coproc_close(void *dev_info, int sub_device) | 387 | static void sscape_coproc_close(void *dev_info, int sub_device) |
387 | { | 388 | { |
388 | struct sscape_info *devc = dev_info; | 389 | struct sscape_info *devc = dev_info; |
389 | unsigned long flags; | 390 | unsigned long flags; |
390 | 391 | ||
391 | spin_lock_irqsave(&devc->lock,flags); | 392 | spin_lock_irqsave(&devc->lock,flags); |
392 | if (devc->dma_allocated) | 393 | if (devc->dma_allocated) |
393 | { | 394 | { |
394 | __sscape_write(GA_DMAA_REG, 0x20); /* DMA channel disabled */ | 395 | __sscape_write(GA_DMAA_REG, 0x20); /* DMA channel disabled */ |
395 | devc->dma_allocated = 0; | 396 | devc->dma_allocated = 0; |
396 | } | 397 | } |
397 | spin_unlock_irqrestore(&devc->lock,flags); | 398 | spin_unlock_irqrestore(&devc->lock,flags); |
398 | return; | 399 | return; |
399 | } | 400 | } |
400 | 401 | ||
401 | static void sscape_coproc_reset(void *dev_info) | 402 | static void sscape_coproc_reset(void *dev_info) |
402 | { | 403 | { |
403 | } | 404 | } |
404 | 405 | ||
405 | static int sscape_download_boot(struct sscape_info *devc, unsigned char *block, int size, int flag) | 406 | static int sscape_download_boot(struct sscape_info *devc, unsigned char *block, int size, int flag) |
406 | { | 407 | { |
407 | unsigned long flags; | 408 | unsigned long flags; |
408 | unsigned char temp; | 409 | unsigned char temp; |
409 | volatile int done, timeout_val; | 410 | volatile int done, timeout_val; |
410 | static unsigned char codec_dma_bits; | 411 | static unsigned char codec_dma_bits; |
411 | 412 | ||
412 | if (flag & CPF_FIRST) | 413 | if (flag & CPF_FIRST) |
413 | { | 414 | { |
414 | /* | 415 | /* |
415 | * First block. Have to allocate DMA and to reset the board | 416 | * First block. Have to allocate DMA and to reset the board |
416 | * before continuing. | 417 | * before continuing. |
417 | */ | 418 | */ |
418 | 419 | ||
419 | spin_lock_irqsave(&devc->lock,flags); | 420 | spin_lock_irqsave(&devc->lock,flags); |
420 | codec_dma_bits = sscape_read(devc, GA_CDCFG_REG); | 421 | codec_dma_bits = sscape_read(devc, GA_CDCFG_REG); |
421 | 422 | ||
422 | if (devc->dma_allocated == 0) | 423 | if (devc->dma_allocated == 0) |
423 | devc->dma_allocated = 1; | 424 | devc->dma_allocated = 1; |
424 | 425 | ||
425 | spin_unlock_irqrestore(&devc->lock,flags); | 426 | spin_unlock_irqrestore(&devc->lock,flags); |
426 | 427 | ||
427 | sscape_write(devc, GA_HMCTL_REG, | 428 | sscape_write(devc, GA_HMCTL_REG, |
428 | (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f); /*Reset */ | 429 | (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f); /*Reset */ |
429 | 430 | ||
430 | for (timeout_val = 10000; timeout_val > 0; timeout_val--) | 431 | for (timeout_val = 10000; timeout_val > 0; timeout_val--) |
431 | sscape_read(devc, GA_HMCTL_REG); /* Delay */ | 432 | sscape_read(devc, GA_HMCTL_REG); /* Delay */ |
432 | 433 | ||
433 | /* Take board out of reset */ | 434 | /* Take board out of reset */ |
434 | sscape_write(devc, GA_HMCTL_REG, | 435 | sscape_write(devc, GA_HMCTL_REG, |
435 | (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80); | 436 | (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80); |
436 | } | 437 | } |
437 | /* | 438 | /* |
438 | * Transfer one code block using DMA | 439 | * Transfer one code block using DMA |
439 | */ | 440 | */ |
440 | if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL) | 441 | if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL) |
441 | { | 442 | { |
442 | printk(KERN_WARNING "soundscape: DMA buffer not available\n"); | 443 | printk(KERN_WARNING "soundscape: DMA buffer not available\n"); |
443 | return 0; | 444 | return 0; |
444 | } | 445 | } |
445 | memcpy(audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size); | 446 | memcpy(audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size); |
446 | 447 | ||
447 | spin_lock_irqsave(&devc->lock,flags); | 448 | spin_lock_irqsave(&devc->lock,flags); |
448 | 449 | ||
449 | /******** INTERRUPTS DISABLED NOW ********/ | 450 | /******** INTERRUPTS DISABLED NOW ********/ |
450 | 451 | ||
451 | do_dma(devc, SSCAPE_DMA_A, | 452 | do_dma(devc, SSCAPE_DMA_A, |
452 | audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys, | 453 | audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys, |
453 | size, DMA_MODE_WRITE); | 454 | size, DMA_MODE_WRITE); |
454 | 455 | ||
455 | /* | 456 | /* |
456 | * Wait until transfer completes. | 457 | * Wait until transfer completes. |
457 | */ | 458 | */ |
458 | 459 | ||
459 | done = 0; | 460 | done = 0; |
460 | timeout_val = 30; | 461 | timeout_val = 30; |
461 | while (!done && timeout_val-- > 0) | 462 | while (!done && timeout_val-- > 0) |
462 | { | 463 | { |
463 | int resid; | 464 | int resid; |
464 | 465 | ||
465 | if (HZ / 50) | 466 | if (HZ / 50) |
466 | sleep(HZ / 50); | 467 | sleep(HZ / 50); |
467 | clear_dma_ff(devc->dma); | 468 | clear_dma_ff(devc->dma); |
468 | if ((resid = get_dma_residue(devc->dma)) == 0) | 469 | if ((resid = get_dma_residue(devc->dma)) == 0) |
469 | done = 1; | 470 | done = 1; |
470 | } | 471 | } |
471 | 472 | ||
472 | spin_unlock_irqrestore(&devc->lock,flags); | 473 | spin_unlock_irqrestore(&devc->lock,flags); |
473 | if (!done) | 474 | if (!done) |
474 | return 0; | 475 | return 0; |
475 | 476 | ||
476 | if (flag & CPF_LAST) | 477 | if (flag & CPF_LAST) |
477 | { | 478 | { |
478 | /* | 479 | /* |
479 | * Take the board out of reset | 480 | * Take the board out of reset |
480 | */ | 481 | */ |
481 | outb((0x00), PORT(HOST_CTRL)); | 482 | outb((0x00), PORT(HOST_CTRL)); |
482 | outb((0x00), PORT(MIDI_CTRL)); | 483 | outb((0x00), PORT(MIDI_CTRL)); |
483 | 484 | ||
484 | temp = sscape_read(devc, GA_HMCTL_REG); | 485 | temp = sscape_read(devc, GA_HMCTL_REG); |
485 | temp |= 0x40; | 486 | temp |= 0x40; |
486 | sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */ | 487 | sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */ |
487 | 488 | ||
488 | /* | 489 | /* |
489 | * Wait until the ODB wakes up | 490 | * Wait until the ODB wakes up |
490 | */ | 491 | */ |
491 | spin_lock_irqsave(&devc->lock,flags); | 492 | spin_lock_irqsave(&devc->lock,flags); |
492 | done = 0; | 493 | done = 0; |
493 | timeout_val = 5 * HZ; | 494 | timeout_val = 5 * HZ; |
494 | while (!done && timeout_val-- > 0) | 495 | while (!done && timeout_val-- > 0) |
495 | { | 496 | { |
496 | unsigned char x; | 497 | unsigned char x; |
497 | 498 | ||
498 | sleep(1); | 499 | sleep(1); |
499 | x = inb(PORT(HOST_DATA)); | 500 | x = inb(PORT(HOST_DATA)); |
500 | if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */ | 501 | if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */ |
501 | { | 502 | { |
502 | DDB(printk("Soundscape: Acknowledge = %x\n", x)); | 503 | DDB(printk("Soundscape: Acknowledge = %x\n", x)); |
503 | done = 1; | 504 | done = 1; |
504 | } | 505 | } |
505 | } | 506 | } |
506 | sscape_write(devc, GA_CDCFG_REG, codec_dma_bits); | 507 | sscape_write(devc, GA_CDCFG_REG, codec_dma_bits); |
507 | 508 | ||
508 | spin_unlock_irqrestore(&devc->lock,flags); | 509 | spin_unlock_irqrestore(&devc->lock,flags); |
509 | if (!done) | 510 | if (!done) |
510 | { | 511 | { |
511 | printk(KERN_ERR "soundscape: The OBP didn't respond after code download\n"); | 512 | printk(KERN_ERR "soundscape: The OBP didn't respond after code download\n"); |
512 | return 0; | 513 | return 0; |
513 | } | 514 | } |
514 | spin_lock_irqsave(&devc->lock,flags); | 515 | spin_lock_irqsave(&devc->lock,flags); |
515 | done = 0; | 516 | done = 0; |
516 | timeout_val = 5 * HZ; | 517 | timeout_val = 5 * HZ; |
517 | while (!done && timeout_val-- > 0) | 518 | while (!done && timeout_val-- > 0) |
518 | { | 519 | { |
519 | sleep(1); | 520 | sleep(1); |
520 | if (inb(PORT(HOST_DATA)) == 0xfe) /* Host startup acknowledge */ | 521 | if (inb(PORT(HOST_DATA)) == 0xfe) /* Host startup acknowledge */ |
521 | done = 1; | 522 | done = 1; |
522 | } | 523 | } |
523 | spin_unlock_irqrestore(&devc->lock,flags); | 524 | spin_unlock_irqrestore(&devc->lock,flags); |
524 | if (!done) | 525 | if (!done) |
525 | { | 526 | { |
526 | printk(KERN_ERR "soundscape: OBP Initialization failed.\n"); | 527 | printk(KERN_ERR "soundscape: OBP Initialization failed.\n"); |
527 | return 0; | 528 | return 0; |
528 | } | 529 | } |
529 | printk(KERN_INFO "SoundScape board initialized OK\n"); | 530 | printk(KERN_INFO "SoundScape board initialized OK\n"); |
530 | set_control(devc, CTL_MASTER_VOL, 100); | 531 | set_control(devc, CTL_MASTER_VOL, 100); |
531 | set_control(devc, CTL_SYNTH_VOL, 100); | 532 | set_control(devc, CTL_SYNTH_VOL, 100); |
532 | 533 | ||
533 | #ifdef SSCAPE_DEBUG3 | 534 | #ifdef SSCAPE_DEBUG3 |
534 | /* | 535 | /* |
535 | * Temporary debugging aid. Print contents of the registers after | 536 | * Temporary debugging aid. Print contents of the registers after |
536 | * downloading the code. | 537 | * downloading the code. |
537 | */ | 538 | */ |
538 | { | 539 | { |
539 | int i; | 540 | int i; |
540 | 541 | ||
541 | for (i = 0; i < 13; i++) | 542 | for (i = 0; i < 13; i++) |
542 | printk("I%d = %02x (new value)\n", i, sscape_read(devc, i)); | 543 | printk("I%d = %02x (new value)\n", i, sscape_read(devc, i)); |
543 | } | 544 | } |
544 | #endif | 545 | #endif |
545 | 546 | ||
546 | } | 547 | } |
547 | return 1; | 548 | return 1; |
548 | } | 549 | } |
549 | 550 | ||
550 | static int download_boot_block(void *dev_info, copr_buffer * buf) | 551 | static int download_boot_block(void *dev_info, copr_buffer * buf) |
551 | { | 552 | { |
552 | if (buf->len <= 0 || buf->len > sizeof(buf->data)) | 553 | if (buf->len <= 0 || buf->len > sizeof(buf->data)) |
553 | return -EINVAL; | 554 | return -EINVAL; |
554 | 555 | ||
555 | if (!sscape_download_boot(devc, buf->data, buf->len, buf->flags)) | 556 | if (!sscape_download_boot(devc, buf->data, buf->len, buf->flags)) |
556 | { | 557 | { |
557 | printk(KERN_ERR "soundscape: Unable to load microcode block to the OBP.\n"); | 558 | printk(KERN_ERR "soundscape: Unable to load microcode block to the OBP.\n"); |
558 | return -EIO; | 559 | return -EIO; |
559 | } | 560 | } |
560 | return 0; | 561 | return 0; |
561 | } | 562 | } |
562 | 563 | ||
563 | static int sscape_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local) | 564 | static int sscape_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local) |
564 | { | 565 | { |
565 | copr_buffer *buf; | 566 | copr_buffer *buf; |
566 | int err; | 567 | int err; |
567 | 568 | ||
568 | switch (cmd) | 569 | switch (cmd) |
569 | { | 570 | { |
570 | case SNDCTL_COPR_RESET: | 571 | case SNDCTL_COPR_RESET: |
571 | sscape_coproc_reset(dev_info); | 572 | sscape_coproc_reset(dev_info); |
572 | return 0; | 573 | return 0; |
573 | 574 | ||
574 | case SNDCTL_COPR_LOAD: | 575 | case SNDCTL_COPR_LOAD: |
575 | buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); | 576 | buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); |
576 | if (buf == NULL) | 577 | if (buf == NULL) |
577 | return -ENOSPC; | 578 | return -ENOSPC; |
578 | if (copy_from_user(buf, arg, sizeof(copr_buffer))) | 579 | if (copy_from_user(buf, arg, sizeof(copr_buffer))) |
579 | { | 580 | { |
580 | vfree(buf); | 581 | vfree(buf); |
581 | return -EFAULT; | 582 | return -EFAULT; |
582 | } | 583 | } |
583 | err = download_boot_block(dev_info, buf); | 584 | err = download_boot_block(dev_info, buf); |
584 | vfree(buf); | 585 | vfree(buf); |
585 | return err; | 586 | return err; |
586 | 587 | ||
587 | default: | 588 | default: |
588 | return -EINVAL; | 589 | return -EINVAL; |
589 | } | 590 | } |
590 | } | 591 | } |
591 | 592 | ||
592 | static coproc_operations sscape_coproc_operations = | 593 | static coproc_operations sscape_coproc_operations = |
593 | { | 594 | { |
594 | "SoundScape M68K", | 595 | "SoundScape M68K", |
595 | THIS_MODULE, | 596 | THIS_MODULE, |
596 | sscape_coproc_open, | 597 | sscape_coproc_open, |
597 | sscape_coproc_close, | 598 | sscape_coproc_close, |
598 | sscape_coproc_ioctl, | 599 | sscape_coproc_ioctl, |
599 | sscape_coproc_reset, | 600 | sscape_coproc_reset, |
600 | &adev_info | 601 | &adev_info |
601 | }; | 602 | }; |
602 | 603 | ||
603 | static struct resource *sscape_ports; | 604 | static struct resource *sscape_ports; |
604 | static int sscape_is_pnp; | 605 | static int sscape_is_pnp; |
605 | 606 | ||
606 | static void __init attach_sscape(struct address_info *hw_config) | 607 | static void __init attach_sscape(struct address_info *hw_config) |
607 | { | 608 | { |
608 | #ifndef SSCAPE_REGS | 609 | #ifndef SSCAPE_REGS |
609 | /* | 610 | /* |
610 | * Config register values for Spea/V7 Media FX and Ensoniq S-2000. | 611 | * Config register values for Spea/V7 Media FX and Ensoniq S-2000. |
611 | * These values are card | 612 | * These values are card |
612 | * dependent. If you have another SoundScape based card, you have to | 613 | * dependent. If you have another SoundScape based card, you have to |
613 | * find the correct values. Do the following: | 614 | * find the correct values. Do the following: |
614 | * - Compile this driver with SSCAPE_DEBUG1 defined. | 615 | * - Compile this driver with SSCAPE_DEBUG1 defined. |
615 | * - Shut down and power off your machine. | 616 | * - Shut down and power off your machine. |
616 | * - Boot with DOS so that the SSINIT.EXE program is run. | 617 | * - Boot with DOS so that the SSINIT.EXE program is run. |
617 | * - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed | 618 | * - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed |
618 | * when detecting the SoundScape. | 619 | * when detecting the SoundScape. |
619 | * - Modify the following list to use the values printed during boot. | 620 | * - Modify the following list to use the values printed during boot. |
620 | * Undefine the SSCAPE_DEBUG1 | 621 | * Undefine the SSCAPE_DEBUG1 |
621 | */ | 622 | */ |
622 | #define SSCAPE_REGS { \ | 623 | #define SSCAPE_REGS { \ |
623 | /* I0 */ 0x00, \ | 624 | /* I0 */ 0x00, \ |
624 | /* I1 */ 0xf0, /* Note! Ignored. Set always to 0xf0 */ \ | 625 | /* I1 */ 0xf0, /* Note! Ignored. Set always to 0xf0 */ \ |
625 | /* I2 */ 0x20, /* Note! Ignored. Set always to 0x20 */ \ | 626 | /* I2 */ 0x20, /* Note! Ignored. Set always to 0x20 */ \ |
626 | /* I3 */ 0x20, /* Note! Ignored. Set always to 0x20 */ \ | 627 | /* I3 */ 0x20, /* Note! Ignored. Set always to 0x20 */ \ |
627 | /* I4 */ 0xf5, /* Ignored */ \ | 628 | /* I4 */ 0xf5, /* Ignored */ \ |
628 | /* I5 */ 0x10, \ | 629 | /* I5 */ 0x10, \ |
629 | /* I6 */ 0x00, \ | 630 | /* I6 */ 0x00, \ |
630 | /* I7 */ 0x2e, /* I7 MEM config A. Likely to vary between models */ \ | 631 | /* I7 */ 0x2e, /* I7 MEM config A. Likely to vary between models */ \ |
631 | /* I8 */ 0x00, /* I8 MEM config B. Likely to vary between models */ \ | 632 | /* I8 */ 0x00, /* I8 MEM config B. Likely to vary between models */ \ |
632 | /* I9 */ 0x40 /* Ignored */ \ | 633 | /* I9 */ 0x40 /* Ignored */ \ |
633 | } | 634 | } |
634 | #endif | 635 | #endif |
635 | 636 | ||
636 | unsigned long flags; | 637 | unsigned long flags; |
637 | static unsigned char regs[10] = SSCAPE_REGS; | 638 | static unsigned char regs[10] = SSCAPE_REGS; |
638 | 639 | ||
639 | int i, irq_bits = 0xff; | 640 | int i, irq_bits = 0xff; |
640 | 641 | ||
641 | if (old_hardware) | 642 | if (old_hardware) |
642 | { | 643 | { |
643 | valid_interrupts = valid_interrupts_old; | 644 | valid_interrupts = valid_interrupts_old; |
644 | conf_printf("Ensoniq SoundScape (old)", hw_config); | 645 | conf_printf("Ensoniq SoundScape (old)", hw_config); |
645 | } | 646 | } |
646 | else | 647 | else |
647 | conf_printf("Ensoniq SoundScape", hw_config); | 648 | conf_printf("Ensoniq SoundScape", hw_config); |
648 | 649 | ||
649 | for (i = 0; i < 4; i++) | 650 | for (i = 0; i < 4; i++) |
650 | { | 651 | { |
651 | if (hw_config->irq == valid_interrupts[i]) | 652 | if (hw_config->irq == valid_interrupts[i]) |
652 | { | 653 | { |
653 | irq_bits = i; | 654 | irq_bits = i; |
654 | break; | 655 | break; |
655 | } | 656 | } |
656 | } | 657 | } |
657 | if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) | 658 | if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) |
658 | { | 659 | { |
659 | printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq); | 660 | printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq); |
660 | release_region(devc->base, 2); | 661 | release_region(devc->base, 2); |
661 | release_region(devc->base + 2, 6); | 662 | release_region(devc->base + 2, 6); |
662 | if (sscape_is_pnp) | 663 | if (sscape_is_pnp) |
663 | release_region(devc->codec, 2); | 664 | release_region(devc->codec, 2); |
664 | return; | 665 | return; |
665 | } | 666 | } |
666 | 667 | ||
667 | if (!sscape_is_pnp) { | 668 | if (!sscape_is_pnp) { |
668 | 669 | ||
669 | spin_lock_irqsave(&devc->lock,flags); | 670 | spin_lock_irqsave(&devc->lock,flags); |
670 | /* Host interrupt enable */ | 671 | /* Host interrupt enable */ |
671 | sscape_write(devc, 1, 0xf0); /* All interrupts enabled */ | 672 | sscape_write(devc, 1, 0xf0); /* All interrupts enabled */ |
672 | /* DMA A status/trigger register */ | 673 | /* DMA A status/trigger register */ |
673 | sscape_write(devc, 2, 0x20); /* DMA channel disabled */ | 674 | sscape_write(devc, 2, 0x20); /* DMA channel disabled */ |
674 | /* DMA B status/trigger register */ | 675 | /* DMA B status/trigger register */ |
675 | sscape_write(devc, 3, 0x20); /* DMA channel disabled */ | 676 | sscape_write(devc, 3, 0x20); /* DMA channel disabled */ |
676 | /* Host interrupt config reg */ | 677 | /* Host interrupt config reg */ |
677 | sscape_write(devc, 4, 0xf0 | (irq_bits << 2) | irq_bits); | 678 | sscape_write(devc, 4, 0xf0 | (irq_bits << 2) | irq_bits); |
678 | /* Don't destroy CD-ROM DMA config bits (0xc0) */ | 679 | /* Don't destroy CD-ROM DMA config bits (0xc0) */ |
679 | sscape_write(devc, 5, (regs[5] & 0x3f) | (sscape_read(devc, 5) & 0xc0)); | 680 | sscape_write(devc, 5, (regs[5] & 0x3f) | (sscape_read(devc, 5) & 0xc0)); |
680 | /* CD-ROM config (WSS codec actually) */ | 681 | /* CD-ROM config (WSS codec actually) */ |
681 | sscape_write(devc, 6, regs[6]); | 682 | sscape_write(devc, 6, regs[6]); |
682 | sscape_write(devc, 7, regs[7]); | 683 | sscape_write(devc, 7, regs[7]); |
683 | sscape_write(devc, 8, regs[8]); | 684 | sscape_write(devc, 8, regs[8]); |
684 | /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */ | 685 | /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */ |
685 | sscape_write(devc, 9, (sscape_read(devc, 9) & 0xf0) | 0x08); | 686 | sscape_write(devc, 9, (sscape_read(devc, 9) & 0xf0) | 0x08); |
686 | spin_unlock_irqrestore(&devc->lock,flags); | 687 | spin_unlock_irqrestore(&devc->lock,flags); |
687 | } | 688 | } |
688 | #ifdef SSCAPE_DEBUG2 | 689 | #ifdef SSCAPE_DEBUG2 |
689 | /* | 690 | /* |
690 | * Temporary debugging aid. Print contents of the registers after | 691 | * Temporary debugging aid. Print contents of the registers after |
691 | * changing them. | 692 | * changing them. |
692 | */ | 693 | */ |
693 | { | 694 | { |
694 | int i; | 695 | int i; |
695 | 696 | ||
696 | for (i = 0; i < 13; i++) | 697 | for (i = 0; i < 13; i++) |
697 | printk("I%d = %02x (new value)\n", i, sscape_read(devc, i)); | 698 | printk("I%d = %02x (new value)\n", i, sscape_read(devc, i)); |
698 | } | 699 | } |
699 | #endif | 700 | #endif |
700 | 701 | ||
701 | if (probe_mpu401(hw_config, sscape_ports)) | 702 | if (probe_mpu401(hw_config, sscape_ports)) |
702 | hw_config->always_detect = 1; | 703 | hw_config->always_detect = 1; |
703 | hw_config->name = "SoundScape"; | 704 | hw_config->name = "SoundScape"; |
704 | 705 | ||
705 | hw_config->irq *= -1; /* Negative value signals IRQ sharing */ | 706 | hw_config->irq *= -1; /* Negative value signals IRQ sharing */ |
706 | attach_mpu401(hw_config, THIS_MODULE); | 707 | attach_mpu401(hw_config, THIS_MODULE); |
707 | hw_config->irq *= -1; /* Restore it */ | 708 | hw_config->irq *= -1; /* Restore it */ |
708 | 709 | ||
709 | if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ | 710 | if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ |
710 | { | 711 | { |
711 | sscape_mididev = hw_config->slots[1]; | 712 | sscape_mididev = hw_config->slots[1]; |
712 | midi_devs[hw_config->slots[1]]->coproc = &sscape_coproc_operations; | 713 | midi_devs[hw_config->slots[1]]->coproc = &sscape_coproc_operations; |
713 | } | 714 | } |
714 | sscape_write(devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */ | 715 | sscape_write(devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */ |
715 | devc->ok = 1; | 716 | devc->ok = 1; |
716 | devc->failed = 0; | 717 | devc->failed = 0; |
717 | } | 718 | } |
718 | 719 | ||
719 | static int detect_ga(sscape_info * devc) | 720 | static int detect_ga(sscape_info * devc) |
720 | { | 721 | { |
721 | unsigned char save; | 722 | unsigned char save; |
722 | 723 | ||
723 | DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base)); | 724 | DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base)); |
724 | 725 | ||
725 | /* | 726 | /* |
726 | * First check that the address register of "ODIE" is | 727 | * First check that the address register of "ODIE" is |
727 | * there and that it has exactly 4 writable bits. | 728 | * there and that it has exactly 4 writable bits. |
728 | * First 4 bits | 729 | * First 4 bits |
729 | */ | 730 | */ |
730 | 731 | ||
731 | if ((save = inb(PORT(ODIE_ADDR))) & 0xf0) | 732 | if ((save = inb(PORT(ODIE_ADDR))) & 0xf0) |
732 | { | 733 | { |
733 | DDB(printk("soundscape: Detect error A\n")); | 734 | DDB(printk("soundscape: Detect error A\n")); |
734 | return 0; | 735 | return 0; |
735 | } | 736 | } |
736 | outb((0x00), PORT(ODIE_ADDR)); | 737 | outb((0x00), PORT(ODIE_ADDR)); |
737 | if (inb(PORT(ODIE_ADDR)) != 0x00) | 738 | if (inb(PORT(ODIE_ADDR)) != 0x00) |
738 | { | 739 | { |
739 | DDB(printk("soundscape: Detect error B\n")); | 740 | DDB(printk("soundscape: Detect error B\n")); |
740 | return 0; | 741 | return 0; |
741 | } | 742 | } |
742 | outb((0xff), PORT(ODIE_ADDR)); | 743 | outb((0xff), PORT(ODIE_ADDR)); |
743 | if (inb(PORT(ODIE_ADDR)) != 0x0f) | 744 | if (inb(PORT(ODIE_ADDR)) != 0x0f) |
744 | { | 745 | { |
745 | DDB(printk("soundscape: Detect error C\n")); | 746 | DDB(printk("soundscape: Detect error C\n")); |
746 | return 0; | 747 | return 0; |
747 | } | 748 | } |
748 | outb((save), PORT(ODIE_ADDR)); | 749 | outb((save), PORT(ODIE_ADDR)); |
749 | 750 | ||
750 | /* | 751 | /* |
751 | * Now verify that some indirect registers return zero on some bits. | 752 | * Now verify that some indirect registers return zero on some bits. |
752 | * This may break the driver with some future revisions of "ODIE" but... | 753 | * This may break the driver with some future revisions of "ODIE" but... |
753 | */ | 754 | */ |
754 | 755 | ||
755 | if (sscape_read(devc, 0) & 0x0c) | 756 | if (sscape_read(devc, 0) & 0x0c) |
756 | { | 757 | { |
757 | DDB(printk("soundscape: Detect error D (%x)\n", sscape_read(devc, 0))); | 758 | DDB(printk("soundscape: Detect error D (%x)\n", sscape_read(devc, 0))); |
758 | return 0; | 759 | return 0; |
759 | } | 760 | } |
760 | if (sscape_read(devc, 1) & 0x0f) | 761 | if (sscape_read(devc, 1) & 0x0f) |
761 | { | 762 | { |
762 | DDB(printk("soundscape: Detect error E\n")); | 763 | DDB(printk("soundscape: Detect error E\n")); |
763 | return 0; | 764 | return 0; |
764 | } | 765 | } |
765 | if (sscape_read(devc, 5) & 0x0f) | 766 | if (sscape_read(devc, 5) & 0x0f) |
766 | { | 767 | { |
767 | DDB(printk("soundscape: Detect error F\n")); | 768 | DDB(printk("soundscape: Detect error F\n")); |
768 | return 0; | 769 | return 0; |
769 | } | 770 | } |
770 | return 1; | 771 | return 1; |
771 | } | 772 | } |
772 | 773 | ||
773 | static int sscape_read_host_ctrl(sscape_info* devc) | 774 | static int sscape_read_host_ctrl(sscape_info* devc) |
774 | { | 775 | { |
775 | return host_read(devc); | 776 | return host_read(devc); |
776 | } | 777 | } |
777 | 778 | ||
778 | static void sscape_write_host_ctrl2(sscape_info *devc, int a, int b) | 779 | static void sscape_write_host_ctrl2(sscape_info *devc, int a, int b) |
779 | { | 780 | { |
780 | host_command2(devc, a, b); | 781 | host_command2(devc, a, b); |
781 | } | 782 | } |
782 | 783 | ||
783 | static int sscape_alloc_dma(sscape_info *devc) | 784 | static int sscape_alloc_dma(sscape_info *devc) |
784 | { | 785 | { |
785 | char *start_addr, *end_addr; | 786 | char *start_addr, *end_addr; |
786 | int dma_pagesize; | 787 | int dma_pagesize; |
787 | int sz, size; | 788 | int sz, size; |
788 | struct page *page; | 789 | struct page *page; |
789 | 790 | ||
790 | if (devc->raw_buf != NULL) return 0; /* Already done */ | 791 | if (devc->raw_buf != NULL) return 0; /* Already done */ |
791 | dma_pagesize = (devc->dma < 4) ? (64 * 1024) : (128 * 1024); | 792 | dma_pagesize = (devc->dma < 4) ? (64 * 1024) : (128 * 1024); |
792 | devc->raw_buf = NULL; | 793 | devc->raw_buf = NULL; |
793 | devc->buffsize = 8192*4; | 794 | devc->buffsize = 8192*4; |
794 | if (devc->buffsize > dma_pagesize) devc->buffsize = dma_pagesize; | 795 | if (devc->buffsize > dma_pagesize) devc->buffsize = dma_pagesize; |
795 | start_addr = NULL; | 796 | start_addr = NULL; |
796 | /* | 797 | /* |
797 | * Now loop until we get a free buffer. Try to get smaller buffer if | 798 | * Now loop until we get a free buffer. Try to get smaller buffer if |
798 | * it fails. Don't accept smaller than 8k buffer for performance | 799 | * it fails. Don't accept smaller than 8k buffer for performance |
799 | * reasons. | 800 | * reasons. |
800 | */ | 801 | */ |
801 | while (start_addr == NULL && devc->buffsize > PAGE_SIZE) { | 802 | while (start_addr == NULL && devc->buffsize > PAGE_SIZE) { |
802 | for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1); | 803 | for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1); |
803 | devc->buffsize = PAGE_SIZE * (1 << sz); | 804 | devc->buffsize = PAGE_SIZE * (1 << sz); |
804 | start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA, sz); | 805 | start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA, sz); |
805 | if (start_addr == NULL) devc->buffsize /= 2; | 806 | if (start_addr == NULL) devc->buffsize /= 2; |
806 | } | 807 | } |
807 | 808 | ||
808 | if (start_addr == NULL) { | 809 | if (start_addr == NULL) { |
809 | printk(KERN_ERR "sscape pnp init error: Couldn't allocate DMA buffer\n"); | 810 | printk(KERN_ERR "sscape pnp init error: Couldn't allocate DMA buffer\n"); |
810 | return 0; | 811 | return 0; |
811 | } else { | 812 | } else { |
812 | /* make some checks */ | 813 | /* make some checks */ |
813 | end_addr = start_addr + devc->buffsize - 1; | 814 | end_addr = start_addr + devc->buffsize - 1; |
814 | /* now check if it fits into the same dma-pagesize */ | 815 | /* now check if it fits into the same dma-pagesize */ |
815 | 816 | ||
816 | if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1)) | 817 | if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1)) |
817 | || end_addr >= (char *) (MAX_DMA_ADDRESS)) { | 818 | || end_addr >= (char *) (MAX_DMA_ADDRESS)) { |
818 | printk(KERN_ERR "sscape pnp: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, devc->buffsize); | 819 | printk(KERN_ERR "sscape pnp: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, devc->buffsize); |
819 | return 0; | 820 | return 0; |
820 | } | 821 | } |
821 | } | 822 | } |
822 | devc->raw_buf = start_addr; | 823 | devc->raw_buf = start_addr; |
823 | devc->raw_buf_phys = virt_to_bus(start_addr); | 824 | devc->raw_buf_phys = virt_to_bus(start_addr); |
824 | 825 | ||
825 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) | 826 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) |
826 | SetPageReserved(page); | 827 | SetPageReserved(page); |
827 | return 1; | 828 | return 1; |
828 | } | 829 | } |
829 | 830 | ||
830 | static void sscape_free_dma(sscape_info *devc) | 831 | static void sscape_free_dma(sscape_info *devc) |
831 | { | 832 | { |
832 | int sz, size; | 833 | int sz, size; |
833 | unsigned long start_addr, end_addr; | 834 | unsigned long start_addr, end_addr; |
834 | struct page *page; | 835 | struct page *page; |
835 | 836 | ||
836 | if (devc->raw_buf == NULL) return; | 837 | if (devc->raw_buf == NULL) return; |
837 | for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1); | 838 | for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1); |
838 | start_addr = (unsigned long) devc->raw_buf; | 839 | start_addr = (unsigned long) devc->raw_buf; |
839 | end_addr = start_addr + devc->buffsize; | 840 | end_addr = start_addr + devc->buffsize; |
840 | 841 | ||
841 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) | 842 | for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) |
842 | ClearPageReserved(page); | 843 | ClearPageReserved(page); |
843 | 844 | ||
844 | free_pages((unsigned long) devc->raw_buf, sz); | 845 | free_pages((unsigned long) devc->raw_buf, sz); |
845 | devc->raw_buf = NULL; | 846 | devc->raw_buf = NULL; |
846 | } | 847 | } |
847 | 848 | ||
848 | /* Intel version !!!!!!!!! */ | 849 | /* Intel version !!!!!!!!! */ |
849 | 850 | ||
850 | static int sscape_start_dma(int chan, unsigned long physaddr, int count, int dma_mode) | 851 | static int sscape_start_dma(int chan, unsigned long physaddr, int count, int dma_mode) |
851 | { | 852 | { |
852 | unsigned long flags; | 853 | unsigned long flags; |
853 | 854 | ||
854 | flags = claim_dma_lock(); | 855 | flags = claim_dma_lock(); |
855 | disable_dma(chan); | 856 | disable_dma(chan); |
856 | clear_dma_ff(chan); | 857 | clear_dma_ff(chan); |
857 | set_dma_mode(chan, dma_mode); | 858 | set_dma_mode(chan, dma_mode); |
858 | set_dma_addr(chan, physaddr); | 859 | set_dma_addr(chan, physaddr); |
859 | set_dma_count(chan, count); | 860 | set_dma_count(chan, count); |
860 | enable_dma(chan); | 861 | enable_dma(chan); |
861 | release_dma_lock(flags); | 862 | release_dma_lock(flags); |
862 | return 0; | 863 | return 0; |
863 | } | 864 | } |
864 | 865 | ||
865 | static void sscape_pnp_start_dma(sscape_info* devc, int arg ) | 866 | static void sscape_pnp_start_dma(sscape_info* devc, int arg ) |
866 | { | 867 | { |
867 | int reg; | 868 | int reg; |
868 | if (arg == 0) reg = 2; | 869 | if (arg == 0) reg = 2; |
869 | else reg = 3; | 870 | else reg = 3; |
870 | 871 | ||
871 | sscape_write(devc, reg, sscape_read( devc, reg) | 0x01); | 872 | sscape_write(devc, reg, sscape_read( devc, reg) | 0x01); |
872 | sscape_write(devc, reg, sscape_read( devc, reg) & 0xFE); | 873 | sscape_write(devc, reg, sscape_read( devc, reg) & 0xFE); |
873 | } | 874 | } |
874 | 875 | ||
875 | static int sscape_pnp_wait_dma (sscape_info* devc, int arg ) | 876 | static int sscape_pnp_wait_dma (sscape_info* devc, int arg ) |
876 | { | 877 | { |
877 | int reg; | 878 | int reg; |
878 | unsigned long i; | 879 | unsigned long i; |
879 | unsigned char d; | 880 | unsigned char d; |
880 | 881 | ||
881 | if (arg == 0) reg = 2; | 882 | if (arg == 0) reg = 2; |
882 | else reg = 3; | 883 | else reg = 3; |
883 | 884 | ||
884 | sleep ( 1 ); | 885 | sleep ( 1 ); |
885 | i = 0; | 886 | i = 0; |
886 | do { | 887 | do { |
887 | d = sscape_read(devc, reg) & 1; | 888 | d = sscape_read(devc, reg) & 1; |
888 | if ( d == 1) break; | 889 | if ( d == 1) break; |
889 | i++; | 890 | i++; |
890 | } while (i < 500000); | 891 | } while (i < 500000); |
891 | d = sscape_read(devc, reg) & 1; | 892 | d = sscape_read(devc, reg) & 1; |
892 | return d; | 893 | return d; |
893 | } | 894 | } |
894 | 895 | ||
895 | static int sscape_pnp_alloc_dma(sscape_info* devc) | 896 | static int sscape_pnp_alloc_dma(sscape_info* devc) |
896 | { | 897 | { |
897 | /* printk(KERN_INFO "sscape: requesting dma\n"); */ | 898 | /* printk(KERN_INFO "sscape: requesting dma\n"); */ |
898 | if (request_dma(devc -> dma, "sscape")) return 0; | 899 | if (request_dma(devc -> dma, "sscape")) return 0; |
899 | /* printk(KERN_INFO "sscape: dma channel allocated\n"); */ | 900 | /* printk(KERN_INFO "sscape: dma channel allocated\n"); */ |
900 | if (!sscape_alloc_dma(devc)) { | 901 | if (!sscape_alloc_dma(devc)) { |
901 | free_dma(devc -> dma); | 902 | free_dma(devc -> dma); |
902 | return 0; | 903 | return 0; |
903 | }; | 904 | }; |
904 | return 1; | 905 | return 1; |
905 | } | 906 | } |
906 | 907 | ||
907 | static void sscape_pnp_free_dma(sscape_info* devc) | 908 | static void sscape_pnp_free_dma(sscape_info* devc) |
908 | { | 909 | { |
909 | sscape_free_dma( devc); | 910 | sscape_free_dma( devc); |
910 | free_dma(devc -> dma ); | 911 | free_dma(devc -> dma ); |
911 | /* printk(KERN_INFO "sscape: dma released\n"); */ | 912 | /* printk(KERN_INFO "sscape: dma released\n"); */ |
912 | } | 913 | } |
913 | 914 | ||
914 | static int sscape_pnp_upload_file(sscape_info* devc, char* fn) | 915 | static int sscape_pnp_upload_file(sscape_info* devc, char* fn) |
915 | { | 916 | { |
916 | int done = 0; | 917 | int done = 0; |
917 | int timeout_val; | 918 | int timeout_val; |
918 | char* data,*dt; | 919 | char* data,*dt; |
919 | int len,l; | 920 | int len,l; |
920 | unsigned long flags; | 921 | unsigned long flags; |
921 | 922 | ||
922 | sscape_write( devc, 9, sscape_read(devc, 9 ) & 0x3F ); | 923 | sscape_write( devc, 9, sscape_read(devc, 9 ) & 0x3F ); |
923 | sscape_write( devc, 2, (devc -> dma << 4) | 0x80 ); | 924 | sscape_write( devc, 2, (devc -> dma << 4) | 0x80 ); |
924 | sscape_write( devc, 3, 0x20 ); | 925 | sscape_write( devc, 3, 0x20 ); |
925 | sscape_write( devc, 9, sscape_read( devc, 9 ) | 0x80 ); | 926 | sscape_write( devc, 9, sscape_read( devc, 9 ) | 0x80 ); |
926 | 927 | ||
927 | len = mod_firmware_load(fn, &data); | 928 | len = mod_firmware_load(fn, &data); |
928 | if (len == 0) { | 929 | if (len == 0) { |
929 | printk(KERN_ERR "sscape: file not found: %s\n", fn); | 930 | printk(KERN_ERR "sscape: file not found: %s\n", fn); |
930 | return 0; | 931 | return 0; |
931 | } | 932 | } |
932 | dt = data; | 933 | dt = data; |
933 | spin_lock_irqsave(&devc->lock,flags); | 934 | spin_lock_irqsave(&devc->lock,flags); |
934 | while ( len > 0 ) { | 935 | while ( len > 0 ) { |
935 | if (len > devc -> buffsize) l = devc->buffsize; | 936 | if (len > devc -> buffsize) l = devc->buffsize; |
936 | else l = len; | 937 | else l = len; |
937 | len -= l; | 938 | len -= l; |
938 | memcpy(devc->raw_buf, dt, l); dt += l; | 939 | memcpy(devc->raw_buf, dt, l); dt += l; |
939 | sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48); | 940 | sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48); |
940 | sscape_pnp_start_dma ( devc, 0 ); | 941 | sscape_pnp_start_dma ( devc, 0 ); |
941 | if (sscape_pnp_wait_dma ( devc, 0 ) == 0) { | 942 | if (sscape_pnp_wait_dma ( devc, 0 ) == 0) { |
942 | spin_unlock_irqrestore(&devc->lock,flags); | 943 | spin_unlock_irqrestore(&devc->lock,flags); |
943 | return 0; | 944 | return 0; |
944 | } | 945 | } |
945 | } | 946 | } |
946 | 947 | ||
947 | spin_unlock_irqrestore(&devc->lock,flags); | 948 | spin_unlock_irqrestore(&devc->lock,flags); |
948 | vfree(data); | 949 | vfree(data); |
949 | 950 | ||
950 | outb(0, devc -> base + 2); | 951 | outb(0, devc -> base + 2); |
951 | outb(0, devc -> base); | 952 | outb(0, devc -> base); |
952 | 953 | ||
953 | sscape_write ( devc, 9, sscape_read( devc, 9 ) | 0x40); | 954 | sscape_write ( devc, 9, sscape_read( devc, 9 ) | 0x40); |
954 | 955 | ||
955 | timeout_val = 5 * HZ; | 956 | timeout_val = 5 * HZ; |
956 | while (!done && timeout_val-- > 0) | 957 | while (!done && timeout_val-- > 0) |
957 | { | 958 | { |
958 | unsigned char x; | 959 | unsigned char x; |
959 | sleep(1); | 960 | sleep(1); |
960 | x = inb( devc -> base + 3); | 961 | x = inb( devc -> base + 3); |
961 | if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */ | 962 | if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */ |
962 | { | 963 | { |
963 | //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x); | 964 | //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x); |
964 | done = 1; | 965 | done = 1; |
965 | } | 966 | } |
966 | } | 967 | } |
967 | timeout_val = 5 * HZ; | 968 | timeout_val = 5 * HZ; |
968 | done = 0; | 969 | done = 0; |
969 | while (!done && timeout_val-- > 0) | 970 | while (!done && timeout_val-- > 0) |
970 | { | 971 | { |
971 | unsigned char x; | 972 | unsigned char x; |
972 | sleep(1); | 973 | sleep(1); |
973 | x = inb( devc -> base + 3); | 974 | x = inb( devc -> base + 3); |
974 | if (x == 0xfe) /* OBP startup acknowledge */ | 975 | if (x == 0xfe) /* OBP startup acknowledge */ |
975 | { | 976 | { |
976 | //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x); | 977 | //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x); |
977 | done = 1; | 978 | done = 1; |
978 | } | 979 | } |
979 | } | 980 | } |
980 | 981 | ||
981 | if ( !done ) printk(KERN_ERR "soundscape: OBP Initialization failed.\n"); | 982 | if ( !done ) printk(KERN_ERR "soundscape: OBP Initialization failed.\n"); |
982 | 983 | ||
983 | sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40); | 984 | sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40); |
984 | sscape_write( devc, 3, (devc -> dma << 4) + 0x80); | 985 | sscape_write( devc, 3, (devc -> dma << 4) + 0x80); |
985 | return 1; | 986 | return 1; |
986 | } | 987 | } |
987 | 988 | ||
988 | static void __init sscape_pnp_init_hw(sscape_info* devc) | 989 | static void __init sscape_pnp_init_hw(sscape_info* devc) |
989 | { | 990 | { |
990 | unsigned char midi_irq = 0, sb_irq = 0; | 991 | unsigned char midi_irq = 0, sb_irq = 0; |
991 | unsigned i; | 992 | unsigned i; |
992 | static char code_file_name[23] = "/sndscape/sndscape.cox"; | 993 | static char code_file_name[23] = "/sndscape/sndscape.cox"; |
993 | 994 | ||
994 | int sscape_joystic_enable = 0x7f; | 995 | int sscape_joystic_enable = 0x7f; |
995 | int sscape_mic_enable = 0; | 996 | int sscape_mic_enable = 0; |
996 | int sscape_ext_midi = 0; | 997 | int sscape_ext_midi = 0; |
997 | 998 | ||
998 | if ( !sscape_pnp_alloc_dma(devc) ) { | 999 | if ( !sscape_pnp_alloc_dma(devc) ) { |
999 | printk(KERN_ERR "sscape: faild to allocate dma\n"); | 1000 | printk(KERN_ERR "sscape: faild to allocate dma\n"); |
1000 | return; | 1001 | return; |
1001 | } | 1002 | } |
1002 | 1003 | ||
1003 | for (i = 0; i < 4; i++) { | 1004 | for (i = 0; i < 4; i++) { |
1004 | if ( devc -> irq == valid_interrupts[i] ) | 1005 | if ( devc -> irq == valid_interrupts[i] ) |
1005 | midi_irq = i; | 1006 | midi_irq = i; |
1006 | if ( devc -> codec_irq == valid_interrupts[i] ) | 1007 | if ( devc -> codec_irq == valid_interrupts[i] ) |
1007 | sb_irq = i; | 1008 | sb_irq = i; |
1008 | } | 1009 | } |
1009 | 1010 | ||
1010 | sscape_write( devc, 5, 0x50); | 1011 | sscape_write( devc, 5, 0x50); |
1011 | sscape_write( devc, 7, 0x2e); | 1012 | sscape_write( devc, 7, 0x2e); |
1012 | sscape_write( devc, 8, 0x00); | 1013 | sscape_write( devc, 8, 0x00); |
1013 | 1014 | ||
1014 | sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40); | 1015 | sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40); |
1015 | sscape_write( devc, 3, ( devc -> dma << 4) | 0x80); | 1016 | sscape_write( devc, 3, ( devc -> dma << 4) | 0x80); |
1016 | 1017 | ||
1017 | sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq); | 1018 | sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq); |
1018 | 1019 | ||
1019 | i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0); | 1020 | i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0); |
1020 | if (sscape_joystic_enable) i |= 8; | 1021 | if (sscape_joystic_enable) i |= 8; |
1021 | 1022 | ||
1022 | sscape_write (devc, 9, i); | 1023 | sscape_write (devc, 9, i); |
1023 | sscape_write (devc, 6, 0x80); | 1024 | sscape_write (devc, 6, 0x80); |
1024 | sscape_write (devc, 1, 0x80); | 1025 | sscape_write (devc, 1, 0x80); |
1025 | 1026 | ||
1026 | if (devc -> codec_type == 2) { | 1027 | if (devc -> codec_type == 2) { |
1027 | sscape_pnp_write_codec( devc, 0x0C, 0x50); | 1028 | sscape_pnp_write_codec( devc, 0x0C, 0x50); |
1028 | sscape_pnp_write_codec( devc, 0x10, sscape_pnp_read_codec( devc, 0x10) & 0x3F); | 1029 | sscape_pnp_write_codec( devc, 0x10, sscape_pnp_read_codec( devc, 0x10) & 0x3F); |
1029 | sscape_pnp_write_codec( devc, 0x11, sscape_pnp_read_codec( devc, 0x11) | 0xC0); | 1030 | sscape_pnp_write_codec( devc, 0x11, sscape_pnp_read_codec( devc, 0x11) | 0xC0); |
1030 | sscape_pnp_write_codec( devc, 29, 0x20); | 1031 | sscape_pnp_write_codec( devc, 29, 0x20); |
1031 | } | 1032 | } |
1032 | 1033 | ||
1033 | if (sscape_pnp_upload_file(devc, "/sndscape/scope.cod") == 0 ) { | 1034 | if (sscape_pnp_upload_file(devc, "/sndscape/scope.cod") == 0 ) { |
1034 | printk(KERN_ERR "sscape: faild to upload file /sndscape/scope.cod\n"); | 1035 | printk(KERN_ERR "sscape: faild to upload file /sndscape/scope.cod\n"); |
1035 | sscape_pnp_free_dma(devc); | 1036 | sscape_pnp_free_dma(devc); |
1036 | return; | 1037 | return; |
1037 | } | 1038 | } |
1038 | 1039 | ||
1039 | i = sscape_read_host_ctrl( devc ); | 1040 | i = sscape_read_host_ctrl( devc ); |
1040 | 1041 | ||
1041 | if ( (i & 0x0F) > 7 ) { | 1042 | if ( (i & 0x0F) > 7 ) { |
1042 | printk(KERN_ERR "sscape: scope.cod faild\n"); | 1043 | printk(KERN_ERR "sscape: scope.cod faild\n"); |
1043 | sscape_pnp_free_dma(devc); | 1044 | sscape_pnp_free_dma(devc); |
1044 | return; | 1045 | return; |
1045 | } | 1046 | } |
1046 | if ( i & 0x10 ) sscape_write( devc, 7, 0x2F); | 1047 | if ( i & 0x10 ) sscape_write( devc, 7, 0x2F); |
1047 | code_file_name[21] = (char) ( i & 0x0F) + 0x30; | 1048 | code_file_name[21] = (char) ( i & 0x0F) + 0x30; |
1048 | if (sscape_pnp_upload_file( devc, code_file_name) == 0) { | 1049 | if (sscape_pnp_upload_file( devc, code_file_name) == 0) { |
1049 | printk(KERN_ERR "sscape: faild to upload file %s\n", code_file_name); | 1050 | printk(KERN_ERR "sscape: faild to upload file %s\n", code_file_name); |
1050 | sscape_pnp_free_dma(devc); | 1051 | sscape_pnp_free_dma(devc); |
1051 | return; | 1052 | return; |
1052 | } | 1053 | } |
1053 | 1054 | ||
1054 | if (devc->ic_type != IC_ODIE) { | 1055 | if (devc->ic_type != IC_ODIE) { |
1055 | sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) | | 1056 | sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) | |
1056 | ( sscape_mic_enable == 0 ? 0x00 : 0x80) ); | 1057 | ( sscape_mic_enable == 0 ? 0x00 : 0x80) ); |
1057 | } | 1058 | } |
1058 | sscape_write_host_ctrl2( devc, 0x84, 0x64 ); /* MIDI volume */ | 1059 | sscape_write_host_ctrl2( devc, 0x84, 0x64 ); /* MIDI volume */ |
1059 | sscape_write_host_ctrl2( devc, 0x86, 0x64 ); /* MIDI volume?? */ | 1060 | sscape_write_host_ctrl2( devc, 0x86, 0x64 ); /* MIDI volume?? */ |
1060 | sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi); | 1061 | sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi); |
1061 | 1062 | ||
1062 | sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL | 1063 | sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL |
1063 | sscape_pnp_write_codec ( devc, 7, 0x3f ); //WAV_VOL | 1064 | sscape_pnp_write_codec ( devc, 7, 0x3f ); //WAV_VOL |
1064 | sscape_pnp_write_codec ( devc, 2, 0x1F ); //WD_CDXVOLL | 1065 | sscape_pnp_write_codec ( devc, 2, 0x1F ); //WD_CDXVOLL |
1065 | sscape_pnp_write_codec ( devc, 3, 0x1F ); //WD_CDXVOLR | 1066 | sscape_pnp_write_codec ( devc, 3, 0x1F ); //WD_CDXVOLR |
1066 | 1067 | ||
1067 | if (devc -> codec_type == 1) { | 1068 | if (devc -> codec_type == 1) { |
1068 | sscape_pnp_write_codec ( devc, 4, 0x1F ); | 1069 | sscape_pnp_write_codec ( devc, 4, 0x1F ); |
1069 | sscape_pnp_write_codec ( devc, 5, 0x1F ); | 1070 | sscape_pnp_write_codec ( devc, 5, 0x1F ); |
1070 | sscape_write_host_ctrl2( devc, 0x88, sscape_mic_enable); | 1071 | sscape_write_host_ctrl2( devc, 0x88, sscape_mic_enable); |
1071 | } else { | 1072 | } else { |
1072 | int t; | 1073 | int t; |
1073 | sscape_pnp_write_codec ( devc, 0x10, 0x1F << 1); | 1074 | sscape_pnp_write_codec ( devc, 0x10, 0x1F << 1); |
1074 | sscape_pnp_write_codec ( devc, 0x11, 0xC0 | (0x1F << 1)); | 1075 | sscape_pnp_write_codec ( devc, 0x11, 0xC0 | (0x1F << 1)); |
1075 | 1076 | ||
1076 | t = sscape_pnp_read_codec( devc, 0x00) & 0xDF; | 1077 | t = sscape_pnp_read_codec( devc, 0x00) & 0xDF; |
1077 | if ( (sscape_mic_enable == 0)) t |= 0; | 1078 | if ( (sscape_mic_enable == 0)) t |= 0; |
1078 | else t |= 0x20; | 1079 | else t |= 0x20; |
1079 | sscape_pnp_write_codec ( devc, 0x00, t); | 1080 | sscape_pnp_write_codec ( devc, 0x00, t); |
1080 | t = sscape_pnp_read_codec( devc, 0x01) & 0xDF; | 1081 | t = sscape_pnp_read_codec( devc, 0x01) & 0xDF; |
1081 | if ( (sscape_mic_enable == 0) ) t |= 0; | 1082 | if ( (sscape_mic_enable == 0) ) t |= 0; |
1082 | else t |= 0x20; | 1083 | else t |= 0x20; |
1083 | sscape_pnp_write_codec ( devc, 0x01, t); | 1084 | sscape_pnp_write_codec ( devc, 0x01, t); |
1084 | sscape_pnp_write_codec ( devc, 0x40 | 29 , 0x20); | 1085 | sscape_pnp_write_codec ( devc, 0x40 | 29 , 0x20); |
1085 | outb(0, devc -> codec); | 1086 | outb(0, devc -> codec); |
1086 | } | 1087 | } |
1087 | if (devc -> ic_type == IC_OPUS ) { | 1088 | if (devc -> ic_type == IC_OPUS ) { |
1088 | int i = sscape_read( devc, 9 ); | 1089 | int i = sscape_read( devc, 9 ); |
1089 | sscape_write( devc, 9, i | 3 ); | 1090 | sscape_write( devc, 9, i | 3 ); |
1090 | sscape_write( devc, 3, 0x40); | 1091 | sscape_write( devc, 3, 0x40); |
1091 | 1092 | ||
1092 | if (request_region(0x228, 1, "sscape setup junk")) { | 1093 | if (request_region(0x228, 1, "sscape setup junk")) { |
1093 | outb(0, 0x228); | 1094 | outb(0, 0x228); |
1094 | release_region(0x228,1); | 1095 | release_region(0x228,1); |
1095 | } | 1096 | } |
1096 | sscape_write( devc, 3, (devc -> dma << 4) | 0x80); | 1097 | sscape_write( devc, 3, (devc -> dma << 4) | 0x80); |
1097 | sscape_write( devc, 9, i ); | 1098 | sscape_write( devc, 9, i ); |
1098 | } | 1099 | } |
1099 | 1100 | ||
1100 | host_close ( devc ); | 1101 | host_close ( devc ); |
1101 | sscape_pnp_free_dma(devc); | 1102 | sscape_pnp_free_dma(devc); |
1102 | } | 1103 | } |
1103 | 1104 | ||
1104 | static int __init detect_sscape_pnp(sscape_info* devc) | 1105 | static int __init detect_sscape_pnp(sscape_info* devc) |
1105 | { | 1106 | { |
1106 | long i, irq_bits = 0xff; | 1107 | long i, irq_bits = 0xff; |
1107 | unsigned int d; | 1108 | unsigned int d; |
1108 | 1109 | ||
1109 | DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base)); | 1110 | DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base)); |
1110 | 1111 | ||
1111 | if (!request_region(devc->codec, 2, "sscape codec")) { | 1112 | if (!request_region(devc->codec, 2, "sscape codec")) { |
1112 | printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec); | 1113 | printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec); |
1113 | return 0; | 1114 | return 0; |
1114 | } | 1115 | } |
1115 | 1116 | ||
1116 | if ((inb(devc->base + 2) & 0x78) != 0) | 1117 | if ((inb(devc->base + 2) & 0x78) != 0) |
1117 | goto fail; | 1118 | goto fail; |
1118 | 1119 | ||
1119 | d = inb ( devc -> base + 4) & 0xF0; | 1120 | d = inb ( devc -> base + 4) & 0xF0; |
1120 | if (d & 0x80) | 1121 | if (d & 0x80) |
1121 | goto fail; | 1122 | goto fail; |
1122 | 1123 | ||
1123 | if (d == 0) { | 1124 | if (d == 0) { |
1124 | devc->codec_type = 1; | 1125 | devc->codec_type = 1; |
1125 | devc->ic_type = IC_ODIE; | 1126 | devc->ic_type = IC_ODIE; |
1126 | } else if ( (d & 0x60) != 0) { | 1127 | } else if ( (d & 0x60) != 0) { |
1127 | devc->codec_type = 2; | 1128 | devc->codec_type = 2; |
1128 | devc->ic_type = IC_OPUS; | 1129 | devc->ic_type = IC_OPUS; |
1129 | } else if ( (d & 0x40) != 0) { /* WTF? */ | 1130 | } else if ( (d & 0x40) != 0) { /* WTF? */ |
1130 | devc->codec_type = 2; | 1131 | devc->codec_type = 2; |
1131 | devc->ic_type = IC_ODIE; | 1132 | devc->ic_type = IC_ODIE; |
1132 | } else | 1133 | } else |
1133 | goto fail; | 1134 | goto fail; |
1134 | 1135 | ||
1135 | sscape_is_pnp = 1; | 1136 | sscape_is_pnp = 1; |
1136 | 1137 | ||
1137 | outb(0xFA, devc -> base+4); | 1138 | outb(0xFA, devc -> base+4); |
1138 | if ((inb( devc -> base+4) & 0x9F) != 0x0A) | 1139 | if ((inb( devc -> base+4) & 0x9F) != 0x0A) |
1139 | goto fail; | 1140 | goto fail; |
1140 | outb(0xFE, devc -> base+4); | 1141 | outb(0xFE, devc -> base+4); |
1141 | if ( (inb(devc -> base+4) & 0x9F) != 0x0E) | 1142 | if ( (inb(devc -> base+4) & 0x9F) != 0x0E) |
1142 | goto fail; | 1143 | goto fail; |
1143 | if ( (inb(devc -> base+5) & 0x9F) != 0x0E) | 1144 | if ( (inb(devc -> base+5) & 0x9F) != 0x0E) |
1144 | goto fail; | 1145 | goto fail; |
1145 | 1146 | ||
1146 | if (devc->codec_type == 2) { | 1147 | if (devc->codec_type == 2) { |
1147 | if (devc->codec != devc->base + 8) { | 1148 | if (devc->codec != devc->base + 8) { |
1148 | printk("soundscape warning: incorrect codec port specified\n"); | 1149 | printk("soundscape warning: incorrect codec port specified\n"); |
1149 | goto fail; | 1150 | goto fail; |
1150 | } | 1151 | } |
1151 | d = 0x10 | (sscape_read(devc, 9) & 0xCF); | 1152 | d = 0x10 | (sscape_read(devc, 9) & 0xCF); |
1152 | sscape_write(devc, 9, d); | 1153 | sscape_write(devc, 9, d); |
1153 | sscape_write(devc, 6, 0x80); | 1154 | sscape_write(devc, 6, 0x80); |
1154 | } else { | 1155 | } else { |
1155 | //todo: check codec is not base + 8 | 1156 | //todo: check codec is not base + 8 |
1156 | } | 1157 | } |
1157 | 1158 | ||
1158 | d = (sscape_read(devc, 9) & 0x3F) | 0xC0; | 1159 | d = (sscape_read(devc, 9) & 0x3F) | 0xC0; |
1159 | sscape_write(devc, 9, d); | 1160 | sscape_write(devc, 9, d); |
1160 | 1161 | ||
1161 | for (i = 0; i < 550000; i++) | 1162 | for (i = 0; i < 550000; i++) |
1162 | if ( !(inb(devc -> codec) & 0x80) ) break; | 1163 | if ( !(inb(devc -> codec) & 0x80) ) break; |
1163 | 1164 | ||
1164 | d = inb(devc -> codec); | 1165 | d = inb(devc -> codec); |
1165 | if (d & 0x80) | 1166 | if (d & 0x80) |
1166 | goto fail; | 1167 | goto fail; |
1167 | if ( inb(devc -> codec + 2) == 0xFF) | 1168 | if ( inb(devc -> codec + 2) == 0xFF) |
1168 | goto fail; | 1169 | goto fail; |
1169 | 1170 | ||
1170 | sscape_write(devc, 9, sscape_read(devc, 9) & 0x3F ); | 1171 | sscape_write(devc, 9, sscape_read(devc, 9) & 0x3F ); |
1171 | 1172 | ||
1172 | d = inb(devc -> codec) & 0x80; | 1173 | d = inb(devc -> codec) & 0x80; |
1173 | if ( d == 0) { | 1174 | if ( d == 0) { |
1174 | printk(KERN_INFO "soundscape: hardware detected\n"); | 1175 | printk(KERN_INFO "soundscape: hardware detected\n"); |
1175 | valid_interrupts = valid_interrupts_new; | 1176 | valid_interrupts = valid_interrupts_new; |
1176 | } else { | 1177 | } else { |
1177 | printk(KERN_INFO "soundscape: board looks like media fx\n"); | 1178 | printk(KERN_INFO "soundscape: board looks like media fx\n"); |
1178 | valid_interrupts = valid_interrupts_old; | 1179 | valid_interrupts = valid_interrupts_old; |
1179 | old_hardware = 1; | 1180 | old_hardware = 1; |
1180 | } | 1181 | } |
1181 | 1182 | ||
1182 | sscape_write( devc, 9, 0xC0 | (sscape_read(devc, 9) & 0x3F) ); | 1183 | sscape_write( devc, 9, 0xC0 | (sscape_read(devc, 9) & 0x3F) ); |
1183 | 1184 | ||
1184 | for (i = 0; i < 550000; i++) | 1185 | for (i = 0; i < 550000; i++) |
1185 | if ( !(inb(devc -> codec) & 0x80)) | 1186 | if ( !(inb(devc -> codec) & 0x80)) |
1186 | break; | 1187 | break; |
1187 | 1188 | ||
1188 | sscape_pnp_init_hw(devc); | 1189 | sscape_pnp_init_hw(devc); |
1189 | 1190 | ||
1190 | for (i = 0; i < 4; i++) | 1191 | for (i = 0; i < 4; i++) |
1191 | { | 1192 | { |
1192 | if (devc->codec_irq == valid_interrupts[i]) { | 1193 | if (devc->codec_irq == valid_interrupts[i]) { |
1193 | irq_bits = i; | 1194 | irq_bits = i; |
1194 | break; | 1195 | break; |
1195 | } | 1196 | } |
1196 | } | 1197 | } |
1197 | sscape_write(devc, GA_INTENA_REG, 0x00); | 1198 | sscape_write(devc, GA_INTENA_REG, 0x00); |
1198 | sscape_write(devc, GA_DMACFG_REG, 0x50); | 1199 | sscape_write(devc, GA_DMACFG_REG, 0x50); |
1199 | sscape_write(devc, GA_DMAA_REG, 0x70); | 1200 | sscape_write(devc, GA_DMAA_REG, 0x70); |
1200 | sscape_write(devc, GA_DMAB_REG, 0x20); | 1201 | sscape_write(devc, GA_DMAB_REG, 0x20); |
1201 | sscape_write(devc, GA_INTCFG_REG, 0xf0); | 1202 | sscape_write(devc, GA_INTCFG_REG, 0xf0); |
1202 | sscape_write(devc, GA_CDCFG_REG, 0x89 | (devc->dma << 4) | (irq_bits << 1)); | 1203 | sscape_write(devc, GA_CDCFG_REG, 0x89 | (devc->dma << 4) | (irq_bits << 1)); |
1203 | 1204 | ||
1204 | sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20); | 1205 | sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20); |
1205 | sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20); | 1206 | sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20); |
1206 | 1207 | ||
1207 | return 1; | 1208 | return 1; |
1208 | fail: | 1209 | fail: |
1209 | release_region(devc->codec, 2); | 1210 | release_region(devc->codec, 2); |
1210 | return 0; | 1211 | return 0; |
1211 | } | 1212 | } |
1212 | 1213 | ||
1213 | static int __init probe_sscape(struct address_info *hw_config) | 1214 | static int __init probe_sscape(struct address_info *hw_config) |
1214 | { | 1215 | { |
1215 | devc->base = hw_config->io_base; | 1216 | devc->base = hw_config->io_base; |
1216 | devc->irq = hw_config->irq; | 1217 | devc->irq = hw_config->irq; |
1217 | devc->dma = hw_config->dma; | 1218 | devc->dma = hw_config->dma; |
1218 | devc->osp = hw_config->osp; | 1219 | devc->osp = hw_config->osp; |
1219 | 1220 | ||
1220 | #ifdef SSCAPE_DEBUG1 | 1221 | #ifdef SSCAPE_DEBUG1 |
1221 | /* | 1222 | /* |
1222 | * Temporary debugging aid. Print contents of the registers before | 1223 | * Temporary debugging aid. Print contents of the registers before |
1223 | * changing them. | 1224 | * changing them. |
1224 | */ | 1225 | */ |
1225 | { | 1226 | { |
1226 | int i; | 1227 | int i; |
1227 | 1228 | ||
1228 | for (i = 0; i < 13; i++) | 1229 | for (i = 0; i < 13; i++) |
1229 | printk("I%d = %02x (old value)\n", i, sscape_read(devc, i)); | 1230 | printk("I%d = %02x (old value)\n", i, sscape_read(devc, i)); |
1230 | } | 1231 | } |
1231 | #endif | 1232 | #endif |
1232 | devc->failed = 1; | 1233 | devc->failed = 1; |
1233 | 1234 | ||
1234 | sscape_ports = request_region(devc->base, 2, "mpu401"); | 1235 | sscape_ports = request_region(devc->base, 2, "mpu401"); |
1235 | if (!sscape_ports) | 1236 | if (!sscape_ports) |
1236 | return 0; | 1237 | return 0; |
1237 | 1238 | ||
1238 | if (!request_region(devc->base + 2, 6, "SoundScape")) { | 1239 | if (!request_region(devc->base + 2, 6, "SoundScape")) { |
1239 | release_region(devc->base, 2); | 1240 | release_region(devc->base, 2); |
1240 | return 0; | 1241 | return 0; |
1241 | } | 1242 | } |
1242 | 1243 | ||
1243 | if (!detect_ga(devc)) { | 1244 | if (!detect_ga(devc)) { |
1244 | if (detect_sscape_pnp(devc)) | 1245 | if (detect_sscape_pnp(devc)) |
1245 | return 1; | 1246 | return 1; |
1246 | release_region(devc->base, 2); | 1247 | release_region(devc->base, 2); |
1247 | release_region(devc->base + 2, 6); | 1248 | release_region(devc->base + 2, 6); |
1248 | return 0; | 1249 | return 0; |
1249 | } | 1250 | } |
1250 | 1251 | ||
1251 | if (old_hardware) /* Check that it's really an old Spea/Reveal card. */ | 1252 | if (old_hardware) /* Check that it's really an old Spea/Reveal card. */ |
1252 | { | 1253 | { |
1253 | unsigned char tmp; | 1254 | unsigned char tmp; |
1254 | int cc; | 1255 | int cc; |
1255 | 1256 | ||
1256 | if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0)) | 1257 | if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0)) |
1257 | { | 1258 | { |
1258 | sscape_write(devc, GA_HMCTL_REG, tmp | 0x80); | 1259 | sscape_write(devc, GA_HMCTL_REG, tmp | 0x80); |
1259 | for (cc = 0; cc < 200000; ++cc) | 1260 | for (cc = 0; cc < 200000; ++cc) |
1260 | inb(devc->base + ODIE_ADDR); | 1261 | inb(devc->base + ODIE_ADDR); |
1261 | } | 1262 | } |
1262 | } | 1263 | } |
1263 | return 1; | 1264 | return 1; |
1264 | } | 1265 | } |
1265 | 1266 | ||
1266 | static int __init init_ss_ms_sound(struct address_info *hw_config) | 1267 | static int __init init_ss_ms_sound(struct address_info *hw_config) |
1267 | { | 1268 | { |
1268 | int i, irq_bits = 0xff; | 1269 | int i, irq_bits = 0xff; |
1269 | int ad_flags = 0; | 1270 | int ad_flags = 0; |
1270 | struct resource *ports; | 1271 | struct resource *ports; |
1271 | 1272 | ||
1272 | if (devc->failed) | 1273 | if (devc->failed) |
1273 | { | 1274 | { |
1274 | printk(KERN_ERR "soundscape: Card not detected\n"); | 1275 | printk(KERN_ERR "soundscape: Card not detected\n"); |
1275 | return 0; | 1276 | return 0; |
1276 | } | 1277 | } |
1277 | if (devc->ok == 0) | 1278 | if (devc->ok == 0) |
1278 | { | 1279 | { |
1279 | printk(KERN_ERR "soundscape: Invalid initialization order.\n"); | 1280 | printk(KERN_ERR "soundscape: Invalid initialization order.\n"); |
1280 | return 0; | 1281 | return 0; |
1281 | } | 1282 | } |
1282 | for (i = 0; i < 4; i++) | 1283 | for (i = 0; i < 4; i++) |
1283 | { | 1284 | { |
1284 | if (hw_config->irq == valid_interrupts[i]) | 1285 | if (hw_config->irq == valid_interrupts[i]) |
1285 | { | 1286 | { |
1286 | irq_bits = i; | 1287 | irq_bits = i; |
1287 | break; | 1288 | break; |
1288 | } | 1289 | } |
1289 | } | 1290 | } |
1290 | if (irq_bits == 0xff) { | 1291 | if (irq_bits == 0xff) { |
1291 | printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq); | 1292 | printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq); |
1292 | return 0; | 1293 | return 0; |
1293 | } | 1294 | } |
1294 | 1295 | ||
1295 | if (old_hardware) | 1296 | if (old_hardware) |
1296 | ad_flags = 0x12345677; /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */ | 1297 | ad_flags = 0x12345677; /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */ |
1297 | else if (sscape_is_pnp) | 1298 | else if (sscape_is_pnp) |
1298 | ad_flags = 0x87654321; /* Tell that we have a soundscape pnp with 1845 chip */ | 1299 | ad_flags = 0x87654321; /* Tell that we have a soundscape pnp with 1845 chip */ |
1299 | 1300 | ||
1300 | ports = request_region(hw_config->io_base, 4, "ad1848"); | 1301 | ports = request_region(hw_config->io_base, 4, "ad1848"); |
1301 | if (!ports) { | 1302 | if (!ports) { |
1302 | printk(KERN_ERR "soundscape: ports busy\n"); | 1303 | printk(KERN_ERR "soundscape: ports busy\n"); |
1303 | return 0; | 1304 | return 0; |
1304 | } | 1305 | } |
1305 | 1306 | ||
1306 | if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) { | 1307 | if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) { |
1307 | release_region(hw_config->io_base, 4); | 1308 | release_region(hw_config->io_base, 4); |
1308 | return 0; | 1309 | return 0; |
1309 | } | 1310 | } |
1310 | 1311 | ||
1311 | if (!sscape_is_pnp) /*pnp is already setup*/ | 1312 | if (!sscape_is_pnp) /*pnp is already setup*/ |
1312 | { | 1313 | { |
1313 | /* | 1314 | /* |
1314 | * Setup the DMA polarity. | 1315 | * Setup the DMA polarity. |
1315 | */ | 1316 | */ |
1316 | sscape_write(devc, GA_DMACFG_REG, 0x50); | 1317 | sscape_write(devc, GA_DMACFG_REG, 0x50); |
1317 | 1318 | ||
1318 | /* | 1319 | /* |
1319 | * Take the gate-array off of the DMA channel. | 1320 | * Take the gate-array off of the DMA channel. |
1320 | */ | 1321 | */ |
1321 | sscape_write(devc, GA_DMAB_REG, 0x20); | 1322 | sscape_write(devc, GA_DMAB_REG, 0x20); |
1322 | 1323 | ||
1323 | /* | 1324 | /* |
1324 | * Init the AD1848 (CD-ROM) config reg. | 1325 | * Init the AD1848 (CD-ROM) config reg. |
1325 | */ | 1326 | */ |
1326 | sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1)); | 1327 | sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1)); |
1327 | } | 1328 | } |
1328 | 1329 | ||
1329 | if (hw_config->irq == devc->irq) | 1330 | if (hw_config->irq == devc->irq) |
1330 | printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n"); | 1331 | printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n"); |
1331 | 1332 | ||
1332 | hw_config->slots[0] = ad1848_init( | 1333 | hw_config->slots[0] = ad1848_init( |
1333 | sscape_is_pnp ? "SoundScape" : "SoundScape PNP", | 1334 | sscape_is_pnp ? "SoundScape" : "SoundScape PNP", |
1334 | ports, | 1335 | ports, |
1335 | hw_config->irq, | 1336 | hw_config->irq, |
1336 | hw_config->dma, | 1337 | hw_config->dma, |
1337 | hw_config->dma, | 1338 | hw_config->dma, |
1338 | 0, | 1339 | 0, |
1339 | devc->osp, | 1340 | devc->osp, |
1340 | THIS_MODULE); | 1341 | THIS_MODULE); |
1341 | 1342 | ||
1342 | 1343 | ||
1343 | if (hw_config->slots[0] != -1) /* The AD1848 driver installed itself */ | 1344 | if (hw_config->slots[0] != -1) /* The AD1848 driver installed itself */ |
1344 | { | 1345 | { |
1345 | audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations; | 1346 | audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations; |
1346 | devc->codec_audiodev = hw_config->slots[0]; | 1347 | devc->codec_audiodev = hw_config->slots[0]; |
1347 | devc->my_audiodev = hw_config->slots[0]; | 1348 | devc->my_audiodev = hw_config->slots[0]; |
1348 | 1349 | ||
1349 | /* Set proper routings here (what are they) */ | 1350 | /* Set proper routings here (what are they) */ |
1350 | AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); | 1351 | AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); |
1351 | } | 1352 | } |
1352 | 1353 | ||
1353 | #ifdef SSCAPE_DEBUG5 | 1354 | #ifdef SSCAPE_DEBUG5 |
1354 | /* | 1355 | /* |
1355 | * Temporary debugging aid. Print contents of the registers | 1356 | * Temporary debugging aid. Print contents of the registers |
1356 | * after the AD1848 device has been initialized. | 1357 | * after the AD1848 device has been initialized. |
1357 | */ | 1358 | */ |
1358 | { | 1359 | { |
1359 | int i; | 1360 | int i; |
1360 | 1361 | ||
1361 | for (i = 0; i < 13; i++) | 1362 | for (i = 0; i < 13; i++) |
1362 | printk("I%d = %02x\n", i, sscape_read(devc, i)); | 1363 | printk("I%d = %02x\n", i, sscape_read(devc, i)); |
1363 | } | 1364 | } |
1364 | #endif | 1365 | #endif |
1365 | return 1; | 1366 | return 1; |
1366 | } | 1367 | } |
1367 | 1368 | ||
1368 | static void __exit unload_sscape(struct address_info *hw_config) | 1369 | static void __exit unload_sscape(struct address_info *hw_config) |
1369 | { | 1370 | { |
1370 | release_region(devc->base + 2, 6); | 1371 | release_region(devc->base + 2, 6); |
1371 | unload_mpu401(hw_config); | 1372 | unload_mpu401(hw_config); |
1372 | if (sscape_is_pnp) | 1373 | if (sscape_is_pnp) |
1373 | release_region(devc->codec, 2); | 1374 | release_region(devc->codec, 2); |
1374 | } | 1375 | } |
1375 | 1376 | ||
1376 | static void __exit unload_ss_ms_sound(struct address_info *hw_config) | 1377 | static void __exit unload_ss_ms_sound(struct address_info *hw_config) |
1377 | { | 1378 | { |
1378 | ad1848_unload(hw_config->io_base, | 1379 | ad1848_unload(hw_config->io_base, |
1379 | hw_config->irq, | 1380 | hw_config->irq, |
1380 | devc->dma, | 1381 | devc->dma, |
1381 | devc->dma, | 1382 | devc->dma, |
1382 | 0); | 1383 | 0); |
1383 | sound_unload_audiodev(hw_config->slots[0]); | 1384 | sound_unload_audiodev(hw_config->slots[0]); |
1384 | } | 1385 | } |
1385 | 1386 | ||
1386 | static struct address_info cfg; | 1387 | static struct address_info cfg; |
1387 | static struct address_info cfg_mpu; | 1388 | static struct address_info cfg_mpu; |
1388 | 1389 | ||
1389 | static int __initdata spea = -1; | 1390 | static int __initdata spea = -1; |
1390 | static int mss = 0; | 1391 | static int mss = 0; |
1391 | static int __initdata dma = -1; | 1392 | static int __initdata dma = -1; |
1392 | static int __initdata irq = -1; | 1393 | static int __initdata irq = -1; |
1393 | static int __initdata io = -1; | 1394 | static int __initdata io = -1; |
1394 | static int __initdata mpu_irq = -1; | 1395 | static int __initdata mpu_irq = -1; |
1395 | static int __initdata mpu_io = -1; | 1396 | static int __initdata mpu_io = -1; |
1396 | 1397 | ||
1397 | module_param(dma, int, 0); | 1398 | module_param(dma, int, 0); |
1398 | module_param(irq, int, 0); | 1399 | module_param(irq, int, 0); |
1399 | module_param(io, int, 0); | 1400 | module_param(io, int, 0); |
1400 | module_param(spea, int, 0); /* spea=0/1 set the old_hardware */ | 1401 | module_param(spea, int, 0); /* spea=0/1 set the old_hardware */ |
1401 | module_param(mpu_irq, int, 0); | 1402 | module_param(mpu_irq, int, 0); |
1402 | module_param(mpu_io, int, 0); | 1403 | module_param(mpu_io, int, 0); |
1403 | module_param(mss, int, 0); | 1404 | module_param(mss, int, 0); |
1404 | 1405 | ||
1405 | static int __init init_sscape(void) | 1406 | static int __init init_sscape(void) |
1406 | { | 1407 | { |
1407 | printk(KERN_INFO "Soundscape driver Copyright (C) by Hannu Savolainen 1993-1996\n"); | 1408 | printk(KERN_INFO "Soundscape driver Copyright (C) by Hannu Savolainen 1993-1996\n"); |
1408 | 1409 | ||
1409 | cfg.irq = irq; | 1410 | cfg.irq = irq; |
1410 | cfg.dma = dma; | 1411 | cfg.dma = dma; |
1411 | cfg.io_base = io; | 1412 | cfg.io_base = io; |
1412 | 1413 | ||
1413 | cfg_mpu.irq = mpu_irq; | 1414 | cfg_mpu.irq = mpu_irq; |
1414 | cfg_mpu.io_base = mpu_io; | 1415 | cfg_mpu.io_base = mpu_io; |
1415 | /* WEH - Try to get right dma channel */ | 1416 | /* WEH - Try to get right dma channel */ |
1416 | cfg_mpu.dma = dma; | 1417 | cfg_mpu.dma = dma; |
1417 | 1418 | ||
1418 | devc->codec = cfg.io_base; | 1419 | devc->codec = cfg.io_base; |
1419 | devc->codec_irq = cfg.irq; | 1420 | devc->codec_irq = cfg.irq; |
1420 | devc->codec_type = 0; | 1421 | devc->codec_type = 0; |
1421 | devc->ic_type = 0; | 1422 | devc->ic_type = 0; |
1422 | devc->raw_buf = NULL; | 1423 | devc->raw_buf = NULL; |
1423 | spin_lock_init(&devc->lock); | 1424 | spin_lock_init(&devc->lock); |
1424 | 1425 | ||
1425 | if (cfg.dma == -1 || cfg.irq == -1 || cfg.io_base == -1) { | 1426 | if (cfg.dma == -1 || cfg.irq == -1 || cfg.io_base == -1) { |
1426 | printk(KERN_ERR "DMA, IRQ, and IO port must be specified.\n"); | 1427 | printk(KERN_ERR "DMA, IRQ, and IO port must be specified.\n"); |
1427 | return -EINVAL; | 1428 | return -EINVAL; |
1428 | } | 1429 | } |
1429 | 1430 | ||
1430 | if (cfg_mpu.irq == -1 && cfg_mpu.io_base != -1) { | 1431 | if (cfg_mpu.irq == -1 && cfg_mpu.io_base != -1) { |
1431 | printk(KERN_ERR "MPU_IRQ must be specified if MPU_IO is set.\n"); | 1432 | printk(KERN_ERR "MPU_IRQ must be specified if MPU_IO is set.\n"); |
1432 | return -EINVAL; | 1433 | return -EINVAL; |
1433 | } | 1434 | } |
1434 | 1435 | ||
1435 | if(spea != -1) { | 1436 | if(spea != -1) { |
1436 | old_hardware = spea; | 1437 | old_hardware = spea; |
1437 | printk(KERN_INFO "Forcing %s hardware support.\n", | 1438 | printk(KERN_INFO "Forcing %s hardware support.\n", |
1438 | spea?"new":"old"); | 1439 | spea?"new":"old"); |
1439 | } | 1440 | } |
1440 | if (probe_sscape(&cfg_mpu) == 0) | 1441 | if (probe_sscape(&cfg_mpu) == 0) |
1441 | return -ENODEV; | 1442 | return -ENODEV; |
1442 | 1443 | ||
1443 | attach_sscape(&cfg_mpu); | 1444 | attach_sscape(&cfg_mpu); |
1444 | 1445 | ||
1445 | mss = init_ss_ms_sound(&cfg); | 1446 | mss = init_ss_ms_sound(&cfg); |
1446 | 1447 | ||
1447 | return 0; | 1448 | return 0; |
1448 | } | 1449 | } |
1449 | 1450 | ||
1450 | static void __exit cleanup_sscape(void) | 1451 | static void __exit cleanup_sscape(void) |
1451 | { | 1452 | { |
1452 | if (mss) | 1453 | if (mss) |
1453 | unload_ss_ms_sound(&cfg); | 1454 | unload_ss_ms_sound(&cfg); |
1454 | unload_sscape(&cfg_mpu); | 1455 | unload_sscape(&cfg_mpu); |
1455 | } | 1456 | } |
1456 | 1457 | ||
1457 | module_init(init_sscape); | 1458 | module_init(init_sscape); |
1458 | module_exit(cleanup_sscape); | 1459 | module_exit(cleanup_sscape); |
1459 | 1460 | ||
1460 | #ifndef MODULE | 1461 | #ifndef MODULE |
1461 | static int __init setup_sscape(char *str) | 1462 | static int __init setup_sscape(char *str) |
1462 | { | 1463 | { |
1463 | /* io, irq, dma, mpu_io, mpu_irq */ | 1464 | /* io, irq, dma, mpu_io, mpu_irq */ |
1464 | int ints[6]; | 1465 | int ints[6]; |
1465 | 1466 | ||
1466 | str = get_options(str, ARRAY_SIZE(ints), ints); | 1467 | str = get_options(str, ARRAY_SIZE(ints), ints); |
1467 | 1468 | ||
1468 | io = ints[1]; | 1469 | io = ints[1]; |
1469 | irq = ints[2]; | 1470 | irq = ints[2]; |
1470 | dma = ints[3]; | 1471 | dma = ints[3]; |
1471 | mpu_io = ints[4]; | 1472 | mpu_io = ints[4]; |
1472 | mpu_irq = ints[5]; | 1473 | mpu_irq = ints[5]; |
1473 | 1474 | ||
1474 | return 1; | 1475 | return 1; |
1475 | } | 1476 | } |
1476 | 1477 | ||
1477 | __setup("sscape=", setup_sscape); | 1478 | __setup("sscape=", setup_sscape); |
1478 | #endif | 1479 | #endif |
1479 | MODULE_LICENSE("GPL"); | 1480 | MODULE_LICENSE("GPL"); |
1480 | 1481 |
sound/oss/trident.c
1 | /* | 1 | /* |
2 | * OSS driver for Linux 2.[46].x for | 2 | * OSS driver for Linux 2.[46].x for |
3 | * | 3 | * |
4 | * Trident 4D-Wave | 4 | * Trident 4D-Wave |
5 | * SiS 7018 | 5 | * SiS 7018 |
6 | * ALi 5451 | 6 | * ALi 5451 |
7 | * Tvia/IGST CyberPro 5050 | 7 | * Tvia/IGST CyberPro 5050 |
8 | * | 8 | * |
9 | * Driver: Alan Cox <alan@redhat.com> | 9 | * Driver: Alan Cox <alan@redhat.com> |
10 | * | 10 | * |
11 | * Built from: | 11 | * Built from: |
12 | * Low level code: <audio@tridentmicro.com> from ALSA | 12 | * Low level code: <audio@tridentmicro.com> from ALSA |
13 | * Framework: Thomas Sailer <sailer@ife.ee.ethz.ch> | 13 | * Framework: Thomas Sailer <sailer@ife.ee.ethz.ch> |
14 | * Extended by: Zach Brown <zab@redhat.com> | 14 | * Extended by: Zach Brown <zab@redhat.com> |
15 | * | 15 | * |
16 | * Hacked up by: | 16 | * Hacked up by: |
17 | * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> | 17 | * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> |
18 | * Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support | 18 | * Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support |
19 | * Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support | 19 | * Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support |
20 | * Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support | 20 | * Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support |
21 | * Peter Wรคchtler <pwaechtler@loewe-komp.de> CyberPro5050 support | 21 | * Peter Wรคchtler <pwaechtler@loewe-komp.de> CyberPro5050 support |
22 | * Muli Ben-Yehuda <mulix@mulix.org> | 22 | * Muli Ben-Yehuda <mulix@mulix.org> |
23 | * | 23 | * |
24 | * | 24 | * |
25 | * This program is free software; you can redistribute it and/or modify | 25 | * This program is free software; you can redistribute it and/or modify |
26 | * it under the terms of the GNU General Public License as published by | 26 | * it under the terms of the GNU General Public License as published by |
27 | * the Free Software Foundation; either version 2 of the License, or | 27 | * the Free Software Foundation; either version 2 of the License, or |
28 | * (at your option) any later version. | 28 | * (at your option) any later version. |
29 | * | 29 | * |
30 | * This program is distributed in the hope that it will be useful, | 30 | * This program is distributed in the hope that it will be useful, |
31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
33 | * GNU General Public License for more details. | 33 | * GNU General Public License for more details. |
34 | * | 34 | * |
35 | * You should have received a copy of the GNU General Public License | 35 | * You should have received a copy of the GNU General Public License |
36 | * along with this program; if not, write to the Free Software | 36 | * along with this program; if not, write to the Free Software |
37 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 37 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
38 | * | 38 | * |
39 | * History | 39 | * History |
40 | * v0.14.10j | 40 | * v0.14.10j |
41 | * January 3 2004 Eugene Teo <eugeneteo@eugeneteo.net> | 41 | * January 3 2004 Eugene Teo <eugeneteo@eugeneteo.net> |
42 | * minor cleanup to use pr_debug instead of TRDBG since it is already | 42 | * minor cleanup to use pr_debug instead of TRDBG since it is already |
43 | * defined in linux/kernel.h. | 43 | * defined in linux/kernel.h. |
44 | * v0.14.10i | 44 | * v0.14.10i |
45 | * December 29 2003 Muli Ben-Yehuda <mulix@mulix.org> | 45 | * December 29 2003 Muli Ben-Yehuda <mulix@mulix.org> |
46 | * major cleanup for 2.6, fix a few error patch buglets | 46 | * major cleanup for 2.6, fix a few error patch buglets |
47 | * with returning without properly cleaning up first, | 47 | * with returning without properly cleaning up first, |
48 | * get rid of lock_kernel(). | 48 | * get rid of lock_kernel(). |
49 | * v0.14.10h | 49 | * v0.14.10h |
50 | * Sept 10 2002 Pascal Schmidt <der.eremit@email.de> | 50 | * Sept 10 2002 Pascal Schmidt <der.eremit@email.de> |
51 | * added support for ALi 5451 joystick port | 51 | * added support for ALi 5451 joystick port |
52 | * v0.14.10g | 52 | * v0.14.10g |
53 | * Sept 05 2002 Alan Cox <alan@redhat.com> | 53 | * Sept 05 2002 Alan Cox <alan@redhat.com> |
54 | * adapt to new pci joystick attachment interface | 54 | * adapt to new pci joystick attachment interface |
55 | * v0.14.10f | 55 | * v0.14.10f |
56 | * July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | 56 | * July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il> |
57 | * patch from Eric Lemar (via Ian Soboroff): in suspend and resume, | 57 | * patch from Eric Lemar (via Ian Soboroff): in suspend and resume, |
58 | * fix wrong cast from pci_dev* to struct trident_card*. | 58 | * fix wrong cast from pci_dev* to struct trident_card*. |
59 | * v0.14.10e | 59 | * v0.14.10e |
60 | * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | 60 | * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> |
61 | * rewrite the DMA buffer allocation/deallcoation functions, to make it | 61 | * rewrite the DMA buffer allocation/deallcoation functions, to make it |
62 | * modular and fix a bug where we would call free_pages on memory | 62 | * modular and fix a bug where we would call free_pages on memory |
63 | * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef | 63 | * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef |
64 | * CONFIG_PROC_FS and various other cleanups. | 64 | * CONFIG_PROC_FS and various other cleanups. |
65 | * v0.14.10d | 65 | * v0.14.10d |
66 | * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | 66 | * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> |
67 | * made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming | 67 | * made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming |
68 | * my syslog with hundreds of messages. | 68 | * my syslog with hundreds of messages. |
69 | * v0.14.10c | 69 | * v0.14.10c |
70 | * July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | 70 | * July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il> |
71 | * Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle | 71 | * Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle |
72 | * and the coding style used in the rest of the file. | 72 | * and the coding style used in the rest of the file. |
73 | * v0.14.10b | 73 | * v0.14.10b |
74 | * June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | 74 | * June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il> |
75 | * add a missing unlock_set_fmt, remove a superflous lock/unlock pair | 75 | * add a missing unlock_set_fmt, remove a superflous lock/unlock pair |
76 | * with nothing in between. | 76 | * with nothing in between. |
77 | * v0.14.10a | 77 | * v0.14.10a |
78 | * June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | 78 | * June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il> |
79 | * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns | 79 | * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns |
80 | * per line, use 'do {} while (0)' in statement macros. | 80 | * per line, use 'do {} while (0)' in statement macros. |
81 | * v0.14.10 | 81 | * v0.14.10 |
82 | * June 6 2002 Lei Hu <Lei_hu@ali.com.tw> | 82 | * June 6 2002 Lei Hu <Lei_hu@ali.com.tw> |
83 | * rewrite the part to read/write registers of audio codec for Ali5451 | 83 | * rewrite the part to read/write registers of audio codec for Ali5451 |
84 | * v0.14.9e | 84 | * v0.14.9e |
85 | * January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport | 85 | * January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport |
86 | * support to avoid resource conflict with pcigame.c | 86 | * support to avoid resource conflict with pcigame.c |
87 | * v0.14.9d | 87 | * v0.14.9d |
88 | * October 8 2001 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 88 | * October 8 2001 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
89 | * use set_current_state, properly release resources on failure in | 89 | * use set_current_state, properly release resources on failure in |
90 | * trident_probe, get rid of check_region | 90 | * trident_probe, get rid of check_region |
91 | * v0.14.9c | 91 | * v0.14.9c |
92 | * August 10 2001 Peter Wรคchtler <pwaechtler@loewe-komp.de> | 92 | * August 10 2001 Peter Wรคchtler <pwaechtler@loewe-komp.de> |
93 | * added support for Tvia (formerly Integraphics/IGST) CyberPro5050 | 93 | * added support for Tvia (formerly Integraphics/IGST) CyberPro5050 |
94 | * this chip is often found in settop boxes (combined video+audio) | 94 | * this chip is often found in settop boxes (combined video+audio) |
95 | * v0.14.9b | 95 | * v0.14.9b |
96 | * Switch to static inline not extern inline (gcc 3) | 96 | * Switch to static inline not extern inline (gcc 3) |
97 | * v0.14.9a | 97 | * v0.14.9a |
98 | * Aug 6 2001 Alan Cox | 98 | * Aug 6 2001 Alan Cox |
99 | * 0.14.9 crashed on rmmod due to a timer/bh left running. Simplified | 99 | * 0.14.9 crashed on rmmod due to a timer/bh left running. Simplified |
100 | * the existing logic (the BH doesn't help as ac97 is lock_irqsave) | 100 | * the existing logic (the BH doesn't help as ac97 is lock_irqsave) |
101 | * and used del_timer_sync to clean up | 101 | * and used del_timer_sync to clean up |
102 | * Fixed a problem where the ALi change broke my generic card | 102 | * Fixed a problem where the ALi change broke my generic card |
103 | * v0.14.9 | 103 | * v0.14.9 |
104 | * Jul 10 2001 Matt Wu | 104 | * Jul 10 2001 Matt Wu |
105 | * Add H/W Volume Control | 105 | * Add H/W Volume Control |
106 | * v0.14.8a | 106 | * v0.14.8a |
107 | * July 7 2001 Alan Cox | 107 | * July 7 2001 Alan Cox |
108 | * Moved Matt Wu's ac97 register cache into the card structure | 108 | * Moved Matt Wu's ac97 register cache into the card structure |
109 | * v0.14.8 | 109 | * v0.14.8 |
110 | * Apr 30 2001 Matt Wu | 110 | * Apr 30 2001 Matt Wu |
111 | * Set EBUF1 and EBUF2 to still mode | 111 | * Set EBUF1 and EBUF2 to still mode |
112 | * Add dc97/ac97 reset function | 112 | * Add dc97/ac97 reset function |
113 | * Fix power management: ali_restore_regs | 113 | * Fix power management: ali_restore_regs |
114 | * unreleased | 114 | * unreleased |
115 | * Mar 09 2001 Matt Wu | 115 | * Mar 09 2001 Matt Wu |
116 | * Add cache for ac97 access | 116 | * Add cache for ac97 access |
117 | * v0.14.7 | 117 | * v0.14.7 |
118 | * Feb 06 2001 Matt Wu | 118 | * Feb 06 2001 Matt Wu |
119 | * Fix ac97 initialization | 119 | * Fix ac97 initialization |
120 | * Fix bug: an extra tail will be played when playing | 120 | * Fix bug: an extra tail will be played when playing |
121 | * Jan 05 2001 Matt Wu | 121 | * Jan 05 2001 Matt Wu |
122 | * Implement multi-channels and S/PDIF in support for ALi 1535+ | 122 | * Implement multi-channels and S/PDIF in support for ALi 1535+ |
123 | * v0.14.6 | 123 | * v0.14.6 |
124 | * Nov 1 2000 Ching-Ling Lee | 124 | * Nov 1 2000 Ching-Ling Lee |
125 | * Fix the bug of memory leak when switching 5.1-channels to 2 channels. | 125 | * Fix the bug of memory leak when switching 5.1-channels to 2 channels. |
126 | * Add lock protection into dynamic changing format of data. | 126 | * Add lock protection into dynamic changing format of data. |
127 | * Oct 18 2000 Ching-Ling Lee | 127 | * Oct 18 2000 Ching-Ling Lee |
128 | * 5.1-channels support for ALi | 128 | * 5.1-channels support for ALi |
129 | * June 28 2000 Ching-Ling Lee | 129 | * June 28 2000 Ching-Ling Lee |
130 | * S/PDIF out/in(playback/record) support for ALi 1535+, using /proc to be selected by user | 130 | * S/PDIF out/in(playback/record) support for ALi 1535+, using /proc to be selected by user |
131 | * Simple Power Management support for ALi | 131 | * Simple Power Management support for ALi |
132 | * v0.14.5 May 23 2000 Ollie Lho | 132 | * v0.14.5 May 23 2000 Ollie Lho |
133 | * Misc bug fix from the Net | 133 | * Misc bug fix from the Net |
134 | * v0.14.4 May 20 2000 Aaron Holtzman | 134 | * v0.14.4 May 20 2000 Aaron Holtzman |
135 | * Fix kfree'd memory access in release | 135 | * Fix kfree'd memory access in release |
136 | * Fix race in open while looking for a free virtual channel slot | 136 | * Fix race in open while looking for a free virtual channel slot |
137 | * remove open_wait wq (which appears to be unused) | 137 | * remove open_wait wq (which appears to be unused) |
138 | * v0.14.3 May 10 2000 Ollie Lho | 138 | * v0.14.3 May 10 2000 Ollie Lho |
139 | * fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU | 139 | * fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU |
140 | * v0.14.2 Mar 29 2000 Ching-Ling Lee | 140 | * v0.14.2 Mar 29 2000 Ching-Ling Lee |
141 | * Add clear to silence advance in trident_update_ptr | 141 | * Add clear to silence advance in trident_update_ptr |
142 | * fix invalid data of the end of the sound | 142 | * fix invalid data of the end of the sound |
143 | * v0.14.1 Mar 24 2000 Ching-Ling Lee | 143 | * v0.14.1 Mar 24 2000 Ching-Ling Lee |
144 | * ALi 5451 support added, playback and recording O.K. | 144 | * ALi 5451 support added, playback and recording O.K. |
145 | * ALi 5451 originally developed and structured based on sonicvibes, and | 145 | * ALi 5451 originally developed and structured based on sonicvibes, and |
146 | * suggested to merge into this file by Alan Cox. | 146 | * suggested to merge into this file by Alan Cox. |
147 | * v0.14 Mar 15 2000 Ollie Lho | 147 | * v0.14 Mar 15 2000 Ollie Lho |
148 | * 5.1 channel output support with channel binding. What's the Matrix ? | 148 | * 5.1 channel output support with channel binding. What's the Matrix ? |
149 | * v0.13.1 Mar 10 2000 Ollie Lho | 149 | * v0.13.1 Mar 10 2000 Ollie Lho |
150 | * few minor bugs on dual codec support, needs more testing | 150 | * few minor bugs on dual codec support, needs more testing |
151 | * v0.13 Mar 03 2000 Ollie Lho | 151 | * v0.13 Mar 03 2000 Ollie Lho |
152 | * new pci_* for 2.4 kernel, back ported to 2.2 | 152 | * new pci_* for 2.4 kernel, back ported to 2.2 |
153 | * v0.12 Feb 23 2000 Ollie Lho | 153 | * v0.12 Feb 23 2000 Ollie Lho |
154 | * Preliminary Recording support | 154 | * Preliminary Recording support |
155 | * v0.11.2 Feb 19 2000 Ollie Lho | 155 | * v0.11.2 Feb 19 2000 Ollie Lho |
156 | * removed incomplete full-dulplex support | 156 | * removed incomplete full-dulplex support |
157 | * v0.11.1 Jan 28 2000 Ollie Lho | 157 | * v0.11.1 Jan 28 2000 Ollie Lho |
158 | * small bug in setting sample rate for 4d-nx (reported by Aaron) | 158 | * small bug in setting sample rate for 4d-nx (reported by Aaron) |
159 | * v0.11 Jan 27 2000 Ollie Lho | 159 | * v0.11 Jan 27 2000 Ollie Lho |
160 | * DMA bug, scheduler latency, second try | 160 | * DMA bug, scheduler latency, second try |
161 | * v0.10 Jan 24 2000 Ollie Lho | 161 | * v0.10 Jan 24 2000 Ollie Lho |
162 | * DMA bug fixed, found kernel scheduling problem | 162 | * DMA bug fixed, found kernel scheduling problem |
163 | * v0.09 Jan 20 2000 Ollie Lho | 163 | * v0.09 Jan 20 2000 Ollie Lho |
164 | * Clean up of channel register access routine (prepare for channel binding) | 164 | * Clean up of channel register access routine (prepare for channel binding) |
165 | * v0.08 Jan 14 2000 Ollie Lho | 165 | * v0.08 Jan 14 2000 Ollie Lho |
166 | * Isolation of AC97 codec code | 166 | * Isolation of AC97 codec code |
167 | * v0.07 Jan 13 2000 Ollie Lho | 167 | * v0.07 Jan 13 2000 Ollie Lho |
168 | * Get rid of ugly old low level access routines (e.g. CHRegs.lp****) | 168 | * Get rid of ugly old low level access routines (e.g. CHRegs.lp****) |
169 | * v0.06 Jan 11 2000 Ollie Lho | 169 | * v0.06 Jan 11 2000 Ollie Lho |
170 | * Preliminary support for dual (more ?) AC97 codecs | 170 | * Preliminary support for dual (more ?) AC97 codecs |
171 | * v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com> | 171 | * v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com> |
172 | * adapt to 2.3.x new __setup/__init call | 172 | * adapt to 2.3.x new __setup/__init call |
173 | * v0.04 Dec 31 1999 Ollie Lho | 173 | * v0.04 Dec 31 1999 Ollie Lho |
174 | * Multiple Open, using Middle Loop Interrupt to smooth playback | 174 | * Multiple Open, using Middle Loop Interrupt to smooth playback |
175 | * v0.03 Dec 24 1999 Ollie Lho | 175 | * v0.03 Dec 24 1999 Ollie Lho |
176 | * mem leak in prog_dmabuf and dealloc_dmabuf removed | 176 | * mem leak in prog_dmabuf and dealloc_dmabuf removed |
177 | * v0.02 Dec 15 1999 Ollie Lho | 177 | * v0.02 Dec 15 1999 Ollie Lho |
178 | * SiS 7018 support added, playback O.K. | 178 | * SiS 7018 support added, playback O.K. |
179 | * v0.01 Alan Cox et. al. | 179 | * v0.01 Alan Cox et. al. |
180 | * Initial Release in kernel 2.3.30, does not work | 180 | * Initial Release in kernel 2.3.30, does not work |
181 | * | 181 | * |
182 | * ToDo | 182 | * ToDo |
183 | * Clean up of low level channel register access code. (done) | 183 | * Clean up of low level channel register access code. (done) |
184 | * Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done) | 184 | * Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done) |
185 | * Dual AC97 codecs support (done) | 185 | * Dual AC97 codecs support (done) |
186 | * Recording support (done) | 186 | * Recording support (done) |
187 | * Mmap support | 187 | * Mmap support |
188 | * "Channel Binding" ioctl extension (done) | 188 | * "Channel Binding" ioctl extension (done) |
189 | * new pci device driver interface for 2.4 kernel (done) | 189 | * new pci device driver interface for 2.4 kernel (done) |
190 | * | 190 | * |
191 | * Lock order (high->low) | 191 | * Lock order (high->low) |
192 | * lock - hardware lock | 192 | * lock - hardware lock |
193 | * open_mutex - guard opens | 193 | * open_mutex - guard opens |
194 | * sem - guard dmabuf, write re-entry etc | 194 | * sem - guard dmabuf, write re-entry etc |
195 | */ | 195 | */ |
196 | 196 | ||
197 | #include <linux/module.h> | 197 | #include <linux/module.h> |
198 | #include <linux/string.h> | 198 | #include <linux/string.h> |
199 | #include <linux/ctype.h> | 199 | #include <linux/ctype.h> |
200 | #include <linux/ioport.h> | 200 | #include <linux/ioport.h> |
201 | #include <linux/sched.h> | 201 | #include <linux/sched.h> |
202 | #include <linux/delay.h> | 202 | #include <linux/delay.h> |
203 | #include <linux/sound.h> | 203 | #include <linux/sound.h> |
204 | #include <linux/slab.h> | 204 | #include <linux/slab.h> |
205 | #include <linux/soundcard.h> | 205 | #include <linux/soundcard.h> |
206 | #include <linux/pci.h> | 206 | #include <linux/pci.h> |
207 | #include <linux/init.h> | 207 | #include <linux/init.h> |
208 | #include <linux/poll.h> | 208 | #include <linux/poll.h> |
209 | #include <linux/spinlock.h> | 209 | #include <linux/spinlock.h> |
210 | #include <linux/smp_lock.h> | 210 | #include <linux/smp_lock.h> |
211 | #include <linux/ac97_codec.h> | 211 | #include <linux/ac97_codec.h> |
212 | #include <linux/bitops.h> | 212 | #include <linux/bitops.h> |
213 | #include <linux/proc_fs.h> | 213 | #include <linux/proc_fs.h> |
214 | #include <linux/interrupt.h> | 214 | #include <linux/interrupt.h> |
215 | #include <linux/pm.h> | 215 | #include <linux/pm.h> |
216 | #include <linux/gameport.h> | 216 | #include <linux/gameport.h> |
217 | #include <linux/kernel.h> | 217 | #include <linux/kernel.h> |
218 | #include <linux/mutex.h> | 218 | #include <linux/mutex.h> |
219 | #include <linux/mm.h> | ||
219 | 220 | ||
220 | #include <asm/uaccess.h> | 221 | #include <asm/uaccess.h> |
221 | #include <asm/io.h> | 222 | #include <asm/io.h> |
222 | #include <asm/dma.h> | 223 | #include <asm/dma.h> |
223 | 224 | ||
224 | #if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC) | 225 | #if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC) |
225 | #include <asm/hwrpb.h> | 226 | #include <asm/hwrpb.h> |
226 | #endif | 227 | #endif |
227 | 228 | ||
228 | #include "trident.h" | 229 | #include "trident.h" |
229 | 230 | ||
230 | #define DRIVER_VERSION "0.14.10j-2.6" | 231 | #define DRIVER_VERSION "0.14.10j-2.6" |
231 | 232 | ||
232 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | 233 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) |
233 | #define SUPPORT_JOYSTICK 1 | 234 | #define SUPPORT_JOYSTICK 1 |
234 | #endif | 235 | #endif |
235 | 236 | ||
236 | /* magic numbers to protect our data structures */ | 237 | /* magic numbers to protect our data structures */ |
237 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ | 238 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ |
238 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ | 239 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ |
239 | 240 | ||
240 | #define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ | 241 | #define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ |
241 | #define ALI_DMA_MASK 0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */ | 242 | #define ALI_DMA_MASK 0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */ |
242 | 243 | ||
243 | #define NR_HW_CH 32 | 244 | #define NR_HW_CH 32 |
244 | 245 | ||
245 | /* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only | 246 | /* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only |
246 | have 2 SDATA_IN lines (currently) */ | 247 | have 2 SDATA_IN lines (currently) */ |
247 | #define NR_AC97 2 | 248 | #define NR_AC97 2 |
248 | 249 | ||
249 | /* minor number of /dev/swmodem (temporary, experimental) */ | 250 | /* minor number of /dev/swmodem (temporary, experimental) */ |
250 | #define SND_DEV_SWMODEM 7 | 251 | #define SND_DEV_SWMODEM 7 |
251 | 252 | ||
252 | static const unsigned ali_multi_channels_5_1[] = { | 253 | static const unsigned ali_multi_channels_5_1[] = { |
253 | /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL, */ | 254 | /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL, */ |
254 | ALI_CENTER_CHANNEL, | 255 | ALI_CENTER_CHANNEL, |
255 | ALI_LEF_CHANNEL, | 256 | ALI_LEF_CHANNEL, |
256 | ALI_SURR_LEFT_CHANNEL, | 257 | ALI_SURR_LEFT_CHANNEL, |
257 | ALI_SURR_RIGHT_CHANNEL | 258 | ALI_SURR_RIGHT_CHANNEL |
258 | }; | 259 | }; |
259 | 260 | ||
260 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; | 261 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; |
261 | static const unsigned sample_shift[] = { 0, 1, 1, 2 }; | 262 | static const unsigned sample_shift[] = { 0, 1, 1, 2 }; |
262 | 263 | ||
263 | static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n"; | 264 | static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n"; |
264 | 265 | ||
265 | enum { | 266 | enum { |
266 | TRIDENT_4D_DX = 0, | 267 | TRIDENT_4D_DX = 0, |
267 | TRIDENT_4D_NX, | 268 | TRIDENT_4D_NX, |
268 | SIS_7018, | 269 | SIS_7018, |
269 | ALI_5451, | 270 | ALI_5451, |
270 | CYBER5050 | 271 | CYBER5050 |
271 | }; | 272 | }; |
272 | 273 | ||
273 | static char *card_names[] = { | 274 | static char *card_names[] = { |
274 | "Trident 4DWave DX", | 275 | "Trident 4DWave DX", |
275 | "Trident 4DWave NX", | 276 | "Trident 4DWave NX", |
276 | "SiS 7018 PCI Audio", | 277 | "SiS 7018 PCI Audio", |
277 | "ALi Audio Accelerator", | 278 | "ALi Audio Accelerator", |
278 | "Tvia/IGST CyberPro 5050" | 279 | "Tvia/IGST CyberPro 5050" |
279 | }; | 280 | }; |
280 | 281 | ||
281 | static struct pci_device_id trident_pci_tbl[] = { | 282 | static struct pci_device_id trident_pci_tbl[] = { |
282 | {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), | 283 | {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), |
283 | PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX}, | 284 | PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX}, |
284 | {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), | 285 | {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), |
285 | 0, 0, TRIDENT_4D_NX}, | 286 | 0, 0, TRIDENT_4D_NX}, |
286 | {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018}, | 287 | {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018}, |
287 | {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451}, | 288 | {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451}, |
288 | {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050), | 289 | {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050), |
289 | 0, 0, CYBER5050}, | 290 | 0, 0, CYBER5050}, |
290 | {0,} | 291 | {0,} |
291 | }; | 292 | }; |
292 | 293 | ||
293 | MODULE_DEVICE_TABLE(pci, trident_pci_tbl); | 294 | MODULE_DEVICE_TABLE(pci, trident_pci_tbl); |
294 | 295 | ||
295 | /* "software" or virtual channel, an instance of opened /dev/dsp */ | 296 | /* "software" or virtual channel, an instance of opened /dev/dsp */ |
296 | struct trident_state { | 297 | struct trident_state { |
297 | unsigned int magic; | 298 | unsigned int magic; |
298 | struct trident_card *card; /* Card info */ | 299 | struct trident_card *card; /* Card info */ |
299 | 300 | ||
300 | /* file mode */ | 301 | /* file mode */ |
301 | mode_t open_mode; | 302 | mode_t open_mode; |
302 | 303 | ||
303 | /* virtual channel number */ | 304 | /* virtual channel number */ |
304 | int virt; | 305 | int virt; |
305 | 306 | ||
306 | struct dmabuf { | 307 | struct dmabuf { |
307 | /* wave sample stuff */ | 308 | /* wave sample stuff */ |
308 | unsigned int rate; | 309 | unsigned int rate; |
309 | unsigned char fmt, enable; | 310 | unsigned char fmt, enable; |
310 | 311 | ||
311 | /* hardware channel */ | 312 | /* hardware channel */ |
312 | struct trident_channel *channel; | 313 | struct trident_channel *channel; |
313 | 314 | ||
314 | /* OSS buffer management stuff */ | 315 | /* OSS buffer management stuff */ |
315 | void *rawbuf; | 316 | void *rawbuf; |
316 | dma_addr_t dma_handle; | 317 | dma_addr_t dma_handle; |
317 | unsigned buforder; | 318 | unsigned buforder; |
318 | unsigned numfrag; | 319 | unsigned numfrag; |
319 | unsigned fragshift; | 320 | unsigned fragshift; |
320 | 321 | ||
321 | /* our buffer acts like a circular ring */ | 322 | /* our buffer acts like a circular ring */ |
322 | unsigned hwptr; /* where dma last started, updated by update_ptr */ | 323 | unsigned hwptr; /* where dma last started, updated by update_ptr */ |
323 | unsigned swptr; /* where driver last clear/filled, updated by read/write */ | 324 | unsigned swptr; /* where driver last clear/filled, updated by read/write */ |
324 | int count; /* bytes to be comsumed or been generated by dma machine */ | 325 | int count; /* bytes to be comsumed or been generated by dma machine */ |
325 | unsigned total_bytes; /* total bytes dmaed by hardware */ | 326 | unsigned total_bytes; /* total bytes dmaed by hardware */ |
326 | 327 | ||
327 | unsigned error; /* number of over/underruns */ | 328 | unsigned error; /* number of over/underruns */ |
328 | /* put process on wait queue when no more space in buffer */ | 329 | /* put process on wait queue when no more space in buffer */ |
329 | wait_queue_head_t wait; | 330 | wait_queue_head_t wait; |
330 | 331 | ||
331 | /* redundant, but makes calculations easier */ | 332 | /* redundant, but makes calculations easier */ |
332 | unsigned fragsize; | 333 | unsigned fragsize; |
333 | unsigned dmasize; | 334 | unsigned dmasize; |
334 | unsigned fragsamples; | 335 | unsigned fragsamples; |
335 | 336 | ||
336 | /* OSS stuff */ | 337 | /* OSS stuff */ |
337 | unsigned mapped:1; | 338 | unsigned mapped:1; |
338 | unsigned ready:1; | 339 | unsigned ready:1; |
339 | unsigned endcleared:1; | 340 | unsigned endcleared:1; |
340 | unsigned update_flag; | 341 | unsigned update_flag; |
341 | unsigned ossfragshift; | 342 | unsigned ossfragshift; |
342 | int ossmaxfrags; | 343 | int ossmaxfrags; |
343 | unsigned subdivision; | 344 | unsigned subdivision; |
344 | 345 | ||
345 | } dmabuf; | 346 | } dmabuf; |
346 | 347 | ||
347 | /* 5.1 channels */ | 348 | /* 5.1 channels */ |
348 | struct trident_state *other_states[4]; | 349 | struct trident_state *other_states[4]; |
349 | int multi_channels_adjust_count; | 350 | int multi_channels_adjust_count; |
350 | unsigned chans_num; | 351 | unsigned chans_num; |
351 | unsigned long fmt_flag; | 352 | unsigned long fmt_flag; |
352 | /* Guard against mmap/write/read races */ | 353 | /* Guard against mmap/write/read races */ |
353 | struct mutex sem; | 354 | struct mutex sem; |
354 | 355 | ||
355 | }; | 356 | }; |
356 | 357 | ||
357 | /* hardware channels */ | 358 | /* hardware channels */ |
358 | struct trident_channel { | 359 | struct trident_channel { |
359 | int num; /* channel number */ | 360 | int num; /* channel number */ |
360 | u32 lba; /* Loop Begine Address, where dma buffer starts */ | 361 | u32 lba; /* Loop Begine Address, where dma buffer starts */ |
361 | u32 eso; /* End Sample Offset, wehre dma buffer ends */ | 362 | u32 eso; /* End Sample Offset, wehre dma buffer ends */ |
362 | /* (in the unit of samples) */ | 363 | /* (in the unit of samples) */ |
363 | u32 delta; /* delta value, sample rate / 48k for playback, */ | 364 | u32 delta; /* delta value, sample rate / 48k for playback, */ |
364 | /* 48k/sample rate for recording */ | 365 | /* 48k/sample rate for recording */ |
365 | u16 attribute; /* control where PCM data go and come */ | 366 | u16 attribute; /* control where PCM data go and come */ |
366 | u16 fm_vol; | 367 | u16 fm_vol; |
367 | u32 control; /* signed/unsigned, 8/16 bits, mono/stereo */ | 368 | u32 control; /* signed/unsigned, 8/16 bits, mono/stereo */ |
368 | }; | 369 | }; |
369 | 370 | ||
370 | struct trident_pcm_bank_address { | 371 | struct trident_pcm_bank_address { |
371 | u32 start; | 372 | u32 start; |
372 | u32 stop; | 373 | u32 stop; |
373 | u32 aint; | 374 | u32 aint; |
374 | u32 aint_en; | 375 | u32 aint_en; |
375 | }; | 376 | }; |
376 | 377 | ||
377 | static struct trident_pcm_bank_address bank_a_addrs = { | 378 | static struct trident_pcm_bank_address bank_a_addrs = { |
378 | T4D_START_A, | 379 | T4D_START_A, |
379 | T4D_STOP_A, | 380 | T4D_STOP_A, |
380 | T4D_AINT_A, | 381 | T4D_AINT_A, |
381 | T4D_AINTEN_A | 382 | T4D_AINTEN_A |
382 | }; | 383 | }; |
383 | 384 | ||
384 | static struct trident_pcm_bank_address bank_b_addrs = { | 385 | static struct trident_pcm_bank_address bank_b_addrs = { |
385 | T4D_START_B, | 386 | T4D_START_B, |
386 | T4D_STOP_B, | 387 | T4D_STOP_B, |
387 | T4D_AINT_B, | 388 | T4D_AINT_B, |
388 | T4D_AINTEN_B | 389 | T4D_AINTEN_B |
389 | }; | 390 | }; |
390 | 391 | ||
391 | struct trident_pcm_bank { | 392 | struct trident_pcm_bank { |
392 | /* register addresses to control bank operations */ | 393 | /* register addresses to control bank operations */ |
393 | struct trident_pcm_bank_address *addresses; | 394 | struct trident_pcm_bank_address *addresses; |
394 | /* each bank has 32 channels */ | 395 | /* each bank has 32 channels */ |
395 | u32 bitmap; /* channel allocation bitmap */ | 396 | u32 bitmap; /* channel allocation bitmap */ |
396 | struct trident_channel channels[32]; | 397 | struct trident_channel channels[32]; |
397 | }; | 398 | }; |
398 | 399 | ||
399 | struct trident_card { | 400 | struct trident_card { |
400 | unsigned int magic; | 401 | unsigned int magic; |
401 | 402 | ||
402 | /* We keep trident cards in a linked list */ | 403 | /* We keep trident cards in a linked list */ |
403 | struct trident_card *next; | 404 | struct trident_card *next; |
404 | 405 | ||
405 | /* single open lock mechanism, only used for recording */ | 406 | /* single open lock mechanism, only used for recording */ |
406 | struct mutex open_mutex; | 407 | struct mutex open_mutex; |
407 | 408 | ||
408 | /* The trident has a certain amount of cross channel interaction | 409 | /* The trident has a certain amount of cross channel interaction |
409 | so we use a single per card lock */ | 410 | so we use a single per card lock */ |
410 | spinlock_t lock; | 411 | spinlock_t lock; |
411 | 412 | ||
412 | /* PCI device stuff */ | 413 | /* PCI device stuff */ |
413 | struct pci_dev *pci_dev; | 414 | struct pci_dev *pci_dev; |
414 | u16 pci_id; | 415 | u16 pci_id; |
415 | u8 revision; | 416 | u8 revision; |
416 | 417 | ||
417 | /* soundcore stuff */ | 418 | /* soundcore stuff */ |
418 | int dev_audio; | 419 | int dev_audio; |
419 | 420 | ||
420 | /* structures for abstraction of hardware facilities, codecs, */ | 421 | /* structures for abstraction of hardware facilities, codecs, */ |
421 | /* banks and channels */ | 422 | /* banks and channels */ |
422 | struct ac97_codec *ac97_codec[NR_AC97]; | 423 | struct ac97_codec *ac97_codec[NR_AC97]; |
423 | struct trident_pcm_bank banks[NR_BANKS]; | 424 | struct trident_pcm_bank banks[NR_BANKS]; |
424 | struct trident_state *states[NR_HW_CH]; | 425 | struct trident_state *states[NR_HW_CH]; |
425 | 426 | ||
426 | /* hardware resources */ | 427 | /* hardware resources */ |
427 | unsigned long iobase; | 428 | unsigned long iobase; |
428 | u32 irq; | 429 | u32 irq; |
429 | 430 | ||
430 | /* Function support */ | 431 | /* Function support */ |
431 | struct trident_channel *(*alloc_pcm_channel) (struct trident_card *); | 432 | struct trident_channel *(*alloc_pcm_channel) (struct trident_card *); |
432 | struct trident_channel *(*alloc_rec_pcm_channel) (struct trident_card *); | 433 | struct trident_channel *(*alloc_rec_pcm_channel) (struct trident_card *); |
433 | void (*free_pcm_channel) (struct trident_card *, unsigned int chan); | 434 | void (*free_pcm_channel) (struct trident_card *, unsigned int chan); |
434 | void (*address_interrupt) (struct trident_card *); | 435 | void (*address_interrupt) (struct trident_card *); |
435 | 436 | ||
436 | /* Added by Matt Wu 01-05-2001 for spdif in */ | 437 | /* Added by Matt Wu 01-05-2001 for spdif in */ |
437 | int multi_channel_use_count; | 438 | int multi_channel_use_count; |
438 | int rec_channel_use_count; | 439 | int rec_channel_use_count; |
439 | u16 mixer_regs[64][NR_AC97]; /* Made card local by Alan */ | 440 | u16 mixer_regs[64][NR_AC97]; /* Made card local by Alan */ |
440 | int mixer_regs_ready; | 441 | int mixer_regs_ready; |
441 | 442 | ||
442 | /* Added for hardware volume control */ | 443 | /* Added for hardware volume control */ |
443 | int hwvolctl; | 444 | int hwvolctl; |
444 | struct timer_list timer; | 445 | struct timer_list timer; |
445 | 446 | ||
446 | /* Game port support */ | 447 | /* Game port support */ |
447 | struct gameport *gameport; | 448 | struct gameport *gameport; |
448 | }; | 449 | }; |
449 | 450 | ||
450 | enum dmabuf_mode { | 451 | enum dmabuf_mode { |
451 | DM_PLAYBACK = 0, | 452 | DM_PLAYBACK = 0, |
452 | DM_RECORD | 453 | DM_RECORD |
453 | }; | 454 | }; |
454 | 455 | ||
455 | /* table to map from CHANNELMASK to channel attribute for SiS 7018 */ | 456 | /* table to map from CHANNELMASK to channel attribute for SiS 7018 */ |
456 | static u16 mask2attr[] = { | 457 | static u16 mask2attr[] = { |
457 | PCM_LR, PCM_LR, SURR_LR, CENTER_LFE, | 458 | PCM_LR, PCM_LR, SURR_LR, CENTER_LFE, |
458 | HSET, MIC, MODEM_LINE1, MODEM_LINE2, | 459 | HSET, MIC, MODEM_LINE1, MODEM_LINE2, |
459 | I2S_LR, SPDIF_LR | 460 | I2S_LR, SPDIF_LR |
460 | }; | 461 | }; |
461 | 462 | ||
462 | /* table to map from channel attribute to CHANNELMASK for SiS 7018 */ | 463 | /* table to map from channel attribute to CHANNELMASK for SiS 7018 */ |
463 | static int attr2mask[] = { | 464 | static int attr2mask[] = { |
464 | DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET, | 465 | DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET, |
465 | DSP_BIND_I2S, DSP_BIND_CENTER_LFE, DSP_BIND_SURR, DSP_BIND_SPDIF | 466 | DSP_BIND_I2S, DSP_BIND_CENTER_LFE, DSP_BIND_SURR, DSP_BIND_SPDIF |
466 | }; | 467 | }; |
467 | 468 | ||
468 | /* Added by Matt Wu 01-05-2001 for spdif in */ | 469 | /* Added by Matt Wu 01-05-2001 for spdif in */ |
469 | static int ali_close_multi_channels(void); | 470 | static int ali_close_multi_channels(void); |
470 | static void ali_delay(struct trident_card *card, int interval); | 471 | static void ali_delay(struct trident_card *card, int interval); |
471 | static void ali_detect_spdif_rate(struct trident_card *card); | 472 | static void ali_detect_spdif_rate(struct trident_card *card); |
472 | 473 | ||
473 | static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val); | 474 | static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val); |
474 | static u16 ali_ac97_read(struct ac97_codec *codec, u8 reg); | 475 | static u16 ali_ac97_read(struct ac97_codec *codec, u8 reg); |
475 | 476 | ||
476 | static struct trident_card *devs; | 477 | static struct trident_card *devs; |
477 | 478 | ||
478 | static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val); | 479 | static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val); |
479 | static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg); | 480 | static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg); |
480 | 481 | ||
481 | static int trident_open_mixdev(struct inode *inode, struct file *file); | 482 | static int trident_open_mixdev(struct inode *inode, struct file *file); |
482 | static int trident_ioctl_mixdev(struct inode *inode, struct file *file, | 483 | static int trident_ioctl_mixdev(struct inode *inode, struct file *file, |
483 | unsigned int cmd, unsigned long arg); | 484 | unsigned int cmd, unsigned long arg); |
484 | 485 | ||
485 | static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val); | 486 | static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val); |
486 | static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg); | 487 | static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg); |
487 | static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate); | 488 | static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate); |
488 | static void ali_enable_special_channel(struct trident_state *stat); | 489 | static void ali_enable_special_channel(struct trident_state *stat); |
489 | static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card); | 490 | static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card); |
490 | static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card); | 491 | static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card); |
491 | static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel); | 492 | static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel); |
492 | static int ali_setup_multi_channels(struct trident_card *card, int chan_nums); | 493 | static int ali_setup_multi_channels(struct trident_card *card, int chan_nums); |
493 | static unsigned int ali_get_spdif_in_rate(struct trident_card *card); | 494 | static unsigned int ali_get_spdif_in_rate(struct trident_card *card); |
494 | static void ali_setup_spdif_in(struct trident_card *card); | 495 | static void ali_setup_spdif_in(struct trident_card *card); |
495 | static void ali_disable_spdif_in(struct trident_card *card); | 496 | static void ali_disable_spdif_in(struct trident_card *card); |
496 | static void ali_disable_special_channel(struct trident_card *card, int ch); | 497 | static void ali_disable_special_channel(struct trident_card *card, int ch); |
497 | static void ali_setup_spdif_out(struct trident_card *card, int flag); | 498 | static void ali_setup_spdif_out(struct trident_card *card, int flag); |
498 | static int ali_write_5_1(struct trident_state *state, | 499 | static int ali_write_5_1(struct trident_state *state, |
499 | const char __user *buffer, | 500 | const char __user *buffer, |
500 | int cnt_for_multi_channel, unsigned int *copy_count, | 501 | int cnt_for_multi_channel, unsigned int *copy_count, |
501 | unsigned int *state_cnt); | 502 | unsigned int *state_cnt); |
502 | static int ali_allocate_other_states_resources(struct trident_state *state, | 503 | static int ali_allocate_other_states_resources(struct trident_state *state, |
503 | int chan_nums); | 504 | int chan_nums); |
504 | static void ali_free_other_states_resources(struct trident_state *state); | 505 | static void ali_free_other_states_resources(struct trident_state *state); |
505 | 506 | ||
506 | #define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) do { \ | 507 | #define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) do { \ |
507 | (dma_ptr) += (offset); \ | 508 | (dma_ptr) += (offset); \ |
508 | (buffer) += (offset); \ | 509 | (buffer) += (offset); \ |
509 | (cnt) -= (offset); \ | 510 | (cnt) -= (offset); \ |
510 | (copy_count) += (offset); \ | 511 | (copy_count) += (offset); \ |
511 | } while (0) | 512 | } while (0) |
512 | 513 | ||
513 | static inline int lock_set_fmt(struct trident_state* state) | 514 | static inline int lock_set_fmt(struct trident_state* state) |
514 | { | 515 | { |
515 | if (test_and_set_bit(0, &state->fmt_flag)) | 516 | if (test_and_set_bit(0, &state->fmt_flag)) |
516 | return -EFAULT; | 517 | return -EFAULT; |
517 | 518 | ||
518 | return 0; | 519 | return 0; |
519 | } | 520 | } |
520 | 521 | ||
521 | static inline void unlock_set_fmt(struct trident_state* state) | 522 | static inline void unlock_set_fmt(struct trident_state* state) |
522 | { | 523 | { |
523 | clear_bit(0, &state->fmt_flag); | 524 | clear_bit(0, &state->fmt_flag); |
524 | } | 525 | } |
525 | 526 | ||
526 | static int | 527 | static int |
527 | trident_enable_loop_interrupts(struct trident_card *card) | 528 | trident_enable_loop_interrupts(struct trident_card *card) |
528 | { | 529 | { |
529 | u32 global_control; | 530 | u32 global_control; |
530 | 531 | ||
531 | global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR)); | 532 | global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR)); |
532 | 533 | ||
533 | switch (card->pci_id) { | 534 | switch (card->pci_id) { |
534 | case PCI_DEVICE_ID_SI_7018: | 535 | case PCI_DEVICE_ID_SI_7018: |
535 | global_control |= (ENDLP_IE | MIDLP_IE | BANK_B_EN); | 536 | global_control |= (ENDLP_IE | MIDLP_IE | BANK_B_EN); |
536 | break; | 537 | break; |
537 | case PCI_DEVICE_ID_ALI_5451: | 538 | case PCI_DEVICE_ID_ALI_5451: |
538 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | 539 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: |
539 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | 540 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: |
540 | case PCI_DEVICE_ID_INTERG_5050: | 541 | case PCI_DEVICE_ID_INTERG_5050: |
541 | global_control |= (ENDLP_IE | MIDLP_IE); | 542 | global_control |= (ENDLP_IE | MIDLP_IE); |
542 | break; | 543 | break; |
543 | default: | 544 | default: |
544 | return 0; | 545 | return 0; |
545 | } | 546 | } |
546 | 547 | ||
547 | outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); | 548 | outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); |
548 | 549 | ||
549 | pr_debug("trident: Enable Loop Interrupts, globctl = 0x%08X\n", | 550 | pr_debug("trident: Enable Loop Interrupts, globctl = 0x%08X\n", |
550 | inl(TRID_REG(card, T4D_LFO_GC_CIR))); | 551 | inl(TRID_REG(card, T4D_LFO_GC_CIR))); |
551 | 552 | ||
552 | return 1; | 553 | return 1; |
553 | } | 554 | } |
554 | 555 | ||
555 | static int | 556 | static int |
556 | trident_disable_loop_interrupts(struct trident_card *card) | 557 | trident_disable_loop_interrupts(struct trident_card *card) |
557 | { | 558 | { |
558 | u32 global_control; | 559 | u32 global_control; |
559 | 560 | ||
560 | global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR)); | 561 | global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR)); |
561 | global_control &= ~(ENDLP_IE | MIDLP_IE); | 562 | global_control &= ~(ENDLP_IE | MIDLP_IE); |
562 | outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); | 563 | outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); |
563 | 564 | ||
564 | pr_debug("trident: Disabled Loop Interrupts, globctl = 0x%08X\n", | 565 | pr_debug("trident: Disabled Loop Interrupts, globctl = 0x%08X\n", |
565 | global_control); | 566 | global_control); |
566 | 567 | ||
567 | return 1; | 568 | return 1; |
568 | } | 569 | } |
569 | 570 | ||
570 | static void | 571 | static void |
571 | trident_enable_voice_irq(struct trident_card *card, unsigned int channel) | 572 | trident_enable_voice_irq(struct trident_card *card, unsigned int channel) |
572 | { | 573 | { |
573 | unsigned int mask = 1 << (channel & 0x1f); | 574 | unsigned int mask = 1 << (channel & 0x1f); |
574 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | 575 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; |
575 | u32 reg, addr = bank->addresses->aint_en; | 576 | u32 reg, addr = bank->addresses->aint_en; |
576 | 577 | ||
577 | reg = inl(TRID_REG(card, addr)); | 578 | reg = inl(TRID_REG(card, addr)); |
578 | reg |= mask; | 579 | reg |= mask; |
579 | outl(reg, TRID_REG(card, addr)); | 580 | outl(reg, TRID_REG(card, addr)); |
580 | 581 | ||
581 | #ifdef DEBUG | 582 | #ifdef DEBUG |
582 | reg = inl(TRID_REG(card, addr)); | 583 | reg = inl(TRID_REG(card, addr)); |
583 | pr_debug("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", | 584 | pr_debug("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", |
584 | channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A", | 585 | channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A", |
585 | reg, addr); | 586 | reg, addr); |
586 | #endif /* DEBUG */ | 587 | #endif /* DEBUG */ |
587 | } | 588 | } |
588 | 589 | ||
589 | static void | 590 | static void |
590 | trident_disable_voice_irq(struct trident_card *card, unsigned int channel) | 591 | trident_disable_voice_irq(struct trident_card *card, unsigned int channel) |
591 | { | 592 | { |
592 | unsigned int mask = 1 << (channel & 0x1f); | 593 | unsigned int mask = 1 << (channel & 0x1f); |
593 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | 594 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; |
594 | u32 reg, addr = bank->addresses->aint_en; | 595 | u32 reg, addr = bank->addresses->aint_en; |
595 | 596 | ||
596 | reg = inl(TRID_REG(card, addr)); | 597 | reg = inl(TRID_REG(card, addr)); |
597 | reg &= ~mask; | 598 | reg &= ~mask; |
598 | outl(reg, TRID_REG(card, addr)); | 599 | outl(reg, TRID_REG(card, addr)); |
599 | 600 | ||
600 | /* Ack the channel in case the interrupt was set before we disable it. */ | 601 | /* Ack the channel in case the interrupt was set before we disable it. */ |
601 | outl(mask, TRID_REG(card, bank->addresses->aint)); | 602 | outl(mask, TRID_REG(card, bank->addresses->aint)); |
602 | 603 | ||
603 | #ifdef DEBUG | 604 | #ifdef DEBUG |
604 | reg = inl(TRID_REG(card, addr)); | 605 | reg = inl(TRID_REG(card, addr)); |
605 | pr_debug("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", | 606 | pr_debug("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", |
606 | channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A", | 607 | channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A", |
607 | reg, addr); | 608 | reg, addr); |
608 | #endif /* DEBUG */ | 609 | #endif /* DEBUG */ |
609 | } | 610 | } |
610 | 611 | ||
611 | static void | 612 | static void |
612 | trident_start_voice(struct trident_card *card, unsigned int channel) | 613 | trident_start_voice(struct trident_card *card, unsigned int channel) |
613 | { | 614 | { |
614 | unsigned int mask = 1 << (channel & 0x1f); | 615 | unsigned int mask = 1 << (channel & 0x1f); |
615 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | 616 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; |
616 | u32 addr = bank->addresses->start; | 617 | u32 addr = bank->addresses->start; |
617 | 618 | ||
618 | #ifdef DEBUG | 619 | #ifdef DEBUG |
619 | u32 reg; | 620 | u32 reg; |
620 | #endif /* DEBUG */ | 621 | #endif /* DEBUG */ |
621 | 622 | ||
622 | outl(mask, TRID_REG(card, addr)); | 623 | outl(mask, TRID_REG(card, addr)); |
623 | 624 | ||
624 | #ifdef DEBUG | 625 | #ifdef DEBUG |
625 | reg = inl(TRID_REG(card, addr)); | 626 | reg = inl(TRID_REG(card, addr)); |
626 | pr_debug("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", | 627 | pr_debug("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", |
627 | channel, addr == T4D_START_B ? "START_B" : "START_A", | 628 | channel, addr == T4D_START_B ? "START_B" : "START_A", |
628 | reg, addr); | 629 | reg, addr); |
629 | #endif /* DEBUG */ | 630 | #endif /* DEBUG */ |
630 | } | 631 | } |
631 | 632 | ||
632 | static void | 633 | static void |
633 | trident_stop_voice(struct trident_card *card, unsigned int channel) | 634 | trident_stop_voice(struct trident_card *card, unsigned int channel) |
634 | { | 635 | { |
635 | unsigned int mask = 1 << (channel & 0x1f); | 636 | unsigned int mask = 1 << (channel & 0x1f); |
636 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | 637 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; |
637 | u32 addr = bank->addresses->stop; | 638 | u32 addr = bank->addresses->stop; |
638 | 639 | ||
639 | #ifdef DEBUG | 640 | #ifdef DEBUG |
640 | u32 reg; | 641 | u32 reg; |
641 | #endif /* DEBUG */ | 642 | #endif /* DEBUG */ |
642 | 643 | ||
643 | outl(mask, TRID_REG(card, addr)); | 644 | outl(mask, TRID_REG(card, addr)); |
644 | 645 | ||
645 | #ifdef DEBUG | 646 | #ifdef DEBUG |
646 | reg = inl(TRID_REG(card, addr)); | 647 | reg = inl(TRID_REG(card, addr)); |
647 | pr_debug("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", | 648 | pr_debug("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", |
648 | channel, addr == T4D_STOP_B ? "STOP_B" : "STOP_A", | 649 | channel, addr == T4D_STOP_B ? "STOP_B" : "STOP_A", |
649 | reg, addr); | 650 | reg, addr); |
650 | #endif /* DEBUG */ | 651 | #endif /* DEBUG */ |
651 | } | 652 | } |
652 | 653 | ||
653 | static u32 | 654 | static u32 |
654 | trident_get_interrupt_mask(struct trident_card *card, unsigned int channel) | 655 | trident_get_interrupt_mask(struct trident_card *card, unsigned int channel) |
655 | { | 656 | { |
656 | struct trident_pcm_bank *bank = &card->banks[channel]; | 657 | struct trident_pcm_bank *bank = &card->banks[channel]; |
657 | u32 addr = bank->addresses->aint; | 658 | u32 addr = bank->addresses->aint; |
658 | return inl(TRID_REG(card, addr)); | 659 | return inl(TRID_REG(card, addr)); |
659 | } | 660 | } |
660 | 661 | ||
661 | static int | 662 | static int |
662 | trident_check_channel_interrupt(struct trident_card *card, unsigned int channel) | 663 | trident_check_channel_interrupt(struct trident_card *card, unsigned int channel) |
663 | { | 664 | { |
664 | unsigned int mask = 1 << (channel & 0x1f); | 665 | unsigned int mask = 1 << (channel & 0x1f); |
665 | u32 reg = trident_get_interrupt_mask(card, channel >> 5); | 666 | u32 reg = trident_get_interrupt_mask(card, channel >> 5); |
666 | 667 | ||
667 | #ifdef DEBUG | 668 | #ifdef DEBUG |
668 | if (reg & mask) | 669 | if (reg & mask) |
669 | pr_debug("trident: channel %d has interrupt, %s = 0x%08x\n", | 670 | pr_debug("trident: channel %d has interrupt, %s = 0x%08x\n", |
670 | channel, reg == T4D_AINT_B ? "AINT_B" : "AINT_A", | 671 | channel, reg == T4D_AINT_B ? "AINT_B" : "AINT_A", |
671 | reg); | 672 | reg); |
672 | #endif /* DEBUG */ | 673 | #endif /* DEBUG */ |
673 | return (reg & mask) ? 1 : 0; | 674 | return (reg & mask) ? 1 : 0; |
674 | } | 675 | } |
675 | 676 | ||
676 | static void | 677 | static void |
677 | trident_ack_channel_interrupt(struct trident_card *card, unsigned int channel) | 678 | trident_ack_channel_interrupt(struct trident_card *card, unsigned int channel) |
678 | { | 679 | { |
679 | unsigned int mask = 1 << (channel & 0x1f); | 680 | unsigned int mask = 1 << (channel & 0x1f); |
680 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | 681 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; |
681 | u32 reg, addr = bank->addresses->aint; | 682 | u32 reg, addr = bank->addresses->aint; |
682 | 683 | ||
683 | reg = inl(TRID_REG(card, addr)); | 684 | reg = inl(TRID_REG(card, addr)); |
684 | reg &= mask; | 685 | reg &= mask; |
685 | outl(reg, TRID_REG(card, addr)); | 686 | outl(reg, TRID_REG(card, addr)); |
686 | 687 | ||
687 | #ifdef DEBUG | 688 | #ifdef DEBUG |
688 | reg = inl(TRID_REG(card, T4D_AINT_B)); | 689 | reg = inl(TRID_REG(card, T4D_AINT_B)); |
689 | pr_debug("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n", | 690 | pr_debug("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n", |
690 | channel, reg); | 691 | channel, reg); |
691 | #endif /* DEBUG */ | 692 | #endif /* DEBUG */ |
692 | } | 693 | } |
693 | 694 | ||
694 | static struct trident_channel * | 695 | static struct trident_channel * |
695 | trident_alloc_pcm_channel(struct trident_card *card) | 696 | trident_alloc_pcm_channel(struct trident_card *card) |
696 | { | 697 | { |
697 | struct trident_pcm_bank *bank; | 698 | struct trident_pcm_bank *bank; |
698 | int idx; | 699 | int idx; |
699 | 700 | ||
700 | bank = &card->banks[BANK_B]; | 701 | bank = &card->banks[BANK_B]; |
701 | 702 | ||
702 | for (idx = 31; idx >= 0; idx--) { | 703 | for (idx = 31; idx >= 0; idx--) { |
703 | if (!(bank->bitmap & (1 << idx))) { | 704 | if (!(bank->bitmap & (1 << idx))) { |
704 | struct trident_channel *channel = &bank->channels[idx]; | 705 | struct trident_channel *channel = &bank->channels[idx]; |
705 | bank->bitmap |= 1 << idx; | 706 | bank->bitmap |= 1 << idx; |
706 | channel->num = idx + 32; | 707 | channel->num = idx + 32; |
707 | return channel; | 708 | return channel; |
708 | } | 709 | } |
709 | } | 710 | } |
710 | 711 | ||
711 | /* no more free channels available */ | 712 | /* no more free channels available */ |
712 | printk(KERN_ERR "trident: no more channels available on Bank B.\n"); | 713 | printk(KERN_ERR "trident: no more channels available on Bank B.\n"); |
713 | return NULL; | 714 | return NULL; |
714 | } | 715 | } |
715 | 716 | ||
716 | static void | 717 | static void |
717 | trident_free_pcm_channel(struct trident_card *card, unsigned int channel) | 718 | trident_free_pcm_channel(struct trident_card *card, unsigned int channel) |
718 | { | 719 | { |
719 | int bank; | 720 | int bank; |
720 | unsigned char b; | 721 | unsigned char b; |
721 | 722 | ||
722 | if (channel < 31 || channel > 63) | 723 | if (channel < 31 || channel > 63) |
723 | return; | 724 | return; |
724 | 725 | ||
725 | if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX || | 726 | if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX || |
726 | card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) { | 727 | card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) { |
727 | b = inb(TRID_REG(card, T4D_REC_CH)); | 728 | b = inb(TRID_REG(card, T4D_REC_CH)); |
728 | if ((b & ~0x80) == channel) | 729 | if ((b & ~0x80) == channel) |
729 | outb(0x0, TRID_REG(card, T4D_REC_CH)); | 730 | outb(0x0, TRID_REG(card, T4D_REC_CH)); |
730 | } | 731 | } |
731 | 732 | ||
732 | bank = channel >> 5; | 733 | bank = channel >> 5; |
733 | channel = channel & 0x1f; | 734 | channel = channel & 0x1f; |
734 | 735 | ||
735 | card->banks[bank].bitmap &= ~(1 << (channel)); | 736 | card->banks[bank].bitmap &= ~(1 << (channel)); |
736 | } | 737 | } |
737 | 738 | ||
738 | static struct trident_channel * | 739 | static struct trident_channel * |
739 | cyber_alloc_pcm_channel(struct trident_card *card) | 740 | cyber_alloc_pcm_channel(struct trident_card *card) |
740 | { | 741 | { |
741 | struct trident_pcm_bank *bank; | 742 | struct trident_pcm_bank *bank; |
742 | int idx; | 743 | int idx; |
743 | 744 | ||
744 | /* The cyberpro 5050 has only 32 voices and one bank */ | 745 | /* The cyberpro 5050 has only 32 voices and one bank */ |
745 | /* .. at least they are not documented (if you want to call that | 746 | /* .. at least they are not documented (if you want to call that |
746 | * crap documentation), perhaps broken ? */ | 747 | * crap documentation), perhaps broken ? */ |
747 | 748 | ||
748 | bank = &card->banks[BANK_A]; | 749 | bank = &card->banks[BANK_A]; |
749 | 750 | ||
750 | for (idx = 31; idx >= 0; idx--) { | 751 | for (idx = 31; idx >= 0; idx--) { |
751 | if (!(bank->bitmap & (1 << idx))) { | 752 | if (!(bank->bitmap & (1 << idx))) { |
752 | struct trident_channel *channel = &bank->channels[idx]; | 753 | struct trident_channel *channel = &bank->channels[idx]; |
753 | bank->bitmap |= 1 << idx; | 754 | bank->bitmap |= 1 << idx; |
754 | channel->num = idx; | 755 | channel->num = idx; |
755 | return channel; | 756 | return channel; |
756 | } | 757 | } |
757 | } | 758 | } |
758 | 759 | ||
759 | /* no more free channels available */ | 760 | /* no more free channels available */ |
760 | printk(KERN_ERR "cyberpro5050: no more channels available on Bank A.\n"); | 761 | printk(KERN_ERR "cyberpro5050: no more channels available on Bank A.\n"); |
761 | return NULL; | 762 | return NULL; |
762 | } | 763 | } |
763 | 764 | ||
764 | static void | 765 | static void |
765 | cyber_free_pcm_channel(struct trident_card *card, unsigned int channel) | 766 | cyber_free_pcm_channel(struct trident_card *card, unsigned int channel) |
766 | { | 767 | { |
767 | if (channel > 31) | 768 | if (channel > 31) |
768 | return; | 769 | return; |
769 | card->banks[BANK_A].bitmap &= ~(1 << (channel)); | 770 | card->banks[BANK_A].bitmap &= ~(1 << (channel)); |
770 | } | 771 | } |
771 | 772 | ||
772 | static inline void | 773 | static inline void |
773 | cyber_outidx(int port, int idx, int data) | 774 | cyber_outidx(int port, int idx, int data) |
774 | { | 775 | { |
775 | outb(idx, port); | 776 | outb(idx, port); |
776 | outb(data, port + 1); | 777 | outb(data, port + 1); |
777 | } | 778 | } |
778 | 779 | ||
779 | static inline int | 780 | static inline int |
780 | cyber_inidx(int port, int idx) | 781 | cyber_inidx(int port, int idx) |
781 | { | 782 | { |
782 | outb(idx, port); | 783 | outb(idx, port); |
783 | return inb(port + 1); | 784 | return inb(port + 1); |
784 | } | 785 | } |
785 | 786 | ||
786 | static int | 787 | static int |
787 | cyber_init_ritual(struct trident_card *card) | 788 | cyber_init_ritual(struct trident_card *card) |
788 | { | 789 | { |
789 | /* some black magic, taken from SDK samples */ | 790 | /* some black magic, taken from SDK samples */ |
790 | /* remove this and nothing will work */ | 791 | /* remove this and nothing will work */ |
791 | int portDat; | 792 | int portDat; |
792 | int ret = 0; | 793 | int ret = 0; |
793 | unsigned long flags; | 794 | unsigned long flags; |
794 | 795 | ||
795 | /* | 796 | /* |
796 | * Keep interrupts off for the configure - we don't want to | 797 | * Keep interrupts off for the configure - we don't want to |
797 | * clash with another cyberpro config event | 798 | * clash with another cyberpro config event |
798 | */ | 799 | */ |
799 | 800 | ||
800 | spin_lock_irqsave(&card->lock, flags); | 801 | spin_lock_irqsave(&card->lock, flags); |
801 | portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); | 802 | portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); |
802 | /* enable, if it was disabled */ | 803 | /* enable, if it was disabled */ |
803 | if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) { | 804 | if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) { |
804 | printk(KERN_INFO "cyberpro5050: enabling audio controller\n"); | 805 | printk(KERN_INFO "cyberpro5050: enabling audio controller\n"); |
805 | cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE, | 806 | cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE, |
806 | portDat | CYBER_BMSK_AUENZ_ENABLE); | 807 | portDat | CYBER_BMSK_AUENZ_ENABLE); |
807 | /* check again if hardware is enabled now */ | 808 | /* check again if hardware is enabled now */ |
808 | portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); | 809 | portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); |
809 | } | 810 | } |
810 | if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) { | 811 | if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) { |
811 | printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n"); | 812 | printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n"); |
812 | ret = -1; | 813 | ret = -1; |
813 | } else { | 814 | } else { |
814 | cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE, | 815 | cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE, |
815 | CYBER_BMSK_AUDIO_INT_ENABLE); | 816 | CYBER_BMSK_AUDIO_INT_ENABLE); |
816 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01); | 817 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01); |
817 | cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20); | 818 | cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20); |
818 | cyber_outidx(CYBER_PORT_AUDIO, 0xbb, 0x08); | 819 | cyber_outidx(CYBER_PORT_AUDIO, 0xbb, 0x08); |
819 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x02); | 820 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x02); |
820 | cyber_outidx(CYBER_PORT_AUDIO, 0xb3, 0x06); | 821 | cyber_outidx(CYBER_PORT_AUDIO, 0xb3, 0x06); |
821 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x00); | 822 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x00); |
822 | } | 823 | } |
823 | spin_unlock_irqrestore(&card->lock, flags); | 824 | spin_unlock_irqrestore(&card->lock, flags); |
824 | return ret; | 825 | return ret; |
825 | } | 826 | } |
826 | 827 | ||
827 | /* called with spin lock held */ | 828 | /* called with spin lock held */ |
828 | 829 | ||
829 | static int | 830 | static int |
830 | trident_load_channel_registers(struct trident_card *card, u32 * data, | 831 | trident_load_channel_registers(struct trident_card *card, u32 * data, |
831 | unsigned int channel) | 832 | unsigned int channel) |
832 | { | 833 | { |
833 | int i; | 834 | int i; |
834 | 835 | ||
835 | if (channel > 63) | 836 | if (channel > 63) |
836 | return 0; | 837 | return 0; |
837 | 838 | ||
838 | /* select hardware channel to write */ | 839 | /* select hardware channel to write */ |
839 | outb(channel, TRID_REG(card, T4D_LFO_GC_CIR)); | 840 | outb(channel, TRID_REG(card, T4D_LFO_GC_CIR)); |
840 | 841 | ||
841 | /* Output the channel registers, but don't write register | 842 | /* Output the channel registers, but don't write register |
842 | three to an ALI chip. */ | 843 | three to an ALI chip. */ |
843 | for (i = 0; i < CHANNEL_REGS; i++) { | 844 | for (i = 0; i < CHANNEL_REGS; i++) { |
844 | if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451) | 845 | if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451) |
845 | continue; | 846 | continue; |
846 | outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i)); | 847 | outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i)); |
847 | } | 848 | } |
848 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451 || | 849 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451 || |
849 | card->pci_id == PCI_DEVICE_ID_INTERG_5050) { | 850 | card->pci_id == PCI_DEVICE_ID_INTERG_5050) { |
850 | outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1)); | 851 | outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1)); |
851 | outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2)); | 852 | outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2)); |
852 | } | 853 | } |
853 | return 1; | 854 | return 1; |
854 | } | 855 | } |
855 | 856 | ||
856 | /* called with spin lock held */ | 857 | /* called with spin lock held */ |
857 | static int | 858 | static int |
858 | trident_write_voice_regs(struct trident_state *state) | 859 | trident_write_voice_regs(struct trident_state *state) |
859 | { | 860 | { |
860 | unsigned int data[CHANNEL_REGS + 1]; | 861 | unsigned int data[CHANNEL_REGS + 1]; |
861 | struct trident_channel *channel; | 862 | struct trident_channel *channel; |
862 | 863 | ||
863 | channel = state->dmabuf.channel; | 864 | channel = state->dmabuf.channel; |
864 | 865 | ||
865 | data[1] = channel->lba; | 866 | data[1] = channel->lba; |
866 | data[4] = channel->control; | 867 | data[4] = channel->control; |
867 | 868 | ||
868 | switch (state->card->pci_id) { | 869 | switch (state->card->pci_id) { |
869 | case PCI_DEVICE_ID_ALI_5451: | 870 | case PCI_DEVICE_ID_ALI_5451: |
870 | data[0] = 0; /* Current Sample Offset */ | 871 | data[0] = 0; /* Current Sample Offset */ |
871 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); | 872 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); |
872 | data[3] = 0; | 873 | data[3] = 0; |
873 | break; | 874 | break; |
874 | case PCI_DEVICE_ID_SI_7018: | 875 | case PCI_DEVICE_ID_SI_7018: |
875 | case PCI_DEVICE_ID_INTERG_5050: | 876 | case PCI_DEVICE_ID_INTERG_5050: |
876 | data[0] = 0; /* Current Sample Offset */ | 877 | data[0] = 0; /* Current Sample Offset */ |
877 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); | 878 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); |
878 | data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff); | 879 | data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff); |
879 | break; | 880 | break; |
880 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | 881 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: |
881 | data[0] = 0; /* Current Sample Offset */ | 882 | data[0] = 0; /* Current Sample Offset */ |
882 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); | 883 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); |
883 | data[3] = channel->fm_vol & 0xffff; | 884 | data[3] = channel->fm_vol & 0xffff; |
884 | break; | 885 | break; |
885 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | 886 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: |
886 | data[0] = (channel->delta << 24); | 887 | data[0] = (channel->delta << 24); |
887 | data[2] = ((channel->delta << 16) & 0xff000000) | | 888 | data[2] = ((channel->delta << 16) & 0xff000000) | |
888 | (channel->eso & 0x00ffffff); | 889 | (channel->eso & 0x00ffffff); |
889 | data[3] = channel->fm_vol & 0xffff; | 890 | data[3] = channel->fm_vol & 0xffff; |
890 | break; | 891 | break; |
891 | default: | 892 | default: |
892 | return 0; | 893 | return 0; |
893 | } | 894 | } |
894 | 895 | ||
895 | return trident_load_channel_registers(state->card, data, channel->num); | 896 | return trident_load_channel_registers(state->card, data, channel->num); |
896 | } | 897 | } |
897 | 898 | ||
898 | static int | 899 | static int |
899 | compute_rate_play(u32 rate) | 900 | compute_rate_play(u32 rate) |
900 | { | 901 | { |
901 | int delta; | 902 | int delta; |
902 | /* We special case 44100 and 8000 since rounding with the equation | 903 | /* We special case 44100 and 8000 since rounding with the equation |
903 | does not give us an accurate enough value. For 11025 and 22050 | 904 | does not give us an accurate enough value. For 11025 and 22050 |
904 | the equation gives us the best answer. All other frequencies will | 905 | the equation gives us the best answer. All other frequencies will |
905 | also use the equation. JDW */ | 906 | also use the equation. JDW */ |
906 | if (rate == 44100) | 907 | if (rate == 44100) |
907 | delta = 0xeb3; | 908 | delta = 0xeb3; |
908 | else if (rate == 8000) | 909 | else if (rate == 8000) |
909 | delta = 0x2ab; | 910 | delta = 0x2ab; |
910 | else if (rate == 48000) | 911 | else if (rate == 48000) |
911 | delta = 0x1000; | 912 | delta = 0x1000; |
912 | else | 913 | else |
913 | delta = (((rate << 12) + rate) / 48000) & 0x0000ffff; | 914 | delta = (((rate << 12) + rate) / 48000) & 0x0000ffff; |
914 | return delta; | 915 | return delta; |
915 | } | 916 | } |
916 | 917 | ||
917 | static int | 918 | static int |
918 | compute_rate_rec(u32 rate) | 919 | compute_rate_rec(u32 rate) |
919 | { | 920 | { |
920 | int delta; | 921 | int delta; |
921 | 922 | ||
922 | if (rate == 44100) | 923 | if (rate == 44100) |
923 | delta = 0x116a; | 924 | delta = 0x116a; |
924 | else if (rate == 8000) | 925 | else if (rate == 8000) |
925 | delta = 0x6000; | 926 | delta = 0x6000; |
926 | else if (rate == 48000) | 927 | else if (rate == 48000) |
927 | delta = 0x1000; | 928 | delta = 0x1000; |
928 | else | 929 | else |
929 | delta = ((48000 << 12) / rate) & 0x0000ffff; | 930 | delta = ((48000 << 12) / rate) & 0x0000ffff; |
930 | 931 | ||
931 | return delta; | 932 | return delta; |
932 | } | 933 | } |
933 | 934 | ||
934 | /* set playback sample rate */ | 935 | /* set playback sample rate */ |
935 | static unsigned int | 936 | static unsigned int |
936 | trident_set_dac_rate(struct trident_state *state, unsigned int rate) | 937 | trident_set_dac_rate(struct trident_state *state, unsigned int rate) |
937 | { | 938 | { |
938 | struct dmabuf *dmabuf = &state->dmabuf; | 939 | struct dmabuf *dmabuf = &state->dmabuf; |
939 | 940 | ||
940 | if (rate > 48000) | 941 | if (rate > 48000) |
941 | rate = 48000; | 942 | rate = 48000; |
942 | if (rate < 4000) | 943 | if (rate < 4000) |
943 | rate = 4000; | 944 | rate = 4000; |
944 | 945 | ||
945 | dmabuf->rate = rate; | 946 | dmabuf->rate = rate; |
946 | dmabuf->channel->delta = compute_rate_play(rate); | 947 | dmabuf->channel->delta = compute_rate_play(rate); |
947 | 948 | ||
948 | trident_write_voice_regs(state); | 949 | trident_write_voice_regs(state); |
949 | 950 | ||
950 | pr_debug("trident: called trident_set_dac_rate : rate = %d\n", rate); | 951 | pr_debug("trident: called trident_set_dac_rate : rate = %d\n", rate); |
951 | 952 | ||
952 | return rate; | 953 | return rate; |
953 | } | 954 | } |
954 | 955 | ||
955 | /* set recording sample rate */ | 956 | /* set recording sample rate */ |
956 | static unsigned int | 957 | static unsigned int |
957 | trident_set_adc_rate(struct trident_state *state, unsigned int rate) | 958 | trident_set_adc_rate(struct trident_state *state, unsigned int rate) |
958 | { | 959 | { |
959 | struct dmabuf *dmabuf = &state->dmabuf; | 960 | struct dmabuf *dmabuf = &state->dmabuf; |
960 | 961 | ||
961 | if (rate > 48000) | 962 | if (rate > 48000) |
962 | rate = 48000; | 963 | rate = 48000; |
963 | if (rate < 4000) | 964 | if (rate < 4000) |
964 | rate = 4000; | 965 | rate = 4000; |
965 | 966 | ||
966 | dmabuf->rate = rate; | 967 | dmabuf->rate = rate; |
967 | dmabuf->channel->delta = compute_rate_rec(rate); | 968 | dmabuf->channel->delta = compute_rate_rec(rate); |
968 | 969 | ||
969 | trident_write_voice_regs(state); | 970 | trident_write_voice_regs(state); |
970 | 971 | ||
971 | pr_debug("trident: called trident_set_adc_rate : rate = %d\n", rate); | 972 | pr_debug("trident: called trident_set_adc_rate : rate = %d\n", rate); |
972 | 973 | ||
973 | return rate; | 974 | return rate; |
974 | } | 975 | } |
975 | 976 | ||
976 | /* prepare channel attributes for playback */ | 977 | /* prepare channel attributes for playback */ |
977 | static void | 978 | static void |
978 | trident_play_setup(struct trident_state *state) | 979 | trident_play_setup(struct trident_state *state) |
979 | { | 980 | { |
980 | struct dmabuf *dmabuf = &state->dmabuf; | 981 | struct dmabuf *dmabuf = &state->dmabuf; |
981 | struct trident_channel *channel = dmabuf->channel; | 982 | struct trident_channel *channel = dmabuf->channel; |
982 | 983 | ||
983 | channel->lba = dmabuf->dma_handle; | 984 | channel->lba = dmabuf->dma_handle; |
984 | channel->delta = compute_rate_play(dmabuf->rate); | 985 | channel->delta = compute_rate_play(dmabuf->rate); |
985 | 986 | ||
986 | channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; | 987 | channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; |
987 | channel->eso -= 1; | 988 | channel->eso -= 1; |
988 | 989 | ||
989 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { | 990 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { |
990 | channel->attribute = 0; | 991 | channel->attribute = 0; |
991 | if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 992 | if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
992 | if ((channel->num == ALI_SPDIF_IN_CHANNEL) || | 993 | if ((channel->num == ALI_SPDIF_IN_CHANNEL) || |
993 | (channel->num == ALI_PCM_IN_CHANNEL)) | 994 | (channel->num == ALI_PCM_IN_CHANNEL)) |
994 | ali_disable_special_channel(state->card, channel->num); | 995 | ali_disable_special_channel(state->card, channel->num); |
995 | else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL)) | 996 | else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL)) |
996 | & ALI_SPDIF_OUT_CH_ENABLE) | 997 | & ALI_SPDIF_OUT_CH_ENABLE) |
997 | && (channel->num == ALI_SPDIF_OUT_CHANNEL)) { | 998 | && (channel->num == ALI_SPDIF_OUT_CHANNEL)) { |
998 | ali_set_spdif_out_rate(state->card, | 999 | ali_set_spdif_out_rate(state->card, |
999 | state->dmabuf.rate); | 1000 | state->dmabuf.rate); |
1000 | state->dmabuf.channel->delta = 0x1000; | 1001 | state->dmabuf.channel->delta = 0x1000; |
1001 | } | 1002 | } |
1002 | } | 1003 | } |
1003 | } | 1004 | } |
1004 | 1005 | ||
1005 | channel->fm_vol = 0x0; | 1006 | channel->fm_vol = 0x0; |
1006 | 1007 | ||
1007 | channel->control = CHANNEL_LOOP; | 1008 | channel->control = CHANNEL_LOOP; |
1008 | if (dmabuf->fmt & TRIDENT_FMT_16BIT) { | 1009 | if (dmabuf->fmt & TRIDENT_FMT_16BIT) { |
1009 | /* 16-bits */ | 1010 | /* 16-bits */ |
1010 | channel->control |= CHANNEL_16BITS; | 1011 | channel->control |= CHANNEL_16BITS; |
1011 | /* signed */ | 1012 | /* signed */ |
1012 | channel->control |= CHANNEL_SIGNED; | 1013 | channel->control |= CHANNEL_SIGNED; |
1013 | } | 1014 | } |
1014 | if (dmabuf->fmt & TRIDENT_FMT_STEREO) | 1015 | if (dmabuf->fmt & TRIDENT_FMT_STEREO) |
1015 | /* stereo */ | 1016 | /* stereo */ |
1016 | channel->control |= CHANNEL_STEREO; | 1017 | channel->control |= CHANNEL_STEREO; |
1017 | 1018 | ||
1018 | pr_debug("trident: trident_play_setup, LBA = 0x%08x, Delta = 0x%08x, " | 1019 | pr_debug("trident: trident_play_setup, LBA = 0x%08x, Delta = 0x%08x, " |
1019 | "ESO = 0x%08x, Control = 0x%08x\n", channel->lba, | 1020 | "ESO = 0x%08x, Control = 0x%08x\n", channel->lba, |
1020 | channel->delta, channel->eso, channel->control); | 1021 | channel->delta, channel->eso, channel->control); |
1021 | 1022 | ||
1022 | trident_write_voice_regs(state); | 1023 | trident_write_voice_regs(state); |
1023 | } | 1024 | } |
1024 | 1025 | ||
1025 | /* prepare channel attributes for recording */ | 1026 | /* prepare channel attributes for recording */ |
1026 | static void | 1027 | static void |
1027 | trident_rec_setup(struct trident_state *state) | 1028 | trident_rec_setup(struct trident_state *state) |
1028 | { | 1029 | { |
1029 | u16 w; | 1030 | u16 w; |
1030 | u8 bval; | 1031 | u8 bval; |
1031 | 1032 | ||
1032 | struct trident_card *card = state->card; | 1033 | struct trident_card *card = state->card; |
1033 | struct dmabuf *dmabuf = &state->dmabuf; | 1034 | struct dmabuf *dmabuf = &state->dmabuf; |
1034 | struct trident_channel *channel = dmabuf->channel; | 1035 | struct trident_channel *channel = dmabuf->channel; |
1035 | unsigned int rate; | 1036 | unsigned int rate; |
1036 | 1037 | ||
1037 | /* Enable AC-97 ADC (capture) */ | 1038 | /* Enable AC-97 ADC (capture) */ |
1038 | switch (card->pci_id) { | 1039 | switch (card->pci_id) { |
1039 | case PCI_DEVICE_ID_ALI_5451: | 1040 | case PCI_DEVICE_ID_ALI_5451: |
1040 | ali_enable_special_channel(state); | 1041 | ali_enable_special_channel(state); |
1041 | break; | 1042 | break; |
1042 | case PCI_DEVICE_ID_SI_7018: | 1043 | case PCI_DEVICE_ID_SI_7018: |
1043 | /* for 7018, the ac97 is always in playback/record (duplex) mode */ | 1044 | /* for 7018, the ac97 is always in playback/record (duplex) mode */ |
1044 | break; | 1045 | break; |
1045 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | 1046 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: |
1046 | w = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT)); | 1047 | w = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT)); |
1047 | outb(w | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT)); | 1048 | outb(w | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT)); |
1048 | /* enable and set record channel */ | 1049 | /* enable and set record channel */ |
1049 | outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); | 1050 | outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); |
1050 | break; | 1051 | break; |
1051 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | 1052 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: |
1052 | w = inw(TRID_REG(card, T4D_MISCINT)); | 1053 | w = inw(TRID_REG(card, T4D_MISCINT)); |
1053 | outw(w | 0x1000, TRID_REG(card, T4D_MISCINT)); | 1054 | outw(w | 0x1000, TRID_REG(card, T4D_MISCINT)); |
1054 | /* enable and set record channel */ | 1055 | /* enable and set record channel */ |
1055 | outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); | 1056 | outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); |
1056 | break; | 1057 | break; |
1057 | case PCI_DEVICE_ID_INTERG_5050: | 1058 | case PCI_DEVICE_ID_INTERG_5050: |
1058 | /* don't know yet, using special channel 22 in GC1(0xd4)? */ | 1059 | /* don't know yet, using special channel 22 in GC1(0xd4)? */ |
1059 | break; | 1060 | break; |
1060 | default: | 1061 | default: |
1061 | return; | 1062 | return; |
1062 | } | 1063 | } |
1063 | 1064 | ||
1064 | channel->lba = dmabuf->dma_handle; | 1065 | channel->lba = dmabuf->dma_handle; |
1065 | channel->delta = compute_rate_rec(dmabuf->rate); | 1066 | channel->delta = compute_rate_rec(dmabuf->rate); |
1066 | if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && | 1067 | if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && |
1067 | (channel->num == ALI_SPDIF_IN_CHANNEL)) { | 1068 | (channel->num == ALI_SPDIF_IN_CHANNEL)) { |
1068 | rate = ali_get_spdif_in_rate(card); | 1069 | rate = ali_get_spdif_in_rate(card); |
1069 | if (rate == 0) { | 1070 | if (rate == 0) { |
1070 | printk(KERN_WARNING "trident: ALi 5451 " | 1071 | printk(KERN_WARNING "trident: ALi 5451 " |
1071 | "S/PDIF input setup error!\n"); | 1072 | "S/PDIF input setup error!\n"); |
1072 | rate = 48000; | 1073 | rate = 48000; |
1073 | } | 1074 | } |
1074 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | 1075 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); |
1075 | if (bval & 0x10) { | 1076 | if (bval & 0x10) { |
1076 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); | 1077 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); |
1077 | printk(KERN_WARNING "trident: cleared ALi " | 1078 | printk(KERN_WARNING "trident: cleared ALi " |
1078 | "5451 S/PDIF parity error flag.\n"); | 1079 | "5451 S/PDIF parity error flag.\n"); |
1079 | } | 1080 | } |
1080 | 1081 | ||
1081 | if (rate != 48000) | 1082 | if (rate != 48000) |
1082 | channel->delta = ((rate << 12) / dmabuf->rate) & 0x0000ffff; | 1083 | channel->delta = ((rate << 12) / dmabuf->rate) & 0x0000ffff; |
1083 | } | 1084 | } |
1084 | 1085 | ||
1085 | channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; | 1086 | channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; |
1086 | channel->eso -= 1; | 1087 | channel->eso -= 1; |
1087 | 1088 | ||
1088 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { | 1089 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { |
1089 | channel->attribute = 0; | 1090 | channel->attribute = 0; |
1090 | } | 1091 | } |
1091 | 1092 | ||
1092 | channel->fm_vol = 0x0; | 1093 | channel->fm_vol = 0x0; |
1093 | 1094 | ||
1094 | channel->control = CHANNEL_LOOP; | 1095 | channel->control = CHANNEL_LOOP; |
1095 | if (dmabuf->fmt & TRIDENT_FMT_16BIT) { | 1096 | if (dmabuf->fmt & TRIDENT_FMT_16BIT) { |
1096 | /* 16-bits */ | 1097 | /* 16-bits */ |
1097 | channel->control |= CHANNEL_16BITS; | 1098 | channel->control |= CHANNEL_16BITS; |
1098 | /* signed */ | 1099 | /* signed */ |
1099 | channel->control |= CHANNEL_SIGNED; | 1100 | channel->control |= CHANNEL_SIGNED; |
1100 | } | 1101 | } |
1101 | if (dmabuf->fmt & TRIDENT_FMT_STEREO) | 1102 | if (dmabuf->fmt & TRIDENT_FMT_STEREO) |
1102 | /* stereo */ | 1103 | /* stereo */ |
1103 | channel->control |= CHANNEL_STEREO; | 1104 | channel->control |= CHANNEL_STEREO; |
1104 | 1105 | ||
1105 | pr_debug("trident: trident_rec_setup, LBA = 0x%08x, Delat = 0x%08x, " | 1106 | pr_debug("trident: trident_rec_setup, LBA = 0x%08x, Delat = 0x%08x, " |
1106 | "ESO = 0x%08x, Control = 0x%08x\n", channel->lba, | 1107 | "ESO = 0x%08x, Control = 0x%08x\n", channel->lba, |
1107 | channel->delta, channel->eso, channel->control); | 1108 | channel->delta, channel->eso, channel->control); |
1108 | 1109 | ||
1109 | trident_write_voice_regs(state); | 1110 | trident_write_voice_regs(state); |
1110 | } | 1111 | } |
1111 | 1112 | ||
1112 | /* get current playback/recording dma buffer pointer (byte offset from LBA), | 1113 | /* get current playback/recording dma buffer pointer (byte offset from LBA), |
1113 | called with spinlock held! */ | 1114 | called with spinlock held! */ |
1114 | static inline unsigned | 1115 | static inline unsigned |
1115 | trident_get_dma_addr(struct trident_state *state) | 1116 | trident_get_dma_addr(struct trident_state *state) |
1116 | { | 1117 | { |
1117 | struct dmabuf *dmabuf = &state->dmabuf; | 1118 | struct dmabuf *dmabuf = &state->dmabuf; |
1118 | u32 cso; | 1119 | u32 cso; |
1119 | 1120 | ||
1120 | if (!dmabuf->enable) | 1121 | if (!dmabuf->enable) |
1121 | return 0; | 1122 | return 0; |
1122 | 1123 | ||
1123 | outb(dmabuf->channel->num, TRID_REG(state->card, T4D_LFO_GC_CIR)); | 1124 | outb(dmabuf->channel->num, TRID_REG(state->card, T4D_LFO_GC_CIR)); |
1124 | 1125 | ||
1125 | switch (state->card->pci_id) { | 1126 | switch (state->card->pci_id) { |
1126 | case PCI_DEVICE_ID_ALI_5451: | 1127 | case PCI_DEVICE_ID_ALI_5451: |
1127 | case PCI_DEVICE_ID_SI_7018: | 1128 | case PCI_DEVICE_ID_SI_7018: |
1128 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | 1129 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: |
1129 | case PCI_DEVICE_ID_INTERG_5050: | 1130 | case PCI_DEVICE_ID_INTERG_5050: |
1130 | /* 16 bits ESO, CSO for 7018 and DX */ | 1131 | /* 16 bits ESO, CSO for 7018 and DX */ |
1131 | cso = inw(TRID_REG(state->card, CH_DX_CSO_ALPHA_FMS + 2)); | 1132 | cso = inw(TRID_REG(state->card, CH_DX_CSO_ALPHA_FMS + 2)); |
1132 | break; | 1133 | break; |
1133 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | 1134 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: |
1134 | /* 24 bits ESO, CSO for NX */ | 1135 | /* 24 bits ESO, CSO for NX */ |
1135 | cso = inl(TRID_REG(state->card, CH_NX_DELTA_CSO)) & 0x00ffffff; | 1136 | cso = inl(TRID_REG(state->card, CH_NX_DELTA_CSO)) & 0x00ffffff; |
1136 | break; | 1137 | break; |
1137 | default: | 1138 | default: |
1138 | return 0; | 1139 | return 0; |
1139 | } | 1140 | } |
1140 | 1141 | ||
1141 | pr_debug("trident: trident_get_dma_addr: chip reported channel: %d, " | 1142 | pr_debug("trident: trident_get_dma_addr: chip reported channel: %d, " |
1142 | "cso = 0x%04x\n", dmabuf->channel->num, cso); | 1143 | "cso = 0x%04x\n", dmabuf->channel->num, cso); |
1143 | 1144 | ||
1144 | /* ESO and CSO are in units of Samples, convert to byte offset */ | 1145 | /* ESO and CSO are in units of Samples, convert to byte offset */ |
1145 | cso <<= sample_shift[dmabuf->fmt]; | 1146 | cso <<= sample_shift[dmabuf->fmt]; |
1146 | 1147 | ||
1147 | return (cso % dmabuf->dmasize); | 1148 | return (cso % dmabuf->dmasize); |
1148 | } | 1149 | } |
1149 | 1150 | ||
1150 | /* Stop recording (lock held) */ | 1151 | /* Stop recording (lock held) */ |
1151 | static inline void | 1152 | static inline void |
1152 | __stop_adc(struct trident_state *state) | 1153 | __stop_adc(struct trident_state *state) |
1153 | { | 1154 | { |
1154 | struct dmabuf *dmabuf = &state->dmabuf; | 1155 | struct dmabuf *dmabuf = &state->dmabuf; |
1155 | unsigned int chan_num = dmabuf->channel->num; | 1156 | unsigned int chan_num = dmabuf->channel->num; |
1156 | struct trident_card *card = state->card; | 1157 | struct trident_card *card = state->card; |
1157 | 1158 | ||
1158 | dmabuf->enable &= ~ADC_RUNNING; | 1159 | dmabuf->enable &= ~ADC_RUNNING; |
1159 | trident_stop_voice(card, chan_num); | 1160 | trident_stop_voice(card, chan_num); |
1160 | trident_disable_voice_irq(card, chan_num); | 1161 | trident_disable_voice_irq(card, chan_num); |
1161 | } | 1162 | } |
1162 | 1163 | ||
1163 | static void | 1164 | static void |
1164 | stop_adc(struct trident_state *state) | 1165 | stop_adc(struct trident_state *state) |
1165 | { | 1166 | { |
1166 | struct trident_card *card = state->card; | 1167 | struct trident_card *card = state->card; |
1167 | unsigned long flags; | 1168 | unsigned long flags; |
1168 | 1169 | ||
1169 | spin_lock_irqsave(&card->lock, flags); | 1170 | spin_lock_irqsave(&card->lock, flags); |
1170 | __stop_adc(state); | 1171 | __stop_adc(state); |
1171 | spin_unlock_irqrestore(&card->lock, flags); | 1172 | spin_unlock_irqrestore(&card->lock, flags); |
1172 | } | 1173 | } |
1173 | 1174 | ||
1174 | static void | 1175 | static void |
1175 | start_adc(struct trident_state *state) | 1176 | start_adc(struct trident_state *state) |
1176 | { | 1177 | { |
1177 | struct dmabuf *dmabuf = &state->dmabuf; | 1178 | struct dmabuf *dmabuf = &state->dmabuf; |
1178 | unsigned int chan_num = dmabuf->channel->num; | 1179 | unsigned int chan_num = dmabuf->channel->num; |
1179 | struct trident_card *card = state->card; | 1180 | struct trident_card *card = state->card; |
1180 | unsigned long flags; | 1181 | unsigned long flags; |
1181 | 1182 | ||
1182 | spin_lock_irqsave(&card->lock, flags); | 1183 | spin_lock_irqsave(&card->lock, flags); |
1183 | if ((dmabuf->mapped || | 1184 | if ((dmabuf->mapped || |
1184 | dmabuf->count < (signed) dmabuf->dmasize) && | 1185 | dmabuf->count < (signed) dmabuf->dmasize) && |
1185 | dmabuf->ready) { | 1186 | dmabuf->ready) { |
1186 | dmabuf->enable |= ADC_RUNNING; | 1187 | dmabuf->enable |= ADC_RUNNING; |
1187 | trident_enable_voice_irq(card, chan_num); | 1188 | trident_enable_voice_irq(card, chan_num); |
1188 | trident_start_voice(card, chan_num); | 1189 | trident_start_voice(card, chan_num); |
1189 | } | 1190 | } |
1190 | spin_unlock_irqrestore(&card->lock, flags); | 1191 | spin_unlock_irqrestore(&card->lock, flags); |
1191 | } | 1192 | } |
1192 | 1193 | ||
1193 | /* stop playback (lock held) */ | 1194 | /* stop playback (lock held) */ |
1194 | static inline void | 1195 | static inline void |
1195 | __stop_dac(struct trident_state *state) | 1196 | __stop_dac(struct trident_state *state) |
1196 | { | 1197 | { |
1197 | struct dmabuf *dmabuf = &state->dmabuf; | 1198 | struct dmabuf *dmabuf = &state->dmabuf; |
1198 | unsigned int chan_num = dmabuf->channel->num; | 1199 | unsigned int chan_num = dmabuf->channel->num; |
1199 | struct trident_card *card = state->card; | 1200 | struct trident_card *card = state->card; |
1200 | 1201 | ||
1201 | dmabuf->enable &= ~DAC_RUNNING; | 1202 | dmabuf->enable &= ~DAC_RUNNING; |
1202 | trident_stop_voice(card, chan_num); | 1203 | trident_stop_voice(card, chan_num); |
1203 | if (state->chans_num == 6) { | 1204 | if (state->chans_num == 6) { |
1204 | trident_stop_voice(card, state->other_states[0]-> | 1205 | trident_stop_voice(card, state->other_states[0]-> |
1205 | dmabuf.channel->num); | 1206 | dmabuf.channel->num); |
1206 | trident_stop_voice(card, state->other_states[1]-> | 1207 | trident_stop_voice(card, state->other_states[1]-> |
1207 | dmabuf.channel->num); | 1208 | dmabuf.channel->num); |
1208 | trident_stop_voice(card, state->other_states[2]-> | 1209 | trident_stop_voice(card, state->other_states[2]-> |
1209 | dmabuf.channel->num); | 1210 | dmabuf.channel->num); |
1210 | trident_stop_voice(card, state->other_states[3]-> | 1211 | trident_stop_voice(card, state->other_states[3]-> |
1211 | dmabuf.channel->num); | 1212 | dmabuf.channel->num); |
1212 | } | 1213 | } |
1213 | trident_disable_voice_irq(card, chan_num); | 1214 | trident_disable_voice_irq(card, chan_num); |
1214 | } | 1215 | } |
1215 | 1216 | ||
1216 | static void | 1217 | static void |
1217 | stop_dac(struct trident_state *state) | 1218 | stop_dac(struct trident_state *state) |
1218 | { | 1219 | { |
1219 | struct trident_card *card = state->card; | 1220 | struct trident_card *card = state->card; |
1220 | unsigned long flags; | 1221 | unsigned long flags; |
1221 | 1222 | ||
1222 | spin_lock_irqsave(&card->lock, flags); | 1223 | spin_lock_irqsave(&card->lock, flags); |
1223 | __stop_dac(state); | 1224 | __stop_dac(state); |
1224 | spin_unlock_irqrestore(&card->lock, flags); | 1225 | spin_unlock_irqrestore(&card->lock, flags); |
1225 | } | 1226 | } |
1226 | 1227 | ||
1227 | static void | 1228 | static void |
1228 | start_dac(struct trident_state *state) | 1229 | start_dac(struct trident_state *state) |
1229 | { | 1230 | { |
1230 | struct dmabuf *dmabuf = &state->dmabuf; | 1231 | struct dmabuf *dmabuf = &state->dmabuf; |
1231 | unsigned int chan_num = dmabuf->channel->num; | 1232 | unsigned int chan_num = dmabuf->channel->num; |
1232 | struct trident_card *card = state->card; | 1233 | struct trident_card *card = state->card; |
1233 | unsigned long flags; | 1234 | unsigned long flags; |
1234 | 1235 | ||
1235 | spin_lock_irqsave(&card->lock, flags); | 1236 | spin_lock_irqsave(&card->lock, flags); |
1236 | if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) { | 1237 | if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) { |
1237 | dmabuf->enable |= DAC_RUNNING; | 1238 | dmabuf->enable |= DAC_RUNNING; |
1238 | trident_enable_voice_irq(card, chan_num); | 1239 | trident_enable_voice_irq(card, chan_num); |
1239 | trident_start_voice(card, chan_num); | 1240 | trident_start_voice(card, chan_num); |
1240 | if (state->chans_num == 6) { | 1241 | if (state->chans_num == 6) { |
1241 | trident_start_voice(card, state->other_states[0]-> | 1242 | trident_start_voice(card, state->other_states[0]-> |
1242 | dmabuf.channel->num); | 1243 | dmabuf.channel->num); |
1243 | trident_start_voice(card, state->other_states[1]-> | 1244 | trident_start_voice(card, state->other_states[1]-> |
1244 | dmabuf.channel->num); | 1245 | dmabuf.channel->num); |
1245 | trident_start_voice(card, state->other_states[2]-> | 1246 | trident_start_voice(card, state->other_states[2]-> |
1246 | dmabuf.channel->num); | 1247 | dmabuf.channel->num); |
1247 | trident_start_voice(card, state->other_states[3]-> | 1248 | trident_start_voice(card, state->other_states[3]-> |
1248 | dmabuf.channel->num); | 1249 | dmabuf.channel->num); |
1249 | } | 1250 | } |
1250 | } | 1251 | } |
1251 | spin_unlock_irqrestore(&card->lock, flags); | 1252 | spin_unlock_irqrestore(&card->lock, flags); |
1252 | } | 1253 | } |
1253 | 1254 | ||
1254 | #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) | 1255 | #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) |
1255 | #define DMABUF_MINORDER 1 | 1256 | #define DMABUF_MINORDER 1 |
1256 | 1257 | ||
1257 | /* alloc a DMA buffer of with a buffer of this order */ | 1258 | /* alloc a DMA buffer of with a buffer of this order */ |
1258 | static int | 1259 | static int |
1259 | alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order) | 1260 | alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order) |
1260 | { | 1261 | { |
1261 | void *rawbuf = NULL; | 1262 | void *rawbuf = NULL; |
1262 | struct page *page, *pend; | 1263 | struct page *page, *pend; |
1263 | 1264 | ||
1264 | if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order, | 1265 | if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order, |
1265 | &dmabuf->dma_handle))) | 1266 | &dmabuf->dma_handle))) |
1266 | return -ENOMEM; | 1267 | return -ENOMEM; |
1267 | 1268 | ||
1268 | pr_debug("trident: allocated %ld (order = %d) bytes at %p\n", | 1269 | pr_debug("trident: allocated %ld (order = %d) bytes at %p\n", |
1269 | PAGE_SIZE << order, order, rawbuf); | 1270 | PAGE_SIZE << order, order, rawbuf); |
1270 | 1271 | ||
1271 | dmabuf->ready = dmabuf->mapped = 0; | 1272 | dmabuf->ready = dmabuf->mapped = 0; |
1272 | dmabuf->rawbuf = rawbuf; | 1273 | dmabuf->rawbuf = rawbuf; |
1273 | dmabuf->buforder = order; | 1274 | dmabuf->buforder = order; |
1274 | 1275 | ||
1275 | /* now mark the pages as reserved; otherwise */ | 1276 | /* now mark the pages as reserved; otherwise */ |
1276 | /* remap_pfn_range doesn't do what we want */ | 1277 | /* remap_pfn_range doesn't do what we want */ |
1277 | pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); | 1278 | pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); |
1278 | for (page = virt_to_page(rawbuf); page <= pend; page++) | 1279 | for (page = virt_to_page(rawbuf); page <= pend; page++) |
1279 | SetPageReserved(page); | 1280 | SetPageReserved(page); |
1280 | 1281 | ||
1281 | return 0; | 1282 | return 0; |
1282 | } | 1283 | } |
1283 | 1284 | ||
1284 | /* allocate the main DMA buffer, playback and recording buffer should be */ | 1285 | /* allocate the main DMA buffer, playback and recording buffer should be */ |
1285 | /* allocated separately */ | 1286 | /* allocated separately */ |
1286 | static int | 1287 | static int |
1287 | alloc_main_dmabuf(struct trident_state *state) | 1288 | alloc_main_dmabuf(struct trident_state *state) |
1288 | { | 1289 | { |
1289 | struct dmabuf *dmabuf = &state->dmabuf; | 1290 | struct dmabuf *dmabuf = &state->dmabuf; |
1290 | int order; | 1291 | int order; |
1291 | int ret = -ENOMEM; | 1292 | int ret = -ENOMEM; |
1292 | 1293 | ||
1293 | /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ | 1294 | /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ |
1294 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { | 1295 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { |
1295 | if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order))) | 1296 | if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order))) |
1296 | return 0; | 1297 | return 0; |
1297 | /* else try again */ | 1298 | /* else try again */ |
1298 | } | 1299 | } |
1299 | return ret; | 1300 | return ret; |
1300 | } | 1301 | } |
1301 | 1302 | ||
1302 | /* deallocate a DMA buffer */ | 1303 | /* deallocate a DMA buffer */ |
1303 | static void | 1304 | static void |
1304 | dealloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev) | 1305 | dealloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev) |
1305 | { | 1306 | { |
1306 | struct page *page, *pend; | 1307 | struct page *page, *pend; |
1307 | 1308 | ||
1308 | if (dmabuf->rawbuf) { | 1309 | if (dmabuf->rawbuf) { |
1309 | /* undo marking the pages as reserved */ | 1310 | /* undo marking the pages as reserved */ |
1310 | pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); | 1311 | pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); |
1311 | for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) | 1312 | for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) |
1312 | ClearPageReserved(page); | 1313 | ClearPageReserved(page); |
1313 | pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder, | 1314 | pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder, |
1314 | dmabuf->rawbuf, dmabuf->dma_handle); | 1315 | dmabuf->rawbuf, dmabuf->dma_handle); |
1315 | dmabuf->rawbuf = NULL; | 1316 | dmabuf->rawbuf = NULL; |
1316 | } | 1317 | } |
1317 | dmabuf->mapped = dmabuf->ready = 0; | 1318 | dmabuf->mapped = dmabuf->ready = 0; |
1318 | } | 1319 | } |
1319 | 1320 | ||
1320 | static int | 1321 | static int |
1321 | prog_dmabuf(struct trident_state *state, enum dmabuf_mode rec) | 1322 | prog_dmabuf(struct trident_state *state, enum dmabuf_mode rec) |
1322 | { | 1323 | { |
1323 | struct dmabuf *dmabuf = &state->dmabuf; | 1324 | struct dmabuf *dmabuf = &state->dmabuf; |
1324 | unsigned bytepersec; | 1325 | unsigned bytepersec; |
1325 | struct trident_state *s = state; | 1326 | struct trident_state *s = state; |
1326 | unsigned bufsize, dma_nums; | 1327 | unsigned bufsize, dma_nums; |
1327 | unsigned long flags; | 1328 | unsigned long flags; |
1328 | int ret, i, order; | 1329 | int ret, i, order; |
1329 | 1330 | ||
1330 | if ((ret = lock_set_fmt(state)) < 0) | 1331 | if ((ret = lock_set_fmt(state)) < 0) |
1331 | return ret; | 1332 | return ret; |
1332 | 1333 | ||
1333 | if (state->chans_num == 6) | 1334 | if (state->chans_num == 6) |
1334 | dma_nums = 5; | 1335 | dma_nums = 5; |
1335 | else | 1336 | else |
1336 | dma_nums = 1; | 1337 | dma_nums = 1; |
1337 | 1338 | ||
1338 | for (i = 0; i < dma_nums; i++) { | 1339 | for (i = 0; i < dma_nums; i++) { |
1339 | if (i > 0) { | 1340 | if (i > 0) { |
1340 | s = state->other_states[i - 1]; | 1341 | s = state->other_states[i - 1]; |
1341 | dmabuf = &s->dmabuf; | 1342 | dmabuf = &s->dmabuf; |
1342 | dmabuf->fmt = state->dmabuf.fmt; | 1343 | dmabuf->fmt = state->dmabuf.fmt; |
1343 | dmabuf->rate = state->dmabuf.rate; | 1344 | dmabuf->rate = state->dmabuf.rate; |
1344 | } | 1345 | } |
1345 | 1346 | ||
1346 | spin_lock_irqsave(&s->card->lock, flags); | 1347 | spin_lock_irqsave(&s->card->lock, flags); |
1347 | dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0; | 1348 | dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0; |
1348 | dmabuf->count = dmabuf->error = 0; | 1349 | dmabuf->count = dmabuf->error = 0; |
1349 | spin_unlock_irqrestore(&s->card->lock, flags); | 1350 | spin_unlock_irqrestore(&s->card->lock, flags); |
1350 | 1351 | ||
1351 | /* allocate DMA buffer if not allocated yet */ | 1352 | /* allocate DMA buffer if not allocated yet */ |
1352 | if (!dmabuf->rawbuf) { | 1353 | if (!dmabuf->rawbuf) { |
1353 | if (i == 0) { | 1354 | if (i == 0) { |
1354 | if ((ret = alloc_main_dmabuf(state))) { | 1355 | if ((ret = alloc_main_dmabuf(state))) { |
1355 | unlock_set_fmt(state); | 1356 | unlock_set_fmt(state); |
1356 | return ret; | 1357 | return ret; |
1357 | } | 1358 | } |
1358 | } else { | 1359 | } else { |
1359 | ret = -ENOMEM; | 1360 | ret = -ENOMEM; |
1360 | order = state->dmabuf.buforder - 1; | 1361 | order = state->dmabuf.buforder - 1; |
1361 | if (order >= DMABUF_MINORDER) { | 1362 | if (order >= DMABUF_MINORDER) { |
1362 | ret = alloc_dmabuf(dmabuf, | 1363 | ret = alloc_dmabuf(dmabuf, |
1363 | state->card->pci_dev, | 1364 | state->card->pci_dev, |
1364 | order); | 1365 | order); |
1365 | } | 1366 | } |
1366 | if (ret) { | 1367 | if (ret) { |
1367 | /* release the main DMA buffer */ | 1368 | /* release the main DMA buffer */ |
1368 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); | 1369 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); |
1369 | /* release the auxiliary DMA buffers */ | 1370 | /* release the auxiliary DMA buffers */ |
1370 | for (i -= 2; i >= 0; i--) | 1371 | for (i -= 2; i >= 0; i--) |
1371 | dealloc_dmabuf(&state->other_states[i]->dmabuf, | 1372 | dealloc_dmabuf(&state->other_states[i]->dmabuf, |
1372 | state->card->pci_dev); | 1373 | state->card->pci_dev); |
1373 | unlock_set_fmt(state); | 1374 | unlock_set_fmt(state); |
1374 | return ret; | 1375 | return ret; |
1375 | } | 1376 | } |
1376 | } | 1377 | } |
1377 | } | 1378 | } |
1378 | /* FIXME: figure out all this OSS fragment stuff */ | 1379 | /* FIXME: figure out all this OSS fragment stuff */ |
1379 | bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt]; | 1380 | bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt]; |
1380 | bufsize = PAGE_SIZE << dmabuf->buforder; | 1381 | bufsize = PAGE_SIZE << dmabuf->buforder; |
1381 | if (dmabuf->ossfragshift) { | 1382 | if (dmabuf->ossfragshift) { |
1382 | if ((1000 << dmabuf->ossfragshift) < bytepersec) | 1383 | if ((1000 << dmabuf->ossfragshift) < bytepersec) |
1383 | dmabuf->fragshift = ld2(bytepersec / 1000); | 1384 | dmabuf->fragshift = ld2(bytepersec / 1000); |
1384 | else | 1385 | else |
1385 | dmabuf->fragshift = dmabuf->ossfragshift; | 1386 | dmabuf->fragshift = dmabuf->ossfragshift; |
1386 | } else { | 1387 | } else { |
1387 | /* lets hand out reasonable big ass buffers by default */ | 1388 | /* lets hand out reasonable big ass buffers by default */ |
1388 | dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT - 2); | 1389 | dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT - 2); |
1389 | } | 1390 | } |
1390 | dmabuf->numfrag = bufsize >> dmabuf->fragshift; | 1391 | dmabuf->numfrag = bufsize >> dmabuf->fragshift; |
1391 | while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) { | 1392 | while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) { |
1392 | dmabuf->fragshift--; | 1393 | dmabuf->fragshift--; |
1393 | dmabuf->numfrag = bufsize >> dmabuf->fragshift; | 1394 | dmabuf->numfrag = bufsize >> dmabuf->fragshift; |
1394 | } | 1395 | } |
1395 | dmabuf->fragsize = 1 << dmabuf->fragshift; | 1396 | dmabuf->fragsize = 1 << dmabuf->fragshift; |
1396 | if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag) | 1397 | if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag) |
1397 | dmabuf->numfrag = dmabuf->ossmaxfrags; | 1398 | dmabuf->numfrag = dmabuf->ossmaxfrags; |
1398 | dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt]; | 1399 | dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt]; |
1399 | dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; | 1400 | dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; |
1400 | 1401 | ||
1401 | memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80, | 1402 | memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80, |
1402 | dmabuf->dmasize); | 1403 | dmabuf->dmasize); |
1403 | 1404 | ||
1404 | spin_lock_irqsave(&s->card->lock, flags); | 1405 | spin_lock_irqsave(&s->card->lock, flags); |
1405 | if (rec == DM_RECORD) | 1406 | if (rec == DM_RECORD) |
1406 | trident_rec_setup(s); | 1407 | trident_rec_setup(s); |
1407 | else /* DM_PLAYBACK */ | 1408 | else /* DM_PLAYBACK */ |
1408 | trident_play_setup(s); | 1409 | trident_play_setup(s); |
1409 | 1410 | ||
1410 | spin_unlock_irqrestore(&s->card->lock, flags); | 1411 | spin_unlock_irqrestore(&s->card->lock, flags); |
1411 | 1412 | ||
1412 | /* set the ready flag for the dma buffer */ | 1413 | /* set the ready flag for the dma buffer */ |
1413 | dmabuf->ready = 1; | 1414 | dmabuf->ready = 1; |
1414 | 1415 | ||
1415 | pr_debug("trident: prog_dmabuf(%d), sample rate = %d, " | 1416 | pr_debug("trident: prog_dmabuf(%d), sample rate = %d, " |
1416 | "format = %d, numfrag = %d, fragsize = %d " | 1417 | "format = %d, numfrag = %d, fragsize = %d " |
1417 | "dmasize = %d\n", dmabuf->channel->num, | 1418 | "dmasize = %d\n", dmabuf->channel->num, |
1418 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, | 1419 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, |
1419 | dmabuf->fragsize, dmabuf->dmasize); | 1420 | dmabuf->fragsize, dmabuf->dmasize); |
1420 | } | 1421 | } |
1421 | unlock_set_fmt(state); | 1422 | unlock_set_fmt(state); |
1422 | return 0; | 1423 | return 0; |
1423 | } | 1424 | } |
1424 | 1425 | ||
1425 | 1426 | ||
1426 | static inline int prog_dmabuf_record(struct trident_state* state) | 1427 | static inline int prog_dmabuf_record(struct trident_state* state) |
1427 | { | 1428 | { |
1428 | return prog_dmabuf(state, DM_RECORD); | 1429 | return prog_dmabuf(state, DM_RECORD); |
1429 | } | 1430 | } |
1430 | 1431 | ||
1431 | static inline int prog_dmabuf_playback(struct trident_state* state) | 1432 | static inline int prog_dmabuf_playback(struct trident_state* state) |
1432 | { | 1433 | { |
1433 | return prog_dmabuf(state, DM_PLAYBACK); | 1434 | return prog_dmabuf(state, DM_PLAYBACK); |
1434 | } | 1435 | } |
1435 | 1436 | ||
1436 | /* we are doing quantum mechanics here, the buffer can only be empty, half or full filled i.e. | 1437 | /* we are doing quantum mechanics here, the buffer can only be empty, half or full filled i.e. |
1437 | |------------|------------| or |xxxxxxxxxxxx|------------| or |xxxxxxxxxxxx|xxxxxxxxxxxx| | 1438 | |------------|------------| or |xxxxxxxxxxxx|------------| or |xxxxxxxxxxxx|xxxxxxxxxxxx| |
1438 | but we almost always get this | 1439 | but we almost always get this |
1439 | |xxxxxx------|------------| or |xxxxxxxxxxxx|xxxxx-------| | 1440 | |xxxxxx------|------------| or |xxxxxxxxxxxx|xxxxx-------| |
1440 | so we have to clear the tail space to "silence" | 1441 | so we have to clear the tail space to "silence" |
1441 | |xxxxxx000000|------------| or |xxxxxxxxxxxx|xxxxxx000000| | 1442 | |xxxxxx000000|------------| or |xxxxxxxxxxxx|xxxxxx000000| |
1442 | */ | 1443 | */ |
1443 | static void | 1444 | static void |
1444 | trident_clear_tail(struct trident_state *state) | 1445 | trident_clear_tail(struct trident_state *state) |
1445 | { | 1446 | { |
1446 | struct dmabuf *dmabuf = &state->dmabuf; | 1447 | struct dmabuf *dmabuf = &state->dmabuf; |
1447 | unsigned swptr; | 1448 | unsigned swptr; |
1448 | unsigned char silence = (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80; | 1449 | unsigned char silence = (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80; |
1449 | unsigned int len; | 1450 | unsigned int len; |
1450 | unsigned long flags; | 1451 | unsigned long flags; |
1451 | 1452 | ||
1452 | spin_lock_irqsave(&state->card->lock, flags); | 1453 | spin_lock_irqsave(&state->card->lock, flags); |
1453 | swptr = dmabuf->swptr; | 1454 | swptr = dmabuf->swptr; |
1454 | spin_unlock_irqrestore(&state->card->lock, flags); | 1455 | spin_unlock_irqrestore(&state->card->lock, flags); |
1455 | 1456 | ||
1456 | if (swptr == 0 || swptr == dmabuf->dmasize / 2 || | 1457 | if (swptr == 0 || swptr == dmabuf->dmasize / 2 || |
1457 | swptr == dmabuf->dmasize) | 1458 | swptr == dmabuf->dmasize) |
1458 | return; | 1459 | return; |
1459 | 1460 | ||
1460 | if (swptr < dmabuf->dmasize / 2) | 1461 | if (swptr < dmabuf->dmasize / 2) |
1461 | len = dmabuf->dmasize / 2 - swptr; | 1462 | len = dmabuf->dmasize / 2 - swptr; |
1462 | else | 1463 | else |
1463 | len = dmabuf->dmasize - swptr; | 1464 | len = dmabuf->dmasize - swptr; |
1464 | 1465 | ||
1465 | memset(dmabuf->rawbuf + swptr, silence, len); | 1466 | memset(dmabuf->rawbuf + swptr, silence, len); |
1466 | if (state->card->pci_id != PCI_DEVICE_ID_ALI_5451) { | 1467 | if (state->card->pci_id != PCI_DEVICE_ID_ALI_5451) { |
1467 | spin_lock_irqsave(&state->card->lock, flags); | 1468 | spin_lock_irqsave(&state->card->lock, flags); |
1468 | dmabuf->swptr += len; | 1469 | dmabuf->swptr += len; |
1469 | dmabuf->count += len; | 1470 | dmabuf->count += len; |
1470 | spin_unlock_irqrestore(&state->card->lock, flags); | 1471 | spin_unlock_irqrestore(&state->card->lock, flags); |
1471 | } | 1472 | } |
1472 | 1473 | ||
1473 | /* restart the dma machine in case it is halted */ | 1474 | /* restart the dma machine in case it is halted */ |
1474 | start_dac(state); | 1475 | start_dac(state); |
1475 | } | 1476 | } |
1476 | 1477 | ||
1477 | static int | 1478 | static int |
1478 | drain_dac(struct trident_state *state, int nonblock) | 1479 | drain_dac(struct trident_state *state, int nonblock) |
1479 | { | 1480 | { |
1480 | DECLARE_WAITQUEUE(wait, current); | 1481 | DECLARE_WAITQUEUE(wait, current); |
1481 | struct dmabuf *dmabuf = &state->dmabuf; | 1482 | struct dmabuf *dmabuf = &state->dmabuf; |
1482 | unsigned long flags; | 1483 | unsigned long flags; |
1483 | unsigned long tmo; | 1484 | unsigned long tmo; |
1484 | int count; | 1485 | int count; |
1485 | unsigned long diff = 0; | 1486 | unsigned long diff = 0; |
1486 | 1487 | ||
1487 | if (dmabuf->mapped || !dmabuf->ready) | 1488 | if (dmabuf->mapped || !dmabuf->ready) |
1488 | return 0; | 1489 | return 0; |
1489 | 1490 | ||
1490 | add_wait_queue(&dmabuf->wait, &wait); | 1491 | add_wait_queue(&dmabuf->wait, &wait); |
1491 | for (;;) { | 1492 | for (;;) { |
1492 | /* It seems that we have to set the current state to TASK_INTERRUPTIBLE | 1493 | /* It seems that we have to set the current state to TASK_INTERRUPTIBLE |
1493 | every time to make the process really go to sleep */ | 1494 | every time to make the process really go to sleep */ |
1494 | set_current_state(TASK_INTERRUPTIBLE); | 1495 | set_current_state(TASK_INTERRUPTIBLE); |
1495 | 1496 | ||
1496 | spin_lock_irqsave(&state->card->lock, flags); | 1497 | spin_lock_irqsave(&state->card->lock, flags); |
1497 | count = dmabuf->count; | 1498 | count = dmabuf->count; |
1498 | spin_unlock_irqrestore(&state->card->lock, flags); | 1499 | spin_unlock_irqrestore(&state->card->lock, flags); |
1499 | 1500 | ||
1500 | if (count <= 0) | 1501 | if (count <= 0) |
1501 | break; | 1502 | break; |
1502 | 1503 | ||
1503 | if (signal_pending(current)) | 1504 | if (signal_pending(current)) |
1504 | break; | 1505 | break; |
1505 | 1506 | ||
1506 | if (nonblock) { | 1507 | if (nonblock) { |
1507 | remove_wait_queue(&dmabuf->wait, &wait); | 1508 | remove_wait_queue(&dmabuf->wait, &wait); |
1508 | set_current_state(TASK_RUNNING); | 1509 | set_current_state(TASK_RUNNING); |
1509 | return -EBUSY; | 1510 | return -EBUSY; |
1510 | } | 1511 | } |
1511 | 1512 | ||
1512 | /* No matter how much data is left in the buffer, we have to wait until | 1513 | /* No matter how much data is left in the buffer, we have to wait until |
1513 | CSO == ESO/2 or CSO == ESO when address engine interrupts */ | 1514 | CSO == ESO/2 or CSO == ESO when address engine interrupts */ |
1514 | if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 || | 1515 | if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 || |
1515 | state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) { | 1516 | state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) { |
1516 | diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize; | 1517 | diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize; |
1517 | diff = diff % (dmabuf->dmasize); | 1518 | diff = diff % (dmabuf->dmasize); |
1518 | tmo = (diff * HZ) / dmabuf->rate; | 1519 | tmo = (diff * HZ) / dmabuf->rate; |
1519 | } else { | 1520 | } else { |
1520 | tmo = (dmabuf->dmasize * HZ) / dmabuf->rate; | 1521 | tmo = (dmabuf->dmasize * HZ) / dmabuf->rate; |
1521 | } | 1522 | } |
1522 | tmo >>= sample_shift[dmabuf->fmt]; | 1523 | tmo >>= sample_shift[dmabuf->fmt]; |
1523 | if (!schedule_timeout(tmo ? tmo : 1) && tmo) { | 1524 | if (!schedule_timeout(tmo ? tmo : 1) && tmo) { |
1524 | break; | 1525 | break; |
1525 | } | 1526 | } |
1526 | } | 1527 | } |
1527 | remove_wait_queue(&dmabuf->wait, &wait); | 1528 | remove_wait_queue(&dmabuf->wait, &wait); |
1528 | set_current_state(TASK_RUNNING); | 1529 | set_current_state(TASK_RUNNING); |
1529 | if (signal_pending(current)) | 1530 | if (signal_pending(current)) |
1530 | return -ERESTARTSYS; | 1531 | return -ERESTARTSYS; |
1531 | 1532 | ||
1532 | return 0; | 1533 | return 0; |
1533 | } | 1534 | } |
1534 | 1535 | ||
1535 | /* update buffer manangement pointers, especially, */ | 1536 | /* update buffer manangement pointers, especially, */ |
1536 | /* dmabuf->count and dmabuf->hwptr */ | 1537 | /* dmabuf->count and dmabuf->hwptr */ |
1537 | static void | 1538 | static void |
1538 | trident_update_ptr(struct trident_state *state) | 1539 | trident_update_ptr(struct trident_state *state) |
1539 | { | 1540 | { |
1540 | struct dmabuf *dmabuf = &state->dmabuf; | 1541 | struct dmabuf *dmabuf = &state->dmabuf; |
1541 | unsigned hwptr, swptr; | 1542 | unsigned hwptr, swptr; |
1542 | int clear_cnt = 0; | 1543 | int clear_cnt = 0; |
1543 | int diff; | 1544 | int diff; |
1544 | unsigned char silence; | 1545 | unsigned char silence; |
1545 | unsigned half_dmasize; | 1546 | unsigned half_dmasize; |
1546 | 1547 | ||
1547 | /* update hardware pointer */ | 1548 | /* update hardware pointer */ |
1548 | hwptr = trident_get_dma_addr(state); | 1549 | hwptr = trident_get_dma_addr(state); |
1549 | diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; | 1550 | diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; |
1550 | dmabuf->hwptr = hwptr; | 1551 | dmabuf->hwptr = hwptr; |
1551 | dmabuf->total_bytes += diff; | 1552 | dmabuf->total_bytes += diff; |
1552 | 1553 | ||
1553 | /* error handling and process wake up for ADC */ | 1554 | /* error handling and process wake up for ADC */ |
1554 | if (dmabuf->enable == ADC_RUNNING) { | 1555 | if (dmabuf->enable == ADC_RUNNING) { |
1555 | if (dmabuf->mapped) { | 1556 | if (dmabuf->mapped) { |
1556 | dmabuf->count -= diff; | 1557 | dmabuf->count -= diff; |
1557 | if (dmabuf->count >= (signed) dmabuf->fragsize) | 1558 | if (dmabuf->count >= (signed) dmabuf->fragsize) |
1558 | wake_up(&dmabuf->wait); | 1559 | wake_up(&dmabuf->wait); |
1559 | } else { | 1560 | } else { |
1560 | dmabuf->count += diff; | 1561 | dmabuf->count += diff; |
1561 | 1562 | ||
1562 | if (dmabuf->count < 0 || | 1563 | if (dmabuf->count < 0 || |
1563 | dmabuf->count > dmabuf->dmasize) { | 1564 | dmabuf->count > dmabuf->dmasize) { |
1564 | /* buffer underrun or buffer overrun, */ | 1565 | /* buffer underrun or buffer overrun, */ |
1565 | /* we have no way to recover it here, just */ | 1566 | /* we have no way to recover it here, just */ |
1566 | /* stop the machine and let the process */ | 1567 | /* stop the machine and let the process */ |
1567 | /* force hwptr and swptr to sync */ | 1568 | /* force hwptr and swptr to sync */ |
1568 | __stop_adc(state); | 1569 | __stop_adc(state); |
1569 | dmabuf->error++; | 1570 | dmabuf->error++; |
1570 | } | 1571 | } |
1571 | if (dmabuf->count < (signed) dmabuf->dmasize / 2) | 1572 | if (dmabuf->count < (signed) dmabuf->dmasize / 2) |
1572 | wake_up(&dmabuf->wait); | 1573 | wake_up(&dmabuf->wait); |
1573 | } | 1574 | } |
1574 | } | 1575 | } |
1575 | 1576 | ||
1576 | /* error handling and process wake up for DAC */ | 1577 | /* error handling and process wake up for DAC */ |
1577 | if (dmabuf->enable == DAC_RUNNING) { | 1578 | if (dmabuf->enable == DAC_RUNNING) { |
1578 | if (dmabuf->mapped) { | 1579 | if (dmabuf->mapped) { |
1579 | dmabuf->count += diff; | 1580 | dmabuf->count += diff; |
1580 | if (dmabuf->count >= (signed) dmabuf->fragsize) | 1581 | if (dmabuf->count >= (signed) dmabuf->fragsize) |
1581 | wake_up(&dmabuf->wait); | 1582 | wake_up(&dmabuf->wait); |
1582 | } else { | 1583 | } else { |
1583 | dmabuf->count -= diff; | 1584 | dmabuf->count -= diff; |
1584 | 1585 | ||
1585 | if (dmabuf->count < 0 || | 1586 | if (dmabuf->count < 0 || |
1586 | dmabuf->count > dmabuf->dmasize) { | 1587 | dmabuf->count > dmabuf->dmasize) { |
1587 | /* buffer underrun or buffer overrun, we have no way to recover | 1588 | /* buffer underrun or buffer overrun, we have no way to recover |
1588 | it here, just stop the machine and let the process force hwptr | 1589 | it here, just stop the machine and let the process force hwptr |
1589 | and swptr to sync */ | 1590 | and swptr to sync */ |
1590 | __stop_dac(state); | 1591 | __stop_dac(state); |
1591 | dmabuf->error++; | 1592 | dmabuf->error++; |
1592 | } else if (!dmabuf->endcleared) { | 1593 | } else if (!dmabuf->endcleared) { |
1593 | swptr = dmabuf->swptr; | 1594 | swptr = dmabuf->swptr; |
1594 | silence = (dmabuf->fmt & TRIDENT_FMT_16BIT ? 0 : 0x80); | 1595 | silence = (dmabuf->fmt & TRIDENT_FMT_16BIT ? 0 : 0x80); |
1595 | if (dmabuf->update_flag & ALI_ADDRESS_INT_UPDATE) { | 1596 | if (dmabuf->update_flag & ALI_ADDRESS_INT_UPDATE) { |
1596 | /* We must clear end data of 1/2 dmabuf if needed. | 1597 | /* We must clear end data of 1/2 dmabuf if needed. |
1597 | According to 1/2 algorithm of Address Engine Interrupt, | 1598 | According to 1/2 algorithm of Address Engine Interrupt, |
1598 | check the validation of the data of half dmasize. */ | 1599 | check the validation of the data of half dmasize. */ |
1599 | half_dmasize = dmabuf->dmasize / 2; | 1600 | half_dmasize = dmabuf->dmasize / 2; |
1600 | if ((diff = hwptr - half_dmasize) < 0) | 1601 | if ((diff = hwptr - half_dmasize) < 0) |
1601 | diff = hwptr; | 1602 | diff = hwptr; |
1602 | if ((dmabuf->count + diff) < half_dmasize) { | 1603 | if ((dmabuf->count + diff) < half_dmasize) { |
1603 | //there is invalid data in the end of half buffer | 1604 | //there is invalid data in the end of half buffer |
1604 | if ((clear_cnt = half_dmasize - swptr) < 0) | 1605 | if ((clear_cnt = half_dmasize - swptr) < 0) |
1605 | clear_cnt += half_dmasize; | 1606 | clear_cnt += half_dmasize; |
1606 | //clear the invalid data | 1607 | //clear the invalid data |
1607 | memset(dmabuf->rawbuf + swptr, silence, clear_cnt); | 1608 | memset(dmabuf->rawbuf + swptr, silence, clear_cnt); |
1608 | if (state->chans_num == 6) { | 1609 | if (state->chans_num == 6) { |
1609 | clear_cnt = clear_cnt / 2; | 1610 | clear_cnt = clear_cnt / 2; |
1610 | swptr = swptr / 2; | 1611 | swptr = swptr / 2; |
1611 | memset(state->other_states[0]->dmabuf.rawbuf + swptr, | 1612 | memset(state->other_states[0]->dmabuf.rawbuf + swptr, |
1612 | silence, clear_cnt); | 1613 | silence, clear_cnt); |
1613 | memset(state->other_states[1]->dmabuf.rawbuf + swptr, | 1614 | memset(state->other_states[1]->dmabuf.rawbuf + swptr, |
1614 | silence, clear_cnt); | 1615 | silence, clear_cnt); |
1615 | memset(state->other_states[2]->dmabuf.rawbuf + swptr, | 1616 | memset(state->other_states[2]->dmabuf.rawbuf + swptr, |
1616 | silence, clear_cnt); | 1617 | silence, clear_cnt); |
1617 | memset(state->other_states[3]->dmabuf.rawbuf + swptr, | 1618 | memset(state->other_states[3]->dmabuf.rawbuf + swptr, |
1618 | silence, clear_cnt); | 1619 | silence, clear_cnt); |
1619 | } | 1620 | } |
1620 | dmabuf->endcleared = 1; | 1621 | dmabuf->endcleared = 1; |
1621 | } | 1622 | } |
1622 | } else if (dmabuf->count < (signed) dmabuf->fragsize) { | 1623 | } else if (dmabuf->count < (signed) dmabuf->fragsize) { |
1623 | clear_cnt = dmabuf->fragsize; | 1624 | clear_cnt = dmabuf->fragsize; |
1624 | if ((swptr + clear_cnt) > dmabuf->dmasize) | 1625 | if ((swptr + clear_cnt) > dmabuf->dmasize) |
1625 | clear_cnt = dmabuf->dmasize - swptr; | 1626 | clear_cnt = dmabuf->dmasize - swptr; |
1626 | memset(dmabuf->rawbuf + swptr, silence, clear_cnt); | 1627 | memset(dmabuf->rawbuf + swptr, silence, clear_cnt); |
1627 | if (state->chans_num == 6) { | 1628 | if (state->chans_num == 6) { |
1628 | clear_cnt = clear_cnt / 2; | 1629 | clear_cnt = clear_cnt / 2; |
1629 | swptr = swptr / 2; | 1630 | swptr = swptr / 2; |
1630 | memset(state->other_states[0]->dmabuf.rawbuf + swptr, | 1631 | memset(state->other_states[0]->dmabuf.rawbuf + swptr, |
1631 | silence, clear_cnt); | 1632 | silence, clear_cnt); |
1632 | memset(state->other_states[1]->dmabuf.rawbuf + swptr, | 1633 | memset(state->other_states[1]->dmabuf.rawbuf + swptr, |
1633 | silence, clear_cnt); | 1634 | silence, clear_cnt); |
1634 | memset(state->other_states[2]->dmabuf.rawbuf + swptr, | 1635 | memset(state->other_states[2]->dmabuf.rawbuf + swptr, |
1635 | silence, clear_cnt); | 1636 | silence, clear_cnt); |
1636 | memset(state->other_states[3]->dmabuf.rawbuf + swptr, | 1637 | memset(state->other_states[3]->dmabuf.rawbuf + swptr, |
1637 | silence, clear_cnt); | 1638 | silence, clear_cnt); |
1638 | } | 1639 | } |
1639 | dmabuf->endcleared = 1; | 1640 | dmabuf->endcleared = 1; |
1640 | } | 1641 | } |
1641 | } | 1642 | } |
1642 | /* trident_update_ptr is called by interrupt handler or by process via | 1643 | /* trident_update_ptr is called by interrupt handler or by process via |
1643 | ioctl/poll, we only wake up the waiting process when we have more | 1644 | ioctl/poll, we only wake up the waiting process when we have more |
1644 | than 1/2 buffer free (always true for interrupt handler) */ | 1645 | than 1/2 buffer free (always true for interrupt handler) */ |
1645 | if (dmabuf->count < (signed) dmabuf->dmasize / 2) | 1646 | if (dmabuf->count < (signed) dmabuf->dmasize / 2) |
1646 | wake_up(&dmabuf->wait); | 1647 | wake_up(&dmabuf->wait); |
1647 | } | 1648 | } |
1648 | } | 1649 | } |
1649 | dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE; | 1650 | dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE; |
1650 | } | 1651 | } |
1651 | 1652 | ||
1652 | static void | 1653 | static void |
1653 | trident_address_interrupt(struct trident_card *card) | 1654 | trident_address_interrupt(struct trident_card *card) |
1654 | { | 1655 | { |
1655 | int i; | 1656 | int i; |
1656 | struct trident_state *state; | 1657 | struct trident_state *state; |
1657 | unsigned int channel; | 1658 | unsigned int channel; |
1658 | 1659 | ||
1659 | /* Update the pointers for all channels we are running. */ | 1660 | /* Update the pointers for all channels we are running. */ |
1660 | /* FIXME: should read interrupt status only once */ | 1661 | /* FIXME: should read interrupt status only once */ |
1661 | for (i = 0; i < NR_HW_CH; i++) { | 1662 | for (i = 0; i < NR_HW_CH; i++) { |
1662 | channel = 63 - i; | 1663 | channel = 63 - i; |
1663 | if (trident_check_channel_interrupt(card, channel)) { | 1664 | if (trident_check_channel_interrupt(card, channel)) { |
1664 | trident_ack_channel_interrupt(card, channel); | 1665 | trident_ack_channel_interrupt(card, channel); |
1665 | if ((state = card->states[i]) != NULL) { | 1666 | if ((state = card->states[i]) != NULL) { |
1666 | trident_update_ptr(state); | 1667 | trident_update_ptr(state); |
1667 | } else { | 1668 | } else { |
1668 | printk(KERN_WARNING "trident: spurious channel " | 1669 | printk(KERN_WARNING "trident: spurious channel " |
1669 | "irq %d.\n", channel); | 1670 | "irq %d.\n", channel); |
1670 | trident_stop_voice(card, channel); | 1671 | trident_stop_voice(card, channel); |
1671 | trident_disable_voice_irq(card, channel); | 1672 | trident_disable_voice_irq(card, channel); |
1672 | } | 1673 | } |
1673 | } | 1674 | } |
1674 | } | 1675 | } |
1675 | } | 1676 | } |
1676 | 1677 | ||
1677 | static void | 1678 | static void |
1678 | ali_hwvol_control(struct trident_card *card, int opt) | 1679 | ali_hwvol_control(struct trident_card *card, int opt) |
1679 | { | 1680 | { |
1680 | u16 dwTemp, volume[2], mute, diff, *pVol[2]; | 1681 | u16 dwTemp, volume[2], mute, diff, *pVol[2]; |
1681 | 1682 | ||
1682 | dwTemp = ali_ac97_read(card->ac97_codec[0], 0x02); | 1683 | dwTemp = ali_ac97_read(card->ac97_codec[0], 0x02); |
1683 | mute = dwTemp & 0x8000; | 1684 | mute = dwTemp & 0x8000; |
1684 | volume[0] = dwTemp & 0x001f; | 1685 | volume[0] = dwTemp & 0x001f; |
1685 | volume[1] = (dwTemp & 0x1f00) >> 8; | 1686 | volume[1] = (dwTemp & 0x1f00) >> 8; |
1686 | if (volume[0] < volume[1]) { | 1687 | if (volume[0] < volume[1]) { |
1687 | pVol[0] = &volume[0]; | 1688 | pVol[0] = &volume[0]; |
1688 | pVol[1] = &volume[1]; | 1689 | pVol[1] = &volume[1]; |
1689 | } else { | 1690 | } else { |
1690 | pVol[1] = &volume[0]; | 1691 | pVol[1] = &volume[0]; |
1691 | pVol[0] = &volume[1]; | 1692 | pVol[0] = &volume[1]; |
1692 | } | 1693 | } |
1693 | diff = *(pVol[1]) - *(pVol[0]); | 1694 | diff = *(pVol[1]) - *(pVol[0]); |
1694 | 1695 | ||
1695 | if (opt == 1) { // MUTE | 1696 | if (opt == 1) { // MUTE |
1696 | dwTemp ^= 0x8000; | 1697 | dwTemp ^= 0x8000; |
1697 | ali_ac97_write(card->ac97_codec[0], | 1698 | ali_ac97_write(card->ac97_codec[0], |
1698 | 0x02, dwTemp); | 1699 | 0x02, dwTemp); |
1699 | } else if (opt == 2) { // Down | 1700 | } else if (opt == 2) { // Down |
1700 | if (mute) | 1701 | if (mute) |
1701 | return; | 1702 | return; |
1702 | if (*(pVol[1]) < 0x001f) { | 1703 | if (*(pVol[1]) < 0x001f) { |
1703 | (*pVol[1])++; | 1704 | (*pVol[1])++; |
1704 | *(pVol[0]) = *(pVol[1]) - diff; | 1705 | *(pVol[0]) = *(pVol[1]) - diff; |
1705 | } | 1706 | } |
1706 | dwTemp &= 0xe0e0; | 1707 | dwTemp &= 0xe0e0; |
1707 | dwTemp |= (volume[0]) | (volume[1] << 8); | 1708 | dwTemp |= (volume[0]) | (volume[1] << 8); |
1708 | ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp); | 1709 | ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp); |
1709 | card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | | 1710 | card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | |
1710 | (((32 - volume[1]) * 25 / 8) << 8); | 1711 | (((32 - volume[1]) * 25 / 8) << 8); |
1711 | } else if (opt == 4) { // Up | 1712 | } else if (opt == 4) { // Up |
1712 | if (mute) | 1713 | if (mute) |
1713 | return; | 1714 | return; |
1714 | if (*(pVol[0]) > 0) { | 1715 | if (*(pVol[0]) > 0) { |
1715 | (*pVol[0])--; | 1716 | (*pVol[0])--; |
1716 | *(pVol[1]) = *(pVol[0]) + diff; | 1717 | *(pVol[1]) = *(pVol[0]) + diff; |
1717 | } | 1718 | } |
1718 | dwTemp &= 0xe0e0; | 1719 | dwTemp &= 0xe0e0; |
1719 | dwTemp |= (volume[0]) | (volume[1] << 8); | 1720 | dwTemp |= (volume[0]) | (volume[1] << 8); |
1720 | ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp); | 1721 | ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp); |
1721 | card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | | 1722 | card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | |
1722 | (((32 - volume[1]) * 25 / 8) << 8); | 1723 | (((32 - volume[1]) * 25 / 8) << 8); |
1723 | } else { | 1724 | } else { |
1724 | /* Nothing needs doing */ | 1725 | /* Nothing needs doing */ |
1725 | } | 1726 | } |
1726 | } | 1727 | } |
1727 | 1728 | ||
1728 | /* | 1729 | /* |
1729 | * Re-enable reporting of vol change after 0.1 seconds | 1730 | * Re-enable reporting of vol change after 0.1 seconds |
1730 | */ | 1731 | */ |
1731 | 1732 | ||
1732 | static void | 1733 | static void |
1733 | ali_timeout(unsigned long ptr) | 1734 | ali_timeout(unsigned long ptr) |
1734 | { | 1735 | { |
1735 | struct trident_card *card = (struct trident_card *) ptr; | 1736 | struct trident_card *card = (struct trident_card *) ptr; |
1736 | u16 temp = 0; | 1737 | u16 temp = 0; |
1737 | 1738 | ||
1738 | /* Enable GPIO IRQ (MISCINT bit 18h) */ | 1739 | /* Enable GPIO IRQ (MISCINT bit 18h) */ |
1739 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); | 1740 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); |
1740 | temp |= 0x0004; | 1741 | temp |= 0x0004; |
1741 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); | 1742 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); |
1742 | } | 1743 | } |
1743 | 1744 | ||
1744 | /* | 1745 | /* |
1745 | * Set up the timer to clear the vol change notification | 1746 | * Set up the timer to clear the vol change notification |
1746 | */ | 1747 | */ |
1747 | 1748 | ||
1748 | static void | 1749 | static void |
1749 | ali_set_timer(struct trident_card *card) | 1750 | ali_set_timer(struct trident_card *card) |
1750 | { | 1751 | { |
1751 | /* Add Timer Routine to Enable GPIO IRQ */ | 1752 | /* Add Timer Routine to Enable GPIO IRQ */ |
1752 | del_timer(&card->timer); /* Never queue twice */ | 1753 | del_timer(&card->timer); /* Never queue twice */ |
1753 | card->timer.function = ali_timeout; | 1754 | card->timer.function = ali_timeout; |
1754 | card->timer.data = (unsigned long) card; | 1755 | card->timer.data = (unsigned long) card; |
1755 | card->timer.expires = jiffies + HZ / 10; | 1756 | card->timer.expires = jiffies + HZ / 10; |
1756 | add_timer(&card->timer); | 1757 | add_timer(&card->timer); |
1757 | } | 1758 | } |
1758 | 1759 | ||
1759 | /* | 1760 | /* |
1760 | * Process a GPIO event | 1761 | * Process a GPIO event |
1761 | */ | 1762 | */ |
1762 | 1763 | ||
1763 | static void | 1764 | static void |
1764 | ali_queue_task(struct trident_card *card, int opt) | 1765 | ali_queue_task(struct trident_card *card, int opt) |
1765 | { | 1766 | { |
1766 | u16 temp; | 1767 | u16 temp; |
1767 | 1768 | ||
1768 | /* Disable GPIO IRQ (MISCINT bit 18h) */ | 1769 | /* Disable GPIO IRQ (MISCINT bit 18h) */ |
1769 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); | 1770 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); |
1770 | temp &= (u16) (~0x0004); | 1771 | temp &= (u16) (~0x0004); |
1771 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); | 1772 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); |
1772 | 1773 | ||
1773 | /* Adjust the volume */ | 1774 | /* Adjust the volume */ |
1774 | ali_hwvol_control(card, opt); | 1775 | ali_hwvol_control(card, opt); |
1775 | 1776 | ||
1776 | /* Set the timer for 1/10th sec */ | 1777 | /* Set the timer for 1/10th sec */ |
1777 | ali_set_timer(card); | 1778 | ali_set_timer(card); |
1778 | } | 1779 | } |
1779 | 1780 | ||
1780 | static void | 1781 | static void |
1781 | cyber_address_interrupt(struct trident_card *card) | 1782 | cyber_address_interrupt(struct trident_card *card) |
1782 | { | 1783 | { |
1783 | int i, irq_status; | 1784 | int i, irq_status; |
1784 | struct trident_state *state; | 1785 | struct trident_state *state; |
1785 | unsigned int channel; | 1786 | unsigned int channel; |
1786 | 1787 | ||
1787 | /* Update the pointers for all channels we are running. */ | 1788 | /* Update the pointers for all channels we are running. */ |
1788 | /* FIXED: read interrupt status only once */ | 1789 | /* FIXED: read interrupt status only once */ |
1789 | irq_status = inl(TRID_REG(card, T4D_AINT_A)); | 1790 | irq_status = inl(TRID_REG(card, T4D_AINT_A)); |
1790 | 1791 | ||
1791 | pr_debug("cyber_address_interrupt: irq_status 0x%X\n", irq_status); | 1792 | pr_debug("cyber_address_interrupt: irq_status 0x%X\n", irq_status); |
1792 | 1793 | ||
1793 | for (i = 0; i < NR_HW_CH; i++) { | 1794 | for (i = 0; i < NR_HW_CH; i++) { |
1794 | channel = 31 - i; | 1795 | channel = 31 - i; |
1795 | if (irq_status & (1 << channel)) { | 1796 | if (irq_status & (1 << channel)) { |
1796 | /* clear bit by writing a 1, zeroes are ignored */ | 1797 | /* clear bit by writing a 1, zeroes are ignored */ |
1797 | outl((1 << channel), TRID_REG(card, T4D_AINT_A)); | 1798 | outl((1 << channel), TRID_REG(card, T4D_AINT_A)); |
1798 | 1799 | ||
1799 | pr_debug("cyber_interrupt: channel %d\n", channel); | 1800 | pr_debug("cyber_interrupt: channel %d\n", channel); |
1800 | 1801 | ||
1801 | if ((state = card->states[i]) != NULL) { | 1802 | if ((state = card->states[i]) != NULL) { |
1802 | trident_update_ptr(state); | 1803 | trident_update_ptr(state); |
1803 | } else { | 1804 | } else { |
1804 | printk(KERN_WARNING "cyber5050: spurious " | 1805 | printk(KERN_WARNING "cyber5050: spurious " |
1805 | "channel irq %d.\n", channel); | 1806 | "channel irq %d.\n", channel); |
1806 | trident_stop_voice(card, channel); | 1807 | trident_stop_voice(card, channel); |
1807 | trident_disable_voice_irq(card, channel); | 1808 | trident_disable_voice_irq(card, channel); |
1808 | } | 1809 | } |
1809 | } | 1810 | } |
1810 | } | 1811 | } |
1811 | } | 1812 | } |
1812 | 1813 | ||
1813 | static irqreturn_t | 1814 | static irqreturn_t |
1814 | trident_interrupt(int irq, void *dev_id) | 1815 | trident_interrupt(int irq, void *dev_id) |
1815 | { | 1816 | { |
1816 | struct trident_card *card = (struct trident_card *) dev_id; | 1817 | struct trident_card *card = (struct trident_card *) dev_id; |
1817 | u32 event; | 1818 | u32 event; |
1818 | u32 gpio; | 1819 | u32 gpio; |
1819 | 1820 | ||
1820 | spin_lock(&card->lock); | 1821 | spin_lock(&card->lock); |
1821 | event = inl(TRID_REG(card, T4D_MISCINT)); | 1822 | event = inl(TRID_REG(card, T4D_MISCINT)); |
1822 | 1823 | ||
1823 | pr_debug("trident: trident_interrupt called, MISCINT = 0x%08x\n", | 1824 | pr_debug("trident: trident_interrupt called, MISCINT = 0x%08x\n", |
1824 | event); | 1825 | event); |
1825 | 1826 | ||
1826 | if (event & ADDRESS_IRQ) { | 1827 | if (event & ADDRESS_IRQ) { |
1827 | card->address_interrupt(card); | 1828 | card->address_interrupt(card); |
1828 | } | 1829 | } |
1829 | 1830 | ||
1830 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 1831 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
1831 | /* GPIO IRQ (H/W Volume Control) */ | 1832 | /* GPIO IRQ (H/W Volume Control) */ |
1832 | event = inl(TRID_REG(card, T4D_MISCINT)); | 1833 | event = inl(TRID_REG(card, T4D_MISCINT)); |
1833 | if (event & (1 << 25)) { | 1834 | if (event & (1 << 25)) { |
1834 | gpio = inl(TRID_REG(card, ALI_GPIO)); | 1835 | gpio = inl(TRID_REG(card, ALI_GPIO)); |
1835 | if (!timer_pending(&card->timer)) | 1836 | if (!timer_pending(&card->timer)) |
1836 | ali_queue_task(card, gpio & 0x07); | 1837 | ali_queue_task(card, gpio & 0x07); |
1837 | } | 1838 | } |
1838 | event = inl(TRID_REG(card, T4D_MISCINT)); | 1839 | event = inl(TRID_REG(card, T4D_MISCINT)); |
1839 | outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), | 1840 | outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), |
1840 | TRID_REG(card, T4D_MISCINT)); | 1841 | TRID_REG(card, T4D_MISCINT)); |
1841 | spin_unlock(&card->lock); | 1842 | spin_unlock(&card->lock); |
1842 | return IRQ_HANDLED; | 1843 | return IRQ_HANDLED; |
1843 | } | 1844 | } |
1844 | 1845 | ||
1845 | /* manually clear interrupt status, bad hardware design, blame T^2 */ | 1846 | /* manually clear interrupt status, bad hardware design, blame T^2 */ |
1846 | outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), | 1847 | outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), |
1847 | TRID_REG(card, T4D_MISCINT)); | 1848 | TRID_REG(card, T4D_MISCINT)); |
1848 | spin_unlock(&card->lock); | 1849 | spin_unlock(&card->lock); |
1849 | return IRQ_HANDLED; | 1850 | return IRQ_HANDLED; |
1850 | } | 1851 | } |
1851 | 1852 | ||
1852 | /* in this loop, dmabuf.count signifies the amount of data that is waiting */ | 1853 | /* in this loop, dmabuf.count signifies the amount of data that is waiting */ |
1853 | /* to be copied to the user's buffer. it is filled by the dma machine and */ | 1854 | /* to be copied to the user's buffer. it is filled by the dma machine and */ |
1854 | /* drained by this loop. */ | 1855 | /* drained by this loop. */ |
1855 | static ssize_t | 1856 | static ssize_t |
1856 | trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) | 1857 | trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) |
1857 | { | 1858 | { |
1858 | struct trident_state *state = (struct trident_state *)file->private_data; | 1859 | struct trident_state *state = (struct trident_state *)file->private_data; |
1859 | struct dmabuf *dmabuf = &state->dmabuf; | 1860 | struct dmabuf *dmabuf = &state->dmabuf; |
1860 | ssize_t ret = 0; | 1861 | ssize_t ret = 0; |
1861 | unsigned long flags; | 1862 | unsigned long flags; |
1862 | unsigned swptr; | 1863 | unsigned swptr; |
1863 | int cnt; | 1864 | int cnt; |
1864 | 1865 | ||
1865 | pr_debug("trident: trident_read called, count = %zd\n", count); | 1866 | pr_debug("trident: trident_read called, count = %zd\n", count); |
1866 | 1867 | ||
1867 | VALIDATE_STATE(state); | 1868 | VALIDATE_STATE(state); |
1868 | 1869 | ||
1869 | if (dmabuf->mapped) | 1870 | if (dmabuf->mapped) |
1870 | return -ENXIO; | 1871 | return -ENXIO; |
1871 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 1872 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
1872 | return -EFAULT; | 1873 | return -EFAULT; |
1873 | 1874 | ||
1874 | mutex_lock(&state->sem); | 1875 | mutex_lock(&state->sem); |
1875 | if (!dmabuf->ready && (ret = prog_dmabuf_record(state))) | 1876 | if (!dmabuf->ready && (ret = prog_dmabuf_record(state))) |
1876 | goto out; | 1877 | goto out; |
1877 | 1878 | ||
1878 | while (count > 0) { | 1879 | while (count > 0) { |
1879 | spin_lock_irqsave(&state->card->lock, flags); | 1880 | spin_lock_irqsave(&state->card->lock, flags); |
1880 | if (dmabuf->count > (signed) dmabuf->dmasize) { | 1881 | if (dmabuf->count > (signed) dmabuf->dmasize) { |
1881 | /* buffer overrun, we are recovering from */ | 1882 | /* buffer overrun, we are recovering from */ |
1882 | /* sleep_on_timeout, resync hwptr and swptr, */ | 1883 | /* sleep_on_timeout, resync hwptr and swptr, */ |
1883 | /* make process flush the buffer */ | 1884 | /* make process flush the buffer */ |
1884 | dmabuf->count = dmabuf->dmasize; | 1885 | dmabuf->count = dmabuf->dmasize; |
1885 | dmabuf->swptr = dmabuf->hwptr; | 1886 | dmabuf->swptr = dmabuf->hwptr; |
1886 | } | 1887 | } |
1887 | swptr = dmabuf->swptr; | 1888 | swptr = dmabuf->swptr; |
1888 | cnt = dmabuf->dmasize - swptr; | 1889 | cnt = dmabuf->dmasize - swptr; |
1889 | if (dmabuf->count < cnt) | 1890 | if (dmabuf->count < cnt) |
1890 | cnt = dmabuf->count; | 1891 | cnt = dmabuf->count; |
1891 | spin_unlock_irqrestore(&state->card->lock, flags); | 1892 | spin_unlock_irqrestore(&state->card->lock, flags); |
1892 | 1893 | ||
1893 | if (cnt > count) | 1894 | if (cnt > count) |
1894 | cnt = count; | 1895 | cnt = count; |
1895 | if (cnt <= 0) { | 1896 | if (cnt <= 0) { |
1896 | unsigned long tmo; | 1897 | unsigned long tmo; |
1897 | /* buffer is empty, start the dma machine and */ | 1898 | /* buffer is empty, start the dma machine and */ |
1898 | /* wait for data to be recorded */ | 1899 | /* wait for data to be recorded */ |
1899 | start_adc(state); | 1900 | start_adc(state); |
1900 | if (file->f_flags & O_NONBLOCK) { | 1901 | if (file->f_flags & O_NONBLOCK) { |
1901 | if (!ret) | 1902 | if (!ret) |
1902 | ret = -EAGAIN; | 1903 | ret = -EAGAIN; |
1903 | goto out; | 1904 | goto out; |
1904 | } | 1905 | } |
1905 | 1906 | ||
1906 | mutex_unlock(&state->sem); | 1907 | mutex_unlock(&state->sem); |
1907 | /* No matter how much space left in the buffer, */ | 1908 | /* No matter how much space left in the buffer, */ |
1908 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ | 1909 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ |
1909 | /* when address engine interrupts */ | 1910 | /* when address engine interrupts */ |
1910 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); | 1911 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); |
1911 | tmo >>= sample_shift[dmabuf->fmt]; | 1912 | tmo >>= sample_shift[dmabuf->fmt]; |
1912 | /* There are two situations when sleep_on_timeout returns, one is when | 1913 | /* There are two situations when sleep_on_timeout returns, one is when |
1913 | the interrupt is serviced correctly and the process is waked up by | 1914 | the interrupt is serviced correctly and the process is waked up by |
1914 | ISR ON TIME. Another is when timeout is expired, which means that | 1915 | ISR ON TIME. Another is when timeout is expired, which means that |
1915 | either interrupt is NOT serviced correctly (pending interrupt) or it | 1916 | either interrupt is NOT serviced correctly (pending interrupt) or it |
1916 | is TOO LATE for the process to be scheduled to run (scheduler latency) | 1917 | is TOO LATE for the process to be scheduled to run (scheduler latency) |
1917 | which results in a (potential) buffer overrun. And worse, there is | 1918 | which results in a (potential) buffer overrun. And worse, there is |
1918 | NOTHING we can do to prevent it. */ | 1919 | NOTHING we can do to prevent it. */ |
1919 | if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { | 1920 | if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { |
1920 | pr_debug(KERN_ERR "trident: recording schedule timeout, " | 1921 | pr_debug(KERN_ERR "trident: recording schedule timeout, " |
1921 | "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", | 1922 | "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", |
1922 | dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, | 1923 | dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, |
1923 | dmabuf->hwptr, dmabuf->swptr); | 1924 | dmabuf->hwptr, dmabuf->swptr); |
1924 | 1925 | ||
1925 | /* a buffer overrun, we delay the recovery until next time the | 1926 | /* a buffer overrun, we delay the recovery until next time the |
1926 | while loop begin and we REALLY have space to record */ | 1927 | while loop begin and we REALLY have space to record */ |
1927 | } | 1928 | } |
1928 | if (signal_pending(current)) { | 1929 | if (signal_pending(current)) { |
1929 | if (!ret) | 1930 | if (!ret) |
1930 | ret = -ERESTARTSYS; | 1931 | ret = -ERESTARTSYS; |
1931 | goto out; | 1932 | goto out; |
1932 | } | 1933 | } |
1933 | mutex_lock(&state->sem); | 1934 | mutex_lock(&state->sem); |
1934 | if (dmabuf->mapped) { | 1935 | if (dmabuf->mapped) { |
1935 | if (!ret) | 1936 | if (!ret) |
1936 | ret = -ENXIO; | 1937 | ret = -ENXIO; |
1937 | goto out; | 1938 | goto out; |
1938 | } | 1939 | } |
1939 | continue; | 1940 | continue; |
1940 | } | 1941 | } |
1941 | 1942 | ||
1942 | if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { | 1943 | if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { |
1943 | if (!ret) | 1944 | if (!ret) |
1944 | ret = -EFAULT; | 1945 | ret = -EFAULT; |
1945 | goto out; | 1946 | goto out; |
1946 | } | 1947 | } |
1947 | 1948 | ||
1948 | swptr = (swptr + cnt) % dmabuf->dmasize; | 1949 | swptr = (swptr + cnt) % dmabuf->dmasize; |
1949 | 1950 | ||
1950 | spin_lock_irqsave(&state->card->lock, flags); | 1951 | spin_lock_irqsave(&state->card->lock, flags); |
1951 | dmabuf->swptr = swptr; | 1952 | dmabuf->swptr = swptr; |
1952 | dmabuf->count -= cnt; | 1953 | dmabuf->count -= cnt; |
1953 | spin_unlock_irqrestore(&state->card->lock, flags); | 1954 | spin_unlock_irqrestore(&state->card->lock, flags); |
1954 | 1955 | ||
1955 | count -= cnt; | 1956 | count -= cnt; |
1956 | buffer += cnt; | 1957 | buffer += cnt; |
1957 | ret += cnt; | 1958 | ret += cnt; |
1958 | start_adc(state); | 1959 | start_adc(state); |
1959 | } | 1960 | } |
1960 | out: | 1961 | out: |
1961 | mutex_unlock(&state->sem); | 1962 | mutex_unlock(&state->sem); |
1962 | return ret; | 1963 | return ret; |
1963 | } | 1964 | } |
1964 | 1965 | ||
1965 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to | 1966 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to |
1966 | the soundcard. it is drained by the dma machine and filled by this loop. */ | 1967 | the soundcard. it is drained by the dma machine and filled by this loop. */ |
1967 | 1968 | ||
1968 | static ssize_t | 1969 | static ssize_t |
1969 | trident_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) | 1970 | trident_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) |
1970 | { | 1971 | { |
1971 | struct trident_state *state = (struct trident_state *)file->private_data; | 1972 | struct trident_state *state = (struct trident_state *)file->private_data; |
1972 | struct dmabuf *dmabuf = &state->dmabuf; | 1973 | struct dmabuf *dmabuf = &state->dmabuf; |
1973 | ssize_t ret; | 1974 | ssize_t ret; |
1974 | unsigned long flags; | 1975 | unsigned long flags; |
1975 | unsigned swptr; | 1976 | unsigned swptr; |
1976 | int cnt; | 1977 | int cnt; |
1977 | unsigned int state_cnt; | 1978 | unsigned int state_cnt; |
1978 | unsigned int copy_count; | 1979 | unsigned int copy_count; |
1979 | int lret; /* for lock_set_fmt */ | 1980 | int lret; /* for lock_set_fmt */ |
1980 | 1981 | ||
1981 | pr_debug("trident: trident_write called, count = %zd\n", count); | 1982 | pr_debug("trident: trident_write called, count = %zd\n", count); |
1982 | 1983 | ||
1983 | VALIDATE_STATE(state); | 1984 | VALIDATE_STATE(state); |
1984 | 1985 | ||
1985 | /* | 1986 | /* |
1986 | * Guard against an mmap or ioctl while writing | 1987 | * Guard against an mmap or ioctl while writing |
1987 | */ | 1988 | */ |
1988 | 1989 | ||
1989 | mutex_lock(&state->sem); | 1990 | mutex_lock(&state->sem); |
1990 | 1991 | ||
1991 | if (dmabuf->mapped) { | 1992 | if (dmabuf->mapped) { |
1992 | ret = -ENXIO; | 1993 | ret = -ENXIO; |
1993 | goto out; | 1994 | goto out; |
1994 | } | 1995 | } |
1995 | if (!dmabuf->ready && (ret = prog_dmabuf_playback(state))) | 1996 | if (!dmabuf->ready && (ret = prog_dmabuf_playback(state))) |
1996 | goto out; | 1997 | goto out; |
1997 | 1998 | ||
1998 | if (!access_ok(VERIFY_READ, buffer, count)) { | 1999 | if (!access_ok(VERIFY_READ, buffer, count)) { |
1999 | ret = -EFAULT; | 2000 | ret = -EFAULT; |
2000 | goto out; | 2001 | goto out; |
2001 | } | 2002 | } |
2002 | 2003 | ||
2003 | ret = 0; | 2004 | ret = 0; |
2004 | 2005 | ||
2005 | while (count > 0) { | 2006 | while (count > 0) { |
2006 | spin_lock_irqsave(&state->card->lock, flags); | 2007 | spin_lock_irqsave(&state->card->lock, flags); |
2007 | if (dmabuf->count < 0) { | 2008 | if (dmabuf->count < 0) { |
2008 | /* buffer underrun, we are recovering from */ | 2009 | /* buffer underrun, we are recovering from */ |
2009 | /* sleep_on_timeout, resync hwptr and swptr */ | 2010 | /* sleep_on_timeout, resync hwptr and swptr */ |
2010 | dmabuf->count = 0; | 2011 | dmabuf->count = 0; |
2011 | dmabuf->swptr = dmabuf->hwptr; | 2012 | dmabuf->swptr = dmabuf->hwptr; |
2012 | } | 2013 | } |
2013 | swptr = dmabuf->swptr; | 2014 | swptr = dmabuf->swptr; |
2014 | cnt = dmabuf->dmasize - swptr; | 2015 | cnt = dmabuf->dmasize - swptr; |
2015 | if (dmabuf->count + cnt > dmabuf->dmasize) | 2016 | if (dmabuf->count + cnt > dmabuf->dmasize) |
2016 | cnt = dmabuf->dmasize - dmabuf->count; | 2017 | cnt = dmabuf->dmasize - dmabuf->count; |
2017 | spin_unlock_irqrestore(&state->card->lock, flags); | 2018 | spin_unlock_irqrestore(&state->card->lock, flags); |
2018 | 2019 | ||
2019 | if (cnt > count) | 2020 | if (cnt > count) |
2020 | cnt = count; | 2021 | cnt = count; |
2021 | if (cnt <= 0) { | 2022 | if (cnt <= 0) { |
2022 | unsigned long tmo; | 2023 | unsigned long tmo; |
2023 | /* buffer is full, start the dma machine and */ | 2024 | /* buffer is full, start the dma machine and */ |
2024 | /* wait for data to be played */ | 2025 | /* wait for data to be played */ |
2025 | start_dac(state); | 2026 | start_dac(state); |
2026 | if (file->f_flags & O_NONBLOCK) { | 2027 | if (file->f_flags & O_NONBLOCK) { |
2027 | if (!ret) | 2028 | if (!ret) |
2028 | ret = -EAGAIN; | 2029 | ret = -EAGAIN; |
2029 | goto out; | 2030 | goto out; |
2030 | } | 2031 | } |
2031 | /* No matter how much data left in the buffer, */ | 2032 | /* No matter how much data left in the buffer, */ |
2032 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ | 2033 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ |
2033 | /* when address engine interrupts */ | 2034 | /* when address engine interrupts */ |
2034 | lock_set_fmt(state); | 2035 | lock_set_fmt(state); |
2035 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); | 2036 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); |
2036 | tmo >>= sample_shift[dmabuf->fmt]; | 2037 | tmo >>= sample_shift[dmabuf->fmt]; |
2037 | unlock_set_fmt(state); | 2038 | unlock_set_fmt(state); |
2038 | mutex_unlock(&state->sem); | 2039 | mutex_unlock(&state->sem); |
2039 | 2040 | ||
2040 | /* There are two situations when sleep_on_timeout */ | 2041 | /* There are two situations when sleep_on_timeout */ |
2041 | /* returns, one is when the interrupt is serviced */ | 2042 | /* returns, one is when the interrupt is serviced */ |
2042 | /* correctly and the process is waked up by ISR */ | 2043 | /* correctly and the process is waked up by ISR */ |
2043 | /* ON TIME. Another is when timeout is expired, which */ | 2044 | /* ON TIME. Another is when timeout is expired, which */ |
2044 | /* means that either interrupt is NOT serviced */ | 2045 | /* means that either interrupt is NOT serviced */ |
2045 | /* correctly (pending interrupt) or it is TOO LATE */ | 2046 | /* correctly (pending interrupt) or it is TOO LATE */ |
2046 | /* for the process to be scheduled to run */ | 2047 | /* for the process to be scheduled to run */ |
2047 | /* (scheduler latency) which results in a (potential) */ | 2048 | /* (scheduler latency) which results in a (potential) */ |
2048 | /* buffer underrun. And worse, there is NOTHING we */ | 2049 | /* buffer underrun. And worse, there is NOTHING we */ |
2049 | /* can do to prevent it. */ | 2050 | /* can do to prevent it. */ |
2050 | if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { | 2051 | if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { |
2051 | pr_debug(KERN_ERR "trident: playback schedule " | 2052 | pr_debug(KERN_ERR "trident: playback schedule " |
2052 | "timeout, dmasz %u fragsz %u count %i " | 2053 | "timeout, dmasz %u fragsz %u count %i " |
2053 | "hwptr %u swptr %u\n", dmabuf->dmasize, | 2054 | "hwptr %u swptr %u\n", dmabuf->dmasize, |
2054 | dmabuf->fragsize, dmabuf->count, | 2055 | dmabuf->fragsize, dmabuf->count, |
2055 | dmabuf->hwptr, dmabuf->swptr); | 2056 | dmabuf->hwptr, dmabuf->swptr); |
2056 | 2057 | ||
2057 | /* a buffer underrun, we delay the recovery */ | 2058 | /* a buffer underrun, we delay the recovery */ |
2058 | /* until next time the while loop begin and */ | 2059 | /* until next time the while loop begin and */ |
2059 | /* we REALLY have data to play */ | 2060 | /* we REALLY have data to play */ |
2060 | } | 2061 | } |
2061 | if (signal_pending(current)) { | 2062 | if (signal_pending(current)) { |
2062 | if (!ret) | 2063 | if (!ret) |
2063 | ret = -ERESTARTSYS; | 2064 | ret = -ERESTARTSYS; |
2064 | goto out_nolock; | 2065 | goto out_nolock; |
2065 | } | 2066 | } |
2066 | mutex_lock(&state->sem); | 2067 | mutex_lock(&state->sem); |
2067 | if (dmabuf->mapped) { | 2068 | if (dmabuf->mapped) { |
2068 | if (!ret) | 2069 | if (!ret) |
2069 | ret = -ENXIO; | 2070 | ret = -ENXIO; |
2070 | goto out; | 2071 | goto out; |
2071 | } | 2072 | } |
2072 | continue; | 2073 | continue; |
2073 | } | 2074 | } |
2074 | if ((lret = lock_set_fmt(state)) < 0) { | 2075 | if ((lret = lock_set_fmt(state)) < 0) { |
2075 | ret = lret; | 2076 | ret = lret; |
2076 | goto out; | 2077 | goto out; |
2077 | } | 2078 | } |
2078 | 2079 | ||
2079 | if (state->chans_num == 6) { | 2080 | if (state->chans_num == 6) { |
2080 | copy_count = 0; | 2081 | copy_count = 0; |
2081 | state_cnt = 0; | 2082 | state_cnt = 0; |
2082 | if (ali_write_5_1(state, buffer, cnt, ©_count, | 2083 | if (ali_write_5_1(state, buffer, cnt, ©_count, |
2083 | &state_cnt) == -EFAULT) { | 2084 | &state_cnt) == -EFAULT) { |
2084 | if (state_cnt) { | 2085 | if (state_cnt) { |
2085 | swptr = (swptr + state_cnt) % dmabuf->dmasize; | 2086 | swptr = (swptr + state_cnt) % dmabuf->dmasize; |
2086 | spin_lock_irqsave(&state->card->lock, flags); | 2087 | spin_lock_irqsave(&state->card->lock, flags); |
2087 | dmabuf->swptr = swptr; | 2088 | dmabuf->swptr = swptr; |
2088 | dmabuf->count += state_cnt; | 2089 | dmabuf->count += state_cnt; |
2089 | dmabuf->endcleared = 0; | 2090 | dmabuf->endcleared = 0; |
2090 | spin_unlock_irqrestore(&state->card->lock, flags); | 2091 | spin_unlock_irqrestore(&state->card->lock, flags); |
2091 | } | 2092 | } |
2092 | ret += copy_count; | 2093 | ret += copy_count; |
2093 | if (!ret) | 2094 | if (!ret) |
2094 | ret = -EFAULT; | 2095 | ret = -EFAULT; |
2095 | unlock_set_fmt(state); | 2096 | unlock_set_fmt(state); |
2096 | goto out; | 2097 | goto out; |
2097 | } | 2098 | } |
2098 | } else { | 2099 | } else { |
2099 | if (copy_from_user(dmabuf->rawbuf + swptr, | 2100 | if (copy_from_user(dmabuf->rawbuf + swptr, |
2100 | buffer, cnt)) { | 2101 | buffer, cnt)) { |
2101 | if (!ret) | 2102 | if (!ret) |
2102 | ret = -EFAULT; | 2103 | ret = -EFAULT; |
2103 | unlock_set_fmt(state); | 2104 | unlock_set_fmt(state); |
2104 | goto out; | 2105 | goto out; |
2105 | } | 2106 | } |
2106 | state_cnt = cnt; | 2107 | state_cnt = cnt; |
2107 | } | 2108 | } |
2108 | unlock_set_fmt(state); | 2109 | unlock_set_fmt(state); |
2109 | 2110 | ||
2110 | swptr = (swptr + state_cnt) % dmabuf->dmasize; | 2111 | swptr = (swptr + state_cnt) % dmabuf->dmasize; |
2111 | 2112 | ||
2112 | spin_lock_irqsave(&state->card->lock, flags); | 2113 | spin_lock_irqsave(&state->card->lock, flags); |
2113 | dmabuf->swptr = swptr; | 2114 | dmabuf->swptr = swptr; |
2114 | dmabuf->count += state_cnt; | 2115 | dmabuf->count += state_cnt; |
2115 | dmabuf->endcleared = 0; | 2116 | dmabuf->endcleared = 0; |
2116 | spin_unlock_irqrestore(&state->card->lock, flags); | 2117 | spin_unlock_irqrestore(&state->card->lock, flags); |
2117 | 2118 | ||
2118 | count -= cnt; | 2119 | count -= cnt; |
2119 | buffer += cnt; | 2120 | buffer += cnt; |
2120 | ret += cnt; | 2121 | ret += cnt; |
2121 | start_dac(state); | 2122 | start_dac(state); |
2122 | } | 2123 | } |
2123 | out: | 2124 | out: |
2124 | mutex_unlock(&state->sem); | 2125 | mutex_unlock(&state->sem); |
2125 | out_nolock: | 2126 | out_nolock: |
2126 | return ret; | 2127 | return ret; |
2127 | } | 2128 | } |
2128 | 2129 | ||
2129 | /* No kernel lock - we have our own spinlock */ | 2130 | /* No kernel lock - we have our own spinlock */ |
2130 | static unsigned int | 2131 | static unsigned int |
2131 | trident_poll(struct file *file, struct poll_table_struct *wait) | 2132 | trident_poll(struct file *file, struct poll_table_struct *wait) |
2132 | { | 2133 | { |
2133 | struct trident_state *state = (struct trident_state *)file->private_data; | 2134 | struct trident_state *state = (struct trident_state *)file->private_data; |
2134 | struct dmabuf *dmabuf = &state->dmabuf; | 2135 | struct dmabuf *dmabuf = &state->dmabuf; |
2135 | unsigned long flags; | 2136 | unsigned long flags; |
2136 | unsigned int mask = 0; | 2137 | unsigned int mask = 0; |
2137 | 2138 | ||
2138 | VALIDATE_STATE(state); | 2139 | VALIDATE_STATE(state); |
2139 | 2140 | ||
2140 | /* | 2141 | /* |
2141 | * Guard against a parallel poll and write causing multiple | 2142 | * Guard against a parallel poll and write causing multiple |
2142 | * prog_dmabuf events | 2143 | * prog_dmabuf events |
2143 | */ | 2144 | */ |
2144 | 2145 | ||
2145 | mutex_lock(&state->sem); | 2146 | mutex_lock(&state->sem); |
2146 | 2147 | ||
2147 | if (file->f_mode & FMODE_WRITE) { | 2148 | if (file->f_mode & FMODE_WRITE) { |
2148 | if (!dmabuf->ready && prog_dmabuf_playback(state)) { | 2149 | if (!dmabuf->ready && prog_dmabuf_playback(state)) { |
2149 | mutex_unlock(&state->sem); | 2150 | mutex_unlock(&state->sem); |
2150 | return 0; | 2151 | return 0; |
2151 | } | 2152 | } |
2152 | poll_wait(file, &dmabuf->wait, wait); | 2153 | poll_wait(file, &dmabuf->wait, wait); |
2153 | } | 2154 | } |
2154 | if (file->f_mode & FMODE_READ) { | 2155 | if (file->f_mode & FMODE_READ) { |
2155 | if (!dmabuf->ready && prog_dmabuf_record(state)) { | 2156 | if (!dmabuf->ready && prog_dmabuf_record(state)) { |
2156 | mutex_unlock(&state->sem); | 2157 | mutex_unlock(&state->sem); |
2157 | return 0; | 2158 | return 0; |
2158 | } | 2159 | } |
2159 | poll_wait(file, &dmabuf->wait, wait); | 2160 | poll_wait(file, &dmabuf->wait, wait); |
2160 | } | 2161 | } |
2161 | 2162 | ||
2162 | mutex_unlock(&state->sem); | 2163 | mutex_unlock(&state->sem); |
2163 | 2164 | ||
2164 | spin_lock_irqsave(&state->card->lock, flags); | 2165 | spin_lock_irqsave(&state->card->lock, flags); |
2165 | trident_update_ptr(state); | 2166 | trident_update_ptr(state); |
2166 | if (file->f_mode & FMODE_READ) { | 2167 | if (file->f_mode & FMODE_READ) { |
2167 | if (dmabuf->count >= (signed) dmabuf->fragsize) | 2168 | if (dmabuf->count >= (signed) dmabuf->fragsize) |
2168 | mask |= POLLIN | POLLRDNORM; | 2169 | mask |= POLLIN | POLLRDNORM; |
2169 | } | 2170 | } |
2170 | if (file->f_mode & FMODE_WRITE) { | 2171 | if (file->f_mode & FMODE_WRITE) { |
2171 | if (dmabuf->mapped) { | 2172 | if (dmabuf->mapped) { |
2172 | if (dmabuf->count >= (signed) dmabuf->fragsize) | 2173 | if (dmabuf->count >= (signed) dmabuf->fragsize) |
2173 | mask |= POLLOUT | POLLWRNORM; | 2174 | mask |= POLLOUT | POLLWRNORM; |
2174 | } else { | 2175 | } else { |
2175 | if ((signed) dmabuf->dmasize >= dmabuf->count + | 2176 | if ((signed) dmabuf->dmasize >= dmabuf->count + |
2176 | (signed) dmabuf->fragsize) | 2177 | (signed) dmabuf->fragsize) |
2177 | mask |= POLLOUT | POLLWRNORM; | 2178 | mask |= POLLOUT | POLLWRNORM; |
2178 | } | 2179 | } |
2179 | } | 2180 | } |
2180 | spin_unlock_irqrestore(&state->card->lock, flags); | 2181 | spin_unlock_irqrestore(&state->card->lock, flags); |
2181 | 2182 | ||
2182 | return mask; | 2183 | return mask; |
2183 | } | 2184 | } |
2184 | 2185 | ||
2185 | static int | 2186 | static int |
2186 | trident_mmap(struct file *file, struct vm_area_struct *vma) | 2187 | trident_mmap(struct file *file, struct vm_area_struct *vma) |
2187 | { | 2188 | { |
2188 | struct trident_state *state = (struct trident_state *)file->private_data; | 2189 | struct trident_state *state = (struct trident_state *)file->private_data; |
2189 | struct dmabuf *dmabuf = &state->dmabuf; | 2190 | struct dmabuf *dmabuf = &state->dmabuf; |
2190 | int ret = -EINVAL; | 2191 | int ret = -EINVAL; |
2191 | unsigned long size; | 2192 | unsigned long size; |
2192 | 2193 | ||
2193 | VALIDATE_STATE(state); | 2194 | VALIDATE_STATE(state); |
2194 | 2195 | ||
2195 | /* | 2196 | /* |
2196 | * Lock against poll read write or mmap creating buffers. Also lock | 2197 | * Lock against poll read write or mmap creating buffers. Also lock |
2197 | * a read or write against an mmap. | 2198 | * a read or write against an mmap. |
2198 | */ | 2199 | */ |
2199 | 2200 | ||
2200 | mutex_lock(&state->sem); | 2201 | mutex_lock(&state->sem); |
2201 | 2202 | ||
2202 | if (vma->vm_flags & VM_WRITE) { | 2203 | if (vma->vm_flags & VM_WRITE) { |
2203 | if ((ret = prog_dmabuf_playback(state)) != 0) | 2204 | if ((ret = prog_dmabuf_playback(state)) != 0) |
2204 | goto out; | 2205 | goto out; |
2205 | } else if (vma->vm_flags & VM_READ) { | 2206 | } else if (vma->vm_flags & VM_READ) { |
2206 | if ((ret = prog_dmabuf_record(state)) != 0) | 2207 | if ((ret = prog_dmabuf_record(state)) != 0) |
2207 | goto out; | 2208 | goto out; |
2208 | } else | 2209 | } else |
2209 | goto out; | 2210 | goto out; |
2210 | 2211 | ||
2211 | ret = -EINVAL; | 2212 | ret = -EINVAL; |
2212 | if (vma->vm_pgoff != 0) | 2213 | if (vma->vm_pgoff != 0) |
2213 | goto out; | 2214 | goto out; |
2214 | size = vma->vm_end - vma->vm_start; | 2215 | size = vma->vm_end - vma->vm_start; |
2215 | if (size > (PAGE_SIZE << dmabuf->buforder)) | 2216 | if (size > (PAGE_SIZE << dmabuf->buforder)) |
2216 | goto out; | 2217 | goto out; |
2217 | ret = -EAGAIN; | 2218 | ret = -EAGAIN; |
2218 | if (remap_pfn_range(vma, vma->vm_start, | 2219 | if (remap_pfn_range(vma, vma->vm_start, |
2219 | virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT, | 2220 | virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT, |
2220 | size, vma->vm_page_prot)) | 2221 | size, vma->vm_page_prot)) |
2221 | goto out; | 2222 | goto out; |
2222 | dmabuf->mapped = 1; | 2223 | dmabuf->mapped = 1; |
2223 | ret = 0; | 2224 | ret = 0; |
2224 | out: | 2225 | out: |
2225 | mutex_unlock(&state->sem); | 2226 | mutex_unlock(&state->sem); |
2226 | return ret; | 2227 | return ret; |
2227 | } | 2228 | } |
2228 | 2229 | ||
2229 | static int | 2230 | static int |
2230 | trident_ioctl(struct inode *inode, struct file *file, | 2231 | trident_ioctl(struct inode *inode, struct file *file, |
2231 | unsigned int cmd, unsigned long arg) | 2232 | unsigned int cmd, unsigned long arg) |
2232 | { | 2233 | { |
2233 | struct trident_state *state = (struct trident_state *)file->private_data; | 2234 | struct trident_state *state = (struct trident_state *)file->private_data; |
2234 | struct dmabuf *dmabuf = &state->dmabuf; | 2235 | struct dmabuf *dmabuf = &state->dmabuf; |
2235 | unsigned long flags; | 2236 | unsigned long flags; |
2236 | audio_buf_info abinfo; | 2237 | audio_buf_info abinfo; |
2237 | count_info cinfo; | 2238 | count_info cinfo; |
2238 | int val, mapped, ret = 0; | 2239 | int val, mapped, ret = 0; |
2239 | struct trident_card *card = state->card; | 2240 | struct trident_card *card = state->card; |
2240 | void __user *argp = (void __user *)arg; | 2241 | void __user *argp = (void __user *)arg; |
2241 | int __user *p = argp; | 2242 | int __user *p = argp; |
2242 | 2243 | ||
2243 | VALIDATE_STATE(state); | 2244 | VALIDATE_STATE(state); |
2244 | 2245 | ||
2245 | 2246 | ||
2246 | mapped = ((file->f_mode & (FMODE_WRITE | FMODE_READ)) && dmabuf->mapped); | 2247 | mapped = ((file->f_mode & (FMODE_WRITE | FMODE_READ)) && dmabuf->mapped); |
2247 | 2248 | ||
2248 | pr_debug("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", | 2249 | pr_debug("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", |
2249 | _IOC_NR(cmd), arg ? *p : 0); | 2250 | _IOC_NR(cmd), arg ? *p : 0); |
2250 | 2251 | ||
2251 | switch (cmd) { | 2252 | switch (cmd) { |
2252 | case OSS_GETVERSION: | 2253 | case OSS_GETVERSION: |
2253 | ret = put_user(SOUND_VERSION, p); | 2254 | ret = put_user(SOUND_VERSION, p); |
2254 | break; | 2255 | break; |
2255 | 2256 | ||
2256 | case SNDCTL_DSP_RESET: | 2257 | case SNDCTL_DSP_RESET: |
2257 | /* FIXME: spin_lock ? */ | 2258 | /* FIXME: spin_lock ? */ |
2258 | if (file->f_mode & FMODE_WRITE) { | 2259 | if (file->f_mode & FMODE_WRITE) { |
2259 | stop_dac(state); | 2260 | stop_dac(state); |
2260 | synchronize_irq(card->irq); | 2261 | synchronize_irq(card->irq); |
2261 | dmabuf->ready = 0; | 2262 | dmabuf->ready = 0; |
2262 | dmabuf->swptr = dmabuf->hwptr = 0; | 2263 | dmabuf->swptr = dmabuf->hwptr = 0; |
2263 | dmabuf->count = dmabuf->total_bytes = 0; | 2264 | dmabuf->count = dmabuf->total_bytes = 0; |
2264 | } | 2265 | } |
2265 | if (file->f_mode & FMODE_READ) { | 2266 | if (file->f_mode & FMODE_READ) { |
2266 | stop_adc(state); | 2267 | stop_adc(state); |
2267 | synchronize_irq(card->irq); | 2268 | synchronize_irq(card->irq); |
2268 | dmabuf->ready = 0; | 2269 | dmabuf->ready = 0; |
2269 | dmabuf->swptr = dmabuf->hwptr = 0; | 2270 | dmabuf->swptr = dmabuf->hwptr = 0; |
2270 | dmabuf->count = dmabuf->total_bytes = 0; | 2271 | dmabuf->count = dmabuf->total_bytes = 0; |
2271 | } | 2272 | } |
2272 | break; | 2273 | break; |
2273 | 2274 | ||
2274 | case SNDCTL_DSP_SYNC: | 2275 | case SNDCTL_DSP_SYNC: |
2275 | if (file->f_mode & FMODE_WRITE) | 2276 | if (file->f_mode & FMODE_WRITE) |
2276 | ret = drain_dac(state, file->f_flags & O_NONBLOCK); | 2277 | ret = drain_dac(state, file->f_flags & O_NONBLOCK); |
2277 | break; | 2278 | break; |
2278 | 2279 | ||
2279 | case SNDCTL_DSP_SPEED: /* set smaple rate */ | 2280 | case SNDCTL_DSP_SPEED: /* set smaple rate */ |
2280 | if (get_user(val, p)) { | 2281 | if (get_user(val, p)) { |
2281 | ret = -EFAULT; | 2282 | ret = -EFAULT; |
2282 | break; | 2283 | break; |
2283 | } | 2284 | } |
2284 | if (val >= 0) { | 2285 | if (val >= 0) { |
2285 | if (file->f_mode & FMODE_WRITE) { | 2286 | if (file->f_mode & FMODE_WRITE) { |
2286 | stop_dac(state); | 2287 | stop_dac(state); |
2287 | dmabuf->ready = 0; | 2288 | dmabuf->ready = 0; |
2288 | spin_lock_irqsave(&state->card->lock, flags); | 2289 | spin_lock_irqsave(&state->card->lock, flags); |
2289 | trident_set_dac_rate(state, val); | 2290 | trident_set_dac_rate(state, val); |
2290 | spin_unlock_irqrestore(&state->card->lock, flags); | 2291 | spin_unlock_irqrestore(&state->card->lock, flags); |
2291 | } | 2292 | } |
2292 | if (file->f_mode & FMODE_READ) { | 2293 | if (file->f_mode & FMODE_READ) { |
2293 | stop_adc(state); | 2294 | stop_adc(state); |
2294 | dmabuf->ready = 0; | 2295 | dmabuf->ready = 0; |
2295 | spin_lock_irqsave(&state->card->lock, flags); | 2296 | spin_lock_irqsave(&state->card->lock, flags); |
2296 | trident_set_adc_rate(state, val); | 2297 | trident_set_adc_rate(state, val); |
2297 | spin_unlock_irqrestore(&state->card->lock, flags); | 2298 | spin_unlock_irqrestore(&state->card->lock, flags); |
2298 | } | 2299 | } |
2299 | } | 2300 | } |
2300 | ret = put_user(dmabuf->rate, p); | 2301 | ret = put_user(dmabuf->rate, p); |
2301 | break; | 2302 | break; |
2302 | 2303 | ||
2303 | case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ | 2304 | case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ |
2304 | if (get_user(val, p)) { | 2305 | if (get_user(val, p)) { |
2305 | ret = -EFAULT; | 2306 | ret = -EFAULT; |
2306 | break; | 2307 | break; |
2307 | } | 2308 | } |
2308 | if ((ret = lock_set_fmt(state)) < 0) | 2309 | if ((ret = lock_set_fmt(state)) < 0) |
2309 | return ret; | 2310 | return ret; |
2310 | 2311 | ||
2311 | if (file->f_mode & FMODE_WRITE) { | 2312 | if (file->f_mode & FMODE_WRITE) { |
2312 | stop_dac(state); | 2313 | stop_dac(state); |
2313 | dmabuf->ready = 0; | 2314 | dmabuf->ready = 0; |
2314 | if (val) | 2315 | if (val) |
2315 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | 2316 | dmabuf->fmt |= TRIDENT_FMT_STEREO; |
2316 | else | 2317 | else |
2317 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | 2318 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; |
2318 | } | 2319 | } |
2319 | if (file->f_mode & FMODE_READ) { | 2320 | if (file->f_mode & FMODE_READ) { |
2320 | stop_adc(state); | 2321 | stop_adc(state); |
2321 | dmabuf->ready = 0; | 2322 | dmabuf->ready = 0; |
2322 | if (val) | 2323 | if (val) |
2323 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | 2324 | dmabuf->fmt |= TRIDENT_FMT_STEREO; |
2324 | else | 2325 | else |
2325 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | 2326 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; |
2326 | } | 2327 | } |
2327 | unlock_set_fmt(state); | 2328 | unlock_set_fmt(state); |
2328 | break; | 2329 | break; |
2329 | 2330 | ||
2330 | case SNDCTL_DSP_GETBLKSIZE: | 2331 | case SNDCTL_DSP_GETBLKSIZE: |
2331 | if (file->f_mode & FMODE_WRITE) { | 2332 | if (file->f_mode & FMODE_WRITE) { |
2332 | if ((val = prog_dmabuf_playback(state))) | 2333 | if ((val = prog_dmabuf_playback(state))) |
2333 | ret = val; | 2334 | ret = val; |
2334 | else | 2335 | else |
2335 | ret = put_user(dmabuf->fragsize, p); | 2336 | ret = put_user(dmabuf->fragsize, p); |
2336 | break; | 2337 | break; |
2337 | } | 2338 | } |
2338 | if (file->f_mode & FMODE_READ) { | 2339 | if (file->f_mode & FMODE_READ) { |
2339 | if ((val = prog_dmabuf_record(state))) | 2340 | if ((val = prog_dmabuf_record(state))) |
2340 | ret = val; | 2341 | ret = val; |
2341 | else | 2342 | else |
2342 | ret = put_user(dmabuf->fragsize, p); | 2343 | ret = put_user(dmabuf->fragsize, p); |
2343 | break; | 2344 | break; |
2344 | } | 2345 | } |
2345 | /* neither READ nor WRITE? is this even possible? */ | 2346 | /* neither READ nor WRITE? is this even possible? */ |
2346 | ret = -EINVAL; | 2347 | ret = -EINVAL; |
2347 | break; | 2348 | break; |
2348 | 2349 | ||
2349 | 2350 | ||
2350 | case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */ | 2351 | case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */ |
2351 | ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | | 2352 | ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | |
2352 | AFMT_U8, p); | 2353 | AFMT_U8, p); |
2353 | break; | 2354 | break; |
2354 | 2355 | ||
2355 | case SNDCTL_DSP_SETFMT: /* Select sample format */ | 2356 | case SNDCTL_DSP_SETFMT: /* Select sample format */ |
2356 | if (get_user(val, p)) { | 2357 | if (get_user(val, p)) { |
2357 | ret = -EFAULT; | 2358 | ret = -EFAULT; |
2358 | break; | 2359 | break; |
2359 | } | 2360 | } |
2360 | if ((ret = lock_set_fmt(state)) < 0) | 2361 | if ((ret = lock_set_fmt(state)) < 0) |
2361 | return ret; | 2362 | return ret; |
2362 | 2363 | ||
2363 | if (val != AFMT_QUERY) { | 2364 | if (val != AFMT_QUERY) { |
2364 | if (file->f_mode & FMODE_WRITE) { | 2365 | if (file->f_mode & FMODE_WRITE) { |
2365 | stop_dac(state); | 2366 | stop_dac(state); |
2366 | dmabuf->ready = 0; | 2367 | dmabuf->ready = 0; |
2367 | if (val == AFMT_S16_LE) | 2368 | if (val == AFMT_S16_LE) |
2368 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | 2369 | dmabuf->fmt |= TRIDENT_FMT_16BIT; |
2369 | else | 2370 | else |
2370 | dmabuf->fmt &= ~TRIDENT_FMT_16BIT; | 2371 | dmabuf->fmt &= ~TRIDENT_FMT_16BIT; |
2371 | } | 2372 | } |
2372 | if (file->f_mode & FMODE_READ) { | 2373 | if (file->f_mode & FMODE_READ) { |
2373 | stop_adc(state); | 2374 | stop_adc(state); |
2374 | dmabuf->ready = 0; | 2375 | dmabuf->ready = 0; |
2375 | if (val == AFMT_S16_LE) | 2376 | if (val == AFMT_S16_LE) |
2376 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | 2377 | dmabuf->fmt |= TRIDENT_FMT_16BIT; |
2377 | else | 2378 | else |
2378 | dmabuf->fmt &= ~TRIDENT_FMT_16BIT; | 2379 | dmabuf->fmt &= ~TRIDENT_FMT_16BIT; |
2379 | } | 2380 | } |
2380 | } | 2381 | } |
2381 | unlock_set_fmt(state); | 2382 | unlock_set_fmt(state); |
2382 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : | 2383 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : |
2383 | AFMT_U8, p); | 2384 | AFMT_U8, p); |
2384 | break; | 2385 | break; |
2385 | 2386 | ||
2386 | case SNDCTL_DSP_CHANNELS: | 2387 | case SNDCTL_DSP_CHANNELS: |
2387 | if (get_user(val, p)) { | 2388 | if (get_user(val, p)) { |
2388 | ret = -EFAULT; | 2389 | ret = -EFAULT; |
2389 | break; | 2390 | break; |
2390 | } | 2391 | } |
2391 | if (val != 0) { | 2392 | if (val != 0) { |
2392 | if ((ret = lock_set_fmt(state)) < 0) | 2393 | if ((ret = lock_set_fmt(state)) < 0) |
2393 | return ret; | 2394 | return ret; |
2394 | 2395 | ||
2395 | if (file->f_mode & FMODE_WRITE) { | 2396 | if (file->f_mode & FMODE_WRITE) { |
2396 | stop_dac(state); | 2397 | stop_dac(state); |
2397 | dmabuf->ready = 0; | 2398 | dmabuf->ready = 0; |
2398 | 2399 | ||
2399 | //prevent from memory leak | 2400 | //prevent from memory leak |
2400 | if ((state->chans_num > 2) && (state->chans_num != val)) { | 2401 | if ((state->chans_num > 2) && (state->chans_num != val)) { |
2401 | ali_free_other_states_resources(state); | 2402 | ali_free_other_states_resources(state); |
2402 | state->chans_num = 1; | 2403 | state->chans_num = 1; |
2403 | } | 2404 | } |
2404 | 2405 | ||
2405 | if (val >= 2) { | 2406 | if (val >= 2) { |
2406 | 2407 | ||
2407 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | 2408 | dmabuf->fmt |= TRIDENT_FMT_STEREO; |
2408 | if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) { | 2409 | if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) { |
2409 | if (card->rec_channel_use_count > 0) { | 2410 | if (card->rec_channel_use_count > 0) { |
2410 | printk(KERN_ERR "trident: Record is " | 2411 | printk(KERN_ERR "trident: Record is " |
2411 | "working on the card!\n"); | 2412 | "working on the card!\n"); |
2412 | ret = -EBUSY; | 2413 | ret = -EBUSY; |
2413 | unlock_set_fmt(state); | 2414 | unlock_set_fmt(state); |
2414 | break; | 2415 | break; |
2415 | } | 2416 | } |
2416 | 2417 | ||
2417 | ret = ali_setup_multi_channels(state->card, 6); | 2418 | ret = ali_setup_multi_channels(state->card, 6); |
2418 | if (ret < 0) { | 2419 | if (ret < 0) { |
2419 | unlock_set_fmt(state); | 2420 | unlock_set_fmt(state); |
2420 | break; | 2421 | break; |
2421 | } | 2422 | } |
2422 | mutex_lock(&state->card->open_mutex); | 2423 | mutex_lock(&state->card->open_mutex); |
2423 | ret = ali_allocate_other_states_resources(state, 6); | 2424 | ret = ali_allocate_other_states_resources(state, 6); |
2424 | if (ret < 0) { | 2425 | if (ret < 0) { |
2425 | mutex_unlock(&state->card->open_mutex); | 2426 | mutex_unlock(&state->card->open_mutex); |
2426 | unlock_set_fmt(state); | 2427 | unlock_set_fmt(state); |
2427 | break; | 2428 | break; |
2428 | } | 2429 | } |
2429 | state->card->multi_channel_use_count++; | 2430 | state->card->multi_channel_use_count++; |
2430 | mutex_unlock(&state->card->open_mutex); | 2431 | mutex_unlock(&state->card->open_mutex); |
2431 | } else | 2432 | } else |
2432 | val = 2; /*yield to 2-channels */ | 2433 | val = 2; /*yield to 2-channels */ |
2433 | } else | 2434 | } else |
2434 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | 2435 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; |
2435 | state->chans_num = val; | 2436 | state->chans_num = val; |
2436 | } | 2437 | } |
2437 | if (file->f_mode & FMODE_READ) { | 2438 | if (file->f_mode & FMODE_READ) { |
2438 | stop_adc(state); | 2439 | stop_adc(state); |
2439 | dmabuf->ready = 0; | 2440 | dmabuf->ready = 0; |
2440 | if (val >= 2) { | 2441 | if (val >= 2) { |
2441 | if (!((file->f_mode & FMODE_WRITE) && | 2442 | if (!((file->f_mode & FMODE_WRITE) && |
2442 | (val == 6))) | 2443 | (val == 6))) |
2443 | val = 2; | 2444 | val = 2; |
2444 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | 2445 | dmabuf->fmt |= TRIDENT_FMT_STEREO; |
2445 | } else | 2446 | } else |
2446 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | 2447 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; |
2447 | state->chans_num = val; | 2448 | state->chans_num = val; |
2448 | } | 2449 | } |
2449 | unlock_set_fmt(state); | 2450 | unlock_set_fmt(state); |
2450 | } | 2451 | } |
2451 | ret = put_user(val, p); | 2452 | ret = put_user(val, p); |
2452 | break; | 2453 | break; |
2453 | 2454 | ||
2454 | case SNDCTL_DSP_POST: | 2455 | case SNDCTL_DSP_POST: |
2455 | /* Cause the working fragment to be output */ | 2456 | /* Cause the working fragment to be output */ |
2456 | break; | 2457 | break; |
2457 | 2458 | ||
2458 | case SNDCTL_DSP_SUBDIVIDE: | 2459 | case SNDCTL_DSP_SUBDIVIDE: |
2459 | if (dmabuf->subdivision) { | 2460 | if (dmabuf->subdivision) { |
2460 | ret = -EINVAL; | 2461 | ret = -EINVAL; |
2461 | break; | 2462 | break; |
2462 | } | 2463 | } |
2463 | if (get_user(val, p)) { | 2464 | if (get_user(val, p)) { |
2464 | ret = -EFAULT; | 2465 | ret = -EFAULT; |
2465 | break; | 2466 | break; |
2466 | } | 2467 | } |
2467 | if (val != 1 && val != 2 && val != 4) { | 2468 | if (val != 1 && val != 2 && val != 4) { |
2468 | ret = -EINVAL; | 2469 | ret = -EINVAL; |
2469 | break; | 2470 | break; |
2470 | } | 2471 | } |
2471 | dmabuf->subdivision = val; | 2472 | dmabuf->subdivision = val; |
2472 | break; | 2473 | break; |
2473 | 2474 | ||
2474 | case SNDCTL_DSP_SETFRAGMENT: | 2475 | case SNDCTL_DSP_SETFRAGMENT: |
2475 | if (get_user(val, p)) { | 2476 | if (get_user(val, p)) { |
2476 | ret = -EFAULT; | 2477 | ret = -EFAULT; |
2477 | break; | 2478 | break; |
2478 | } | 2479 | } |
2479 | 2480 | ||
2480 | dmabuf->ossfragshift = val & 0xffff; | 2481 | dmabuf->ossfragshift = val & 0xffff; |
2481 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; | 2482 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; |
2482 | if (dmabuf->ossfragshift < 4) | 2483 | if (dmabuf->ossfragshift < 4) |
2483 | dmabuf->ossfragshift = 4; | 2484 | dmabuf->ossfragshift = 4; |
2484 | if (dmabuf->ossfragshift > 15) | 2485 | if (dmabuf->ossfragshift > 15) |
2485 | dmabuf->ossfragshift = 15; | 2486 | dmabuf->ossfragshift = 15; |
2486 | if (dmabuf->ossmaxfrags < 4) | 2487 | if (dmabuf->ossmaxfrags < 4) |
2487 | dmabuf->ossmaxfrags = 4; | 2488 | dmabuf->ossmaxfrags = 4; |
2488 | 2489 | ||
2489 | break; | 2490 | break; |
2490 | 2491 | ||
2491 | case SNDCTL_DSP_GETOSPACE: | 2492 | case SNDCTL_DSP_GETOSPACE: |
2492 | if (!(file->f_mode & FMODE_WRITE)) { | 2493 | if (!(file->f_mode & FMODE_WRITE)) { |
2493 | ret = -EINVAL; | 2494 | ret = -EINVAL; |
2494 | break; | 2495 | break; |
2495 | } | 2496 | } |
2496 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) { | 2497 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) { |
2497 | ret = val; | 2498 | ret = val; |
2498 | break; | 2499 | break; |
2499 | } | 2500 | } |
2500 | spin_lock_irqsave(&state->card->lock, flags); | 2501 | spin_lock_irqsave(&state->card->lock, flags); |
2501 | trident_update_ptr(state); | 2502 | trident_update_ptr(state); |
2502 | abinfo.fragsize = dmabuf->fragsize; | 2503 | abinfo.fragsize = dmabuf->fragsize; |
2503 | abinfo.bytes = dmabuf->dmasize - dmabuf->count; | 2504 | abinfo.bytes = dmabuf->dmasize - dmabuf->count; |
2504 | abinfo.fragstotal = dmabuf->numfrag; | 2505 | abinfo.fragstotal = dmabuf->numfrag; |
2505 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; | 2506 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; |
2506 | spin_unlock_irqrestore(&state->card->lock, flags); | 2507 | spin_unlock_irqrestore(&state->card->lock, flags); |
2507 | ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? | 2508 | ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? |
2508 | -EFAULT : 0; | 2509 | -EFAULT : 0; |
2509 | break; | 2510 | break; |
2510 | 2511 | ||
2511 | case SNDCTL_DSP_GETISPACE: | 2512 | case SNDCTL_DSP_GETISPACE: |
2512 | if (!(file->f_mode & FMODE_READ)) { | 2513 | if (!(file->f_mode & FMODE_READ)) { |
2513 | ret = -EINVAL; | 2514 | ret = -EINVAL; |
2514 | break; | 2515 | break; |
2515 | } | 2516 | } |
2516 | if (!dmabuf->ready && (val = prog_dmabuf_record(state)) != 0) { | 2517 | if (!dmabuf->ready && (val = prog_dmabuf_record(state)) != 0) { |
2517 | ret = val; | 2518 | ret = val; |
2518 | break; | 2519 | break; |
2519 | } | 2520 | } |
2520 | spin_lock_irqsave(&state->card->lock, flags); | 2521 | spin_lock_irqsave(&state->card->lock, flags); |
2521 | trident_update_ptr(state); | 2522 | trident_update_ptr(state); |
2522 | abinfo.fragsize = dmabuf->fragsize; | 2523 | abinfo.fragsize = dmabuf->fragsize; |
2523 | abinfo.bytes = dmabuf->count; | 2524 | abinfo.bytes = dmabuf->count; |
2524 | abinfo.fragstotal = dmabuf->numfrag; | 2525 | abinfo.fragstotal = dmabuf->numfrag; |
2525 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; | 2526 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; |
2526 | spin_unlock_irqrestore(&state->card->lock, flags); | 2527 | spin_unlock_irqrestore(&state->card->lock, flags); |
2527 | ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? | 2528 | ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? |
2528 | -EFAULT : 0; | 2529 | -EFAULT : 0; |
2529 | break; | 2530 | break; |
2530 | 2531 | ||
2531 | case SNDCTL_DSP_NONBLOCK: | 2532 | case SNDCTL_DSP_NONBLOCK: |
2532 | file->f_flags |= O_NONBLOCK; | 2533 | file->f_flags |= O_NONBLOCK; |
2533 | break; | 2534 | break; |
2534 | 2535 | ||
2535 | case SNDCTL_DSP_GETCAPS: | 2536 | case SNDCTL_DSP_GETCAPS: |
2536 | ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | | 2537 | ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | |
2537 | DSP_CAP_MMAP | DSP_CAP_BIND, p); | 2538 | DSP_CAP_MMAP | DSP_CAP_BIND, p); |
2538 | break; | 2539 | break; |
2539 | 2540 | ||
2540 | case SNDCTL_DSP_GETTRIGGER: | 2541 | case SNDCTL_DSP_GETTRIGGER: |
2541 | val = 0; | 2542 | val = 0; |
2542 | if ((file->f_mode & FMODE_READ) && dmabuf->enable) | 2543 | if ((file->f_mode & FMODE_READ) && dmabuf->enable) |
2543 | val |= PCM_ENABLE_INPUT; | 2544 | val |= PCM_ENABLE_INPUT; |
2544 | if ((file->f_mode & FMODE_WRITE) && dmabuf->enable) | 2545 | if ((file->f_mode & FMODE_WRITE) && dmabuf->enable) |
2545 | val |= PCM_ENABLE_OUTPUT; | 2546 | val |= PCM_ENABLE_OUTPUT; |
2546 | ret = put_user(val, p); | 2547 | ret = put_user(val, p); |
2547 | break; | 2548 | break; |
2548 | 2549 | ||
2549 | case SNDCTL_DSP_SETTRIGGER: | 2550 | case SNDCTL_DSP_SETTRIGGER: |
2550 | if (get_user(val, p)) { | 2551 | if (get_user(val, p)) { |
2551 | ret = -EFAULT; | 2552 | ret = -EFAULT; |
2552 | break; | 2553 | break; |
2553 | } | 2554 | } |
2554 | if (file->f_mode & FMODE_READ) { | 2555 | if (file->f_mode & FMODE_READ) { |
2555 | if (val & PCM_ENABLE_INPUT) { | 2556 | if (val & PCM_ENABLE_INPUT) { |
2556 | if (!dmabuf->ready && | 2557 | if (!dmabuf->ready && |
2557 | (ret = prog_dmabuf_record(state))) | 2558 | (ret = prog_dmabuf_record(state))) |
2558 | break; | 2559 | break; |
2559 | start_adc(state); | 2560 | start_adc(state); |
2560 | } else | 2561 | } else |
2561 | stop_adc(state); | 2562 | stop_adc(state); |
2562 | } | 2563 | } |
2563 | if (file->f_mode & FMODE_WRITE) { | 2564 | if (file->f_mode & FMODE_WRITE) { |
2564 | if (val & PCM_ENABLE_OUTPUT) { | 2565 | if (val & PCM_ENABLE_OUTPUT) { |
2565 | if (!dmabuf->ready && | 2566 | if (!dmabuf->ready && |
2566 | (ret = prog_dmabuf_playback(state))) | 2567 | (ret = prog_dmabuf_playback(state))) |
2567 | break; | 2568 | break; |
2568 | start_dac(state); | 2569 | start_dac(state); |
2569 | } else | 2570 | } else |
2570 | stop_dac(state); | 2571 | stop_dac(state); |
2571 | } | 2572 | } |
2572 | break; | 2573 | break; |
2573 | 2574 | ||
2574 | case SNDCTL_DSP_GETIPTR: | 2575 | case SNDCTL_DSP_GETIPTR: |
2575 | if (!(file->f_mode & FMODE_READ)) { | 2576 | if (!(file->f_mode & FMODE_READ)) { |
2576 | ret = -EINVAL; | 2577 | ret = -EINVAL; |
2577 | break; | 2578 | break; |
2578 | } | 2579 | } |
2579 | if (!dmabuf->ready && (val = prog_dmabuf_record(state)) | 2580 | if (!dmabuf->ready && (val = prog_dmabuf_record(state)) |
2580 | != 0) { | 2581 | != 0) { |
2581 | ret = val; | 2582 | ret = val; |
2582 | break; | 2583 | break; |
2583 | } | 2584 | } |
2584 | spin_lock_irqsave(&state->card->lock, flags); | 2585 | spin_lock_irqsave(&state->card->lock, flags); |
2585 | trident_update_ptr(state); | 2586 | trident_update_ptr(state); |
2586 | cinfo.bytes = dmabuf->total_bytes; | 2587 | cinfo.bytes = dmabuf->total_bytes; |
2587 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; | 2588 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; |
2588 | cinfo.ptr = dmabuf->hwptr; | 2589 | cinfo.ptr = dmabuf->hwptr; |
2589 | if (dmabuf->mapped) | 2590 | if (dmabuf->mapped) |
2590 | dmabuf->count &= dmabuf->fragsize - 1; | 2591 | dmabuf->count &= dmabuf->fragsize - 1; |
2591 | spin_unlock_irqrestore(&state->card->lock, flags); | 2592 | spin_unlock_irqrestore(&state->card->lock, flags); |
2592 | ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? | 2593 | ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? |
2593 | -EFAULT : 0; | 2594 | -EFAULT : 0; |
2594 | break; | 2595 | break; |
2595 | 2596 | ||
2596 | case SNDCTL_DSP_GETOPTR: | 2597 | case SNDCTL_DSP_GETOPTR: |
2597 | if (!(file->f_mode & FMODE_WRITE)) { | 2598 | if (!(file->f_mode & FMODE_WRITE)) { |
2598 | ret = -EINVAL; | 2599 | ret = -EINVAL; |
2599 | break; | 2600 | break; |
2600 | } | 2601 | } |
2601 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) | 2602 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) |
2602 | != 0) { | 2603 | != 0) { |
2603 | ret = val; | 2604 | ret = val; |
2604 | break; | 2605 | break; |
2605 | } | 2606 | } |
2606 | 2607 | ||
2607 | spin_lock_irqsave(&state->card->lock, flags); | 2608 | spin_lock_irqsave(&state->card->lock, flags); |
2608 | trident_update_ptr(state); | 2609 | trident_update_ptr(state); |
2609 | cinfo.bytes = dmabuf->total_bytes; | 2610 | cinfo.bytes = dmabuf->total_bytes; |
2610 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; | 2611 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; |
2611 | cinfo.ptr = dmabuf->hwptr; | 2612 | cinfo.ptr = dmabuf->hwptr; |
2612 | if (dmabuf->mapped) | 2613 | if (dmabuf->mapped) |
2613 | dmabuf->count &= dmabuf->fragsize - 1; | 2614 | dmabuf->count &= dmabuf->fragsize - 1; |
2614 | spin_unlock_irqrestore(&state->card->lock, flags); | 2615 | spin_unlock_irqrestore(&state->card->lock, flags); |
2615 | ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? | 2616 | ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? |
2616 | -EFAULT : 0; | 2617 | -EFAULT : 0; |
2617 | break; | 2618 | break; |
2618 | 2619 | ||
2619 | case SNDCTL_DSP_SETDUPLEX: | 2620 | case SNDCTL_DSP_SETDUPLEX: |
2620 | ret = -EINVAL; | 2621 | ret = -EINVAL; |
2621 | break; | 2622 | break; |
2622 | 2623 | ||
2623 | case SNDCTL_DSP_GETODELAY: | 2624 | case SNDCTL_DSP_GETODELAY: |
2624 | if (!(file->f_mode & FMODE_WRITE)) { | 2625 | if (!(file->f_mode & FMODE_WRITE)) { |
2625 | ret = -EINVAL; | 2626 | ret = -EINVAL; |
2626 | break; | 2627 | break; |
2627 | } | 2628 | } |
2628 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) { | 2629 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) { |
2629 | ret = val; | 2630 | ret = val; |
2630 | break; | 2631 | break; |
2631 | } | 2632 | } |
2632 | spin_lock_irqsave(&state->card->lock, flags); | 2633 | spin_lock_irqsave(&state->card->lock, flags); |
2633 | trident_update_ptr(state); | 2634 | trident_update_ptr(state); |
2634 | val = dmabuf->count; | 2635 | val = dmabuf->count; |
2635 | spin_unlock_irqrestore(&state->card->lock, flags); | 2636 | spin_unlock_irqrestore(&state->card->lock, flags); |
2636 | ret = put_user(val, p); | 2637 | ret = put_user(val, p); |
2637 | break; | 2638 | break; |
2638 | 2639 | ||
2639 | case SOUND_PCM_READ_RATE: | 2640 | case SOUND_PCM_READ_RATE: |
2640 | ret = put_user(dmabuf->rate, p); | 2641 | ret = put_user(dmabuf->rate, p); |
2641 | break; | 2642 | break; |
2642 | 2643 | ||
2643 | case SOUND_PCM_READ_CHANNELS: | 2644 | case SOUND_PCM_READ_CHANNELS: |
2644 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, | 2645 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, |
2645 | p); | 2646 | p); |
2646 | break; | 2647 | break; |
2647 | 2648 | ||
2648 | case SOUND_PCM_READ_BITS: | 2649 | case SOUND_PCM_READ_BITS: |
2649 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : | 2650 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : |
2650 | AFMT_U8, p); | 2651 | AFMT_U8, p); |
2651 | break; | 2652 | break; |
2652 | 2653 | ||
2653 | case SNDCTL_DSP_GETCHANNELMASK: | 2654 | case SNDCTL_DSP_GETCHANNELMASK: |
2654 | ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR | | 2655 | ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR | |
2655 | DSP_BIND_CENTER_LFE, p); | 2656 | DSP_BIND_CENTER_LFE, p); |
2656 | break; | 2657 | break; |
2657 | 2658 | ||
2658 | case SNDCTL_DSP_BIND_CHANNEL: | 2659 | case SNDCTL_DSP_BIND_CHANNEL: |
2659 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { | 2660 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { |
2660 | ret = -EINVAL; | 2661 | ret = -EINVAL; |
2661 | break; | 2662 | break; |
2662 | } | 2663 | } |
2663 | 2664 | ||
2664 | if (get_user(val, p)) { | 2665 | if (get_user(val, p)) { |
2665 | ret = -EFAULT; | 2666 | ret = -EFAULT; |
2666 | break; | 2667 | break; |
2667 | } | 2668 | } |
2668 | if (val == DSP_BIND_QUERY) { | 2669 | if (val == DSP_BIND_QUERY) { |
2669 | val = dmabuf->channel->attribute | 0x3c00; | 2670 | val = dmabuf->channel->attribute | 0x3c00; |
2670 | val = attr2mask[val >> 8]; | 2671 | val = attr2mask[val >> 8]; |
2671 | } else { | 2672 | } else { |
2672 | dmabuf->ready = 0; | 2673 | dmabuf->ready = 0; |
2673 | if (file->f_mode & FMODE_READ) | 2674 | if (file->f_mode & FMODE_READ) |
2674 | dmabuf->channel->attribute = (CHANNEL_REC | | 2675 | dmabuf->channel->attribute = (CHANNEL_REC | |
2675 | SRC_ENABLE); | 2676 | SRC_ENABLE); |
2676 | if (file->f_mode & FMODE_WRITE) | 2677 | if (file->f_mode & FMODE_WRITE) |
2677 | dmabuf->channel->attribute = (CHANNEL_SPC_PB | | 2678 | dmabuf->channel->attribute = (CHANNEL_SPC_PB | |
2678 | SRC_ENABLE); | 2679 | SRC_ENABLE); |
2679 | dmabuf->channel->attribute |= mask2attr[ffs(val)]; | 2680 | dmabuf->channel->attribute |= mask2attr[ffs(val)]; |
2680 | } | 2681 | } |
2681 | ret = put_user(val, p); | 2682 | ret = put_user(val, p); |
2682 | break; | 2683 | break; |
2683 | 2684 | ||
2684 | case SNDCTL_DSP_MAPINBUF: | 2685 | case SNDCTL_DSP_MAPINBUF: |
2685 | case SNDCTL_DSP_MAPOUTBUF: | 2686 | case SNDCTL_DSP_MAPOUTBUF: |
2686 | case SNDCTL_DSP_SETSYNCRO: | 2687 | case SNDCTL_DSP_SETSYNCRO: |
2687 | case SOUND_PCM_WRITE_FILTER: | 2688 | case SOUND_PCM_WRITE_FILTER: |
2688 | case SOUND_PCM_READ_FILTER: | 2689 | case SOUND_PCM_READ_FILTER: |
2689 | default: | 2690 | default: |
2690 | ret = -EINVAL; | 2691 | ret = -EINVAL; |
2691 | break; | 2692 | break; |
2692 | 2693 | ||
2693 | } | 2694 | } |
2694 | return ret; | 2695 | return ret; |
2695 | } | 2696 | } |
2696 | 2697 | ||
2697 | static int | 2698 | static int |
2698 | trident_open(struct inode *inode, struct file *file) | 2699 | trident_open(struct inode *inode, struct file *file) |
2699 | { | 2700 | { |
2700 | int i = 0; | 2701 | int i = 0; |
2701 | int minor = iminor(inode); | 2702 | int minor = iminor(inode); |
2702 | struct trident_card *card = devs; | 2703 | struct trident_card *card = devs; |
2703 | struct trident_state *state = NULL; | 2704 | struct trident_state *state = NULL; |
2704 | struct dmabuf *dmabuf = NULL; | 2705 | struct dmabuf *dmabuf = NULL; |
2705 | 2706 | ||
2706 | /* Added by Matt Wu 01-05-2001 */ | 2707 | /* Added by Matt Wu 01-05-2001 */ |
2707 | /* TODO: there's some redundacy here wrt the check below */ | 2708 | /* TODO: there's some redundacy here wrt the check below */ |
2708 | /* for multi_use_count > 0. Should we return -EBUSY or find */ | 2709 | /* for multi_use_count > 0. Should we return -EBUSY or find */ |
2709 | /* a different card? for now, don't break current behaviour */ | 2710 | /* a different card? for now, don't break current behaviour */ |
2710 | /* -- mulix */ | 2711 | /* -- mulix */ |
2711 | if (file->f_mode & FMODE_READ) { | 2712 | if (file->f_mode & FMODE_READ) { |
2712 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 2713 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
2713 | if (card->multi_channel_use_count > 0) | 2714 | if (card->multi_channel_use_count > 0) |
2714 | return -EBUSY; | 2715 | return -EBUSY; |
2715 | } | 2716 | } |
2716 | } | 2717 | } |
2717 | 2718 | ||
2718 | /* find an available virtual channel (instance of /dev/dsp) */ | 2719 | /* find an available virtual channel (instance of /dev/dsp) */ |
2719 | while (card != NULL) { | 2720 | while (card != NULL) { |
2720 | mutex_lock(&card->open_mutex); | 2721 | mutex_lock(&card->open_mutex); |
2721 | if (file->f_mode & FMODE_READ) { | 2722 | if (file->f_mode & FMODE_READ) { |
2722 | /* Skip opens on cards that are in 6 channel mode */ | 2723 | /* Skip opens on cards that are in 6 channel mode */ |
2723 | if (card->multi_channel_use_count > 0) { | 2724 | if (card->multi_channel_use_count > 0) { |
2724 | mutex_unlock(&card->open_mutex); | 2725 | mutex_unlock(&card->open_mutex); |
2725 | card = card->next; | 2726 | card = card->next; |
2726 | continue; | 2727 | continue; |
2727 | } | 2728 | } |
2728 | } | 2729 | } |
2729 | for (i = 0; i < NR_HW_CH; i++) { | 2730 | for (i = 0; i < NR_HW_CH; i++) { |
2730 | if (card->states[i] == NULL) { | 2731 | if (card->states[i] == NULL) { |
2731 | state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); | 2732 | state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); |
2732 | if (state == NULL) { | 2733 | if (state == NULL) { |
2733 | mutex_unlock(&card->open_mutex); | 2734 | mutex_unlock(&card->open_mutex); |
2734 | return -ENOMEM; | 2735 | return -ENOMEM; |
2735 | } | 2736 | } |
2736 | memset(state, 0, sizeof(*state)); | 2737 | memset(state, 0, sizeof(*state)); |
2737 | mutex_init(&state->sem); | 2738 | mutex_init(&state->sem); |
2738 | dmabuf = &state->dmabuf; | 2739 | dmabuf = &state->dmabuf; |
2739 | goto found_virt; | 2740 | goto found_virt; |
2740 | } | 2741 | } |
2741 | } | 2742 | } |
2742 | mutex_unlock(&card->open_mutex); | 2743 | mutex_unlock(&card->open_mutex); |
2743 | card = card->next; | 2744 | card = card->next; |
2744 | } | 2745 | } |
2745 | /* no more virtual channel avaiable */ | 2746 | /* no more virtual channel avaiable */ |
2746 | if (!state) { | 2747 | if (!state) { |
2747 | return -ENODEV; | 2748 | return -ENODEV; |
2748 | } | 2749 | } |
2749 | found_virt: | 2750 | found_virt: |
2750 | /* found a free virtual channel, allocate hardware channels */ | 2751 | /* found a free virtual channel, allocate hardware channels */ |
2751 | if (file->f_mode & FMODE_READ) | 2752 | if (file->f_mode & FMODE_READ) |
2752 | dmabuf->channel = card->alloc_rec_pcm_channel(card); | 2753 | dmabuf->channel = card->alloc_rec_pcm_channel(card); |
2753 | else | 2754 | else |
2754 | dmabuf->channel = card->alloc_pcm_channel(card); | 2755 | dmabuf->channel = card->alloc_pcm_channel(card); |
2755 | 2756 | ||
2756 | if (dmabuf->channel == NULL) { | 2757 | if (dmabuf->channel == NULL) { |
2757 | kfree(card->states[i]); | 2758 | kfree(card->states[i]); |
2758 | card->states[i] = NULL; | 2759 | card->states[i] = NULL; |
2759 | return -ENODEV; | 2760 | return -ENODEV; |
2760 | } | 2761 | } |
2761 | 2762 | ||
2762 | /* initialize the virtual channel */ | 2763 | /* initialize the virtual channel */ |
2763 | state->virt = i; | 2764 | state->virt = i; |
2764 | state->card = card; | 2765 | state->card = card; |
2765 | state->magic = TRIDENT_STATE_MAGIC; | 2766 | state->magic = TRIDENT_STATE_MAGIC; |
2766 | init_waitqueue_head(&dmabuf->wait); | 2767 | init_waitqueue_head(&dmabuf->wait); |
2767 | file->private_data = state; | 2768 | file->private_data = state; |
2768 | 2769 | ||
2769 | /* set default sample format. According to OSS Programmer's */ | 2770 | /* set default sample format. According to OSS Programmer's */ |
2770 | /* Guide /dev/dsp should be default to unsigned 8-bits, mono, */ | 2771 | /* Guide /dev/dsp should be default to unsigned 8-bits, mono, */ |
2771 | /* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */ | 2772 | /* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */ |
2772 | if (file->f_mode & FMODE_WRITE) { | 2773 | if (file->f_mode & FMODE_WRITE) { |
2773 | dmabuf->fmt &= ~TRIDENT_FMT_MASK; | 2774 | dmabuf->fmt &= ~TRIDENT_FMT_MASK; |
2774 | if ((minor & 0x0f) == SND_DEV_DSP16) | 2775 | if ((minor & 0x0f) == SND_DEV_DSP16) |
2775 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | 2776 | dmabuf->fmt |= TRIDENT_FMT_16BIT; |
2776 | dmabuf->ossfragshift = 0; | 2777 | dmabuf->ossfragshift = 0; |
2777 | dmabuf->ossmaxfrags = 0; | 2778 | dmabuf->ossmaxfrags = 0; |
2778 | dmabuf->subdivision = 0; | 2779 | dmabuf->subdivision = 0; |
2779 | if (card->pci_id == PCI_DEVICE_ID_SI_7018) { | 2780 | if (card->pci_id == PCI_DEVICE_ID_SI_7018) { |
2780 | /* set default channel attribute to normal playback */ | 2781 | /* set default channel attribute to normal playback */ |
2781 | dmabuf->channel->attribute = CHANNEL_PB; | 2782 | dmabuf->channel->attribute = CHANNEL_PB; |
2782 | } | 2783 | } |
2783 | trident_set_dac_rate(state, 8000); | 2784 | trident_set_dac_rate(state, 8000); |
2784 | } | 2785 | } |
2785 | 2786 | ||
2786 | if (file->f_mode & FMODE_READ) { | 2787 | if (file->f_mode & FMODE_READ) { |
2787 | /* FIXME: Trident 4d can only record in signed 16-bits stereo, */ | 2788 | /* FIXME: Trident 4d can only record in signed 16-bits stereo, */ |
2788 | /* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */ | 2789 | /* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */ |
2789 | dmabuf->fmt &= ~TRIDENT_FMT_MASK; | 2790 | dmabuf->fmt &= ~TRIDENT_FMT_MASK; |
2790 | if ((minor & 0x0f) == SND_DEV_DSP16) | 2791 | if ((minor & 0x0f) == SND_DEV_DSP16) |
2791 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | 2792 | dmabuf->fmt |= TRIDENT_FMT_16BIT; |
2792 | dmabuf->ossfragshift = 0; | 2793 | dmabuf->ossfragshift = 0; |
2793 | dmabuf->ossmaxfrags = 0; | 2794 | dmabuf->ossmaxfrags = 0; |
2794 | dmabuf->subdivision = 0; | 2795 | dmabuf->subdivision = 0; |
2795 | if (card->pci_id == PCI_DEVICE_ID_SI_7018) { | 2796 | if (card->pci_id == PCI_DEVICE_ID_SI_7018) { |
2796 | /* set default channel attribute to 0x8a80, record from | 2797 | /* set default channel attribute to 0x8a80, record from |
2797 | PCM L/R FIFO and mono = (left + right + 1)/2 */ | 2798 | PCM L/R FIFO and mono = (left + right + 1)/2 */ |
2798 | dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR | | 2799 | dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR | |
2799 | MONO_MIX); | 2800 | MONO_MIX); |
2800 | } | 2801 | } |
2801 | trident_set_adc_rate(state, 8000); | 2802 | trident_set_adc_rate(state, 8000); |
2802 | 2803 | ||
2803 | /* Added by Matt Wu 01-05-2001 */ | 2804 | /* Added by Matt Wu 01-05-2001 */ |
2804 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) | 2805 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) |
2805 | card->rec_channel_use_count++; | 2806 | card->rec_channel_use_count++; |
2806 | } | 2807 | } |
2807 | 2808 | ||
2808 | state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | 2809 | state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); |
2809 | mutex_unlock(&card->open_mutex); | 2810 | mutex_unlock(&card->open_mutex); |
2810 | 2811 | ||
2811 | pr_debug("trident: open virtual channel %d, hard channel %d\n", | 2812 | pr_debug("trident: open virtual channel %d, hard channel %d\n", |
2812 | state->virt, dmabuf->channel->num); | 2813 | state->virt, dmabuf->channel->num); |
2813 | 2814 | ||
2814 | return nonseekable_open(inode, file); | 2815 | return nonseekable_open(inode, file); |
2815 | } | 2816 | } |
2816 | 2817 | ||
2817 | static int | 2818 | static int |
2818 | trident_release(struct inode *inode, struct file *file) | 2819 | trident_release(struct inode *inode, struct file *file) |
2819 | { | 2820 | { |
2820 | struct trident_state *state = (struct trident_state *)file->private_data; | 2821 | struct trident_state *state = (struct trident_state *)file->private_data; |
2821 | struct trident_card *card; | 2822 | struct trident_card *card; |
2822 | struct dmabuf *dmabuf; | 2823 | struct dmabuf *dmabuf; |
2823 | 2824 | ||
2824 | VALIDATE_STATE(state); | 2825 | VALIDATE_STATE(state); |
2825 | 2826 | ||
2826 | card = state->card; | 2827 | card = state->card; |
2827 | dmabuf = &state->dmabuf; | 2828 | dmabuf = &state->dmabuf; |
2828 | 2829 | ||
2829 | if (file->f_mode & FMODE_WRITE) { | 2830 | if (file->f_mode & FMODE_WRITE) { |
2830 | trident_clear_tail(state); | 2831 | trident_clear_tail(state); |
2831 | drain_dac(state, file->f_flags & O_NONBLOCK); | 2832 | drain_dac(state, file->f_flags & O_NONBLOCK); |
2832 | } | 2833 | } |
2833 | 2834 | ||
2834 | pr_debug("trident: closing virtual channel %d, hard channel %d\n", | 2835 | pr_debug("trident: closing virtual channel %d, hard channel %d\n", |
2835 | state->virt, dmabuf->channel->num); | 2836 | state->virt, dmabuf->channel->num); |
2836 | 2837 | ||
2837 | /* stop DMA state machine and free DMA buffers/channels */ | 2838 | /* stop DMA state machine and free DMA buffers/channels */ |
2838 | mutex_lock(&card->open_mutex); | 2839 | mutex_lock(&card->open_mutex); |
2839 | 2840 | ||
2840 | if (file->f_mode & FMODE_WRITE) { | 2841 | if (file->f_mode & FMODE_WRITE) { |
2841 | stop_dac(state); | 2842 | stop_dac(state); |
2842 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); | 2843 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); |
2843 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); | 2844 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); |
2844 | 2845 | ||
2845 | /* Added by Matt Wu */ | 2846 | /* Added by Matt Wu */ |
2846 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 2847 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
2847 | if (state->chans_num > 2) { | 2848 | if (state->chans_num > 2) { |
2848 | if (card->multi_channel_use_count-- < 0) | 2849 | if (card->multi_channel_use_count-- < 0) |
2849 | card->multi_channel_use_count = 0; | 2850 | card->multi_channel_use_count = 0; |
2850 | if (card->multi_channel_use_count == 0) | 2851 | if (card->multi_channel_use_count == 0) |
2851 | ali_close_multi_channels(); | 2852 | ali_close_multi_channels(); |
2852 | ali_free_other_states_resources(state); | 2853 | ali_free_other_states_resources(state); |
2853 | } | 2854 | } |
2854 | } | 2855 | } |
2855 | } | 2856 | } |
2856 | if (file->f_mode & FMODE_READ) { | 2857 | if (file->f_mode & FMODE_READ) { |
2857 | stop_adc(state); | 2858 | stop_adc(state); |
2858 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); | 2859 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); |
2859 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); | 2860 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); |
2860 | 2861 | ||
2861 | /* Added by Matt Wu */ | 2862 | /* Added by Matt Wu */ |
2862 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 2863 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
2863 | if (card->rec_channel_use_count-- < 0) | 2864 | if (card->rec_channel_use_count-- < 0) |
2864 | card->rec_channel_use_count = 0; | 2865 | card->rec_channel_use_count = 0; |
2865 | } | 2866 | } |
2866 | } | 2867 | } |
2867 | 2868 | ||
2868 | card->states[state->virt] = NULL; | 2869 | card->states[state->virt] = NULL; |
2869 | kfree(state); | 2870 | kfree(state); |
2870 | 2871 | ||
2871 | /* we're covered by the open_mutex */ | 2872 | /* we're covered by the open_mutex */ |
2872 | mutex_unlock(&card->open_mutex); | 2873 | mutex_unlock(&card->open_mutex); |
2873 | 2874 | ||
2874 | return 0; | 2875 | return 0; |
2875 | } | 2876 | } |
2876 | 2877 | ||
2877 | static /*const */ struct file_operations trident_audio_fops = { | 2878 | static /*const */ struct file_operations trident_audio_fops = { |
2878 | .owner = THIS_MODULE, | 2879 | .owner = THIS_MODULE, |
2879 | .llseek = no_llseek, | 2880 | .llseek = no_llseek, |
2880 | .read = trident_read, | 2881 | .read = trident_read, |
2881 | .write = trident_write, | 2882 | .write = trident_write, |
2882 | .poll = trident_poll, | 2883 | .poll = trident_poll, |
2883 | .ioctl = trident_ioctl, | 2884 | .ioctl = trident_ioctl, |
2884 | .mmap = trident_mmap, | 2885 | .mmap = trident_mmap, |
2885 | .open = trident_open, | 2886 | .open = trident_open, |
2886 | .release = trident_release, | 2887 | .release = trident_release, |
2887 | }; | 2888 | }; |
2888 | 2889 | ||
2889 | /* trident specific AC97 functions */ | 2890 | /* trident specific AC97 functions */ |
2890 | /* Write AC97 codec registers */ | 2891 | /* Write AC97 codec registers */ |
2891 | static void | 2892 | static void |
2892 | trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val) | 2893 | trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val) |
2893 | { | 2894 | { |
2894 | struct trident_card *card = (struct trident_card *)codec->private_data; | 2895 | struct trident_card *card = (struct trident_card *)codec->private_data; |
2895 | unsigned int address, mask, busy; | 2896 | unsigned int address, mask, busy; |
2896 | unsigned short count = 0xffff; | 2897 | unsigned short count = 0xffff; |
2897 | unsigned long flags; | 2898 | unsigned long flags; |
2898 | u32 data; | 2899 | u32 data; |
2899 | 2900 | ||
2900 | data = ((u32) val) << 16; | 2901 | data = ((u32) val) << 16; |
2901 | 2902 | ||
2902 | switch (card->pci_id) { | 2903 | switch (card->pci_id) { |
2903 | default: | 2904 | default: |
2904 | case PCI_DEVICE_ID_SI_7018: | 2905 | case PCI_DEVICE_ID_SI_7018: |
2905 | address = SI_AC97_WRITE; | 2906 | address = SI_AC97_WRITE; |
2906 | mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY; | 2907 | mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY; |
2907 | if (codec->id) | 2908 | if (codec->id) |
2908 | mask |= SI_AC97_SECONDARY; | 2909 | mask |= SI_AC97_SECONDARY; |
2909 | busy = SI_AC97_BUSY_WRITE; | 2910 | busy = SI_AC97_BUSY_WRITE; |
2910 | break; | 2911 | break; |
2911 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | 2912 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: |
2912 | address = DX_ACR0_AC97_W; | 2913 | address = DX_ACR0_AC97_W; |
2913 | mask = busy = DX_AC97_BUSY_WRITE; | 2914 | mask = busy = DX_AC97_BUSY_WRITE; |
2914 | break; | 2915 | break; |
2915 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | 2916 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: |
2916 | address = NX_ACR1_AC97_W; | 2917 | address = NX_ACR1_AC97_W; |
2917 | mask = NX_AC97_BUSY_WRITE; | 2918 | mask = NX_AC97_BUSY_WRITE; |
2918 | if (codec->id) | 2919 | if (codec->id) |
2919 | mask |= NX_AC97_WRITE_SECONDARY; | 2920 | mask |= NX_AC97_WRITE_SECONDARY; |
2920 | busy = NX_AC97_BUSY_WRITE; | 2921 | busy = NX_AC97_BUSY_WRITE; |
2921 | break; | 2922 | break; |
2922 | case PCI_DEVICE_ID_INTERG_5050: | 2923 | case PCI_DEVICE_ID_INTERG_5050: |
2923 | address = SI_AC97_WRITE; | 2924 | address = SI_AC97_WRITE; |
2924 | mask = busy = SI_AC97_BUSY_WRITE; | 2925 | mask = busy = SI_AC97_BUSY_WRITE; |
2925 | if (codec->id) | 2926 | if (codec->id) |
2926 | mask |= SI_AC97_SECONDARY; | 2927 | mask |= SI_AC97_SECONDARY; |
2927 | break; | 2928 | break; |
2928 | } | 2929 | } |
2929 | 2930 | ||
2930 | spin_lock_irqsave(&card->lock, flags); | 2931 | spin_lock_irqsave(&card->lock, flags); |
2931 | do { | 2932 | do { |
2932 | if ((inw(TRID_REG(card, address)) & busy) == 0) | 2933 | if ((inw(TRID_REG(card, address)) & busy) == 0) |
2933 | break; | 2934 | break; |
2934 | } while (count--); | 2935 | } while (count--); |
2935 | 2936 | ||
2936 | data |= (mask | (reg & AC97_REG_ADDR)); | 2937 | data |= (mask | (reg & AC97_REG_ADDR)); |
2937 | 2938 | ||
2938 | if (count == 0) { | 2939 | if (count == 0) { |
2939 | printk(KERN_ERR "trident: AC97 CODEC write timed out.\n"); | 2940 | printk(KERN_ERR "trident: AC97 CODEC write timed out.\n"); |
2940 | spin_unlock_irqrestore(&card->lock, flags); | 2941 | spin_unlock_irqrestore(&card->lock, flags); |
2941 | return; | 2942 | return; |
2942 | } | 2943 | } |
2943 | 2944 | ||
2944 | outl(data, TRID_REG(card, address)); | 2945 | outl(data, TRID_REG(card, address)); |
2945 | spin_unlock_irqrestore(&card->lock, flags); | 2946 | spin_unlock_irqrestore(&card->lock, flags); |
2946 | } | 2947 | } |
2947 | 2948 | ||
2948 | /* Read AC97 codec registers */ | 2949 | /* Read AC97 codec registers */ |
2949 | static u16 | 2950 | static u16 |
2950 | trident_ac97_get(struct ac97_codec *codec, u8 reg) | 2951 | trident_ac97_get(struct ac97_codec *codec, u8 reg) |
2951 | { | 2952 | { |
2952 | struct trident_card *card = (struct trident_card *)codec->private_data; | 2953 | struct trident_card *card = (struct trident_card *)codec->private_data; |
2953 | unsigned int address, mask, busy; | 2954 | unsigned int address, mask, busy; |
2954 | unsigned short count = 0xffff; | 2955 | unsigned short count = 0xffff; |
2955 | unsigned long flags; | 2956 | unsigned long flags; |
2956 | u32 data; | 2957 | u32 data; |
2957 | 2958 | ||
2958 | switch (card->pci_id) { | 2959 | switch (card->pci_id) { |
2959 | default: | 2960 | default: |
2960 | case PCI_DEVICE_ID_SI_7018: | 2961 | case PCI_DEVICE_ID_SI_7018: |
2961 | address = SI_AC97_READ; | 2962 | address = SI_AC97_READ; |
2962 | mask = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY; | 2963 | mask = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY; |
2963 | if (codec->id) | 2964 | if (codec->id) |
2964 | mask |= SI_AC97_SECONDARY; | 2965 | mask |= SI_AC97_SECONDARY; |
2965 | busy = SI_AC97_BUSY_READ; | 2966 | busy = SI_AC97_BUSY_READ; |
2966 | break; | 2967 | break; |
2967 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | 2968 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: |
2968 | address = DX_ACR1_AC97_R; | 2969 | address = DX_ACR1_AC97_R; |
2969 | mask = busy = DX_AC97_BUSY_READ; | 2970 | mask = busy = DX_AC97_BUSY_READ; |
2970 | break; | 2971 | break; |
2971 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | 2972 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: |
2972 | if (codec->id) | 2973 | if (codec->id) |
2973 | address = NX_ACR3_AC97_R_SECONDARY; | 2974 | address = NX_ACR3_AC97_R_SECONDARY; |
2974 | else | 2975 | else |
2975 | address = NX_ACR2_AC97_R_PRIMARY; | 2976 | address = NX_ACR2_AC97_R_PRIMARY; |
2976 | mask = NX_AC97_BUSY_READ; | 2977 | mask = NX_AC97_BUSY_READ; |
2977 | busy = NX_AC97_BUSY_READ | NX_AC97_BUSY_DATA; | 2978 | busy = NX_AC97_BUSY_READ | NX_AC97_BUSY_DATA; |
2978 | break; | 2979 | break; |
2979 | case PCI_DEVICE_ID_INTERG_5050: | 2980 | case PCI_DEVICE_ID_INTERG_5050: |
2980 | address = SI_AC97_READ; | 2981 | address = SI_AC97_READ; |
2981 | mask = busy = SI_AC97_BUSY_READ; | 2982 | mask = busy = SI_AC97_BUSY_READ; |
2982 | if (codec->id) | 2983 | if (codec->id) |
2983 | mask |= SI_AC97_SECONDARY; | 2984 | mask |= SI_AC97_SECONDARY; |
2984 | break; | 2985 | break; |
2985 | } | 2986 | } |
2986 | 2987 | ||
2987 | data = (mask | (reg & AC97_REG_ADDR)); | 2988 | data = (mask | (reg & AC97_REG_ADDR)); |
2988 | 2989 | ||
2989 | spin_lock_irqsave(&card->lock, flags); | 2990 | spin_lock_irqsave(&card->lock, flags); |
2990 | outl(data, TRID_REG(card, address)); | 2991 | outl(data, TRID_REG(card, address)); |
2991 | do { | 2992 | do { |
2992 | data = inl(TRID_REG(card, address)); | 2993 | data = inl(TRID_REG(card, address)); |
2993 | if ((data & busy) == 0) | 2994 | if ((data & busy) == 0) |
2994 | break; | 2995 | break; |
2995 | } while (count--); | 2996 | } while (count--); |
2996 | spin_unlock_irqrestore(&card->lock, flags); | 2997 | spin_unlock_irqrestore(&card->lock, flags); |
2997 | 2998 | ||
2998 | if (count == 0) { | 2999 | if (count == 0) { |
2999 | printk(KERN_ERR "trident: AC97 CODEC read timed out.\n"); | 3000 | printk(KERN_ERR "trident: AC97 CODEC read timed out.\n"); |
3000 | data = 0; | 3001 | data = 0; |
3001 | } | 3002 | } |
3002 | return ((u16) (data >> 16)); | 3003 | return ((u16) (data >> 16)); |
3003 | } | 3004 | } |
3004 | 3005 | ||
3005 | /* rewrite ac97 read and write mixer register by hulei for ALI*/ | 3006 | /* rewrite ac97 read and write mixer register by hulei for ALI*/ |
3006 | static int | 3007 | static int |
3007 | acquirecodecaccess(struct trident_card *card) | 3008 | acquirecodecaccess(struct trident_card *card) |
3008 | { | 3009 | { |
3009 | u16 wsemamask = 0x6000; /* bit 14..13 */ | 3010 | u16 wsemamask = 0x6000; /* bit 14..13 */ |
3010 | u16 wsemabits; | 3011 | u16 wsemabits; |
3011 | u16 wcontrol; | 3012 | u16 wcontrol; |
3012 | int block = 0; | 3013 | int block = 0; |
3013 | int ncount = 25; | 3014 | int ncount = 25; |
3014 | while (1) { | 3015 | while (1) { |
3015 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | 3016 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); |
3016 | wsemabits = wcontrol & wsemamask; | 3017 | wsemabits = wcontrol & wsemamask; |
3017 | 3018 | ||
3018 | if (wsemabits == 0x4000) | 3019 | if (wsemabits == 0x4000) |
3019 | return 1; /* 0x4000 is audio ,then success */ | 3020 | return 1; /* 0x4000 is audio ,then success */ |
3020 | if (ncount-- < 0) | 3021 | if (ncount-- < 0) |
3021 | break; | 3022 | break; |
3022 | if (wsemabits == 0) { | 3023 | if (wsemabits == 0) { |
3023 | unlock: | 3024 | unlock: |
3024 | outl(((u32) (wcontrol & 0x1eff) | 0x00004000), | 3025 | outl(((u32) (wcontrol & 0x1eff) | 0x00004000), |
3025 | TRID_REG(card, ALI_AC97_WRITE)); | 3026 | TRID_REG(card, ALI_AC97_WRITE)); |
3026 | continue; | 3027 | continue; |
3027 | } | 3028 | } |
3028 | udelay(20); | 3029 | udelay(20); |
3029 | } | 3030 | } |
3030 | if (!block) { | 3031 | if (!block) { |
3031 | pr_debug("accesscodecsemaphore: try unlock\n"); | 3032 | pr_debug("accesscodecsemaphore: try unlock\n"); |
3032 | block = 1; | 3033 | block = 1; |
3033 | goto unlock; | 3034 | goto unlock; |
3034 | } | 3035 | } |
3035 | return 0; | 3036 | return 0; |
3036 | } | 3037 | } |
3037 | 3038 | ||
3038 | static void | 3039 | static void |
3039 | releasecodecaccess(struct trident_card *card) | 3040 | releasecodecaccess(struct trident_card *card) |
3040 | { | 3041 | { |
3041 | unsigned long wcontrol; | 3042 | unsigned long wcontrol; |
3042 | wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE)); | 3043 | wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE)); |
3043 | outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE)); | 3044 | outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE)); |
3044 | } | 3045 | } |
3045 | 3046 | ||
3046 | static int | 3047 | static int |
3047 | waitforstimertick(struct trident_card *card) | 3048 | waitforstimertick(struct trident_card *card) |
3048 | { | 3049 | { |
3049 | unsigned long chk1, chk2; | 3050 | unsigned long chk1, chk2; |
3050 | unsigned int wcount = 0xffff; | 3051 | unsigned int wcount = 0xffff; |
3051 | chk1 = inl(TRID_REG(card, ALI_STIMER)); | 3052 | chk1 = inl(TRID_REG(card, ALI_STIMER)); |
3052 | 3053 | ||
3053 | while (1) { | 3054 | while (1) { |
3054 | chk2 = inl(TRID_REG(card, ALI_STIMER)); | 3055 | chk2 = inl(TRID_REG(card, ALI_STIMER)); |
3055 | if ((wcount > 0) && chk1 != chk2) | 3056 | if ((wcount > 0) && chk1 != chk2) |
3056 | return 1; | 3057 | return 1; |
3057 | if (wcount <= 0) | 3058 | if (wcount <= 0) |
3058 | break; | 3059 | break; |
3059 | udelay(50); | 3060 | udelay(50); |
3060 | } | 3061 | } |
3061 | return 0; | 3062 | return 0; |
3062 | } | 3063 | } |
3063 | 3064 | ||
3064 | /* Read AC97 codec registers for ALi*/ | 3065 | /* Read AC97 codec registers for ALi*/ |
3065 | static u16 | 3066 | static u16 |
3066 | ali_ac97_get(struct trident_card *card, int secondary, u8 reg) | 3067 | ali_ac97_get(struct trident_card *card, int secondary, u8 reg) |
3067 | { | 3068 | { |
3068 | unsigned int address, mask; | 3069 | unsigned int address, mask; |
3069 | unsigned int ncount; | 3070 | unsigned int ncount; |
3070 | unsigned long aud_reg; | 3071 | unsigned long aud_reg; |
3071 | u32 data; | 3072 | u32 data; |
3072 | u16 wcontrol; | 3073 | u16 wcontrol; |
3073 | unsigned long flags; | 3074 | unsigned long flags; |
3074 | 3075 | ||
3075 | if (!card) | 3076 | if (!card) |
3076 | BUG(); | 3077 | BUG(); |
3077 | 3078 | ||
3078 | address = ALI_AC97_READ; | 3079 | address = ALI_AC97_READ; |
3079 | if (card->revision == ALI_5451_V02) { | 3080 | if (card->revision == ALI_5451_V02) { |
3080 | address = ALI_AC97_WRITE; | 3081 | address = ALI_AC97_WRITE; |
3081 | } | 3082 | } |
3082 | mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY; | 3083 | mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY; |
3083 | if (secondary) | 3084 | if (secondary) |
3084 | mask |= ALI_AC97_SECONDARY; | 3085 | mask |= ALI_AC97_SECONDARY; |
3085 | 3086 | ||
3086 | spin_lock_irqsave(&card->lock, flags); | 3087 | spin_lock_irqsave(&card->lock, flags); |
3087 | 3088 | ||
3088 | if (!acquirecodecaccess(card)) | 3089 | if (!acquirecodecaccess(card)) |
3089 | printk(KERN_ERR "access codec fail\n"); | 3090 | printk(KERN_ERR "access codec fail\n"); |
3090 | 3091 | ||
3091 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | 3092 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); |
3092 | wcontrol &= 0xfe00; | 3093 | wcontrol &= 0xfe00; |
3093 | wcontrol |= (0x8000 | reg); | 3094 | wcontrol |= (0x8000 | reg); |
3094 | outw(wcontrol, TRID_REG(card, ALI_AC97_WRITE)); | 3095 | outw(wcontrol, TRID_REG(card, ALI_AC97_WRITE)); |
3095 | 3096 | ||
3096 | data = (mask | (reg & AC97_REG_ADDR)); | 3097 | data = (mask | (reg & AC97_REG_ADDR)); |
3097 | 3098 | ||
3098 | if (!waitforstimertick(card)) { | 3099 | if (!waitforstimertick(card)) { |
3099 | printk(KERN_ERR "ali_ac97_read: BIT_CLOCK is dead\n"); | 3100 | printk(KERN_ERR "ali_ac97_read: BIT_CLOCK is dead\n"); |
3100 | goto releasecodec; | 3101 | goto releasecodec; |
3101 | } | 3102 | } |
3102 | 3103 | ||
3103 | udelay(20); | 3104 | udelay(20); |
3104 | 3105 | ||
3105 | ncount = 10; | 3106 | ncount = 10; |
3106 | 3107 | ||
3107 | while (1) { | 3108 | while (1) { |
3108 | if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) | 3109 | if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) |
3109 | != 0) | 3110 | != 0) |
3110 | break; | 3111 | break; |
3111 | if (ncount <= 0) | 3112 | if (ncount <= 0) |
3112 | break; | 3113 | break; |
3113 | if (ncount-- == 1) { | 3114 | if (ncount-- == 1) { |
3114 | pr_debug("ali_ac97_read :try clear busy flag\n"); | 3115 | pr_debug("ali_ac97_read :try clear busy flag\n"); |
3115 | aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE)); | 3116 | aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE)); |
3116 | outl((aud_reg & 0xffff7fff), | 3117 | outl((aud_reg & 0xffff7fff), |
3117 | TRID_REG(card, ALI_AC97_WRITE)); | 3118 | TRID_REG(card, ALI_AC97_WRITE)); |
3118 | } | 3119 | } |
3119 | udelay(10); | 3120 | udelay(10); |
3120 | } | 3121 | } |
3121 | 3122 | ||
3122 | data = inl(TRID_REG(card, address)); | 3123 | data = inl(TRID_REG(card, address)); |
3123 | 3124 | ||
3124 | spin_unlock_irqrestore(&card->lock, flags); | 3125 | spin_unlock_irqrestore(&card->lock, flags); |
3125 | 3126 | ||
3126 | return ((u16) (data >> 16)); | 3127 | return ((u16) (data >> 16)); |
3127 | 3128 | ||
3128 | releasecodec: | 3129 | releasecodec: |
3129 | releasecodecaccess(card); | 3130 | releasecodecaccess(card); |
3130 | spin_unlock_irqrestore(&card->lock, flags); | 3131 | spin_unlock_irqrestore(&card->lock, flags); |
3131 | printk(KERN_ERR "ali_ac97_read: AC97 CODEC read timed out.\n"); | 3132 | printk(KERN_ERR "ali_ac97_read: AC97 CODEC read timed out.\n"); |
3132 | return 0; | 3133 | return 0; |
3133 | } | 3134 | } |
3134 | 3135 | ||
3135 | /* Write AC97 codec registers for hulei*/ | 3136 | /* Write AC97 codec registers for hulei*/ |
3136 | static void | 3137 | static void |
3137 | ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) | 3138 | ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) |
3138 | { | 3139 | { |
3139 | unsigned int address, mask; | 3140 | unsigned int address, mask; |
3140 | unsigned int ncount; | 3141 | unsigned int ncount; |
3141 | u32 data; | 3142 | u32 data; |
3142 | u16 wcontrol; | 3143 | u16 wcontrol; |
3143 | unsigned long flags; | 3144 | unsigned long flags; |
3144 | 3145 | ||
3145 | data = ((u32) val) << 16; | 3146 | data = ((u32) val) << 16; |
3146 | 3147 | ||
3147 | if (!card) | 3148 | if (!card) |
3148 | BUG(); | 3149 | BUG(); |
3149 | 3150 | ||
3150 | address = ALI_AC97_WRITE; | 3151 | address = ALI_AC97_WRITE; |
3151 | mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; | 3152 | mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; |
3152 | if (secondary) | 3153 | if (secondary) |
3153 | mask |= ALI_AC97_SECONDARY; | 3154 | mask |= ALI_AC97_SECONDARY; |
3154 | if (card->revision == ALI_5451_V02) | 3155 | if (card->revision == ALI_5451_V02) |
3155 | mask |= ALI_AC97_WRITE_MIXER_REGISTER; | 3156 | mask |= ALI_AC97_WRITE_MIXER_REGISTER; |
3156 | 3157 | ||
3157 | spin_lock_irqsave(&card->lock, flags); | 3158 | spin_lock_irqsave(&card->lock, flags); |
3158 | if (!acquirecodecaccess(card)) | 3159 | if (!acquirecodecaccess(card)) |
3159 | printk(KERN_ERR "ali_ac97_write: access codec fail\n"); | 3160 | printk(KERN_ERR "ali_ac97_write: access codec fail\n"); |
3160 | 3161 | ||
3161 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | 3162 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); |
3162 | wcontrol &= 0xff00; | 3163 | wcontrol &= 0xff00; |
3163 | wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */ | 3164 | wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */ |
3164 | /* ali1535+ write */ | 3165 | /* ali1535+ write */ |
3165 | outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE)); | 3166 | outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE)); |
3166 | 3167 | ||
3167 | if (!waitforstimertick(card)) { | 3168 | if (!waitforstimertick(card)) { |
3168 | printk(KERN_ERR "BIT_CLOCK is dead\n"); | 3169 | printk(KERN_ERR "BIT_CLOCK is dead\n"); |
3169 | goto releasecodec; | 3170 | goto releasecodec; |
3170 | } | 3171 | } |
3171 | 3172 | ||
3172 | ncount = 10; | 3173 | ncount = 10; |
3173 | while (1) { | 3174 | while (1) { |
3174 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | 3175 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); |
3175 | if (!(wcontrol & 0x8000)) | 3176 | if (!(wcontrol & 0x8000)) |
3176 | break; | 3177 | break; |
3177 | if (ncount <= 0) | 3178 | if (ncount <= 0) |
3178 | break; | 3179 | break; |
3179 | if (ncount-- == 1) { | 3180 | if (ncount-- == 1) { |
3180 | pr_debug("ali_ac97_set :try clear busy flag!!\n"); | 3181 | pr_debug("ali_ac97_set :try clear busy flag!!\n"); |
3181 | outw(wcontrol & 0x7fff, | 3182 | outw(wcontrol & 0x7fff, |
3182 | TRID_REG(card, ALI_AC97_WRITE)); | 3183 | TRID_REG(card, ALI_AC97_WRITE)); |
3183 | } | 3184 | } |
3184 | udelay(10); | 3185 | udelay(10); |
3185 | } | 3186 | } |
3186 | 3187 | ||
3187 | releasecodec: | 3188 | releasecodec: |
3188 | releasecodecaccess(card); | 3189 | releasecodecaccess(card); |
3189 | spin_unlock_irqrestore(&card->lock, flags); | 3190 | spin_unlock_irqrestore(&card->lock, flags); |
3190 | return; | 3191 | return; |
3191 | } | 3192 | } |
3192 | 3193 | ||
3193 | static void | 3194 | static void |
3194 | ali_enable_special_channel(struct trident_state *stat) | 3195 | ali_enable_special_channel(struct trident_state *stat) |
3195 | { | 3196 | { |
3196 | struct trident_card *card = stat->card; | 3197 | struct trident_card *card = stat->card; |
3197 | unsigned long s_channels; | 3198 | unsigned long s_channels; |
3198 | 3199 | ||
3199 | s_channels = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3200 | s_channels = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3200 | s_channels |= (1 << stat->dmabuf.channel->num); | 3201 | s_channels |= (1 << stat->dmabuf.channel->num); |
3201 | outl(s_channels, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3202 | outl(s_channels, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3202 | } | 3203 | } |
3203 | 3204 | ||
3204 | static u16 | 3205 | static u16 |
3205 | ali_ac97_read(struct ac97_codec *codec, u8 reg) | 3206 | ali_ac97_read(struct ac97_codec *codec, u8 reg) |
3206 | { | 3207 | { |
3207 | int id; | 3208 | int id; |
3208 | u16 data; | 3209 | u16 data; |
3209 | struct trident_card *card = NULL; | 3210 | struct trident_card *card = NULL; |
3210 | 3211 | ||
3211 | /* Added by Matt Wu */ | 3212 | /* Added by Matt Wu */ |
3212 | if (!codec) | 3213 | if (!codec) |
3213 | BUG(); | 3214 | BUG(); |
3214 | 3215 | ||
3215 | card = (struct trident_card *) codec->private_data; | 3216 | card = (struct trident_card *) codec->private_data; |
3216 | 3217 | ||
3217 | if (!card->mixer_regs_ready) | 3218 | if (!card->mixer_regs_ready) |
3218 | return ali_ac97_get(card, codec->id, reg); | 3219 | return ali_ac97_get(card, codec->id, reg); |
3219 | 3220 | ||
3220 | /* | 3221 | /* |
3221 | * FIXME: need to stop this caching some registers | 3222 | * FIXME: need to stop this caching some registers |
3222 | */ | 3223 | */ |
3223 | if (codec->id) | 3224 | if (codec->id) |
3224 | id = 1; | 3225 | id = 1; |
3225 | else | 3226 | else |
3226 | id = 0; | 3227 | id = 0; |
3227 | 3228 | ||
3228 | data = card->mixer_regs[reg / 2][id]; | 3229 | data = card->mixer_regs[reg / 2][id]; |
3229 | return data; | 3230 | return data; |
3230 | } | 3231 | } |
3231 | 3232 | ||
3232 | static void | 3233 | static void |
3233 | ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val) | 3234 | ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val) |
3234 | { | 3235 | { |
3235 | int id; | 3236 | int id; |
3236 | struct trident_card *card; | 3237 | struct trident_card *card; |
3237 | 3238 | ||
3238 | /* Added by Matt Wu */ | 3239 | /* Added by Matt Wu */ |
3239 | if (!codec) | 3240 | if (!codec) |
3240 | BUG(); | 3241 | BUG(); |
3241 | 3242 | ||
3242 | card = (struct trident_card *) codec->private_data; | 3243 | card = (struct trident_card *) codec->private_data; |
3243 | 3244 | ||
3244 | if (!card->mixer_regs_ready) { | 3245 | if (!card->mixer_regs_ready) { |
3245 | ali_ac97_set(card, codec->id, reg, val); | 3246 | ali_ac97_set(card, codec->id, reg, val); |
3246 | return; | 3247 | return; |
3247 | } | 3248 | } |
3248 | 3249 | ||
3249 | if (codec->id) | 3250 | if (codec->id) |
3250 | id = 1; | 3251 | id = 1; |
3251 | else | 3252 | else |
3252 | id = 0; | 3253 | id = 0; |
3253 | 3254 | ||
3254 | card->mixer_regs[reg / 2][id] = val; | 3255 | card->mixer_regs[reg / 2][id] = val; |
3255 | ali_ac97_set(card, codec->id, reg, val); | 3256 | ali_ac97_set(card, codec->id, reg, val); |
3256 | } | 3257 | } |
3257 | 3258 | ||
3258 | /* | 3259 | /* |
3259 | flag: ALI_SPDIF_OUT_TO_SPDIF_OUT | 3260 | flag: ALI_SPDIF_OUT_TO_SPDIF_OUT |
3260 | ALI_PCM_TO_SPDIF_OUT | 3261 | ALI_PCM_TO_SPDIF_OUT |
3261 | */ | 3262 | */ |
3262 | 3263 | ||
3263 | static void | 3264 | static void |
3264 | ali_setup_spdif_out(struct trident_card *card, int flag) | 3265 | ali_setup_spdif_out(struct trident_card *card, int flag) |
3265 | { | 3266 | { |
3266 | unsigned long spdif; | 3267 | unsigned long spdif; |
3267 | unsigned char ch; | 3268 | unsigned char ch; |
3268 | 3269 | ||
3269 | char temp; | 3270 | char temp; |
3270 | struct pci_dev *pci_dev = NULL; | 3271 | struct pci_dev *pci_dev = NULL; |
3271 | 3272 | ||
3272 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | 3273 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, |
3273 | pci_dev); | 3274 | pci_dev); |
3274 | if (pci_dev == NULL) | 3275 | if (pci_dev == NULL) |
3275 | return; | 3276 | return; |
3276 | pci_read_config_byte(pci_dev, 0x61, &temp); | 3277 | pci_read_config_byte(pci_dev, 0x61, &temp); |
3277 | temp |= 0x40; | 3278 | temp |= 0x40; |
3278 | pci_write_config_byte(pci_dev, 0x61, temp); | 3279 | pci_write_config_byte(pci_dev, 0x61, temp); |
3279 | pci_read_config_byte(pci_dev, 0x7d, &temp); | 3280 | pci_read_config_byte(pci_dev, 0x7d, &temp); |
3280 | temp |= 0x01; | 3281 | temp |= 0x01; |
3281 | pci_write_config_byte(pci_dev, 0x7d, temp); | 3282 | pci_write_config_byte(pci_dev, 0x7d, temp); |
3282 | pci_read_config_byte(pci_dev, 0x7e, &temp); | 3283 | pci_read_config_byte(pci_dev, 0x7e, &temp); |
3283 | temp &= (~0x20); | 3284 | temp &= (~0x20); |
3284 | temp |= 0x10; | 3285 | temp |= 0x10; |
3285 | pci_write_config_byte(pci_dev, 0x7e, temp); | 3286 | pci_write_config_byte(pci_dev, 0x7e, temp); |
3286 | 3287 | ||
3287 | pci_dev_put(pci_dev); | 3288 | pci_dev_put(pci_dev); |
3288 | 3289 | ||
3289 | ch = inb(TRID_REG(card, ALI_SCTRL)); | 3290 | ch = inb(TRID_REG(card, ALI_SCTRL)); |
3290 | outb(ch | ALI_SPDIF_OUT_ENABLE, TRID_REG(card, ALI_SCTRL)); | 3291 | outb(ch | ALI_SPDIF_OUT_ENABLE, TRID_REG(card, ALI_SCTRL)); |
3291 | ch = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | 3292 | ch = inb(TRID_REG(card, ALI_SPDIF_CTRL)); |
3292 | outb(ch & ALI_SPDIF_OUT_CH_STATUS, TRID_REG(card, ALI_SPDIF_CTRL)); | 3293 | outb(ch & ALI_SPDIF_OUT_CH_STATUS, TRID_REG(card, ALI_SPDIF_CTRL)); |
3293 | 3294 | ||
3294 | if (flag & ALI_SPDIF_OUT_TO_SPDIF_OUT) { | 3295 | if (flag & ALI_SPDIF_OUT_TO_SPDIF_OUT) { |
3295 | spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3296 | spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3296 | spdif |= ALI_SPDIF_OUT_CH_ENABLE; | 3297 | spdif |= ALI_SPDIF_OUT_CH_ENABLE; |
3297 | spdif &= ALI_SPDIF_OUT_SEL_SPDIF; | 3298 | spdif &= ALI_SPDIF_OUT_SEL_SPDIF; |
3298 | outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3299 | outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3299 | spdif = inw(TRID_REG(card, ALI_SPDIF_CS)); | 3300 | spdif = inw(TRID_REG(card, ALI_SPDIF_CS)); |
3300 | if (flag & ALI_SPDIF_OUT_NON_PCM) | 3301 | if (flag & ALI_SPDIF_OUT_NON_PCM) |
3301 | spdif |= 0x0002; | 3302 | spdif |= 0x0002; |
3302 | else | 3303 | else |
3303 | spdif &= (~0x0002); | 3304 | spdif &= (~0x0002); |
3304 | outw(spdif, TRID_REG(card, ALI_SPDIF_CS)); | 3305 | outw(spdif, TRID_REG(card, ALI_SPDIF_CS)); |
3305 | } else { | 3306 | } else { |
3306 | spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3307 | spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3307 | spdif |= ALI_SPDIF_OUT_SEL_PCM; | 3308 | spdif |= ALI_SPDIF_OUT_SEL_PCM; |
3308 | outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3309 | outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3309 | } | 3310 | } |
3310 | } | 3311 | } |
3311 | 3312 | ||
3312 | static void | 3313 | static void |
3313 | ali_disable_special_channel(struct trident_card *card, int ch) | 3314 | ali_disable_special_channel(struct trident_card *card, int ch) |
3314 | { | 3315 | { |
3315 | unsigned long sc; | 3316 | unsigned long sc; |
3316 | 3317 | ||
3317 | sc = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3318 | sc = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3318 | sc &= ~(1 << ch); | 3319 | sc &= ~(1 << ch); |
3319 | outl(sc, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3320 | outl(sc, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3320 | } | 3321 | } |
3321 | 3322 | ||
3322 | static void | 3323 | static void |
3323 | ali_disable_spdif_in(struct trident_card *card) | 3324 | ali_disable_spdif_in(struct trident_card *card) |
3324 | { | 3325 | { |
3325 | unsigned long spdif; | 3326 | unsigned long spdif; |
3326 | 3327 | ||
3327 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3328 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3328 | spdif &= (~ALI_SPDIF_IN_SUPPORT); | 3329 | spdif &= (~ALI_SPDIF_IN_SUPPORT); |
3329 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3330 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3330 | 3331 | ||
3331 | ali_disable_special_channel(card, ALI_SPDIF_IN_CHANNEL); | 3332 | ali_disable_special_channel(card, ALI_SPDIF_IN_CHANNEL); |
3332 | } | 3333 | } |
3333 | 3334 | ||
3334 | static void | 3335 | static void |
3335 | ali_setup_spdif_in(struct trident_card *card) | 3336 | ali_setup_spdif_in(struct trident_card *card) |
3336 | { | 3337 | { |
3337 | unsigned long spdif; | 3338 | unsigned long spdif; |
3338 | 3339 | ||
3339 | //Set SPDIF IN Supported | 3340 | //Set SPDIF IN Supported |
3340 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3341 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3341 | spdif |= ALI_SPDIF_IN_SUPPORT; | 3342 | spdif |= ALI_SPDIF_IN_SUPPORT; |
3342 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3343 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3343 | 3344 | ||
3344 | //Set SPDIF IN Rec | 3345 | //Set SPDIF IN Rec |
3345 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3346 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3346 | spdif |= ALI_SPDIF_IN_CH_ENABLE; | 3347 | spdif |= ALI_SPDIF_IN_CH_ENABLE; |
3347 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 3348 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
3348 | 3349 | ||
3349 | spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | 3350 | spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL)); |
3350 | spdif |= ALI_SPDIF_IN_CH_STATUS; | 3351 | spdif |= ALI_SPDIF_IN_CH_STATUS; |
3351 | outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL)); | 3352 | outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL)); |
3352 | /* | 3353 | /* |
3353 | spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | 3354 | spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL)); |
3354 | spdif |= ALI_SPDIF_IN_FUNC_ENABLE; | 3355 | spdif |= ALI_SPDIF_IN_FUNC_ENABLE; |
3355 | outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL)); | 3356 | outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL)); |
3356 | */ | 3357 | */ |
3357 | } | 3358 | } |
3358 | 3359 | ||
3359 | static void | 3360 | static void |
3360 | ali_delay(struct trident_card *card, int interval) | 3361 | ali_delay(struct trident_card *card, int interval) |
3361 | { | 3362 | { |
3362 | unsigned long begintimer, currenttimer; | 3363 | unsigned long begintimer, currenttimer; |
3363 | 3364 | ||
3364 | begintimer = inl(TRID_REG(card, ALI_STIMER)); | 3365 | begintimer = inl(TRID_REG(card, ALI_STIMER)); |
3365 | currenttimer = inl(TRID_REG(card, ALI_STIMER)); | 3366 | currenttimer = inl(TRID_REG(card, ALI_STIMER)); |
3366 | 3367 | ||
3367 | while (currenttimer < begintimer + interval) | 3368 | while (currenttimer < begintimer + interval) |
3368 | currenttimer = inl(TRID_REG(card, ALI_STIMER)); | 3369 | currenttimer = inl(TRID_REG(card, ALI_STIMER)); |
3369 | } | 3370 | } |
3370 | 3371 | ||
3371 | static void | 3372 | static void |
3372 | ali_detect_spdif_rate(struct trident_card *card) | 3373 | ali_detect_spdif_rate(struct trident_card *card) |
3373 | { | 3374 | { |
3374 | u16 wval = 0; | 3375 | u16 wval = 0; |
3375 | u16 count = 0; | 3376 | u16 count = 0; |
3376 | u8 bval = 0, R1 = 0, R2 = 0; | 3377 | u8 bval = 0, R1 = 0, R2 = 0; |
3377 | 3378 | ||
3378 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | 3379 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); |
3379 | bval |= 0x02; | 3380 | bval |= 0x02; |
3380 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); | 3381 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); |
3381 | 3382 | ||
3382 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); | 3383 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); |
3383 | bval |= 0x1F; | 3384 | bval |= 0x1F; |
3384 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1)); | 3385 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1)); |
3385 | 3386 | ||
3386 | while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) && | 3387 | while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) && |
3387 | count <= 50000) { | 3388 | count <= 50000) { |
3388 | count++; | 3389 | count++; |
3389 | 3390 | ||
3390 | ali_delay(card, 6); | 3391 | ali_delay(card, 6); |
3391 | 3392 | ||
3392 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); | 3393 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); |
3393 | R1 = bval & 0x1F; | 3394 | R1 = bval & 0x1F; |
3394 | } | 3395 | } |
3395 | 3396 | ||
3396 | if (count > 50000) { | 3397 | if (count > 50000) { |
3397 | printk(KERN_WARNING "trident: Error in " | 3398 | printk(KERN_WARNING "trident: Error in " |
3398 | "ali_detect_spdif_rate!\n"); | 3399 | "ali_detect_spdif_rate!\n"); |
3399 | return; | 3400 | return; |
3400 | } | 3401 | } |
3401 | 3402 | ||
3402 | count = 0; | 3403 | count = 0; |
3403 | 3404 | ||
3404 | while (count <= 50000) { | 3405 | while (count <= 50000) { |
3405 | count++; | 3406 | count++; |
3406 | 3407 | ||
3407 | ali_delay(card, 6); | 3408 | ali_delay(card, 6); |
3408 | 3409 | ||
3409 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); | 3410 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); |
3410 | R2 = bval & 0x1F; | 3411 | R2 = bval & 0x1F; |
3411 | 3412 | ||
3412 | if (R2 != R1) | 3413 | if (R2 != R1) |
3413 | R1 = R2; | 3414 | R1 = R2; |
3414 | else | 3415 | else |
3415 | break; | 3416 | break; |
3416 | } | 3417 | } |
3417 | 3418 | ||
3418 | if (count > 50000) { | 3419 | if (count > 50000) { |
3419 | printk(KERN_WARNING "trident: Error in " | 3420 | printk(KERN_WARNING "trident: Error in " |
3420 | "ali_detect_spdif_rate!\n"); | 3421 | "ali_detect_spdif_rate!\n"); |
3421 | return; | 3422 | return; |
3422 | } | 3423 | } |
3423 | 3424 | ||
3424 | switch (R2) { | 3425 | switch (R2) { |
3425 | case 0x0b: | 3426 | case 0x0b: |
3426 | case 0x0c: | 3427 | case 0x0c: |
3427 | case 0x0d: | 3428 | case 0x0d: |
3428 | case 0x0e: | 3429 | case 0x0e: |
3429 | wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2)); | 3430 | wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2)); |
3430 | wval &= 0xE0F0; | 3431 | wval &= 0xE0F0; |
3431 | wval |= (u16) 0x09 << 8 | (u16) 0x05; | 3432 | wval |= (u16) 0x09 << 8 | (u16) 0x05; |
3432 | outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2)); | 3433 | outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2)); |
3433 | 3434 | ||
3434 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0; | 3435 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0; |
3435 | outb(bval | 0x02, TRID_REG(card, ALI_SPDIF_CS + 3)); | 3436 | outb(bval | 0x02, TRID_REG(card, ALI_SPDIF_CS + 3)); |
3436 | break; | 3437 | break; |
3437 | 3438 | ||
3438 | case 0x12: | 3439 | case 0x12: |
3439 | wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2)); | 3440 | wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2)); |
3440 | wval &= 0xE0F0; | 3441 | wval &= 0xE0F0; |
3441 | wval |= (u16) 0x0E << 8 | (u16) 0x08; | 3442 | wval |= (u16) 0x0E << 8 | (u16) 0x08; |
3442 | outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2)); | 3443 | outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2)); |
3443 | 3444 | ||
3444 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0; | 3445 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0; |
3445 | outb(bval | 0x03, TRID_REG(card, ALI_SPDIF_CS + 3)); | 3446 | outb(bval | 0x03, TRID_REG(card, ALI_SPDIF_CS + 3)); |
3446 | break; | 3447 | break; |
3447 | 3448 | ||
3448 | default: | 3449 | default: |
3449 | break; | 3450 | break; |
3450 | } | 3451 | } |
3451 | 3452 | ||
3452 | } | 3453 | } |
3453 | 3454 | ||
3454 | static unsigned int | 3455 | static unsigned int |
3455 | ali_get_spdif_in_rate(struct trident_card *card) | 3456 | ali_get_spdif_in_rate(struct trident_card *card) |
3456 | { | 3457 | { |
3457 | u32 dwRate = 0; | 3458 | u32 dwRate = 0; |
3458 | u8 bval = 0; | 3459 | u8 bval = 0; |
3459 | 3460 | ||
3460 | ali_detect_spdif_rate(card); | 3461 | ali_detect_spdif_rate(card); |
3461 | 3462 | ||
3462 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | 3463 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); |
3463 | bval &= 0x7F; | 3464 | bval &= 0x7F; |
3464 | bval |= 0x40; | 3465 | bval |= 0x40; |
3465 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); | 3466 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); |
3466 | 3467 | ||
3467 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)); | 3468 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)); |
3468 | bval &= 0x0F; | 3469 | bval &= 0x0F; |
3469 | 3470 | ||
3470 | switch (bval) { | 3471 | switch (bval) { |
3471 | case 0: | 3472 | case 0: |
3472 | dwRate = 44100; | 3473 | dwRate = 44100; |
3473 | break; | 3474 | break; |
3474 | case 1: | 3475 | case 1: |
3475 | dwRate = 48000; | 3476 | dwRate = 48000; |
3476 | break; | 3477 | break; |
3477 | case 2: | 3478 | case 2: |
3478 | dwRate = 32000; | 3479 | dwRate = 32000; |
3479 | break; | 3480 | break; |
3480 | default: | 3481 | default: |
3481 | // Error occurs | 3482 | // Error occurs |
3482 | break; | 3483 | break; |
3483 | } | 3484 | } |
3484 | 3485 | ||
3485 | return dwRate; | 3486 | return dwRate; |
3486 | 3487 | ||
3487 | } | 3488 | } |
3488 | 3489 | ||
3489 | static int | 3490 | static int |
3490 | ali_close_multi_channels(void) | 3491 | ali_close_multi_channels(void) |
3491 | { | 3492 | { |
3492 | char temp = 0; | 3493 | char temp = 0; |
3493 | struct pci_dev *pci_dev = NULL; | 3494 | struct pci_dev *pci_dev = NULL; |
3494 | 3495 | ||
3495 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | 3496 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, |
3496 | pci_dev); | 3497 | pci_dev); |
3497 | if (pci_dev == NULL) | 3498 | if (pci_dev == NULL) |
3498 | return -1; | 3499 | return -1; |
3499 | 3500 | ||
3500 | pci_read_config_byte(pci_dev, 0x59, &temp); | 3501 | pci_read_config_byte(pci_dev, 0x59, &temp); |
3501 | temp &= ~0x80; | 3502 | temp &= ~0x80; |
3502 | pci_write_config_byte(pci_dev, 0x59, temp); | 3503 | pci_write_config_byte(pci_dev, 0x59, temp); |
3503 | 3504 | ||
3504 | pci_dev_put(pci_dev); | 3505 | pci_dev_put(pci_dev); |
3505 | 3506 | ||
3506 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, | 3507 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, |
3507 | NULL); | 3508 | NULL); |
3508 | if (pci_dev == NULL) | 3509 | if (pci_dev == NULL) |
3509 | return -1; | 3510 | return -1; |
3510 | 3511 | ||
3511 | pci_read_config_byte(pci_dev, 0xB8, &temp); | 3512 | pci_read_config_byte(pci_dev, 0xB8, &temp); |
3512 | temp &= ~0x20; | 3513 | temp &= ~0x20; |
3513 | pci_write_config_byte(pci_dev, 0xB8, temp); | 3514 | pci_write_config_byte(pci_dev, 0xB8, temp); |
3514 | 3515 | ||
3515 | pci_dev_put(pci_dev); | 3516 | pci_dev_put(pci_dev); |
3516 | 3517 | ||
3517 | return 0; | 3518 | return 0; |
3518 | } | 3519 | } |
3519 | 3520 | ||
3520 | static int | 3521 | static int |
3521 | ali_setup_multi_channels(struct trident_card *card, int chan_nums) | 3522 | ali_setup_multi_channels(struct trident_card *card, int chan_nums) |
3522 | { | 3523 | { |
3523 | unsigned long dwValue; | 3524 | unsigned long dwValue; |
3524 | char temp = 0; | 3525 | char temp = 0; |
3525 | struct pci_dev *pci_dev = NULL; | 3526 | struct pci_dev *pci_dev = NULL; |
3526 | 3527 | ||
3527 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | 3528 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, |
3528 | pci_dev); | 3529 | pci_dev); |
3529 | if (pci_dev == NULL) | 3530 | if (pci_dev == NULL) |
3530 | return -1; | 3531 | return -1; |
3531 | pci_read_config_byte(pci_dev, 0x59, &temp); | 3532 | pci_read_config_byte(pci_dev, 0x59, &temp); |
3532 | temp |= 0x80; | 3533 | temp |= 0x80; |
3533 | pci_write_config_byte(pci_dev, 0x59, temp); | 3534 | pci_write_config_byte(pci_dev, 0x59, temp); |
3534 | 3535 | ||
3535 | pci_dev_put(pci_dev); | 3536 | pci_dev_put(pci_dev); |
3536 | 3537 | ||
3537 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, | 3538 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, |
3538 | NULL); | 3539 | NULL); |
3539 | if (pci_dev == NULL) | 3540 | if (pci_dev == NULL) |
3540 | return -1; | 3541 | return -1; |
3541 | pci_read_config_byte(pci_dev, (int) 0xB8, &temp); | 3542 | pci_read_config_byte(pci_dev, (int) 0xB8, &temp); |
3542 | temp |= 0x20; | 3543 | temp |= 0x20; |
3543 | pci_write_config_byte(pci_dev, (int) 0xB8, (u8) temp); | 3544 | pci_write_config_byte(pci_dev, (int) 0xB8, (u8) temp); |
3544 | 3545 | ||
3545 | pci_dev_put(pci_dev); | 3546 | pci_dev_put(pci_dev); |
3546 | 3547 | ||
3547 | if (chan_nums == 6) { | 3548 | if (chan_nums == 6) { |
3548 | dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000; | 3549 | dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000; |
3549 | outl(dwValue, TRID_REG(card, ALI_SCTRL)); | 3550 | outl(dwValue, TRID_REG(card, ALI_SCTRL)); |
3550 | mdelay(4); | 3551 | mdelay(4); |
3551 | dwValue = inl(TRID_REG(card, ALI_SCTRL)); | 3552 | dwValue = inl(TRID_REG(card, ALI_SCTRL)); |
3552 | if (dwValue & 0x2000000) { | 3553 | if (dwValue & 0x2000000) { |
3553 | ali_ac97_write(card->ac97_codec[0], 0x02, 8080); | 3554 | ali_ac97_write(card->ac97_codec[0], 0x02, 8080); |
3554 | ali_ac97_write(card->ac97_codec[0], 0x36, 0); | 3555 | ali_ac97_write(card->ac97_codec[0], 0x36, 0); |
3555 | ali_ac97_write(card->ac97_codec[0], 0x38, 0); | 3556 | ali_ac97_write(card->ac97_codec[0], 0x38, 0); |
3556 | /* | 3557 | /* |
3557 | * On a board with a single codec you won't get the | 3558 | * On a board with a single codec you won't get the |
3558 | * surround. On other boards configure it. | 3559 | * surround. On other boards configure it. |
3559 | */ | 3560 | */ |
3560 | if (card->ac97_codec[1] != NULL) { | 3561 | if (card->ac97_codec[1] != NULL) { |
3561 | ali_ac97_write(card->ac97_codec[1], 0x36, 0); | 3562 | ali_ac97_write(card->ac97_codec[1], 0x36, 0); |
3562 | ali_ac97_write(card->ac97_codec[1], 0x38, 0); | 3563 | ali_ac97_write(card->ac97_codec[1], 0x38, 0); |
3563 | ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606); | 3564 | ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606); |
3564 | ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303); | 3565 | ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303); |
3565 | ali_ac97_write(card->ac97_codec[1], 0x74, 0x3); | 3566 | ali_ac97_write(card->ac97_codec[1], 0x74, 0x3); |
3566 | } | 3567 | } |
3567 | return 1; | 3568 | return 1; |
3568 | } | 3569 | } |
3569 | } | 3570 | } |
3570 | return -EINVAL; | 3571 | return -EINVAL; |
3571 | } | 3572 | } |
3572 | 3573 | ||
3573 | static void | 3574 | static void |
3574 | ali_free_pcm_channel(struct trident_card *card, unsigned int channel) | 3575 | ali_free_pcm_channel(struct trident_card *card, unsigned int channel) |
3575 | { | 3576 | { |
3576 | int bank; | 3577 | int bank; |
3577 | 3578 | ||
3578 | if (channel > 31) | 3579 | if (channel > 31) |
3579 | return; | 3580 | return; |
3580 | 3581 | ||
3581 | bank = channel >> 5; | 3582 | bank = channel >> 5; |
3582 | channel = channel & 0x1f; | 3583 | channel = channel & 0x1f; |
3583 | 3584 | ||
3584 | card->banks[bank].bitmap &= ~(1 << (channel)); | 3585 | card->banks[bank].bitmap &= ~(1 << (channel)); |
3585 | } | 3586 | } |
3586 | 3587 | ||
3587 | static int | 3588 | static int |
3588 | ali_allocate_other_states_resources(struct trident_state *state, int chan_nums) | 3589 | ali_allocate_other_states_resources(struct trident_state *state, int chan_nums) |
3589 | { | 3590 | { |
3590 | struct trident_card *card = state->card; | 3591 | struct trident_card *card = state->card; |
3591 | struct trident_state *s; | 3592 | struct trident_state *s; |
3592 | int i, state_count = 0; | 3593 | int i, state_count = 0; |
3593 | struct trident_pcm_bank *bank; | 3594 | struct trident_pcm_bank *bank; |
3594 | struct trident_channel *channel; | 3595 | struct trident_channel *channel; |
3595 | unsigned long num; | 3596 | unsigned long num; |
3596 | 3597 | ||
3597 | bank = &card->banks[BANK_A]; | 3598 | bank = &card->banks[BANK_A]; |
3598 | 3599 | ||
3599 | if (chan_nums != 6) | 3600 | if (chan_nums != 6) |
3600 | return 0; | 3601 | return 0; |
3601 | 3602 | ||
3602 | for (i = 0; (i < ALI_CHANNELS) && (state_count != 4); i++) { | 3603 | for (i = 0; (i < ALI_CHANNELS) && (state_count != 4); i++) { |
3603 | if (card->states[i]) | 3604 | if (card->states[i]) |
3604 | continue; | 3605 | continue; |
3605 | 3606 | ||
3606 | num = ali_multi_channels_5_1[state_count]; | 3607 | num = ali_multi_channels_5_1[state_count]; |
3607 | if (!(bank->bitmap & (1 << num))) { | 3608 | if (!(bank->bitmap & (1 << num))) { |
3608 | bank->bitmap |= 1 << num; | 3609 | bank->bitmap |= 1 << num; |
3609 | channel = &bank->channels[num]; | 3610 | channel = &bank->channels[num]; |
3610 | channel->num = num; | 3611 | channel->num = num; |
3611 | } else { | 3612 | } else { |
3612 | state_count--; | 3613 | state_count--; |
3613 | for (; state_count >= 0; state_count--) { | 3614 | for (; state_count >= 0; state_count--) { |
3614 | kfree(state->other_states[state_count]); | 3615 | kfree(state->other_states[state_count]); |
3615 | num = ali_multi_channels_5_1[state_count]; | 3616 | num = ali_multi_channels_5_1[state_count]; |
3616 | ali_free_pcm_channel(card, num); | 3617 | ali_free_pcm_channel(card, num); |
3617 | } | 3618 | } |
3618 | return -EBUSY; | 3619 | return -EBUSY; |
3619 | } | 3620 | } |
3620 | s = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); | 3621 | s = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); |
3621 | if (!s) { | 3622 | if (!s) { |
3622 | num = ali_multi_channels_5_1[state_count]; | 3623 | num = ali_multi_channels_5_1[state_count]; |
3623 | ali_free_pcm_channel(card, num); | 3624 | ali_free_pcm_channel(card, num); |
3624 | state_count--; | 3625 | state_count--; |
3625 | for (; state_count >= 0; state_count--) { | 3626 | for (; state_count >= 0; state_count--) { |
3626 | num = ali_multi_channels_5_1[state_count]; | 3627 | num = ali_multi_channels_5_1[state_count]; |
3627 | ali_free_pcm_channel(card, num); | 3628 | ali_free_pcm_channel(card, num); |
3628 | kfree(state->other_states[state_count]); | 3629 | kfree(state->other_states[state_count]); |
3629 | } | 3630 | } |
3630 | return -ENOMEM; | 3631 | return -ENOMEM; |
3631 | } | 3632 | } |
3632 | memset(s, 0, sizeof(*state)); | 3633 | memset(s, 0, sizeof(*state)); |
3633 | 3634 | ||
3634 | s->dmabuf.channel = channel; | 3635 | s->dmabuf.channel = channel; |
3635 | s->dmabuf.ossfragshift = s->dmabuf.ossmaxfrags = | 3636 | s->dmabuf.ossfragshift = s->dmabuf.ossmaxfrags = |
3636 | s->dmabuf.subdivision = 0; | 3637 | s->dmabuf.subdivision = 0; |
3637 | init_waitqueue_head(&s->dmabuf.wait); | 3638 | init_waitqueue_head(&s->dmabuf.wait); |
3638 | s->magic = card->magic; | 3639 | s->magic = card->magic; |
3639 | s->card = card; | 3640 | s->card = card; |
3640 | s->virt = i; | 3641 | s->virt = i; |
3641 | ali_enable_special_channel(s); | 3642 | ali_enable_special_channel(s); |
3642 | state->other_states[state_count++] = s; | 3643 | state->other_states[state_count++] = s; |
3643 | } | 3644 | } |
3644 | 3645 | ||
3645 | if (state_count != 4) { | 3646 | if (state_count != 4) { |
3646 | state_count--; | 3647 | state_count--; |
3647 | for (; state_count >= 0; state_count--) { | 3648 | for (; state_count >= 0; state_count--) { |
3648 | kfree(state->other_states[state_count]); | 3649 | kfree(state->other_states[state_count]); |
3649 | num = ali_multi_channels_5_1[state_count]; | 3650 | num = ali_multi_channels_5_1[state_count]; |
3650 | ali_free_pcm_channel(card, num); | 3651 | ali_free_pcm_channel(card, num); |
3651 | } | 3652 | } |
3652 | return -EBUSY; | 3653 | return -EBUSY; |
3653 | } | 3654 | } |
3654 | return 0; | 3655 | return 0; |
3655 | } | 3656 | } |
3656 | 3657 | ||
3657 | #ifdef CONFIG_PM | 3658 | #ifdef CONFIG_PM |
3658 | /* save registers for ALi Power Management */ | 3659 | /* save registers for ALi Power Management */ |
3659 | static struct ali_saved_registers { | 3660 | static struct ali_saved_registers { |
3660 | unsigned long global_regs[ALI_GLOBAL_REGS]; | 3661 | unsigned long global_regs[ALI_GLOBAL_REGS]; |
3661 | unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS]; | 3662 | unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS]; |
3662 | unsigned mixer_regs[ALI_MIXER_REGS]; | 3663 | unsigned mixer_regs[ALI_MIXER_REGS]; |
3663 | } ali_registers; | 3664 | } ali_registers; |
3664 | 3665 | ||
3665 | static void | 3666 | static void |
3666 | ali_save_regs(struct trident_card *card) | 3667 | ali_save_regs(struct trident_card *card) |
3667 | { | 3668 | { |
3668 | unsigned long flags; | 3669 | unsigned long flags; |
3669 | int i, j; | 3670 | int i, j; |
3670 | 3671 | ||
3671 | spin_lock_irqsave(&card->lock, flags); | 3672 | spin_lock_irqsave(&card->lock, flags); |
3672 | 3673 | ||
3673 | ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT)); | 3674 | ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT)); |
3674 | //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A)); | 3675 | //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A)); |
3675 | ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A)); | 3676 | ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A)); |
3676 | 3677 | ||
3677 | //disable all IRQ bits | 3678 | //disable all IRQ bits |
3678 | outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT)); | 3679 | outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT)); |
3679 | 3680 | ||
3680 | for (i = 1; i < ALI_MIXER_REGS; i++) | 3681 | for (i = 1; i < ALI_MIXER_REGS; i++) |
3681 | ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0], | 3682 | ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0], |
3682 | i * 2); | 3683 | i * 2); |
3683 | 3684 | ||
3684 | for (i = 0; i < ALI_GLOBAL_REGS; i++) { | 3685 | for (i = 0; i < ALI_GLOBAL_REGS; i++) { |
3685 | if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A)) | 3686 | if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A)) |
3686 | continue; | 3687 | continue; |
3687 | ali_registers.global_regs[i] = inl(TRID_REG(card, i * 4)); | 3688 | ali_registers.global_regs[i] = inl(TRID_REG(card, i * 4)); |
3688 | } | 3689 | } |
3689 | 3690 | ||
3690 | for (i = 0; i < ALI_CHANNELS; i++) { | 3691 | for (i = 0; i < ALI_CHANNELS; i++) { |
3691 | outb(i, TRID_REG(card, T4D_LFO_GC_CIR)); | 3692 | outb(i, TRID_REG(card, T4D_LFO_GC_CIR)); |
3692 | for (j = 0; j < ALI_CHANNEL_REGS; j++) | 3693 | for (j = 0; j < ALI_CHANNEL_REGS; j++) |
3693 | ali_registers.channel_regs[i][j] = inl(TRID_REG(card, | 3694 | ali_registers.channel_regs[i][j] = inl(TRID_REG(card, |
3694 | j * 4 + 0xe0)); | 3695 | j * 4 + 0xe0)); |
3695 | } | 3696 | } |
3696 | 3697 | ||
3697 | //Stop all HW channel | 3698 | //Stop all HW channel |
3698 | outl(ALI_STOP_ALL_CHANNELS, TRID_REG(card, T4D_STOP_A)); | 3699 | outl(ALI_STOP_ALL_CHANNELS, TRID_REG(card, T4D_STOP_A)); |
3699 | 3700 | ||
3700 | spin_unlock_irqrestore(&card->lock, flags); | 3701 | spin_unlock_irqrestore(&card->lock, flags); |
3701 | } | 3702 | } |
3702 | 3703 | ||
3703 | static void | 3704 | static void |
3704 | ali_restore_regs(struct trident_card *card) | 3705 | ali_restore_regs(struct trident_card *card) |
3705 | { | 3706 | { |
3706 | unsigned long flags; | 3707 | unsigned long flags; |
3707 | int i, j; | 3708 | int i, j; |
3708 | 3709 | ||
3709 | spin_lock_irqsave(&card->lock, flags); | 3710 | spin_lock_irqsave(&card->lock, flags); |
3710 | 3711 | ||
3711 | for (i = 1; i < ALI_MIXER_REGS; i++) | 3712 | for (i = 1; i < ALI_MIXER_REGS; i++) |
3712 | ali_ac97_write(card->ac97_codec[0], i * 2, | 3713 | ali_ac97_write(card->ac97_codec[0], i * 2, |
3713 | ali_registers.mixer_regs[i]); | 3714 | ali_registers.mixer_regs[i]); |
3714 | 3715 | ||
3715 | for (i = 0; i < ALI_CHANNELS; i++) { | 3716 | for (i = 0; i < ALI_CHANNELS; i++) { |
3716 | outb(i, TRID_REG(card, T4D_LFO_GC_CIR)); | 3717 | outb(i, TRID_REG(card, T4D_LFO_GC_CIR)); |
3717 | for (j = 0; j < ALI_CHANNEL_REGS; j++) | 3718 | for (j = 0; j < ALI_CHANNEL_REGS; j++) |
3718 | outl(ali_registers.channel_regs[i][j], | 3719 | outl(ali_registers.channel_regs[i][j], |
3719 | TRID_REG(card, j * 4 + 0xe0)); | 3720 | TRID_REG(card, j * 4 + 0xe0)); |
3720 | } | 3721 | } |
3721 | 3722 | ||
3722 | for (i = 0; i < ALI_GLOBAL_REGS; i++) { | 3723 | for (i = 0; i < ALI_GLOBAL_REGS; i++) { |
3723 | if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) || | 3724 | if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) || |
3724 | (i * 4 == T4D_START_A)) | 3725 | (i * 4 == T4D_START_A)) |
3725 | continue; | 3726 | continue; |
3726 | outl(ali_registers.global_regs[i], TRID_REG(card, i * 4)); | 3727 | outl(ali_registers.global_regs[i], TRID_REG(card, i * 4)); |
3727 | } | 3728 | } |
3728 | 3729 | ||
3729 | //start HW channel | 3730 | //start HW channel |
3730 | outl(ali_registers.global_regs[0x20], TRID_REG(card, T4D_START_A)); | 3731 | outl(ali_registers.global_regs[0x20], TRID_REG(card, T4D_START_A)); |
3731 | //restore IRQ enable bits | 3732 | //restore IRQ enable bits |
3732 | outl(ali_registers.global_regs[0x2c], TRID_REG(card, T4D_MISCINT)); | 3733 | outl(ali_registers.global_regs[0x2c], TRID_REG(card, T4D_MISCINT)); |
3733 | 3734 | ||
3734 | spin_unlock_irqrestore(&card->lock, flags); | 3735 | spin_unlock_irqrestore(&card->lock, flags); |
3735 | } | 3736 | } |
3736 | 3737 | ||
3737 | static int | 3738 | static int |
3738 | trident_suspend(struct pci_dev *dev, pm_message_t unused) | 3739 | trident_suspend(struct pci_dev *dev, pm_message_t unused) |
3739 | { | 3740 | { |
3740 | struct trident_card *card = pci_get_drvdata(dev); | 3741 | struct trident_card *card = pci_get_drvdata(dev); |
3741 | 3742 | ||
3742 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 3743 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
3743 | ali_save_regs(card); | 3744 | ali_save_regs(card); |
3744 | } | 3745 | } |
3745 | return 0; | 3746 | return 0; |
3746 | } | 3747 | } |
3747 | 3748 | ||
3748 | static int | 3749 | static int |
3749 | trident_resume(struct pci_dev *dev) | 3750 | trident_resume(struct pci_dev *dev) |
3750 | { | 3751 | { |
3751 | struct trident_card *card = pci_get_drvdata(dev); | 3752 | struct trident_card *card = pci_get_drvdata(dev); |
3752 | 3753 | ||
3753 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 3754 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
3754 | ali_restore_regs(card); | 3755 | ali_restore_regs(card); |
3755 | } | 3756 | } |
3756 | return 0; | 3757 | return 0; |
3757 | } | 3758 | } |
3758 | #endif | 3759 | #endif |
3759 | 3760 | ||
3760 | static struct trident_channel * | 3761 | static struct trident_channel * |
3761 | ali_alloc_pcm_channel(struct trident_card *card) | 3762 | ali_alloc_pcm_channel(struct trident_card *card) |
3762 | { | 3763 | { |
3763 | struct trident_pcm_bank *bank; | 3764 | struct trident_pcm_bank *bank; |
3764 | int idx; | 3765 | int idx; |
3765 | 3766 | ||
3766 | bank = &card->banks[BANK_A]; | 3767 | bank = &card->banks[BANK_A]; |
3767 | 3768 | ||
3768 | if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & | 3769 | if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & |
3769 | (ALI_SPDIF_OUT_CH_ENABLE)) { | 3770 | (ALI_SPDIF_OUT_CH_ENABLE)) { |
3770 | idx = ALI_SPDIF_OUT_CHANNEL; | 3771 | idx = ALI_SPDIF_OUT_CHANNEL; |
3771 | if (!(bank->bitmap & (1 << idx))) { | 3772 | if (!(bank->bitmap & (1 << idx))) { |
3772 | struct trident_channel *channel = &bank->channels[idx]; | 3773 | struct trident_channel *channel = &bank->channels[idx]; |
3773 | bank->bitmap |= 1 << idx; | 3774 | bank->bitmap |= 1 << idx; |
3774 | channel->num = idx; | 3775 | channel->num = idx; |
3775 | return channel; | 3776 | return channel; |
3776 | } | 3777 | } |
3777 | } | 3778 | } |
3778 | 3779 | ||
3779 | for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST; | 3780 | for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST; |
3780 | idx++) { | 3781 | idx++) { |
3781 | if (!(bank->bitmap & (1 << idx))) { | 3782 | if (!(bank->bitmap & (1 << idx))) { |
3782 | struct trident_channel *channel = &bank->channels[idx]; | 3783 | struct trident_channel *channel = &bank->channels[idx]; |
3783 | bank->bitmap |= 1 << idx; | 3784 | bank->bitmap |= 1 << idx; |
3784 | channel->num = idx; | 3785 | channel->num = idx; |
3785 | return channel; | 3786 | return channel; |
3786 | } | 3787 | } |
3787 | } | 3788 | } |
3788 | 3789 | ||
3789 | /* no more free channels avaliable */ | 3790 | /* no more free channels avaliable */ |
3790 | #if 0 | 3791 | #if 0 |
3791 | printk(KERN_ERR "ali: no more channels available on Bank A.\n"); | 3792 | printk(KERN_ERR "ali: no more channels available on Bank A.\n"); |
3792 | #endif /* 0 */ | 3793 | #endif /* 0 */ |
3793 | return NULL; | 3794 | return NULL; |
3794 | } | 3795 | } |
3795 | 3796 | ||
3796 | static struct trident_channel * | 3797 | static struct trident_channel * |
3797 | ali_alloc_rec_pcm_channel(struct trident_card *card) | 3798 | ali_alloc_rec_pcm_channel(struct trident_card *card) |
3798 | { | 3799 | { |
3799 | struct trident_pcm_bank *bank; | 3800 | struct trident_pcm_bank *bank; |
3800 | int idx; | 3801 | int idx; |
3801 | 3802 | ||
3802 | if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_IN_SUPPORT) | 3803 | if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_IN_SUPPORT) |
3803 | idx = ALI_SPDIF_IN_CHANNEL; | 3804 | idx = ALI_SPDIF_IN_CHANNEL; |
3804 | else | 3805 | else |
3805 | idx = ALI_PCM_IN_CHANNEL; | 3806 | idx = ALI_PCM_IN_CHANNEL; |
3806 | 3807 | ||
3807 | bank = &card->banks[BANK_A]; | 3808 | bank = &card->banks[BANK_A]; |
3808 | 3809 | ||
3809 | if (!(bank->bitmap & (1 << idx))) { | 3810 | if (!(bank->bitmap & (1 << idx))) { |
3810 | struct trident_channel *channel = &bank->channels[idx]; | 3811 | struct trident_channel *channel = &bank->channels[idx]; |
3811 | bank->bitmap |= 1 << idx; | 3812 | bank->bitmap |= 1 << idx; |
3812 | channel->num = idx; | 3813 | channel->num = idx; |
3813 | return channel; | 3814 | return channel; |
3814 | } | 3815 | } |
3815 | 3816 | ||
3816 | /* no free recordable channels avaliable */ | 3817 | /* no free recordable channels avaliable */ |
3817 | #if 0 | 3818 | #if 0 |
3818 | printk(KERN_ERR "ali: no recordable channels available on Bank A.\n"); | 3819 | printk(KERN_ERR "ali: no recordable channels available on Bank A.\n"); |
3819 | #endif /* 0 */ | 3820 | #endif /* 0 */ |
3820 | return NULL; | 3821 | return NULL; |
3821 | } | 3822 | } |
3822 | 3823 | ||
3823 | static void | 3824 | static void |
3824 | ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate) | 3825 | ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate) |
3825 | { | 3826 | { |
3826 | unsigned char ch_st_sel; | 3827 | unsigned char ch_st_sel; |
3827 | unsigned short status_rate; | 3828 | unsigned short status_rate; |
3828 | 3829 | ||
3829 | switch (rate) { | 3830 | switch (rate) { |
3830 | case 44100: | 3831 | case 44100: |
3831 | status_rate = 0; | 3832 | status_rate = 0; |
3832 | break; | 3833 | break; |
3833 | case 32000: | 3834 | case 32000: |
3834 | status_rate = 0x300; | 3835 | status_rate = 0x300; |
3835 | break; | 3836 | break; |
3836 | case 48000: | 3837 | case 48000: |
3837 | default: | 3838 | default: |
3838 | status_rate = 0x200; | 3839 | status_rate = 0x200; |
3839 | break; | 3840 | break; |
3840 | } | 3841 | } |
3841 | 3842 | ||
3842 | /* select spdif_out */ | 3843 | /* select spdif_out */ |
3843 | ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS; | 3844 | ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS; |
3844 | 3845 | ||
3845 | ch_st_sel |= 0x80; /* select right */ | 3846 | ch_st_sel |= 0x80; /* select right */ |
3846 | outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL)); | 3847 | outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL)); |
3847 | outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2)); | 3848 | outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2)); |
3848 | 3849 | ||
3849 | ch_st_sel &= (~0x80); /* select left */ | 3850 | ch_st_sel &= (~0x80); /* select left */ |
3850 | outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL)); | 3851 | outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL)); |
3851 | outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2)); | 3852 | outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2)); |
3852 | } | 3853 | } |
3853 | 3854 | ||
3854 | static void | 3855 | static void |
3855 | ali_address_interrupt(struct trident_card *card) | 3856 | ali_address_interrupt(struct trident_card *card) |
3856 | { | 3857 | { |
3857 | int i, channel; | 3858 | int i, channel; |
3858 | struct trident_state *state; | 3859 | struct trident_state *state; |
3859 | u32 mask, channel_mask; | 3860 | u32 mask, channel_mask; |
3860 | 3861 | ||
3861 | mask = trident_get_interrupt_mask(card, 0); | 3862 | mask = trident_get_interrupt_mask(card, 0); |
3862 | for (i = 0; i < NR_HW_CH; i++) { | 3863 | for (i = 0; i < NR_HW_CH; i++) { |
3863 | if ((state = card->states[i]) == NULL) | 3864 | if ((state = card->states[i]) == NULL) |
3864 | continue; | 3865 | continue; |
3865 | channel = state->dmabuf.channel->num; | 3866 | channel = state->dmabuf.channel->num; |
3866 | if ((channel_mask = 1 << channel) & mask) { | 3867 | if ((channel_mask = 1 << channel) & mask) { |
3867 | mask &= ~channel_mask; | 3868 | mask &= ~channel_mask; |
3868 | trident_ack_channel_interrupt(card, channel); | 3869 | trident_ack_channel_interrupt(card, channel); |
3869 | udelay(100); | 3870 | udelay(100); |
3870 | state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE; | 3871 | state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE; |
3871 | trident_update_ptr(state); | 3872 | trident_update_ptr(state); |
3872 | } | 3873 | } |
3873 | } | 3874 | } |
3874 | if (mask) { | 3875 | if (mask) { |
3875 | for (i = 0; i < NR_HW_CH; i++) { | 3876 | for (i = 0; i < NR_HW_CH; i++) { |
3876 | if (mask & (1 << i)) { | 3877 | if (mask & (1 << i)) { |
3877 | printk("ali: spurious channel irq %d.\n", i); | 3878 | printk("ali: spurious channel irq %d.\n", i); |
3878 | trident_ack_channel_interrupt(card, i); | 3879 | trident_ack_channel_interrupt(card, i); |
3879 | trident_stop_voice(card, i); | 3880 | trident_stop_voice(card, i); |
3880 | trident_disable_voice_irq(card, i); | 3881 | trident_disable_voice_irq(card, i); |
3881 | } | 3882 | } |
3882 | } | 3883 | } |
3883 | } | 3884 | } |
3884 | } | 3885 | } |
3885 | 3886 | ||
3886 | /* Updating the values of counters of other_states' DMAs without lock | 3887 | /* Updating the values of counters of other_states' DMAs without lock |
3887 | protection is no harm because all DMAs of multi-channels and interrupt | 3888 | protection is no harm because all DMAs of multi-channels and interrupt |
3888 | depend on a master state's DMA, and changing the counters of the master | 3889 | depend on a master state's DMA, and changing the counters of the master |
3889 | state DMA is protected by a spinlock. | 3890 | state DMA is protected by a spinlock. |
3890 | */ | 3891 | */ |
3891 | static int | 3892 | static int |
3892 | ali_write_5_1(struct trident_state *state, const char __user *buf, | 3893 | ali_write_5_1(struct trident_state *state, const char __user *buf, |
3893 | int cnt_for_multi_channel, unsigned int *copy_count, | 3894 | int cnt_for_multi_channel, unsigned int *copy_count, |
3894 | unsigned int *state_cnt) | 3895 | unsigned int *state_cnt) |
3895 | { | 3896 | { |
3896 | 3897 | ||
3897 | struct dmabuf *dmabuf = &state->dmabuf; | 3898 | struct dmabuf *dmabuf = &state->dmabuf; |
3898 | struct dmabuf *dmabuf_temp; | 3899 | struct dmabuf *dmabuf_temp; |
3899 | const char __user *buffer = buf; | 3900 | const char __user *buffer = buf; |
3900 | unsigned swptr, other_dma_nums, sample_s; | 3901 | unsigned swptr, other_dma_nums, sample_s; |
3901 | unsigned int i, loop; | 3902 | unsigned int i, loop; |
3902 | 3903 | ||
3903 | other_dma_nums = 4; | 3904 | other_dma_nums = 4; |
3904 | sample_s = sample_size[dmabuf->fmt] >> 1; | 3905 | sample_s = sample_size[dmabuf->fmt] >> 1; |
3905 | swptr = dmabuf->swptr; | 3906 | swptr = dmabuf->swptr; |
3906 | 3907 | ||
3907 | if ((i = state->multi_channels_adjust_count) > 0) { | 3908 | if ((i = state->multi_channels_adjust_count) > 0) { |
3908 | if (i == 1) { | 3909 | if (i == 1) { |
3909 | if (copy_from_user(dmabuf->rawbuf + swptr, | 3910 | if (copy_from_user(dmabuf->rawbuf + swptr, |
3910 | buffer, sample_s)) | 3911 | buffer, sample_s)) |
3911 | return -EFAULT; | 3912 | return -EFAULT; |
3912 | seek_offset(swptr, buffer, cnt_for_multi_channel, | 3913 | seek_offset(swptr, buffer, cnt_for_multi_channel, |
3913 | sample_s, *copy_count); | 3914 | sample_s, *copy_count); |
3914 | i--; | 3915 | i--; |
3915 | (*state_cnt) += sample_s; | 3916 | (*state_cnt) += sample_s; |
3916 | state->multi_channels_adjust_count++; | 3917 | state->multi_channels_adjust_count++; |
3917 | } else | 3918 | } else |
3918 | i = i - (state->chans_num - other_dma_nums); | 3919 | i = i - (state->chans_num - other_dma_nums); |
3919 | for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) { | 3920 | for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) { |
3920 | dmabuf_temp = &state->other_states[i]->dmabuf; | 3921 | dmabuf_temp = &state->other_states[i]->dmabuf; |
3921 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | 3922 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, |
3922 | buffer, sample_s)) | 3923 | buffer, sample_s)) |
3923 | return -EFAULT; | 3924 | return -EFAULT; |
3924 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | 3925 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, |
3925 | sample_s, *copy_count); | 3926 | sample_s, *copy_count); |
3926 | } | 3927 | } |
3927 | if (cnt_for_multi_channel == 0) | 3928 | if (cnt_for_multi_channel == 0) |
3928 | state->multi_channels_adjust_count += i; | 3929 | state->multi_channels_adjust_count += i; |
3929 | } | 3930 | } |
3930 | if (cnt_for_multi_channel > 0) { | 3931 | if (cnt_for_multi_channel > 0) { |
3931 | loop = cnt_for_multi_channel / (state->chans_num * sample_s); | 3932 | loop = cnt_for_multi_channel / (state->chans_num * sample_s); |
3932 | for (i = 0; i < loop; i++) { | 3933 | for (i = 0; i < loop; i++) { |
3933 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, | 3934 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, |
3934 | sample_s * 2)) | 3935 | sample_s * 2)) |
3935 | return -EFAULT; | 3936 | return -EFAULT; |
3936 | seek_offset(swptr, buffer, cnt_for_multi_channel, | 3937 | seek_offset(swptr, buffer, cnt_for_multi_channel, |
3937 | sample_s * 2, *copy_count); | 3938 | sample_s * 2, *copy_count); |
3938 | (*state_cnt) += (sample_s * 2); | 3939 | (*state_cnt) += (sample_s * 2); |
3939 | 3940 | ||
3940 | dmabuf_temp = &state->other_states[0]->dmabuf; | 3941 | dmabuf_temp = &state->other_states[0]->dmabuf; |
3941 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | 3942 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, |
3942 | buffer, sample_s)) | 3943 | buffer, sample_s)) |
3943 | return -EFAULT; | 3944 | return -EFAULT; |
3944 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | 3945 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, |
3945 | sample_s, *copy_count); | 3946 | sample_s, *copy_count); |
3946 | 3947 | ||
3947 | dmabuf_temp = &state->other_states[1]->dmabuf; | 3948 | dmabuf_temp = &state->other_states[1]->dmabuf; |
3948 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | 3949 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, |
3949 | buffer, sample_s)) | 3950 | buffer, sample_s)) |
3950 | return -EFAULT; | 3951 | return -EFAULT; |
3951 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | 3952 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, |
3952 | sample_s, *copy_count); | 3953 | sample_s, *copy_count); |
3953 | 3954 | ||
3954 | dmabuf_temp = &state->other_states[2]->dmabuf; | 3955 | dmabuf_temp = &state->other_states[2]->dmabuf; |
3955 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | 3956 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, |
3956 | buffer, sample_s)) | 3957 | buffer, sample_s)) |
3957 | return -EFAULT; | 3958 | return -EFAULT; |
3958 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | 3959 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, |
3959 | sample_s, *copy_count); | 3960 | sample_s, *copy_count); |
3960 | 3961 | ||
3961 | dmabuf_temp = &state->other_states[3]->dmabuf; | 3962 | dmabuf_temp = &state->other_states[3]->dmabuf; |
3962 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | 3963 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, |
3963 | buffer, sample_s)) | 3964 | buffer, sample_s)) |
3964 | return -EFAULT; | 3965 | return -EFAULT; |
3965 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | 3966 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, |
3966 | sample_s, *copy_count); | 3967 | sample_s, *copy_count); |
3967 | } | 3968 | } |
3968 | 3969 | ||
3969 | if (cnt_for_multi_channel > 0) { | 3970 | if (cnt_for_multi_channel > 0) { |
3970 | state->multi_channels_adjust_count = cnt_for_multi_channel / sample_s; | 3971 | state->multi_channels_adjust_count = cnt_for_multi_channel / sample_s; |
3971 | 3972 | ||
3972 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) | 3973 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) |
3973 | return -EFAULT; | 3974 | return -EFAULT; |
3974 | seek_offset(swptr, buffer, cnt_for_multi_channel, | 3975 | seek_offset(swptr, buffer, cnt_for_multi_channel, |
3975 | sample_s, *copy_count); | 3976 | sample_s, *copy_count); |
3976 | (*state_cnt) += sample_s; | 3977 | (*state_cnt) += sample_s; |
3977 | 3978 | ||
3978 | if (cnt_for_multi_channel > 0) { | 3979 | if (cnt_for_multi_channel > 0) { |
3979 | if (copy_from_user(dmabuf->rawbuf + swptr, | 3980 | if (copy_from_user(dmabuf->rawbuf + swptr, |
3980 | buffer, sample_s)) | 3981 | buffer, sample_s)) |
3981 | return -EFAULT; | 3982 | return -EFAULT; |
3982 | seek_offset(swptr, buffer, cnt_for_multi_channel, | 3983 | seek_offset(swptr, buffer, cnt_for_multi_channel, |
3983 | sample_s, *copy_count); | 3984 | sample_s, *copy_count); |
3984 | (*state_cnt) += sample_s; | 3985 | (*state_cnt) += sample_s; |
3985 | 3986 | ||
3986 | if (cnt_for_multi_channel > 0) { | 3987 | if (cnt_for_multi_channel > 0) { |
3987 | int diff = state->chans_num - other_dma_nums; | 3988 | int diff = state->chans_num - other_dma_nums; |
3988 | loop = state->multi_channels_adjust_count - diff; | 3989 | loop = state->multi_channels_adjust_count - diff; |
3989 | for (i = 0; i < loop; i++) { | 3990 | for (i = 0; i < loop; i++) { |
3990 | dmabuf_temp = &state->other_states[i]->dmabuf; | 3991 | dmabuf_temp = &state->other_states[i]->dmabuf; |
3991 | if (copy_from_user(dmabuf_temp->rawbuf + | 3992 | if (copy_from_user(dmabuf_temp->rawbuf + |
3992 | dmabuf_temp->swptr, | 3993 | dmabuf_temp->swptr, |
3993 | buffer, sample_s)) | 3994 | buffer, sample_s)) |
3994 | return -EFAULT; | 3995 | return -EFAULT; |
3995 | seek_offset(dmabuf_temp->swptr, buffer, | 3996 | seek_offset(dmabuf_temp->swptr, buffer, |
3996 | cnt_for_multi_channel, | 3997 | cnt_for_multi_channel, |
3997 | sample_s, *copy_count); | 3998 | sample_s, *copy_count); |
3998 | } | 3999 | } |
3999 | } | 4000 | } |
4000 | } | 4001 | } |
4001 | } else | 4002 | } else |
4002 | state->multi_channels_adjust_count = 0; | 4003 | state->multi_channels_adjust_count = 0; |
4003 | } | 4004 | } |
4004 | for (i = 0; i < other_dma_nums; i++) { | 4005 | for (i = 0; i < other_dma_nums; i++) { |
4005 | dmabuf_temp = &state->other_states[i]->dmabuf; | 4006 | dmabuf_temp = &state->other_states[i]->dmabuf; |
4006 | dmabuf_temp->swptr = dmabuf_temp->swptr % dmabuf_temp->dmasize; | 4007 | dmabuf_temp->swptr = dmabuf_temp->swptr % dmabuf_temp->dmasize; |
4007 | } | 4008 | } |
4008 | return *state_cnt; | 4009 | return *state_cnt; |
4009 | } | 4010 | } |
4010 | 4011 | ||
4011 | static void | 4012 | static void |
4012 | ali_free_other_states_resources(struct trident_state *state) | 4013 | ali_free_other_states_resources(struct trident_state *state) |
4013 | { | 4014 | { |
4014 | int i; | 4015 | int i; |
4015 | struct trident_card *card = state->card; | 4016 | struct trident_card *card = state->card; |
4016 | struct trident_state *s; | 4017 | struct trident_state *s; |
4017 | unsigned other_states_count; | 4018 | unsigned other_states_count; |
4018 | 4019 | ||
4019 | other_states_count = state->chans_num - 2; /* except PCM L/R channels */ | 4020 | other_states_count = state->chans_num - 2; /* except PCM L/R channels */ |
4020 | for (i = 0; i < other_states_count; i++) { | 4021 | for (i = 0; i < other_states_count; i++) { |
4021 | s = state->other_states[i]; | 4022 | s = state->other_states[i]; |
4022 | dealloc_dmabuf(&s->dmabuf, card->pci_dev); | 4023 | dealloc_dmabuf(&s->dmabuf, card->pci_dev); |
4023 | ali_disable_special_channel(s->card, s->dmabuf.channel->num); | 4024 | ali_disable_special_channel(s->card, s->dmabuf.channel->num); |
4024 | state->card->free_pcm_channel(s->card, s->dmabuf.channel->num); | 4025 | state->card->free_pcm_channel(s->card, s->dmabuf.channel->num); |
4025 | card->states[s->virt] = NULL; | 4026 | card->states[s->virt] = NULL; |
4026 | kfree(s); | 4027 | kfree(s); |
4027 | } | 4028 | } |
4028 | } | 4029 | } |
4029 | 4030 | ||
4030 | static struct proc_dir_entry *res; | 4031 | static struct proc_dir_entry *res; |
4031 | 4032 | ||
4032 | static int | 4033 | static int |
4033 | ali_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) | 4034 | ali_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) |
4034 | { | 4035 | { |
4035 | struct trident_card *card = (struct trident_card *) data; | 4036 | struct trident_card *card = (struct trident_card *) data; |
4036 | unsigned long flags; | 4037 | unsigned long flags; |
4037 | char c; | 4038 | char c; |
4038 | 4039 | ||
4039 | if (count < 0) | 4040 | if (count < 0) |
4040 | return -EINVAL; | 4041 | return -EINVAL; |
4041 | if (count == 0) | 4042 | if (count == 0) |
4042 | return 0; | 4043 | return 0; |
4043 | if (get_user(c, buffer)) | 4044 | if (get_user(c, buffer)) |
4044 | return -EFAULT; | 4045 | return -EFAULT; |
4045 | 4046 | ||
4046 | spin_lock_irqsave(&card->lock, flags); | 4047 | spin_lock_irqsave(&card->lock, flags); |
4047 | switch (c) { | 4048 | switch (c) { |
4048 | case '0': | 4049 | case '0': |
4049 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); | 4050 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); |
4050 | ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); | 4051 | ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); |
4051 | break; | 4052 | break; |
4052 | case '1': | 4053 | case '1': |
4053 | ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | | 4054 | ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | |
4054 | ALI_SPDIF_OUT_PCM); | 4055 | ALI_SPDIF_OUT_PCM); |
4055 | break; | 4056 | break; |
4056 | case '2': | 4057 | case '2': |
4057 | ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | | 4058 | ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | |
4058 | ALI_SPDIF_OUT_NON_PCM); | 4059 | ALI_SPDIF_OUT_NON_PCM); |
4059 | break; | 4060 | break; |
4060 | case '3': | 4061 | case '3': |
4061 | ali_disable_spdif_in(card); //default | 4062 | ali_disable_spdif_in(card); //default |
4062 | break; | 4063 | break; |
4063 | case '4': | 4064 | case '4': |
4064 | ali_setup_spdif_in(card); | 4065 | ali_setup_spdif_in(card); |
4065 | break; | 4066 | break; |
4066 | } | 4067 | } |
4067 | spin_unlock_irqrestore(&card->lock, flags); | 4068 | spin_unlock_irqrestore(&card->lock, flags); |
4068 | 4069 | ||
4069 | return count; | 4070 | return count; |
4070 | } | 4071 | } |
4071 | 4072 | ||
4072 | /* OSS /dev/mixer file operation methods */ | 4073 | /* OSS /dev/mixer file operation methods */ |
4073 | static int | 4074 | static int |
4074 | trident_open_mixdev(struct inode *inode, struct file *file) | 4075 | trident_open_mixdev(struct inode *inode, struct file *file) |
4075 | { | 4076 | { |
4076 | int i = 0; | 4077 | int i = 0; |
4077 | int minor = iminor(inode); | 4078 | int minor = iminor(inode); |
4078 | struct trident_card *card = devs; | 4079 | struct trident_card *card = devs; |
4079 | 4080 | ||
4080 | for (card = devs; card != NULL; card = card->next) | 4081 | for (card = devs; card != NULL; card = card->next) |
4081 | for (i = 0; i < NR_AC97; i++) | 4082 | for (i = 0; i < NR_AC97; i++) |
4082 | if (card->ac97_codec[i] != NULL && | 4083 | if (card->ac97_codec[i] != NULL && |
4083 | card->ac97_codec[i]->dev_mixer == minor) | 4084 | card->ac97_codec[i]->dev_mixer == minor) |
4084 | goto match; | 4085 | goto match; |
4085 | 4086 | ||
4086 | if (!card) { | 4087 | if (!card) { |
4087 | return -ENODEV; | 4088 | return -ENODEV; |
4088 | } | 4089 | } |
4089 | match: | 4090 | match: |
4090 | file->private_data = card->ac97_codec[i]; | 4091 | file->private_data = card->ac97_codec[i]; |
4091 | 4092 | ||
4092 | return nonseekable_open(inode, file); | 4093 | return nonseekable_open(inode, file); |
4093 | } | 4094 | } |
4094 | 4095 | ||
4095 | static int | 4096 | static int |
4096 | trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, | 4097 | trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, |
4097 | unsigned long arg) | 4098 | unsigned long arg) |
4098 | { | 4099 | { |
4099 | struct ac97_codec *codec = (struct ac97_codec *) file->private_data; | 4100 | struct ac97_codec *codec = (struct ac97_codec *) file->private_data; |
4100 | 4101 | ||
4101 | return codec->mixer_ioctl(codec, cmd, arg); | 4102 | return codec->mixer_ioctl(codec, cmd, arg); |
4102 | } | 4103 | } |
4103 | 4104 | ||
4104 | static /*const */ struct file_operations trident_mixer_fops = { | 4105 | static /*const */ struct file_operations trident_mixer_fops = { |
4105 | .owner = THIS_MODULE, | 4106 | .owner = THIS_MODULE, |
4106 | .llseek = no_llseek, | 4107 | .llseek = no_llseek, |
4107 | .ioctl = trident_ioctl_mixdev, | 4108 | .ioctl = trident_ioctl_mixdev, |
4108 | .open = trident_open_mixdev, | 4109 | .open = trident_open_mixdev, |
4109 | }; | 4110 | }; |
4110 | 4111 | ||
4111 | static int | 4112 | static int |
4112 | ali_reset_5451(struct trident_card *card) | 4113 | ali_reset_5451(struct trident_card *card) |
4113 | { | 4114 | { |
4114 | struct pci_dev *pci_dev = NULL; | 4115 | struct pci_dev *pci_dev = NULL; |
4115 | unsigned int dwVal; | 4116 | unsigned int dwVal; |
4116 | unsigned short wCount, wReg; | 4117 | unsigned short wCount, wReg; |
4117 | 4118 | ||
4118 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | 4119 | pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, |
4119 | pci_dev); | 4120 | pci_dev); |
4120 | if (pci_dev == NULL) | 4121 | if (pci_dev == NULL) |
4121 | return -1; | 4122 | return -1; |
4122 | 4123 | ||
4123 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); | 4124 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); |
4124 | pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); | 4125 | pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); |
4125 | udelay(5000); | 4126 | udelay(5000); |
4126 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); | 4127 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); |
4127 | pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff); | 4128 | pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff); |
4128 | udelay(5000); | 4129 | udelay(5000); |
4129 | pci_dev_put(pci_dev); | 4130 | pci_dev_put(pci_dev); |
4130 | 4131 | ||
4131 | pci_dev = card->pci_dev; | 4132 | pci_dev = card->pci_dev; |
4132 | if (pci_dev == NULL) | 4133 | if (pci_dev == NULL) |
4133 | return -1; | 4134 | return -1; |
4134 | 4135 | ||
4135 | pci_read_config_dword(pci_dev, 0x44, &dwVal); | 4136 | pci_read_config_dword(pci_dev, 0x44, &dwVal); |
4136 | pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000); | 4137 | pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000); |
4137 | udelay(500); | 4138 | udelay(500); |
4138 | pci_read_config_dword(pci_dev, 0x44, &dwVal); | 4139 | pci_read_config_dword(pci_dev, 0x44, &dwVal); |
4139 | pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff); | 4140 | pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff); |
4140 | udelay(5000); | 4141 | udelay(5000); |
4141 | 4142 | ||
4142 | /* TODO: recognize if we have a PM capable codec and only do this */ | 4143 | /* TODO: recognize if we have a PM capable codec and only do this */ |
4143 | /* if the codec is PM capable */ | 4144 | /* if the codec is PM capable */ |
4144 | wCount = 2000; | 4145 | wCount = 2000; |
4145 | while (wCount--) { | 4146 | while (wCount--) { |
4146 | wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL); | 4147 | wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL); |
4147 | if ((wReg & 0x000f) == 0x000f) | 4148 | if ((wReg & 0x000f) == 0x000f) |
4148 | return 0; | 4149 | return 0; |
4149 | udelay(5000); | 4150 | udelay(5000); |
4150 | } | 4151 | } |
4151 | /* This is non fatal if you have a non PM capable codec.. */ | 4152 | /* This is non fatal if you have a non PM capable codec.. */ |
4152 | return 0; | 4153 | return 0; |
4153 | } | 4154 | } |
4154 | 4155 | ||
4155 | /* AC97 codec initialisation. */ | 4156 | /* AC97 codec initialisation. */ |
4156 | static int __devinit | 4157 | static int __devinit |
4157 | trident_ac97_init(struct trident_card *card) | 4158 | trident_ac97_init(struct trident_card *card) |
4158 | { | 4159 | { |
4159 | int num_ac97 = 0; | 4160 | int num_ac97 = 0; |
4160 | unsigned long ready_2nd = 0; | 4161 | unsigned long ready_2nd = 0; |
4161 | struct ac97_codec *codec; | 4162 | struct ac97_codec *codec; |
4162 | int i = 0; | 4163 | int i = 0; |
4163 | 4164 | ||
4164 | /* initialize controller side of AC link, and find out if secondary codes | 4165 | /* initialize controller side of AC link, and find out if secondary codes |
4165 | really exist */ | 4166 | really exist */ |
4166 | switch (card->pci_id) { | 4167 | switch (card->pci_id) { |
4167 | case PCI_DEVICE_ID_ALI_5451: | 4168 | case PCI_DEVICE_ID_ALI_5451: |
4168 | if (ali_reset_5451(card)) { | 4169 | if (ali_reset_5451(card)) { |
4169 | printk(KERN_ERR "trident_ac97_init: error " | 4170 | printk(KERN_ERR "trident_ac97_init: error " |
4170 | "resetting 5451.\n"); | 4171 | "resetting 5451.\n"); |
4171 | return -1; | 4172 | return -1; |
4172 | } | 4173 | } |
4173 | outl(0x80000001, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 4174 | outl(0x80000001, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
4174 | outl(0x00000000, TRID_REG(card, T4D_AINTEN_A)); | 4175 | outl(0x00000000, TRID_REG(card, T4D_AINTEN_A)); |
4175 | outl(0xffffffff, TRID_REG(card, T4D_AINT_A)); | 4176 | outl(0xffffffff, TRID_REG(card, T4D_AINT_A)); |
4176 | outl(0x00000000, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); | 4177 | outl(0x00000000, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); |
4177 | outb(0x10, TRID_REG(card, ALI_MPUR2)); | 4178 | outb(0x10, TRID_REG(card, ALI_MPUR2)); |
4178 | ready_2nd = inl(TRID_REG(card, ALI_SCTRL)); | 4179 | ready_2nd = inl(TRID_REG(card, ALI_SCTRL)); |
4179 | ready_2nd &= 0x3fff; | 4180 | ready_2nd &= 0x3fff; |
4180 | outl(ready_2nd | PCMOUT | 0x8000, TRID_REG(card, ALI_SCTRL)); | 4181 | outl(ready_2nd | PCMOUT | 0x8000, TRID_REG(card, ALI_SCTRL)); |
4181 | ready_2nd = inl(TRID_REG(card, ALI_SCTRL)); | 4182 | ready_2nd = inl(TRID_REG(card, ALI_SCTRL)); |
4182 | ready_2nd &= SI_AC97_SECONDARY_READY; | 4183 | ready_2nd &= SI_AC97_SECONDARY_READY; |
4183 | if (card->revision < ALI_5451_V02) | 4184 | if (card->revision < ALI_5451_V02) |
4184 | ready_2nd = 0; | 4185 | ready_2nd = 0; |
4185 | break; | 4186 | break; |
4186 | case PCI_DEVICE_ID_SI_7018: | 4187 | case PCI_DEVICE_ID_SI_7018: |
4187 | /* disable AC97 GPIO interrupt */ | 4188 | /* disable AC97 GPIO interrupt */ |
4188 | outl(0x00, TRID_REG(card, SI_AC97_GPIO)); | 4189 | outl(0x00, TRID_REG(card, SI_AC97_GPIO)); |
4189 | /* when power up the AC link is in cold reset mode so stop it */ | 4190 | /* when power up the AC link is in cold reset mode so stop it */ |
4190 | outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID, | 4191 | outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID, |
4191 | TRID_REG(card, SI_SERIAL_INTF_CTRL)); | 4192 | TRID_REG(card, SI_SERIAL_INTF_CTRL)); |
4192 | /* it take a long time to recover from a cold reset */ | 4193 | /* it take a long time to recover from a cold reset */ |
4193 | /* (especially when you have more than one codec) */ | 4194 | /* (especially when you have more than one codec) */ |
4194 | udelay(2000); | 4195 | udelay(2000); |
4195 | ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL)); | 4196 | ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL)); |
4196 | ready_2nd &= SI_AC97_SECONDARY_READY; | 4197 | ready_2nd &= SI_AC97_SECONDARY_READY; |
4197 | break; | 4198 | break; |
4198 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | 4199 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: |
4199 | /* playback on */ | 4200 | /* playback on */ |
4200 | outl(DX_AC97_PLAYBACK, TRID_REG(card, DX_ACR2_AC97_COM_STAT)); | 4201 | outl(DX_AC97_PLAYBACK, TRID_REG(card, DX_ACR2_AC97_COM_STAT)); |
4201 | break; | 4202 | break; |
4202 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | 4203 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: |
4203 | /* enable AC97 Output Slot 3,4 (PCM Left/Right Playback) */ | 4204 | /* enable AC97 Output Slot 3,4 (PCM Left/Right Playback) */ |
4204 | outl(NX_AC97_PCM_OUTPUT, TRID_REG(card, NX_ACR0_AC97_COM_STAT)); | 4205 | outl(NX_AC97_PCM_OUTPUT, TRID_REG(card, NX_ACR0_AC97_COM_STAT)); |
4205 | ready_2nd = inl(TRID_REG(card, NX_ACR0_AC97_COM_STAT)); | 4206 | ready_2nd = inl(TRID_REG(card, NX_ACR0_AC97_COM_STAT)); |
4206 | ready_2nd &= NX_AC97_SECONDARY_READY; | 4207 | ready_2nd &= NX_AC97_SECONDARY_READY; |
4207 | break; | 4208 | break; |
4208 | case PCI_DEVICE_ID_INTERG_5050: | 4209 | case PCI_DEVICE_ID_INTERG_5050: |
4209 | /* disable AC97 GPIO interrupt */ | 4210 | /* disable AC97 GPIO interrupt */ |
4210 | outl(0x00, TRID_REG(card, SI_AC97_GPIO)); | 4211 | outl(0x00, TRID_REG(card, SI_AC97_GPIO)); |
4211 | /* when power up, the AC link is in cold reset mode, so stop it */ | 4212 | /* when power up, the AC link is in cold reset mode, so stop it */ |
4212 | outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT, | 4213 | outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT, |
4213 | TRID_REG(card, SI_SERIAL_INTF_CTRL)); | 4214 | TRID_REG(card, SI_SERIAL_INTF_CTRL)); |
4214 | /* it take a long time to recover from a cold reset (especially */ | 4215 | /* it take a long time to recover from a cold reset (especially */ |
4215 | /* when you have more than one codec) */ | 4216 | /* when you have more than one codec) */ |
4216 | udelay(2000); | 4217 | udelay(2000); |
4217 | ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL)); | 4218 | ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL)); |
4218 | ready_2nd &= SI_AC97_SECONDARY_READY; | 4219 | ready_2nd &= SI_AC97_SECONDARY_READY; |
4219 | break; | 4220 | break; |
4220 | } | 4221 | } |
4221 | 4222 | ||
4222 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { | 4223 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { |
4223 | if ((codec = ac97_alloc_codec()) == NULL) | 4224 | if ((codec = ac97_alloc_codec()) == NULL) |
4224 | return -ENOMEM; | 4225 | return -ENOMEM; |
4225 | 4226 | ||
4226 | /* initialize some basic codec information, other fields */ | 4227 | /* initialize some basic codec information, other fields */ |
4227 | /* will be filled in ac97_probe_codec */ | 4228 | /* will be filled in ac97_probe_codec */ |
4228 | codec->private_data = card; | 4229 | codec->private_data = card; |
4229 | codec->id = num_ac97; | 4230 | codec->id = num_ac97; |
4230 | 4231 | ||
4231 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 4232 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
4232 | codec->codec_read = ali_ac97_read; | 4233 | codec->codec_read = ali_ac97_read; |
4233 | codec->codec_write = ali_ac97_write; | 4234 | codec->codec_write = ali_ac97_write; |
4234 | } else { | 4235 | } else { |
4235 | codec->codec_read = trident_ac97_get; | 4236 | codec->codec_read = trident_ac97_get; |
4236 | codec->codec_write = trident_ac97_set; | 4237 | codec->codec_write = trident_ac97_set; |
4237 | } | 4238 | } |
4238 | 4239 | ||
4239 | if (ac97_probe_codec(codec) == 0) | 4240 | if (ac97_probe_codec(codec) == 0) |
4240 | break; | 4241 | break; |
4241 | 4242 | ||
4242 | codec->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1); | 4243 | codec->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1); |
4243 | if (codec->dev_mixer < 0) { | 4244 | if (codec->dev_mixer < 0) { |
4244 | printk(KERN_ERR "trident: couldn't register mixer!\n"); | 4245 | printk(KERN_ERR "trident: couldn't register mixer!\n"); |
4245 | ac97_release_codec(codec); | 4246 | ac97_release_codec(codec); |
4246 | break; | 4247 | break; |
4247 | } | 4248 | } |
4248 | 4249 | ||
4249 | card->ac97_codec[num_ac97] = codec; | 4250 | card->ac97_codec[num_ac97] = codec; |
4250 | 4251 | ||
4251 | /* if there is no secondary codec at all, don't probe any more */ | 4252 | /* if there is no secondary codec at all, don't probe any more */ |
4252 | if (!ready_2nd) | 4253 | if (!ready_2nd) |
4253 | break; | 4254 | break; |
4254 | } | 4255 | } |
4255 | 4256 | ||
4256 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 4257 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
4257 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { | 4258 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { |
4258 | if (card->ac97_codec[num_ac97] == NULL) | 4259 | if (card->ac97_codec[num_ac97] == NULL) |
4259 | break; | 4260 | break; |
4260 | for (i = 0; i < 64; i++) { | 4261 | for (i = 0; i < 64; i++) { |
4261 | u16 reg = ali_ac97_get(card, num_ac97, i * 2); | 4262 | u16 reg = ali_ac97_get(card, num_ac97, i * 2); |
4262 | card->mixer_regs[i][num_ac97] = reg; | 4263 | card->mixer_regs[i][num_ac97] = reg; |
4263 | } | 4264 | } |
4264 | } | 4265 | } |
4265 | } | 4266 | } |
4266 | return num_ac97 + 1; | 4267 | return num_ac97 + 1; |
4267 | } | 4268 | } |
4268 | 4269 | ||
4269 | #ifdef SUPPORT_JOYSTICK | 4270 | #ifdef SUPPORT_JOYSTICK |
4270 | /* Gameport functions for the cards ADC gameport */ | 4271 | /* Gameport functions for the cards ADC gameport */ |
4271 | 4272 | ||
4272 | static unsigned char trident_game_read(struct gameport *gameport) | 4273 | static unsigned char trident_game_read(struct gameport *gameport) |
4273 | { | 4274 | { |
4274 | struct trident_card *card = gameport->port_data; | 4275 | struct trident_card *card = gameport->port_data; |
4275 | 4276 | ||
4276 | return inb(TRID_REG(card, T4D_GAME_LEG)); | 4277 | return inb(TRID_REG(card, T4D_GAME_LEG)); |
4277 | } | 4278 | } |
4278 | 4279 | ||
4279 | static void trident_game_trigger(struct gameport *gameport) | 4280 | static void trident_game_trigger(struct gameport *gameport) |
4280 | { | 4281 | { |
4281 | struct trident_card *card = gameport->port_data; | 4282 | struct trident_card *card = gameport->port_data; |
4282 | 4283 | ||
4283 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); | 4284 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); |
4284 | } | 4285 | } |
4285 | 4286 | ||
4286 | static int trident_game_cooked_read(struct gameport *gameport, | 4287 | static int trident_game_cooked_read(struct gameport *gameport, |
4287 | int *axes, int *buttons) | 4288 | int *axes, int *buttons) |
4288 | { | 4289 | { |
4289 | struct trident_card *card = gameport->port_data; | 4290 | struct trident_card *card = gameport->port_data; |
4290 | int i; | 4291 | int i; |
4291 | 4292 | ||
4292 | *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf; | 4293 | *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf; |
4293 | 4294 | ||
4294 | for (i = 0; i < 4; i++) { | 4295 | for (i = 0; i < 4; i++) { |
4295 | axes[i] = inw(TRID_REG(card, T4D_GAME_AXD) + i * sizeof (u16)); | 4296 | axes[i] = inw(TRID_REG(card, T4D_GAME_AXD) + i * sizeof (u16)); |
4296 | if (axes[i] == 0xffff) | 4297 | if (axes[i] == 0xffff) |
4297 | axes[i] = -1; | 4298 | axes[i] = -1; |
4298 | } | 4299 | } |
4299 | 4300 | ||
4300 | return 0; | 4301 | return 0; |
4301 | } | 4302 | } |
4302 | 4303 | ||
4303 | static int trident_game_open(struct gameport *gameport, int mode) | 4304 | static int trident_game_open(struct gameport *gameport, int mode) |
4304 | { | 4305 | { |
4305 | struct trident_card *card = gameport->port_data; | 4306 | struct trident_card *card = gameport->port_data; |
4306 | 4307 | ||
4307 | switch (mode) { | 4308 | switch (mode) { |
4308 | case GAMEPORT_MODE_COOKED: | 4309 | case GAMEPORT_MODE_COOKED: |
4309 | outb(0x80, TRID_REG(card, T4D_GAME_CR)); | 4310 | outb(0x80, TRID_REG(card, T4D_GAME_CR)); |
4310 | msleep(20); | 4311 | msleep(20); |
4311 | return 0; | 4312 | return 0; |
4312 | case GAMEPORT_MODE_RAW: | 4313 | case GAMEPORT_MODE_RAW: |
4313 | outb(0x00, TRID_REG(card, T4D_GAME_CR)); | 4314 | outb(0x00, TRID_REG(card, T4D_GAME_CR)); |
4314 | return 0; | 4315 | return 0; |
4315 | default: | 4316 | default: |
4316 | return -1; | 4317 | return -1; |
4317 | } | 4318 | } |
4318 | 4319 | ||
4319 | return 0; | 4320 | return 0; |
4320 | } | 4321 | } |
4321 | 4322 | ||
4322 | static int __devinit trident_register_gameport(struct trident_card *card) | 4323 | static int __devinit trident_register_gameport(struct trident_card *card) |
4323 | { | 4324 | { |
4324 | struct gameport *gp; | 4325 | struct gameport *gp; |
4325 | 4326 | ||
4326 | card->gameport = gp = gameport_allocate_port(); | 4327 | card->gameport = gp = gameport_allocate_port(); |
4327 | if (!gp) { | 4328 | if (!gp) { |
4328 | printk(KERN_ERR "trident: can not allocate memory for gameport\n"); | 4329 | printk(KERN_ERR "trident: can not allocate memory for gameport\n"); |
4329 | return -ENOMEM; | 4330 | return -ENOMEM; |
4330 | } | 4331 | } |
4331 | 4332 | ||
4332 | gameport_set_name(gp, "Trident 4DWave"); | 4333 | gameport_set_name(gp, "Trident 4DWave"); |
4333 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev)); | 4334 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev)); |
4334 | gp->read = trident_game_read; | 4335 | gp->read = trident_game_read; |
4335 | gp->trigger = trident_game_trigger; | 4336 | gp->trigger = trident_game_trigger; |
4336 | gp->cooked_read = trident_game_cooked_read; | 4337 | gp->cooked_read = trident_game_cooked_read; |
4337 | gp->open = trident_game_open; | 4338 | gp->open = trident_game_open; |
4338 | gp->fuzz = 64; | 4339 | gp->fuzz = 64; |
4339 | gp->port_data = card; | 4340 | gp->port_data = card; |
4340 | 4341 | ||
4341 | gameport_register_port(gp); | 4342 | gameport_register_port(gp); |
4342 | 4343 | ||
4343 | return 0; | 4344 | return 0; |
4344 | } | 4345 | } |
4345 | 4346 | ||
4346 | static inline void trident_unregister_gameport(struct trident_card *card) | 4347 | static inline void trident_unregister_gameport(struct trident_card *card) |
4347 | { | 4348 | { |
4348 | if (card->gameport) | 4349 | if (card->gameport) |
4349 | gameport_unregister_port(card->gameport); | 4350 | gameport_unregister_port(card->gameport); |
4350 | } | 4351 | } |
4351 | 4352 | ||
4352 | #else | 4353 | #else |
4353 | static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; } | 4354 | static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; } |
4354 | static inline void trident_unregister_gameport(struct trident_card *card) { } | 4355 | static inline void trident_unregister_gameport(struct trident_card *card) { } |
4355 | #endif /* SUPPORT_JOYSTICK */ | 4356 | #endif /* SUPPORT_JOYSTICK */ |
4356 | 4357 | ||
4357 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ | 4358 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ |
4358 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ | 4359 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ |
4359 | /* open/read/write/ioctl/mmap) */ | 4360 | /* open/read/write/ioctl/mmap) */ |
4360 | static int __devinit | 4361 | static int __devinit |
4361 | trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) | 4362 | trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) |
4362 | { | 4363 | { |
4363 | unsigned long iobase; | 4364 | unsigned long iobase; |
4364 | struct trident_card *card; | 4365 | struct trident_card *card; |
4365 | u8 bits; | 4366 | u8 bits; |
4366 | u8 revision; | 4367 | u8 revision; |
4367 | int i = 0; | 4368 | int i = 0; |
4368 | u16 temp; | 4369 | u16 temp; |
4369 | struct pci_dev *pci_dev_m1533 = NULL; | 4370 | struct pci_dev *pci_dev_m1533 = NULL; |
4370 | int rc = -ENODEV; | 4371 | int rc = -ENODEV; |
4371 | u64 dma_mask; | 4372 | u64 dma_mask; |
4372 | 4373 | ||
4373 | if (pci_enable_device(pci_dev)) | 4374 | if (pci_enable_device(pci_dev)) |
4374 | goto out; | 4375 | goto out; |
4375 | 4376 | ||
4376 | if (pci_dev->device == PCI_DEVICE_ID_ALI_5451) | 4377 | if (pci_dev->device == PCI_DEVICE_ID_ALI_5451) |
4377 | dma_mask = ALI_DMA_MASK; | 4378 | dma_mask = ALI_DMA_MASK; |
4378 | else | 4379 | else |
4379 | dma_mask = TRIDENT_DMA_MASK; | 4380 | dma_mask = TRIDENT_DMA_MASK; |
4380 | if (pci_set_dma_mask(pci_dev, dma_mask)) { | 4381 | if (pci_set_dma_mask(pci_dev, dma_mask)) { |
4381 | printk(KERN_ERR "trident: architecture does not support" | 4382 | printk(KERN_ERR "trident: architecture does not support" |
4382 | " %s PCI busmaster DMA\n", | 4383 | " %s PCI busmaster DMA\n", |
4383 | pci_dev->device == PCI_DEVICE_ID_ALI_5451 ? | 4384 | pci_dev->device == PCI_DEVICE_ID_ALI_5451 ? |
4384 | "32-bit" : "30-bit"); | 4385 | "32-bit" : "30-bit"); |
4385 | goto out; | 4386 | goto out; |
4386 | } | 4387 | } |
4387 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); | 4388 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); |
4388 | 4389 | ||
4389 | if (pci_id->device == PCI_DEVICE_ID_INTERG_5050) | 4390 | if (pci_id->device == PCI_DEVICE_ID_INTERG_5050) |
4390 | iobase = pci_resource_start(pci_dev, 1); | 4391 | iobase = pci_resource_start(pci_dev, 1); |
4391 | else | 4392 | else |
4392 | iobase = pci_resource_start(pci_dev, 0); | 4393 | iobase = pci_resource_start(pci_dev, 0); |
4393 | 4394 | ||
4394 | if (!request_region(iobase, 256, card_names[pci_id->driver_data])) { | 4395 | if (!request_region(iobase, 256, card_names[pci_id->driver_data])) { |
4395 | printk(KERN_ERR "trident: can't allocate I/O space at " | 4396 | printk(KERN_ERR "trident: can't allocate I/O space at " |
4396 | "0x%4.4lx\n", iobase); | 4397 | "0x%4.4lx\n", iobase); |
4397 | goto out; | 4398 | goto out; |
4398 | } | 4399 | } |
4399 | 4400 | ||
4400 | rc = -ENOMEM; | 4401 | rc = -ENOMEM; |
4401 | if ((card = kmalloc(sizeof(*card), GFP_KERNEL)) == NULL) { | 4402 | if ((card = kmalloc(sizeof(*card), GFP_KERNEL)) == NULL) { |
4402 | printk(KERN_ERR "trident: out of memory\n"); | 4403 | printk(KERN_ERR "trident: out of memory\n"); |
4403 | goto out_release_region; | 4404 | goto out_release_region; |
4404 | } | 4405 | } |
4405 | memset(card, 0, sizeof (*card)); | 4406 | memset(card, 0, sizeof (*card)); |
4406 | 4407 | ||
4407 | init_timer(&card->timer); | 4408 | init_timer(&card->timer); |
4408 | card->iobase = iobase; | 4409 | card->iobase = iobase; |
4409 | card->pci_dev = pci_dev_get(pci_dev); | 4410 | card->pci_dev = pci_dev_get(pci_dev); |
4410 | card->pci_id = pci_id->device; | 4411 | card->pci_id = pci_id->device; |
4411 | card->revision = revision; | 4412 | card->revision = revision; |
4412 | card->irq = pci_dev->irq; | 4413 | card->irq = pci_dev->irq; |
4413 | card->next = devs; | 4414 | card->next = devs; |
4414 | card->magic = TRIDENT_CARD_MAGIC; | 4415 | card->magic = TRIDENT_CARD_MAGIC; |
4415 | card->banks[BANK_A].addresses = &bank_a_addrs; | 4416 | card->banks[BANK_A].addresses = &bank_a_addrs; |
4416 | card->banks[BANK_A].bitmap = 0UL; | 4417 | card->banks[BANK_A].bitmap = 0UL; |
4417 | card->banks[BANK_B].addresses = &bank_b_addrs; | 4418 | card->banks[BANK_B].addresses = &bank_b_addrs; |
4418 | card->banks[BANK_B].bitmap = 0UL; | 4419 | card->banks[BANK_B].bitmap = 0UL; |
4419 | 4420 | ||
4420 | mutex_init(&card->open_mutex); | 4421 | mutex_init(&card->open_mutex); |
4421 | spin_lock_init(&card->lock); | 4422 | spin_lock_init(&card->lock); |
4422 | init_timer(&card->timer); | 4423 | init_timer(&card->timer); |
4423 | 4424 | ||
4424 | devs = card; | 4425 | devs = card; |
4425 | 4426 | ||
4426 | pci_set_master(pci_dev); | 4427 | pci_set_master(pci_dev); |
4427 | 4428 | ||
4428 | printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", | 4429 | printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", |
4429 | card_names[pci_id->driver_data], card->iobase, card->irq); | 4430 | card_names[pci_id->driver_data], card->iobase, card->irq); |
4430 | 4431 | ||
4431 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 4432 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
4432 | /* ALi channel Management */ | 4433 | /* ALi channel Management */ |
4433 | card->alloc_pcm_channel = ali_alloc_pcm_channel; | 4434 | card->alloc_pcm_channel = ali_alloc_pcm_channel; |
4434 | card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel; | 4435 | card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel; |
4435 | card->free_pcm_channel = ali_free_pcm_channel; | 4436 | card->free_pcm_channel = ali_free_pcm_channel; |
4436 | 4437 | ||
4437 | card->address_interrupt = ali_address_interrupt; | 4438 | card->address_interrupt = ali_address_interrupt; |
4438 | 4439 | ||
4439 | /* Added by Matt Wu 01-05-2001 for spdif in */ | 4440 | /* Added by Matt Wu 01-05-2001 for spdif in */ |
4440 | card->multi_channel_use_count = 0; | 4441 | card->multi_channel_use_count = 0; |
4441 | card->rec_channel_use_count = 0; | 4442 | card->rec_channel_use_count = 0; |
4442 | 4443 | ||
4443 | /* ALi SPDIF OUT function */ | 4444 | /* ALi SPDIF OUT function */ |
4444 | if (card->revision == ALI_5451_V02) { | 4445 | if (card->revision == ALI_5451_V02) { |
4445 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); | 4446 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); |
4446 | res = create_proc_entry("ALi5451", 0, NULL); | 4447 | res = create_proc_entry("ALi5451", 0, NULL); |
4447 | if (res) { | 4448 | if (res) { |
4448 | res->write_proc = ali_write_proc; | 4449 | res->write_proc = ali_write_proc; |
4449 | res->data = card; | 4450 | res->data = card; |
4450 | } | 4451 | } |
4451 | } | 4452 | } |
4452 | 4453 | ||
4453 | /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ | 4454 | /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ |
4454 | card->hwvolctl = 0; | 4455 | card->hwvolctl = 0; |
4455 | pci_dev_m1533 = pci_find_device(PCI_VENDOR_ID_AL, | 4456 | pci_dev_m1533 = pci_find_device(PCI_VENDOR_ID_AL, |
4456 | PCI_DEVICE_ID_AL_M1533, | 4457 | PCI_DEVICE_ID_AL_M1533, |
4457 | pci_dev_m1533); | 4458 | pci_dev_m1533); |
4458 | rc = -ENODEV; | 4459 | rc = -ENODEV; |
4459 | if (pci_dev_m1533 == NULL) | 4460 | if (pci_dev_m1533 == NULL) |
4460 | goto out_proc_fs; | 4461 | goto out_proc_fs; |
4461 | pci_read_config_byte(pci_dev_m1533, 0x63, &bits); | 4462 | pci_read_config_byte(pci_dev_m1533, 0x63, &bits); |
4462 | if (bits & (1 << 5)) | 4463 | if (bits & (1 << 5)) |
4463 | card->hwvolctl = 1; | 4464 | card->hwvolctl = 1; |
4464 | if (card->hwvolctl) { | 4465 | if (card->hwvolctl) { |
4465 | /* Clear m1533 pci cfg 78h bit 30 to zero, which makes | 4466 | /* Clear m1533 pci cfg 78h bit 30 to zero, which makes |
4466 | GPIO11/12/13 work as ACGP_UP/DOWN/MUTE. */ | 4467 | GPIO11/12/13 work as ACGP_UP/DOWN/MUTE. */ |
4467 | pci_read_config_byte(pci_dev_m1533, 0x7b, &bits); | 4468 | pci_read_config_byte(pci_dev_m1533, 0x7b, &bits); |
4468 | bits &= 0xbf; /*clear bit 6 */ | 4469 | bits &= 0xbf; /*clear bit 6 */ |
4469 | pci_write_config_byte(pci_dev_m1533, 0x7b, bits); | 4470 | pci_write_config_byte(pci_dev_m1533, 0x7b, bits); |
4470 | } | 4471 | } |
4471 | } else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) { | 4472 | } else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) { |
4472 | card->alloc_pcm_channel = cyber_alloc_pcm_channel; | 4473 | card->alloc_pcm_channel = cyber_alloc_pcm_channel; |
4473 | card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel; | 4474 | card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel; |
4474 | card->free_pcm_channel = cyber_free_pcm_channel; | 4475 | card->free_pcm_channel = cyber_free_pcm_channel; |
4475 | card->address_interrupt = cyber_address_interrupt; | 4476 | card->address_interrupt = cyber_address_interrupt; |
4476 | cyber_init_ritual(card); | 4477 | cyber_init_ritual(card); |
4477 | } else { | 4478 | } else { |
4478 | card->alloc_pcm_channel = trident_alloc_pcm_channel; | 4479 | card->alloc_pcm_channel = trident_alloc_pcm_channel; |
4479 | card->alloc_rec_pcm_channel = trident_alloc_pcm_channel; | 4480 | card->alloc_rec_pcm_channel = trident_alloc_pcm_channel; |
4480 | card->free_pcm_channel = trident_free_pcm_channel; | 4481 | card->free_pcm_channel = trident_free_pcm_channel; |
4481 | card->address_interrupt = trident_address_interrupt; | 4482 | card->address_interrupt = trident_address_interrupt; |
4482 | } | 4483 | } |
4483 | 4484 | ||
4484 | /* claim our irq */ | 4485 | /* claim our irq */ |
4485 | rc = -ENODEV; | 4486 | rc = -ENODEV; |
4486 | if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED, | 4487 | if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED, |
4487 | card_names[pci_id->driver_data], card)) { | 4488 | card_names[pci_id->driver_data], card)) { |
4488 | printk(KERN_ERR "trident: unable to allocate irq %d\n", | 4489 | printk(KERN_ERR "trident: unable to allocate irq %d\n", |
4489 | card->irq); | 4490 | card->irq); |
4490 | goto out_proc_fs; | 4491 | goto out_proc_fs; |
4491 | } | 4492 | } |
4492 | /* register /dev/dsp */ | 4493 | /* register /dev/dsp */ |
4493 | if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) { | 4494 | if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) { |
4494 | printk(KERN_ERR "trident: couldn't register DSP device!\n"); | 4495 | printk(KERN_ERR "trident: couldn't register DSP device!\n"); |
4495 | goto out_free_irq; | 4496 | goto out_free_irq; |
4496 | } | 4497 | } |
4497 | card->mixer_regs_ready = 0; | 4498 | card->mixer_regs_ready = 0; |
4498 | /* initialize AC97 codec and register /dev/mixer */ | 4499 | /* initialize AC97 codec and register /dev/mixer */ |
4499 | if (trident_ac97_init(card) <= 0) { | 4500 | if (trident_ac97_init(card) <= 0) { |
4500 | /* unregister audio devices */ | 4501 | /* unregister audio devices */ |
4501 | for (i = 0; i < NR_AC97; i++) { | 4502 | for (i = 0; i < NR_AC97; i++) { |
4502 | if (card->ac97_codec[i] != NULL) { | 4503 | if (card->ac97_codec[i] != NULL) { |
4503 | struct ac97_codec* codec = card->ac97_codec[i]; | 4504 | struct ac97_codec* codec = card->ac97_codec[i]; |
4504 | unregister_sound_mixer(codec->dev_mixer); | 4505 | unregister_sound_mixer(codec->dev_mixer); |
4505 | ac97_release_codec(codec); | 4506 | ac97_release_codec(codec); |
4506 | } | 4507 | } |
4507 | } | 4508 | } |
4508 | goto out_unregister_sound_dsp; | 4509 | goto out_unregister_sound_dsp; |
4509 | } | 4510 | } |
4510 | card->mixer_regs_ready = 1; | 4511 | card->mixer_regs_ready = 1; |
4511 | outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); | 4512 | outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); |
4512 | 4513 | ||
4513 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 4514 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
4514 | /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ | 4515 | /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ |
4515 | if (card->hwvolctl) { | 4516 | if (card->hwvolctl) { |
4516 | /* Enable GPIO IRQ (MISCINT bit 18h) */ | 4517 | /* Enable GPIO IRQ (MISCINT bit 18h) */ |
4517 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); | 4518 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); |
4518 | temp |= 0x0004; | 4519 | temp |= 0x0004; |
4519 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); | 4520 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); |
4520 | 4521 | ||
4521 | /* Enable H/W Volume Control GLOVAL CONTROL bit 0 */ | 4522 | /* Enable H/W Volume Control GLOVAL CONTROL bit 0 */ |
4522 | temp = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); | 4523 | temp = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); |
4523 | temp |= 0x0001; | 4524 | temp |= 0x0001; |
4524 | outw(temp, TRID_REG(card, ALI_GLOBAL_CONTROL)); | 4525 | outw(temp, TRID_REG(card, ALI_GLOBAL_CONTROL)); |
4525 | 4526 | ||
4526 | } | 4527 | } |
4527 | if (card->revision == ALI_5451_V02) | 4528 | if (card->revision == ALI_5451_V02) |
4528 | ali_close_multi_channels(); | 4529 | ali_close_multi_channels(); |
4529 | /* edited by HMSEO for GT sound */ | 4530 | /* edited by HMSEO for GT sound */ |
4530 | #if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC) | 4531 | #if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC) |
4531 | { | 4532 | { |
4532 | u16 ac97_data; | 4533 | u16 ac97_data; |
4533 | extern struct hwrpb_struct *hwrpb; | 4534 | extern struct hwrpb_struct *hwrpb; |
4534 | 4535 | ||
4535 | if ((hwrpb->sys_type) == 201) { | 4536 | if ((hwrpb->sys_type) == 201) { |
4536 | printk(KERN_INFO "trident: Running on Alpha system " | 4537 | printk(KERN_INFO "trident: Running on Alpha system " |
4537 | "type Nautilus\n"); | 4538 | "type Nautilus\n"); |
4538 | ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL); | 4539 | ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL); |
4539 | ali_ac97_set(card, 0, AC97_POWER_CONTROL, | 4540 | ali_ac97_set(card, 0, AC97_POWER_CONTROL, |
4540 | ac97_data | ALI_EAPD_POWER_DOWN); | 4541 | ac97_data | ALI_EAPD_POWER_DOWN); |
4541 | } | 4542 | } |
4542 | } | 4543 | } |
4543 | #endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */ | 4544 | #endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */ |
4544 | /* edited by HMSEO for GT sound */ | 4545 | /* edited by HMSEO for GT sound */ |
4545 | } | 4546 | } |
4546 | rc = 0; | 4547 | rc = 0; |
4547 | pci_set_drvdata(pci_dev, card); | 4548 | pci_set_drvdata(pci_dev, card); |
4548 | 4549 | ||
4549 | /* Enable Address Engine Interrupts */ | 4550 | /* Enable Address Engine Interrupts */ |
4550 | trident_enable_loop_interrupts(card); | 4551 | trident_enable_loop_interrupts(card); |
4551 | 4552 | ||
4552 | /* Register gameport */ | 4553 | /* Register gameport */ |
4553 | trident_register_gameport(card); | 4554 | trident_register_gameport(card); |
4554 | 4555 | ||
4555 | out: | 4556 | out: |
4556 | return rc; | 4557 | return rc; |
4557 | 4558 | ||
4558 | out_unregister_sound_dsp: | 4559 | out_unregister_sound_dsp: |
4559 | unregister_sound_dsp(card->dev_audio); | 4560 | unregister_sound_dsp(card->dev_audio); |
4560 | out_free_irq: | 4561 | out_free_irq: |
4561 | free_irq(card->irq, card); | 4562 | free_irq(card->irq, card); |
4562 | out_proc_fs: | 4563 | out_proc_fs: |
4563 | pci_dev_put(card->pci_dev); | 4564 | pci_dev_put(card->pci_dev); |
4564 | if (res) { | 4565 | if (res) { |
4565 | remove_proc_entry("ALi5451", NULL); | 4566 | remove_proc_entry("ALi5451", NULL); |
4566 | res = NULL; | 4567 | res = NULL; |
4567 | } | 4568 | } |
4568 | kfree(card); | 4569 | kfree(card); |
4569 | devs = NULL; | 4570 | devs = NULL; |
4570 | out_release_region: | 4571 | out_release_region: |
4571 | release_region(iobase, 256); | 4572 | release_region(iobase, 256); |
4572 | return rc; | 4573 | return rc; |
4573 | } | 4574 | } |
4574 | 4575 | ||
4575 | static void __devexit | 4576 | static void __devexit |
4576 | trident_remove(struct pci_dev *pci_dev) | 4577 | trident_remove(struct pci_dev *pci_dev) |
4577 | { | 4578 | { |
4578 | int i; | 4579 | int i; |
4579 | struct trident_card *card = pci_get_drvdata(pci_dev); | 4580 | struct trident_card *card = pci_get_drvdata(pci_dev); |
4580 | 4581 | ||
4581 | /* | 4582 | /* |
4582 | * Kill running timers before unload. We can't have them | 4583 | * Kill running timers before unload. We can't have them |
4583 | * going off after rmmod! | 4584 | * going off after rmmod! |
4584 | */ | 4585 | */ |
4585 | if (card->hwvolctl) | 4586 | if (card->hwvolctl) |
4586 | del_timer_sync(&card->timer); | 4587 | del_timer_sync(&card->timer); |
4587 | 4588 | ||
4588 | /* ALi S/PDIF and Power Management */ | 4589 | /* ALi S/PDIF and Power Management */ |
4589 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | 4590 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { |
4590 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); | 4591 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); |
4591 | ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); | 4592 | ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); |
4592 | ali_disable_spdif_in(card); | 4593 | ali_disable_spdif_in(card); |
4593 | remove_proc_entry("ALi5451", NULL); | 4594 | remove_proc_entry("ALi5451", NULL); |
4594 | } | 4595 | } |
4595 | 4596 | ||
4596 | /* Unregister gameport */ | 4597 | /* Unregister gameport */ |
4597 | trident_unregister_gameport(card); | 4598 | trident_unregister_gameport(card); |
4598 | 4599 | ||
4599 | /* Kill interrupts, and SP/DIF */ | 4600 | /* Kill interrupts, and SP/DIF */ |
4600 | trident_disable_loop_interrupts(card); | 4601 | trident_disable_loop_interrupts(card); |
4601 | 4602 | ||
4602 | /* free hardware resources */ | 4603 | /* free hardware resources */ |
4603 | free_irq(card->irq, card); | 4604 | free_irq(card->irq, card); |
4604 | release_region(card->iobase, 256); | 4605 | release_region(card->iobase, 256); |
4605 | 4606 | ||
4606 | /* unregister audio devices */ | 4607 | /* unregister audio devices */ |
4607 | for (i = 0; i < NR_AC97; i++) | 4608 | for (i = 0; i < NR_AC97; i++) |
4608 | if (card->ac97_codec[i] != NULL) { | 4609 | if (card->ac97_codec[i] != NULL) { |
4609 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); | 4610 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); |
4610 | ac97_release_codec(card->ac97_codec[i]); | 4611 | ac97_release_codec(card->ac97_codec[i]); |
4611 | } | 4612 | } |
4612 | unregister_sound_dsp(card->dev_audio); | 4613 | unregister_sound_dsp(card->dev_audio); |
4613 | 4614 | ||
4614 | pci_set_drvdata(pci_dev, NULL); | 4615 | pci_set_drvdata(pci_dev, NULL); |
4615 | pci_dev_put(card->pci_dev); | 4616 | pci_dev_put(card->pci_dev); |
4616 | kfree(card); | 4617 | kfree(card); |
4617 | } | 4618 | } |
4618 | 4619 | ||
4619 | MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho, Ching Ling Lee, Muli Ben-Yehuda"); | 4620 | MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho, Ching Ling Lee, Muli Ben-Yehuda"); |
4620 | MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 and Tvia/IGST CyberPro5050 PCI " | 4621 | MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 and Tvia/IGST CyberPro5050 PCI " |
4621 | "Audio Driver"); | 4622 | "Audio Driver"); |
4622 | MODULE_LICENSE("GPL"); | 4623 | MODULE_LICENSE("GPL"); |
4623 | 4624 | ||
4624 | #define TRIDENT_MODULE_NAME "trident" | 4625 | #define TRIDENT_MODULE_NAME "trident" |
4625 | 4626 | ||
4626 | static struct pci_driver trident_pci_driver = { | 4627 | static struct pci_driver trident_pci_driver = { |
4627 | .name = TRIDENT_MODULE_NAME, | 4628 | .name = TRIDENT_MODULE_NAME, |
4628 | .id_table = trident_pci_tbl, | 4629 | .id_table = trident_pci_tbl, |
4629 | .probe = trident_probe, | 4630 | .probe = trident_probe, |
4630 | .remove = __devexit_p(trident_remove), | 4631 | .remove = __devexit_p(trident_remove), |
4631 | #ifdef CONFIG_PM | 4632 | #ifdef CONFIG_PM |
4632 | .suspend = trident_suspend, | 4633 | .suspend = trident_suspend, |
4633 | .resume = trident_resume | 4634 | .resume = trident_resume |
4634 | #endif | 4635 | #endif |
4635 | }; | 4636 | }; |
4636 | 4637 | ||
4637 | static int __init | 4638 | static int __init |
4638 | trident_init_module(void) | 4639 | trident_init_module(void) |
4639 | { | 4640 | { |
4640 | printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro " | 4641 | printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro " |
4641 | "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " " | 4642 | "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " " |
4642 | __DATE__ "\n"); | 4643 | __DATE__ "\n"); |
4643 | 4644 | ||
4644 | return pci_register_driver(&trident_pci_driver); | 4645 | return pci_register_driver(&trident_pci_driver); |
4645 | } | 4646 | } |
4646 | 4647 | ||
4647 | static void __exit | 4648 | static void __exit |
4648 | trident_cleanup_module(void) | 4649 | trident_cleanup_module(void) |
4649 | { | 4650 | { |
4650 | pci_unregister_driver(&trident_pci_driver); | 4651 | pci_unregister_driver(&trident_pci_driver); |
4651 | } | 4652 | } |
4652 | 4653 | ||
4653 | module_init(trident_init_module); | 4654 | module_init(trident_init_module); |
4654 | module_exit(trident_cleanup_module); | 4655 | module_exit(trident_cleanup_module); |
4655 | 4656 |