/* * Common code to disable/enable mixer emulation at run time * * Copyright (C) 2013 Red Hat, Inc. * * Written by Bandan Das <bsd@redhat.com> * with important bits picked up from hda-codec.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. */ /* * HDA codec descriptions */ #ifdef HDA_MIXER #define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x12) #define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x22) #define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x32) #define QEMU_HDA_AMP_CAPS \ (AC_AMPCAP_MUTE | \ (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT) | \ (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) | \ (3 << AC_AMPCAP_STEP_SIZE_SHIFT)) #else #define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x11) #define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x21) #define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x31) #define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE #endif /* common: audio output widget */ static const desc_param glue(common_params_audio_dac_, PARAM)[] = { { .id = AC_PAR_AUDIO_WIDGET_CAP, .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) | AC_WCAP_FORMAT_OVRD | AC_WCAP_AMP_OVRD | AC_WCAP_OUT_AMP | AC_WCAP_STEREO), },{ .id = AC_PAR_PCM, .val = QEMU_HDA_PCM_FORMATS, },{ .id = AC_PAR_STREAM, .val = AC_SUPFMT_PCM, },{ .id = AC_PAR_AMP_IN_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_AMP_OUT_CAP, .val = QEMU_HDA_AMP_CAPS, }, }; /* common: audio input widget */ static const desc_param glue(common_params_audio_adc_, PARAM)[] = { { .id = AC_PAR_AUDIO_WIDGET_CAP, .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) | AC_WCAP_CONN_LIST | AC_WCAP_FORMAT_OVRD | AC_WCAP_AMP_OVRD | AC_WCAP_IN_AMP | AC_WCAP_STEREO), },{ .id = AC_PAR_CONNLIST_LEN, .val = 1, },{ .id = AC_PAR_PCM, .val = QEMU_HDA_PCM_FORMATS, },{ .id = AC_PAR_STREAM, .val = AC_SUPFMT_PCM, },{ .id = AC_PAR_AMP_IN_CAP, .val = QEMU_HDA_AMP_CAPS, },{ .id = AC_PAR_AMP_OUT_CAP, .val = QEMU_HDA_AMP_NONE, }, }; /* common: pin widget (line-out) */ static const desc_param glue(common_params_audio_lineout_, PARAM)[] = { { .id = AC_PAR_AUDIO_WIDGET_CAP, .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | AC_WCAP_CONN_LIST | AC_WCAP_STEREO), },{ .id = AC_PAR_PIN_CAP, .val = AC_PINCAP_OUT, },{ .id = AC_PAR_CONNLIST_LEN, .val = 1, },{ .id = AC_PAR_AMP_IN_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_AMP_OUT_CAP, .val = QEMU_HDA_AMP_NONE, }, }; /* common: pin widget (line-in) */ static const desc_param glue(common_params_audio_linein_, PARAM)[] = { { .id = AC_PAR_AUDIO_WIDGET_CAP, .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | AC_WCAP_STEREO), },{ .id = AC_PAR_PIN_CAP, .val = AC_PINCAP_IN, },{ .id = AC_PAR_AMP_IN_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_AMP_OUT_CAP, .val = QEMU_HDA_AMP_NONE, }, }; /* output: root node */ static const desc_param glue(output_params_root_, PARAM)[] = { { .id = AC_PAR_VENDOR_ID, .val = QEMU_HDA_ID_OUTPUT, },{ .id = AC_PAR_SUBSYSTEM_ID, .val = QEMU_HDA_ID_OUTPUT, },{ .id = AC_PAR_REV_ID, .val = 0x00100101, },{ .id = AC_PAR_NODE_COUNT, .val = 0x00010001, }, }; /* output: audio function */ static const desc_param glue(output_params_audio_func_, PARAM)[] = { { .id = AC_PAR_FUNCTION_TYPE, .val = AC_GRP_AUDIO_FUNCTION, },{ .id = AC_PAR_SUBSYSTEM_ID, .val = QEMU_HDA_ID_OUTPUT, },{ .id = AC_PAR_NODE_COUNT, .val = 0x00020002, },{ .id = AC_PAR_PCM, .val = QEMU_HDA_PCM_FORMATS, },{ .id = AC_PAR_STREAM, .val = AC_SUPFMT_PCM, },{ .id = AC_PAR_AMP_IN_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_AMP_OUT_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_GPIO_CAP, .val = 0, },{ .id = AC_PAR_AUDIO_FG_CAP, .val = 0x00000808, },{ .id = AC_PAR_POWER_STATE, .val = 0, }, }; /* output: nodes */ static const desc_node glue(output_nodes_, PARAM)[] = { { .nid = AC_NODE_ROOT, .name = "root", .params = glue(output_params_root_, PARAM), .nparams = ARRAY_SIZE(glue(output_params_root_, PARAM)), },{ .nid = 1, .name = "func", .params = glue(output_params_audio_func_, PARAM), .nparams = ARRAY_SIZE(glue(output_params_audio_func_, PARAM)), },{ .nid = 2, .name = "dac", .params = glue(common_params_audio_dac_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)), .stindex = 0, },{ .nid = 3, .name = "out", .params = glue(common_params_audio_lineout_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)), .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | 0x10), .pinctl = AC_PINCTL_OUT_EN, .conn = (uint32_t[]) { 2 }, } }; /* output: codec */ static const desc_codec glue(output_, PARAM) = { .name = "output", .iid = QEMU_HDA_ID_OUTPUT, .nodes = glue(output_nodes_, PARAM), .nnodes = ARRAY_SIZE(glue(output_nodes_, PARAM)), }; /* duplex: root node */ static const desc_param glue(duplex_params_root_, PARAM)[] = { { .id = AC_PAR_VENDOR_ID, .val = QEMU_HDA_ID_DUPLEX, },{ .id = AC_PAR_SUBSYSTEM_ID, .val = QEMU_HDA_ID_DUPLEX, },{ .id = AC_PAR_REV_ID, .val = 0x00100101, },{ .id = AC_PAR_NODE_COUNT, .val = 0x00010001, }, }; /* duplex: audio function */ static const desc_param glue(duplex_params_audio_func_, PARAM)[] = { { .id = AC_PAR_FUNCTION_TYPE, .val = AC_GRP_AUDIO_FUNCTION, },{ .id = AC_PAR_SUBSYSTEM_ID, .val = QEMU_HDA_ID_DUPLEX, },{ .id = AC_PAR_NODE_COUNT, .val = 0x00020004, },{ .id = AC_PAR_PCM, .val = QEMU_HDA_PCM_FORMATS, },{ .id = AC_PAR_STREAM, .val = AC_SUPFMT_PCM, },{ .id = AC_PAR_AMP_IN_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_AMP_OUT_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_GPIO_CAP, .val = 0, },{ .id = AC_PAR_AUDIO_FG_CAP, .val = 0x00000808, },{ .id = AC_PAR_POWER_STATE, .val = 0, }, }; /* duplex: nodes */ static const desc_node glue(duplex_nodes_, PARAM)[] = { { .nid = AC_NODE_ROOT, .name = "root", .params = glue(duplex_params_root_, PARAM), .nparams = ARRAY_SIZE(glue(duplex_params_root_, PARAM)), },{ .nid = 1, .name = "func", .params = glue(duplex_params_audio_func_, PARAM), .nparams = ARRAY_SIZE(glue(duplex_params_audio_func_, PARAM)), },{ .nid = 2, .name = "dac", .params = glue(common_params_audio_dac_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)), .stindex = 0, },{ .nid = 3, .name = "out", .params = glue(common_params_audio_lineout_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)), .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | 0x10), .pinctl = AC_PINCTL_OUT_EN, .conn = (uint32_t[]) { 2 }, },{ .nid = 4, .name = "adc", .params = glue(common_params_audio_adc_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)), .stindex = 1, .conn = (uint32_t[]) { 5 }, },{ .nid = 5, .name = "in", .params = glue(common_params_audio_linein_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)), .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) | (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) | 0x20), .pinctl = AC_PINCTL_IN_EN, } }; /* duplex: codec */ static const desc_codec glue(duplex_, PARAM) = { .name = "duplex", .iid = QEMU_HDA_ID_DUPLEX, .nodes = glue(duplex_nodes_, PARAM), .nnodes = ARRAY_SIZE(glue(duplex_nodes_, PARAM)), }; /* micro: root node */ static const desc_param glue(micro_params_root_, PARAM)[] = { { .id = AC_PAR_VENDOR_ID, .val = QEMU_HDA_ID_MICRO, },{ .id = AC_PAR_SUBSYSTEM_ID, .val = QEMU_HDA_ID_MICRO, },{ .id = AC_PAR_REV_ID, .val = 0x00100101, },{ .id = AC_PAR_NODE_COUNT, .val = 0x00010001, }, }; /* micro: audio function */ static const desc_param glue(micro_params_audio_func_, PARAM)[] = { { .id = AC_PAR_FUNCTION_TYPE, .val = AC_GRP_AUDIO_FUNCTION, },{ .id = AC_PAR_SUBSYSTEM_ID, .val = QEMU_HDA_ID_MICRO, },{ .id = AC_PAR_NODE_COUNT, .val = 0x00020004, },{ .id = AC_PAR_PCM, .val = QEMU_HDA_PCM_FORMATS, },{ .id = AC_PAR_STREAM, .val = AC_SUPFMT_PCM, },{ .id = AC_PAR_AMP_IN_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_AMP_OUT_CAP, .val = QEMU_HDA_AMP_NONE, },{ .id = AC_PAR_GPIO_CAP, .val = 0, },{ .id = AC_PAR_AUDIO_FG_CAP, .val = 0x00000808, },{ .id = AC_PAR_POWER_STATE, .val = 0, }, }; /* micro: nodes */ static const desc_node glue(micro_nodes_, PARAM)[] = { { .nid = AC_NODE_ROOT, .name = "root", .params = glue(micro_params_root_, PARAM), .nparams = ARRAY_SIZE(glue(micro_params_root_, PARAM)), },{ .nid = 1, .name = "func", .params = glue(micro_params_audio_func_, PARAM), .nparams = ARRAY_SIZE(glue(micro_params_audio_func_, PARAM)), },{ .nid = 2, .name = "dac", .params = glue(common_params_audio_dac_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)), .stindex = 0, },{ .nid = 3, .name = "out", .params = glue(common_params_audio_lineout_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)), .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | (AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) | (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | 0x10), .pinctl = AC_PINCTL_OUT_EN, .conn = (uint32_t[]) { 2 }, },{ .nid = 4, .name = "adc", .params = glue(common_params_audio_adc_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)), .stindex = 1, .conn = (uint32_t[]) { 5 }, },{ .nid = 5, .name = "in", .params = glue(common_params_audio_linein_, PARAM), .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)), .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) | (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) | 0x20), .pinctl = AC_PINCTL_IN_EN, } }; /* micro: codec */ static const desc_codec glue(micro_, PARAM) = { .name = "micro", .iid = QEMU_HDA_ID_MICRO, .nodes = glue(micro_nodes_, PARAM), .nnodes = ARRAY_SIZE(glue(micro_nodes_, PARAM)), }; #undef PARAM #undef HDA_MIXER #undef QEMU_HDA_ID_OUTPUT #undef QEMU_HDA_ID_DUPLEX #undef QEMU_HDA_ID_MICRO #undef QEMU_HDA_AMP_CAPS