blob: 2cb731c7e1a4ff105a1fb36636c9aabd78c53470 [file] [log] [blame]
Stefan Reinauerb24d07c2010-08-14 17:45:54 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
5 * Copyright (C) 2008-2010 coresystems GmbH
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000015 */
16
17#include <console/console.h>
18#include <device/device.h>
Jonathan A. Kollaschec505ad22015-07-07 12:57:46 -050019#include <device/azalia_device.h>
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000020#include <device/pci.h>
21#include <device/pci_ids.h>
22#include <device/pci_ops.h>
23#include <arch/io.h>
24#include <delay.h>
25#include "mcp55.h"
26
Jonathan A. Kollaschec505ad22015-07-07 12:57:46 -050027#if IS_ENABLED(CONFIG_MCP55_USE_AZA)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000028#define HDA_ICII_REG 0x68
Andrew Wuae8d0692013-08-02 19:29:17 +080029#define HDA_ICII_BUSY (1 << 0)
30#define HDA_ICII_VALID (1 << 1)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000031
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080032static int set_bits(void *port, u32 mask, u32 val)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000033{
34 u32 reg32;
35 int count;
36
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000037 /* Write (val & mask) to port. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000038 val &= mask;
39 reg32 = read32(port);
40 reg32 &= ~mask;
41 reg32 |= val;
42 write32(port, reg32);
43
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000044 /* Wait for readback of register to match what was written to it. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000045 count = 50;
46 do {
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000047 /* Wait 1ms based on BKDG wait time. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000048 mdelay(1);
49 reg32 = read32(port);
50 reg32 &= mask;
51 } while ((reg32 != val) && --count);
52
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000053 /* Timeout occurred. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000054 if (!count)
55 return -1;
56 return 0;
57}
58
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080059static int codec_detect(u8 *base)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000060{
61 u32 reg32;
62
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000063 /* Set bit 0 to 0 to enter reset state (BAR + 0x8)[0]. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000064 if (set_bits(base + 0x08, 1, 0) == -1)
65 goto no_codec;
66
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000067 /* Set bit 0 to 1 to exit reset state (BAR + 0x8)[0]. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000068 if (set_bits(base + 0x08, 1, 1) == -1)
69 goto no_codec;
70
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000071 /* Read in codec location (BAR + 0xe)[2..0]. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000072 reg32 = read32(base + 0xe);
73 reg32 &= 0x0f;
74 if (!reg32)
75 goto no_codec;
76
77 return reg32;
78
79no_codec:
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000080 /* Codec not found. */
81 /* Put HDA back in reset (BAR + 0x8)[0]. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000082 set_bits(base + 0x08, 1, 0);
83 printk(BIOS_DEBUG, "Azalia: No codec!\n");
84 return 0;
85}
86
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000087
Jonathan A. Kollaschec505ad22015-07-07 12:57:46 -050088static u32 find_verb(struct device *dev, u32 viddid, const u32 **verb)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000089{
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000090 int idx = 0;
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000091
92 while (idx < (cim_verb_data_size / sizeof(u32))) {
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000093 u32 verb_size = 4 * cim_verb_data[idx + 2]; /* in u32 */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000094 if (cim_verb_data[idx] != viddid) {
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000095 idx += verb_size + 3; /* Skip verb + header. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000096 continue;
97 }
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +000098 *verb = &cim_verb_data[idx + 3];
Stefan Reinauerb24d07c2010-08-14 17:45:54 +000099 return verb_size;
100 }
101
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000102 /* Not all codecs need to load another verb. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000103 return 0;
104}
105
106/**
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000107 * Wait 50usec for the codec to indicate it is ready.
108 * No response would imply that the codec is non-operative.
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000109 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800110static int wait_for_ready(u8 *base)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000111{
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000112 /* Use a 50 usec timeout - the Linux kernel uses the same duration. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000113 int timeout = 50;
114
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000115 while (timeout--) {
116 u32 reg32 = read32(base + HDA_ICII_REG);
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000117 if (!(reg32 & HDA_ICII_BUSY))
118 return 0;
119 udelay(1);
120 }
121
122 return -1;
123}
124
125/**
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000126 * Wait 50usec for the codec to indicate that it accepted the previous command.
127 * No response would imply that the code is non-operative.
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000128 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800129static int wait_for_valid(u8 *base)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000130{
131 u32 reg32;
132
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000133 /* Send the verb to the codec. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000134 reg32 = read32(base + 0x68);
135 reg32 |= (1 << 0) | (1 << 1);
136 write32(base + 0x68, reg32);
137
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000138 /* Use a 50 usec timeout - the Linux kernel uses the same duration. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000139 int timeout = 50;
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000140 while (timeout--) {
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000141 reg32 = read32(base + HDA_ICII_REG);
142 if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
143 HDA_ICII_VALID)
144 return 0;
145 udelay(1);
146 }
147
148 return -1;
149}
150
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800151static void codec_init(struct device *dev, u8 *base, int addr)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000152{
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000153 u32 reg32, verb_size;
Jonathan A. Kollaschec505ad22015-07-07 12:57:46 -0500154 const u32 *verb;
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000155 int i;
156
157 printk(BIOS_DEBUG, "Azalia: Initializing codec #%d\n", addr);
158
159 /* 1 */
160 if (wait_for_ready(base) == -1)
161 return;
162
163 reg32 = (addr << 28) | 0x000f0000;
164 write32(base + 0x60, reg32);
165
166 if (wait_for_valid(base) == -1)
167 return;
168
169 reg32 = read32(base + 0x64);
170
171 /* 2 */
172 printk(BIOS_DEBUG, "Azalia: codec viddid: %08x\n", reg32);
173 verb_size = find_verb(dev, reg32, &verb);
174
175 if (!verb_size) {
176 printk(BIOS_DEBUG, "Azalia: No verb!\n");
177 return;
178 }
179 printk(BIOS_DEBUG, "Azalia: verb_size: %d\n", verb_size);
180
181 /* 3 */
182 for (i = 0; i < verb_size; i++) {
183 if (wait_for_ready(base) == -1)
184 return;
185
186 write32(base + 0x60, verb[i]);
187
188 if (wait_for_valid(base) == -1)
189 return;
190 }
191 printk(BIOS_DEBUG, "Azalia: verb loaded.\n");
192}
193
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800194static void codecs_init(struct device *dev, u8 *base, u32 codec_mask)
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000195{
196 int i;
197 for (i = 2; i >= 0; i--) {
198 if (codec_mask & (1 << i))
199 codec_init(dev, base, i);
200 }
201}
Jonathan A. Kollaschec505ad22015-07-07 12:57:46 -0500202#endif
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000203
204static void azalia_init(struct device *dev)
205{
Jonathan A. Kollaschec505ad22015-07-07 12:57:46 -0500206#if IS_ENABLED(CONFIG_MCP55_USE_AZA)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800207 u8 *base;
208 u32 codec_mask, reg32;
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000209 struct resource *res;
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000210 u8 reg8;
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000211
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000212 /* Set bus master. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000213 reg32 = pci_read_config32(dev, PCI_COMMAND);
214 pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
215
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000216 pci_write_config8(dev, 0x3c, 0x0a); // TODO: Unused?
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000217
218 reg8 = pci_read_config8(dev, 0x40);
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000219 reg8 |= (1 << 3); /* Clear Clock Detect bit. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000220 pci_write_config8(dev, 0x40, reg8);
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000221 reg8 &= ~(1 << 3); /* Keep CLKDETCLR from clearing the bit over and over. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000222 pci_write_config8(dev, 0x40, reg8);
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000223 reg8 |= (1 << 2); /* Enable clock detection. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000224 pci_write_config8(dev, 0x40, reg8);
225 mdelay(1);
226 reg8 = pci_read_config8(dev, 0x40);
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000227 printk(BIOS_DEBUG, "Azalia: codec type: %s\n",
228 (reg8 & (1 << 1)) ? "Azalia" : "AC97");
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000229
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000230 reg8 = pci_read_config8(dev, 0x40); /* Audio control */
231 reg8 |= 1; /* Select Azalia mode. TODO: Control via devicetree.cb. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000232 pci_write_config8(dev, 0x40, reg8);
233
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000234 reg8 = pci_read_config8(dev, 0x4d); /* Docking status. */
235 reg8 &= ~(1 << 7); /* Docking not supported. */
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000236 pci_write_config8(dev, 0x4d, reg8);
237
238 res = find_resource(dev, 0x10);
239 if (!res)
240 return;
241
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000242 /*
243 * NOTE: This will break as soon as the Azalia gets a BAR above
244 * 4G. Is there anything we can do about it?
245 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800246 base = res2mmio(res, 0, 0);
247 printk(BIOS_DEBUG, "Azalia: base = %p\n", base);
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000248 codec_mask = codec_detect(base);
249
250 if (codec_mask) {
251 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
252 codecs_init(dev, base, codec_mask);
253 }
Jonathan A. Kollaschec505ad22015-07-07 12:57:46 -0500254#endif
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000255}
256
257static void azalia_set_subsystem(device_t dev, unsigned vendor, unsigned device)
258{
259 if (!vendor || !device) {
260 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
261 pci_read_config32(dev, PCI_VENDOR_ID));
262 } else {
263 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
264 ((device & 0xffff) << 16) | (vendor & 0xffff));
265 }
266}
267
268static struct pci_operations azalia_pci_ops = {
Uwe Hermannc7f0c8f2011-01-04 19:51:33 +0000269 .set_subsystem = azalia_set_subsystem,
Stefan Reinauerb24d07c2010-08-14 17:45:54 +0000270};
271
272static struct device_operations azalia_ops = {
273 .read_resources = pci_dev_read_resources,
274 .set_resources = pci_dev_set_resources,
275 .enable_resources = pci_dev_enable_resources,
276 .init = azalia_init,
277 .scan_bus = 0,
278// .enable = mcp55_enable,
279 .ops_pci = &azalia_pci_ops,
280};
281
282static const struct pci_driver azalia __pci_driver = {
283 .ops = &azalia_ops,
284 .vendor = PCI_VENDOR_ID_NVIDIA,
285 .device = PCI_DEVICE_ID_NVIDIA_MCP55_AZA,
286};