Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2005-2006 Erik Waling
0003  * Copyright 2006 Stephane Marchesin
0004  * Copyright 2007-2009 Stuart Bennett
0005  *
0006  * Permission is hereby granted, free of charge, to any person obtaining a
0007  * copy of this software and associated documentation files (the "Software"),
0008  * to deal in the Software without restriction, including without limitation
0009  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010  * and/or sell copies of the Software, and to permit persons to whom the
0011  * Software is furnished to do so, subject to the following conditions:
0012  *
0013  * The above copyright notice and this permission notice shall be included in
0014  * all copies or substantial portions of the Software.
0015  *
0016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0017  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0018  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0019  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
0020  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
0021  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0022  * SOFTWARE.
0023  */
0024 #include <subdev/bios.h>
0025 #include <subdev/bios/bit.h>
0026 #include <subdev/bios/bmp.h>
0027 #include <subdev/bios/pll.h>
0028 #include <subdev/vga.h>
0029 
0030 
0031 struct pll_mapping {
0032     u8  type;
0033     u32 reg;
0034 };
0035 
0036 static struct pll_mapping
0037 nv04_pll_mapping[] = {
0038     { PLL_CORE  , 0x680500 },
0039     { PLL_MEMORY, 0x680504 },
0040     { PLL_VPLL0 , 0x680508 },
0041     { PLL_VPLL1 , 0x680520 },
0042     {}
0043 };
0044 
0045 static struct pll_mapping
0046 nv40_pll_mapping[] = {
0047     { PLL_CORE  , 0x004000 },
0048     { PLL_MEMORY, 0x004020 },
0049     { PLL_VPLL0 , 0x680508 },
0050     { PLL_VPLL1 , 0x680520 },
0051     {}
0052 };
0053 
0054 static struct pll_mapping
0055 nv50_pll_mapping[] = {
0056     { PLL_CORE  , 0x004028 },
0057     { PLL_SHADER, 0x004020 },
0058     { PLL_UNK03 , 0x004000 },
0059     { PLL_MEMORY, 0x004008 },
0060     { PLL_UNK40 , 0x00e810 },
0061     { PLL_UNK41 , 0x00e818 },
0062     { PLL_UNK42 , 0x00e824 },
0063     { PLL_VPLL0 , 0x614100 },
0064     { PLL_VPLL1 , 0x614900 },
0065     {}
0066 };
0067 
0068 static struct pll_mapping
0069 g84_pll_mapping[] = {
0070     { PLL_CORE  , 0x004028 },
0071     { PLL_SHADER, 0x004020 },
0072     { PLL_MEMORY, 0x004008 },
0073     { PLL_VDEC  , 0x004030 },
0074     { PLL_UNK41 , 0x00e818 },
0075     { PLL_VPLL0 , 0x614100 },
0076     { PLL_VPLL1 , 0x614900 },
0077     {}
0078 };
0079 
0080 static u32
0081 pll_limits_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
0082 {
0083     struct bit_entry bit_C;
0084     u32 data = 0x0000;
0085 
0086     if (!bit_entry(bios, 'C', &bit_C)) {
0087         if (bit_C.version == 1 && bit_C.length >= 10)
0088             data = nvbios_rd16(bios, bit_C.offset + 8);
0089         if (bit_C.version == 2 && bit_C.length >= 4)
0090             data = nvbios_rd32(bios, bit_C.offset + 0);
0091         if (data) {
0092             *ver = nvbios_rd08(bios, data + 0);
0093             *hdr = nvbios_rd08(bios, data + 1);
0094             *len = nvbios_rd08(bios, data + 2);
0095             *cnt = nvbios_rd08(bios, data + 3);
0096             return data;
0097         }
0098     }
0099 
0100     if (bmp_version(bios) >= 0x0524) {
0101         data = nvbios_rd16(bios, bios->bmp_offset + 142);
0102         if (data) {
0103             *ver = nvbios_rd08(bios, data + 0);
0104             *hdr = 1;
0105             *cnt = 1;
0106             *len = 0x18;
0107             return data;
0108         }
0109     }
0110 
0111     *ver = 0x00;
0112     return data;
0113 }
0114 
0115 static struct pll_mapping *
0116 pll_map(struct nvkm_bios *bios)
0117 {
0118     struct nvkm_device *device = bios->subdev.device;
0119     switch (device->card_type) {
0120     case NV_04:
0121     case NV_10:
0122     case NV_11:
0123     case NV_20:
0124     case NV_30:
0125         return nv04_pll_mapping;
0126     case NV_40:
0127         return nv40_pll_mapping;
0128     case NV_50:
0129         if (device->chipset == 0x50)
0130             return nv50_pll_mapping;
0131         else
0132         if (device->chipset <  0xa3 ||
0133             device->chipset == 0xaa ||
0134             device->chipset == 0xac)
0135             return g84_pll_mapping;
0136         fallthrough;
0137     default:
0138         return NULL;
0139     }
0140 }
0141 
0142 static u32
0143 pll_map_reg(struct nvkm_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)
0144 {
0145     struct pll_mapping *map;
0146     u8  hdr, cnt;
0147     u32 data;
0148 
0149     data = pll_limits_table(bios, ver, &hdr, &cnt, len);
0150     if (data && *ver >= 0x30) {
0151         data += hdr;
0152         while (cnt--) {
0153             if (nvbios_rd32(bios, data + 3) == reg) {
0154                 *type = nvbios_rd08(bios, data + 0);
0155                 return data;
0156             }
0157             data += *len;
0158         }
0159         return 0x0000;
0160     }
0161 
0162     map = pll_map(bios);
0163     while (map && map->reg) {
0164         if (map->reg == reg && *ver >= 0x20) {
0165             u32 addr = (data += hdr);
0166             *type = map->type;
0167             while (cnt--) {
0168                 if (nvbios_rd32(bios, data) == map->reg)
0169                     return data;
0170                 data += *len;
0171             }
0172             return addr;
0173         } else
0174         if (map->reg == reg) {
0175             *type = map->type;
0176             return data + 1;
0177         }
0178         map++;
0179     }
0180 
0181     return 0x0000;
0182 }
0183 
0184 static u32
0185 pll_map_type(struct nvkm_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)
0186 {
0187     struct pll_mapping *map;
0188     u8  hdr, cnt;
0189     u32 data;
0190 
0191     data = pll_limits_table(bios, ver, &hdr, &cnt, len);
0192     if (data && *ver >= 0x30) {
0193         data += hdr;
0194         while (cnt--) {
0195             if (nvbios_rd08(bios, data + 0) == type) {
0196                 if (*ver < 0x50)
0197                     *reg = nvbios_rd32(bios, data + 3);
0198                 else
0199                     *reg = 0;
0200                 return data;
0201             }
0202             data += *len;
0203         }
0204         return 0x0000;
0205     }
0206 
0207     map = pll_map(bios);
0208     while (map && map->reg) {
0209         if (map->type == type && *ver >= 0x20) {
0210             u32 addr = (data += hdr);
0211             *reg = map->reg;
0212             while (cnt--) {
0213                 if (nvbios_rd32(bios, data) == map->reg)
0214                     return data;
0215                 data += *len;
0216             }
0217             return addr;
0218         } else
0219         if (map->type == type) {
0220             *reg = map->reg;
0221             return data + 1;
0222         }
0223         map++;
0224     }
0225 
0226     return 0x0000;
0227 }
0228 
0229 int
0230 nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info)
0231 {
0232     struct nvkm_subdev *subdev = &bios->subdev;
0233     struct nvkm_device *device = subdev->device;
0234     u8  ver, len;
0235     u32 reg = type;
0236     u32 data;
0237 
0238     if (type > PLL_MAX) {
0239         reg  = type;
0240         data = pll_map_reg(bios, reg, &type, &ver, &len);
0241     } else {
0242         data = pll_map_type(bios, type, &reg, &ver, &len);
0243     }
0244 
0245     if (ver && !data)
0246         return -ENOENT;
0247 
0248     memset(info, 0, sizeof(*info));
0249     info->type = type;
0250     info->reg = reg;
0251 
0252     switch (ver) {
0253     case 0x00:
0254         break;
0255     case 0x10:
0256     case 0x11:
0257         info->vco1.min_freq = nvbios_rd32(bios, data + 0);
0258         info->vco1.max_freq = nvbios_rd32(bios, data + 4);
0259         info->vco2.min_freq = nvbios_rd32(bios, data + 8);
0260         info->vco2.max_freq = nvbios_rd32(bios, data + 12);
0261         info->vco1.min_inputfreq = nvbios_rd32(bios, data + 16);
0262         info->vco2.min_inputfreq = nvbios_rd32(bios, data + 20);
0263         info->vco1.max_inputfreq = INT_MAX;
0264         info->vco2.max_inputfreq = INT_MAX;
0265 
0266         info->max_p = 0x7;
0267         info->max_p_usable = 0x6;
0268 
0269         /* these values taken from nv30/31/36 */
0270         switch (bios->version.chip) {
0271         case 0x36:
0272             info->vco1.min_n = 0x5;
0273             break;
0274         default:
0275             info->vco1.min_n = 0x1;
0276             break;
0277         }
0278         info->vco1.max_n = 0xff;
0279         info->vco1.min_m = 0x1;
0280         info->vco1.max_m = 0xd;
0281 
0282         /*
0283          * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this
0284          * table version (apart from nv35)), N2 is compared to
0285          * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and
0286          * save a comparison
0287          */
0288         info->vco2.min_n = 0x4;
0289         switch (bios->version.chip) {
0290         case 0x30:
0291         case 0x35:
0292             info->vco2.max_n = 0x1f;
0293             break;
0294         default:
0295             info->vco2.max_n = 0x28;
0296             break;
0297         }
0298         info->vco2.min_m = 0x1;
0299         info->vco2.max_m = 0x4;
0300         break;
0301     case 0x20:
0302     case 0x21:
0303         info->vco1.min_freq = nvbios_rd16(bios, data + 4) * 1000;
0304         info->vco1.max_freq = nvbios_rd16(bios, data + 6) * 1000;
0305         info->vco2.min_freq = nvbios_rd16(bios, data + 8) * 1000;
0306         info->vco2.max_freq = nvbios_rd16(bios, data + 10) * 1000;
0307         info->vco1.min_inputfreq = nvbios_rd16(bios, data + 12) * 1000;
0308         info->vco2.min_inputfreq = nvbios_rd16(bios, data + 14) * 1000;
0309         info->vco1.max_inputfreq = nvbios_rd16(bios, data + 16) * 1000;
0310         info->vco2.max_inputfreq = nvbios_rd16(bios, data + 18) * 1000;
0311         info->vco1.min_n = nvbios_rd08(bios, data + 20);
0312         info->vco1.max_n = nvbios_rd08(bios, data + 21);
0313         info->vco1.min_m = nvbios_rd08(bios, data + 22);
0314         info->vco1.max_m = nvbios_rd08(bios, data + 23);
0315         info->vco2.min_n = nvbios_rd08(bios, data + 24);
0316         info->vco2.max_n = nvbios_rd08(bios, data + 25);
0317         info->vco2.min_m = nvbios_rd08(bios, data + 26);
0318         info->vco2.max_m = nvbios_rd08(bios, data + 27);
0319 
0320         info->max_p = nvbios_rd08(bios, data + 29);
0321         info->max_p_usable = info->max_p;
0322         if (bios->version.chip < 0x60)
0323             info->max_p_usable = 0x6;
0324         info->bias_p = nvbios_rd08(bios, data + 30);
0325 
0326         if (len > 0x22)
0327             info->refclk = nvbios_rd32(bios, data + 31);
0328         break;
0329     case 0x30:
0330         data = nvbios_rd16(bios, data + 1);
0331 
0332         info->vco1.min_freq = nvbios_rd16(bios, data + 0) * 1000;
0333         info->vco1.max_freq = nvbios_rd16(bios, data + 2) * 1000;
0334         info->vco2.min_freq = nvbios_rd16(bios, data + 4) * 1000;
0335         info->vco2.max_freq = nvbios_rd16(bios, data + 6) * 1000;
0336         info->vco1.min_inputfreq = nvbios_rd16(bios, data + 8) * 1000;
0337         info->vco2.min_inputfreq = nvbios_rd16(bios, data + 10) * 1000;
0338         info->vco1.max_inputfreq = nvbios_rd16(bios, data + 12) * 1000;
0339         info->vco2.max_inputfreq = nvbios_rd16(bios, data + 14) * 1000;
0340         info->vco1.min_n = nvbios_rd08(bios, data + 16);
0341         info->vco1.max_n = nvbios_rd08(bios, data + 17);
0342         info->vco1.min_m = nvbios_rd08(bios, data + 18);
0343         info->vco1.max_m = nvbios_rd08(bios, data + 19);
0344         info->vco2.min_n = nvbios_rd08(bios, data + 20);
0345         info->vco2.max_n = nvbios_rd08(bios, data + 21);
0346         info->vco2.min_m = nvbios_rd08(bios, data + 22);
0347         info->vco2.max_m = nvbios_rd08(bios, data + 23);
0348         info->max_p_usable = info->max_p = nvbios_rd08(bios, data + 25);
0349         info->bias_p = nvbios_rd08(bios, data + 27);
0350         info->refclk = nvbios_rd32(bios, data + 28);
0351         break;
0352     case 0x40:
0353         info->refclk = nvbios_rd16(bios, data + 9) * 1000;
0354         data = nvbios_rd16(bios, data + 1);
0355 
0356         info->vco1.min_freq = nvbios_rd16(bios, data + 0) * 1000;
0357         info->vco1.max_freq = nvbios_rd16(bios, data + 2) * 1000;
0358         info->vco1.min_inputfreq = nvbios_rd16(bios, data + 4) * 1000;
0359         info->vco1.max_inputfreq = nvbios_rd16(bios, data + 6) * 1000;
0360         info->vco1.min_m = nvbios_rd08(bios, data + 8);
0361         info->vco1.max_m = nvbios_rd08(bios, data + 9);
0362         info->vco1.min_n = nvbios_rd08(bios, data + 10);
0363         info->vco1.max_n = nvbios_rd08(bios, data + 11);
0364         info->min_p = nvbios_rd08(bios, data + 12);
0365         info->max_p = nvbios_rd08(bios, data + 13);
0366         break;
0367     case 0x50:
0368         info->refclk = nvbios_rd16(bios, data + 1) * 1000;
0369         /* info->refclk_alt = nvbios_rd16(bios, data + 3) * 1000; */
0370         info->vco1.min_freq = nvbios_rd16(bios, data + 5) * 1000;
0371         info->vco1.max_freq = nvbios_rd16(bios, data + 7) * 1000;
0372         info->vco1.min_inputfreq = nvbios_rd16(bios, data + 9) * 1000;
0373         info->vco1.max_inputfreq = nvbios_rd16(bios, data + 11) * 1000;
0374         info->vco1.min_m = nvbios_rd08(bios, data + 13);
0375         info->vco1.max_m = nvbios_rd08(bios, data + 14);
0376         info->vco1.min_n = nvbios_rd08(bios, data + 15);
0377         info->vco1.max_n = nvbios_rd08(bios, data + 16);
0378         info->min_p = nvbios_rd08(bios, data + 17);
0379         info->max_p = nvbios_rd08(bios, data + 18);
0380         break;
0381     default:
0382         nvkm_error(subdev, "unknown pll limits version 0x%02x\n", ver);
0383         return -EINVAL;
0384     }
0385 
0386     if (!info->refclk) {
0387         info->refclk = device->crystal;
0388         if (bios->version.chip == 0x51) {
0389             u32 sel_clk = nvkm_rd32(device, 0x680524);
0390             if ((info->reg == 0x680508 && sel_clk & 0x20) ||
0391                 (info->reg == 0x680520 && sel_clk & 0x80)) {
0392                 if (nvkm_rdvgac(device, 0, 0x27) < 0xa3)
0393                     info->refclk = 200000;
0394                 else
0395                     info->refclk = 25000;
0396             }
0397         }
0398     }
0399 
0400     /*
0401      * By now any valid limit table ought to have set a max frequency for
0402      * vco1, so if it's zero it's either a pre limit table bios, or one
0403      * with an empty limit table (seen on nv18)
0404      */
0405     if (!info->vco1.max_freq) {
0406         info->vco1.max_freq = nvbios_rd32(bios, bios->bmp_offset + 67);
0407         info->vco1.min_freq = nvbios_rd32(bios, bios->bmp_offset + 71);
0408         if (bmp_version(bios) < 0x0506) {
0409             info->vco1.max_freq = 256000;
0410             info->vco1.min_freq = 128000;
0411         }
0412 
0413         info->vco1.min_inputfreq = 0;
0414         info->vco1.max_inputfreq = INT_MAX;
0415         info->vco1.min_n = 0x1;
0416         info->vco1.max_n = 0xff;
0417         info->vco1.min_m = 0x1;
0418 
0419         if (device->crystal == 13500) {
0420             /* nv05 does this, nv11 doesn't, nv10 unknown */
0421             if (bios->version.chip < 0x11)
0422                 info->vco1.min_m = 0x7;
0423             info->vco1.max_m = 0xd;
0424         } else {
0425             if (bios->version.chip < 0x11)
0426                 info->vco1.min_m = 0x8;
0427             info->vco1.max_m = 0xe;
0428         }
0429 
0430         if (bios->version.chip <  0x17 ||
0431             bios->version.chip == 0x1a ||
0432             bios->version.chip == 0x20)
0433             info->max_p = 4;
0434         else
0435             info->max_p = 5;
0436         info->max_p_usable = info->max_p;
0437     }
0438 
0439     return 0;
0440 }