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