* 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:
@@ -37,7 +37,7 @@
|
|||||||
#define HDA_MAX_AUDIO_GROUPS 15
|
#define HDA_MAX_AUDIO_GROUPS 15
|
||||||
#define HDA_MAX_CODECS 15
|
#define HDA_MAX_CODECS 15
|
||||||
#define HDA_MAX_STREAMS 16
|
#define HDA_MAX_STREAMS 16
|
||||||
#define MAX_CODEC_RESPONSES 10
|
#define MAX_CODEC_RESPONSES 16
|
||||||
#define MAX_INPUTS 32
|
#define MAX_INPUTS 32
|
||||||
#define MAX_IO_WIDGETS 8
|
#define MAX_IO_WIDGETS 8
|
||||||
#define MAX_ASSOCIATIONS 16
|
#define MAX_ASSOCIATIONS 16
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ dump_widget_pm_support(hda_widget& widget)
|
|||||||
static void
|
static void
|
||||||
dump_widget_stream_support(hda_widget& widget)
|
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_8BIT_S ? "8bits " : "",
|
||||||
widget.d.io.formats & B_FMT_16BIT ? "16bits " : "",
|
widget.d.io.formats & B_FMT_16BIT ? "16bits " : "",
|
||||||
widget.d.io.formats & B_FMT_20BIT ? "20bits " : "",
|
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_32BIT ? "32bits " : "",
|
||||||
widget.d.io.formats & B_FMT_FLOAT ? "float " : "",
|
widget.d.io.formats & B_FMT_FLOAT ? "float " : "",
|
||||||
widget.d.io.formats & B_FMT_DOUBLE ? "double " : "",
|
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",
|
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_8000 ? "8khz " : "",
|
||||||
widget.d.io.rates & B_SR_11025 ? "11khz " : "",
|
widget.d.io.rates & B_SR_11025 ? "11khz " : "",
|
||||||
@@ -885,13 +886,17 @@ dprintf("build tree!\n");
|
|||||||
widget.active_input = 0;
|
widget.active_input = 0;
|
||||||
if (widget.num_inputs < 2)
|
if (widget.num_inputs < 2)
|
||||||
continue;
|
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,
|
corb_t verb = MAKE_VERB(audioGroup->codec->addr,
|
||||||
widget.node_id, VID_SET_CONNECTION_SELECT, widget.active_input);
|
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",
|
dprintf("hda: Setting output selector %ld failed on widget %ld!\n",
|
||||||
widget.active_input, widget.node_id);
|
widget.active_input, widget.node_id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_audiogroup_widgets(audioGroup);
|
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_INPUT | AMP_SET_LEFT_CHANNEL
|
||||||
| AMP_SET_RIGHT_CHANNEL
|
| AMP_SET_RIGHT_CHANNEL
|
||||||
| AMP_SET_INPUT_INDEX(i)
|
| AMP_SET_INPUT_INDEX(i)
|
||||||
|
| ((widget.active_input == (int32)i) ? 0 : AMP_MUTE)
|
||||||
| AMP_CAP_OFFSET(widget.capabilities.input_amplifier));
|
| AMP_CAP_OFFSET(widget.capabilities.input_amplifier));
|
||||||
hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
|
hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
B_MIX_GAIN = 1 << 0,
|
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;
|
} 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
|
static int32
|
||||||
hda_create_group_control(hda_multi *multi, uint32 *index, int32 parent,
|
hda_create_group_control(hda_multi *multi, uint32 *index, int32 parent,
|
||||||
enum strind_id string, const char* name) {
|
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
|
static void
|
||||||
hda_find_multi_string(hda_widget& widget)
|
hda_create_mux_control(hda_multi *multi, uint32 *index, int32 parent, hda_widget& widget) {
|
||||||
{
|
uint32 i = *index, parent2;
|
||||||
switch (CONF_DEFAULT_DEVICE(widget.d.pin.config)) {
|
hda_multi_mixer_control control;
|
||||||
case PIN_DEV_CD:
|
hda_audio_group *audioGroup = multi->group;
|
||||||
return S_CD;
|
|
||||||
case PIN_DEV_LINE_IN:
|
control.nid = widget.node_id;
|
||||||
case PIN_DEV_LINE_OUT:
|
control.input = true;
|
||||||
return S_LINE;
|
control.mute = 0;
|
||||||
case PIN_DEV_MIC_IN:
|
control.gain = 0;
|
||||||
return S_MIC;
|
control.mix_control.master = MULTI_CONTROL_MASTERID;
|
||||||
case PIN_DEV_AUX:
|
control.mix_control.parent = parent;
|
||||||
return S_AUX;
|
control.mix_control.id = MULTI_CONTROL_FIRSTID + i;
|
||||||
case PIN_DEV_SPDIF_IN:
|
control.mix_control.flags = B_MULTI_MIX_MUX;
|
||||||
case PIN_DEV_SPDIF_OUT:
|
control.mix_control.string = S_null;
|
||||||
return S_SPDIF;
|
control.type = (widget.type == WT_AUDIO_MIXER) ? B_MIX_MUX_MIXER : B_MIX_MUX_SELECTOR;
|
||||||
case PIN_DEV_HEAD_PHONE_OUT:
|
multi->controls[i] = control;
|
||||||
return S_HEADPHONE;
|
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;
|
*index = i;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -450,6 +493,12 @@ hda_create_controls_list(hda_multi *multi)
|
|||||||
bool gain = true, mute = true;
|
bool gain = true, mute = true;
|
||||||
hda_create_channel_control(multi, &index, parent2, 0,
|
hda_create_channel_control(multi, &index, parent2, 0,
|
||||||
widget, true, capabilities, 0, gain, mute);
|
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;
|
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);
|
* AMP_CAP_STEP_SIZE(control->capabilities);
|
||||||
TRACE("get_mix: %ld gain: %f (%ld)\n", control->nid, mmvi->values[i].gain, value);
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -659,14 +728,29 @@ set_mix(hda_audio_group* audioGroup, multi_mix_value_info * mmvi)
|
|||||||
|
|
||||||
if (control2)
|
if (control2)
|
||||||
i++;
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user