xref: /haiku/src/add-ons/kernel/drivers/audio/ice1712/ice1712.cpp (revision f2df0cfe93a902842f6f4629ff614f5b3f9bf687)
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 
28 static status_t ice1712Settings_load(ice1712 *card);
29 status_t ice1712Settings_apply(ice1712 *card);
30 static int32 ice1712HW_interrupt(void *arg);
31 static status_t ice1712HW_setup(ice1712 *ice);
32 static void ice1712HW_shutdown(ice1712 *ice);
33 
34 extern device_hooks ice1712Midi_hooks;
35 extern device_hooks ice1712Audio_hooks;
36 void ice1712Midi_interrupt(int32 op, void *data);
37 
38 pci_module_info *pci;
39 generic_mpu401_module *mpu401;
40 
41 int32 num_cards = 0;
42 ice1712 cards[NUM_CARDS];
43 
44 //3 interfaces (2 midi + 1 audio) can be defined for each card
45 static char *names[NUM_CARDS*3+1];
46 static int32 num_names = 0;
47 
48 #define HMULTI_AUDIO_DEV_PATH "audio/hmulti/ice1712"
49 
50 //Haiku Driver API
51 //----------------
52 
53 int32 api_version = B_CUR_DRIVER_API_VERSION;
54 
55 extern "C" status_t
56 init_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 
81 extern "C" status_t
82 init_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 
145 extern "C" void
146 uninit_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 
166 extern "C" const char **
167 publish_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 
179 extern "C" device_hooks *
180 find_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 
204 int32
205 ice1712HW_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 
262 status_t
263 ice1712HW_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 
494 void
495 ice1712HW_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 
513 static status_t
514 ice1712Audio_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 
538 static status_t
539 ice1712Audio_close(void *cookie)
540 {
541 	ITRACE("** close()\n");
542 	return B_OK;
543 }
544 
545 
546 static status_t
547 ice1712Audio_free(void *cookie)
548 {
549 	ITRACE("** free()\n");
550 	return B_OK;
551 }
552 
553 
554 static status_t
555 ice1712Audio_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 
656 static status_t
657 ice1712Audio_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 
666 static status_t
667 ice1712Audio_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 
676 device_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 
695 status_t
696 ice1712Settings_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 
726 status_t
727 ice1712Settings_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