1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#define AW2_SAA7146_M
25
26#include <linux/init.h>
27#include <linux/pci.h>
28#include <linux/interrupt.h>
29#include <linux/delay.h>
30#include <asm/system.h>
31#include <asm/io.h>
32#include <sound/core.h>
33#include <sound/initval.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36
37#include "saa7146.h"
38#include "aw2-saa7146.h"
39
40#include "aw2-tsl.c"
41
42#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
43#define READREG(addr) readl(chip->base_addr + (addr))
44
45static struct snd_aw2_saa7146_cb_param
46 arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
47static struct snd_aw2_saa7146_cb_param
48 arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
49
50static int snd_aw2_saa7146_get_limit(int size);
51
52
53int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
54{
55
56 WRITEREG(0, IER);
57
58
59 WRITEREG((MRST_N << 16), MC1);
60
61
62 chip->base_addr = NULL;
63
64 return 0;
65}
66
67void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
68 void __iomem *pci_base_addr)
69{
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 unsigned int acon2;
91 unsigned int acon1 = 0;
92 int i;
93
94
95 chip->base_addr = pci_base_addr;
96
97
98 WRITEREG(0, IER);
99
100
101 WRITEREG((MRST_N << 16), MC1);
102
103
104#ifdef __BIG_ENDIAN
105 acon1 |= A1_SWAP;
106 acon1 |= A2_SWAP;
107#endif
108
109
110
111 acon1 |= 0 * WS1_CTRL;
112 acon1 |= 0 * WS2_CTRL;
113
114
115
116 acon1 |= 3 * WS4_CTRL;
117
118
119 acon1 |= 2 * WS3_CTRL;
120
121
122 acon1 |= 3 * AUDIO_MODE;
123 WRITEREG(acon1, ACON1);
124
125
126
127
128 WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
129 3 * (BurstA1_out) + 3 * (ThreshA1_out) +
130 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
131
132
133 WRITEREG((EAP << 16) | EAP, MC1);
134
135
136 WRITEREG((EI2C << 16) | EI2C, MC1);
137
138 WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
139
140
141 acon2 = A2_CLKSRC | BCLK1_OEN;
142 WRITEREG(acon2, ACON2);
143
144
145 snd_aw2_saa7146_use_digital_input(chip, 0);
146
147
148 for (i = 0; i < 8; ++i) {
149 WRITEREG(tsl1[i], TSL1 + (i * 4));
150 WRITEREG(tsl2[i], TSL2 + (i * 4));
151 }
152
153}
154
155void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
156 int stream_number,
157 unsigned long dma_addr,
158 unsigned long period_size,
159 unsigned long buffer_size)
160{
161 unsigned long dw_page, dw_limit;
162
163
164
165
166
167
168
169
170
171 dw_page = (0L << 11);
172
173
174
175
176
177
178
179
180
181
182
183 dw_limit = snd_aw2_saa7146_get_limit(period_size);
184 dw_page |= (dw_limit << 4);
185
186 if (stream_number == 0) {
187 WRITEREG(dw_page, PageA2_out);
188
189
190
191
192 WRITEREG(dma_addr, BaseA2_out);
193
194
195 WRITEREG(dma_addr + buffer_size, ProtA2_out);
196
197 } else if (stream_number == 1) {
198 WRITEREG(dw_page, PageA1_out);
199
200
201
202
203 WRITEREG(dma_addr, BaseA1_out);
204
205
206 WRITEREG(dma_addr + buffer_size, ProtA1_out);
207 } else {
208 printk(KERN_ERR
209 "aw2: snd_aw2_saa7146_pcm_init_playback: "
210 "Substream number is not 0 or 1 -> not managed\n");
211 }
212}
213
214void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
215 int stream_number, unsigned long dma_addr,
216 unsigned long period_size,
217 unsigned long buffer_size)
218{
219 unsigned long dw_page, dw_limit;
220
221
222
223
224
225
226
227
228
229 dw_page = (0L << 11);
230
231
232
233
234
235
236
237
238
239
240
241 dw_limit = snd_aw2_saa7146_get_limit(period_size);
242 dw_page |= (dw_limit << 4);
243
244 if (stream_number == 0) {
245 WRITEREG(dw_page, PageA1_in);
246
247
248
249
250 WRITEREG(dma_addr, BaseA1_in);
251
252
253 WRITEREG(dma_addr + buffer_size, ProtA1_in);
254 } else {
255 printk(KERN_ERR
256 "aw2: snd_aw2_saa7146_pcm_init_capture: "
257 "Substream number is not 0 -> not managed\n");
258 }
259}
260
261void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
262 snd_aw2_saa7146_it_cb
263 p_it_callback,
264 void *p_callback_param)
265{
266 if (stream_number < NB_STREAM_PLAYBACK) {
267 arr_substream_it_playback_cb[stream_number].p_it_callback =
268 (snd_aw2_saa7146_it_cb) p_it_callback;
269 arr_substream_it_playback_cb[stream_number].p_callback_param =
270 (void *)p_callback_param;
271 }
272}
273
274void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
275 snd_aw2_saa7146_it_cb
276 p_it_callback,
277 void *p_callback_param)
278{
279 if (stream_number < NB_STREAM_CAPTURE) {
280 arr_substream_it_capture_cb[stream_number].p_it_callback =
281 (snd_aw2_saa7146_it_cb) p_it_callback;
282 arr_substream_it_capture_cb[stream_number].p_callback_param =
283 (void *)p_callback_param;
284 }
285}
286
287void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
288 int stream_number)
289{
290 unsigned int acon1 = 0;
291
292
293 acon1 = READREG(ACON1);
294 if (stream_number == 0) {
295 WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
296
297
298 acon1 |= 2 * WS2_CTRL;
299 WRITEREG(acon1, ACON1);
300
301 } else if (stream_number == 1) {
302 WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
303
304
305 acon1 |= 1 * WS1_CTRL;
306 WRITEREG(acon1, ACON1);
307 }
308}
309
310void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
311 int stream_number)
312{
313 unsigned int acon1 = 0;
314 acon1 = READREG(ACON1);
315 if (stream_number == 0) {
316
317 acon1 &= ~(3 * WS2_CTRL);
318 WRITEREG(acon1, ACON1);
319
320 WRITEREG((TR_E_A2_OUT << 16), MC1);
321 } else if (stream_number == 1) {
322
323 acon1 &= ~(3 * WS1_CTRL);
324 WRITEREG(acon1, ACON1);
325
326 WRITEREG((TR_E_A1_OUT << 16), MC1);
327 }
328}
329
330void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
331 int stream_number)
332{
333
334
335 if (stream_number == 0)
336 WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
337}
338
339void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
340 int stream_number)
341{
342 if (stream_number == 0)
343 WRITEREG((TR_E_A1_IN << 16), MC1);
344}
345
346irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
347{
348 unsigned int isr;
349 unsigned int iicsta;
350 struct snd_aw2_saa7146 *chip = dev_id;
351
352 isr = READREG(ISR);
353 if (!isr)
354 return IRQ_NONE;
355
356 WRITEREG(isr, ISR);
357
358 if (isr & (IIC_S | IIC_E)) {
359 iicsta = READREG(IICSTA);
360 WRITEREG(0x100, IICSTA);
361 }
362
363 if (isr & A1_out) {
364 if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
365 arr_substream_it_playback_cb[1].
366 p_it_callback(arr_substream_it_playback_cb[1].
367 p_callback_param);
368 }
369 }
370 if (isr & A2_out) {
371 if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
372 arr_substream_it_playback_cb[0].
373 p_it_callback(arr_substream_it_playback_cb[0].
374 p_callback_param);
375 }
376
377 }
378 if (isr & A1_in) {
379 if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
380 arr_substream_it_capture_cb[0].
381 p_it_callback(arr_substream_it_capture_cb[0].
382 p_callback_param);
383 }
384 }
385 return IRQ_HANDLED;
386}
387
388unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
389 int stream_number,
390 unsigned char *start_addr,
391 unsigned int buffer_size)
392{
393 long pci_adp = 0;
394 size_t ptr = 0;
395
396 if (stream_number == 0) {
397 pci_adp = READREG(PCI_ADP3);
398 ptr = pci_adp - (long)start_addr;
399
400 if (ptr == buffer_size)
401 ptr = 0;
402 }
403 if (stream_number == 1) {
404 pci_adp = READREG(PCI_ADP1);
405 ptr = pci_adp - (size_t) start_addr;
406
407 if (ptr == buffer_size)
408 ptr = 0;
409 }
410 return ptr;
411}
412
413unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
414 int stream_number,
415 unsigned char *start_addr,
416 unsigned int buffer_size)
417{
418 size_t pci_adp = 0;
419 size_t ptr = 0;
420 if (stream_number == 0) {
421 pci_adp = READREG(PCI_ADP2);
422 ptr = pci_adp - (size_t) start_addr;
423
424 if (ptr == buffer_size)
425 ptr = 0;
426 }
427 return ptr;
428}
429
430void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
431 int use_digital)
432{
433
434
435
436
437
438
439 if (use_digital)
440 WRITEREG(0x40, GPIO_CTRL);
441 else
442 WRITEREG(0x50, GPIO_CTRL);
443}
444
445int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
446{
447 unsigned int reg_val = READREG(GPIO_CTRL);
448 if ((reg_val & 0xFF) == 0x40)
449 return 1;
450 else
451 return 0;
452}
453
454
455static int snd_aw2_saa7146_get_limit(int size)
456{
457 int limitsize = 32;
458 int limit = 0;
459 while (limitsize < size) {
460 limitsize *= 2;
461 limit++;
462 }
463 return limit;
464}
465