1 | /* $NetBSD: nouveau_subdev_devinit_nv05.c,v 1.1.1.1 2014/08/06 12:36:30 riastradh Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (C) 2010 Francisco Jerez. |
5 | * All Rights Reserved. |
6 | * |
7 | * Permission is hereby granted, free of charge, to any person obtaining |
8 | * a copy of this software and associated documentation files (the |
9 | * "Software"), to deal in the Software without restriction, including |
10 | * without limitation the rights to use, copy, modify, merge, publish, |
11 | * distribute, sublicense, and/or sell copies of the Software, and to |
12 | * permit persons to whom the Software is furnished to do so, subject to |
13 | * the following conditions: |
14 | * |
15 | * The above copyright notice and this permission notice (including the |
16 | * next paragraph) shall be included in all copies or substantial |
17 | * portions of the Software. |
18 | * |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
22 | * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
23 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
24 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
25 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
26 | * |
27 | */ |
28 | |
29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: nouveau_subdev_devinit_nv05.c,v 1.1.1.1 2014/08/06 12:36:30 riastradh Exp $" ); |
31 | |
32 | #include <subdev/bios.h> |
33 | #include <subdev/bios/bmp.h> |
34 | #include <subdev/vga.h> |
35 | |
36 | #include "fbmem.h" |
37 | #include "nv04.h" |
38 | |
39 | static void |
40 | nv05_devinit_meminit(struct nouveau_devinit *devinit) |
41 | { |
42 | static const u8 default_config_tab[][2] = { |
43 | { 0x24, 0x00 }, |
44 | { 0x28, 0x00 }, |
45 | { 0x24, 0x01 }, |
46 | { 0x1f, 0x00 }, |
47 | { 0x0f, 0x00 }, |
48 | { 0x17, 0x00 }, |
49 | { 0x06, 0x00 }, |
50 | { 0x00, 0x00 } |
51 | }; |
52 | struct nv04_devinit_priv *priv = (void *)devinit; |
53 | struct nouveau_bios *bios = nouveau_bios(priv); |
54 | struct io_mapping *fb; |
55 | u32 patt = 0xdeadbeef; |
56 | u16 data; |
57 | u8 strap, ramcfg[2]; |
58 | int i, v; |
59 | |
60 | /* Map the framebuffer aperture */ |
61 | fb = fbmem_init(nv_device(priv)); |
62 | if (!fb) { |
63 | nv_error(priv, "failed to map fb\n" ); |
64 | return; |
65 | } |
66 | |
67 | strap = (nv_rd32(priv, 0x101000) & 0x0000003c) >> 2; |
68 | if ((data = bmp_mem_init_table(bios))) { |
69 | ramcfg[0] = nv_ro08(bios, data + 2 * strap + 0); |
70 | ramcfg[1] = nv_ro08(bios, data + 2 * strap + 1); |
71 | } else { |
72 | ramcfg[0] = default_config_tab[strap][0]; |
73 | ramcfg[1] = default_config_tab[strap][1]; |
74 | } |
75 | |
76 | /* Sequencer off */ |
77 | nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20); |
78 | |
79 | if (nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) |
80 | goto out; |
81 | |
82 | nv_mask(priv, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); |
83 | |
84 | /* If present load the hardcoded scrambling table */ |
85 | if (data) { |
86 | for (i = 0, data += 0x10; i < 8; i++, data += 4) { |
87 | u32 scramble = nv_ro32(bios, data); |
88 | nv_wr32(priv, NV04_PFB_SCRAMBLE(i), scramble); |
89 | } |
90 | } |
91 | |
92 | /* Set memory type/width/length defaults depending on the straps */ |
93 | nv_mask(priv, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); |
94 | |
95 | if (ramcfg[1] & 0x80) |
96 | nv_mask(priv, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); |
97 | |
98 | nv_mask(priv, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); |
99 | nv_mask(priv, NV04_PFB_CFG1, 0, 1); |
100 | |
101 | /* Probe memory bus width */ |
102 | for (i = 0; i < 4; i++) |
103 | fbmem_poke(fb, 4 * i, patt); |
104 | |
105 | if (fbmem_peek(fb, 0xc) != patt) |
106 | nv_mask(priv, NV04_PFB_BOOT_0, |
107 | NV04_PFB_BOOT_0_RAM_WIDTH_128, 0); |
108 | |
109 | /* Probe memory length */ |
110 | v = nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; |
111 | |
112 | if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_32MB && |
113 | (!fbmem_readback(fb, 0x1000000, ++patt) || |
114 | !fbmem_readback(fb, 0, ++patt))) |
115 | nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, |
116 | NV04_PFB_BOOT_0_RAM_AMOUNT_16MB); |
117 | |
118 | if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_16MB && |
119 | !fbmem_readback(fb, 0x800000, ++patt)) |
120 | nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, |
121 | NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); |
122 | |
123 | if (!fbmem_readback(fb, 0x400000, ++patt)) |
124 | nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, |
125 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); |
126 | |
127 | out: |
128 | /* Sequencer on */ |
129 | nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20); |
130 | fbmem_fini(fb); |
131 | } |
132 | |
133 | struct nouveau_oclass * |
134 | nv05_devinit_oclass = &(struct nouveau_devinit_impl) { |
135 | .base.handle = NV_SUBDEV(DEVINIT, 0x05), |
136 | .base.ofuncs = &(struct nouveau_ofuncs) { |
137 | .ctor = nv04_devinit_ctor, |
138 | .dtor = nv04_devinit_dtor, |
139 | .init = nv04_devinit_init, |
140 | .fini = nv04_devinit_fini, |
141 | }, |
142 | .meminit = nv05_devinit_meminit, |
143 | .pll_set = nv04_devinit_pll_set, |
144 | }.base; |
145 | |