blob: 543d5cb3eacf1356cab64345a3dd6924bf0eb1f8 [file] [log] [blame]
Angel Ponsc74dae92020-04-02 23:48:16 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Andrew Wub7bb70d2013-08-12 20:07:47 +08002
3#include <console/console.h>
4#include <device/device.h>
5#include <device/pci.h>
Andrew Wub7bb70d2013-08-12 20:07:47 +08006#include <device/azalia_device.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02007#include <device/mmio.h>
Andrew Wub7bb70d2013-08-12 20:07:47 +08008#include <delay.h>
9
Angel Pons61dd8362020-12-05 18:02:32 +010010int azalia_set_bits(void *port, u32 mask, u32 val)
Andrew Wub7bb70d2013-08-12 20:07:47 +080011{
12 u32 reg32;
13 int count;
14
15 /* Write (val & mask) to port */
16 val &= mask;
17 reg32 = read32(port);
18 reg32 &= ~mask;
19 reg32 |= val;
20 write32(port, reg32);
21
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020022 /* Wait for readback of register to match what was just written to it */
Andrew Wub7bb70d2013-08-12 20:07:47 +080023 count = 50;
24 do {
25 /* Wait 1ms based on BKDG wait time */
26 mdelay(1);
27 reg32 = read32(port);
28 reg32 &= mask;
29 } while ((reg32 != val) && --count);
30
31 /* Timeout occurred */
32 if (!count)
33 return -1;
34 return 0;
35}
36
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080037static int codec_detect(u8 *base)
Andrew Wub7bb70d2013-08-12 20:07:47 +080038{
39 u32 reg32;
40 int count;
41
42 /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
Angel Pons61dd8362020-12-05 18:02:32 +010043 if (azalia_set_bits(base + HDA_GCTL_REG, 1, HDA_GCTL_CRST) < 0)
Andrew Wub7bb70d2013-08-12 20:07:47 +080044 goto no_codec;
45
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020046 /* clear STATESTS bits (BAR + 0xe)[2:0] */
Elyes HAOUASd8c47992020-08-03 15:31:39 +020047 reg32 = read32(base + HDA_STATESTS_REG);
Andrew Wub7bb70d2013-08-12 20:07:47 +080048 reg32 |= 7;
Elyes HAOUASd8c47992020-08-03 15:31:39 +020049 write32(base + HDA_STATESTS_REG, reg32);
Andrew Wub7bb70d2013-08-12 20:07:47 +080050
51 /* Wait for readback of register to
52 * match what was just written to it
53 */
54 count = 50;
55 do {
56 /* Wait 1ms based on BKDG wait time */
57 mdelay(1);
Elyes HAOUASd8c47992020-08-03 15:31:39 +020058 reg32 = read32(base + HDA_STATESTS_REG);
Andrew Wub7bb70d2013-08-12 20:07:47 +080059 } while ((reg32 != 0) && --count);
Martin Roth2ed0aa22016-01-05 20:58:58 -070060 /* Timeout occurred */
Andrew Wub7bb70d2013-08-12 20:07:47 +080061 if (!count)
62 goto no_codec;
63
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020064 /* Set Bit 0 to 0 to enter reset state (BAR + 0x8)[0] */
Angel Pons61dd8362020-12-05 18:02:32 +010065 if (azalia_set_bits(base + HDA_GCTL_REG, 1, 0) < 0)
Andrew Wub7bb70d2013-08-12 20:07:47 +080066 goto no_codec;
67
68 /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
Angel Pons61dd8362020-12-05 18:02:32 +010069 if (azalia_set_bits(base + HDA_GCTL_REG, 1, HDA_GCTL_CRST) < 0)
Andrew Wub7bb70d2013-08-12 20:07:47 +080070 goto no_codec;
71
72 /* Read in Codec location (BAR + 0xe)[2..0] */
Elyes HAOUASd8c47992020-08-03 15:31:39 +020073 reg32 = read32(base + HDA_STATESTS_REG);
Andrew Wub7bb70d2013-08-12 20:07:47 +080074 reg32 &= 0x0f;
75 if (!reg32)
76 goto no_codec;
77
78 return reg32;
79
80no_codec:
81 /* Codec Not found */
82 /* Put HDA back in reset (BAR + 0x8) [0] */
Angel Pons61dd8362020-12-05 18:02:32 +010083 azalia_set_bits(base + HDA_GCTL_REG, 1, 0);
Andrew Wub7bb70d2013-08-12 20:07:47 +080084 printk(BIOS_DEBUG, "azalia_audio: No codec!\n");
85 return 0;
86}
87
Elyes HAOUASe414a4e2019-01-03 10:40:43 +010088static u32 find_verb(struct device *dev, u32 viddid, const u32 **verb)
Andrew Wub7bb70d2013-08-12 20:07:47 +080089{
90 printk(BIOS_DEBUG, "azalia_audio: dev=%s\n", dev_path(dev));
91 printk(BIOS_DEBUG, "azalia_audio: Reading viddid=%x\n", viddid);
92
93 int idx = 0;
94
95 while (idx < (cim_verb_data_size / sizeof(u32))) {
96 u32 verb_size = 4 * cim_verb_data[idx + 2]; // in u32
97 if (cim_verb_data[idx] != viddid) {
98 idx += verb_size + 3; // skip verb + header
99 continue;
100 }
101 *verb = &cim_verb_data[idx + 3];
102 return verb_size;
103 }
104
105 /* Not all codecs need to load another verb */
106 return 0;
107}
108
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200109/*
110 * Wait 50usec for the codec to indicate it is ready.
111 * No response would imply that the codec is non-operative.
Andrew Wub7bb70d2013-08-12 20:07:47 +0800112 */
113
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800114static int wait_for_ready(u8 *base)
Andrew Wub7bb70d2013-08-12 20:07:47 +0800115{
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200116 /* Use a 50 usec timeout - the Linux kernel uses the same duration */
Andrew Wub7bb70d2013-08-12 20:07:47 +0800117 int timeout = 50;
118
119 while (timeout--) {
120 u32 reg32 = read32(base + HDA_ICII_REG);
121 if (!(reg32 & HDA_ICII_BUSY))
122 return 0;
123 udelay(1);
124 }
125
126 return -1;
127}
128
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200129/*
130 * Wait 50usec for the codec to indicate that it accepted the previous command.
131 * No response would imply that the code is non-operative.
Andrew Wub7bb70d2013-08-12 20:07:47 +0800132 */
133
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800134static int wait_for_valid(u8 *base)
Andrew Wub7bb70d2013-08-12 20:07:47 +0800135{
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200136 u32 reg32;
137 /* Use a 50 usec timeout - the Linux kernel uses the same duration */
Andrew Wub7bb70d2013-08-12 20:07:47 +0800138 int timeout = 25;
139
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200140 /* Send the verb to the codec */
141 reg32 = read32(base + HDA_ICII_REG);
142 reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
143 write32(base + HDA_ICII_REG, reg32);
144
Andrew Wub7bb70d2013-08-12 20:07:47 +0800145 while (timeout--) {
146 udelay(1);
147 }
148 timeout = 50;
149 while (timeout--) {
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200150 reg32 = read32(base + HDA_ICII_REG);
151 if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID)
Andrew Wub7bb70d2013-08-12 20:07:47 +0800152 return 0;
153 udelay(1);
154 }
155
156 return -1;
157}
158
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800159static void codec_init(struct device *dev, u8 *base, int addr)
Andrew Wub7bb70d2013-08-12 20:07:47 +0800160{
161 u32 reg32;
162 const u32 *verb;
163 u32 verb_size;
164 int i;
165
166 printk(BIOS_DEBUG, "azalia_audio: Initializing codec #%d\n", addr);
167
168 /* 1 */
Angel Pons554713e2020-10-24 23:23:07 +0200169 if (wait_for_ready(base) < 0) {
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200170 printk(BIOS_DEBUG, " codec not ready.\n");
Andrew Wub7bb70d2013-08-12 20:07:47 +0800171 return;
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200172 }
Andrew Wub7bb70d2013-08-12 20:07:47 +0800173
174 reg32 = (addr << 28) | 0x000f0000;
Elyes HAOUASd8c47992020-08-03 15:31:39 +0200175 write32(base + HDA_IC_REG, reg32);
Andrew Wub7bb70d2013-08-12 20:07:47 +0800176
Angel Pons554713e2020-10-24 23:23:07 +0200177 if (wait_for_valid(base) < 0) {
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200178 printk(BIOS_DEBUG, " codec not valid.\n");
Andrew Wub7bb70d2013-08-12 20:07:47 +0800179 return;
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200180 }
Andrew Wub7bb70d2013-08-12 20:07:47 +0800181
182 /* 2 */
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200183 reg32 = read32(base + HDA_IR_REG);
Andrew Wub7bb70d2013-08-12 20:07:47 +0800184 printk(BIOS_DEBUG, "azalia_audio: codec viddid: %08x\n", reg32);
185 verb_size = find_verb(dev, reg32, &verb);
186
187 if (!verb_size) {
188 printk(BIOS_DEBUG, "azalia_audio: No verb!\n");
189 return;
190 }
191 printk(BIOS_DEBUG, "azalia_audio: verb_size: %d\n", verb_size);
192
193 /* 3 */
194 for (i = 0; i < verb_size; i++) {
Angel Pons554713e2020-10-24 23:23:07 +0200195 if (wait_for_ready(base) < 0)
Andrew Wub7bb70d2013-08-12 20:07:47 +0800196 return;
197
Elyes HAOUASd8c47992020-08-03 15:31:39 +0200198 write32(base + HDA_IC_REG, verb[i]);
Andrew Wub7bb70d2013-08-12 20:07:47 +0800199
Angel Pons554713e2020-10-24 23:23:07 +0200200 if (wait_for_valid(base) < 0)
Andrew Wub7bb70d2013-08-12 20:07:47 +0800201 return;
202 }
203 printk(BIOS_DEBUG, "azalia_audio: 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)
Andrew Wub7bb70d2013-08-12 20:07:47 +0800207{
208 int i;
209
210 for (i = 2; i >= 0; i--) {
211 if (codec_mask & (1 << i))
212 codec_init(dev, base, i);
213 }
214}
215
216void azalia_audio_init(struct device *dev)
217{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800218 u8 *base;
Andrew Wub7bb70d2013-08-12 20:07:47 +0800219 struct resource *res;
220 u32 codec_mask;
221
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200222 res = find_resource(dev, PCI_BASE_ADDRESS_0);
Andrew Wub7bb70d2013-08-12 20:07:47 +0800223 if (!res)
224 return;
225
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200226 // NOTE this will break as soon as the azalia_audio get's a bar above 4G.
227 // Is there anything we can do about it?
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800228 base = res2mmio(res, 0, 0);
229 printk(BIOS_DEBUG, "azalia_audio: base = %p\n", base);
Andrew Wub7bb70d2013-08-12 20:07:47 +0800230 codec_mask = codec_detect(base);
231
232 if (codec_mask) {
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +0200233 printk(BIOS_DEBUG, "azalia_audio: codec_mask = %02x\n", codec_mask);
Andrew Wub7bb70d2013-08-12 20:07:47 +0800234 codecs_init(dev, base, codec_mask);
235 }
236}
237
Andrew Wub7bb70d2013-08-12 20:07:47 +0800238struct device_operations default_azalia_audio_ops = {
239 .read_resources = pci_dev_read_resources,
240 .set_resources = pci_dev_set_resources,
241 .enable_resources = pci_dev_enable_resources,
242 .init = azalia_audio_init,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200243 .ops_pci = &pci_dev_ops_pci,
Andrew Wub7bb70d2013-08-12 20:07:47 +0800244};