1 // SPDX-License-Identifier: GPL-2.0-only
2 /*****************************************************************************
3 *
4 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
5 * Jean-Christian Hassler <jhassler@free.fr>
6 *
7 * This file is part of the Audiowerk2 ALSA driver
8 *
9 *****************************************************************************/
10
11 #define AW2_SAA7146_M
12
13 #include <linux/init.h>
14 #include <linux/pci.h>
15 #include <linux/interrupt.h>
16 #include <linux/delay.h>
17 #include <linux/io.h>
18 #include <sound/core.h>
19 #include <sound/initval.h>
20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h>
22
23 #include "saa7146.h"
24 #include "aw2-saa7146.h"
25
26 #include "aw2-tsl.c"
27
28 #define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
29 #define READREG(addr) readl(chip->base_addr + (addr))
30
31 static struct snd_aw2_saa7146_cb_param
32 arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
33 static struct snd_aw2_saa7146_cb_param
34 arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
35
36 static int snd_aw2_saa7146_get_limit(int size);
37
38 /* chip-specific destructor */
snd_aw2_saa7146_free(struct snd_aw2_saa7146 * chip)39 int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
40 {
41 /* disable all irqs */
42 WRITEREG(0, IER);
43
44 /* reset saa7146 */
45 WRITEREG((MRST_N << 16), MC1);
46
47 /* Unset base addr */
48 chip->base_addr = NULL;
49
50 return 0;
51 }
52
snd_aw2_saa7146_setup(struct snd_aw2_saa7146 * chip,void __iomem * pci_base_addr)53 void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
54 void __iomem *pci_base_addr)
55 {
56 /* set PCI burst/threshold
57
58 Burst length definition
59 VALUE BURST LENGTH
60 000 1 Dword
61 001 2 Dwords
62 010 4 Dwords
63 011 8 Dwords
64 100 16 Dwords
65 101 32 Dwords
66 110 64 Dwords
67 111 128 Dwords
68
69 Threshold definition
70 VALUE WRITE MODE READ MODE
71 00 1 Dword of valid data 1 empty Dword
72 01 4 Dwords of valid data 4 empty Dwords
73 10 8 Dwords of valid data 8 empty Dwords
74 11 16 Dwords of valid data 16 empty Dwords */
75
76 unsigned int acon2;
77 unsigned int acon1 = 0;
78 int i;
79
80 /* Set base addr */
81 chip->base_addr = pci_base_addr;
82
83 /* disable all irqs */
84 WRITEREG(0, IER);
85
86 /* reset saa7146 */
87 WRITEREG((MRST_N << 16), MC1);
88
89 /* enable audio interface */
90 #ifdef __BIG_ENDIAN
91 acon1 |= A1_SWAP;
92 acon1 |= A2_SWAP;
93 #endif
94 /* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
95
96 /* At initialization WS1 and WS2 are disabled (configured as input) */
97 acon1 |= 0 * WS1_CTRL;
98 acon1 |= 0 * WS2_CTRL;
99
100 /* WS4 is not used. So it must not restart A2.
101 This is why it is configured as output (force to low) */
102 acon1 |= 3 * WS4_CTRL;
103
104 /* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
105 acon1 |= 2 * WS3_CTRL;
106
107 /* A1 and A2 are active and asynchronous */
108 acon1 |= 3 * AUDIO_MODE;
109 WRITEREG(acon1, ACON1);
110
111 /* The following comes from original windows driver.
112 It is needed to have a correct behavior of input and output
113 simultenously, but I don't know why ! */
114 WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
115 3 * (BurstA1_out) + 3 * (ThreshA1_out) +
116 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
117
118 /* enable audio port pins */
119 WRITEREG((EAP << 16) | EAP, MC1);
120
121 /* enable I2C */
122 WRITEREG((EI2C << 16) | EI2C, MC1);
123 /* enable interrupts */
124 WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
125
126 /* audio configuration */
127 acon2 = A2_CLKSRC | BCLK1_OEN;
128 WRITEREG(acon2, ACON2);
129
130 /* By default use analog input */
131 snd_aw2_saa7146_use_digital_input(chip, 0);
132
133 /* TSL setup */
134 for (i = 0; i < 8; ++i) {
135 WRITEREG(tsl1[i], TSL1 + (i * 4));
136 WRITEREG(tsl2[i], TSL2 + (i * 4));
137 }
138
139 }
140
snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 * chip,int stream_number,unsigned long dma_addr,unsigned long period_size,unsigned long buffer_size)141 void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
142 int stream_number,
143 unsigned long dma_addr,
144 unsigned long period_size,
145 unsigned long buffer_size)
146 {
147 unsigned long dw_page, dw_limit;
148
149 /* Configure DMA for substream
150 Configuration informations: ALSA has allocated continuous memory
151 pages. So we don't need to use MMU of saa7146.
152 */
153
154 /* No MMU -> nothing to do with PageA1, we only configure the limit of
155 PageAx_out register */
156 /* Disable MMU */
157 dw_page = (0L << 11);
158
159 /* Configure Limit for DMA access.
160 The limit register defines an address limit, which generates
161 an interrupt if passed by the actual PCI address pointer.
162 '0001' means an interrupt will be generated if the lower
163 6 bits (64 bytes) of the PCI address are zero. '0010'
164 defines a limit of 128 bytes, '0011' one of 256 bytes, and
165 so on up to 1 Mbyte defined by '1111'. This interrupt range
166 can be calculated as follows:
167 Range = 2^(5 + Limit) bytes.
168 */
169 dw_limit = snd_aw2_saa7146_get_limit(period_size);
170 dw_page |= (dw_limit << 4);
171
172 if (stream_number == 0) {
173 WRITEREG(dw_page, PageA2_out);
174
175 /* Base address for DMA transfert. */
176 /* This address has been reserved by ALSA. */
177 /* This is a physical address */
178 WRITEREG(dma_addr, BaseA2_out);
179
180 /* Define upper limit for DMA access */
181 WRITEREG(dma_addr + buffer_size, ProtA2_out);
182
183 } else if (stream_number == 1) {
184 WRITEREG(dw_page, PageA1_out);
185
186 /* Base address for DMA transfert. */
187 /* This address has been reserved by ALSA. */
188 /* This is a physical address */
189 WRITEREG(dma_addr, BaseA1_out);
190
191 /* Define upper limit for DMA access */
192 WRITEREG(dma_addr + buffer_size, ProtA1_out);
193 } else {
194 pr_err("aw2: snd_aw2_saa7146_pcm_init_playback: "
195 "Substream number is not 0 or 1 -> not managed\n");
196 }
197 }
198
snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 * chip,int stream_number,unsigned long dma_addr,unsigned long period_size,unsigned long buffer_size)199 void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
200 int stream_number, unsigned long dma_addr,
201 unsigned long period_size,
202 unsigned long buffer_size)
203 {
204 unsigned long dw_page, dw_limit;
205
206 /* Configure DMA for substream
207 Configuration informations: ALSA has allocated continuous memory
208 pages. So we don't need to use MMU of saa7146.
209 */
210
211 /* No MMU -> nothing to do with PageA1, we only configure the limit of
212 PageAx_out register */
213 /* Disable MMU */
214 dw_page = (0L << 11);
215
216 /* Configure Limit for DMA access.
217 The limit register defines an address limit, which generates
218 an interrupt if passed by the actual PCI address pointer.
219 '0001' means an interrupt will be generated if the lower
220 6 bits (64 bytes) of the PCI address are zero. '0010'
221 defines a limit of 128 bytes, '0011' one of 256 bytes, and
222 so on up to 1 Mbyte defined by '1111'. This interrupt range
223 can be calculated as follows:
224 Range = 2^(5 + Limit) bytes.
225 */
226 dw_limit = snd_aw2_saa7146_get_limit(period_size);
227 dw_page |= (dw_limit << 4);
228
229 if (stream_number == 0) {
230 WRITEREG(dw_page, PageA1_in);
231
232 /* Base address for DMA transfert. */
233 /* This address has been reserved by ALSA. */
234 /* This is a physical address */
235 WRITEREG(dma_addr, BaseA1_in);
236
237 /* Define upper limit for DMA access */
238 WRITEREG(dma_addr + buffer_size, ProtA1_in);
239 } else {
240 pr_err("aw2: snd_aw2_saa7146_pcm_init_capture: "
241 "Substream number is not 0 -> not managed\n");
242 }
243 }
244
snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,snd_aw2_saa7146_it_cb p_it_callback,void * p_callback_param)245 void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
246 snd_aw2_saa7146_it_cb
247 p_it_callback,
248 void *p_callback_param)
249 {
250 if (stream_number < NB_STREAM_PLAYBACK) {
251 arr_substream_it_playback_cb[stream_number].p_it_callback =
252 (snd_aw2_saa7146_it_cb) p_it_callback;
253 arr_substream_it_playback_cb[stream_number].p_callback_param =
254 (void *)p_callback_param;
255 }
256 }
257
snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,snd_aw2_saa7146_it_cb p_it_callback,void * p_callback_param)258 void snd_aw2_saa7146_define_it_capture_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_CAPTURE) {
264 arr_substream_it_capture_cb[stream_number].p_it_callback =
265 (snd_aw2_saa7146_it_cb) p_it_callback;
266 arr_substream_it_capture_cb[stream_number].p_callback_param =
267 (void *)p_callback_param;
268 }
269 }
270
snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 * chip,int stream_number)271 void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
272 int stream_number)
273 {
274 unsigned int acon1 = 0;
275 /* In aw8 driver, dma transfert is always active. It is
276 started and stopped in a larger "space" */
277 acon1 = READREG(ACON1);
278 if (stream_number == 0) {
279 WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
280
281 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
282 acon1 |= 2 * WS2_CTRL;
283 WRITEREG(acon1, ACON1);
284
285 } else if (stream_number == 1) {
286 WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
287
288 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
289 acon1 |= 1 * WS1_CTRL;
290 WRITEREG(acon1, ACON1);
291 }
292 }
293
snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 * chip,int stream_number)294 void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
295 int stream_number)
296 {
297 unsigned int acon1 = 0;
298 acon1 = READREG(ACON1);
299 if (stream_number == 0) {
300 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
301 acon1 &= ~(3 * WS2_CTRL);
302 WRITEREG(acon1, ACON1);
303
304 WRITEREG((TR_E_A2_OUT << 16), MC1);
305 } else if (stream_number == 1) {
306 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
307 acon1 &= ~(3 * WS1_CTRL);
308 WRITEREG(acon1, ACON1);
309
310 WRITEREG((TR_E_A1_OUT << 16), MC1);
311 }
312 }
313
snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 * chip,int stream_number)314 void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
315 int stream_number)
316 {
317 /* In aw8 driver, dma transfert is always active. It is
318 started and stopped in a larger "space" */
319 if (stream_number == 0)
320 WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
321 }
322
snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 * chip,int stream_number)323 void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
324 int stream_number)
325 {
326 if (stream_number == 0)
327 WRITEREG((TR_E_A1_IN << 16), MC1);
328 }
329
snd_aw2_saa7146_interrupt(int irq,void * dev_id)330 irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
331 {
332 unsigned int isr;
333 __always_unused unsigned int iicsta;
334 struct snd_aw2_saa7146 *chip = dev_id;
335
336 isr = READREG(ISR);
337 if (!isr)
338 return IRQ_NONE;
339
340 WRITEREG(isr, ISR);
341
342 if (isr & (IIC_S | IIC_E)) {
343 iicsta = READREG(IICSTA);
344 WRITEREG(0x100, IICSTA);
345 }
346
347 if (isr & A1_out) {
348 if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
349 arr_substream_it_playback_cb[1].
350 p_it_callback(arr_substream_it_playback_cb[1].
351 p_callback_param);
352 }
353 }
354 if (isr & A2_out) {
355 if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
356 arr_substream_it_playback_cb[0].
357 p_it_callback(arr_substream_it_playback_cb[0].
358 p_callback_param);
359 }
360
361 }
362 if (isr & A1_in) {
363 if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
364 arr_substream_it_capture_cb[0].
365 p_it_callback(arr_substream_it_capture_cb[0].
366 p_callback_param);
367 }
368 }
369 return IRQ_HANDLED;
370 }
371
snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 * chip,int stream_number,unsigned char * start_addr,unsigned int buffer_size)372 unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
373 int stream_number,
374 unsigned char *start_addr,
375 unsigned int buffer_size)
376 {
377 long pci_adp = 0;
378 size_t ptr = 0;
379
380 if (stream_number == 0) {
381 pci_adp = READREG(PCI_ADP3);
382 ptr = pci_adp - (long)start_addr;
383
384 if (ptr == buffer_size)
385 ptr = 0;
386 }
387 if (stream_number == 1) {
388 pci_adp = READREG(PCI_ADP1);
389 ptr = pci_adp - (size_t) start_addr;
390
391 if (ptr == buffer_size)
392 ptr = 0;
393 }
394 return ptr;
395 }
396
snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 * chip,int stream_number,unsigned char * start_addr,unsigned int buffer_size)397 unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
398 int stream_number,
399 unsigned char *start_addr,
400 unsigned int buffer_size)
401 {
402 size_t pci_adp = 0;
403 size_t ptr = 0;
404 if (stream_number == 0) {
405 pci_adp = READREG(PCI_ADP2);
406 ptr = pci_adp - (size_t) start_addr;
407
408 if (ptr == buffer_size)
409 ptr = 0;
410 }
411 return ptr;
412 }
413
snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 * chip,int use_digital)414 void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
415 int use_digital)
416 {
417 /* FIXME: switch between analog and digital input does not always work.
418 It can produce a kind of white noise. It seams that received data
419 are inverted sometime (endian inversion). Why ? I don't know, maybe
420 a problem of synchronization... However for the time being I have
421 not found the problem. Workaround: switch again (and again) between
422 digital and analog input until it works. */
423 if (use_digital)
424 WRITEREG(0x40, GPIO_CTRL);
425 else
426 WRITEREG(0x50, GPIO_CTRL);
427 }
428
snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 * chip)429 int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
430 {
431 unsigned int reg_val = READREG(GPIO_CTRL);
432 if ((reg_val & 0xFF) == 0x40)
433 return 1;
434 else
435 return 0;
436 }
437
438
snd_aw2_saa7146_get_limit(int size)439 static int snd_aw2_saa7146_get_limit(int size)
440 {
441 int limitsize = 32;
442 int limit = 0;
443 while (limitsize < size) {
444 limitsize *= 2;
445 limit++;
446 }
447 return limit;
448 }
449