* 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
This commit is contained in:
Axel Dörfler 2008-03-03 14:55:37 +00:00
parent 69fac0cee0
commit 0e8c024030
3 changed files with 122 additions and 81 deletions

View File

@ -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).

View File

@ -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;
}

View File

@ -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 */