xref: /minix/minix/drivers/audio/trident/trident.c (revision 77e79d33)
1 #include "trident.h"
2 #include "mixer.h"
3 
4 /* global value */
5 DEV_STRUCT dev;
6 aud_sub_dev_conf_t aud_conf[3];
7 sub_dev_t sub_dev[3];
8 special_file_t special_file[3];
9 drv_t drv;
10 
11 /* internal function */
12 static int dev_probe(void);
13 static int set_sample_rate(u32_t rate, int num);
14 static int set_stereo(u32_t stereo, int num);
15 static int set_bits(u32_t bits, int sub_dev);
16 static int set_frag_size(u32_t frag_size, int num);
17 static int set_sign(u32_t val, int num);
18 static int get_frag_size(u32_t *val, int *len, int num);
19 static int free_buf(u32_t *val, int *len, int num);
20 
21 /* developer interface */
22 static int dev_reset(u32_t *base);
23 static void dev_configure(u32_t *base);
24 static void dev_init_mixer(u32_t *base);
25 static void dev_set_sample_rate(u32_t *base, u16_t sample_rate);
26 static void dev_set_format(u32_t *base, u32_t bits, u32_t sign,
27 							u32_t stereo, u32_t sample_count);
28 static void dev_start_channel(u32_t *base, int sub_dev);
29 static void dev_stop_channel(u32_t *base, int sub_dev);
30 static void dev_set_dma(u32_t *base, u32_t dma, u32_t len, int sub_dev);
31 static u32_t dev_read_dma_current(u32_t *base, int sub_dev);
32 static void dev_pause_dma(u32_t *base, int sub_dev);
33 static void dev_resume_dma(u32_t *base, int sub_dev);
34 static void dev_intr_other(u32_t *base, u32_t status);
35 static u32_t dev_read_clear_intr_status(u32_t *base);
36 static void dev_intr_enable(u32_t *base, int flag);
37 
38 /* ======= Developer implemented function ======= */
39 /* ====== Self-defined function ====== */
40 static void dev_write_chan_reg(u32_t base) {
41 	u32_t reg[5], i, data;
42 	reg[0] = (my_chan.cso << 16) | (my_chan.alpha << 4) | my_chan.fms;
43 	reg[1] = my_chan.dma;
44 	reg[2] = (my_chan.eso << 16) | my_chan.delta;
45 	reg[3] = (my_chan.fmc << 14) | (my_chan.rvol << 7) | my_chan.cvol;
46 	reg[4] = (my_chan.gvsel << 31) | (my_chan.pan << 24) | (my_chan.vol << 16) |
47 				(my_chan.ctrl << 12) | (my_chan.ec);
48 	for (i = 0; i < 5; i++)
49 		sdr_out32(base, REG_CHAN_BASE + (i << 2), reg[i]);
50 }
51 
52 /* ====== Mixer handling interface ======*/
53 /* Write the data to mixer register (### WRITE_MIXER_REG ###) */
54 void dev_mixer_write(u32_t *base, u32_t reg, u32_t val) {
55 	u32_t i, data, base0 = base[0];
56 	for (i = 0; i < 50000; i++) {
57 		data = sdr_in16(base0, REG_CODEC_WRITE);
58 		if (!(data & STS_CODEC_BUSY))
59 			break;
60 	}
61 	if (i == 50000)
62 		printf("SDR: Codec is not ready\n");
63 	data = (data << 16) | (reg & 0x00ff) | STS_CODEC_BUSY;
64 	sdr_out32(base0, REG_CODEC_WRITE, data);
65 }
66 
67 /* Read the data from mixer register (### READ_MIXER_REG ###) */
68 u32_t dev_mixer_read(u32_t *base, u32_t reg) {
69 	u32_t i, data, base0 = base[0];
70 	data = (reg & 0x00ff) | STS_CODEC_BUSY;
71 	sdr_out32(base0, REG_CODEC_READ, data);
72 	for (i = 0; i < 50000; i++) {
73 		data = sdr_in16(base0, REG_CODEC_WRITE);
74 		if (!(data & STS_CODEC_BUSY))
75 			break;
76 	}
77 	if (i == 50000)
78 		printf("SDR: Codec is not ready\n");
79 	return (data >> 16);
80 }
81 
82 /* ====== Developer interface ======*/
83 
84 /* Reset the device (### RESET_HARDWARE_CAN_FAIL ###)
85  * -- Return OK means success, Others means failure */
86 static int dev_reset(u32_t *base) {
87 	u32_t base0 = base[0];
88 	sdr_out32(base0, REG_CODEC_CTRL, 0x000a);
89 	return OK;
90 }
91 
92 /* Configure hardware registers (### CONF_HARDWARE ###) */
93 static void dev_configure(u32_t *base) {
94 	u32_t base0 = base[0];
95 	sdr_out32(base0, REG_GCTRL, 0x3000);
96 }
97 
98 /* Initialize the mixer (### INIT_MIXER ###) */
99 static void dev_init_mixer(u32_t *base) {
100 	dev_mixer_write(base, 0, 0);
101 }
102 
103 /* Set DAC and ADC sample rate (### SET_SAMPLE_RATE ###) */
104 static void dev_set_sample_rate(u32_t *base, u16_t sample_rate) {
105 	u32_t base0 = base[0];
106 	my_chan.delta = (sample_rate << 12) / 48000;
107 	sdr_out16(base0, REG_SB_DELTA, (48000 << 12) / sample_rate);
108 }
109 
110 /* Set DAC and ADC format (### SET_FORMAT ###)*/
111 static void dev_set_format(u32_t *base, u32_t bits, u32_t sign,
112 							u32_t stereo, u32_t sample_count) {
113 	u32_t data = 0, base0 = base[0];
114 	if (bits == 16)
115 		data |= CMD_FORMAT_BIT16;
116 	if (sign == 1)
117 		data |= CMD_FORMAT_SIGN;
118 	if (stereo == 1)
119 		data |= CMD_FORMAT_STEREO;
120 	my_chan.ctrl = data;
121 
122 	data = my_chan.eso + 1;
123 	if (bits == 16)
124 		data >>= 1;
125 	data --;
126 	sdr_out32(base0, REG_SB_BASE, data | (data << 16));
127 	sdr_out8(base0, REG_SB_CTRL, (my_chan.ctrl << 4) | 0x18);
128 }
129 
130 /* Start the channel (### START_CHANNEL ###) */
131 static void dev_start_channel(u32_t *base, int sub_dev) {
132 	u32_t data, base0 = base[0];
133 	if (sub_dev == DAC) {
134 		my_chan.fmc = 3; my_chan.fms = 0; my_chan.ec = 0;
135 		my_chan.alpha = 0; my_chan.cso = 0;
136 		my_chan.rvol = my_chan.cvol = 0x7f;
137 		my_chan.gvsel = 0; my_chan.pan = 0;
138 		my_chan.vol = 0; my_chan.ctrl |= 0x01;
139 		dev_write_chan_reg(base0);
140 		data = sdr_in32(base0, REG_START_A);
141 		sdr_out32(base0, REG_START_A, data | 0x01);
142 	}
143 	else if (sub_dev == ADC) {
144 		data = sdr_in8(base0, REG_SB_CTRL);
145 		sdr_out8(base0, REG_SB_CTRL, data | 0x01);
146 	}
147 }
148 
149 /* Stop the channel (### STOP_CHANNEL ###) */
150 static void dev_stop_channel(u32_t *base, int sub_dev) {
151 	u32_t data, base0 = base[0];
152 	if (sub_dev == DAC)
153 		sdr_out32(base0, REG_STOP_A, 1);
154 	else if (sub_dev == ADC)
155 		sdr_out8(base0, REG_SB_CTRL, 0);
156 }
157 
158 /* Set DMA address and length (### SET_DMA ###) */
159 static void dev_set_dma(u32_t *base, u32_t dma, u32_t len, int sub_dev) {
160 	u32_t data, base0 = base[0];
161 	my_chan.dma = dma;
162 	my_chan.eso = len - 1;
163 	if (sub_dev == ADC) {
164 		sdr_out8(base0, REG_DMA15, 0);
165 		sdr_out8(base0, REG_DMA11, 0x54);
166 		sdr_out32(base0, REG_DMA0, dma);
167 		data = sdr_in32(base0, REG_DMA4) & 0xff000000;
168 		sdr_out16(base0, REG_DMA4, (len - 1) | data);
169 	}
170 }
171 
172 /* Read current address (### READ_DMA_CURRENT_ADDR ###) */
173 static u32_t dev_read_dma_current(u32_t *base, int sub_dev) {
174 	u32_t data, base0 = base[0];
175 	sdr_out8(base0, REG_GCTRL, 0);
176 	if (sub_dev == DAC)
177 		data = sdr_in16(base0, REG_CHAN_BASE + 0x02);
178 	else if (sub_dev == ADC)
179 		data = sdr_in16(base0, REG_SB_BASE);
180 	data &= 0xffff;
181 	return 0;
182 }
183 
184 /* Pause the DMA (### PAUSE_DMA ###) */
185 static void dev_pause_dma(u32_t *base, int sub_dev) {
186 	u32_t data, base0 = base[0];
187 	if (sub_dev == DAC)
188 		sdr_out32(base0, REG_STOP_A, 1);
189 	else if (sub_dev == ADC) {
190 		data = sdr_in8(base0, REG_SB_CTRL);
191 		sdr_out8(base0, REG_SB_CTRL, data & 0xf8);
192 	}
193 }
194 
195 /* Resume the DMA (### RESUME_DMA ###) */
196 static void dev_resume_dma(u32_t *base, int sub_dev) {
197 	u32_t data, base0 = base[0];
198 	if (sub_dev == DAC) {
199 		data = sdr_in32(base0, REG_START_A);
200 		sdr_out32(base0, REG_START_A, data | 0x01);
201 	}
202 	else if (sub_dev == ADC) {
203 		data = sdr_in8(base0, REG_SB_CTRL);
204 		sdr_out8(base0, REG_SB_CTRL, data | 0x01);
205 	}
206 }
207 
208 /* Read and clear interrupt stats (### READ_CLEAR_INTR_STS ###)
209  * -- Return interrupt status */
210 static u32_t dev_read_clear_intr_status(u32_t *base) {
211 	u32_t status, base0 = base[0];
212 	status = sdr_in32(base0, REG_INTR_STS);
213 	if (status & INTR_STS_ADC) {
214 		sdr_in8(base0, 0x1e);
215 		sdr_in8(base0, 0x1f);
216 	}
217 	return status;
218 }
219 
220 /* Enable or disable interrupt (### INTR_ENABLE_DISABLE ###) */
221 static void dev_intr_enable(u32_t *base, int flag) {
222 	u32_t data, base0 = base[0];
223 	data = sdr_in32(base0, REG_INTR_CTRL_A);
224 	data &= 0xfffe;
225 	if (flag == INTR_ENABLE)
226 		data |= 0x01;
227 	sdr_out32(base0, REG_ADDR_INT_A, 1);
228 	sdr_out32(base0, REG_INTR_CTRL_A, data);
229 }
230 
231 /* ======= Common driver function ======= */
232 /* Probe the device */
233 static int dev_probe(void) {
234 	int devind, i, ioflag;
235 	u32_t device, bar, size, base;
236 	u16_t vid, did, temp;
237 	u8_t *reg;
238 
239 	pci_init();
240 	device = pci_first_dev(&devind, &vid, &did);
241 	while (device > 0) {
242 		if (vid == VENDOR_ID && did == DEVICE_ID)
243 			break;
244 		device = pci_next_dev(&devind, &vid, &did);
245 	}
246 	if (vid != VENDOR_ID || did != DEVICE_ID)
247 		return EIO;
248 	pci_reserve(devind);
249 
250 	for (i = 0; i < 6; i++)
251 		dev.base[i] = 0;
252 #ifdef DMA_BASE_IOMAP
253 	for (i = 0; i < 6; i++) {
254 		if (pci_get_bar(devind, PCI_BAR + i * 4, &base, &size, &ioflag)) {
255 			/* printf("SDR: Fail to get PCI BAR %d\n", i); */
256 			continue;
257 		}
258 		if (ioflag) {
259 			/* printf("SDR: PCI BAR %d is not for memory\n", i); */
260 			continue;
261 		}
262 		if ((reg = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED) {
263 			printf("SDR: Fail to map hardware registers from PCI\n");
264 			return -EIO;
265 		}
266 		dev.base[i] = (u32_t)reg;
267 	}
268 #else
269 	/* Get PCI BAR0-5 */
270 	for (i = 0; i < 6; i++)
271 		dev.base[i] = pci_attr_r32(devind, PCI_BAR + i * 4) & 0xffffffe0;
272 #endif
273 	dev.name = pci_dev_name(vid, did);
274 	dev.irq = pci_attr_r8(devind, PCI_ILR);
275 	dev.revision = pci_attr_r8(devind, PCI_REV);
276 	dev.did = did;
277 	dev.vid = vid;
278 	dev.devind = devind;
279 	temp = pci_attr_r16(devind, PCI_CR);
280 	pci_attr_w16(devind, PCI_CR, temp | 0x105);
281 
282 #ifdef MY_DEBUG
283 	printf("SDR: Hardware name is %s\n", dev.name);
284 	for (i = 0; i < 6; i++)
285 		printf("SDR: PCI BAR%d is 0x%08x\n", i, dev.base[i]);
286 	printf("SDR: IRQ number is 0x%02x\n", dev.irq);
287 #endif
288 	return OK;
289 }
290 
291 /* Set sample rate in configuration */
292 static int set_sample_rate(u32_t rate, int num) {
293 	aud_conf[num].sample_rate = rate;
294 	return OK;
295 }
296 
297 /* Set stereo in configuration */
298 static int set_stereo(u32_t stereo, int num) {
299 	aud_conf[num].stereo = stereo;
300 	return OK;
301 }
302 
303 /* Set sample bits in configuration */
304 static int set_bits(u32_t bits, int num) {
305 	aud_conf[num].nr_of_bits = bits;
306 	return OK;
307 }
308 
309 /* Set fragment size in configuration */
310 static int set_frag_size(u32_t frag_size, int num) {
311 	if (frag_size > (sub_dev[num].DmaSize / sub_dev[num].NrOfDmaFragments) ||
312 		frag_size < sub_dev[num].MinFragmentSize) {
313 		return EINVAL;
314 	}
315 	aud_conf[num].fragment_size = frag_size;
316 	return OK;
317 }
318 
319 /* Set frame sign in configuration */
320 static int set_sign(u32_t val, int num) {
321 	aud_conf[num].sign = val;
322 	return OK;
323 }
324 
325 /* Get maximum fragment size */
326 static int get_max_frag_size(u32_t *val, int *len, int num) {
327 	*len = sizeof(*val);
328 	*val = (sub_dev[num].DmaSize / sub_dev[num].NrOfDmaFragments);
329 	return OK;
330 }
331 
332 /* Return 1 if there are free buffers */
333 static int free_buf(u32_t *val, int *len, int num) {
334 	*len = sizeof(*val);
335 	if (sub_dev[num].BufLength == sub_dev[num].NrOfExtraBuffers)
336 		*val = 0;
337 	else
338 		*val = 1;
339 	return OK;
340 }
341 
342 /* Get the current sample counter */
343 static int get_samples_in_buf(u32_t *result, int *len, int chan) {
344 	u32_t res;
345 	/* READ_DMA_CURRENT_ADDR */
346 	res = dev_read_dma_current(dev.base, chan);
347 	*result = (u32_t)(sub_dev[chan].BufLength * 8192) + res;
348 	return OK;
349 }
350 
351 /* ======= [Audio interface] Initialize data structure ======= */
352 int drv_init(void) {
353 	drv.DriverName = DRIVER_NAME;
354 	drv.NrOfSubDevices = 3;
355 	drv.NrOfSpecialFiles = 3;
356 
357 	sub_dev[DAC].readable = 0;
358 	sub_dev[DAC].writable = 1;
359 	sub_dev[DAC].DmaSize = 64 * 1024;
360 	sub_dev[DAC].NrOfDmaFragments = 2;
361 	sub_dev[DAC].MinFragmentSize = 1024;
362 	sub_dev[DAC].NrOfExtraBuffers = 4;
363 
364 	sub_dev[ADC].readable = 1;
365 	sub_dev[ADC].writable = 0;
366 	sub_dev[ADC].DmaSize = 64 * 1024;
367 	sub_dev[ADC].NrOfDmaFragments = 2;
368 	sub_dev[ADC].MinFragmentSize = 1024;
369 	sub_dev[ADC].NrOfExtraBuffers = 4;
370 
371 	sub_dev[MIX].writable = 0;
372 	sub_dev[MIX].readable = 0;
373 
374 	special_file[0].minor_dev_nr = 0;
375 	special_file[0].write_chan = DAC;
376 	special_file[0].read_chan = NO_CHANNEL;
377 	special_file[0].io_ctl = DAC;
378 
379 	special_file[1].minor_dev_nr = 1;
380 	special_file[1].write_chan = NO_CHANNEL;
381 	special_file[1].read_chan = ADC;
382 	special_file[1].io_ctl = ADC;
383 
384 	special_file[2].minor_dev_nr = 2;
385 	special_file[2].write_chan = NO_CHANNEL;
386 	special_file[2].read_chan = NO_CHANNEL;
387 	special_file[2].io_ctl = MIX;
388 
389 	return OK;
390 }
391 
392 /* ======= [Audio interface] Initialize hardware ======= */
393 int drv_init_hw(void) {
394 	int i;
395 
396 	/* Match the device */
397 	if (dev_probe()) {
398 		printf("SDR: No sound card found\n");
399 		return EIO;
400 	}
401 
402 	/* Reset the device */
403 	/* ### RESET_HARDWARE_CAN_FAIL ### */
404 	if (dev_reset(dev.base)) {
405 		printf("SDR: Fail to reset the device\n");
406 		return EIO;
407 	}
408 
409 	/* Configure the hardware */
410 	/* ### CONF_HARDWARE ### */
411 	dev_configure(dev.base);
412 
413 	/* Initialize the mixer */
414 	/* ### INIT_MIXER ### */
415 	dev_init_mixer(dev.base);
416 
417 	/* Set default mixer volume */
418 	dev_set_default_volume(dev.base);
419 
420 	/* Initialize subdevice data */
421 	for (i = 0; i < drv.NrOfSubDevices; i++) {
422 		if (i == MIX)
423 			continue;
424 		aud_conf[i].busy = 0;
425 		aud_conf[i].stereo = 1;
426 		aud_conf[i].sample_rate = 44100;
427 		aud_conf[i].nr_of_bits = 16;
428 		aud_conf[i].sign = 1;
429 		aud_conf[i].fragment_size =
430 			sub_dev[i].DmaSize / sub_dev[i].NrOfDmaFragments;
431 	}
432 	return OK;
433 }
434 
435 /* ======= [Audio interface] Driver reset =======*/
436 int drv_reset(void) {
437 	/* ### RESET_HARDWARE_CAN_FAIL ### */
438 	return dev_reset(dev.base);
439 }
440 
441 /* ======= [Audio interface] Driver start ======= */
442 int drv_start(int sub_dev, int DmaMode) {
443 	int sample_count;
444 
445 	/* Set DAC and ADC sample rate */
446 	/* ### SET_SAMPLE_RATE ### */
447 	dev_set_sample_rate(dev.base, aud_conf[sub_dev].sample_rate);
448 
449 	sample_count = aud_conf[sub_dev].fragment_size;
450 #ifdef DMA_LENGTH_BY_FRAME
451 	sample_count = sample_count / (aud_conf[sub_dev].nr_of_bits * (aud_conf[sub_dev].stereo + 1) / 8);
452 #endif
453 	/* Set DAC and ADC format */
454 	/* ### SET_FORMAT ### */
455 	dev_set_format(dev.base, aud_conf[sub_dev].nr_of_bits,
456 			aud_conf[sub_dev].sign, aud_conf[sub_dev].stereo, sample_count);
457 
458 	drv_reenable_int(sub_dev);
459 
460 	/* Start the channel */
461 	/* ### START_CHANNEL ### */
462 	dev_start_channel(dev.base, sub_dev);
463 	aud_conf[sub_dev].busy = 1;
464 
465 	return OK;
466 }
467 
468 /* ======= [Audio interface] Driver start ======= */
469 int drv_stop(int sub_dev) {
470 	u32_t data;
471 
472 	/* INTR_ENABLE_DISABLE */
473 	dev_intr_enable(dev.base, INTR_DISABLE);
474 
475 	/* ### STOP_CHANNEL ### */
476 	dev_stop_channel(dev.base, sub_dev);
477 
478 	aud_conf[sub_dev].busy = 0;
479 	return OK;
480 }
481 
482 /* ======= [Audio interface] Enable interrupt ======= */
483 int drv_reenable_int(int chan) {
484 	/* INTR_ENABLE_DISABLE */
485 	dev_intr_enable(dev.base, INTR_ENABLE);
486 	return OK;
487 }
488 
489 /* ======= [Audio interface] I/O control ======= */
490 int drv_io_ctl(unsigned long request, void *val, int *len, int sub_dev) {
491 	int status;
492 	switch (request) {
493 		case DSPIORATE:
494 			status = set_sample_rate(*((u32_t *)val), sub_dev);
495 			break;
496 		case DSPIOSTEREO:
497 			status = set_stereo(*((u32_t *)val), sub_dev);
498 			break;
499 		case DSPIOBITS:
500 			status = set_bits(*((u32_t *)val), sub_dev);
501 			break;
502 		case DSPIOSIZE:
503 			status = set_frag_size(*((u32_t *)val), sub_dev);
504 			break;
505 		case DSPIOSIGN:
506 			status = set_sign(*((u32_t *)val), sub_dev);
507 			break;
508 		case DSPIOMAX:
509 			status = get_max_frag_size(val, len, sub_dev);
510 			break;
511 		case DSPIORESET:
512 			status = drv_reset();
513 			break;
514 		case DSPIOFREEBUF:
515 			status = free_buf(val, len, sub_dev);
516 			break;
517 		case DSPIOSAMPLESINBUF:
518 			status = get_samples_in_buf(val, len, sub_dev);
519 			break;
520 		case DSPIOPAUSE:
521 			status = drv_pause(sub_dev);
522 			break;
523 		case DSPIORESUME:
524 			status = drv_resume(sub_dev);
525 			break;
526 		case MIXIOGETVOLUME:
527 			/* ### GET_SET_VOLUME ### */
528 			status = get_set_volume(dev.base, val, GET_VOL);
529 			break;
530 		case MIXIOSETVOLUME:
531 			/* ### GET_SET_VOLUME ### */
532 			status = get_set_volume(dev.base, val, SET_VOL);
533 			break;
534 		default:
535 			status = EINVAL;
536 			break;
537 	}
538 	return status;
539 }
540 
541 /* ======= [Audio interface] Get request number ======= */
542 int drv_get_irq(char *irq) {
543 	*irq = dev.irq;
544 	return OK;
545 }
546 
547 /* ======= [Audio interface] Get fragment size ======= */
548 int drv_get_frag_size(u32_t *frag_size, int sub_dev) {
549 	*frag_size = aud_conf[sub_dev].fragment_size;
550 	return OK;
551 }
552 
553 /* ======= [Audio interface] Set DMA channel ======= */
554 int drv_set_dma(u32_t dma, u32_t length, int chan) {
555 #ifdef DMA_LENGTH_BY_FRAME
556 	length = length / (aud_conf[chan].nr_of_bits * (aud_conf[chan].stereo + 1) / 8);
557 #endif
558 	/* ### SET_DMA ### */
559 	dev_set_dma(dev.base, dma, length, chan);
560 	return OK;
561 }
562 
563 /* ======= [Audio interface] Get interrupt summary status ======= */
564 int drv_int_sum(void) {
565 	u32_t status;
566 	/* ### READ_CLEAR_INTR_STS ### */
567 	status = dev_read_clear_intr_status(dev.base);
568 	dev.intr_status = status;
569 #ifdef MY_DEBUG
570 	printf("SDR: Interrupt status is 0x%08x\n", status);
571 #endif
572 	return (status & (INTR_STS_DAC | INTR_STS_ADC));
573 }
574 
575 /* ======= [Audio interface] Handle interrupt status ======= */
576 int drv_int(int sub_dev) {
577 	u32_t mask;
578 
579 	/* ### CHECK_INTR_DAC ### */
580 	if (sub_dev == DAC)
581 		mask = INTR_STS_DAC;
582 	/* ### CHECK_INTR_ADC ### */
583 	else if (sub_dev == ADC)
584 		mask = INTR_STS_ADC;
585 	else
586 		return 0;
587 
588 	return dev.intr_status & mask;
589 }
590 
591 /* ======= [Audio interface] Pause DMA ======= */
592 int drv_pause(int sub_dev) {
593 	/* ### PAUSE_DMA ### */
594 	dev_pause_dma(dev.base, sub_dev);
595 	return OK;
596 }
597 
598 /* ======= [Audio interface] Resume DMA ======= */
599 int drv_resume(int sub_dev) {
600 	/* ### RESUME_DMA ### */
601 	dev_resume_dma(dev.base, sub_dev);
602 	return OK;
603 }
604