blob: 2510996bf89e5797795cf2b21d8e9566319a67ed [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Vladimir Serbinenko888d5592013-11-13 17:53:38 +01002
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>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02008#include <device/mmio.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +01009#include <delay.h>
Vladimir Serbinenko75c83872014-09-05 01:01:31 +020010#include <device/azalia_device.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010011#include "pch.h"
12
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080013static int codec_detect(u8 *base)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010014{
15 u8 reg8;
16
17 /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
Angel Pons61dd8362020-12-05 18:02:32 +010018 if (azalia_set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, HDA_GCTL_CRST) < 0)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010019 goto no_codec;
20
21 /* Write back the value once reset bit is set. */
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020022 write16(base + HDA_GCAP_REG, read16(base + HDA_GCAP_REG));
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010023
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020024 /* Read in Codec location (BAR + 0xe)[2..0] */
Elyes HAOUAS59236d52020-08-03 15:36:52 +020025 reg8 = read8(base + HDA_STATESTS_REG);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010026 reg8 &= 0x0f;
27 if (!reg8)
28 goto no_codec;
29
30 return reg8;
31
32no_codec:
33 /* Codec Not found */
34 /* Put HDA back in reset (BAR + 0x8) [0] */
Angel Pons61dd8362020-12-05 18:02:32 +010035 azalia_set_bits(base + HDA_GCTL_REG, 1, 0);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010036 printk(BIOS_DEBUG, "Azalia: No codec!\n");
37 return 0;
38}
39
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020040/*
41 * Wait 50usec for the codec to indicate it is ready.
42 * No response would imply that the codec is non-operative.
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010043 */
44
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080045static int wait_for_ready(u8 *base)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010046{
47 /* Use a 1msec timeout */
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010048 int timeout = 1000;
49
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020050 while (timeout--) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080051 u32 reg32 = read32(base + HDA_ICII_REG);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010052 if (!(reg32 & HDA_ICII_BUSY))
53 return 0;
54 udelay(1);
55 }
56
57 return -1;
58}
59
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020060/*
61 * Wait 50usec for the codec to indicate that it accepted the previous command.
62 * No response would imply that the code is non-operative.
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010063 */
64
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080065static int wait_for_valid(u8 *base)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010066{
67 u32 reg32;
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020068 /* Use a 1msec timeout */
69 int timeout = 1000;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010070
71 /* Send the verb to the codec */
72 reg32 = read32(base + HDA_ICII_REG);
73 reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
74 write32(base + HDA_ICII_REG, reg32);
75
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020076 while (timeout--) {
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010077 reg32 = read32(base + HDA_ICII_REG);
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020078 if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010079 return 0;
80 udelay(1);
81 }
82
83 return -1;
84}
85
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080086static void codec_init(struct device *dev, u8 *base, int addr)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010087{
88 u32 reg32;
89 const u32 *verb;
90 u32 verb_size;
91 int i;
92
93 printk(BIOS_DEBUG, "Azalia: Initializing codec #%d\n", addr);
94
95 /* 1 */
Angel Pons554713e2020-10-24 23:23:07 +020096 if (wait_for_ready(base) < 0) {
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010097 printk(BIOS_DEBUG, " codec not ready.\n");
98 return;
99 }
100
101 reg32 = (addr << 28) | 0x000f0000;
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200102 write32(base + HDA_IC_REG, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100103
Angel Pons554713e2020-10-24 23:23:07 +0200104 if (wait_for_valid(base) < 0) {
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100105 printk(BIOS_DEBUG, " codec not valid.\n");
106 return;
107 }
108
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100109 /* 2 */
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200110 reg32 = read32(base + HDA_IR_REG);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100111 printk(BIOS_DEBUG, "Azalia: codec viddid: %08x\n", reg32);
Angel Ponsd425ddd2020-12-05 18:22:58 +0100112 verb_size = azalia_find_verb(cim_verb_data, cim_verb_data_size, reg32, &verb);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100113
114 if (!verb_size) {
115 printk(BIOS_DEBUG, "Azalia: No verb!\n");
116 return;
117 }
118 printk(BIOS_DEBUG, "Azalia: verb_size: %d\n", verb_size);
119
120 /* 3 */
121 for (i = 0; i < verb_size; i++) {
Angel Pons554713e2020-10-24 23:23:07 +0200122 if (wait_for_ready(base) < 0)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100123 return;
124
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200125 write32(base + HDA_IC_REG, verb[i]);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100126
Angel Pons554713e2020-10-24 23:23:07 +0200127 if (wait_for_valid(base) < 0)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100128 return;
129 }
130 printk(BIOS_DEBUG, "Azalia: verb loaded.\n");
131}
132
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800133static void codecs_init(struct device *dev, u8 *base, u32 codec_mask)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100134{
135 int i;
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200136
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100137 for (i = 3; i >= 0; i--) {
138 if (codec_mask & (1 << i))
139 codec_init(dev, base, i);
140 }
141
142 for (i = 0; i < pc_beep_verbs_size; i++) {
Angel Pons554713e2020-10-24 23:23:07 +0200143 if (wait_for_ready(base) < 0)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100144 return;
145
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200146 write32(base + HDA_IC_REG, pc_beep_verbs[i]);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100147
Angel Pons554713e2020-10-24 23:23:07 +0200148 if (wait_for_valid(base) < 0)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100149 return;
150 }
151}
152
153static void azalia_init(struct device *dev)
154{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800155 u8 *base;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100156 struct resource *res;
157 u32 codec_mask;
158 u8 reg8;
159 u16 reg16;
160 u32 reg32;
161
162 /* Find base address */
163 res = find_resource(dev, PCI_BASE_ADDRESS_0);
164 if (!res)
165 return;
166
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200167 // NOTE this will break as soon as the Azalia get's a bar above 4G.
168 // Is there anything we can do about it?
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800169 base = res2mmio(res, 0, 0);
Patrick Rudolph819c2062019-11-29 19:27:37 +0100170 printk(BIOS_DEBUG, "Azalia: base = %p\n", base);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100171
172 if (RCBA32(0x2030) & (1 << 31)) {
173 reg32 = pci_read_config32(dev, 0x120);
174 reg32 &= 0xf8ffff01;
175 reg32 |= (1 << 24); // 2 << 24 for server
176 reg32 |= RCBA32(0x2030) & 0xfe;
177 pci_write_config32(dev, 0x120, reg32);
178
179 reg16 = pci_read_config16(dev, 0x78);
180 reg16 |= (1 << 11);
181 pci_write_config16(dev, 0x78, reg16);
182 } else
183 printk(BIOS_DEBUG, "Azalia: V1CTL disabled.\n");
184
185 reg32 = pci_read_config32(dev, 0x114);
186 reg32 &= ~0xfe;
187 pci_write_config32(dev, 0x114, reg32);
188
189 // Set VCi enable bit
190 reg32 = pci_read_config32(dev, 0x120);
191 reg32 |= (1 << 31);
192 pci_write_config32(dev, 0x120, reg32);
193
194 // Enable HDMI codec:
195 reg32 = pci_read_config32(dev, 0xc4);
196 reg32 |= (1 << 1);
197 pci_write_config32(dev, 0xc4, reg32);
198
199 reg8 = pci_read_config8(dev, 0x43);
200 reg8 |= (1 << 6);
201 pci_write_config8(dev, 0x43, reg8);
202
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100203 reg32 = pci_read_config32(dev, 0xd0);
204 reg32 &= ~(1 << 31);
205 pci_write_config32(dev, 0xd0, reg32);
206
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100207 /* Set Bus Master */
Elyes HAOUAS8b6dfde2020-04-28 09:58:21 +0200208 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100209
210 pci_write_config8(dev, 0x3c, 0x0a); // unused?
211
212 /* Codec Initialization Programming Sequence */
213
214 /* Take controller out of reset */
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200215 reg32 = read32(base + HDA_GCTL_REG);
216 reg32 |= HDA_GCTL_CRST;
217 write32(base + HDA_GCTL_REG, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100218 /* Wait 1ms */
219 udelay(1000);
220
221 //
222 reg8 = pci_read_config8(dev, 0x40); // Audio Control
223 reg8 |= 1; // Select Azalia mode. This needs to be controlled via devicetree.cb
224 pci_write_config8(dev, 0x40, reg8);
225
226 reg8 = pci_read_config8(dev, 0x4d); // Docking Status
227 reg8 &= ~(1 << 7); // Docking not supported
228 pci_write_config8(dev, 0x4d, reg8);
229
230 codec_mask = codec_detect(base);
231
232 if (codec_mask) {
233 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
234 codecs_init(dev, base, codec_mask);
235 }
236
237 /* Enable dynamic clock gating */
238 reg8 = pci_read_config8(dev, 0x43);
239 reg8 &= ~0x7;
240 reg8 |= (1 << 2) | (1 << 0);
241 pci_write_config8(dev, 0x43, reg8);
242}
243
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100244static struct device_operations azalia_ops = {
245 .read_resources = pci_dev_read_resources,
246 .set_resources = pci_dev_set_resources,
247 .enable_resources = pci_dev_enable_resources,
248 .init = azalia_init,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200249 .ops_pci = &pci_dev_ops_pci,
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100250};
251
Felix Singer838fbc72019-11-21 21:23:32 +0100252static const unsigned short pci_device_ids[] = {
253 0x1c20,
254 0x1e20,
255 PCI_DID_INTEL_IBEXPEAK_AUDIO,
256 0
257};
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100258
259static const struct pci_driver pch_azalia __pci_driver = {
260 .ops = &azalia_ops,
261 .vendor = PCI_VENDOR_ID_INTEL,
262 .devices = pci_device_ids,
263};