hda: subsystem is from the codec, not the PCI bus.
* Refactors so that we look for a codec subsystem ID, then the Audio Function Group subsystem ID if not found. * Moves the order around a bit so that the quirks are set early enough. * Also adds a quirk for MacBookAir 6,2, allows speakers to work. Change-Id: I4c64f96936a82a5d7187d86d8558f28516fd4ecb Reviewed-on: https://review.haiku-os.org/c/haiku/+/4654 Reviewed-by: Adrien Destugues <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
@@ -292,6 +292,7 @@ struct hda_audio_group {
|
||||
struct hda_codec {
|
||||
uint16 vendor_id;
|
||||
uint16 product_id;
|
||||
uint32 subsystem_id;
|
||||
uint8 major;
|
||||
uint8 minor;
|
||||
uint8 revision;
|
||||
|
||||
@@ -95,6 +95,8 @@ static const struct {
|
||||
HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0}, // MacBook
|
||||
{ 0x106b, 0x00a3, REALTEK_VENDORID, 0x0885,
|
||||
HDA_QUIRK_GPIO0, 0}, // MacBook
|
||||
{ 0x106b, 0x7200, CIRRUSLOGIC_VENDORID, 0x4208,
|
||||
HDA_QUIRK_GPIO0, 0}, // MacBookAir 6,2
|
||||
{ HDA_ALL, HDA_ALL, IDT_VENDORID, 0x76b2, HDA_QUIRK_GPIO0, 0},
|
||||
};
|
||||
|
||||
@@ -363,9 +365,8 @@ hda_codec_get_quirks(hda_codec* codec)
|
||||
{
|
||||
codec->quirks = 0;
|
||||
|
||||
uint32 subSystemID = codec->controller->pci_info.u.h0.subsystem_id;
|
||||
uint32 subSystemVendorID
|
||||
= codec->controller->pci_info.u.h0.subsystem_vendor_id;
|
||||
uint32 subSystemID = codec->subsystem_id & 0xffff;
|
||||
uint32 subSystemVendorID = codec->subsystem_id >> 16;
|
||||
|
||||
for (uint32 i = 0;
|
||||
i < (sizeof(kCodecQuirks) / sizeof(kCodecQuirks[0])); i++) {
|
||||
@@ -1496,6 +1497,7 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
|
||||
struct {
|
||||
uint32 device : 16;
|
||||
uint32 vendor : 16;
|
||||
uint32 subsystem : 32;
|
||||
uint32 stepping : 8;
|
||||
uint32 revision : 8;
|
||||
uint32 minor : 4;
|
||||
@@ -1507,13 +1509,14 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
|
||||
uint32 _reserved2 : 8;
|
||||
} response;
|
||||
|
||||
corb_t verbs[3];
|
||||
corb_t verbs[4];
|
||||
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,
|
||||
verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_SUBSYSTEM_ID);
|
||||
verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID);
|
||||
verbs[3] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER,
|
||||
PID_SUB_NODE_COUNT);
|
||||
|
||||
status = hda_send_verbs(codec, verbs, (uint32*)&response, 3);
|
||||
status = hda_send_verbs(codec, verbs, (uint32*)&response, 4);
|
||||
if (status != B_OK) {
|
||||
ERROR("Failed to get vendor and revision parameters: %s\n",
|
||||
strerror(status));
|
||||
@@ -1521,6 +1524,7 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
|
||||
}
|
||||
|
||||
codec->vendor_id = response.vendor;
|
||||
codec->subsystem_id = response.subsystem;
|
||||
codec->product_id = response.device;
|
||||
codec->stepping = response.stepping;
|
||||
codec->revision = response.revision;
|
||||
@@ -1528,29 +1532,30 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
|
||||
codec->major = response.major;
|
||||
hda_codec_get_quirks(codec);
|
||||
|
||||
TRACE("Codec %" B_PRIu32 " Vendor: %04" B_PRIx32 " "
|
||||
"Product: %04" B_PRIx32 ", "
|
||||
"Revision: %" B_PRIu32 ".%" B_PRIu32 ".%" B_PRIu32 ".%" B_PRIu32 " "
|
||||
"Quirks: %04" B_PRIx32 "\n",
|
||||
codecAddress, response.vendor,
|
||||
response.device,
|
||||
response.major, response.minor, response.revision, response.stepping,
|
||||
codec->quirks);
|
||||
|
||||
for (uint32 nodeID = response.start;
|
||||
nodeID < response.start + response.count; nodeID++) {
|
||||
uint32 groupType;
|
||||
struct {
|
||||
uint32 groupType;
|
||||
uint32 subsystem;
|
||||
} functionResponse;
|
||||
verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER,
|
||||
PID_FUNCTION_GROUP_TYPE);
|
||||
verbs[1] = MAKE_VERB(codecAddress, nodeID, VID_GET_SUBSYSTEMID, 0);
|
||||
|
||||
if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) {
|
||||
if (hda_send_verbs(codec, verbs, (uint32*)&functionResponse, 2) != B_OK) {
|
||||
ERROR("Failed to get function group type\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((groupType & FUNCTION_GROUP_NODETYPE_MASK)
|
||||
if ((functionResponse.groupType & FUNCTION_GROUP_NODETYPE_MASK)
|
||||
== FUNCTION_GROUP_NODETYPE_AUDIO) {
|
||||
// Found an Audio Function Group!
|
||||
if (response.subsystem == 0 && functionResponse.subsystem != 0) {
|
||||
// Update our subsystem, and re-check quirks for this codec
|
||||
codec->subsystem_id = functionResponse.subsystem;
|
||||
hda_codec_get_quirks(codec);
|
||||
}
|
||||
|
||||
status_t status = hda_codec_new_audio_group(codec, nodeID);
|
||||
if (status != B_OK) {
|
||||
ERROR("Failed to setup new audio function group (%s)!\n",
|
||||
@@ -1560,6 +1565,18 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Codec %" B_PRIu32 " Vendor: %04" B_PRIx32 " "
|
||||
"Product: %04" B_PRIx32 " "
|
||||
"Subsystem: %08" B_PRIx32 ", "
|
||||
"Revision: %" B_PRIu32 ".%" B_PRIu32 ".%" B_PRIu32 ".%" B_PRIu32 " "
|
||||
"Quirks: %04" B_PRIx32 "\n",
|
||||
codecAddress,
|
||||
response.vendor,
|
||||
response.device,
|
||||
codec->subsystem_id,
|
||||
response.major, response.minor, response.revision, response.stepping,
|
||||
codec->quirks);
|
||||
|
||||
codec->unsol_response_thread = spawn_kernel_thread(
|
||||
(status_t(*)(void*))hda_codec_switch_handler,
|
||||
"hda_codec_unsol_thread", B_LOW_PRIORITY, codec);
|
||||
|
||||
@@ -143,6 +143,7 @@ enum pin_dev_type {
|
||||
|
||||
/* Parameter IDs */
|
||||
#define PID_VENDOR_ID 0x00
|
||||
#define PID_SUBSYSTEM_ID 0x01
|
||||
#define PID_REVISION_ID 0x02
|
||||
#define PID_SUB_NODE_COUNT 0x04
|
||||
#define PID_FUNCTION_GROUP_TYPE 0x05
|
||||
|
||||
Reference in New Issue
Block a user