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