blob: 15178cbf9d952a29c44c5821519a0b77ed50dee1 [file] [log] [blame]
Stefan Reinauer8e073822012-04-04 00:07:22 +02001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauer8e073822012-04-04 00:07:22 +02004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Stefan Reinauer8e073822012-04-04 00:07:22 +020013 */
14
15#include <console/console.h>
16#include <device/device.h>
17#include <device/pci.h>
18#include <device/pci_ids.h>
19#include <device/pci_ops.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020020#include <device/mmio.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020021#include <delay.h>
Vladimir Serbinenko75c83872014-09-05 01:01:31 +020022#include <device/azalia_device.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030023
24#include "chip.h"
Stefan Reinauer8e073822012-04-04 00:07:22 +020025#include "pch.h"
26
27#define HDA_ICII_REG 0x68
Andrew Wuae8d0692013-08-02 19:29:17 +080028#define HDA_ICII_BUSY (1 << 0)
29#define HDA_ICII_VALID (1 << 1)
Stefan Reinauer8e073822012-04-04 00:07:22 +020030
31typedef struct southbridge_intel_bd82x6x_config config_t;
32
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080033static int set_bits(void *port, u32 mask, u32 val)
Stefan Reinauer8e073822012-04-04 00:07:22 +020034{
35 u32 reg32;
36 int count;
37
38 /* Write (val & mask) to port */
39 val &= mask;
40 reg32 = read32(port);
41 reg32 &= ~mask;
42 reg32 |= val;
43 write32(port, reg32);
44
45 /* Wait for readback of register to
46 * match what was just written to it
47 */
48 count = 50;
49 do {
50 /* Wait 1ms based on BKDG wait time */
51 mdelay(1);
52 reg32 = read32(port);
53 reg32 &= mask;
54 } while ((reg32 != val) && --count);
55
56 /* Timeout occurred */
57 if (!count)
58 return -1;
59 return 0;
60}
61
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080062static int codec_detect(u8 *base)
Stefan Reinauer8e073822012-04-04 00:07:22 +020063{
64 u8 reg8;
65
66 /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
67 if (set_bits(base + 0x08, 1, 1) == -1)
68 goto no_codec;
69
70 /* Write back the value once reset bit is set. */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080071 write16(base + 0x0,
72 read16(base + 0x0));
Stefan Reinauer8e073822012-04-04 00:07:22 +020073
74 /* Read in Codec location (BAR + 0xe)[2..0]*/
75 reg8 = read8(base + 0xe);
76 reg8 &= 0x0f;
77 if (!reg8)
78 goto no_codec;
79
80 return reg8;
81
82no_codec:
83 /* Codec Not found */
84 /* Put HDA back in reset (BAR + 0x8) [0] */
85 set_bits(base + 0x08, 1, 0);
86 printk(BIOS_DEBUG, "Azalia: No codec!\n");
87 return 0;
88}
89
Elyes HAOUASe414a4e2019-01-03 10:40:43 +010090static u32 find_verb(struct device *dev, u32 viddid, const u32 **verb)
Stefan Reinauer8e073822012-04-04 00:07:22 +020091{
92 int idx=0;
93
94 while (idx < (cim_verb_data_size / sizeof(u32))) {
95 u32 verb_size = 4 * cim_verb_data[idx+2]; // in u32
96 if (cim_verb_data[idx] != viddid) {
97 idx += verb_size + 3; // skip verb + header
98 continue;
99 }
100 *verb = &cim_verb_data[idx+3];
101 return verb_size;
102 }
103
104 /* Not all codecs need to load another verb */
105 return 0;
106}
107
108/**
109 * Wait 50usec for the codec to indicate it is ready
110 * no response would imply that the codec is non-operative
111 */
112
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800113static int wait_for_ready(u8 *base)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200114{
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800115 /* Use a 1msec timeout */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200116
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800117 int timeout = 1000;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200118
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200119 while (timeout--) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800120 u32 reg32 = read32(base + HDA_ICII_REG);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200121 if (!(reg32 & HDA_ICII_BUSY))
122 return 0;
123 udelay(1);
124 }
125
126 return -1;
127}
128
129/**
130 * Wait 50usec for the codec to indicate that it accepted
131 * the previous command. No response would imply that the code
132 * is non-operative
133 */
134
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800135static int wait_for_valid(u8 *base)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200136{
137 u32 reg32;
138
139 /* Send the verb to the codec */
140 reg32 = read32(base + HDA_ICII_REG);
141 reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
142 write32(base + HDA_ICII_REG, reg32);
143
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800144 /* Use a 1msec timeout */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200145
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800146 int timeout = 1000;
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200147 while (timeout--) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200148 reg32 = read32(base + HDA_ICII_REG);
149 if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
150 HDA_ICII_VALID)
151 return 0;
152 udelay(1);
153 }
154
155 return -1;
156}
157
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800158static void codec_init(struct device *dev, u8 *base, int addr)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200159{
160 u32 reg32;
161 const u32 *verb;
162 u32 verb_size;
163 int i;
164
165 printk(BIOS_DEBUG, "Azalia: Initializing codec #%d\n", addr);
166
167 /* 1 */
168 if (wait_for_ready(base) == -1) {
169 printk(BIOS_DEBUG, " codec not ready.\n");
170 return;
171 }
172
173 reg32 = (addr << 28) | 0x000f0000;
174 write32(base + 0x60, reg32);
175
176 if (wait_for_valid(base) == -1) {
177 printk(BIOS_DEBUG, " codec not valid.\n");
178 return;
179 }
180
181 reg32 = read32(base + 0x64);
182
183 /* 2 */
184 printk(BIOS_DEBUG, "Azalia: codec viddid: %08x\n", reg32);
185 verb_size = find_verb(dev, reg32, &verb);
186
187 if (!verb_size) {
188 printk(BIOS_DEBUG, "Azalia: No verb!\n");
189 return;
190 }
191 printk(BIOS_DEBUG, "Azalia: verb_size: %d\n", verb_size);
192
193 /* 3 */
194 for (i = 0; i < verb_size; i++) {
195 if (wait_for_ready(base) == -1)
196 return;
197
198 write32(base + 0x60, verb[i]);
199
200 if (wait_for_valid(base) == -1)
201 return;
202 }
203 printk(BIOS_DEBUG, "Azalia: verb loaded.\n");
204}
205
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800206static void codecs_init(struct device *dev, u8 *base, u32 codec_mask)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200207{
208 int i;
209 for (i = 3; i >= 0; i--) {
210 if (codec_mask & (1 << i))
211 codec_init(dev, base, i);
212 }
Dylan Reidb98d0782012-04-27 11:37:33 -0700213
214 for (i = 0; i < pc_beep_verbs_size; i++) {
215 if (wait_for_ready(base) == -1)
216 return;
217
218 write32(base + 0x60, pc_beep_verbs[i]);
219
220 if (wait_for_valid(base) == -1)
221 return;
222 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200223}
224
225static void azalia_init(struct device *dev)
226{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800227 u8 *base;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200228 struct resource *res;
229 u32 codec_mask;
230 u8 reg8;
231 u16 reg16;
232 u32 reg32;
233
234 /* Find base address */
235 res = find_resource(dev, PCI_BASE_ADDRESS_0);
236 if (!res)
237 return;
238
239 // NOTE this will break as soon as the Azalia get's a bar above
240 // 4G. Is there anything we can do about it?
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800241 base = res2mmio(res, 0, 0);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200242 printk(BIOS_DEBUG, "Azalia: base = %08x\n", (u32)base);
243
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200244 if (RCBA32(CIR31) & (1 << 31)) {
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300245 reg32 = pci_read_config32(dev, 0x120);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200246 reg32 &= 0xf8ffff01;
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800247 reg32 |= (1 << 24); // 2 << 24 for server
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200248 reg32 |= RCBA32(CIR31) & 0xfe;
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300249 pci_write_config32(dev, 0x120, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200250
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300251 reg16 = pci_read_config16(dev, 0x78);
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800252 reg16 |= (1 << 11);
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300253 pci_write_config16(dev, 0x78, reg16);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200254 } else
255 printk(BIOS_DEBUG, "Azalia: V1CTL disabled.\n");
256
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300257 reg32 = pci_read_config32(dev, 0x114);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200258 reg32 &= ~0xfe;
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300259 pci_write_config32(dev, 0x114, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200260
261 // Set VCi enable bit
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300262 reg32 = pci_read_config32(dev, 0x120);
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800263 reg32 |= (1 << 31);
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300264 pci_write_config32(dev, 0x120, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200265
266 // Enable HDMI codec:
267 reg32 = pci_read_config32(dev, 0xc4);
268 reg32 |= (1 << 1);
269 pci_write_config32(dev, 0xc4, reg32);
270
271 reg8 = pci_read_config8(dev, 0x43);
272 reg8 |= (1 << 6);
273 pci_write_config8(dev, 0x43, reg8);
274
275 /* Additional programming steps */
276 reg32 = pci_read_config32(dev, 0xc4);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200277 reg32 |= (1 << 13);
278 pci_write_config32(dev, 0xc4, reg32);
279
280 reg32 = pci_read_config32(dev, 0xc4);
281 reg32 |= (1 << 10);
282 pci_write_config32(dev, 0xc4, reg32);
283
284 reg32 = pci_read_config32(dev, 0xd0);
285 reg32 &= ~(1 << 31);
286 pci_write_config32(dev, 0xd0, reg32);
287
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800288 if (dev->device == 0x1e20) {
289 /* Additional step on Panther Point */
290 reg32 = pci_read_config32(dev, 0xc4);
291 reg32 |= (1 << 17);
292 pci_write_config32(dev, 0xc4, reg32);
293 }
294
Stefan Reinauer8e073822012-04-04 00:07:22 +0200295 /* Set Bus Master */
296 reg32 = pci_read_config32(dev, PCI_COMMAND);
297 pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
298
299 pci_write_config8(dev, 0x3c, 0x0a); // unused?
300
301 /* Codec Initialization Programming Sequence */
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800302
303 /* Take controller out of reset */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200304 reg32 = read32(base + 0x08);
305 reg32 |= (1 << 0);
306 write32(base + 0x08, reg32);
Stefan Reinauer15ba2bc2012-11-14 12:25:15 -0800307 /* Wait 1ms */
308 udelay(1000);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200309
310 //
311 reg8 = pci_read_config8(dev, 0x40); // Audio Control
312 reg8 |= 1; // Select Azalia mode. This needs to be controlled via devicetree.cb
313 pci_write_config8(dev, 0x40, reg8);
314
315 reg8 = pci_read_config8(dev, 0x4d); // Docking Status
316 reg8 &= ~(1 << 7); // Docking not supported
317 pci_write_config8(dev, 0x4d, reg8);
318
319 codec_mask = codec_detect(base);
320
321 if (codec_mask) {
322 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
323 codecs_init(dev, base, codec_mask);
324 }
325
326 /* Enable dynamic clock gating */
327 reg8 = pci_read_config8(dev, 0x43);
328 reg8 &= ~0x7;
329 reg8 |= (1 << 2) | (1 << 0);
330 pci_write_config8(dev, 0x43, reg8);
331}
332
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600333static const char *azalia_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200334{
335 return "HDEF";
336}
337
Stefan Reinauer8e073822012-04-04 00:07:22 +0200338static struct pci_operations azalia_pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530339 .set_subsystem = pci_dev_set_subsystem,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200340};
341
342static struct device_operations azalia_ops = {
343 .read_resources = pci_dev_read_resources,
344 .set_resources = pci_dev_set_resources,
345 .enable_resources = pci_dev_enable_resources,
346 .init = azalia_init,
347 .scan_bus = 0,
348 .ops_pci = &azalia_pci_ops,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200349 .acpi_name = azalia_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200350};
351
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700352static const unsigned short pci_device_ids[] = { 0x1c20, 0x1e20, 0 };
Stefan Reinauer8e073822012-04-04 00:07:22 +0200353
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700354static const struct pci_driver pch_azalia __pci_driver = {
355 .ops = &azalia_ops,
356 .vendor = PCI_VENDOR_ID_INTEL,
357 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200358};