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", false);
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 %" 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
172status_t
173es1370_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
189static uint32
190es1370_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
205void
206es1370_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
251void
252es1370_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
268es1370_stream *
269es1370_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
305void
306es1370_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
325static int32
326es1370_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 */
382status_t
383init_hardware(void)
384{
385	int ix=0;
386	pci_info info;
387	status_t err = ENODEV;
388
389	if (get_module(pci_name, (module_info **)&pci))
390		return ENOSYS;
391
392	while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
393		if (info.vendor_id == 0x1274 && (info.device_id == 0x5000
394			/*|| info.device_id == 0x1371 || info.device_id == 0x5880*/))
395		{
396			LOG_CREATE();
397			PRINT(("init_hardware()\n"));
398
399			err = B_OK;
400		}
401		ix++;
402	}
403
404	put_module(pci_name);
405
406	return err;
407}
408
409static void
410make_device_names(
411	es1370_dev * card)
412{
413	sprintf(card->name, "audio/hmulti/es1370/%ld", card-cards+1);
414	names[num_names++] = card->name;
415
416	names[num_names] = NULL;
417}
418
419
420status_t
421es1370_init(es1370_dev * card)
422{
423	card->interrupt_mask = STAT_DAC2 | STAT_ADC;
424
425	/* Init streams list */
426	LIST_INIT(&(card->streams));
427
428	/* Init mems list */
429	LIST_INIT(&(card->mems));
430
431	return B_OK;
432}
433
434static status_t
435es1370_setup(es1370_dev * card)
436{
437	status_t err = B_OK;
438	unsigned char cmd;
439
440	PRINT(("es1370_setup(%p)\n", card));
441
442	make_device_names(card);
443
444	card->config.base = card->info.u.h0.base_registers[0];
445	card->config.irq = card->info.u.h0.interrupt_line;
446	card->config.type = 0;
447
448	PRINT(("%s deviceid = %#04x chiprev = %x model = %x enhanced at %" B_PRIx32
449		"\n", card->name, card->info.device_id, card->info.revision,
450		card->info.u.h0.subsystem_id, card->config.base));
451
452	cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2);
453	PRINT(("PCI command before: %x\n", cmd));
454	(*pci->write_pci_config)(card->info.bus, card->info.device,
455		card->info.function, PCI_command, 2,
456		cmd | PCI_command_master | PCI_command_io);
457	cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2);
458	PRINT(("PCI command after: %x\n", cmd));
459
460	es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, SCTRL_P2INTEN | SCTRL_R1INTEN);
461	es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, CTRL_CDC_EN);
462
463	/* reset the codec */
464	PRINT(("codec reset\n"));
465	es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x2);
466	snooze (20);
467	es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x3);
468	snooze (20);
469	es1370_codec_write(&card->config, CODEC_CLOCK_SEL, 0x0);
470
471	/* set max volume on master and mixer outputs */
472	es1370_codec_write(&card->config, CODEC_MASTER_VOL_L, 0x0);
473	es1370_codec_write(&card->config, CODEC_MASTER_VOL_R, 0x0);
474	es1370_codec_write(&card->config, CODEC_VOICE_VOL_L, 0x0);
475	es1370_codec_write(&card->config, CODEC_VOICE_VOL_R, 0x0);
476
477	/* unmute CD playback */
478	es1370_codec_write(&card->config, CODEC_OUTPUT_MIX1, ES1370_OUTPUT_MIX1_CDL | ES1370_OUTPUT_MIX1_CDR);
479	/* unmute mixer output */
480	es1370_codec_write(&card->config, CODEC_OUTPUT_MIX2, ES1370_OUTPUT_MIX2_VOICEL | ES1370_OUTPUT_MIX2_VOICER);
481
482	snooze(50000); // 50 ms
483
484	PRINT(("installing interrupt : %" B_PRIu32 "\n", card->config.irq));
485	err = install_io_interrupt_handler(card->config.irq, es1370_int, card, 0);
486	if (err != B_OK) {
487		PRINT(("failed to install interrupt\n"));
488		return err;
489	}
490
491	if ((err = es1370_init(card)))
492		return (err);
493
494	PRINT(("init_driver done\n"));
495
496	return err;
497}
498
499
500status_t
501init_driver(void)
502{
503	void *settings_handle;
504	pci_info info;
505	int ix = 0;
506	status_t err;
507	num_cards = 0;
508
509	PRINT(("init_driver()\n"));
510
511	// get driver settings
512	settings_handle  = load_driver_settings ("es1370.settings");
513	if (settings_handle != NULL) {
514		const char *item;
515		char       *end;
516		uint32      value;
517
518		item = get_driver_parameter (settings_handle, "sample_rate", "44100", "44100");
519		value = strtoul (item, &end, 0);
520		if (*end == '\0') current_settings.sample_rate = value;
521
522		item = get_driver_parameter (settings_handle, "buffer_frames", "512", "512");
523		value = strtoul (item, &end, 0);
524		if (*end == '\0') current_settings.buffer_frames = value;
525
526		item = get_driver_parameter (settings_handle, "buffer_count", "2", "2");
527		value = strtoul (item, &end, 0);
528		if (*end == '\0') current_settings.buffer_count = value;
529
530		unload_driver_settings (settings_handle);
531	}
532
533	if (get_module(pci_name, (module_info **) &pci))
534		return ENOSYS;
535
536	while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) {
537		if (info.vendor_id == 0x1274
538                        && (info.device_id == 0x5000
539                        /*|| info.device_id == 0x1371
540                        || info.device_id == 0x5880*/)
541			) {
542			if (num_cards == NUM_CARDS) {
543				PRINT(("Too many es1370 cards installed!\n"));
544				break;
545			}
546			memset(&cards[num_cards], 0, sizeof(es1370_dev));
547			cards[num_cards].info = info;
548#ifdef __HAIKU__
549			if ((err = (*pci->reserve_device)(info.bus, info.device, info.function,
550				DRIVER_NAME, &cards[num_cards])) < B_OK) {
551				dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n",
552					DRIVER_NAME, info.bus, info.device, info.function,
553					strerror(err));
554				continue;
555			}
556#endif
557			if (es1370_setup(&cards[num_cards])) {
558				PRINT(("Setup of es1370 %" B_PRId32 " failed\n", num_cards+1));
559#ifdef __HAIKU__
560				(*pci->unreserve_device)(info.bus, info.device, info.function,
561					DRIVER_NAME, &cards[num_cards]);
562#endif
563			}
564			else {
565				num_cards++;
566			}
567		}
568	}
569	if (!num_cards) {
570		PRINT(("no cards\n"));
571		put_module(pci_name);
572		PRINT(("no suitable cards found\n"));
573		return ENODEV;
574	}
575
576	return B_OK;
577}
578
579
580static void
581es1370_shutdown(es1370_dev *card)
582{
583	PRINT(("shutdown(%p)\n", card));
584	//ac97_amp_enable(&card->config, false);
585	card->interrupt_mask = 0;
586
587	remove_io_interrupt_handler(card->config.irq, es1370_int, card);
588}
589
590
591void
592uninit_driver(void)
593{
594	int ix, cnt = num_cards;
595	num_cards = 0;
596
597	PRINT(("uninit_driver()\n"));
598	for (ix=0; ix<cnt; ix++) {
599		es1370_shutdown(&cards[ix]);
600#ifdef __HAIKU__
601		(*pci->unreserve_device)(cards[ix].info.bus,
602			cards[ix].info.device, cards[ix].info.function,
603			DRIVER_NAME, &cards[ix]);
604#endif
605	}
606	memset(&cards, 0, sizeof(cards));
607	put_module(pci_name);
608}
609
610
611const char **
612publish_devices(void)
613{
614	int ix = 0;
615	PRINT(("publish_devices()\n"));
616
617	for (ix=0; names[ix]; ix++) {
618		PRINT(("publish %s\n", names[ix]));
619	}
620	return (const char **)names;
621}
622
623
624device_hooks *
625find_device(const char * name)
626{
627	int ix;
628
629	PRINT(("find_device(%s)\n", name));
630
631	for (ix=0; ix<num_cards; ix++) {
632		if (!strcmp(cards[ix].name, name)) {
633			return &multi_hooks;
634		}
635	}
636	PRINT(("find_device(%s) failed\n", name));
637	return NULL;
638}
639
640int32	api_version = B_CUR_DRIVER_API_VERSION;
641
642