* 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:
parent
69fac0cee0
commit
0e8c024030
@ -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).
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user