2 * Copyright (C) 2010 Francisco Jerez.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include <subdev/bios.h>
30 #include <subdev/bios/bmp.h>
31 #include <subdev/bios/init.h>
32 #include <subdev/vga.h>
35 nv05_devinit_meminit(struct nvkm_devinit
*init
)
37 static const u8 default_config_tab
[][2] = {
47 struct nvkm_subdev
*subdev
= &init
->subdev
;
48 struct nvkm_device
*device
= subdev
->device
;
49 struct nvkm_bios
*bios
= device
->bios
;
50 struct io_mapping
*fb
;
51 u32 patt
= 0xdeadbeef;
56 /* Map the framebuffer aperture */
57 fb
= fbmem_init(device
);
59 nvkm_error(subdev
, "failed to map fb\n");
63 strap
= (nvkm_rd32(device
, 0x101000) & 0x0000003c) >> 2;
64 if ((data
= bmp_mem_init_table(bios
))) {
65 ramcfg
[0] = nvbios_rd08(bios
, data
+ 2 * strap
+ 0);
66 ramcfg
[1] = nvbios_rd08(bios
, data
+ 2 * strap
+ 1);
68 ramcfg
[0] = default_config_tab
[strap
][0];
69 ramcfg
[1] = default_config_tab
[strap
][1];
73 nvkm_wrvgas(device
, 0, 1, nvkm_rdvgas(device
, 0, 1) | 0x20);
75 if (nvkm_rd32(device
, NV04_PFB_BOOT_0
) & NV04_PFB_BOOT_0_UMA_ENABLE
)
78 nvkm_mask(device
, NV04_PFB_DEBUG_0
, NV04_PFB_DEBUG_0_REFRESH_OFF
, 0);
80 /* If present load the hardcoded scrambling table */
82 for (i
= 0, data
+= 0x10; i
< 8; i
++, data
+= 4) {
83 u32 scramble
= nvbios_rd32(bios
, data
);
84 nvkm_wr32(device
, NV04_PFB_SCRAMBLE(i
), scramble
);
88 /* Set memory type/width/length defaults depending on the straps */
89 nvkm_mask(device
, NV04_PFB_BOOT_0
, 0x3f, ramcfg
[0]);
92 nvkm_mask(device
, NV04_PFB_CFG0
, 0, NV04_PFB_CFG0_SCRAMBLE
);
94 nvkm_mask(device
, NV04_PFB_CFG1
, 0x700001, (ramcfg
[1] & 1) << 20);
95 nvkm_mask(device
, NV04_PFB_CFG1
, 0, 1);
97 /* Probe memory bus width */
98 for (i
= 0; i
< 4; i
++)
99 fbmem_poke(fb
, 4 * i
, patt
);
101 if (fbmem_peek(fb
, 0xc) != patt
)
102 nvkm_mask(device
, NV04_PFB_BOOT_0
,
103 NV04_PFB_BOOT_0_RAM_WIDTH_128
, 0);
105 /* Probe memory length */
106 v
= nvkm_rd32(device
, NV04_PFB_BOOT_0
) & NV04_PFB_BOOT_0_RAM_AMOUNT
;
108 if (v
== NV04_PFB_BOOT_0_RAM_AMOUNT_32MB
&&
109 (!fbmem_readback(fb
, 0x1000000, ++patt
) ||
110 !fbmem_readback(fb
, 0, ++patt
)))
111 nvkm_mask(device
, NV04_PFB_BOOT_0
, NV04_PFB_BOOT_0_RAM_AMOUNT
,
112 NV04_PFB_BOOT_0_RAM_AMOUNT_16MB
);
114 if (v
== NV04_PFB_BOOT_0_RAM_AMOUNT_16MB
&&
115 !fbmem_readback(fb
, 0x800000, ++patt
))
116 nvkm_mask(device
, NV04_PFB_BOOT_0
, NV04_PFB_BOOT_0_RAM_AMOUNT
,
117 NV04_PFB_BOOT_0_RAM_AMOUNT_8MB
);
119 if (!fbmem_readback(fb
, 0x400000, ++patt
))
120 nvkm_mask(device
, NV04_PFB_BOOT_0
, NV04_PFB_BOOT_0_RAM_AMOUNT
,
121 NV04_PFB_BOOT_0_RAM_AMOUNT_4MB
);
125 nvkm_wrvgas(device
, 0, 1, nvkm_rdvgas(device
, 0, 1) & ~0x20);
129 static const struct nvkm_devinit_func
131 .dtor
= nv04_devinit_dtor
,
132 .preinit
= nv04_devinit_preinit
,
133 .post
= nv04_devinit_post
,
134 .meminit
= nv05_devinit_meminit
,
135 .pll_set
= nv04_devinit_pll_set
,
139 nv05_devinit_new(struct nvkm_device
*device
, int index
,
140 struct nvkm_devinit
**pinit
)
142 return nv04_devinit_new_(&nv05_devinit
, device
, index
, pinit
);