Loading...
1/*****************************************************************************
2 *
3 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
4 * Jean-Christian Hassler <jhassler@free.fr>
5 *
6 * This file is part of the Audiowerk2 ALSA driver
7 *
8 * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 *
12 * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
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/* chip-specific destructor */
52int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
53{
54 /* disable all irqs */
55 WRITEREG(0, IER);
56
57 /* reset saa7146 */
58 WRITEREG((MRST_N << 16), MC1);
59
60 /* Unset base addr */
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 /* set PCI burst/threshold
70
71 Burst length definition
72 VALUE BURST LENGTH
73 000 1 Dword
74 001 2 Dwords
75 010 4 Dwords
76 011 8 Dwords
77 100 16 Dwords
78 101 32 Dwords
79 110 64 Dwords
80 111 128 Dwords
81
82 Threshold definition
83 VALUE WRITE MODE READ MODE
84 00 1 Dword of valid data 1 empty Dword
85 01 4 Dwords of valid data 4 empty Dwords
86 10 8 Dwords of valid data 8 empty Dwords
87 11 16 Dwords of valid data 16 empty Dwords */
88
89 unsigned int acon2;
90 unsigned int acon1 = 0;
91 int i;
92
93 /* Set base addr */
94 chip->base_addr = pci_base_addr;
95
96 /* disable all irqs */
97 WRITEREG(0, IER);
98
99 /* reset saa7146 */
100 WRITEREG((MRST_N << 16), MC1);
101
102 /* enable audio interface */
103#ifdef __BIG_ENDIAN
104 acon1 |= A1_SWAP;
105 acon1 |= A2_SWAP;
106#endif
107 /* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
108
109 /* At initialization WS1 and WS2 are disabled (configured as input) */
110 acon1 |= 0 * WS1_CTRL;
111 acon1 |= 0 * WS2_CTRL;
112
113 /* WS4 is not used. So it must not restart A2.
114 This is why it is configured as output (force to low) */
115 acon1 |= 3 * WS4_CTRL;
116
117 /* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
118 acon1 |= 2 * WS3_CTRL;
119
120 /* A1 and A2 are active and asynchronous */
121 acon1 |= 3 * AUDIO_MODE;
122 WRITEREG(acon1, ACON1);
123
124 /* The following comes from original windows driver.
125 It is needed to have a correct behavior of input and output
126 simultenously, but I don't know why ! */
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 /* enable audio port pins */
132 WRITEREG((EAP << 16) | EAP, MC1);
133
134 /* enable I2C */
135 WRITEREG((EI2C << 16) | EI2C, MC1);
136 /* enable interrupts */
137 WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
138
139 /* audio configuration */
140 acon2 = A2_CLKSRC | BCLK1_OEN;
141 WRITEREG(acon2, ACON2);
142
143 /* By default use analog input */
144 snd_aw2_saa7146_use_digital_input(chip, 0);
145
146 /* TSL setup */
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 /* Configure DMA for substream
163 Configuration informations: ALSA has allocated continuous memory
164 pages. So we don't need to use MMU of saa7146.
165 */
166
167 /* No MMU -> nothing to do with PageA1, we only configure the limit of
168 PageAx_out register */
169 /* Disable MMU */
170 dw_page = (0L << 11);
171
172 /* Configure Limit for DMA access.
173 The limit register defines an address limit, which generates
174 an interrupt if passed by the actual PCI address pointer.
175 '0001' means an interrupt will be generated if the lower
176 6 bits (64 bytes) of the PCI address are zero. '0010'
177 defines a limit of 128 bytes, '0011' one of 256 bytes, and
178 so on up to 1 Mbyte defined by '1111'. This interrupt range
179 can be calculated as follows:
180 Range = 2^(5 + Limit) bytes.
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 /* Base address for DMA transfert. */
189 /* This address has been reserved by ALSA. */
190 /* This is a physical address */
191 WRITEREG(dma_addr, BaseA2_out);
192
193 /* Define upper limit for DMA access */
194 WRITEREG(dma_addr + buffer_size, ProtA2_out);
195
196 } else if (stream_number == 1) {
197 WRITEREG(dw_page, PageA1_out);
198
199 /* Base address for DMA transfert. */
200 /* This address has been reserved by ALSA. */
201 /* This is a physical address */
202 WRITEREG(dma_addr, BaseA1_out);
203
204 /* Define upper limit for DMA access */
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 /* Configure DMA for substream
220 Configuration informations: ALSA has allocated continuous memory
221 pages. So we don't need to use MMU of saa7146.
222 */
223
224 /* No MMU -> nothing to do with PageA1, we only configure the limit of
225 PageAx_out register */
226 /* Disable MMU */
227 dw_page = (0L << 11);
228
229 /* Configure Limit for DMA access.
230 The limit register defines an address limit, which generates
231 an interrupt if passed by the actual PCI address pointer.
232 '0001' means an interrupt will be generated if the lower
233 6 bits (64 bytes) of the PCI address are zero. '0010'
234 defines a limit of 128 bytes, '0011' one of 256 bytes, and
235 so on up to 1 Mbyte defined by '1111'. This interrupt range
236 can be calculated as follows:
237 Range = 2^(5 + Limit) bytes.
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 /* Base address for DMA transfert. */
246 /* This address has been reserved by ALSA. */
247 /* This is a physical address */
248 WRITEREG(dma_addr, BaseA1_in);
249
250 /* Define upper limit for DMA access */
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 /* In aw8 driver, dma transfert is always active. It is
289 started and stopped in a larger "space" */
290 acon1 = READREG(ACON1);
291 if (stream_number == 0) {
292 WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
293
294 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
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 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
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 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
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 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
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 /* In aw8 driver, dma transfert is always active. It is
331 started and stopped in a larger "space" */
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 /* FIXME: switch between analog and digital input does not always work.
431 It can produce a kind of white noise. It seams that received data
432 are inverted sometime (endian inversion). Why ? I don't know, maybe
433 a problem of synchronization... However for the time being I have
434 not found the problem. Workaround: switch again (and again) between
435 digital and analog input until it works. */
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}
1/*****************************************************************************
2 *
3 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
4 * Jean-Christian Hassler <jhassler@free.fr>
5 *
6 * This file is part of the Audiowerk2 ALSA driver
7 *
8 * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 *
12 * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
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/* chip-specific destructor */
53int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
54{
55 /* disable all irqs */
56 WRITEREG(0, IER);
57
58 /* reset saa7146 */
59 WRITEREG((MRST_N << 16), MC1);
60
61 /* Unset base addr */
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 /* set PCI burst/threshold
71
72 Burst length definition
73 VALUE BURST LENGTH
74 000 1 Dword
75 001 2 Dwords
76 010 4 Dwords
77 011 8 Dwords
78 100 16 Dwords
79 101 32 Dwords
80 110 64 Dwords
81 111 128 Dwords
82
83 Threshold definition
84 VALUE WRITE MODE READ MODE
85 00 1 Dword of valid data 1 empty Dword
86 01 4 Dwords of valid data 4 empty Dwords
87 10 8 Dwords of valid data 8 empty Dwords
88 11 16 Dwords of valid data 16 empty Dwords */
89
90 unsigned int acon2;
91 unsigned int acon1 = 0;
92 int i;
93
94 /* Set base addr */
95 chip->base_addr = pci_base_addr;
96
97 /* disable all irqs */
98 WRITEREG(0, IER);
99
100 /* reset saa7146 */
101 WRITEREG((MRST_N << 16), MC1);
102
103 /* enable audio interface */
104#ifdef __BIG_ENDIAN
105 acon1 |= A1_SWAP;
106 acon1 |= A2_SWAP;
107#endif
108 /* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
109
110 /* At initialization WS1 and WS2 are disabled (configured as input) */
111 acon1 |= 0 * WS1_CTRL;
112 acon1 |= 0 * WS2_CTRL;
113
114 /* WS4 is not used. So it must not restart A2.
115 This is why it is configured as output (force to low) */
116 acon1 |= 3 * WS4_CTRL;
117
118 /* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
119 acon1 |= 2 * WS3_CTRL;
120
121 /* A1 and A2 are active and asynchronous */
122 acon1 |= 3 * AUDIO_MODE;
123 WRITEREG(acon1, ACON1);
124
125 /* The following comes from original windows driver.
126 It is needed to have a correct behavior of input and output
127 simultenously, but I don't know why ! */
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 /* enable audio port pins */
133 WRITEREG((EAP << 16) | EAP, MC1);
134
135 /* enable I2C */
136 WRITEREG((EI2C << 16) | EI2C, MC1);
137 /* enable interrupts */
138 WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
139
140 /* audio configuration */
141 acon2 = A2_CLKSRC | BCLK1_OEN;
142 WRITEREG(acon2, ACON2);
143
144 /* By default use analog input */
145 snd_aw2_saa7146_use_digital_input(chip, 0);
146
147 /* TSL setup */
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 /* Configure DMA for substream
164 Configuration informations: ALSA has allocated continuous memory
165 pages. So we don't need to use MMU of saa7146.
166 */
167
168 /* No MMU -> nothing to do with PageA1, we only configure the limit of
169 PageAx_out register */
170 /* Disable MMU */
171 dw_page = (0L << 11);
172
173 /* Configure Limit for DMA access.
174 The limit register defines an address limit, which generates
175 an interrupt if passed by the actual PCI address pointer.
176 '0001' means an interrupt will be generated if the lower
177 6 bits (64 bytes) of the PCI address are zero. '0010'
178 defines a limit of 128 bytes, '0011' one of 256 bytes, and
179 so on up to 1 Mbyte defined by '1111'. This interrupt range
180 can be calculated as follows:
181 Range = 2^(5 + Limit) bytes.
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 /* Base address for DMA transfert. */
190 /* This address has been reserved by ALSA. */
191 /* This is a physical address */
192 WRITEREG(dma_addr, BaseA2_out);
193
194 /* Define upper limit for DMA access */
195 WRITEREG(dma_addr + buffer_size, ProtA2_out);
196
197 } else if (stream_number == 1) {
198 WRITEREG(dw_page, PageA1_out);
199
200 /* Base address for DMA transfert. */
201 /* This address has been reserved by ALSA. */
202 /* This is a physical address */
203 WRITEREG(dma_addr, BaseA1_out);
204
205 /* Define upper limit for DMA access */
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 /* Configure DMA for substream
222 Configuration informations: ALSA has allocated continuous memory
223 pages. So we don't need to use MMU of saa7146.
224 */
225
226 /* No MMU -> nothing to do with PageA1, we only configure the limit of
227 PageAx_out register */
228 /* Disable MMU */
229 dw_page = (0L << 11);
230
231 /* Configure Limit for DMA access.
232 The limit register defines an address limit, which generates
233 an interrupt if passed by the actual PCI address pointer.
234 '0001' means an interrupt will be generated if the lower
235 6 bits (64 bytes) of the PCI address are zero. '0010'
236 defines a limit of 128 bytes, '0011' one of 256 bytes, and
237 so on up to 1 Mbyte defined by '1111'. This interrupt range
238 can be calculated as follows:
239 Range = 2^(5 + Limit) bytes.
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 /* Base address for DMA transfert. */
248 /* This address has been reserved by ALSA. */
249 /* This is a physical address */
250 WRITEREG(dma_addr, BaseA1_in);
251
252 /* Define upper limit for DMA access */
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 /* In aw8 driver, dma transfert is always active. It is
292 started and stopped in a larger "space" */
293 acon1 = READREG(ACON1);
294 if (stream_number == 0) {
295 WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
296
297 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
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 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
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 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
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 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
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 /* In aw8 driver, dma transfert is always active. It is
334 started and stopped in a larger "space" */
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 /* FIXME: switch between analog and digital input does not always work.
434 It can produce a kind of white noise. It seams that received data
435 are inverted sometime (endian inversion). Why ? I don't know, maybe
436 a problem of synchronization... However for the time being I have
437 not found the problem. Workaround: switch again (and again) between
438 digital and analog input until it works. */
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}