From 0e8c024030a7e2687f35cc2ef8a3778b862076fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 3 Mar 2008 14:55:37 +0000 Subject: [PATCH] * Also print the codec's revision. * Only print [Output] if it's an output. * Further cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24215 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/drivers/audio/hda/driver.h | 2 +- .../kernel/drivers/audio/hda/hda_codec.cpp | 119 ++++++++++-------- .../kernel/drivers/audio/hda/hda_codec_defs.h | 82 +++++++----- 3 files changed, 122 insertions(+), 81 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.h b/src/add-ons/kernel/drivers/audio/hda/driver.h index 9768ac2eb8..72773275f4 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.h +++ b/src/add-ons/kernel/drivers/audio/hda/driver.h @@ -114,7 +114,7 @@ struct hda_widget { } d; }; -/*! This structure describes a single Audio Function Group. An afg +/*! This structure describes a single Audio Function Group. An AFG is a group of audio widgets which can be used to configure multiple streams of audio either from the HDA Link to an output device (= playback) or from an input device to the HDA link (= recording). 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 dc06e3fd5d..04f657c87f 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp @@ -128,7 +128,8 @@ hda_widget_get_amplifier_capabilities(hda_codec* codec, uint32 nodeID) corb_t verb; uint32 resp; - verb = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, PID_OUTPUT_AMP_CAP); + verb = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, + PID_OUTPUT_AMPLIFIER_CAP); rc = hda_send_verbs(codec, &verb, &resp, 1); if (rc == B_OK && resp != 0) { dprintf("\tAMP: Mute: %s, step size: %ld, # steps: %ld, offset: %ld\n", @@ -159,7 +160,7 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup) verbs[1] = MAKE_VERB(audioGroup->codec->addr, audioGroup->root_node_id, VID_GET_PARAMETER, PID_GPIO_COUNT); verbs[2] = MAKE_VERB(audioGroup->codec->addr, audioGroup->root_node_id, - VID_GET_PARAMETER, PID_SUBORD_NODE_COUNT); + VID_GET_PARAMETER, PID_SUBORDINATE_NODE_COUNT); if (hda_send_verbs(audioGroup->codec, verbs, resp, 3) != B_OK) return B_ERROR; @@ -266,7 +267,7 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup) dprintf("\t%s%s\n", audioGroup->widgets[widx].d.pin.input ? "[Input] " : "", - audioGroup->widgets[widx].d.pin.input ? "[Output]" : ""); + audioGroup->widgets[widx].d.pin.output ? "[Output]" : ""); } else { dprintf("%s: Error getting Pin Complex IO\n", __func__); } @@ -451,6 +452,7 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) audioGroup->widgets[i].inputs[inputIndex], WT_AUDIO_OUTPUT, 0); } else { + // find and select output widget for (inputIndex = 0; (uint32)inputIndex < audioGroup->widgets[i].num_inputs; inputIndex++) { outputWidget = hda_codec_audio_group_find_path(audioGroup, @@ -485,11 +487,12 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) verb[0] = MAKE_VERB(codec->addr, audioGroup->playback_stream->pin_widget, VID_SET_AMPLIFIER_GAIN_MUTE, - (1 << 15) | (1 << 13) | (1 << 12)); + AMP_SET_OUTPUT | AMP_SET_LEFT_CHANNEL + | AMP_SET_RIGHT_CHANNEL); verb[1] = MAKE_VERB(codec->addr, audioGroup->playback_stream->pin_widget, VID_SET_PIN_WIDGET_CONTROL, - (1 << 7) | (1 << 6)); + PIN_ENABLE_HEAD_PHONE | PIN_ENABLE_OUTPUT); hda_send_verbs(codec, verb, NULL, 2); dprintf("%s: Found output PIN (%s) connected to output " @@ -507,6 +510,7 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) audioGroup->widgets[i].inputs[inputIndex], WT_PIN_COMPLEX, 0); } else { + // find and select input widget for (inputIndex = 0; (uint32)inputIndex < audioGroup->widgets[i].num_inputs; inputIndex++) { inputWidget = hda_codec_audio_group_find_path(audioGroup, @@ -541,9 +545,10 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) verb = MAKE_VERB(codec->addr, audioGroup->record_stream->pin_widget, VID_SET_AMPLIFIER_GAIN_MUTE, - (1 << 15) | (1 << 13) | (1 << 12)); + AMP_SET_INPUT | AMP_SET_LEFT_CHANNEL + | AMP_SET_RIGHT_CHANNEL); hda_send_verbs(codec, &verb, NULL, 1); - } + } dprintf("%s: Found input PIN (%s) connected to input CONV " "wid:%ld\n", __func__, kDefaultDevice[audioGroup->widgets[ @@ -571,74 +576,86 @@ err: void hda_codec_delete(hda_codec* codec) { - if (codec == NULL) { - uint32 idx; + if (codec == NULL) + return; - delete_sem(codec->response_sem); + delete_sem(codec->response_sem); - for (idx = 0; idx < codec->num_audio_groups; idx++) { - hda_codec_delete_audio_group(codec->audio_groups[idx]); - codec->audio_groups[idx] = NULL; - } - - free(codec); + for (uint32 i = 0; i < codec->num_audio_groups; i++) { + hda_codec_delete_audio_group(codec->audio_groups[i]); + codec->audio_groups[i] = NULL; } + + free(codec); } hda_codec* -hda_codec_new(hda_controller* controller, uint32 cad) +hda_codec_new(hda_controller* controller, uint32 codecAddress) { - hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec)); - uint32 responses[3]; - corb_t verbs[3]; - uint32 nodeID; + if (codecAddress > HDA_MAX_CODECS) + return NULL; + hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec)); if (codec == NULL) - goto exit_new; + return NULL; codec->controller = controller; - codec->addr = cad; + codec->addr = codecAddress; codec->response_sem = create_sem(0, "hda_codec_response_sem"); - controller->codecs[cad] = codec; + controller->codecs[codecAddress] = codec; - verbs[0] = MAKE_VERB(cad, 0, VID_GET_PARAMETER, PID_VENDOR_ID); - verbs[1] = MAKE_VERB(cad, 0, VID_GET_PARAMETER, PID_REVISION_ID); - verbs[2] = MAKE_VERB(cad, 0, VID_GET_PARAMETER, PID_SUBORD_NODE_COUNT); + struct { + uint32 device : 16; + uint32 vendor : 16; + uint32 stepping : 8; + uint32 revision : 8; + uint32 minor : 4; + uint32 major : 4; + uint32 _reserved0 : 8; + uint32 count : 8; + uint32 _reserved1 : 8; + uint32 start : 8; + uint32 _reserved2 : 8; + } response; + corb_t verbs[3]; - if (hda_send_verbs(codec, verbs, responses, 3) != B_OK) - goto cmd_failed; + verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID); + verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID); + verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, + PID_SUBORDINATE_NODE_COUNT); - dprintf("Codec %ld Vendor: %04lx Product: %04lx\n", - cad, responses[0] >> 16, responses[0] & 0xffff); + if (hda_send_verbs(codec, verbs, (uint32*)&response, 3) != B_OK) + goto err; - for (nodeID = responses[2] >> 16; - nodeID < (responses[2] >> 16) + (responses[2] & 0xff); nodeID++) { - uint32 resp; - verbs[0] = MAKE_VERB(cad, nodeID, VID_GET_PARAMETER, + dprintf("Codec %ld Vendor: %04lx Product: %04lx, Revision: " + "%lu.%lu.%lu.%lu\n", codecAddress, response.vendor, response.device, + response.major, response.minor, response.revision, response.stepping); + + for (uint32 nodeID = response.start; nodeID < response.start + + response.count; nodeID++) { + uint32 groupType; + verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER, PID_FUNCTION_GROUP_TYPE); - if (hda_send_verbs(codec, verbs, &resp, 1) != B_OK) - goto cmd_failed; + if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) + goto err; - if ((resp & 0xff) == 1) { + if ((groupType & 0xff) == 1) { /* Found an Audio Function Group! */ - status_t rc = hda_codec_new_audio_group(codec, nodeID); - if (rc != B_OK) { - dprintf("%s: Failed to setup new audio function group (%s)!\n", - __func__, strerror(rc)); - goto cmd_failed; + status_t status = hda_codec_new_audio_group(codec, nodeID); + if (status != B_OK) { + dprintf("hda: Failed to setup new audio function group (%s)!\n", + strerror(status)); + goto err; } } } - goto exit_new; - -cmd_failed: - controller->codecs[cad] = NULL; - hda_codec_delete(codec); - codec = NULL; - -exit_new: return codec; + +err: + controller->codecs[codecAddress] = NULL; + hda_codec_delete(codec); + return NULL; } diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_codec_defs.h b/src/add-ons/kernel/drivers/audio/hda/hda_codec_defs.h index cce865ddbd..8236f49170 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_codec_defs.h +++ b/src/add-ons/kernel/drivers/audio/hda/hda_codec_defs.h @@ -101,8 +101,8 @@ enum pin_dev_type { #define VID_SET_GPIOSTICKY 0x71A00 #define VID_GET_BEEPGEN 0xF0A00 #define VID_SET_BEEPGEN 0x70A00 -#define VID_GET_VOLUMEKNOB 0xF0F00 -#define VID_SET_VOLUMEKNOB 0x70F00 +#define VID_GET_VOLUME_KNOB 0xf0f00 +#define VID_SET_VOLUME_KNOB 0x70f00 #define VID_GET_SUBSYSTEMID 0xF2000 #define VID_SET_SUBSYSTEMID1 0x72000 #define VID_SET_SUBSYSTEMID2 0x72100 @@ -113,38 +113,62 @@ enum pin_dev_type { #define VID_SET_CONFIGURATION_DEFAULT2 0x71d00 #define VID_SET_CONFIGURATION_DEFAULT3 0x71e00 #define VID_SET_CONFIGURATION_DEFAULT4 0x71f00 -#define VID_GET_STRIPECTRL 0xF2400 -#define VID_SET_STRIPECTRL 0x72000 -#define VID_FUNCTION_RESET 0x7FF00 +#define VID_GET_STRIPE_CONTROL 0xf2400 +#define VID_SET_STRIPE_CONTROL 0x72000 +#define VID_FUNCTION_RESET 0x7ff00 /* Parameter IDs */ -#define PID_VENDOR_ID 0x00 -#define PID_REVISION_ID 0x02 -#define PID_SUBORD_NODE_COUNT 0x04 -#define PID_FUNCTION_GROUP_TYPE 0x05 -#define PID_AUDIO_GROUP_CAP 0x08 -#define PID_AUDIO_WIDGET_CAP 0x09 -#define PID_PCM_SUPPORT 0x0A -#define PID_STREAM_SUPPORT 0x0B -#define PID_PIN_CAP 0x0C -#define PID_INPUT_AMP_CAP 0x0D -#define PID_CONNECTION_LIST_LENGTH 0x0E -#define PID_POWERSTATE_SUPPORT 0x0F -#define PID_PROCESSING_CAP 0x10 -#define PID_GPIO_COUNT 0x11 -#define PID_OUTPUT_AMP_CAP 0x12 -#define PID_VOLUMEKNOB_CAP 0x13 +#define PID_VENDOR_ID 0x00 +#define PID_REVISION_ID 0x02 +#define PID_SUBORDINATE_NODE_COUNT 0x04 +#define PID_FUNCTION_GROUP_TYPE 0x05 +#define PID_AUDIO_GROUP_CAP 0x08 +#define PID_AUDIO_WIDGET_CAP 0x09 +#define PID_PCM_SUPPORT 0x0a +#define PID_STREAM_SUPPORT 0x0b +#define PID_PIN_CAP 0x0c +#define PID_INPUT_AMPLIFIER_CAP 0x0d +#define PID_CONNECTION_LIST_LENGTH 0x0e +#define PID_POWERSTATE_SUPPORT 0x0f +#define PID_PROCESSING_CAP 0x10 +#define PID_GPIO_COUNT 0x11 +#define PID_OUTPUT_AMPLIFIER_CAP 0x12 +#define PID_VOLUME_KNOB_CAP 0x13 /* PCM support */ -#define PCM_8_BIT (1L << 16) -#define PCM_16_BIT (1L << 17) -#define PCM_20_BIT (1L << 18) -#define PCM_24_BIT (1L << 19) -#define PCM_32_BIT (1L << 20) +#define PCM_8_BIT (1L << 16) +#define PCM_16_BIT (1L << 17) +#define PCM_20_BIT (1L << 18) +#define PCM_24_BIT (1L << 19) +#define PCM_32_BIT (1L << 20) /* stream support */ -#define STREAM_AC3 0x00000004 -#define STREAM_FLOAT 0x00000002 -#define STREAM_PCM 0x00000001 +#define STREAM_AC3 0x00000004 +#define STREAM_FLOAT 0x00000002 +#define STREAM_PCM 0x00000001 + +/* Amplifier Gain/Mute */ +#define AMP_GET_OUTPUT (1L << 15) +#define AMP_GET_INPUT (0L << 15) +#define AMP_GET_LEFT_CHANNEL (1L << 13) +#define AMP_GET_RIGHT_CHANNEL (0L << 13) +#define AMP_GET_INPUT_INDEX_MASK 0x0000000f +#define AMP_GET_INPUT_INDEX_SHIFT 0 + +#define AMP_SET_OUTPUT (1L << 15) +#define AMP_SET_INPUT (1L << 14) +#define AMP_SET_LEFT_CHANNEL (1L << 13) +#define AMP_SET_RIGHT_CHANNEL (1L << 12) +#define AMP_SET_INPUT_INDEX_MASK 0x00000f00 +#define AMP_SET_INPUT_INDEX_SHIFT 8 + +#define AMP_GAIN_MASK 0x0000007f +#define AMP_MUTE (1L << 8) + +/* Pin Widget Control */ +#define PIN_ENABLE_HEAD_PHONE (1L << 7) +#define PIN_ENABLE_OUTPUT (1L << 6) +#define PIN_ENABLE_INPUT (1L << 5) +#define PIN_ENABLE_VOLTAGE_REF_MASK 0x3 #endif /* HDA_CODEC_H */