xref: /haiku/src/add-ons/kernel/drivers/audio/ac97/es1370/es1370.c (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
1 /*
2  * ES1370 Haiku Driver for ES1370 audio
3  *
4  * Copyright 2002-2007, Haiku, Inc.
5  * Distributed under the terms of the MIT License.
6  *
7  * Authors:
8  *		Jerome Duval, jerome.duval@free.fr
9  */
10 
11 #include <KernelExport.h>
12 #include <PCI.h>
13 #include <driver_settings.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "es1370.h"
18 #include "debug.h"
19 #include "config.h"
20 #include "util.h"
21 #include "io.h"
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <malloc.h>
25 
26 status_t init_hardware(void);
27 status_t init_driver(void);
28 void uninit_driver(void);
29 const char ** publish_devices(void);
30 device_hooks * find_device(const char *);
31 status_t es1370_init(es1370_dev * card);
32 
33 static char pci_name[] = B_PCI_MODULE_NAME;
34 pci_module_info	*pci;
35 
36 int32 num_cards;
37 es1370_dev cards[NUM_CARDS];
38 int32 num_names;
39 char * names[NUM_CARDS*20+1];
40 
41 extern device_hooks multi_hooks;
42 
43 es1370_settings current_settings = {
44 	44100,	// sample rate
45 	512,	// buffer frames
46 	2,	// buffer count
47 };
48 
49 
50 /* es1370 Memory management */
51 
52 static es1370_mem *
53 es1370_mem_new(es1370_dev *card, size_t size)
54 {
55 	es1370_mem *mem;
56 
57 	if ((mem = malloc(sizeof(*mem))) == NULL)
58 		return (NULL);
59 
60 	mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "es1370 buffer");
61 	mem->size = size;
62 	if (mem->area < B_OK) {
63 		free(mem);
64 		return NULL;
65 	}
66 	return mem;
67 }
68 
69 static void
70 es1370_mem_delete(es1370_mem *mem)
71 {
72 	if(mem->area > B_OK)
73 		delete_area(mem->area);
74 	free(mem);
75 }
76 
77 static void *
78 es1370_mem_alloc(es1370_dev *card, size_t size)
79 {
80 	es1370_mem *mem;
81 
82 	mem = es1370_mem_new(card, size);
83 	if (mem == NULL)
84 		return (NULL);
85 
86 	LIST_INSERT_HEAD(&(card->mems), mem, next);
87 
88 	return mem;
89 }
90 
91 static void
92 es1370_mem_free(es1370_dev *card, void *ptr)
93 {
94 	es1370_mem 		*mem;
95 
96 	LIST_FOREACH(mem, &card->mems, next) {
97 		if (mem->log_base != ptr)
98 			continue;
99 		LIST_REMOVE(mem, next);
100 
101 		es1370_mem_delete(mem);
102 		break;
103 	}
104 }
105 
106 /*	es1370 stream functions */
107 
108 status_t
109 es1370_stream_set_audioparms(es1370_stream *stream, uint8 channels,
110      uint8 b16, uint32 sample_rate)
111 {
112 	uint8 			sample_size, frame_size;
113 	LOG(("es1370_stream_set_audioparms\n"));
114 
115 	if ((stream->channels == channels) &&
116 		(stream->b16 == b16) &&
117 		(stream->sample_rate == sample_rate))
118 		return B_OK;
119 
120 	if(stream->buffer)
121 		es1370_mem_free(stream->card, stream->buffer->log_base);
122 
123 	stream->b16 = b16;
124 	stream->sample_rate = sample_rate;
125 	stream->channels = channels;
126 
127 	sample_size = stream->b16 + 1;
128 	frame_size = sample_size * stream->channels;
129 
130 	stream->buffer = es1370_mem_alloc(stream->card, stream->bufframes * frame_size * stream->bufcount);
131 
132 	stream->trigblk = 0;	/* This shouldn't be needed */
133 	stream->blkmod = stream->bufcount;
134 	stream->blksize = stream->bufframes * frame_size;
135 
136 	return B_OK;
137 }
138 
139 status_t
140 es1370_stream_commit_parms(es1370_stream *stream)
141 {
142 	uint8 			sample_size, frame_size;
143 	uint32	ctrl;
144 	es1370_dev *card = stream->card;
145 	LOG(("es1370_stream_commit_parms\n"));
146 
147 	ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL) & ~CTRL_PCLKDIV;
148 	ctrl |= DAC2_SRTODIV((uint16)stream->sample_rate) << CTRL_SH_PCLKDIV;
149 	es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl);
150 
151 	sample_size = stream->b16 + 1;
152 	frame_size = sample_size * stream->channels;
153 
154 	if (stream->use & ES1370_USE_RECORD) {
155 		es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, 0xd);
156 		es1370_reg_write_32(&card->config, ES1370_REG_ADC_FRAMEADR & 0xff, (uint32)stream->buffer->phy_base);
157 		es1370_reg_write_32(&card->config, ES1370_REG_ADC_FRAMECNT & 0xff, ((stream->blksize * stream->bufcount) >> 2) - 1);
158 		es1370_reg_write_32(&card->config, ES1370_REG_ADC_SCOUNT & 0xff, stream->bufframes - 1);
159 	} else {
160 		es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, 0xc);
161 		es1370_reg_write_32(&card->config, ES1370_REG_DAC2_FRAMEADR & 0xff, (uint32)stream->buffer->phy_base);
162 		es1370_reg_write_32(&card->config, ES1370_REG_DAC2_FRAMECNT & 0xff, ((stream->blksize * stream->bufcount) >> 2) - 1);
163 		es1370_reg_write_32(&card->config, ES1370_REG_DAC2_SCOUNT & 0xff, stream->bufframes - 1);
164 		LOG(("es1370_stream_commit_parms %" B_PRId32 " %" B_PRId32 "\n",
165 			((stream->blksize * stream->bufcount) >> 2) - 1,
166 			(stream->blksize / frame_size) - 1));
167 	}
168 
169 	return B_OK;
170 }
171 
172 status_t
173 es1370_stream_get_nth_buffer(es1370_stream *stream, uint8 chan, uint8 buf,
174 					char** buffer, size_t *stride)
175 {
176 	uint8 			sample_size, frame_size;
177 	LOG(("es1370_stream_get_nth_buffer\n"));
178 
179 	sample_size = stream->b16 + 1;
180 	frame_size = sample_size * stream->channels;
181 
182 	*buffer = (char *)stream->buffer->log_base
183 		+ (buf * stream->bufframes * frame_size) + chan * sample_size;
184 	*stride = frame_size;
185 
186 	return B_OK;
187 }
188 
189 static uint32
190 es1370_stream_curaddr(es1370_stream *stream)
191 {
192 	es1370_dev *card = stream->card;
193 	uint32 reg = 0, cnt = 0;
194 	if (stream->use & ES1370_USE_RECORD) {
195 		reg = ES1370_REG_ADC_FRAMECNT;
196 	} else {
197 		reg = ES1370_REG_DAC2_FRAMECNT;
198 	}
199 	es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, reg >> 8);
200 	cnt = es1370_reg_read_32(&card->config, reg & 0xff) >> 16;
201 	//TRACE(("stream_curaddr %lx\n", (cnt << 2) / stream->blksize));
202 	return (cnt << 2) / stream->blksize;
203 }
204 
205 void
206 es1370_stream_start(es1370_stream *stream, void (*inth) (void *), void *inthparam)
207 {
208 	uint32 sctrl = 0, ctrl = 0;
209 	es1370_dev *card = stream->card;
210 	LOG(("es1370_stream_start\n"));
211 
212 	stream->inth = inth;
213 	stream->inthparam = inthparam;
214 
215 	stream->state |= ES1370_STATE_STARTED;
216 
217 	sctrl = es1370_reg_read_32(&card->config, ES1370_REG_SERIAL_CONTROL);
218 	ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL);
219 
220 	if (stream->use & ES1370_USE_RECORD) {
221 		sctrl &= ~(SCTRL_R1SEB | SCTRL_R1SMB);
222 		if (stream->b16)
223 			sctrl |= SCTRL_R1SEB;
224 		if (stream->channels == 2)
225 			sctrl |= SCTRL_R1SMB;
226 		es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_R1INTEN);
227 		es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_R1INTEN);
228 
229 		ctrl |= CTRL_ADC_EN;
230 	} else {
231 		sctrl &= ~(SCTRL_P2SEB | SCTRL_P2SMB | 0x003f0000);
232 		if (stream->b16)
233 			sctrl |= SCTRL_P2SEB;
234 		if (stream->channels == 2)
235 			sctrl |= SCTRL_P2SMB;
236 		sctrl |= (stream->b16 + 1) << SCTRL_SH_P2ENDINC;
237 		es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_P2INTEN);
238 		es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_P2INTEN);
239 
240 		ctrl |= CTRL_DAC2_EN;
241 	}
242 
243 	es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl);
244 	es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl);
245 
246 #ifdef DEBUG
247 	//dump_hardware_regs(&stream->card->config);
248 #endif
249 }
250 
251 void
252 es1370_stream_halt(es1370_stream *stream)
253 {
254 	uint32 ctrl;
255 	es1370_dev *card = stream->card;
256 	LOG(("es1370_stream_halt\n"));
257 
258 	stream->state &= ~ES1370_STATE_STARTED;
259 
260 	ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL);
261 	if (stream->use & ES1370_USE_RECORD)
262 		ctrl &= ~CTRL_ADC_EN;
263 	else
264 		ctrl &= ~CTRL_DAC2_EN;
265 	es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl);
266 }
267 
268 es1370_stream *
269 es1370_stream_new(es1370_dev *card, uint8 use, uint32 bufframes, uint8 bufcount)
270 {
271 	es1370_stream *stream;
272 	cpu_status status;
273 	LOG(("es1370_stream_new\n"));
274 
275 	stream = malloc(sizeof(es1370_stream));
276 	if (stream == NULL)
277 		return (NULL);
278 	stream->card = card;
279 	stream->use = use;
280 	stream->state = !ES1370_STATE_STARTED;
281 	stream->b16 = 0;
282 	stream->sample_rate = 0;
283 	stream->channels = 0;
284 	stream->bufframes = bufframes;
285 	stream->bufcount = bufcount;
286 	stream->inth = NULL;
287 	stream->inthparam = NULL;
288 	stream->buffer = NULL;
289 	stream->blksize = 0;
290 	stream->trigblk = 0;
291 	stream->blkmod = 0;
292 
293 	stream->buffer_cycle = 0;
294 	stream->frames_count = 0;
295 	stream->real_time = 0;
296 	stream->update_needed = false;
297 
298 	status = lock();
299 	LIST_INSERT_HEAD((&card->streams), stream, next);
300 	unlock(status);
301 
302 	return stream;
303 }
304 
305 void
306 es1370_stream_delete(es1370_stream *stream)
307 {
308 	cpu_status status;
309 	LOG(("es1370_stream_delete\n"));
310 
311 	es1370_stream_halt(stream);
312 
313 	if(stream->buffer)
314 		es1370_mem_free(stream->card, stream->buffer->log_base);
315 
316 	status = lock();
317 	LIST_REMOVE(stream, next);
318 	unlock(status);
319 
320 	free(stream);
321 }
322 
323 /* es1370 interrupt */
324 
325 static int32
326 es1370_int(void *arg)
327 {
328 	es1370_dev	 	*card = arg;
329 	bool 			gotone 	= false;
330 	uint32       	curblk;
331 	es1370_stream 	*stream = NULL;
332 	uint32		sta, sctrl;
333 
334 	// TRACE(("es1370_int(%p)\n", card));
335 
336 	sta = es1370_reg_read_32(&card->config, ES1370_REG_STATUS);
337 	if (sta & card->interrupt_mask) {
338 
339 		//TRACE(("interrupt !! %x\n", sta));
340 		sctrl = es1370_reg_read_32(&card->config, ES1370_REG_SERIAL_CONTROL);
341 
342 		LIST_FOREACH(stream, &card->streams, next) {
343 			if (stream->use & ES1370_USE_RECORD) {
344 				if ((sta & STAT_ADC) == 0)
345 					continue;
346 				es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_R1INTEN);
347 				es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_R1INTEN);
348 			} else {
349 				if ((sta & STAT_DAC2) == 0)
350 					continue;
351 				es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_P2INTEN);
352 				es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_P2INTEN);
353 			}
354 
355 			curblk = es1370_stream_curaddr(stream);
356 			// TRACE(("INTR at trigblk %lu, stream->trigblk %lu\n", curblk, stream->trigblk));
357 			if (curblk == stream->trigblk) {
358 				stream->trigblk++;
359 				stream->trigblk = stream->trigblk % stream->blkmod;
360 				if (stream->inth)
361 					stream->inth(stream->inthparam);
362 			}
363 			gotone = true;
364 		}
365 	} else {
366 		//TRACE(("interrupt masked %x, ", card->interrupt_mask));
367 		//TRACE(("sta %x\n", sta));
368 	}
369 
370 	if (gotone)
371 		return B_INVOKE_SCHEDULER;
372 
373 	//TRACE(("Got unhandled interrupt\n"));
374 	return B_UNHANDLED_INTERRUPT;
375 }
376 
377 
378 /*	es1370 driver functions */
379 
380 
381 /* detect presence of our hardware */
382 status_t
383 init_hardware(void)
384 {
385 	int ix=0;
386 	pci_info info;
387 	status_t err = ENODEV;
388 
389 	LOG_CREATE();
390 
391 	PRINT(("init_hardware()\n"));
392 
393 	if (get_module(pci_name, (module_info **)&pci))
394 		return ENOSYS;
395 
396 	while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
397 		if (info.vendor_id == 0x1274
398 			&& (info.device_id == 0x5000
399 			/*|| info.device_id == 0x1371
400 			|| info.device_id == 0x5880*/)
401 			)
402 		 {
403 			err = B_OK;
404 		}
405 		ix++;
406 	}
407 
408 	put_module(pci_name);
409 
410 	return err;
411 }
412 
413 static void
414 make_device_names(
415 	es1370_dev * card)
416 {
417 	sprintf(card->name, "audio/hmulti/es1370/%ld", card-cards+1);
418 	names[num_names++] = card->name;
419 
420 	names[num_names] = NULL;
421 }
422 
423 
424 status_t
425 es1370_init(es1370_dev * card)
426 {
427 	card->interrupt_mask = STAT_DAC2 | STAT_ADC;
428 
429 	/* Init streams list */
430 	LIST_INIT(&(card->streams));
431 
432 	/* Init mems list */
433 	LIST_INIT(&(card->mems));
434 
435 	return B_OK;
436 }
437 
438 static status_t
439 es1370_setup(es1370_dev * card)
440 {
441 	status_t err = B_OK;
442 	unsigned char cmd;
443 
444 	PRINT(("es1370_setup(%p)\n", card));
445 
446 	make_device_names(card);
447 
448 	card->config.base = card->info.u.h0.base_registers[0];
449 	card->config.irq = card->info.u.h0.interrupt_line;
450 	card->config.type = 0;
451 
452 	PRINT(("%s deviceid = %#04x chiprev = %x model = %x enhanced at %" B_PRIx32
453 		"\n", card->name, card->info.device_id, card->info.revision,
454 		card->info.u.h0.subsystem_id, card->config.base));
455 
456 	cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2);
457 	PRINT(("PCI command before: %x\n", cmd));
458 	(*pci->write_pci_config)(card->info.bus, card->info.device,
459 		card->info.function, PCI_command, 2,
460 		cmd | PCI_command_master | PCI_command_io);
461 	cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2);
462 	PRINT(("PCI command after: %x\n", cmd));
463 
464 	es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, SCTRL_P2INTEN | SCTRL_R1INTEN);
465 	es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, CTRL_CDC_EN);
466 
467 	/* reset the codec */
468 	PRINT(("codec reset\n"));
469 	es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x2);
470 	snooze (20);
471 	es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x3);
472 	snooze (20);
473 	es1370_codec_write(&card->config, CODEC_CLOCK_SEL, 0x0);
474 
475 	/* set max volume on master and mixer outputs */
476 	es1370_codec_write(&card->config, CODEC_MASTER_VOL_L, 0x0);
477 	es1370_codec_write(&card->config, CODEC_MASTER_VOL_R, 0x0);
478 	es1370_codec_write(&card->config, CODEC_VOICE_VOL_L, 0x0);
479 	es1370_codec_write(&card->config, CODEC_VOICE_VOL_R, 0x0);
480 
481 	/* unmute CD playback */
482 	es1370_codec_write(&card->config, CODEC_OUTPUT_MIX1, ES1370_OUTPUT_MIX1_CDL | ES1370_OUTPUT_MIX1_CDR);
483 	/* unmute mixer output */
484 	es1370_codec_write(&card->config, CODEC_OUTPUT_MIX2, ES1370_OUTPUT_MIX2_VOICEL | ES1370_OUTPUT_MIX2_VOICER);
485 
486 	snooze(50000); // 50 ms
487 
488 	PRINT(("installing interrupt : %" B_PRIu32 "\n", card->config.irq));
489 	err = install_io_interrupt_handler(card->config.irq, es1370_int, card, 0);
490 	if (err != B_OK) {
491 		PRINT(("failed to install interrupt\n"));
492 		return err;
493 	}
494 
495 	if ((err = es1370_init(card)))
496 		return (err);
497 
498 	PRINT(("init_driver done\n"));
499 
500 	return err;
501 }
502 
503 
504 status_t
505 init_driver(void)
506 {
507 	void *settings_handle;
508 	pci_info info;
509 	int ix = 0;
510 	status_t err;
511 	num_cards = 0;
512 
513 	PRINT(("init_driver()\n"));
514 
515 	// get driver settings
516 	settings_handle  = load_driver_settings ("es1370.settings");
517 	if (settings_handle != NULL) {
518 		const char *item;
519 		char       *end;
520 		uint32      value;
521 
522 		item = get_driver_parameter (settings_handle, "sample_rate", "44100", "44100");
523 		value = strtoul (item, &end, 0);
524 		if (*end == '\0') current_settings.sample_rate = value;
525 
526 		item = get_driver_parameter (settings_handle, "buffer_frames", "512", "512");
527 		value = strtoul (item, &end, 0);
528 		if (*end == '\0') current_settings.buffer_frames = value;
529 
530 		item = get_driver_parameter (settings_handle, "buffer_count", "2", "2");
531 		value = strtoul (item, &end, 0);
532 		if (*end == '\0') current_settings.buffer_count = value;
533 
534 		unload_driver_settings (settings_handle);
535 	}
536 
537 	if (get_module(pci_name, (module_info **) &pci))
538 		return ENOSYS;
539 
540 	while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) {
541 		if (info.vendor_id == 0x1274
542                         && (info.device_id == 0x5000
543                         /*|| info.device_id == 0x1371
544                         || info.device_id == 0x5880*/)
545 			) {
546 			if (num_cards == NUM_CARDS) {
547 				PRINT(("Too many es1370 cards installed!\n"));
548 				break;
549 			}
550 			memset(&cards[num_cards], 0, sizeof(es1370_dev));
551 			cards[num_cards].info = info;
552 #ifdef __HAIKU__
553 			if ((err = (*pci->reserve_device)(info.bus, info.device, info.function,
554 				DRIVER_NAME, &cards[num_cards])) < B_OK) {
555 				dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n",
556 					DRIVER_NAME, info.bus, info.device, info.function,
557 					strerror(err));
558 				continue;
559 			}
560 #endif
561 			if (es1370_setup(&cards[num_cards])) {
562 				PRINT(("Setup of es1370 %" B_PRId32 " failed\n", num_cards+1));
563 #ifdef __HAIKU__
564 				(*pci->unreserve_device)(info.bus, info.device, info.function,
565 					DRIVER_NAME, &cards[num_cards]);
566 #endif
567 			}
568 			else {
569 				num_cards++;
570 			}
571 		}
572 	}
573 	if (!num_cards) {
574 		PRINT(("no cards\n"));
575 		put_module(pci_name);
576 		PRINT(("no suitable cards found\n"));
577 		return ENODEV;
578 	}
579 
580 	return B_OK;
581 }
582 
583 
584 static void
585 es1370_shutdown(es1370_dev *card)
586 {
587 	PRINT(("shutdown(%p)\n", card));
588 	//ac97_amp_enable(&card->config, false);
589 	card->interrupt_mask = 0;
590 
591 	remove_io_interrupt_handler(card->config.irq, es1370_int, card);
592 }
593 
594 
595 void
596 uninit_driver(void)
597 {
598 	int ix, cnt = num_cards;
599 	num_cards = 0;
600 
601 	PRINT(("uninit_driver()\n"));
602 	for (ix=0; ix<cnt; ix++) {
603 		es1370_shutdown(&cards[ix]);
604 #ifdef __HAIKU__
605 		(*pci->unreserve_device)(cards[ix].info.bus,
606 			cards[ix].info.device, cards[ix].info.function,
607 			DRIVER_NAME, &cards[ix]);
608 #endif
609 	}
610 	memset(&cards, 0, sizeof(cards));
611 	put_module(pci_name);
612 }
613 
614 
615 const char **
616 publish_devices(void)
617 {
618 	int ix = 0;
619 	PRINT(("publish_devices()\n"));
620 
621 	for (ix=0; names[ix]; ix++) {
622 		PRINT(("publish %s\n", names[ix]));
623 	}
624 	return (const char **)names;
625 }
626 
627 
628 device_hooks *
629 find_device(const char * name)
630 {
631 	int ix;
632 
633 	PRINT(("find_device(%s)\n", name));
634 
635 	for (ix=0; ix<num_cards; ix++) {
636 		if (!strcmp(cards[ix].name, name)) {
637 			return &multi_hooks;
638 		}
639 	}
640 	PRINT(("find_device(%s) failed\n", name));
641 	return NULL;
642 }
643 
644 int32	api_version = B_CUR_DRIVER_API_VERSION;
645 
646