blob: cc77956b542605e2df4c21442b76276e7d31afc3 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Aaron Durbin76c37002012-10-30 09:03:43 -05003
4#include <console/console.h>
5#include <device/device.h>
6#include <device/pci.h>
7#include <device/pci_ids.h>
8#include <device/pci_ops.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02009#include <device/mmio.h>
Vladimir Serbinenko75c83872014-09-05 01:01:31 +020010#include <device/azalia_device.h>
Elyes HAOUASbf0970e2019-03-21 11:10:03 +010011
Aaron Durbin76c37002012-10-30 09:03:43 -050012#include "pch.h"
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070013#include "hda_verb.h"
Aaron Durbin76c37002012-10-30 09:03:43 -050014
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080015static void codecs_init(u8 *base, u32 codec_mask)
Aaron Durbin76c37002012-10-30 09:03:43 -050016{
17 int i;
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070018
19 /* Can support up to 4 codecs */
Aaron Durbin76c37002012-10-30 09:03:43 -050020 for (i = 3; i >= 0; i--) {
21 if (codec_mask & (1 << i))
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070022 hda_codec_init(base, i,
23 cim_verb_data_size,
24 cim_verb_data);
Aaron Durbin76c37002012-10-30 09:03:43 -050025 }
26
Vladimir Serbinenko75c83872014-09-05 01:01:31 +020027 if (pc_beep_verbs_size)
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070028 hda_codec_write(base, pc_beep_verbs_size, pc_beep_verbs);
Aaron Durbin76c37002012-10-30 09:03:43 -050029}
30
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080031static void azalia_pch_init(struct device *dev, u8 *base)
Aaron Durbin76c37002012-10-30 09:03:43 -050032{
Aaron Durbin76c37002012-10-30 09:03:43 -050033 u8 reg8;
34 u16 reg16;
35 u32 reg32;
36
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -070037 if (RCBA32(0x2030) & (1UL << 31)) {
Kyösti Mälkki386b3e62013-07-26 08:52:49 +030038 reg32 = pci_read_config32(dev, 0x120);
Aaron Durbin76c37002012-10-30 09:03:43 -050039 reg32 &= 0xf8ffff01;
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070040 reg32 |= (1 << 25);
Aaron Durbin76c37002012-10-30 09:03:43 -050041 reg32 |= RCBA32(0x2030) & 0xfe;
Kyösti Mälkki386b3e62013-07-26 08:52:49 +030042 pci_write_config32(dev, 0x120, reg32);
Aaron Durbin76c37002012-10-30 09:03:43 -050043
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070044 if (!pch_is_lp()) {
45 reg16 = pci_read_config16(dev, 0x78);
46 reg16 &= ~(1 << 11);
47 pci_write_config16(dev, 0x78, reg16);
48 }
Aaron Durbin76c37002012-10-30 09:03:43 -050049 } else
50 printk(BIOS_DEBUG, "Azalia: V1CTL disabled.\n");
51
Kyösti Mälkki386b3e62013-07-26 08:52:49 +030052 reg32 = pci_read_config32(dev, 0x114);
Aaron Durbin76c37002012-10-30 09:03:43 -050053 reg32 &= ~0xfe;
Kyösti Mälkki386b3e62013-07-26 08:52:49 +030054 pci_write_config32(dev, 0x114, reg32);
Aaron Durbin76c37002012-10-30 09:03:43 -050055
56 // Set VCi enable bit
Kyösti Mälkki386b3e62013-07-26 08:52:49 +030057 if (pci_read_config32(dev, 0x120) & ((1 << 24) |
Aaron Durbin76c37002012-10-30 09:03:43 -050058 (1 << 25) | (1 << 26))) {
Kyösti Mälkki386b3e62013-07-26 08:52:49 +030059 reg32 = pci_read_config32(dev, 0x120);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070060 if (pch_is_lp())
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -070061 reg32 &= ~(1UL << 31);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070062 else
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -070063 reg32 |= (1UL << 31);
Kyösti Mälkki386b3e62013-07-26 08:52:49 +030064 pci_write_config32(dev, 0x120, reg32);
Aaron Durbin76c37002012-10-30 09:03:43 -050065 }
66
Aaron Durbin76c37002012-10-30 09:03:43 -050067 reg8 = pci_read_config8(dev, 0x43);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070068 if (pch_is_lp())
69 reg8 &= ~(1 << 6);
70 else
71 reg8 |= (1 << 4);
Aaron Durbin76c37002012-10-30 09:03:43 -050072 pci_write_config8(dev, 0x43, reg8);
73
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070074 if (!pch_is_lp()) {
75 reg32 = pci_read_config32(dev, 0xc0);
76 reg32 |= (1 << 17);
77 pci_write_config32(dev, 0xc0, reg32);
78 }
Aaron Durbin76c37002012-10-30 09:03:43 -050079
80 /* Additional programming steps */
81 reg32 = pci_read_config32(dev, 0xc4);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070082 if (pch_is_lp())
83 reg32 |= (1 << 24);
84 else
85 reg32 |= (1 << 14);
Aaron Durbin76c37002012-10-30 09:03:43 -050086 pci_write_config32(dev, 0xc4, reg32);
87
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070088 if (!pch_is_lp()) {
89 reg32 = pci_read_config32(dev, 0xd0);
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -070090 reg32 &= ~(1UL << 31);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070091 pci_write_config32(dev, 0xd0, reg32);
92 }
Aaron Durbin76c37002012-10-30 09:03:43 -050093
Aaron Durbin76c37002012-10-30 09:03:43 -050094 reg8 = pci_read_config8(dev, 0x40); // Audio Control
Duncan Laurie0a7c49e2013-06-20 12:40:55 -070095 reg8 |= 1; // Select Azalia mode
Aaron Durbin76c37002012-10-30 09:03:43 -050096 pci_write_config8(dev, 0x40, reg8);
97
98 reg8 = pci_read_config8(dev, 0x4d); // Docking Status
99 reg8 &= ~(1 << 7); // Docking not supported
100 pci_write_config8(dev, 0x4d, reg8);
101
Duncan Laurie0a7c49e2013-06-20 12:40:55 -0700102 if (pch_is_lp()) {
103 reg16 = read32(base + 0x0012);
104 reg16 |= (1 << 0);
105 write32(base + 0x0012, reg16);
106
107 /* disable Auto Voltage Detector */
108 reg8 = pci_read_config8(dev, 0x42);
109 reg8 |= (1 << 2);
110 pci_write_config8(dev, 0x42, reg8);
111 }
112}
113
114static void azalia_init(struct device *dev)
115{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800116 u8 *base;
Duncan Laurie0a7c49e2013-06-20 12:40:55 -0700117 struct resource *res;
118 u32 codec_mask;
Duncan Laurie0a7c49e2013-06-20 12:40:55 -0700119
120 /* Find base address */
121 res = find_resource(dev, PCI_BASE_ADDRESS_0);
122 if (!res)
123 return;
124
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800125 base = res2mmio(res, 0, 0);
126 printk(BIOS_DEBUG, "Azalia: base = %p\n", base);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -0700127
128 /* Set Bus Master */
Elyes HAOUAS73ae0762020-04-28 10:13:05 +0200129 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -0700130
131 azalia_pch_init(dev, base);
132
133 codec_mask = hda_codec_detect(base);
Aaron Durbin76c37002012-10-30 09:03:43 -0500134
135 if (codec_mask) {
136 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
Duncan Laurie0a7c49e2013-06-20 12:40:55 -0700137 codecs_init(base, codec_mask);
Aaron Durbin76c37002012-10-30 09:03:43 -0500138 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500139}
140
Aaron Durbin76c37002012-10-30 09:03:43 -0500141static struct pci_operations azalia_pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530142 .set_subsystem = pci_dev_set_subsystem,
Aaron Durbin76c37002012-10-30 09:03:43 -0500143};
144
145static struct device_operations azalia_ops = {
146 .read_resources = pci_dev_read_resources,
147 .set_resources = pci_dev_set_resources,
148 .enable_resources = pci_dev_enable_resources,
149 .init = azalia_init,
Aaron Durbin76c37002012-10-30 09:03:43 -0500150 .ops_pci = &azalia_pci_ops,
151};
152
Aaron Durbined095ca2013-05-20 15:57:16 -0500153static const unsigned short pci_device_ids[] = { 0x8c20, 0x9c20, 0 };
Aaron Durbin76c37002012-10-30 09:03:43 -0500154
155static const struct pci_driver pch_azalia __pci_driver = {
156 .ops = &azalia_ops,
157 .vendor = PCI_VENDOR_ID_INTEL,
158 .devices = pci_device_ids,
159};