1/*
2 * Copyright 2004-2015 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Jérôme Duval, jerome.duval@free.fr
7 *		Marcus Overhagen, marcus@overhagen.de
8 *		Jérôme Lévêque, leveque.jerome@gmail.com
9 */
10
11
12#include "ice1712.h"
13#include "ice1712_reg.h"
14#include "io.h"
15#include "multi.h"
16#include "util.h"
17
18#include <KernelExport.h>
19#include <Drivers.h>
20#include <OS.h>
21#include <midi_driver.h>
22#include <drivers/driver_settings.h>
23
24#include <fcntl.h>
25#include <stdlib.h>
26#include <string.h>
27
28static status_t ice1712Settings_load(ice1712 *card);
29status_t ice1712Settings_apply(ice1712 *card);
30static int32 ice1712HW_interrupt(void *arg);
31static status_t ice1712HW_setup(ice1712 *ice);
32static void ice1712HW_shutdown(ice1712 *ice);
33
34extern device_hooks ice1712Midi_hooks;
35extern device_hooks ice1712Audio_hooks;
36void ice1712Midi_interrupt(int32 op, void *data);
37
38pci_module_info *pci;
39generic_mpu401_module *mpu401;
40
41int32 num_cards = 0;
42ice1712 cards[NUM_CARDS];
43
44//3 interfaces (2 midi + 1 audio) can be defined for each card
45static char *names[NUM_CARDS*3+1];
46static int32 num_names = 0;
47
48#define HMULTI_AUDIO_DEV_PATH "audio/hmulti/ice1712"
49
50//Haiku Driver API
51//----------------
52
53int32 api_version = B_CUR_DRIVER_API_VERSION;
54
55extern "C" status_t
56init_hardware(void)
57{
58	int ix = 0;
59	pci_info info;
60
61	memset(cards, 0, sizeof(ice1712) * NUM_CARDS);
62	ITRACE("@@ init_hardware()\n");
63
64	if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci))
65		return ENOSYS;
66
67	while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
68		if ((info.vendor_id == ICE1712_VENDOR_ID)
69			&& (info.device_id == ICE1712_DEVICE_ID)) {
70			ITRACE("Found at least 1 card\n");
71			put_module(B_PCI_MODULE_NAME);
72			return B_OK;
73		}
74		ix++;
75	}
76	put_module(B_PCI_MODULE_NAME);
77	return ENODEV;
78}
79
80
81extern "C" status_t
82init_driver(void)
83{
84	int i = 0;
85	status_t err;
86	num_cards = 0;
87
88	ITRACE("@@ init_driver()\n");
89
90	if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci))
91		return ENOSYS;
92
93	if (get_module(B_MPU_401_MODULE_NAME, (module_info **) &mpu401)) {
94		put_module(B_PCI_MODULE_NAME);
95		return ENOSYS;
96	}
97
98	while ((*pci->get_nth_pci_info)(i, &cards[num_cards].info) == B_OK) {
99		//TODO check other Vendor_ID and DEVICE_ID
100		if ((cards[num_cards].info.vendor_id == ICE1712_VENDOR_ID)
101			&& (cards[num_cards].info.device_id == ICE1712_DEVICE_ID)) {
102			if (num_cards == NUM_CARDS) {
103				ITRACE("Too many ice1712 cards installed!\n");
104				break;
105			}
106
107			if ((err = (*pci->reserve_device)(cards[num_cards].info.bus,
108				cards[num_cards].info.device,
109				cards[num_cards].info.function,
110				DRIVER_NAME, &cards[num_cards])) < B_OK) {
111				ITRACE_VV("%s: failed to reserve_device(%d, %d, %d,): %s\n",
112					DRIVER_NAME, cards[num_cards].info.bus,
113					cards[num_cards].info.device,
114					cards[num_cards].info.function, strerror(err));
115				continue;
116			}
117
118			ice1712Settings_load(&cards[num_cards]);
119
120			if (ice1712HW_setup(&cards[num_cards]) != B_OK) {
121			//Vendor_ID and Device_ID has been modified
122				ITRACE("Setup of ice1712 %" B_PRIu32 " failed\n", num_cards + 1);
123				(*pci->unreserve_device)(cards[num_cards].info.bus,
124					cards[num_cards].info.device,
125					cards[num_cards].info.function,
126					DRIVER_NAME, &cards[num_cards]);
127			} else {
128				num_cards++;
129			}
130		}
131		i++;
132	}
133
134	ITRACE("Succesfully initialised card : %" B_PRIu32 "\n", num_cards);
135
136	if (num_cards == 0) {
137		put_module(B_PCI_MODULE_NAME);
138		put_module(B_MPU_401_MODULE_NAME);
139		return ENODEV;
140	}
141	return B_OK;
142}
143
144
145extern "C" void
146uninit_driver(void)
147{
148	int ix, cnt = num_cards;
149
150	ITRACE("@@ uninit_driver()\n");
151
152	num_cards = 0;
153
154	for (ix = 0; ix < cnt; ix++) {
155		ice1712HW_shutdown(&cards[ix]);
156		(*pci->unreserve_device)(cards[ix].info.bus,
157			cards[ix].info.device, cards[ix].info.function,
158			DRIVER_NAME, &cards[ix]);
159	}
160	memset(&cards, 0, sizeof(cards));
161	put_module(B_MPU_401_MODULE_NAME);
162	put_module(B_PCI_MODULE_NAME);
163}
164
165
166extern "C" const char **
167publish_devices(void)
168{
169	int ix = 0;
170	ITRACE("@@ publish_devices()\n");
171
172	for (ix = 0; names[ix]; ix++) {
173		ITRACE("publish %s\n", names[ix]);
174	}
175	return (const char **)names;
176}
177
178
179extern "C" device_hooks *
180find_device(const char * name)
181{
182	int ix, midi;
183
184	ITRACE("@@ find_device()\n");
185
186	for (ix = 0; ix < num_cards; ix++) {
187		for (midi = 0; midi < MAX_MIDI_INTERFACE; midi++) {
188			if (!strcmp(cards[ix].midiItf[midi].name, name)) {
189				return &ice1712Midi_hooks;
190			}
191		}
192
193		if (!strcmp(cards[ix].name, name)) {
194			return &ice1712Audio_hooks;
195		}
196	}
197	ITRACE("!!! failed !!!\n");
198	return NULL;
199}
200
201//ICE1712 driver - Hardware
202//-------------------------
203
204int32
205ice1712HW_interrupt(void *arg)
206{
207	ice1712 *ice = (ice1712*)arg;
208	uint8 reg8 = 0;
209	uint16 reg16 = 0;
210	uint32 status = B_UNHANDLED_INTERRUPT;
211
212	// interrupt from DMA PATH
213	reg8 = read_mt_uint8(ice, MT_DMA_INT_MASK_STATUS);
214	if (reg8 != 0) {
215		ice->buffer++;
216		ice->played_time = system_time();
217		ice->frames_count += ice->buffer_size;
218
219		release_sem_etc(ice->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
220		write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, reg8);
221		status = B_HANDLED_INTERRUPT;
222	}
223
224	// interrupt from Controller Registers
225	reg8 = read_ccs_uint8(ice, CCS_INTERRUPT_STATUS);
226	if (reg8 != 0) {
227		bool ret;
228		if (reg8 & CCS_INTERRUPT_MIDI_1) {
229			ret = (*mpu401->interrupt_hook)(ice->midiItf[0].mpu401device);
230			if (ret) {
231				//Do not ack, cause more datas are available
232				reg8 &= ~CCS_INTERRUPT_MIDI_1;
233			}
234		}
235
236		if (reg8 & CCS_INTERRUPT_MIDI_2) {
237			ret = (*mpu401->interrupt_hook)(ice->midiItf[1].mpu401device);
238			if (ret) {
239				//Do not ack, cause more datas are available
240				reg8 &= ~CCS_INTERRUPT_MIDI_2;
241			}
242		}
243
244		if (reg8 != 0) {
245			write_ccs_uint8(ice, CCS_INTERRUPT_STATUS, reg8);
246			status = B_HANDLED_INTERRUPT;
247		}
248	}
249
250	// interrupt from DS PATH
251	reg16 = read_ds_uint16(ice, DS_DMA_INT_STATUS);
252	if (reg16 != 0) {
253		//Ack interrupt
254		write_ds_uint16(ice, DS_DMA_INT_STATUS, reg16);
255		status = B_HANDLED_INTERRUPT;
256	}
257
258	return status;
259}
260
261
262status_t
263ice1712HW_setup(ice1712 *ice)
264{
265	int i;
266	uint8 reg8 = 0;
267	uint16 mute;
268
269	ice->irq = ice->info.u.h0.interrupt_line;
270	ice->Controller = ice->info.u.h0.base_registers[0];
271	ice->DDMA = ice->info.u.h0.base_registers[1];
272	ice->DMA_Path = ice->info.u.h0.base_registers[2];
273	ice->Multi_Track = ice->info.u.h0.base_registers[3];
274
275	// Soft Reset
276	write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x81);
277	snooze(200000);
278	write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x01);
279	snooze(200000);
280
281	read_eeprom(ice, ice->eeprom_data);
282
283	write_ccs_uint8(ice, CCS_SERR_SHADOW, 0x01);
284
285	//Write all configurations register from EEProm
286	ice->info.device_id = ice->eeprom_data[E2PROM_MAP_SUBVENDOR_HIGH] << 8
287		| ice->eeprom_data[E2PROM_MAP_SUBVENDOR_LOW];
288	ice->info.vendor_id = ice->eeprom_data[E2PROM_MAP_SUBDEVICE_HIGH] << 8
289		| ice->eeprom_data[E2PROM_MAP_SUBDEVICE_LOW];
290	ice->config.product = (ice1712Product)(ice->info.vendor_id << 16
291		| ice->info.device_id);
292	ITRACE("Product ID : 0x%x\n", ice->config.product);
293
294	write_cci_uint8(ice, CCI_GPIO_WRITE_MASK,
295		ice->eeprom_data[E2PROM_MAP_GPIOMASK]);
296	write_cci_uint8(ice, CCI_GPIO_DATA,
297		ice->eeprom_data[E2PROM_MAP_GPIOSTATE]);
298	write_cci_uint8(ice, CCI_GPIO_DIRECTION_CONTROL,
299		ice->eeprom_data[E2PROM_MAP_GPIODIR]);
300
301	ITRACE("CCI_GPIO_WRITE_MASK : 0x%x\n",
302		ice->eeprom_data[E2PROM_MAP_GPIOMASK]);
303	ITRACE("CCI_GPIO_DATA : 0x%x\n",
304		ice->eeprom_data[E2PROM_MAP_GPIOSTATE]);
305	ITRACE("CCI_GPIO_DIRECTION_CONTROL : 0x%x\n",
306		ice->eeprom_data[E2PROM_MAP_GPIODIR]);
307
308	//Write Configuration in the PCI configuration Register
309	(pci->write_pci_config)(ice->info.bus, ice->info.device,
310		ice->info.function, 0x60, 1, ice->eeprom_data[E2PROM_MAP_CONFIG]);
311	(pci->write_pci_config)(ice->info.bus, ice->info.device,
312		ice->info.function, 0x61, 1, ice->eeprom_data[E2PROM_MAP_ACL]);
313	(pci->write_pci_config)(ice->info.bus, ice->info.device,
314		ice->info.function, 0x62, 1, ice->eeprom_data[E2PROM_MAP_I2S]);
315	(pci->write_pci_config)(ice->info.bus, ice->info.device,
316		ice->info.function, 0x63, 1, ice->eeprom_data[E2PROM_MAP_SPDIF]);
317
318	ITRACE("E2PROM_MAP_CONFIG : 0x%x\n", ice->eeprom_data[E2PROM_MAP_CONFIG]);
319	reg8 = ice->eeprom_data[E2PROM_MAP_CONFIG];
320	//Bits signification for E2PROM_MAP_CONFIG Byte
321	//
322	// 8   7   6   5   4   3   2   1   0
323	//           |-D-|-C-|---B---|---A---
324	//
325	// D : MPU401 number minus 1
326	// C : AC'97
327	// B : Stereo ADC number minus 1 (=> 1 to 4)
328	// A : Stereo DAC number minus 1 (=> 1 to 4)
329
330	ice->config.nb_DAC = ((reg8 & 0x03) + 1) * 2;
331	reg8 >>= 2;
332	ice->config.nb_ADC = ((reg8 & 0x03) + 1) * 2;
333	reg8 >>= 2;
334
335	if ((reg8 & 0x01) != 0) {//Consumer AC'97 Exist
336		ITRACE("Consumer AC'97 does exist\n");
337		//For now do nothing
338/*		write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x40);
339		snooze(10000);
340		write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x00);
341		snooze(20000);
342*/	} else {
343		ITRACE("Consumer AC'97 does NOT exist\n");
344	}
345	reg8 >>= 1;
346	ice->config.nb_MPU401 = (reg8 & 0x1) + 1;
347
348	if (ice->config.nb_MPU401 > 0) {
349		sprintf(ice->midiItf[0].name, "midi/ice1712/%ld/1", ice - cards + 1);
350
351		(*mpu401->create_device)(ice->Controller + CCS_MIDI_1_DATA,
352			&ice->midiItf[0].mpu401device,
353			0x14121712,
354			ice1712Midi_interrupt,
355			&ice->midiItf[0]);
356
357		names[num_names++] = ice->midiItf[0].name;
358		ice->midiItf[0].card = ice;
359		ice->midiItf[0].int_mask = CCS_INTERRUPT_MIDI_1;
360	}
361
362	if (ice->config.nb_MPU401 > 1) {
363		sprintf(ice->midiItf[1].name, "midi/ice1712/%ld/2", ice - cards + 1);
364
365		(*mpu401->create_device)(ice->Controller + CCS_MIDI_2_DATA,
366			&ice->midiItf[1].mpu401device,
367			0x14121712,
368			ice1712Midi_interrupt,
369			&ice->midiItf[1]);
370
371		names[num_names++] = ice->midiItf[1].name;
372		ice->midiItf[1].card = ice;
373		ice->midiItf[1].int_mask = CCS_INTERRUPT_MIDI_2;
374	}
375
376	ITRACE("E2PROM_MAP_SPDIF : 0x%x\n", ice->eeprom_data[E2PROM_MAP_SPDIF]);
377	ice->config.spdif = ice->eeprom_data[E2PROM_MAP_SPDIF];
378
379	switch (ice->config.product) {
380		case ICE1712_SUBDEVICE_DELTA66 :
381		case ICE1712_SUBDEVICE_DELTA44 :
382			ice->CommLines.clock = DELTA66_CLK;
383			ice->CommLines.data_in = 0;
384			ice->CommLines.data_out = DELTA66_DOUT;
385			ice->CommLines.cs_mask = DELTA66_CLK | DELTA66_DOUT
386				| DELTA66_CS_MASK;
387			break;
388		case ICE1712_SUBDEVICE_DELTA410 :
389		case ICE1712_SUBDEVICE_AUDIOPHILE_2496 :
390		case ICE1712_SUBDEVICE_DELTADIO2496 :
391			ice->CommLines.clock = AP2496_CLK;
392			ice->CommLines.data_in = AP2496_DIN;
393			ice->CommLines.data_out = AP2496_DOUT;
394			ice->CommLines.cs_mask = AP2496_CLK | AP2496_DIN
395				| AP2496_DOUT | AP2496_CS_MASK;
396			break;
397		case ICE1712_SUBDEVICE_DELTA1010 :
398		case ICE1712_SUBDEVICE_DELTA1010LT :
399			ice->CommLines.clock = DELTA1010LT_CLK;
400			ice->CommLines.data_in = DELTA1010LT_DIN;
401			ice->CommLines.data_out = DELTA1010LT_DOUT;
402			ice->CommLines.cs_mask = DELTA1010LT_CLK | DELTA1010LT_DIN
403				| DELTA1010LT_DOUT | DELTA1010LT_CS_NONE;
404			break;
405		case ICE1712_SUBDEVICE_VX442 :
406			ice->CommLines.clock = VX442_CLK;
407			ice->CommLines.data_in = VX442_DIN;
408			ice->CommLines.data_out = VX442_DOUT;
409			ice->CommLines.cs_mask = VX442_CLK | VX442_DIN | VX442_DOUT
410				| VX442_CS_MASK;
411			break;
412	}
413
414	sprintf(ice->name, "%s/%ld", HMULTI_AUDIO_DEV_PATH, ice - cards + 1);
415	names[num_names++] = ice->name;
416	names[num_names] = NULL;
417
418	ice->buffer_ready_sem = create_sem(0, "Buffer Exchange");
419	if (ice->buffer_ready_sem < B_OK) {
420		return ice->buffer_ready_sem;
421	}
422
423	install_io_interrupt_handler(ice->irq, ice1712HW_interrupt, ice, 0);
424
425	ice->mem_id_pb = alloc_mem(&ice->phys_pb, &ice->log_addr_pb,
426		PLAYBACK_BUFFER_TOTAL_SIZE, "playback buffer");
427	if (ice->mem_id_pb < B_OK) {
428		remove_io_interrupt_handler(ice->irq, ice1712HW_interrupt, ice);
429		delete_sem(ice->buffer_ready_sem);
430		return ice->mem_id_pb;
431	}
432
433	ice->mem_id_rec = alloc_mem(&ice->phys_rec, &ice->log_addr_rec,
434		RECORD_BUFFER_TOTAL_SIZE, "record buffer");
435	if (ice->mem_id_rec < B_OK) {
436		remove_io_interrupt_handler(ice->irq, ice1712HW_interrupt, ice);
437		delete_sem(ice->buffer_ready_sem);
438		delete_area(ice->mem_id_pb);
439		return(ice->mem_id_rec);
440	}
441
442	ice->config.samplingRate = 0x08;
443	ice->buffer = 0;
444	ice->frames_count = 0;
445	ice->buffer_size = ice->settings.bufferSize;
446
447	ice->total_output_channels = ice->config.nb_DAC;
448	if (ice->config.spdif & SPDIF_OUT_PRESENT)
449		ice->total_output_channels += 2;
450
451	ice->total_input_channels = ice->config.nb_ADC + 2;
452	if (ice->config.spdif & SPDIF_IN_PRESENT)
453		ice->total_input_channels += 2;
454
455	//Write bits in the GPIO
456	write_cci_uint8(ice, CCI_GPIO_WRITE_MASK, ~(ice->CommLines.cs_mask));
457	//Deselect CS
458	write_cci_uint8(ice, CCI_GPIO_DATA, ice->CommLines.cs_mask);
459
460	//Set the rampe volume to a faster one
461	write_mt_uint16(ice, MT_VOLUME_CONTROL_RATE, 0x01);
462
463	//All Analog outputs from DMA
464	write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT, 0x0000);
465	//All Digital output from DMA
466	write_mt_uint16(ice, MT_ROUTING_CONTROL_SPDOUT, 0x0000);
467
468	//Mute all input
469	mute = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
470	for (i = 0; i < 2 * ICE1712_HARDWARE_VOLUME; i++) {
471		write_mt_uint8(ice, MT_VOLUME_CONTROL_CHANNEL_INDEX, i);
472		write_mt_uint16(ice, MT_VOLUME_CONTROL_CHANNEL_INDEX, mute);
473	}
474
475	//Unmask Interrupt
476	write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x41);
477
478	reg8 = read_ccs_uint8(ice, CCS_INTERRUPT_MASK);
479	ITRACE("-----CCS----- = %x\n", reg8);
480	write_ccs_uint8(ice, CCS_INTERRUPT_MASK, 0xEF);
481
482/*	reg16 = read_ds_uint16(ice, DS_DMA_INT_MASK);
483	ITRACE("-----DS_DMA----- = %x\n", reg16);
484	write_ds_uint16(ice, DS_DMA_INT_MASK, 0x0000);
485*/
486	reg8 = read_mt_uint8(ice, MT_DMA_INT_MASK_STATUS);
487	ITRACE("-----MT_DMA----- = %x\n", reg8);
488	write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, 0x00);
489
490	return B_OK;
491};
492
493
494void
495ice1712HW_shutdown(ice1712 *ice)
496{
497	delete_sem(ice->buffer_ready_sem);
498
499	remove_io_interrupt_handler(ice->irq, ice1712HW_interrupt, ice);
500
501	if (ice->mem_id_pb != B_ERROR)
502		delete_area(ice->mem_id_pb);
503
504	if (ice->mem_id_rec != B_ERROR)
505		delete_area(ice->mem_id_rec);
506
507	codec_write(ice, AK45xx_RESET_REGISTER, 0x00);
508}
509
510//ICE1712 driver - Hook
511//---------------------
512
513static status_t
514ice1712Audio_open(const char *name, uint32 flags, void **cookie)
515{
516	int ix;
517	ice1712 *card = NULL;
518	ITRACE("** open(): %s\n", name);
519
520	for (ix = 0; ix<num_cards; ix++) {
521		if (!strcmp(cards[ix].name, name)) {
522			card = &cards[ix];
523		}
524	}
525
526	if (card == NULL) {
527		ITRACE("open() card not found %s\n", name);
528		for (ix=0; ix<num_cards; ix++) {
529			ITRACE("open() card available %s\n", cards[ix].name);
530		}
531		return B_ERROR;
532	}
533	*cookie = cards;
534	return B_OK;
535}
536
537
538static status_t
539ice1712Audio_close(void *cookie)
540{
541	ITRACE("** close()\n");
542	return B_OK;
543}
544
545
546static status_t
547ice1712Audio_free(void *cookie)
548{
549	ITRACE("** free()\n");
550	return B_OK;
551}
552
553
554static status_t
555ice1712Audio_control(void *cookie, uint32 op, void *arg, size_t len)
556{
557	switch (op) {
558		case B_MULTI_GET_DESCRIPTION :
559			ITRACE("B_MULTI_GET_DESCRIPTION\n");
560			return ice1712Get_Description((ice1712 *)cookie,
561				(multi_description*)arg);
562		case B_MULTI_GET_EVENT_INFO :
563			ITRACE("B_MULTI_GET_EVENT_INFO\n");
564			return B_ERROR;
565		case B_MULTI_SET_EVENT_INFO :
566			ITRACE("B_MULTI_SET_EVENT_INFO\n");
567			return B_ERROR;
568		case B_MULTI_GET_EVENT :
569			ITRACE("B_MULTI_GET_EVENT\n");
570			return B_ERROR;
571		case B_MULTI_GET_ENABLED_CHANNELS :
572			ITRACE("B_MULTI_GET_ENABLED_CHANNELS\n");
573			return ice1712Get_Channel((ice1712*)cookie,
574				(multi_channel_enable*)arg);
575		case B_MULTI_SET_ENABLED_CHANNELS :
576			ITRACE("B_MULTI_SET_ENABLED_CHANNELS\n");
577			return ice1712Set_Channel((ice1712*)cookie,
578				(multi_channel_enable*)arg);
579		case B_MULTI_GET_GLOBAL_FORMAT :
580			ITRACE("B_MULTI_GET_GLOBAL_FORMAT\n");
581			return ice1712Get_Format((ice1712*)cookie,
582				(multi_format_info *)arg);
583		case B_MULTI_SET_GLOBAL_FORMAT :
584			ITRACE("B_MULTI_SET_GLOBAL_FORMAT\n");
585			return ice1712Set_Format((ice1712*)cookie,
586				(multi_format_info *)arg);
587		case B_MULTI_GET_CHANNEL_FORMATS :
588			ITRACE("B_MULTI_GET_CHANNEL_FORMATS\n");
589			return B_ERROR;
590		case B_MULTI_SET_CHANNEL_FORMATS :
591			ITRACE("B_MULTI_SET_CHANNEL_FORMATS\n");
592			return B_ERROR;
593		case B_MULTI_GET_MIX :
594			ITRACE("B_MULTI_GET_MIX\n");
595			return ice1712Get_MixValue((ice1712*)cookie,
596				(multi_mix_value_info *)arg);
597		case B_MULTI_SET_MIX :
598			ITRACE("B_MULTI_SET_MIX\n");
599			return ice1712Set_MixValue((ice1712*)cookie,
600				(multi_mix_value_info *)arg);
601		case B_MULTI_LIST_MIX_CHANNELS :
602			ITRACE("B_MULTI_LIST_MIX_CHANNELS\n");
603			return ice1712Get_MixValueChannel((ice1712*)cookie,
604				(multi_mix_channel_info *)arg);
605		case B_MULTI_LIST_MIX_CONTROLS :
606			ITRACE("B_MULTI_LIST_MIX_CONTROLS\n");
607			return ice1712Get_MixValueControls((ice1712*)cookie,
608				(multi_mix_control_info *)arg);
609		case B_MULTI_LIST_MIX_CONNECTIONS :
610			ITRACE("B_MULTI_LIST_MIX_CONNECTIONS\n");
611			return ice1712Get_MixValueConnections((ice1712*)cookie,
612				(multi_mix_connection_info *)arg);
613		case B_MULTI_GET_BUFFERS :
614			ITRACE("B_MULTI_GET_BUFFERS\n");
615			return ice1712Buffer_Get((ice1712*)cookie,
616				(multi_buffer_list*)arg);
617		case B_MULTI_SET_BUFFERS :
618			ITRACE("B_MULTI_SET_BUFFERS\n");
619			return B_ERROR;
620		case B_MULTI_SET_START_TIME :
621			ITRACE("B_MULTI_SET_START_TIME\n");
622			return B_ERROR;
623		case B_MULTI_BUFFER_EXCHANGE :
624//			ITRACE("B_MULTI_BUFFER_EXCHANGE\n");
625			return ice1712Buffer_Exchange((ice1712*)cookie,
626				(multi_buffer_info *)arg);
627		case B_MULTI_BUFFER_FORCE_STOP :
628			ITRACE("B_MULTI_BUFFER_FORCE_STOP\n");
629			return ice1712Buffer_Stop((ice1712*)cookie);
630		case B_MULTI_LIST_EXTENSIONS :
631			ITRACE("B_MULTI_LIST_EXTENSIONS\n");
632			return B_ERROR;
633		case B_MULTI_GET_EXTENSION :
634			ITRACE("B_MULTI_GET_EXTENSION\n");
635			return B_ERROR;
636		case B_MULTI_SET_EXTENSION :
637			ITRACE("B_MULTI_SET_EXTENSION\n");
638			return B_ERROR;
639		case B_MULTI_LIST_MODES :
640			ITRACE("B_MULTI_LIST_MODES\n");
641			return B_ERROR;
642		case B_MULTI_GET_MODE :
643			ITRACE("B_MULTI_GET_MODE\n");
644			return B_ERROR;
645		case B_MULTI_SET_MODE :
646			ITRACE("B_MULTI_SET_MODE\n");
647			return B_ERROR;
648
649		default :
650			ITRACE("ERROR: unknown multi_control %#x\n", (int)op);
651			return B_ERROR;
652	}
653}
654
655
656static status_t
657ice1712Audio_read(void *cookie, off_t position, void *buf,
658	size_t *num_bytes)
659{
660	ITRACE("** read()\n");
661	*num_bytes = 0;
662	return B_IO_ERROR;
663}
664
665
666static status_t
667ice1712Audio_write(void *cookie, off_t position, const void *buffer,
668	size_t *num_bytes)
669{
670	ITRACE("** write()\n");
671	*num_bytes = 0;
672	return B_IO_ERROR;
673}
674
675
676device_hooks ice1712Audio_hooks =
677{
678	ice1712Audio_open,
679	ice1712Audio_close,
680	ice1712Audio_free,
681	ice1712Audio_control,
682	ice1712Audio_read,
683	ice1712Audio_write,
684	NULL,
685	NULL,
686	NULL,
687	NULL
688};
689
690
691//ICE1712 Drivers - Settings
692//--------------------------
693
694
695status_t
696ice1712Settings_load(ice1712 *card)
697{
698	// get driver settings
699	void *settings_handle = load_driver_settings("ice1712.settings");
700
701	//Use a large enough value for modern computer
702	card->settings.bufferSize = 512;
703
704	if (settings_handle != NULL) {
705		const char *item;
706		char *end;
707
708		item = get_driver_parameter(settings_handle,
709			"buffer_size", "512", "512");
710		if (item != NULL) {
711			uint32 value = strtoul(item, &end, 0);
712			if ((*end == '\0')
713				&& (value >= MIN_BUFFER_FRAMES)
714				&& (value <= MAX_BUFFER_FRAMES)) {
715					card->settings.bufferSize = value;
716			}
717		}
718
719		unload_driver_settings(settings_handle);
720	}
721
722	return B_OK;
723}
724
725
726status_t
727ice1712Settings_apply(ice1712 *card)
728{
729	int i;
730	uint16 val, mt30 = 0;
731	uint32 mt34 = 0;
732
733	for (i = 0; i < ICE1712_HARDWARE_VOLUME; i++) {
734		//Select the channel
735		write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX, i);
736
737		if (card->settings.playback[i].mute == true) {
738			val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
739		} else {
740			uint8 volume = card->settings.playback[i].volume / -1.5;
741			if (i & 1) {//a right channel
742				val = ICE1712_MUTE_VALUE << 0; //Mute left volume
743				val |= volume << 8;
744			} else {//a left channel
745				val = ICE1712_MUTE_VALUE << 8; //Mute right volume
746				val |= volume << 0;
747			}
748		}
749
750		write_mt_uint16(card, MT_LR_VOLUME_CONTROL,	val);
751		ITRACE_VV("Apply Settings %d : 0x%x\n", i, val);
752	}
753
754	for (i = 0; i < ICE1712_HARDWARE_VOLUME; i++) {
755		//Select the channel
756		write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX,
757			i + ICE1712_HARDWARE_VOLUME);
758
759		if (card->settings.record[i].mute == true) {
760			val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
761		} else {
762			uint8 volume = card->settings.record[i].volume / -1.5;
763			if (i & 1) {//a right channel
764				val = ICE1712_MUTE_VALUE << 0; //Mute left volume
765				val |= volume << 8;
766			} else {//a left channel
767				val = ICE1712_MUTE_VALUE << 8; //Mute right volume
768				val |= volume << 0;
769			}
770		}
771
772		write_mt_uint16(card, MT_LR_VOLUME_CONTROL,	val);
773		ITRACE_VV("Apply Settings %d : 0x%x\n", i, val);
774	}
775
776	//Analog output selection
777	for (i = 0; i < 4; i++) {
778		uint8 out = card->settings.output[i];
779		if (out == 0) {
780			ITRACE_VV("Output %d is haiku output\n", i);
781			//Nothing to do
782		} else if (out <= (card->config.nb_ADC / 2)) {
783			uint8 mt34_c;
784			out--;
785			ITRACE_VV("Output %d is input %d\n", i, out);
786			mt34_c = (out * 2);
787			mt34_c |= (out * 2 + 1) << 4;
788			mt30 |= 0x0202 << (2 * i);
789			mt30 |= mt34_c << (8 * i);
790		} else if (out == ((card->config.nb_ADC / 2) + 1)
791				&& (card->config.spdif & SPDIF_IN_PRESENT) != 0) {
792			ITRACE_VV("Output %d is digital input\n", i);
793			mt30 |= 0x0303 << (2 * i);
794			mt34 |= 0x80 << (8 * i);
795		} else {
796			ITRACE_VV("Output %d is digital Mixer\n", i);
797			mt30 |= 0x0101;
798		}
799	}
800	write_mt_uint16(card, MT_ROUTING_CONTROL_PSDOUT, mt30);
801	write_mt_uint32(card, MT_CAPTURED_DATA, mt34);
802
803	//Digital output
804	if ((card->config.spdif & SPDIF_OUT_PRESENT) != 0) {
805		uint16 mt32 = 0;
806		uint8 out = card->settings.output[4];
807		if (out == 0) {
808			ITRACE_VV("Digital output is haiku output\n");
809			//Nothing to do
810		} else if (out <= (card->config.nb_ADC / 2)) {
811			out--;
812			ITRACE_VV("Digital output is input %d\n", out);
813			mt32 |= 0x0202;
814			mt32 |= (out * 2) << 8;
815			mt32 |= (out * 2 + 1) << 12;
816		} else if (out == ((card->config.nb_ADC / 2) + 1)
817				&& (card->config.spdif & SPDIF_IN_PRESENT) != 0) {
818			ITRACE_VV("Digital output is digital input\n");
819			mt32 |= 0x800F;
820		} else {
821			ITRACE_VV("Digital output is digital Mixer\n");
822			mt32 |= 0x0005;
823		}
824
825		write_mt_uint16(card, MT_ROUTING_CONTROL_SPDOUT, mt32);
826	}
827
828	return B_OK;
829}
830