From 32f411b9abac731f8c00b44817bf66b03d8c4339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 3 Feb 2022 21:42:24 +0100 Subject: [PATCH] hda: detect some audio devices per device ID as it's possible they use the audio class_sub instead of hd_audio. * also power up the audio function, this seems required on Jasper Lake. * tested on Acer Swift 1 SF114-34. Change-Id: I603018b1b973e7884aa99a58be1c24e568f2d5ae Reviewed-on: https://review.haiku-os.org/c/haiku/+/4928 Reviewed-by: waddlesplash Tested-by: Commit checker robot --- .../kernel/drivers/audio/hda/driver.cpp | 38 +++++++++++++++++-- .../kernel/drivers/audio/hda/hda_codec.cpp | 6 +++ .../drivers/audio/hda/hda_controller.cpp | 26 ++++++++++++- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.cpp b/src/add-ons/kernel/drivers/audio/hda/driver.cpp index 15df71d791..71a161f9db 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/driver.cpp @@ -18,6 +18,34 @@ pci_module_info* gPci; pci_x86_module_info* gPCIx86Module; +static struct { + uint16 vendor; + uint16 device; +} kSupportedDevices[] = { + { 0x8086, 0x9d71}, // 200 Series HD Audio + { 0x8086, 0x9dc8}, // 300 Series HD Audio + { 0x8086, 0x06c8}, // 400 Series cAVS + { 0x8086, 0xa0c8}, // 500 Series HD Audio + { 0x8086, 0x4dc8}, // JasperLake HD Audio + { 0x8086, 0x43c8}, // Tiger Lake-H HD Audio + { 0x8086, 0xa171}, // CM238 HD Audio + { 0x8086, 0x3198}, // GeminiLake HD Audio +}; + + +static bool +supports_device(pci_info &info) +{ + for (size_t i = 0; i < B_COUNT_OF(kSupportedDevices); i++) { + if (info.vendor_id == kSupportedDevices[i].vendor + && info.device_id == kSupportedDevices[i].device) { + return true; + } + } + return false; +} + + extern "C" status_t init_hardware(void) { @@ -28,8 +56,9 @@ init_hardware(void) return ENODEV; for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK; i++) { - if (info.class_base == PCI_multimedia - && info.class_sub == PCI_hd_audio) { + if ((info.class_base == PCI_multimedia + && info.class_sub == PCI_hd_audio) + || supports_device(info)) { put_module(B_PCI_MODULE_NAME); return B_OK; } @@ -54,8 +83,9 @@ init_driver(void) for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK && gNumCards < MAX_CARDS; i++) { - if (info.class_base == PCI_multimedia - && info.class_sub == PCI_hd_audio) { + if ((info.class_base == PCI_multimedia + && info.class_sub == PCI_hd_audio) + || supports_device(info)) { #ifdef __HAIKU__ if ((*gPci->reserve_device)(info.bus, info.device, info.function, "hda", &gCards[gNumCards]) < B_OK) { 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 b08f95e4e9..1f570a33c3 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp @@ -720,6 +720,12 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup) hda_codec* codec = audioGroup->codec; uint32 codec_id = (codec->vendor_id << 16) | codec->product_id; + + // Power up the audio function + verbs[0] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, + VID_SET_POWER_STATE, 0); + hda_send_verbs(audioGroup->codec, verbs, NULL, 1); + hda_widget_get_stream_support(audioGroup, &audioGroup->widget); hda_widget_get_pm_support(audioGroup, &audioGroup->widget); hda_widget_get_amplifier_capabilities(audioGroup, &audioGroup->widget); diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp index 12822c05d4..772d2d532e 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp @@ -18,6 +18,14 @@ #include "hda_codec_defs.h" +//#define TRACE_HDA_VERBS +#ifdef TRACE_HDA_VERBS +# define TRACE_VERBS(x...) dprintf("\33[33mhda:\33[0m " x) +#else +# define TRACE_VERBS(x...) ; +#endif + + #define MAKE_RATE(base, multiply, divide) \ ((base == 44100 ? FORMAT_44_1_BASE_RATE : 0) \ | ((multiply - 1) << FORMAT_MULTIPLY_RATE_SHIFT) \ @@ -1026,6 +1034,9 @@ hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses, uint32 count) } controller->corb[writePos] = verbs[sent++]; + TRACE_VERBS("send_verb: (%02x:%02x.%x:%u) cmd 0x%08" B_PRIx32 "\n", + controller->pci_info.bus, controller->pci_info.device, + controller->pci_info.function, codec->addr, controller->corb[writePos]); controller->corb_write_pos = writePos; queued++; } @@ -1037,8 +1048,13 @@ hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses, uint32 count) return status; } - if (responses != NULL) + if (responses != NULL) { + TRACE_VERBS("send_verb: (%02x:%02x.%x:%u) resp 0x%08" B_PRIx32 "\n", + controller->pci_info.bus, controller->pci_info.device, + controller->pci_info.function, codec->addr, codec->responses[0]); + memcpy(responses, codec->responses, count * sizeof(uint32)); + } return B_OK; } @@ -1321,6 +1337,14 @@ hda_hw_stop(hda_controller* controller) if (controller->streams[index] && controller->streams[index]->running) hda_stream_stop(controller, controller->streams[index]); } + + // Power off the audio functions + for (uint32 index = 0; index < controller->active_codec->num_audio_groups; index++) { + hda_audio_group* audioGroup = controller->active_codec->audio_groups[index]; + corb_t verb = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, + VID_SET_POWER_STATE, 3); + hda_send_verbs(audioGroup->codec, &verb, NULL, 1); + } }