printk_foo -> printk(BIOS_FOO, ...)
[coreboot.git] / src / southbridge / nvidia / mcp55 / mcp55_aza.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2004 Tyan Computer
5  * Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
6  * Copyright (C) 2006,2007 AMD
7  * Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
22  */
23
24 #include <console/console.h>
25 #include <device/device.h>
26 #include <device/pci.h>
27 #include <device/pci_ids.h>
28 #include <device/pci_ops.h>
29 #include <arch/io.h>
30 #include <delay.h>
31 #include "mcp55.h"
32
33 static int set_bits(uint8_t *port, uint32_t mask, uint32_t val)
34 {
35         uint32_t dword;
36         int count;
37
38         val &= mask;
39         dword = read32(port);
40         dword &= ~mask;
41         dword |= val;
42         write32(port, dword);
43
44         count = 50;
45         do {
46                 dword = read32(port);
47                 dword &= mask;
48                 udelay(100);
49         } while ((dword != val) && --count);
50
51         if(!count) return -1;
52
53         udelay(540);
54         return 0;
55
56 }
57
58 static int codec_detect(uint8_t *base)
59 {
60         uint32_t dword;
61
62         /* 1 */
63         set_bits(base + 0x08, 1, 1);
64
65         /* 2 */
66         dword = read32(base + 0x0e);
67         dword |= 7;
68         write32(base + 0x0e, dword);
69
70         /* 3 */
71         set_bits(base + 0x08, 1, 0);
72
73         /* 4 */
74         set_bits(base + 0x08, 1, 1);
75
76         /* 5 */
77         dword = read32(base + 0xe);
78         dword &= 7;
79
80         /* 6 */
81         if(!dword) {
82                 set_bits(base + 0x08, 1, 0);
83                 printk(BIOS_DEBUG, "No codec!\n");
84                 return 0;
85         }
86         return dword;
87
88 }
89
90 static uint32_t verb_data[] = {
91 #if 0
92         0x00172001,
93         0x001721e6,
94         0x00172200,
95         0x00172300,
96 #endif
97
98         0x01471c10,
99         0x01471d44,
100         0x01471e01,
101         0x01471f01,
102 //1
103         0x01571c12,
104         0x01571d14,
105         0x01571e01,
106         0x01571f01,
107 //2
108         0x01671c11,
109         0x01671d60,
110         0x01671e01,
111         0x01671f01,
112 //3
113         0x01771c14,
114         0x01771d20,
115         0x01771e01,
116         0x01771f01,
117 //4
118         0x01871c30,
119         0x01871d9c,
120         0x01871ea1,
121         0x01871f01,
122 //5
123         0x01971c40,
124         0x01971d9c,
125         0x01971ea1,
126         0x01971f02,
127 //6
128         0x01a71c31,
129         0x01a71d34,
130         0x01a71e81,
131         0x01a71f01,
132 //7
133         0x01b71c1f,
134         0x01b71d44,
135         0x01b71e21,
136         0x01b71f02,
137 //8
138         0x01c71cf0,
139         0x01c71d11,
140         0x01c71e11,
141         0x01c71f41,
142 //9
143         0x01d71c3e,
144         0x01d71d01,
145         0x01d71e83,
146         0x01d71f99,
147 //10
148         0x01e71c20,
149         0x01e71d41,
150         0x01e71e45,
151         0x01e71f01,
152 //11
153         0x01f71c50,
154         0x01f71d91,
155         0x01f71ec5,
156         0x01f71f01,
157 };
158
159 static unsigned find_verb(uint32_t viddid, uint32_t **verb)
160 {
161         if(viddid != 0x10ec0880) return 0;
162         *verb =  (uint32_t *)verb_data;
163         return sizeof(verb_data)/sizeof(uint32_t);
164 }
165
166
167 static void codec_init(uint8_t *base, int addr)
168 {
169         uint32_t dword;
170         uint32_t *verb;
171         unsigned verb_size;
172         int i;
173
174         /* 1 */
175         do {
176                 dword = read32(base + 0x68);
177         } while (dword & 1);
178
179         dword = (addr<<28) | 0x000f0000;
180         write32(base + 0x60, dword);
181
182         do {
183                 dword = read32(base + 0x68);
184         } while ((dword & 3)!=2);
185
186         dword = read32(base + 0x64);
187
188         /* 2 */
189         printk(BIOS_DEBUG, "codec viddid: %08x\n", dword);
190         verb_size = find_verb(dword, &verb);
191
192         if(!verb_size) {
193                 printk(BIOS_DEBUG, "No verb!\n");
194                 return;
195         }
196
197         printk(BIOS_DEBUG, "verb_size: %d\n", verb_size);
198         /* 3 */
199         for(i=0; i<verb_size; i++) {
200                 do {
201                         dword = read32(base + 0x68);
202                 } while (dword & 1);
203
204                 write32(base + 0x60, verb[i]);
205
206                 do {
207                         dword = read32(base + 0x68);
208                 } while ((dword & 3) != 2);
209         }
210         printk(BIOS_DEBUG, "verb loaded!\n");
211 }
212
213 static void codecs_init(uint8_t *base, uint32_t codec_mask)
214 {
215         int i;
216         for(i=2; i>=0; i--) {
217                 if( codec_mask & (1<<i) )
218                         codec_init(base, i);
219         }
220 }
221
222 static void aza_init(struct device *dev)
223 {
224         uint8_t *base;
225         struct resource *res;
226         uint32_t codec_mask;
227
228         res = find_resource(dev, 0x10);
229         if(!res)
230                 return;
231
232         base =(uint8_t *) res->base;
233         printk(BIOS_DEBUG, "base = %08x\n", base);
234
235         codec_mask = codec_detect(base);
236
237         if(codec_mask) {
238                 printk(BIOS_DEBUG, "codec_mask = %02x\n", codec_mask);
239                 codecs_init(base, codec_mask);
240         }
241 }
242
243 static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
244 {
245         pci_write_config32(dev, 0x40,
246                 ((device & 0xffff) << 16) | (vendor & 0xffff));
247 }
248
249 static struct pci_operations lops_pci = {
250         .set_subsystem  = lpci_set_subsystem,
251 };
252
253 static struct device_operations aza_audio_ops  = {
254         .read_resources = pci_dev_read_resources,
255         .set_resources  = pci_dev_set_resources,
256         .enable_resources       = pci_dev_enable_resources,
257 //      .enable         = mcp55_enable,
258         .init           = aza_init,
259         .scan_bus       = 0,
260         .ops_pci        = &lops_pci,
261 };
262
263 static const struct pci_driver azaaudio_driver __pci_driver = {
264         .ops    = &aza_audio_ops,
265         .vendor = PCI_VENDOR_ID_NVIDIA,
266         .device = PCI_DEVICE_ID_NVIDIA_MCP55_AZA,
267 };
268