1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <device/device.h>
5 #include <device/pci.h>
6 #include <device/pci_ids.h>
7 #include <device/pci_ops.h>
8 #include <device/mmio.h>
10 #include <device/azalia_device.h>
16 static int codec_detect(u8
*base
)
20 if (azalia_exit_reset(base
) != CB_SUCCESS
)
23 /* Write back the value once reset bit is set. */
24 write16(base
+ HDA_GCAP_REG
, read16(base
+ HDA_GCAP_REG
));
26 /* Read in Codec location (BAR + 0xe)[2..0] */
27 reg8
= read8(base
+ HDA_STATESTS_REG
);
35 /* Codec not found, put HDA back in reset */
36 azalia_enter_reset(base
);
37 printk(BIOS_DEBUG
, "Azalia: No codec!\n");
41 static void azalia_init(struct device
*dev
)
48 res
= probe_resource(dev
, PCI_BASE_ADDRESS_0
);
52 // NOTE this will break as soon as the Azalia gets a bar above 4G.
53 // Is there anything we can do about it?
54 base
= res2mmio(res
, 0, 0);
55 printk(BIOS_DEBUG
, "Azalia: base = %p\n", base
);
57 if (RCBA32(CIR31
) & (1 << 31)) {
58 reg32
= pci_read_config32(dev
, 0x120);
60 reg32
|= (1 << 24); // 2 << 24 for server
61 reg32
|= RCBA32(CIR31
) & 0xfe;
62 pci_write_config32(dev
, 0x120, reg32
);
64 pci_or_config16(dev
, 0x78, 1 << 11);
66 printk(BIOS_DEBUG
, "Azalia: V1CTL disabled.\n");
68 pci_and_config32(dev
, 0x114, ~0xfe);
71 pci_or_config32(dev
, 0x120, 1 << 31);
74 pci_or_config32(dev
, 0xc4, 1 << 1);
76 pci_or_config8(dev
, 0x43, 1 << 6);
78 /* Additional programming steps */
79 pci_or_config32(dev
, 0xc4, 1 << 13);
81 pci_or_config32(dev
, 0xc4, 1 << 10);
83 pci_and_config32(dev
, 0xd0, ~(1 << 31));
85 if (dev
->device
== 0x1e20) {
86 /* Additional step on Panther Point */
87 pci_or_config32(dev
, 0xc4, 1 << 17);
91 pci_or_config16(dev
, PCI_COMMAND
, PCI_COMMAND_MASTER
);
93 pci_write_config8(dev
, 0x3c, 0x0a); // unused?
95 /* Codec Initialization Programming Sequence */
97 /* Take controller out of reset */
98 reg32
= read32(base
+ HDA_GCTL_REG
);
99 reg32
|= HDA_GCTL_CRST
;
100 write32(base
+ HDA_GCTL_REG
, reg32
);
104 // Select Azalia mode. This needs to be controlled via devicetree.cb
105 pci_or_config8(dev
, 0x40, 1); // Audio Control
107 // Docking not supported
108 pci_and_config8(dev
, 0x4d, (u8
)~(1 << 7)); // Docking Status
110 codec_mask
= codec_detect(base
);
113 printk(BIOS_DEBUG
, "Azalia: codec_mask = %02x\n", codec_mask
);
114 azalia_codecs_init(base
, codec_mask
);
117 /* Enable dynamic clock gating */
118 pci_update_config8(dev
, 0x43, ~0x07, (1 << 2) | (1 << 0));
121 static const char *azalia_acpi_name(const struct device
*dev
)
126 struct device_operations bd82x6x_azalia_ops
= {
127 .read_resources
= pci_dev_read_resources
,
128 .set_resources
= pci_dev_set_resources
,
129 .enable_resources
= pci_dev_enable_resources
,
131 .ops_pci
= &pci_dev_ops_pci
,
132 .acpi_name
= azalia_acpi_name
,