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 <waddlesplash@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
Jérôme Duval 2022-02-03 21:42:24 +01:00
parent a8d965a0c4
commit 32f411b9ab
3 changed files with 65 additions and 5 deletions

View File

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

View File

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

View File

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