Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2013 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs
0023  */
0024 #include "nv50.h"
0025 
0026 #include <subdev/bios.h>
0027 #include <subdev/bios/init.h>
0028 #include <subdev/bios/pll.h>
0029 #include <subdev/clk/pll.h>
0030 
0031 int
0032 gt215_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
0033 {
0034     struct nvkm_subdev *subdev = &init->subdev;
0035     struct nvkm_device *device = subdev->device;
0036     struct nvbios_pll info;
0037     int N, fN, M, P;
0038     int ret;
0039 
0040     ret = nvbios_pll_parse(device->bios, type, &info);
0041     if (ret)
0042         return ret;
0043 
0044     ret = gt215_pll_calc(subdev, &info, freq, &N, &fN, &M, &P);
0045     if (ret < 0)
0046         return ret;
0047 
0048     switch (info.type) {
0049     case PLL_VPLL0:
0050     case PLL_VPLL1:
0051         nvkm_wr32(device, info.reg + 0, 0x50000610);
0052         nvkm_mask(device, info.reg + 4, 0x003fffff,
0053                         (P << 16) | (M << 8) | N);
0054         nvkm_wr32(device, info.reg + 8, fN);
0055         break;
0056     default:
0057         nvkm_warn(subdev, "%08x/%dKhz unimplemented\n", type, freq);
0058         ret = -EINVAL;
0059         break;
0060     }
0061 
0062     return ret;
0063 }
0064 
0065 static u64
0066 gt215_devinit_disable(struct nvkm_devinit *init)
0067 {
0068     struct nvkm_device *device = init->subdev.device;
0069     u32 r001540 = nvkm_rd32(device, 0x001540);
0070     u32 r00154c = nvkm_rd32(device, 0x00154c);
0071 
0072     if (!(r001540 & 0x40000000)) {
0073         nvkm_subdev_disable(device, NVKM_ENGINE_MSPDEC, 0);
0074         nvkm_subdev_disable(device, NVKM_ENGINE_MSPPP, 0);
0075     }
0076 
0077     if (!(r00154c & 0x00000004))
0078         nvkm_subdev_disable(device, NVKM_ENGINE_DISP, 0);
0079     if (!(r00154c & 0x00000020))
0080         nvkm_subdev_disable(device, NVKM_ENGINE_MSVLD, 0);
0081     if (!(r00154c & 0x00000200))
0082         nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0);
0083 
0084     return 0ULL;
0085 }
0086 
0087 static u32
0088 gt215_devinit_mmio_part[] = {
0089     0x100720, 0x1008bc, 4,
0090     0x100a20, 0x100adc, 4,
0091     0x100d80, 0x100ddc, 4,
0092     0x110000, 0x110f9c, 4,
0093     0x111000, 0x11103c, 8,
0094     0x111080, 0x1110fc, 4,
0095     0x111120, 0x1111fc, 4,
0096     0x111300, 0x1114bc, 4,
0097     0,
0098 };
0099 
0100 static u32
0101 gt215_devinit_mmio(struct nvkm_devinit *base, u32 addr)
0102 {
0103     struct nv50_devinit *init = nv50_devinit(base);
0104     struct nvkm_device *device = init->base.subdev.device;
0105     u32 *mmio = gt215_devinit_mmio_part;
0106 
0107     /* the init tables on some boards have INIT_RAM_RESTRICT_ZM_REG_GROUP
0108      * instructions which touch registers that may not even exist on
0109      * some configurations (Quadro 400), which causes the register
0110      * interface to screw up for some amount of time after attempting to
0111      * write to one of these, and results in all sorts of things going
0112      * horribly wrong.
0113      *
0114      * the binary driver avoids touching these registers at all, however,
0115      * the video bios doesn't care and does what the scripts say.  it's
0116      * presumed that the io-port access to init registers isn't effected
0117      * by the screw-up bug mentioned above.
0118      *
0119      * really, a new opcode should've been invented to handle these
0120      * requirements, but whatever, it's too late for that now.
0121      */
0122     while (mmio[0]) {
0123         if (addr >= mmio[0] && addr <= mmio[1]) {
0124             u32 part = (addr / mmio[2]) & 7;
0125             if (!init->r001540)
0126                 init->r001540 = nvkm_rd32(device, 0x001540);
0127             if (part >= hweight8((init->r001540 >> 16) & 0xff))
0128                 return ~0;
0129             return addr;
0130         }
0131         mmio += 3;
0132     }
0133 
0134     return addr;
0135 }
0136 
0137 static const struct nvkm_devinit_func
0138 gt215_devinit = {
0139     .preinit = nv50_devinit_preinit,
0140     .init = nv50_devinit_init,
0141     .post = nv04_devinit_post,
0142     .mmio = gt215_devinit_mmio,
0143     .pll_set = gt215_devinit_pll_set,
0144     .disable = gt215_devinit_disable,
0145 };
0146 
0147 int
0148 gt215_devinit_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0149           struct nvkm_devinit **pinit)
0150 {
0151     return nv50_devinit_new_(&gt215_devinit, device, type, inst, pinit);
0152 }