root/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nvbios_perf_table
  2. nvbios_perf_entry
  3. nvbios_perfEp
  4. nvbios_perfSe
  5. nvbios_perfSp
  6. nvbios_perf_fan_parse

   1 /*
   2  * Copyright 2012 Nouveau Community
   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: Martin Peres
  23  */
  24 #include <subdev/bios.h>
  25 #include <subdev/bios/bit.h>
  26 #include <subdev/bios/perf.h>
  27 #include <subdev/pci.h>
  28 
  29 u32
  30 nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr,
  31                   u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
  32 {
  33         struct bit_entry bit_P;
  34         u32 perf = 0;
  35 
  36         if (!bit_entry(bios, 'P', &bit_P)) {
  37                 if (bit_P.version <= 2) {
  38                         perf = nvbios_rd32(bios, bit_P.offset + 0);
  39                         if (perf) {
  40                                 *ver = nvbios_rd08(bios, perf + 0);
  41                                 *hdr = nvbios_rd08(bios, perf + 1);
  42                                 if (*ver >= 0x40 && *ver < 0x41) {
  43                                         *cnt = nvbios_rd08(bios, perf + 5);
  44                                         *len = nvbios_rd08(bios, perf + 2);
  45                                         *snr = nvbios_rd08(bios, perf + 4);
  46                                         *ssz = nvbios_rd08(bios, perf + 3);
  47                                         return perf;
  48                                 } else
  49                                 if (*ver >= 0x20 && *ver < 0x40) {
  50                                         *cnt = nvbios_rd08(bios, perf + 2);
  51                                         *len = nvbios_rd08(bios, perf + 3);
  52                                         *snr = nvbios_rd08(bios, perf + 4);
  53                                         *ssz = nvbios_rd08(bios, perf + 5);
  54                                         return perf;
  55                                 }
  56                         }
  57                 }
  58         }
  59 
  60         if (bios->bmp_offset) {
  61                 if (nvbios_rd08(bios, bios->bmp_offset + 6) >= 0x25) {
  62                         perf = nvbios_rd16(bios, bios->bmp_offset + 0x94);
  63                         if (perf) {
  64                                 *hdr = nvbios_rd08(bios, perf + 0);
  65                                 *ver = nvbios_rd08(bios, perf + 1);
  66                                 *cnt = nvbios_rd08(bios, perf + 2);
  67                                 *len = nvbios_rd08(bios, perf + 3);
  68                                 *snr = 0;
  69                                 *ssz = 0;
  70                                 return perf;
  71                         }
  72                 }
  73         }
  74 
  75         return 0;
  76 }
  77 
  78 u32
  79 nvbios_perf_entry(struct nvkm_bios *bios, int idx,
  80                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
  81 {
  82         u8  snr, ssz;
  83         u32 perf = nvbios_perf_table(bios, ver, hdr, cnt, len, &snr, &ssz);
  84         if (perf && idx < *cnt) {
  85                 perf = perf + *hdr + (idx * (*len + (snr * ssz)));
  86                 *hdr = *len;
  87                 *cnt = snr;
  88                 *len = ssz;
  89                 return perf;
  90         }
  91         return 0;
  92 }
  93 
  94 u32
  95 nvbios_perfEp(struct nvkm_bios *bios, int idx,
  96               u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *info)
  97 {
  98         u32 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len);
  99         memset(info, 0x00, sizeof(*info));
 100         info->pstate = nvbios_rd08(bios, perf + 0x00);
 101         switch (!!perf * *ver) {
 102         case 0x12:
 103         case 0x13:
 104         case 0x14:
 105                 info->core     = nvbios_rd32(bios, perf + 0x01) * 10;
 106                 info->memory   = nvbios_rd32(bios, perf + 0x05) * 20;
 107                 info->fanspeed = nvbios_rd08(bios, perf + 0x37);
 108                 if (*hdr > 0x38)
 109                         info->voltage = nvbios_rd08(bios, perf + 0x38);
 110                 break;
 111         case 0x21:
 112         case 0x23:
 113         case 0x24:
 114                 info->fanspeed = nvbios_rd08(bios, perf + 0x04);
 115                 info->voltage  = nvbios_rd08(bios, perf + 0x05);
 116                 info->shader   = nvbios_rd16(bios, perf + 0x06) * 1000;
 117                 info->core     = info->shader + (signed char)
 118                                  nvbios_rd08(bios, perf + 0x08) * 1000;
 119                 switch (bios->subdev.device->chipset) {
 120                 case 0x49:
 121                 case 0x4b:
 122                         info->memory = nvbios_rd16(bios, perf + 0x0b) * 1000;
 123                         break;
 124                 default:
 125                         info->memory = nvbios_rd16(bios, perf + 0x0b) * 2000;
 126                         break;
 127                 }
 128                 break;
 129         case 0x25:
 130                 info->fanspeed = nvbios_rd08(bios, perf + 0x04);
 131                 info->voltage  = nvbios_rd08(bios, perf + 0x05);
 132                 info->core     = nvbios_rd16(bios, perf + 0x06) * 1000;
 133                 info->shader   = nvbios_rd16(bios, perf + 0x0a) * 1000;
 134                 info->memory   = nvbios_rd16(bios, perf + 0x0c) * 1000;
 135                 break;
 136         case 0x30:
 137                 info->script   = nvbios_rd16(bios, perf + 0x02);
 138                 /* fall through */
 139         case 0x35:
 140                 info->fanspeed = nvbios_rd08(bios, perf + 0x06);
 141                 info->voltage  = nvbios_rd08(bios, perf + 0x07);
 142                 info->core     = nvbios_rd16(bios, perf + 0x08) * 1000;
 143                 info->shader   = nvbios_rd16(bios, perf + 0x0a) * 1000;
 144                 info->memory   = nvbios_rd16(bios, perf + 0x0c) * 1000;
 145                 info->vdec     = nvbios_rd16(bios, perf + 0x10) * 1000;
 146                 info->disp     = nvbios_rd16(bios, perf + 0x14) * 1000;
 147                 break;
 148         case 0x40:
 149                 info->voltage  = nvbios_rd08(bios, perf + 0x02);
 150                 switch (nvbios_rd08(bios, perf + 0xb) & 0x3) {
 151                 case 0:
 152                         info->pcie_speed = NVKM_PCIE_SPEED_5_0;
 153                         break;
 154                 case 3:
 155                 case 1:
 156                         info->pcie_speed = NVKM_PCIE_SPEED_2_5;
 157                         break;
 158                 case 2:
 159                         info->pcie_speed = NVKM_PCIE_SPEED_8_0;
 160                         break;
 161                 default:
 162                         break;
 163                 }
 164                 info->pcie_width = 0xff;
 165                 break;
 166         default:
 167                 return 0;
 168         }
 169         return perf;
 170 }
 171 
 172 u32
 173 nvbios_perfSe(struct nvkm_bios *bios, u32 perfE, int idx,
 174               u8 *ver, u8 *hdr, u8 cnt, u8 len)
 175 {
 176         u32 data = 0x00000000;
 177         if (idx < cnt) {
 178                 data = perfE + *hdr + (idx * len);
 179                 *hdr = len;
 180         }
 181         return data;
 182 }
 183 
 184 u32
 185 nvbios_perfSp(struct nvkm_bios *bios, u32 perfE, int idx,
 186               u8 *ver, u8 *hdr, u8 cnt, u8 len,
 187               struct nvbios_perfS *info)
 188 {
 189         u32 data = nvbios_perfSe(bios, perfE, idx, ver, hdr, cnt, len);
 190         memset(info, 0x00, sizeof(*info));
 191         switch (!!data * *ver) {
 192         case 0x40:
 193                 info->v40.freq = (nvbios_rd16(bios, data + 0x00) & 0x3fff) * 1000;
 194                 break;
 195         default:
 196                 break;
 197         }
 198         return data;
 199 }
 200 
 201 int
 202 nvbios_perf_fan_parse(struct nvkm_bios *bios,
 203                       struct nvbios_perf_fan *fan)
 204 {
 205         u8  ver, hdr, cnt, len, snr, ssz;
 206         u32 perf = nvbios_perf_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
 207         if (!perf)
 208                 return -ENODEV;
 209 
 210         if (ver >= 0x20 && ver < 0x40 && hdr > 6)
 211                 fan->pwm_divisor = nvbios_rd16(bios, perf + 6);
 212         else
 213                 fan->pwm_divisor = 0;
 214 
 215         return 0;
 216 }

/* [<][>][^][v][top][bottom][index][help] */