Exemple #1
0
//This will create a Tab
static int32
create_group_control(multi_mix_control **p_mmc, int32 index, int32 parent,
	enum strind_id string, const char* name)
{
	multi_mix_control *mmc = *p_mmc;
	int32 group;

	TRACE_VV("Create ID create_group_control\n");

	mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_SET_INDEX(index);
	mmc->parent = parent;
	mmc->flags = B_MULTI_MIX_GROUP;
	mmc->master = CONTROL_IS_MASTER;
	mmc->string = string;

	group = mmc->id;

	if (name != NULL)
		strcpy(mmc->name, name);

	TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id);

	nb_control_created++; mmc++;
	(*p_mmc) = mmc;

	return group;
}
Exemple #2
0
static void
set_volume_cb(ice1712 *card, multi_mix_value *mmv)
{
	channel_volume *vol;
	uint32 chan = ICE1712_MULTI_GET_CHANNEL(mmv->id);

	TRACE_VV("   set_volume_cb\n");

	if (chan < ICE1712_HARDWARE_VOLUME) {
		vol = card->settings.playback;
	}
	else {
		vol = card->settings.record;
		chan -= ICE1712_HARDWARE_VOLUME;
	}

	//chan is normaly <= ICE1712_HARDWARE_VOLUME
	switch (ICE1712_MULTI_GET_INDEX(mmv->id)) {
		case 0: //Mute
			vol[chan].mute = mmv->u.enable;
			vol[chan + 1].mute = mmv->u.enable;
			TRACE_VV("\tChange mute to %d for channel %d and %d\n",
				mmv->u.enable, (int)chan, (int)chan + 1);
			break;

		case 2: //Right channel
			chan++;
			//No break
		case 1: //Left channel
			vol[chan].volume = mmv->u.gain;
			TRACE_VV("\tChange Volume to %f for channel %d\n",
				mmv->u.gain, (int)chan);
			break;
	}
}
Exemple #3
0
status_t
ice1712_set_mix(ice1712 *card, multi_mix_value_info *data)
{
	int i;

	TRACE_VV("	Asking to set %ld control(s)\n", data->item_count);

	for (i = 0; i < data->item_count; i++) {
		multi_mix_value *mmv = &(data->values[i]);
		TRACE_VV("	 Id %#x\n", (unsigned int)mmv->id);
		switch (mmv->id & ICE1712_MULTI_CONTROL_TYPE_MASK) {
			case ICE1712_MULTI_CONTROL_TYPE_COMBO:
				set_combo_cb(card, ICE1712_MULTI_GET_CHANNEL(mmv->id),
					mmv->u.mux);
				break;

			case ICE1712_MULTI_CONTROL_TYPE_VOLUME:
				set_volume_cb(card, mmv);
				break;

			case ICE1712_MULTI_CONTROL_TYPE_OUTPUT:
				set_output_cb(card, ICE1712_MULTI_GET_CHANNEL(mmv->id),
					mmv->u.mux);
				break;

			default:
				TRACE_VV("	  default 0x%x\n", (unsigned int)mmv->id);
				break;
		}
	}

	return apply_settings(card);
}
Exemple #4
0
//This will create a Slider with a "Mute" CheckBox
static void
create_channel_control(multi_mix_control **p_mmc, int32 channel, int32 parent,
	const char* name)
{
	int32 id = ICE1712_MULTI_CONTROL_FIRSTID
		+ ICE1712_MULTI_CONTROL_TYPE_VOLUME
		+ ICE1712_MULTI_SET_CHANNEL(channel);
	multi_mix_control *mmc = *p_mmc;
	multi_mix_control control;

	TRACE_VV("Create ID create_channel_control\n");

	control.master = CONTROL_IS_MASTER;
	control.parent = parent;
	control.u.gain.max_gain = 0.0;
	control.u.gain.min_gain = -144.0;
	control.u.gain.granularity = 1.5;

	//The Mute Checkbox
	control.id = id++;
	control.flags = B_MULTI_MIX_ENABLE;
	control.string = S_MUTE;
	*mmc = control;
	mmc++;

	TRACE_VV("Create ID %#x\n", (unsigned int)control.id);

	//The Left Slider
	control.string = S_null;
	control.id = id++;
	control.flags = B_MULTI_MIX_GAIN;
	if (name != NULL)
		strcpy(control.name, name);
	*mmc = control;
	mmc++;

	TRACE_VV("Create ID %#x\n", (unsigned int)control.id);

	//The Right Slider
	control.master = control.id; //The Id of the Left Slider
	control.id = id++;
	*mmc = control;
	mmc++;

	TRACE_VV("Create ID %#x\n", (unsigned int)control.id);

	nb_control_created += 3;
	(*p_mmc) = mmc;
}
Exemple #5
0
static void
set_combo_cb(ice1712 *card, uint32 index, uint32 value)
{
	TRACE_VV("   set_combo_cb: %ld, %ld\n", index, value);

	switch (index) {
		case 0:
			if (value < 2)
				card->settings.clock = value;
			break;

		case 1:
			if (value < 2)
				card->settings.outFormat = value;
			break;

		case 2:
			if (value < 3)
				card->settings.emphasis = value;
			break;

		case 3:
			if (value < 3)
				card->settings.copyMode = value;
			break;
	}
}
Exemple #6
0
static uint32
get_combo_cb(ice1712 *card, uint32 index)
{
	uint32 value = 0;

	TRACE_VV("   get_combo_cb: %ld, %ld\n", index, value);

	switch (index) {
		case 0:
			value = card->settings.clock;
			break;

		case 1:
			value = card->settings.outFormat;
			break;

		case 2:
			value = card->settings.emphasis;
			break;

		case 3:
			value = card->settings.copyMode;
			break;
	}

	return value;
}
Exemple #7
0
static void
set_output_cb(ice1712 *card, uint32 index, uint32 value)
{
	if (index < 5)
		card->settings.output[index] = value;

	TRACE_VV("   set_output_cb: %ld, %ld\n", index, value);
}
Exemple #8
0
static uint32
get_output_cb(ice1712 *card, uint32 index)
{
	uint32 value = 0;

	if (index < 5)
		value = card->settings.output[index];

	TRACE_VV("   get_output_cb: %ld, %ld\n", index, value);

	return value;
}
Exemple #9
0
static void
create_combo_control(multi_mix_control **p_mmc, const char *values[],
	int32 parent, int32 nb_combo, const char *name)
{
	int32 id = ICE1712_MULTI_CONTROL_FIRSTID
		+ ICE1712_MULTI_CONTROL_TYPE_COMBO
		+ ICE1712_MULTI_SET_CHANNEL(nb_combo);
	multi_mix_control *mmc = *p_mmc;
	int32 parentControl, i;

	TRACE_VV("Create ID create_combo_control\n");

	//The label
	parentControl = mmc->id = id++;
	mmc->flags = B_MULTI_MIX_MUX;
	mmc->parent = parent;
	strcpy(mmc->name, name);

	TRACE_VV("Create ID %#x\n", (unsigned int)parentControl);

	nb_control_created++; mmc++;

	//The values
	for (i = 0; values[i] != NULL; i++) {
		mmc->id = id++;
		mmc->flags = B_MULTI_MIX_MUX_VALUE;
		mmc->parent = parentControl;
		strcpy(mmc->name, values[i]);

		TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id);

		nb_control_created++; mmc++;
	}

	(*p_mmc) = mmc;
}
Exemple #10
0
status_t
applySettings(ice1712 *card)
{
	int i;
	uint16 val, mt30 = 0;
	uint32 mt34 = 0;

	for (i = 0; i < ICE1712_HARDWARE_VOLUME; i++) {
		//Select the channel
		write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX, i);

		if (card->settings.playback[i].mute == true) {
			val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
		} else {
			unsigned char volume = card->settings.playback[i].volume / -1.5;
			if (i & 1) {//a right channel
				val = ICE1712_MUTE_VALUE << 0; //Mute left volume
				val |= volume << 8;
			} else {//a left channel
				val = ICE1712_MUTE_VALUE << 8; //Mute right volume
				val |= volume << 0;
			}
		}

		write_mt_uint16(card, MT_LR_VOLUME_CONTROL,	val);
		TRACE_VV("Apply Settings %d : 0x%x\n", i, val);
	}

	for (i = 0; i < ICE1712_HARDWARE_VOLUME; i++) {
		//Select the channel
		write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX,
			i + ICE1712_HARDWARE_VOLUME);

		if (card->settings.record[i].mute == true) {
			val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
		} else {
			uint8 volume = card->settings.record[i].volume / -1.5;
			if (i & 1) {//a right channel
				val = ICE1712_MUTE_VALUE << 0; //Mute left volume
				val |= volume << 8;
			} else {//a left channel
				val = ICE1712_MUTE_VALUE << 8; //Mute right volume
				val |= volume << 0;
			}
		}

		write_mt_uint16(card, MT_LR_VOLUME_CONTROL,	val);
		TRACE_VV("Apply Settings %d : 0x%x\n", i, val);
	}

	//Analog output selection
	for (i = 0; i < 4; i++) {
		uint8 out = card->settings.output[i];
		if (out == 0) {
			TRACE_VV("Output %d is haiku output\n", i);
			//Nothing to do
		} else if (out <= (card->config.nb_ADC / 2)) {
			uint8 mt34_c;
			out--;
			TRACE_VV("Output %d is input %d\n", i, out);
			mt34_c = (out * 2);
			mt34_c |= (out * 2 + 1) << 4;
			mt30 |= 0x0202 << (2*i);
			mt30 |= mt34_c << (8*i);
		} else if (out == ((card->config.nb_ADC / 2) + 1)
				&& (card->config.spdif & SPDIF_IN_PRESENT) != 0) {
			TRACE_VV("Output %d is digital input\n", i);
			mt30 |= 0x0303 << (2*i);
			mt34 |= 0x80 << (8*i);
		} else {
			TRACE_VV("Output %d is digital Mixer\n", i);
			mt30 |= 0x0101;
		}
	}
	write_mt_uint16(card, MT_ROUTING_CONTROL_PSDOUT, mt30);
	write_mt_uint32(card, MT_CAPTURED_DATA, mt34);
	
	//Digital output
	if ((card->config.spdif & SPDIF_OUT_PRESENT) != 0) {
		uint16 mt32 = 0;
		uint8 out = card->settings.output[4];
		if (out == 0) {
			TRACE_VV("Digital output is haiku output\n");
			//Nothing to do
		} else if (out <= (card->config.nb_ADC / 2)) {
			out--;
			TRACE_VV("Digital output is input %d\n", out);
			mt32 |= 0x0202;
			mt32 |= (out * 2) << 8;
			mt32 |= (out * 2 + 1) << 12;
		} else if (out == ((card->config.nb_ADC / 2) + 1)
				&& (card->config.spdif & SPDIF_IN_PRESENT) != 0) {
			TRACE_VV("Digital output is digital input\n");
			mt32 |= 0x800F;
		} else {
			TRACE_VV("Digital output is digital Mixer\n");
			mt32 |= 0x0005;
		}

		write_mt_uint16(card, MT_ROUTING_CONTROL_SPDOUT, mt32);
	}

	
	return B_OK;
}
Exemple #11
0
status_t
ice1712_get_buffers(ice1712 *card, multi_buffer_list *data)
{
	int buff, chan_i = 0, chan_o = 0;

	TRACE_VV("flags = %#lx\n", data->flags);
	TRACE_VV("request_playback_buffers = %ld\n",
		  data->request_playback_buffers);
	TRACE_VV("request_playback_channels = %ld\n",
		  data->request_playback_channels);
	TRACE_VV("request_playback_buffer_size = %lx\n",
		  data->request_playback_buffer_size);
	TRACE_VV("request_record_buffers = %ld\n",
		  data->request_record_buffers);
	TRACE_VV("request_record_channels = %ld\n",
		  data->request_record_channels);
	TRACE_VV("request_record_buffer_size = %lx\n",
		  data->request_record_buffer_size);

	for (buff = 0; buff < SWAPPING_BUFFERS; buff++) {
		uint32 stride_o = MAX_DAC * SAMPLE_SIZE;
		uint32 stride_i = MAX_ADC * SAMPLE_SIZE;
		uint32 buf_o = stride_o * card->buffer_size;
		uint32 buf_i = stride_i * card->buffer_size;

		if (data->request_playback_channels == card->total_output_channels) {
			for (chan_o = 0; chan_o < card->config.nb_DAC; chan_o++) {
			//Analog STEREO output
				data->playback_buffers[buff][chan_o].base = card->log_addr_pb
					+ buf_o * buff + SAMPLE_SIZE * chan_o;
				data->playback_buffers[buff][chan_o].stride = stride_o;
				TRACE_VV("pb_buffer[%ld][%ld] = %p\n", buff, chan_o,
					data->playback_buffers[buff][chan_o].base);
			}

			if (card->config.spdif & SPDIF_OUT_PRESENT) {
			//SPDIF STEREO output
				data->playback_buffers[buff][chan_o].base = card->log_addr_pb
					+ buf_o * buff + SAMPLE_SIZE * SPDIF_LEFT;
				data->playback_buffers[buff][chan_o].stride = stride_o;
				TRACE_VV("pb_buffer[%ld][%ld] = %p\n", buff, chan_o,
					data->playback_buffers[buff][chan_o].base);

				chan_o++;
				data->playback_buffers[buff][chan_o].base = card->log_addr_pb
					+ buf_o * buff + SAMPLE_SIZE * SPDIF_RIGHT;
				data->playback_buffers[buff][chan_o].stride = stride_o;
				TRACE_VV("pb_buffer[%ld][%ld] = %p\n", buff, chan_o,
					data->playback_buffers[buff][chan_o].base);
				chan_o++;
			}
		}

		if (data->request_record_channels == card->total_input_channels) {
			for (chan_i = 0; chan_i < card->config.nb_ADC; chan_i++) {
			//Analog STEREO input
				data->record_buffers[buff][chan_i].base = card->log_addr_rec
					+ buf_i * buff + SAMPLE_SIZE * chan_i;
				data->record_buffers[buff][chan_i].stride = stride_i;
				TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i,
					data->record_buffers[buff][chan_i].base);
			}

			if (card->config.spdif & SPDIF_IN_PRESENT) {
			//SPDIF STEREO input
				data->record_buffers[buff][chan_i].base = card->log_addr_rec
					+ buf_i * buff + SAMPLE_SIZE * SPDIF_LEFT;
				data->record_buffers[buff][chan_i].stride = stride_i;
				TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i,
					data->record_buffers[buff][chan_i].base);

				chan_i++;
				data->record_buffers[buff][chan_i].base = card->log_addr_rec
					+ buf_i * buff + SAMPLE_SIZE * SPDIF_RIGHT;
				data->record_buffers[buff][chan_i].stride = stride_i;
				TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i,
					data->record_buffers[buff][chan_i].base);
				chan_i++;
			}

			//The digital mixer output
			data->record_buffers[buff][chan_i].base = card->log_addr_rec
				+ buf_i * buff + SAMPLE_SIZE * MIXER_OUT_LEFT;
			data->record_buffers[buff][chan_i].stride = stride_i;
			TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i,
					data->record_buffers[buff][chan_i].base);

			chan_i++;
			data->record_buffers[buff][chan_i].base = card->log_addr_rec
				+ buf_i * buff + SAMPLE_SIZE * MIXER_OUT_RIGHT;
			data->record_buffers[buff][chan_i].stride = stride_i;
			TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i,
					data->record_buffers[buff][chan_i].base);
			chan_i++;
		}
	}

	data->return_playback_buffers = SWAPPING_BUFFERS;
	data->return_playback_channels = card->total_output_channels;
	data->return_playback_buffer_size = card->buffer_size;

	TRACE("return_playback_buffers = %ld\n", data->return_playback_buffers);
	TRACE("return_playback_channels = %ld\n", data->return_playback_channels);
	TRACE("return_playback_buffer_size = %ld\n",
		data->return_playback_buffer_size);

	data->return_record_buffers = SWAPPING_BUFFERS;
	data->return_record_channels = card->total_input_channels;
	data->return_record_channels = chan_i;
	data->return_record_buffer_size = card->buffer_size;

	TRACE("return_record_buffers = %ld\n", data->return_record_buffers);
	TRACE("return_record_channels = %ld\n", data->return_record_channels);
	TRACE("return_record_buffer_size = %ld\n",
		data->return_record_buffer_size);

	start_DMA(card);

	return B_OK;
}
Exemple #12
0
status_t
ice1712_list_mix_controls(ice1712 *card, multi_mix_control_info *mmci)
{
	uint32 i, parentTab, parentTabColumn;
	multi_mix_control *mmc = mmci->controls;
	uint32 group = 0, combo = 0, channel = 0;

	nb_control_created = 0;

	TRACE_VV("count = %ld\n", mmci->control_count);

	//Cleaning
	memset(mmc, 0, mmci->control_count * sizeof(multi_mix_control));

	//Setup tab
	parentTab = create_group_control(&mmc, group++,
		CONTROL_IS_MASTER, S_SETUP, NULL);

	//General Settings
	parentTabColumn = create_group_control(&mmc, group++, parentTab,
		S_null, string_list[1]);
	for (i = 0; SettingsGeneral[i] != NULL; i++) {
		create_combo_control(&mmc, SettingsGeneral[i], parentTabColumn,
			combo++, string_list[5 + i]);
	}

	//Digital Settings
	parentTabColumn = create_group_control(&mmc, group++, parentTab,
		S_null, string_list[2]);
	for (i = 0; SettingsDigital[i] != NULL; i++) {
		create_combo_control(&mmc, SettingsDigital[i], parentTabColumn,
			combo++, string_list[8 + i]);
	}

	//Output Selection Settings
	parentTabColumn = create_group_control(&mmc, group++, parentTab,
		S_null, string_list[3]);
	for (i = 0; i < card->config.nb_DAC; i += 2) {
		create_output_choice(card, &mmc, i / 2, parentTabColumn);
	}

	if (card->config.spdif & SPDIF_OUT_PRESENT) {
		create_output_choice(card, &mmc, 4, parentTabColumn);
	}

	//Internal Mixer Tab
	//Output
	parentTab = create_group_control(&mmc, group++, CONTROL_IS_MASTER,
		S_null, string_list[4]);

	for (i = 0; i < card->config.nb_DAC; i += 2) {
		parentTabColumn = create_group_control(&mmc, group++, parentTab,
			S_null, string_list[(i / 2) + 11]);
		create_channel_control(&mmc, channel++, parentTabColumn, NULL);
	}

	if (card->config.spdif & SPDIF_OUT_PRESENT) {
		parentTabColumn = create_group_control(&mmc, group++, parentTab,
			S_null, string_list[15]);
		create_channel_control(&mmc, ICE1712_HARDWARE_VOLUME - 2,
			parentTabColumn, NULL);
	}

	//Input
	channel = ICE1712_HARDWARE_VOLUME;
	for (i = 0; i < card->config.nb_ADC; i += 2) {
		parentTabColumn = create_group_control(&mmc, group++, parentTab,
			 S_null, string_list[(i / 2) + 17]);
		create_channel_control(&mmc, channel++, parentTabColumn, NULL);
	}

	if (card->config.spdif & SPDIF_IN_PRESENT) {
		parentTabColumn = create_group_control(&mmc, group++, parentTab,
			S_null, string_list[21]);
		create_channel_control(&mmc, 2 * ICE1712_HARDWARE_VOLUME - 2,
			parentTabColumn, NULL);
	}

	TRACE_VV("Return %ld control(s)\n", nb_control_created);
	mmci->control_count = nb_control_created;

	return B_OK;
}
Exemple #13
0
//This will create all possible value for the output
//output 0 -> 3 (physical stereo output) 4 is the Digital
static void
create_output_choice(ice1712 *card, multi_mix_control **p_mmc,
	int32 output, int32 parent)
{
	int32 id = ICE1712_MULTI_CONTROL_FIRSTID
		+ ICE1712_MULTI_CONTROL_TYPE_OUTPUT
		+ ICE1712_MULTI_SET_CHANNEL(output);
	multi_mix_control *mmc = *p_mmc;
	int32 parentControl, i;

	TRACE_VV("Create ID create_output_choice\n");

	//The label
	parentControl = mmc->id = id++;
	mmc->flags = B_MULTI_MIX_MUX;
	mmc->parent = parent;
	strcpy(mmc->name, string_list[11 + output]);
	nb_control_created++; mmc++;

	TRACE_VV("Create ID %#x\n", (unsigned int)parentControl);

	//Haiku output
	mmc->id = id++;
	mmc->flags = B_MULTI_MIX_MUX_VALUE;
	mmc->parent = parentControl;
	strcpy(mmc->name, string_list[16]);

	TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id);

	nb_control_created++; mmc++;

	//Physical Input
	for (i = 0; i < card->config.nb_DAC; i += 2) {
		mmc->id = id++;
		mmc->flags = B_MULTI_MIX_MUX_VALUE;
		mmc->parent = parentControl;
		strcpy(mmc->name, string_list[17 + (i / 2)]);

		TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id);

		nb_control_created++; mmc++;
	}

	//Physical Digital Input
	if (card->config.spdif & SPDIF_IN_PRESENT) {
		mmc->id = id++;
		mmc->flags = B_MULTI_MIX_MUX_VALUE;
		mmc->parent = parentControl;
		strcpy(mmc->name, string_list[21]);

		TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id);

		nb_control_created++; mmc++;
	}

	//Internal mixer only for Output 1 and Digital Output
	if ((output == 0) || (output == 4)) {
		mmc->id = id++;
		mmc->flags = B_MULTI_MIX_MUX_VALUE;
		mmc->parent = parentControl;
		strcpy(mmc->name, string_list[22]);

		TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id);

		nb_control_created++; mmc++;
	}

	(*p_mmc) = mmc;
}
Exemple #14
0
status_t
ice1712_get_description(ice1712 *card, multi_description *data)
{
	int chan = 0, i, size;

	data->interface_version = B_CURRENT_INTERFACE_VERSION;
	data->interface_minimum = B_CURRENT_INTERFACE_VERSION;

	switch (card->product) {
		case ICE1712_SUBDEVICE_DELTA1010:
			strncpy(data->friendly_name, "Delta 1010", 32);
			break;
		case ICE1712_SUBDEVICE_DELTADIO2496:
			strncpy(data->friendly_name, "Delta DIO 2496", 32);
			break;
		case ICE1712_SUBDEVICE_DELTA66:
			strncpy(data->friendly_name, "Delta 66", 32);
			break;
		case ICE1712_SUBDEVICE_DELTA44:
			strncpy(data->friendly_name, "Delta 44", 32);
			break;
		case ICE1712_SUBDEVICE_AUDIOPHILE_2496:
			strncpy(data->friendly_name, "Audiophile 2496", 32);
			break;
		case ICE1712_SUBDEVICE_DELTA410:
			strncpy(data->friendly_name, "Delta 410", 32);
			break;
		case ICE1712_SUBDEVICE_DELTA1010LT:
			strncpy(data->friendly_name, "Delta 1010 LT", 32);
			break;
		case ICE1712_SUBDEVICE_VX442:
			strncpy(data->friendly_name, "VX 442", 32);
			break;

		default:
			strncpy(data->friendly_name, "Unknow device", 32);
			break;
	}

	strncpy(data->vendor_info, "Haiku OS", 32);

	data->output_channel_count = card->total_output_channels;
	data->input_channel_count = card->total_input_channels;
	data->output_bus_channel_count = 0;
	data->input_bus_channel_count = 0;
	data->aux_bus_channel_count = 0;

	size =  data->output_channel_count + data->input_channel_count
		+ data->output_bus_channel_count + data->input_bus_channel_count
		+ data->aux_bus_channel_count;

	TRACE_VV("request_channel_count = %ld\n", data->request_channel_count);

	if (size <= data->request_channel_count) {
		for (i = 0; i < card->config.nb_DAC; i++) {
		//Analog STEREO output
			data->channels[chan].channel_id = chan;
			data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL;
			data->channels[chan].designations = B_CHANNEL_STEREO_BUS
				| (((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT);
			data->channels[chan].connectors = 0;
			chan++;
		}

		if (card->config.spdif & SPDIF_OUT_PRESENT) {
		//SPDIF STEREO output
			data->channels[chan].channel_id = chan;
			data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL;
			data->channels[chan].designations = B_CHANNEL_STEREO_BUS
				| B_CHANNEL_LEFT;
			data->channels[chan].connectors = 0;
			chan++;
			data->channels[chan].channel_id = chan;
			data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL;
			data->channels[chan].designations = B_CHANNEL_STEREO_BUS
				| B_CHANNEL_RIGHT;
			data->channels[chan].connectors = 0;
			chan++;
		}

		for (i = 0; i < card->config.nb_ADC; i++) {
		//Analog STEREO input
			data->channels[chan].channel_id = chan;
			data->channels[chan].kind = B_MULTI_INPUT_CHANNEL;
			data->channels[chan].designations = B_CHANNEL_STEREO_BUS
				| (((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT);
			data->channels[chan].connectors = 0;
			chan++;
		}

		if (card->config.spdif & SPDIF_IN_PRESENT) {
		//SPDIF STEREO input
			data->channels[chan].channel_id = chan;
			data->channels[chan].kind = B_MULTI_INPUT_CHANNEL;
			data->channels[chan].designations = B_CHANNEL_STEREO_BUS
				| B_CHANNEL_LEFT;
			data->channels[chan].connectors = 0;
			chan++;
			data->channels[chan].channel_id = chan;
			data->channels[chan].kind = B_MULTI_INPUT_CHANNEL;
			data->channels[chan].designations = B_CHANNEL_STEREO_BUS
				| B_CHANNEL_RIGHT;
			data->channels[chan].connectors = 0;
			chan++;
		}

		//The digital mixer output (it's an Input for Haiku)
		data->channels[chan].channel_id = chan;
		data->channels[chan].kind = B_MULTI_INPUT_CHANNEL;
		data->channels[chan].designations = B_CHANNEL_STEREO_BUS
			| B_CHANNEL_LEFT;
		data->channels[chan].connectors = 0;
		chan++;
		data->channels[chan].channel_id = chan;
		data->channels[chan].kind = B_MULTI_INPUT_CHANNEL;
		data->channels[chan].designations = B_CHANNEL_STEREO_BUS
			| B_CHANNEL_RIGHT;
		data->channels[chan].connectors = 0;
		chan++;
	}

	TRACE("output_channel_count = %ld\n", data->output_channel_count);
	TRACE("input_channel_count = %ld\n", data->input_channel_count);
	TRACE("output_bus_channel_count = %ld\n", data->output_bus_channel_count);
	TRACE("input_bus_channel_count = %ld\n", data->input_bus_channel_count);

	data->output_rates = data->input_rates = AUTHORIZED_RATE;
	data->min_cvsr_rate = 44100;
	data->max_cvsr_rate = 96000;

	data->output_formats = data->input_formats = AUTHORIZED_SAMPLE_SIZE;
	data->lock_sources = B_MULTI_LOCK_INTERNAL | B_MULTI_LOCK_SPDIF;
	data->timecode_sources = 0;
	data->interface_flags = B_MULTI_INTERFACE_PLAYBACK
		| B_MULTI_INTERFACE_RECORD;
	data->start_latency = 0;

	strcpy(data->control_panel,"");

	return B_OK;
}