* added input selector controls

* increased responses count
* only unmute active inputs on mixer widgets


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33120 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2009-09-13 21:58:22 +00:00
parent afdc051482
commit ba4d7ed20d
3 changed files with 172 additions and 82 deletions
@@ -37,7 +37,7 @@
#define HDA_MAX_AUDIO_GROUPS 15
#define HDA_MAX_CODECS 15
#define HDA_MAX_STREAMS 16
#define MAX_CODEC_RESPONSES 10
#define MAX_CODEC_RESPONSES 16
#define MAX_INPUTS 32
#define MAX_IO_WIDGETS 8
#define MAX_ASSOCIATIONS 16
@@ -154,7 +154,7 @@ dump_widget_pm_support(hda_widget& widget)
static void
dump_widget_stream_support(hda_widget& widget)
{
dprintf("\tSupported formats: %s%s%s%s%s%s%s%s\n",
dprintf("\tSupported formats: %s%s%s%s%s%s%s%s%s\n",
widget.d.io.formats & B_FMT_8BIT_S ? "8bits " : "",
widget.d.io.formats & B_FMT_16BIT ? "16bits " : "",
widget.d.io.formats & B_FMT_20BIT ? "20bits " : "",
@@ -162,7 +162,8 @@ dump_widget_stream_support(hda_widget& widget)
widget.d.io.formats & B_FMT_32BIT ? "32bits " : "",
widget.d.io.formats & B_FMT_FLOAT ? "float " : "",
widget.d.io.formats & B_FMT_DOUBLE ? "double " : "",
widget.d.io.formats & B_FMT_EXTENDED ? "extended " : "");
widget.d.io.formats & B_FMT_EXTENDED ? "extended " : "",
widget.d.io.formats & B_FMT_BITSTREAM ? "bitstream " : "");
dprintf("\tSupported rates: %s%s%s%s%s%s%s%s%s%s%s%s\n",
widget.d.io.rates & B_SR_8000 ? "8khz " : "",
widget.d.io.rates & B_SR_11025 ? "11khz " : "",
@@ -885,13 +886,17 @@ dprintf("build tree!\n");
widget.active_input = 0;
if (widget.num_inputs < 2)
continue;
if (widget.type != WT_AUDIO_INPUT
&& widget.type != WT_AUDIO_SELECTOR
&& widget.type != WT_PIN_COMPLEX)
continue;
corb_t verb = MAKE_VERB(audioGroup->codec->addr,
widget.node_id, VID_SET_CONNECTION_SELECT, widget.active_input);
if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK) {
if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK)
dprintf("hda: Setting output selector %ld failed on widget %ld!\n",
widget.active_input, widget.node_id);
}
}
dump_audiogroup_widgets(audioGroup);
@@ -1039,6 +1044,7 @@ dprintf("UNMUTE/SET INPUT GAIN widget %ld (offset %ld)\n", widget.node_id,
AMP_SET_INPUT | AMP_SET_LEFT_CHANNEL
| AMP_SET_RIGHT_CHANNEL
| AMP_SET_INPUT_INDEX(i)
| ((widget.active_input == (int32)i) ? 0 : AMP_MUTE)
| AMP_CAP_OFFSET(widget.capabilities.input_amplifier));
hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
}
@@ -25,7 +25,9 @@
typedef enum {
B_MIX_GAIN = 1 << 0,
B_MIX_MUTE = 1 << 1
B_MIX_MUTE = 1 << 1,
B_MIX_MUX_MIXER = 1 << 2,
B_MIX_MUX_SELECTOR = 1 << 3
} mixer_type;
@@ -191,6 +193,73 @@ set_global_format(hda_audio_group* audioGroup, multi_format_info* data)
}
static enum strind_id
hda_find_multi_string(hda_widget& widget)
{
switch (CONF_DEFAULT_DEVICE(widget.d.pin.config)) {
case PIN_DEV_CD:
return S_CD;
case PIN_DEV_LINE_IN:
case PIN_DEV_LINE_OUT:
return S_LINE;
case PIN_DEV_MIC_IN:
return S_MIC;
case PIN_DEV_AUX:
return S_AUX;
case PIN_DEV_SPDIF_IN:
case PIN_DEV_SPDIF_OUT:
return S_SPDIF;
case PIN_DEV_HEAD_PHONE_OUT:
return S_HEADPHONE;
}
TRACE("couln't find a string for widget %ld in hda_find_multi_string()\n", widget.node_id);
return S_null;
}
static const char *
hda_find_multi_custom_string(hda_widget& widget)
{
switch (CONF_DEFAULT_DEVICE(widget.d.pin.config)) {
case PIN_DEV_LINE_IN:
case PIN_DEV_LINE_OUT:
case PIN_DEV_MIC_IN:
switch (CONF_DEFAULT_COLOR(widget.d.pin.config)) {
case 1:
return "Rear";
case 2:
return "Side";
case 3:
return "Line In";
case 4:
return "Front";
case 6:
return "Center/Sub";
case 9:
return "Mic in";
}
if (CONF_DEFAULT_DEVICE(widget.d.pin.config) == PIN_DEV_LINE_IN)
return "Line In";
if (CONF_DEFAULT_DEVICE(widget.d.pin.config) == PIN_DEV_MIC_IN)
return "Mic In";
return "Line Out";
break;
case PIN_DEV_SPDIF_IN:
return "SPDIF In";
case PIN_DEV_SPDIF_OUT:
return "SPDIF Out";
case PIN_DEV_CD:
return "CD";
case PIN_DEV_HEAD_PHONE_OUT:
return "Headphones";
case PIN_DEV_SPEAKER:
return "Speaker";
}
TRACE("couldn't find a string for widget %ld in hda_find_multi_custom_string()\n", widget.node_id);
return NULL;
}
static int32
hda_create_group_control(hda_multi *multi, uint32 *index, int32 parent,
enum strind_id string, const char* name) {
@@ -261,69 +330,43 @@ hda_create_channel_control(hda_multi *multi, uint32 *index, int32 parent, int32
}
static enum strind_id
hda_find_multi_string(hda_widget& widget)
{
switch (CONF_DEFAULT_DEVICE(widget.d.pin.config)) {
case PIN_DEV_CD:
return S_CD;
case PIN_DEV_LINE_IN:
case PIN_DEV_LINE_OUT:
return S_LINE;
case PIN_DEV_MIC_IN:
return S_MIC;
case PIN_DEV_AUX:
return S_AUX;
case PIN_DEV_SPDIF_IN:
case PIN_DEV_SPDIF_OUT:
return S_SPDIF;
case PIN_DEV_HEAD_PHONE_OUT:
return S_HEADPHONE;
static void
hda_create_mux_control(hda_multi *multi, uint32 *index, int32 parent, hda_widget& widget) {
uint32 i = *index, parent2;
hda_multi_mixer_control control;
hda_audio_group *audioGroup = multi->group;
control.nid = widget.node_id;
control.input = true;
control.mute = 0;
control.gain = 0;
control.mix_control.master = MULTI_CONTROL_MASTERID;
control.mix_control.parent = parent;
control.mix_control.id = MULTI_CONTROL_FIRSTID + i;
control.mix_control.flags = B_MULTI_MIX_MUX;
control.mix_control.string = S_null;
control.type = (widget.type == WT_AUDIO_MIXER) ? B_MIX_MUX_MIXER : B_MIX_MUX_SELECTOR;
multi->controls[i] = control;
strcpy(multi->controls[i].mix_control.name, "");
i++;
parent2 = control.mix_control.id;
for (uint32 j = 0; j < widget.num_inputs; j++) {
hda_widget *input = hda_audio_group_get_widget(audioGroup, widget.inputs[j]);
if (input->type != WT_PIN_COMPLEX)
continue;
control.nid = widget.node_id;
control.input = true;
control.mix_control.id = MULTI_CONTROL_FIRSTID + i;
control.mix_control.flags = B_MULTI_MIX_MUX_VALUE;
control.mix_control.parent = parent2;
control.mix_control.string = S_null;
multi->controls[i] = control;
strcpy(multi->controls[i].mix_control.name, hda_find_multi_custom_string(*input));
i++;
}
TRACE("couln't find a string for widget %ld in hda_find_multi_string()\n", widget.node_id);
return S_null;
}
static const char *
hda_find_multi_custom_string(hda_widget& widget)
{
switch (CONF_DEFAULT_DEVICE(widget.d.pin.config)) {
case PIN_DEV_LINE_IN:
case PIN_DEV_LINE_OUT:
case PIN_DEV_MIC_IN:
switch (CONF_DEFAULT_COLOR(widget.d.pin.config)) {
case 1:
return "Rear";
case 2:
return "Side";
case 3:
return "Line In";
case 4:
return "Front";
case 6:
return "Center/Sub";
case 9:
return "Mic in";
}
if (CONF_DEFAULT_DEVICE(widget.d.pin.config) == PIN_DEV_LINE_IN)
return "Line In";
if (CONF_DEFAULT_DEVICE(widget.d.pin.config) == PIN_DEV_MIC_IN)
return "Mic In";
return "Line Out";
break;
case PIN_DEV_SPDIF_IN:
return "SPDIF In";
case PIN_DEV_SPDIF_OUT:
return "SPDIF Out";
case PIN_DEV_CD:
return "CD";
case PIN_DEV_HEAD_PHONE_OUT:
return "Headphones";
case PIN_DEV_SPEAKER:
return "Speaker";
}
TRACE("couldn't find a string for widget %ld in hda_find_multi_custom_string()\n", widget.node_id);
return NULL;
*index = i;
}
@@ -450,6 +493,12 @@ hda_create_controls_list(hda_multi *multi)
bool gain = true, mute = true;
hda_create_channel_control(multi, &index, parent2, 0,
widget, true, capabilities, 0, gain, mute);
hda_widget *mixer = hda_audio_group_get_widget(audioGroup, widget.inputs[0]);
if (mixer->type != WT_AUDIO_MIXER && mixer->type != WT_AUDIO_SELECTOR)
continue;
TRACE(" create mixer nid %lu\n", mixer->node_id);
hda_create_mux_control(multi, &index, parent2, *mixer);
}
multi->control_count = index;
@@ -539,15 +588,35 @@ get_mix(hda_audio_group* audioGroup, multi_mix_value_info * mmvi)
* AMP_CAP_STEP_SIZE(control->capabilities);
TRACE("get_mix: %ld gain: %f (%ld)\n", control->nid, mmvi->values[i].gain, value);
}
} else if (control->mix_control.flags & B_MIX_MUX_MIXER) {
hda_widget *mixer = hda_audio_group_get_widget(audioGroup, control->nid);
mmvi->values[i].mux = 0;
for (uint32 j = 0; j < mixer->num_inputs; j++) {
uint32 verb = MAKE_VERB(audioGroup->codec->addr,
control->nid, VID_GET_AMPLIFIER_GAIN_MUTE, AMP_GET_INPUT
| AMP_GET_LEFT_CHANNEL | AMP_GET_INPUT_INDEX(j));
uint32 resp;
if (hda_send_verbs(audioGroup->codec, &verb, &resp, 1) == B_OK) {
TRACE("get_mix: %ld mixer %ld is %smute\n", control->nid,
j, (resp & AMP_MUTE) ? "" : "un");
if ((resp & AMP_MUTE) == 0) {
mmvi->values[i].mux = j;
#ifndef TRACE_MULTI_AUDIO
break;
#endif
}
}
}
TRACE("get_mix: %ld mixer: %ld\n", control->nid, mmvi->values[i].mux);
} else if (control->mix_control.flags & B_MIX_MUX_SELECTOR) {
uint32 verb = MAKE_VERB(audioGroup->codec->addr, control->nid,
VID_GET_CONNECTION_SELECT, 0);
uint32 resp;
if (hda_send_verbs(audioGroup->codec, &verb, &resp, 1) == B_OK)
mmvi->values[i].mux = resp & 0xff;
TRACE("get_mix: %ld selector: %ld\n", control->nid, mmvi->values[i].mux);
}
/*if (control->mix_control.flags & B_MULTI_MIX_MUX && control->get) {
float values[1];
control->get(audioGroup, control, values);
mmvi->values[i].mux = (int32)values[0];
}*/
}
return B_OK;
}
@@ -659,14 +728,29 @@ set_mix(hda_audio_group* audioGroup, multi_mix_value_info * mmvi)
if (control2)
i++;
} else if (control->mix_control.flags & B_MIX_MUX_MIXER) {
TRACE("set_mix: %ld mixer: %ld\n", control->nid, mmvi->values[i].mux);
hda_widget *mixer = hda_audio_group_get_widget(audioGroup, control->nid);
uint32 verb[mixer->num_inputs];
for (uint32 j = 0; j < mixer->num_inputs; j++) {
verb[j] = MAKE_VERB(audioGroup->codec->addr,
control->nid, VID_SET_AMPLIFIER_GAIN_MUTE, AMP_SET_INPUT
| AMP_SET_LEFT_CHANNEL | AMP_SET_RIGHT_CHANNEL | AMP_SET_INPUT_INDEX(j)
| ((mmvi->values[i].mux == j) ? 0 : AMP_MUTE));
TRACE("set_mix: %ld mixer %smuting %ld (%lx)\n", control->nid,
(mmvi->values[i].mux == j) ? "un" : "", j, verb[j]);
}
if (hda_send_verbs(audioGroup->codec, verb, NULL, mixer->num_inputs) != B_OK)
dprintf("hda: Setting mixer %ld failed on widget %ld!\n",
mmvi->values[i].mux, control->nid);
} else if (control->mix_control.flags & B_MIX_MUX_SELECTOR) {
uint32 verb = MAKE_VERB(audioGroup->codec->addr, control->nid,
VID_SET_CONNECTION_SELECT, mmvi->values[i].mux);
if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK)
dprintf("hda: Setting output selector %ld failed on widget %ld!\n",
mmvi->values[i].mux, control->nid);
TRACE("set_mix: %ld selector: %ld\n", control->nid, mmvi->values[i].mux);
}
/*if (control->mix_control.flags & B_MULTI_MIX_MUX && control->set) {
float values[1];
values[0] = (float)mmvi->values[i].mux;
control->set(card, control->channel, control->type, values);
}*/
}
return B_OK;
}