From 69958ca2efd69e0c2ed37c0a512dd2125594e655 Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Sun, 24 Oct 2021 21:47:24 +1300 Subject: [PATCH] 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 Tested-by: Commit checker robot --- src/add-ons/kernel/drivers/audio/hda/driver.h | 1 + .../kernel/drivers/audio/hda/hda_codec.cpp | 55 ++++++++++++------- .../kernel/drivers/audio/hda/hda_codec_defs.h | 1 + 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.h b/src/add-ons/kernel/drivers/audio/hda/driver.h index 89c7604f66..9045e51de0 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.h +++ b/src/add-ons/kernel/drivers/audio/hda/driver.h @@ -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; 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 8c377abd9a..b08f95e4e9 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp @@ -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); 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 94797c2f71..b3eb6c4c7c 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 @@ -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