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/dcb.h>
0028 #include <subdev/bios/disp.h>
0029 #include <subdev/bios/init.h>
0030 #include <subdev/bios/pll.h>
0031 #include <subdev/clk/pll.h>
0032 #include <subdev/vga.h>
0033 
0034 int
0035 nv50_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
0036 {
0037     struct nvkm_subdev *subdev = &init->subdev;
0038     struct nvkm_device *device = subdev->device;
0039     struct nvkm_bios *bios = device->bios;
0040     struct nvbios_pll info;
0041     int N1, M1, N2, M2, P;
0042     int ret;
0043 
0044     ret = nvbios_pll_parse(bios, type, &info);
0045     if (ret) {
0046         nvkm_error(subdev, "failed to retrieve pll data, %d\n", ret);
0047         return ret;
0048     }
0049 
0050     ret = nv04_pll_calc(subdev, &info, freq, &N1, &M1, &N2, &M2, &P);
0051     if (!ret) {
0052         nvkm_error(subdev, "failed pll calculation\n");
0053         return -EINVAL;
0054     }
0055 
0056     switch (info.type) {
0057     case PLL_VPLL0:
0058     case PLL_VPLL1:
0059         nvkm_wr32(device, info.reg + 0, 0x10000611);
0060         nvkm_mask(device, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1);
0061         nvkm_mask(device, info.reg + 8, 0x7fff00ff, (P  << 28) |
0062                                 (M2 << 16) | N2);
0063         break;
0064     case PLL_MEMORY:
0065         nvkm_mask(device, info.reg + 0, 0x01ff0000,
0066                             (P << 22) |
0067                         (info.bias_p << 19) |
0068                         (P << 16));
0069         nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1);
0070         break;
0071     default:
0072         nvkm_mask(device, info.reg + 0, 0x00070000, (P << 16));
0073         nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1);
0074         break;
0075     }
0076 
0077     return 0;
0078 }
0079 
0080 static u64
0081 nv50_devinit_disable(struct nvkm_devinit *init)
0082 {
0083     struct nvkm_device *device = init->subdev.device;
0084     u32 r001540 = nvkm_rd32(device, 0x001540);
0085     u64 disable = 0ULL;
0086 
0087     if (!(r001540 & 0x40000000))
0088         nvkm_subdev_disable(device, NVKM_ENGINE_MPEG, 0);
0089 
0090     return disable;
0091 }
0092 
0093 void
0094 nv50_devinit_preinit(struct nvkm_devinit *base)
0095 {
0096     struct nvkm_subdev *subdev = &base->subdev;
0097     struct nvkm_device *device = subdev->device;
0098 
0099     /* our heuristics can't detect whether the board has had its
0100      * devinit scripts executed or not if the display engine is
0101      * missing, assume it's a secondary gpu which requires post
0102      */
0103     if (!base->post) {
0104         nvkm_devinit_disable(base);
0105         if (!device->disp)
0106             base->post = true;
0107     }
0108 
0109     /* magic to detect whether or not x86 vbios code has executed
0110      * the devinit scripts to initialise the board
0111      */
0112     if (!base->post) {
0113         if (!nvkm_rdvgac(device, 0, 0x00) &&
0114             !nvkm_rdvgac(device, 0, 0x1a)) {
0115             nvkm_debug(subdev, "adaptor not initialised\n");
0116             base->post = true;
0117         }
0118     }
0119 }
0120 
0121 void
0122 nv50_devinit_init(struct nvkm_devinit *base)
0123 {
0124     struct nv50_devinit *init = nv50_devinit(base);
0125     struct nvkm_subdev *subdev = &init->base.subdev;
0126     struct nvkm_device *device = subdev->device;
0127     struct nvkm_bios *bios = device->bios;
0128     struct nvbios_outp info;
0129     struct dcb_output outp;
0130     u8  ver = 0xff, hdr, cnt, len;
0131     int i = 0;
0132 
0133     /* if we ran the init tables, we have to execute the first script
0134      * pointer of each dcb entry's display encoder table in order
0135      * to properly initialise each encoder.
0136      */
0137     while (init->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) {
0138         if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
0139                       &ver, &hdr, &cnt, &len, &info)) {
0140             nvbios_init(subdev, info.script[0],
0141                 init.outp = &outp;
0142                 init.or   = ffs(outp.or) - 1;
0143                 init.link = outp.sorconf.link == 2;
0144             );
0145         }
0146         i++;
0147     }
0148 }
0149 
0150 int
0151 nv50_devinit_new_(const struct nvkm_devinit_func *func, struct nvkm_device *device,
0152           enum nvkm_subdev_type type, int inst, struct nvkm_devinit **pinit)
0153 {
0154     struct nv50_devinit *init;
0155 
0156     if (!(init = kzalloc(sizeof(*init), GFP_KERNEL)))
0157         return -ENOMEM;
0158     *pinit = &init->base;
0159 
0160     nvkm_devinit_ctor(func, device, type, inst, &init->base);
0161     return 0;
0162 }
0163 
0164 static const struct nvkm_devinit_func
0165 nv50_devinit = {
0166     .preinit = nv50_devinit_preinit,
0167     .init = nv50_devinit_init,
0168     .post = nv04_devinit_post,
0169     .pll_set = nv50_devinit_pll_set,
0170     .disable = nv50_devinit_disable,
0171 };
0172 
0173 int
0174 nv50_devinit_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0175          struct nvkm_devinit **pinit)
0176 {
0177     return nv50_devinit_new_(&nv50_devinit, device, type, inst, pinit);
0178 }