xref: /openbmc/linux/sound/pci/aw2/aw2-saa7146.c (revision f2f4bf5a)
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 */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
330 irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
331 {
332 	unsigned int isr;
333 	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 
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 
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 
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 
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 
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