Fix a few whitespace and coding style issues.
[coreboot.git] / src / southbridge / intel / sch / audio.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2008 Advanced Micro Devices, Inc.
5  * Copyright (C) 2008-2009 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <console/console.h>
22 #include <device/device.h>
23 #include <device/pci.h>
24 #include <device/pci_ids.h>
25 #include <device/pci_ops.h>
26 #include <arch/io.h>
27 #include <delay.h>
28
29 #define HDA_ICII_REG 0x68
30 #define   HDA_ICII_BUSY (1 << 0)
31 #define   HDA_ICII_VALID  (1 << 1)
32
33 typedef struct southbridge_intel_sch_config config_t;
34
35 static int set_bits(u32 port, u32 mask, u32 val)
36 {
37         u32 reg32;
38         int count;
39
40         /* Write (val & mask) to port */
41         val &= mask;
42         reg32 = read32(port);
43         reg32 &= ~mask;
44         reg32 |= val;
45         write32(port, reg32);
46
47         /* Wait for readback of register to
48          * match what was just written to it
49          */
50         count = 50;
51         do {
52                 /* Wait 1ms based on BKDG wait time */
53                 mdelay(1);
54                 reg32 = read32(port);
55                 reg32 &= mask;
56         } while ((reg32 != val) && --count);
57
58         /* Timeout occurred */
59         if (!count)
60                 return -1;
61         return 0;
62 }
63
64 static int codec_detect(u32 base)
65 {
66         u32 reg32;
67         int count;
68
69         /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
70         if (set_bits(base + 0x08, 1, 1) == -1)
71                 goto no_codec;
72
73         /* clear STATESTS bits (BAR + 0xE)[2:0] */
74         reg32 = read32(base + 0x0E);
75         reg32 |= 7;
76         write32(base + 0x0E, reg32);
77
78         /* Wait for readback of register to
79          * match what was just written to it
80          */
81         count = 50;
82         do {
83                 /* Wait 1ms based on BKDG wait time */
84                 mdelay(1);
85                 reg32 = read32(base + 0x0E);
86         } while ((reg32 != 0) && --count);
87         /* Timeout occured */
88         if (!count)
89                 goto no_codec;
90
91         /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */
92         if (set_bits(base + 0x08, 1, 0) == -1)
93                 goto no_codec;
94
95         /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
96         if (set_bits(base + 0x08, 1, 1) == -1)
97                 goto no_codec;
98
99         /* Read in Codec location (BAR + 0xe)[2..0] */
100         reg32 = read32(base + 0xe);
101         reg32 &= 0x0f;
102         if (!reg32)
103                 goto no_codec;
104
105         return reg32;
106
107 no_codec:
108         /* Codec Not found */
109         /* Put HDA back in reset (BAR + 0x8) [0] */
110         set_bits(base + 0x08, 1, 0);
111         printk(BIOS_DEBUG, "sch_audio: No codec!\n");
112         return 0;
113 }
114
115 const u32 *cim_verb_data = NULL;
116 u32 cim_verb_data_size = 0;
117
118 static u32 find_verb(struct device *dev, u32 viddid, const u32 ** verb)
119 {
120         printk(BIOS_DEBUG, "sch_audio: dev=%s\n", dev_path(dev));
121         printk(BIOS_DEBUG, "sch_audio: Reading viddid=%x\n", viddid);
122
123         int idx = 0;
124
125         while (idx < (cim_verb_data_size / sizeof(u32))) {
126                 u32 verb_size = 4 * cim_verb_data[idx + 2];     // in u32
127                 verb_size++;    // we ship an additional gain value
128                 if (cim_verb_data[idx] != viddid) {
129                         idx += verb_size + 3;   // skip verb + header
130                         continue;
131                 }
132                 *verb = &cim_verb_data[idx + 3];
133                 return verb_size;
134         }
135
136         /* Not all codecs need to load another verb */
137         return 0;
138 }
139
140 /**
141  *  Wait 50usec for the codec to indicate it is ready
142  *  no response would imply that the codec is non-operative
143  */
144
145 static int wait_for_ready(u32 base)
146 {
147         /* Use a 50 usec timeout - the Linux kernel uses the
148          * same duration */
149
150         int timeout = 50;
151
152         while (timeout--) {
153                 u32 reg32 = read32(base + HDA_ICII_REG);
154                 if (!(reg32 & HDA_ICII_BUSY))
155                         return 0;
156                 udelay(1);
157         }
158
159         return -1;
160 }
161
162 /**
163  *  Wait 50usec for the codec to indicate that it accepted
164  *  the previous command.  No response would imply that the code
165  *  is non-operative
166  */
167
168 static int wait_for_valid(u32 base)
169 {
170         /* Use a 50 usec timeout - the Linux kernel uses the
171          * same duration */
172
173         int timeout = 25;
174
175         write32(base + 0x68, 1);
176         while (timeout--) {
177                 udelay(1);
178         }
179         timeout = 50;
180         while (timeout--) {
181                 u32 reg32 = read32(base + 0x68);
182                 if ((reg32 & ((1 << 1) | (1 << 0))) == (1 << 1)) {
183
184                         write32(base + 0x68, 2);
185                         return 0;
186                 }
187                 udelay(1);
188         }
189
190         return 1;
191 }
192
193 static void codec_init(struct device *dev, u32 base, int addr)
194 {
195         u32 reg32;
196         const u32 *verb;
197         u32 verb_size;
198         int i;
199
200         printk(BIOS_DEBUG, "sch_audio: Initializing codec #%d\n", addr);
201
202         /* 1 */
203         if (wait_for_ready(base) == -1)
204                 return;
205
206         reg32 = (addr << 28) | 0x000f0000;
207         write32(base + 0x60, reg32);
208
209         if (wait_for_valid(base) == -1)
210                 return;
211
212         reg32 = read32(base + 0x0);
213         printk(BIOS_DEBUG, "sch_audio: GCAP: %08x\n", reg32);
214
215         reg32 = read32(base + 0x4);
216         printk(BIOS_DEBUG, "sch_audio: OUTPAY: %08x\n", reg32);
217         reg32 = read32(base + 0x6);
218         printk(BIOS_DEBUG, "sch_audio: INPAY: %08x\n", reg32);
219
220         reg32 = read32(base + 0x64);
221
222         /* 2 */
223         printk(BIOS_DEBUG, "sch_audio: codec viddid: %08x\n", reg32);
224         verb_size = find_verb(dev, reg32, &verb);
225
226         if (!verb_size) {
227                 printk(BIOS_DEBUG, "sch_audio: No verb!\n");
228                 return;
229         }
230         printk(BIOS_DEBUG, "sch_audio: verb_size: %d\n", verb_size);
231
232         /* 3 */
233         for (i = 0; i < verb_size; i++) {
234                 if (wait_for_ready(base) == -1)
235                         return;
236
237                 write32(base + 0x60, verb[i]);
238
239                 if (wait_for_valid(base) == -1)
240                         return;
241         }
242         printk(BIOS_DEBUG, "sch_audio: verb loaded.\n");
243 }
244
245 static void codecs_init(struct device *dev, u32 base, u32 codec_mask)
246 {
247         int i;
248
249         for (i = 2; i >= 0; i--) {
250                 if (codec_mask & (1 << i))
251                         codec_init(dev, base, i);
252         }
253 }
254
255 static void sch_audio_init(struct device *dev)
256 {
257         u32 base;
258         struct resource *res;
259         u32 codec_mask;
260         u32 reg32;
261
262         res = find_resource(dev, 0x10);
263         if (!res)
264                 return;
265
266         reg32 = pci_read_config32(dev, PCI_COMMAND);
267         pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MEMORY);
268
269         // NOTE this will break as soon as the sch_audio get's a bar above
270         // 4G. Is there anything we can do about it?
271         base = (u32) res->base;
272         printk(BIOS_DEBUG, "sch_audio: base = %08x\n", (u32) base);
273         codec_mask = codec_detect(base);
274
275         if (codec_mask) {
276                 printk(BIOS_DEBUG, "sch_audio: codec_mask = %02x\n",
277                        codec_mask);
278                 codecs_init(dev, base, codec_mask);
279         } else {
280                 /* No audio codecs found disable HD audio controller */
281                 pci_write_config32(dev, 0x10, 0);
282                 pci_write_config32(dev, PCI_COMMAND, 0);
283                 reg32 = pci_read_config32(dev, 0xFC);
284                 pci_write_config32(dev, 0xFC, reg32 | 1);
285         }
286 }
287
288 static void sch_audio_set_subsystem(device_t dev, unsigned vendor,
289                                     unsigned device)
290 {
291         if (!vendor || !device) {
292                 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
293                                    pci_read_config32(dev, PCI_VENDOR_ID));
294         } else {
295                 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
296                         ((device & 0xffff) << 16) | (vendor & 0xffff));
297         }
298 }
299
300 static struct pci_operations sch_audio_pci_ops = {
301         .set_subsystem = sch_audio_set_subsystem,
302 };
303
304 static struct device_operations sch_audio_ops = {
305         .read_resources         = pci_dev_read_resources,
306         .set_resources          = pci_dev_set_resources,
307         .enable_resources       = pci_dev_enable_resources,
308         .init                   = sch_audio_init,
309         .scan_bus               = 0,
310         .ops_pci                = &sch_audio_pci_ops,
311 };
312
313 /* SCH audio function */
314 static const struct pci_driver sch_audio __pci_driver = {
315         .ops    = &sch_audio_ops,
316         .vendor = PCI_VENDOR_ID_INTEL,
317         .device = 0x811B,
318 };