* Copyright 2004-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Jérôme Duval, jerome.duval@free.fr
* Marcus Overhagen, marcus@overhagen.de
* Jérôme Lévêque, leveque.jerome@gmail.com
*/
#include "ice1712_reg.h"
#include "io.h"
#include "multi.h"
#include "util.h"
#include <string.h>
#include "debug.h"
status_t ice1712Settings_apply(ice1712 *card);
static void ice1712Buffer_Start(ice1712 *card);
static uint32 ice1712UI_GetCombo(ice1712 *card, uint32 index);
static void ice1712UI_SetCombo(ice1712 *card, uint32 index, uint32 value);
static uint32 ice1712UI_GetOutput(ice1712 *card, uint32 index);
static void ice1712UI_SetOutput(ice1712 *card, uint32 index, uint32 value);
static void ice1712UI_GetVolume(ice1712 *card, multi_mix_value *mmv);
static void ice1712UI_SetVolume(ice1712 *card, multi_mix_value *mmv);
static void ice1712UI_CreateOutput(ice1712 *card, multi_mix_control **p_mmc,
int32 output, int32 parent);
static void ice1712UI_CreateCombo(multi_mix_control **p_mmc,
const char *values[], int32 parent, int32 nb_combo, const char *name);
static void ice1712UI_CreateChannel(multi_mix_control **p_mmc,
int32 channel, int32 parent, const char* name);
static int32 ice1712UI_CreateGroup(multi_mix_control **p_mmc,
int32 index, int32 parent, enum strind_id string, const char* name);
static int32 nb_control_created;
#define AUTHORIZED_RATE (B_SR_SAME_AS_INPUT | B_SR_96000 \
| B_SR_88200 | B_SR_48000 | B_SR_44100)
#define AUTHORIZED_SAMPLE_SIZE (B_FMT_24BIT)
#define MAX_CONTROL 32
void
ice1712Buffer_Start(ice1712 *card)
{
uint16 size = card->buffer_size * MAX_DAC;
write_mt_uint8(card, MT_PROF_PB_CONTROL, 0);
write_mt_uint32(card, MT_PROF_PB_DMA_BASE_ADDRESS,
(uint32)(card->phys_pb.address));
write_mt_uint16(card, MT_PROF_PB_DMA_COUNT_ADDRESS,
(size * SWAPPING_BUFFERS) - 1);
write_mt_uint16(card, MT_PROF_PB_DMA_TERM_COUNT, size - 1);
ITRACE("SIZE DMA PLAYBACK %#x\n", size);
size = card->buffer_size * MAX_ADC;
write_mt_uint32(card, MT_PROF_REC_DMA_BASE_ADDRESS,
(uint32)(card->phys_rec.address));
write_mt_uint16(card, MT_PROF_REC_DMA_COUNT_ADDRESS,
(size * SWAPPING_BUFFERS) - 1);
write_mt_uint16(card, MT_PROF_REC_DMA_TERM_COUNT, 0);
ITRACE("SIZE DMA RECORD %#x\n", size);
switch (card->config.product) {
case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_DELTA44:
case ICE1712_SUBDEVICE_AUDIOPHILE_2496:
case ICE1712_SUBDEVICE_DELTADIO2496:
case ICE1712_SUBDEVICE_DELTA410:
case ICE1712_SUBDEVICE_DELTA1010LT:
case ICE1712_SUBDEVICE_DELTA1010:
codec_write(card, AK45xx_CLOCK_FORMAT_REGISTER, 0x69);
codec_write(card, AK45xx_RESET_REGISTER, 0x03);
break;
case ICE1712_SUBDEVICE_VX442:
break;
}
switch (card->config.product) {
case ICE1712_SUBDEVICE_DELTA1010:
break;
case ICE1712_SUBDEVICE_DELTADIO2496:
break;
case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_DELTA44:
break;
case ICE1712_SUBDEVICE_AUDIOPHILE_2496:
spdif_write(card, CS84xx_SERIAL_INPUT_FORMAT_REG, 0x85);
spdif_write(card, CS84xx_SERIAL_OUTPUT_FORMAT_REG, 0x85);
break;
case ICE1712_SUBDEVICE_DELTA410:
break;
case ICE1712_SUBDEVICE_DELTA1010LT:
break;
case ICE1712_SUBDEVICE_VX442:
break;
}
card->buffer = 1;
write_mt_uint8(card, MT_PROF_PB_CONTROL, 5);
}
status_t
ice1712Buffer_Exchange(ice1712 *card, multi_buffer_info *data)
{
multi_buffer_info buffer_info;
#ifdef __HAIKU__
if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK)
return B_BAD_ADDRESS;
#else
memcpy(&buffer_info, data, sizeof(buffer_info));
#endif
buffer_info.flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD;
if (acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT
| B_CAN_INTERRUPT, 50000) == B_TIMED_OUT) {
ITRACE("buffer_exchange timeout\n");
};
buffer_info.played_real_time = card->played_time;
buffer_info.played_frames_count = card->frames_count;
buffer_info.playback_buffer_cycle = (card->buffer - 1)
% SWAPPING_BUFFERS;
buffer_info.recorded_real_time = card->played_time;
buffer_info.recorded_frames_count = card->frames_count;
buffer_info.record_buffer_cycle = (card->buffer - 1)
% SWAPPING_BUFFERS;
#ifdef __HAIKU__
if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK)
return B_BAD_ADDRESS;
#else
memcpy(data, &buffer_info, sizeof(buffer_info));
#endif
return B_OK;
}
status_t
ice1712Buffer_Stop(ice1712 *card)
{
write_mt_uint8(card, MT_PROF_PB_CONTROL, 0);
card->played_time = 0;
card->frames_count = 0;
card->buffer = 0;
return B_OK;
}
status_t
ice1712Get_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->config.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", 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;
ITRACE_VV("request_channel_count = %" B_PRIi32 "\n",
data->request_channel_count);
if (size <= data->request_channel_count) {
for (i = 0; i < card->config.nb_DAC; i++) {
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) {
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++) {
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) {
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++;
}
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++;
}
ITRACE("output_channel_count = %" B_PRIi32 "\n",
data->output_channel_count);
ITRACE("input_channel_count = %" B_PRIi32 "\n",
data->input_channel_count);
ITRACE("output_bus_channel_count = %" B_PRIi32 "\n",
data->output_bus_channel_count);
ITRACE("input_bus_channel_count = %" B_PRIi32 "\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;
}
status_t
ice1712Get_Channel(ice1712 *card, multi_channel_enable *data)
{
int i, total_channel;
uint8 reg;
total_channel = card->total_output_channels + card->total_input_channels;
for (i = 0; i < total_channel; i++)
B_SET_CHANNEL(data->enable_bits, i, true);
reg = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT);
if (reg == 0x10)
data->lock_source = B_MULTI_LOCK_SPDIF;
else
data->lock_source = B_MULTI_LOCK_INTERNAL;
return B_OK;
}
status_t
ice1712Set_Channel(ice1712 *card, multi_channel_enable *data)
{
int i;
int total_channel;
total_channel = card->total_output_channels + card->total_input_channels;
for (i = 0; i < total_channel; i++)
ITRACE_VV("set_enabled_channels %d : %s\n", i,
B_TEST_CHANNEL(data->enable_bits, i) ? "enabled": "disabled");
ITRACE_VV("lock_source %" B_PRIx32 "\n", data->lock_source);
ITRACE_VV("lock_data %" B_PRIx32 "\n", data->lock_data);
if (data->lock_source == B_MULTI_LOCK_SPDIF)
write_mt_uint8(card, MT_SAMPLING_RATE_SELECT, 0x10);
else
write_mt_uint8(card, MT_SAMPLING_RATE_SELECT,
card->config.samplingRate);
card->config.lockSource = data->lock_source;
return B_OK;
}
status_t
ice1712Get_Format(ice1712 *card, multi_format_info *data)
{
uint8 sr = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT);
switch (sr) {
case ICE1712_SAMPLERATE_48K:
data->input.rate = data->output.rate = B_SR_48000;
data->input.cvsr = data->output.cvsr = 48000.0f;
break;
case ICE1712_SAMPLERATE_96K:
data->input.rate = data->output.rate = B_SR_96000;
data->input.cvsr = data->output.cvsr = 96000.0f;
break;
case ICE1712_SAMPLERATE_44K1:
data->input.rate = data->output.rate = B_SR_44100;
data->input.cvsr = data->output.cvsr = 44100.0f;
break;
case ICE1712_SAMPLERATE_88K2:
data->input.rate = data->output.rate = B_SR_88200;
data->input.cvsr = data->output.cvsr = 88200.0f;
break;
}
data->timecode_kind = 0;
data->output_latency = data->input_latency = 0;
data->output.format = data->input.format = AUTHORIZED_SAMPLE_SIZE;
ITRACE("Sampling Rate = %f\n", data->input.cvsr);
return B_OK;
}
status_t
ice1712Set_Format(ice1712 *card, multi_format_info *data)
{
ITRACE("Input Sampling Rate = %" B_PRIu32 "\n",
data->input.rate);
ITRACE("Output Sampling Rate = %" B_PRIu32 "\n",
data->output.rate);
if (data->input.rate != data->output.rate)
return B_OK;
if (card->config.lockSource == B_MULTI_LOCK_INTERNAL) {
switch (data->output.rate) {
case B_SR_96000:
card->config.samplingRate = 0x07;
break;
case B_SR_88200:
card->config.samplingRate = 0x0B;
break;
case B_SR_48000:
card->config.samplingRate = 0x00;
break;
case B_SR_44100:
card->config.samplingRate = 0x08;
break;
}
write_mt_uint8(card, MT_SAMPLING_RATE_SELECT,
card->config.samplingRate);
}
ITRACE("New rate = %#x\n", read_mt_uint8(card, MT_SAMPLING_RATE_SELECT));
return B_OK;
}
static const char *Clock[] = {
"Internal",
"Digital",
NULL,
};
static const char *DigitalFormat[] = {
"Consumer",
"Professional",
NULL,
};
static const char *DigitalEmphasis[] = {
"None",
"CCITT",
"15/50usec",
NULL,
};
static const char *DigitalCopyMode[] = {
"Original",
"1st Generation",
"No SCMS",
NULL,
};
static const char **SettingsGeneral[] = {
Clock,
NULL,
};
static const char **SettingsDigital[] = {
DigitalFormat,
DigitalEmphasis,
DigitalCopyMode,
NULL,
};
static const char *string_list[] = {
"Setup",
"General",
"Digital",
"Output Selection",
"Internal Mixer",
"Master clock",
"reserved_0",
"reserved_1",
"Output format",
"Emphasis",
"Copy mode",
"Output 1",
"Output 2",
"Output 3",
"Output 4",
"Digital Output",
"Haiku output",
"Input 1",
"Input 2",
"Input 3",
"Input 4",
"Digital Input",
"Internal mixer",
};
* This will create a Tab
*/
int32
ice1712UI_CreateGroup(multi_mix_control **p_mmc, int32 index,
int32 parent, enum strind_id string, const char* name)
{
multi_mix_control *mmc = *p_mmc;
int32 group;
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);
ITRACE_VV("Create Group: ID %#" B_PRIx32 "\n", mmc->id);
nb_control_created++; mmc++;
(*p_mmc) = mmc;
return group;
}
* This will create a Slider with a "Mute" CheckBox
*/
void
ice1712UI_CreateChannel(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;
control.master = CONTROL_IS_MASTER;
control.parent = parent;
control.gain.max_gain = 0.0;
control.gain.min_gain = -144.0;
control.gain.granularity = 1.5;
control.id = id++;
control.flags = B_MULTI_MIX_ENABLE;
control.string = S_MUTE;
*mmc = control;
mmc++;
ITRACE_VV("Create Channel (Mute): ID %#" B_PRIx32 "\n", control.id);
control.string = S_null;
control.id = id++;
control.flags = B_MULTI_MIX_GAIN;
if (name != NULL)
strcpy(control.name, name);
*mmc = control;
mmc++;
ITRACE_VV("Create Channel (Left): ID %#" B_PRIx32 "\n", control.id);
control.master = control.id;
control.id = id++;
*mmc = control;
mmc++;
ITRACE_VV("Create Channel (Right): ID %#" B_PRIx32 "\n", control.id);
nb_control_created += 3;
(*p_mmc) = mmc;
}
void
ice1712UI_CreateCombo(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;
parentControl = mmc->id = id++;
mmc->flags = B_MULTI_MIX_MUX;
mmc->parent = parent;
strcpy(mmc->name, name);
ITRACE_VV("Create Combo (label): ID %#" B_PRIx32 "\n", parentControl);
nb_control_created++; mmc++;
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]);
ITRACE_VV("Create Combo (value): ID %#" B_PRIx32 "\n", mmc->id);
nb_control_created++; mmc++;
}
(*p_mmc) = mmc;
}
* This will create all possible value for the output
* output 0 -> 3 (physical stereo output) 4 is the Digital
*/
void
ice1712UI_CreateOutput(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;
parentControl = mmc->id = id++;
mmc->flags = B_MULTI_MIX_MUX;
mmc->parent = parent;
strcpy(mmc->name, string_list[11 + output]);
nb_control_created++; mmc++;
ITRACE_VV("Create Output (label): ID %#" B_PRIx32 "\n", parentControl);
mmc->id = id++;
mmc->flags = B_MULTI_MIX_MUX_VALUE;
mmc->parent = parentControl;
strcpy(mmc->name, string_list[16]);
ITRACE_VV("Create Output (Haiku): ID %#" B_PRIx32 "\n", mmc->id);
nb_control_created++; mmc++;
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)]);
ITRACE_VV("Create Output (Physical In): ID %#" B_PRIx32 "\n", mmc->id);
nb_control_created++; mmc++;
}
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]);
ITRACE_VV("Create Output (Digital In) ID %#" B_PRIx32 "\n", mmc->id);
nb_control_created++; mmc++;
}
if ((output == 0) || (output == 4)) {
mmc->id = id++;
mmc->flags = B_MULTI_MIX_MUX_VALUE;
mmc->parent = parentControl;
strcpy(mmc->name, string_list[22]);
ITRACE_VV("Create Output (Mix); ID %#" B_PRIx32 "\n", mmc->id);
nb_control_created++; mmc++;
}
(*p_mmc) = mmc;
}
uint32
ice1712UI_GetCombo(ice1712 *card, uint32 index)
{
uint32 value = 0;
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;
}
ITRACE_VV("Get combo: %" B_PRIu32 ", %" B_PRIu32 "\n",
index, value);
return value;
}
void
ice1712UI_SetCombo(ice1712 *card, uint32 index, uint32 value)
{
ITRACE_VV("Set combo: %" B_PRIu32 ", %" B_PRIu32 "\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;
}
}
uint32
ice1712UI_GetOutput(ice1712 *card, uint32 index)
{
uint32 value = 0;
if (index < 5)
value = card->settings.output[index];
ITRACE_VV("Get output: %" B_PRIu32 ", %" B_PRIu32 "\n", index, value);
return value;
}
void
ice1712UI_SetOutput(ice1712 *card, uint32 index, uint32 value)
{
if (index < 5)
card->settings.output[index] = value;
ITRACE_VV("Set output: %" B_PRIu32 ", %" B_PRIu32 "\n", index, value);
}
void
ice1712UI_GetVolume(ice1712 *card, multi_mix_value *mmv)
{
ice1712Volume *vol;
uint32 chan = ICE1712_MULTI_GET_CHANNEL(mmv->id);
ITRACE_VV("Get volume\n");
if (chan < ICE1712_HARDWARE_VOLUME) {
vol = card->settings.playback;
} else {
vol = card->settings.record;
chan -= ICE1712_HARDWARE_VOLUME;
}
switch (ICE1712_MULTI_GET_INDEX(mmv->id)) {
case 0:
mmv->enable = vol[chan].mute | vol[chan + 1].mute;
ITRACE_VV(" Get mute %d for channel %d or %d\n",
mmv->enable, (int)chan, (int)chan + 1);
break;
case 2:
chan++;
case 1:
mmv->gain = vol[chan].volume;
ITRACE_VV(" Get Volume %f for channel %d\n",
mmv->gain, (int)chan);
break;
}
}
void
ice1712UI_SetVolume(ice1712 *card, multi_mix_value *mmv)
{
ice1712Volume *vol;
uint32 chan = ICE1712_MULTI_GET_CHANNEL(mmv->id);
ITRACE_VV("Set volume\n");
if (chan < ICE1712_HARDWARE_VOLUME) {
vol = card->settings.playback;
} else {
vol = card->settings.record;
chan -= ICE1712_HARDWARE_VOLUME;
}
switch (ICE1712_MULTI_GET_INDEX(mmv->id)) {
case 0:
vol[chan].mute = mmv->enable;
vol[chan + 1].mute = mmv->enable;
ITRACE_VV(" Change mute to %d for channel %d and %d\n",
mmv->enable, (int)chan, (int)chan + 1);
break;
case 2:
chan++;
case 1:
vol[chan].volume = mmv->gain;
ITRACE_VV(" Change Volume to %f for channel %d\n",
mmv->gain, (int)chan);
break;
}
}
status_t
ice1712Get_MixValue(ice1712 *card, multi_mix_value_info *data)
{
int i;
for (i = 0; i < data->item_count; i++) {
multi_mix_value *mmv = &(data->values[i]);
ITRACE_VV("Get Mix: Id %" B_PRIu32 "\n", mmv->id);
switch (mmv->id & ICE1712_MULTI_CONTROL_TYPE_MASK) {
case ICE1712_MULTI_CONTROL_TYPE_COMBO:
mmv->mux = ice1712UI_GetCombo(card,
ICE1712_MULTI_GET_CHANNEL(mmv->id));
break;
case ICE1712_MULTI_CONTROL_TYPE_VOLUME:
ice1712UI_GetVolume(card, mmv);
break;
case ICE1712_MULTI_CONTROL_TYPE_OUTPUT:
mmv->mux = ice1712UI_GetOutput(card,
ICE1712_MULTI_GET_CHANNEL(mmv->id));
break;
default:
ITRACE_VV("Get Mix: unknow %" B_PRIu32 "\n", mmv->id);
break;
}
}
return B_OK;
}
status_t
ice1712Set_MixValue(ice1712 *card, multi_mix_value_info *data)
{
int i;
for (i = 0; i < data->item_count; i++) {
multi_mix_value *mmv = &(data->values[i]);
ITRACE_VV("Set Mix: Id %" B_PRIu32 "\n", mmv->id);
switch (mmv->id & ICE1712_MULTI_CONTROL_TYPE_MASK) {
case ICE1712_MULTI_CONTROL_TYPE_COMBO:
ice1712UI_SetCombo(card,
ICE1712_MULTI_GET_CHANNEL(mmv->id), mmv->mux);
break;
case ICE1712_MULTI_CONTROL_TYPE_VOLUME:
ice1712UI_SetVolume(card, mmv);
break;
case ICE1712_MULTI_CONTROL_TYPE_OUTPUT:
ice1712UI_SetOutput(card,
ICE1712_MULTI_GET_CHANNEL(mmv->id), mmv->mux);
break;
default:
ITRACE_VV("Set Mix: unknow %" B_PRIu32 "\n", mmv->id);
break;
}
}
return ice1712Settings_apply(card);
}
* Not implemented
*/
status_t
ice1712Get_MixValueChannel(ice1712 *card, multi_mix_channel_info *data)
{
return B_OK;
}
status_t
ice1712Get_MixValueControls(ice1712 *card, multi_mix_control_info *mmci)
{
int32 i;
uint32 parentTab, parentTabColumn;
multi_mix_control *mmc = mmci->controls;
uint32 group = 0, combo = 0, channel = 0;
nb_control_created = 0;
ITRACE_VV("Get MixValue Channels: Max %" B_PRIi32 "\n", mmci->control_count);
memset(mmc, 0, mmci->control_count * sizeof(multi_mix_control));
parentTab = ice1712UI_CreateGroup(&mmc, group++,
CONTROL_IS_MASTER, S_SETUP, NULL);
parentTabColumn = ice1712UI_CreateGroup(&mmc, group++, parentTab,
S_null, string_list[1]);
for (i = 0; SettingsGeneral[i] != NULL; i++) {
ice1712UI_CreateCombo(&mmc, SettingsGeneral[i], parentTabColumn,
combo++, string_list[5 + i]);
}
parentTabColumn = ice1712UI_CreateGroup(&mmc, group++, parentTab,
S_null, string_list[2]);
for (i = 0; SettingsDigital[i] != NULL; i++) {
ice1712UI_CreateCombo(&mmc, SettingsDigital[i], parentTabColumn,
combo++, string_list[8 + i]);
}
parentTabColumn = ice1712UI_CreateGroup(&mmc, group++, parentTab,
S_null, string_list[3]);
for (i = 0; i < card->config.nb_DAC; i += 2) {
ice1712UI_CreateOutput(card, &mmc, i / 2, parentTabColumn);
}
if (card->config.spdif & SPDIF_OUT_PRESENT) {
ice1712UI_CreateOutput(card, &mmc, 4, parentTabColumn);
}
parentTab = ice1712UI_CreateGroup(&mmc, group++, CONTROL_IS_MASTER,
S_null, string_list[4]);
for (i = 0; i < card->config.nb_DAC; i += 2) {
parentTabColumn = ice1712UI_CreateGroup(&mmc, group++,
parentTab, S_null, string_list[(i / 2) + 11]);
ice1712UI_CreateChannel(&mmc, channel++, parentTabColumn, NULL);
}
if (card->config.spdif & SPDIF_OUT_PRESENT) {
parentTabColumn = ice1712UI_CreateGroup(&mmc, group++,
parentTab, S_null, string_list[15]);
ice1712UI_CreateChannel(&mmc, ICE1712_HARDWARE_VOLUME - 2,
parentTabColumn, NULL);
}
channel = ICE1712_HARDWARE_VOLUME;
for (i = 0; i < card->config.nb_ADC; i += 2) {
parentTabColumn = ice1712UI_CreateGroup(&mmc, group++,
parentTab, S_null, string_list[(i / 2) + 17]);
ice1712UI_CreateChannel(&mmc, channel++, parentTabColumn, NULL);
}
if (card->config.spdif & SPDIF_IN_PRESENT) {
parentTabColumn = ice1712UI_CreateGroup(&mmc, group++,
parentTab, S_null, string_list[21]);
ice1712UI_CreateChannel(&mmc, 2 * ICE1712_HARDWARE_VOLUME - 2,
parentTabColumn, NULL);
}
mmci->control_count = nb_control_created;
ITRACE_VV("Get MixValue Channels: Returned %" B_PRIi32 "\n",
mmci->control_count);
return B_OK;
}
* Not implemented
*/
status_t
ice1712Get_MixValueConnections(ice1712 *card,
multi_mix_connection_info *data)
{
data->actual_count = 0;
return B_OK;
}
status_t
ice1712Buffer_Get(ice1712 *card, multi_buffer_list *data)
{
const size_t stride_o = MAX_DAC * SAMPLE_SIZE;
const size_t stride_i = MAX_ADC * SAMPLE_SIZE;
const uint32 buf_o = stride_o * card->buffer_size;
const uint32 buf_i = stride_i * card->buffer_size;
int buff, chan_i = 0, chan_o = 0;
ITRACE_VV("flags = %#" B_PRIx32 "\n", data->flags);
ITRACE_VV("request_playback_buffers = %" B_PRIu32 "\n",
data->request_playback_buffers);
ITRACE_VV("request_playback_channels = %" B_PRIu32 "\n",
data->request_playback_channels);
ITRACE_VV("request_playback_buffer_size = %" B_PRIx32 "\n",
data->request_playback_buffer_size);
ITRACE_VV("request_record_buffers = %" B_PRIu32 "\n",
data->request_record_buffers);
ITRACE_VV("request_record_channels = %" B_PRIu32 "\n",
data->request_record_channels);
ITRACE_VV("request_record_buffer_size = %" B_PRIx32 "\n",
data->request_record_buffer_size);
for (buff = 0; buff < SWAPPING_BUFFERS; buff++) {
if (data->request_playback_channels == card->total_output_channels) {
for (chan_o = 0; chan_o < card->config.nb_DAC; chan_o++) {
data->playback_buffers[buff][chan_o].base =
(char*)(card->log_addr_pb + buf_o * buff
+ SAMPLE_SIZE * chan_o);
data->playback_buffers[buff][chan_o].stride = stride_o;
ITRACE_VV("pb_buffer[%d][%d] = %p\n", buff, chan_o,
data->playback_buffers[buff][chan_o].base);
}
if (card->config.spdif & SPDIF_OUT_PRESENT) {
data->playback_buffers[buff][chan_o].base =
(char*)(card->log_addr_pb + buf_o * buff
+ SAMPLE_SIZE * SPDIF_LEFT);
data->playback_buffers[buff][chan_o].stride = stride_o;
ITRACE_VV("pb_buffer[%d][%d] = %p\n", buff, chan_o,
data->playback_buffers[buff][chan_o].base);
chan_o++;
data->playback_buffers[buff][chan_o].base =
(char*)(card->log_addr_pb + buf_o * buff
+ SAMPLE_SIZE * SPDIF_RIGHT);
data->playback_buffers[buff][chan_o].stride = stride_o;
ITRACE_VV("pb_buffer[%d][%d] = %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++) {
data->record_buffers[buff][chan_i].base =
(char*)(card->log_addr_rec + buf_i * buff
+ SAMPLE_SIZE * chan_i);
data->record_buffers[buff][chan_i].stride = stride_i;
ITRACE_VV("rec_buffer[%d][%d] = %p\n", buff, chan_i,
data->record_buffers[buff][chan_i].base);
}
if (card->config.spdif & SPDIF_IN_PRESENT) {
data->record_buffers[buff][chan_i].base =
(char*)(card->log_addr_rec + buf_i * buff
+ SAMPLE_SIZE * SPDIF_LEFT);
data->record_buffers[buff][chan_i].stride = stride_i;
ITRACE_VV("rec_buffer[%d][%d] = %p\n", buff, chan_i,
data->record_buffers[buff][chan_i].base);
chan_i++;
data->record_buffers[buff][chan_i].base =
(char*)(card->log_addr_rec + buf_i * buff
+ SAMPLE_SIZE * SPDIF_RIGHT);
data->record_buffers[buff][chan_i].stride = stride_i;
ITRACE_VV("rec_buffer[%d][%d] = %p\n", buff, chan_i,
data->record_buffers[buff][chan_i].base);
chan_i++;
}
data->record_buffers[buff][chan_i].base =
(char*)(card->log_addr_rec + buf_i * buff
+ SAMPLE_SIZE * MIXER_OUT_LEFT);
data->record_buffers[buff][chan_i].stride = stride_i;
ITRACE_VV("rec_buffer[%d][%d] = %p\n", buff, chan_i,
data->record_buffers[buff][chan_i].base);
chan_i++;
data->record_buffers[buff][chan_i].base =
(char*)(card->log_addr_rec + buf_i * buff
+ SAMPLE_SIZE * MIXER_OUT_RIGHT);
data->record_buffers[buff][chan_i].stride = stride_i;
ITRACE_VV("rec_buffer[%d][%d] = %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;
ITRACE("return_playback_buffers = %" B_PRIi32 "\n",
data->return_playback_buffers);
ITRACE("return_playback_channels = %" B_PRIi32 "\n",
data->return_playback_channels);
ITRACE("return_playback_buffer_size = %" B_PRIu32 "\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;
ITRACE("return_record_buffers = %" B_PRIi32 "\n",
data->return_record_buffers);
ITRACE("return_record_channels = %" B_PRIi32 "\n",
data->return_record_channels);
ITRACE("return_record_buffer_size = %" B_PRIu32 "\n",
data->return_record_buffer_size);
ice1712Buffer_Start(card);
return B_OK;
}