blob: 011bde60b1f117f561eae2dfdf5189624894f01f [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 set_bits(void *port, u32 mask, u32 val)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010014{
15 u32 reg32;
16 int count;
17
18 /* Write (val & mask) to port */
19 val &= mask;
20 reg32 = read32(port);
21 reg32 &= ~mask;
22 reg32 |= val;
23 write32(port, reg32);
24
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020025 /* Wait for readback of register to match what was just written to it */
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010026 count = 50;
27 do {
28 /* Wait 1ms based on BKDG wait time */
29 mdelay(1);
30 reg32 = read32(port);
31 reg32 &= mask;
32 } while ((reg32 != val) && --count);
33
34 /* Timeout occurred */
35 if (!count)
36 return -1;
37 return 0;
38}
39
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080040static int codec_detect(u8 *base)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010041{
42 u8 reg8;
43
44 /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020045 if (set_bits(base + HDA_GCTL_REG, 1, HDA_GCTL_CRST) == -1)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010046 goto no_codec;
47
48 /* Write back the value once reset bit is set. */
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020049 write16(base + HDA_GCAP_REG, read16(base + HDA_GCAP_REG));
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010050
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020051 /* Read in Codec location (BAR + 0xe)[2..0] */
Elyes HAOUAS59236d52020-08-03 15:36:52 +020052 reg8 = read8(base + HDA_STATESTS_REG);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010053 reg8 &= 0x0f;
54 if (!reg8)
55 goto no_codec;
56
57 return reg8;
58
59no_codec:
60 /* Codec Not found */
61 /* Put HDA back in reset (BAR + 0x8) [0] */
Elyes HAOUAS59236d52020-08-03 15:36:52 +020062 set_bits(base + HDA_GCTL_REG, 1, 0);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010063 printk(BIOS_DEBUG, "Azalia: No codec!\n");
64 return 0;
65}
66
Elyes HAOUASe414a4e2019-01-03 10:40:43 +010067static u32 find_verb(struct device *dev, u32 viddid, const u32 **verb)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010068{
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020069 int idx = 0;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010070
71 while (idx < (cim_verb_data_size / sizeof(u32))) {
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020072 u32 verb_size = 4 * cim_verb_data[idx + 2]; // in u32
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010073 if (cim_verb_data[idx] != viddid) {
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020074 idx += verb_size + 3; // skip verb + header
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010075 continue;
76 }
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020077 *verb = &cim_verb_data[idx + 3];
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010078 return verb_size;
79 }
80
81 /* Not all codecs need to load another verb */
82 return 0;
83}
84
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020085/*
86 * Wait 50usec for the codec to indicate it is ready.
87 * No response would imply that the codec is non-operative.
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010088 */
89
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080090static int wait_for_ready(u8 *base)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010091{
92 /* Use a 1msec timeout */
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010093 int timeout = 1000;
94
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020095 while (timeout--) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080096 u32 reg32 = read32(base + HDA_ICII_REG);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010097 if (!(reg32 & HDA_ICII_BUSY))
98 return 0;
99 udelay(1);
100 }
101
102 return -1;
103}
104
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200105/*
106 * Wait 50usec for the codec to indicate that it accepted the previous command.
107 * No response would imply that the code is non-operative.
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100108 */
109
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800110static int wait_for_valid(u8 *base)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100111{
112 u32 reg32;
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200113 /* Use a 1msec timeout */
114 int timeout = 1000;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100115
116 /* Send the verb to the codec */
117 reg32 = read32(base + HDA_ICII_REG);
118 reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
119 write32(base + HDA_ICII_REG, reg32);
120
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200121 while (timeout--) {
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100122 reg32 = read32(base + HDA_ICII_REG);
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200123 if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100124 return 0;
125 udelay(1);
126 }
127
128 return -1;
129}
130
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800131static void codec_init(struct device *dev, u8 *base, int addr)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100132{
133 u32 reg32;
134 const u32 *verb;
135 u32 verb_size;
136 int i;
137
138 printk(BIOS_DEBUG, "Azalia: Initializing codec #%d\n", addr);
139
140 /* 1 */
141 if (wait_for_ready(base) == -1) {
142 printk(BIOS_DEBUG, " codec not ready.\n");
143 return;
144 }
145
146 reg32 = (addr << 28) | 0x000f0000;
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200147 write32(base + HDA_IC_REG, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100148
149 if (wait_for_valid(base) == -1) {
150 printk(BIOS_DEBUG, " codec not valid.\n");
151 return;
152 }
153
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100154 /* 2 */
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200155 reg32 = read32(base + HDA_IR_REG);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100156 printk(BIOS_DEBUG, "Azalia: codec viddid: %08x\n", reg32);
157 verb_size = find_verb(dev, reg32, &verb);
158
159 if (!verb_size) {
160 printk(BIOS_DEBUG, "Azalia: No verb!\n");
161 return;
162 }
163 printk(BIOS_DEBUG, "Azalia: verb_size: %d\n", verb_size);
164
165 /* 3 */
166 for (i = 0; i < verb_size; i++) {
167 if (wait_for_ready(base) == -1)
168 return;
169
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200170 write32(base + HDA_IC_REG, verb[i]);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100171
172 if (wait_for_valid(base) == -1)
173 return;
174 }
175 printk(BIOS_DEBUG, "Azalia: verb loaded.\n");
176}
177
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800178static void codecs_init(struct device *dev, u8 *base, u32 codec_mask)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100179{
180 int i;
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200181
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100182 for (i = 3; i >= 0; i--) {
183 if (codec_mask & (1 << i))
184 codec_init(dev, base, i);
185 }
186
187 for (i = 0; i < pc_beep_verbs_size; i++) {
188 if (wait_for_ready(base) == -1)
189 return;
190
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200191 write32(base + HDA_IC_REG, pc_beep_verbs[i]);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100192
193 if (wait_for_valid(base) == -1)
194 return;
195 }
196}
197
198static void azalia_init(struct device *dev)
199{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800200 u8 *base;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100201 struct resource *res;
202 u32 codec_mask;
203 u8 reg8;
204 u16 reg16;
205 u32 reg32;
206
207 /* Find base address */
208 res = find_resource(dev, PCI_BASE_ADDRESS_0);
209 if (!res)
210 return;
211
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200212 // NOTE this will break as soon as the Azalia get's a bar above 4G.
213 // Is there anything we can do about it?
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800214 base = res2mmio(res, 0, 0);
Patrick Rudolph819c2062019-11-29 19:27:37 +0100215 printk(BIOS_DEBUG, "Azalia: base = %p\n", base);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100216
217 if (RCBA32(0x2030) & (1 << 31)) {
218 reg32 = pci_read_config32(dev, 0x120);
219 reg32 &= 0xf8ffff01;
220 reg32 |= (1 << 24); // 2 << 24 for server
221 reg32 |= RCBA32(0x2030) & 0xfe;
222 pci_write_config32(dev, 0x120, reg32);
223
224 reg16 = pci_read_config16(dev, 0x78);
225 reg16 |= (1 << 11);
226 pci_write_config16(dev, 0x78, reg16);
227 } else
228 printk(BIOS_DEBUG, "Azalia: V1CTL disabled.\n");
229
230 reg32 = pci_read_config32(dev, 0x114);
231 reg32 &= ~0xfe;
232 pci_write_config32(dev, 0x114, reg32);
233
234 // Set VCi enable bit
235 reg32 = pci_read_config32(dev, 0x120);
236 reg32 |= (1 << 31);
237 pci_write_config32(dev, 0x120, reg32);
238
239 // Enable HDMI codec:
240 reg32 = pci_read_config32(dev, 0xc4);
241 reg32 |= (1 << 1);
242 pci_write_config32(dev, 0xc4, reg32);
243
244 reg8 = pci_read_config8(dev, 0x43);
245 reg8 |= (1 << 6);
246 pci_write_config8(dev, 0x43, reg8);
247
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100248 reg32 = pci_read_config32(dev, 0xd0);
249 reg32 &= ~(1 << 31);
250 pci_write_config32(dev, 0xd0, reg32);
251
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100252 /* Set Bus Master */
Elyes HAOUAS8b6dfde2020-04-28 09:58:21 +0200253 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100254
255 pci_write_config8(dev, 0x3c, 0x0a); // unused?
256
257 /* Codec Initialization Programming Sequence */
258
259 /* Take controller out of reset */
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200260 reg32 = read32(base + HDA_GCTL_REG);
261 reg32 |= HDA_GCTL_CRST;
262 write32(base + HDA_GCTL_REG, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100263 /* Wait 1ms */
264 udelay(1000);
265
266 //
267 reg8 = pci_read_config8(dev, 0x40); // Audio Control
268 reg8 |= 1; // Select Azalia mode. This needs to be controlled via devicetree.cb
269 pci_write_config8(dev, 0x40, reg8);
270
271 reg8 = pci_read_config8(dev, 0x4d); // Docking Status
272 reg8 &= ~(1 << 7); // Docking not supported
273 pci_write_config8(dev, 0x4d, reg8);
274
275 codec_mask = codec_detect(base);
276
277 if (codec_mask) {
278 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
279 codecs_init(dev, base, codec_mask);
280 }
281
282 /* Enable dynamic clock gating */
283 reg8 = pci_read_config8(dev, 0x43);
284 reg8 &= ~0x7;
285 reg8 |= (1 << 2) | (1 << 0);
286 pci_write_config8(dev, 0x43, reg8);
287}
288
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100289static struct device_operations azalia_ops = {
290 .read_resources = pci_dev_read_resources,
291 .set_resources = pci_dev_set_resources,
292 .enable_resources = pci_dev_enable_resources,
293 .init = azalia_init,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200294 .ops_pci = &pci_dev_ops_pci,
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100295};
296
Felix Singer838fbc72019-11-21 21:23:32 +0100297static const unsigned short pci_device_ids[] = {
298 0x1c20,
299 0x1e20,
300 PCI_DID_INTEL_IBEXPEAK_AUDIO,
301 0
302};
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100303
304static const struct pci_driver pch_azalia __pci_driver = {
305 .ops = &azalia_ops,
306 .vendor = PCI_VENDOR_ID_INTEL,
307 .devices = pci_device_ids,
308};