1 /* 2 * Copyright 2013 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24 #include "nv50.h" 25 26 #include <subdev/bios.h> 27 #include <subdev/bios/dcb.h> 28 #include <subdev/bios/disp.h> 29 #include <subdev/bios/init.h> 30 #include <subdev/bios/pll.h> 31 #include <subdev/clk/pll.h> 32 #include <subdev/ibus.h> 33 #include <subdev/vga.h> 34 35 int 36 nv50_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) 37 { 38 struct nvkm_subdev *subdev = &init->subdev; 39 struct nvkm_device *device = subdev->device; 40 struct nvkm_bios *bios = device->bios; 41 struct nvbios_pll info; 42 int N1, M1, N2, M2, P; 43 int ret; 44 45 ret = nvbios_pll_parse(bios, type, &info); 46 if (ret) { 47 nvkm_error(subdev, "failed to retrieve pll data, %d\n", ret); 48 return ret; 49 } 50 51 ret = nv04_pll_calc(subdev, &info, freq, &N1, &M1, &N2, &M2, &P); 52 if (!ret) { 53 nvkm_error(subdev, "failed pll calculation\n"); 54 return ret; 55 } 56 57 switch (info.type) { 58 case PLL_VPLL0: 59 case PLL_VPLL1: 60 nvkm_wr32(device, info.reg + 0, 0x10000611); 61 nvkm_mask(device, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1); 62 nvkm_mask(device, info.reg + 8, 0x7fff00ff, (P << 28) | 63 (M2 << 16) | N2); 64 break; 65 case PLL_MEMORY: 66 nvkm_mask(device, info.reg + 0, 0x01ff0000, 67 (P << 22) | 68 (info.bias_p << 19) | 69 (P << 16)); 70 nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1); 71 break; 72 default: 73 nvkm_mask(device, info.reg + 0, 0x00070000, (P << 16)); 74 nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1); 75 break; 76 } 77 78 return 0; 79 } 80 81 static u64 82 nv50_devinit_disable(struct nvkm_devinit *init) 83 { 84 struct nvkm_device *device = init->subdev.device; 85 u32 r001540 = nvkm_rd32(device, 0x001540); 86 u64 disable = 0ULL; 87 88 if (!(r001540 & 0x40000000)) 89 disable |= (1ULL << NVDEV_ENGINE_MPEG); 90 91 return disable; 92 } 93 94 int 95 nv50_devinit_init(struct nvkm_object *object) 96 { 97 struct nv50_devinit *init = (void *)object; 98 struct nvkm_subdev *subdev = &init->base.subdev; 99 struct nvkm_device *device = subdev->device; 100 struct nvkm_bios *bios = device->bios; 101 struct nvkm_subdev *ibus = device->ibus; 102 struct nvbios_outp info; 103 struct dcb_output outp; 104 u8 ver = 0xff, hdr, cnt, len; 105 int ret, i = 0; 106 107 if (!init->base.post) { 108 if (!nv_rdvgac(init, 0, 0x00) && 109 !nv_rdvgac(init, 0, 0x1a)) { 110 nvkm_debug(subdev, "adaptor not initialised\n"); 111 init->base.post = true; 112 } 113 } 114 115 /* some boards appear to require certain init register timeouts 116 * to be bumped before runing devinit scripts. not a clue why 117 * the vbios engineers didn't make the scripts just work... 118 */ 119 if (init->base.post && ibus) 120 nv_ofuncs(ibus)->init(nv_object(ibus)); 121 122 ret = nvkm_devinit_init(&init->base); 123 if (ret) 124 return ret; 125 126 /* if we ran the init tables, we have to execute the first script 127 * pointer of each dcb entry's display encoder table in order 128 * to properly initialise each encoder. 129 */ 130 while (init->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) { 131 if (nvbios_outp_match(bios, outp.hasht, outp.hashm, 132 &ver, &hdr, &cnt, &len, &info)) { 133 struct nvbios_init exec = { 134 .subdev = nv_subdev(init), 135 .bios = bios, 136 .offset = info.script[0], 137 .outp = &outp, 138 .crtc = -1, 139 .execute = 1, 140 }; 141 142 nvbios_exec(&exec); 143 } 144 i++; 145 } 146 147 return 0; 148 } 149 150 int 151 nv50_devinit_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 152 struct nvkm_oclass *oclass, void *data, u32 size, 153 struct nvkm_object **pobject) 154 { 155 struct nv50_devinit *init; 156 int ret; 157 158 ret = nvkm_devinit_create(parent, engine, oclass, &init); 159 *pobject = nv_object(init); 160 if (ret) 161 return ret; 162 163 return 0; 164 } 165 166 struct nvkm_oclass * 167 nv50_devinit_oclass = &(struct nvkm_devinit_impl) { 168 .base.handle = NV_SUBDEV(DEVINIT, 0x50), 169 .base.ofuncs = &(struct nvkm_ofuncs) { 170 .ctor = nv50_devinit_ctor, 171 .dtor = _nvkm_devinit_dtor, 172 .init = nv50_devinit_init, 173 .fini = _nvkm_devinit_fini, 174 }, 175 .pll_set = nv50_devinit_pll_set, 176 .disable = nv50_devinit_disable, 177 .post = nvbios_init, 178 }.base; 179