From ba4d7ed20dbd4cf97ca7e8a869e958ffd659b725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 13 Sep 2009 21:58:22 +0000 Subject: [PATCH] * 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 --- src/add-ons/kernel/drivers/audio/hda/driver.h | 2 +- .../kernel/drivers/audio/hda/hda_codec.cpp | 14 +- .../drivers/audio/hda/hda_multi_audio.cpp | 238 ++++++++++++------ 3 files changed, 172 insertions(+), 82 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.h b/src/add-ons/kernel/drivers/audio/hda/driver.h index 0fe8000329..3924b75698 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.h +++ b/src/add-ons/kernel/drivers/audio/hda/driver.h @@ -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 diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp b/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp index b6fe832f0a..d185ff9542 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp @@ -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); } diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.cpp b/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.cpp index 0c8f2a40a7..ab10df2327 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.cpp @@ -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; }