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

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

DEFINITIONS

This source file includes following definitions.
  1. nvbios_volt_table
  2. nvbios_volt_parse
  3. nvbios_volt_entry
  4. nvbios_volt_entry_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/volt.h>
  27 
  28 u32
  29 nvbios_volt_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
  30 {
  31         struct bit_entry bit_P;
  32         u32 volt = 0;
  33 
  34         if (!bit_entry(bios, 'P', &bit_P)) {
  35                 if (bit_P.version == 2)
  36                         volt = nvbios_rd32(bios, bit_P.offset + 0x0c);
  37                 else
  38                 if (bit_P.version == 1)
  39                         volt = nvbios_rd32(bios, bit_P.offset + 0x10);
  40 
  41                 if (volt) {
  42                         *ver = nvbios_rd08(bios, volt + 0);
  43                         switch (*ver) {
  44                         case 0x12:
  45                                 *hdr = 5;
  46                                 *cnt = nvbios_rd08(bios, volt + 2);
  47                                 *len = nvbios_rd08(bios, volt + 1);
  48                                 return volt;
  49                         case 0x20:
  50                                 *hdr = nvbios_rd08(bios, volt + 1);
  51                                 *cnt = nvbios_rd08(bios, volt + 2);
  52                                 *len = nvbios_rd08(bios, volt + 3);
  53                                 return volt;
  54                         case 0x30:
  55                         case 0x40:
  56                         case 0x50:
  57                                 *hdr = nvbios_rd08(bios, volt + 1);
  58                                 *cnt = nvbios_rd08(bios, volt + 3);
  59                                 *len = nvbios_rd08(bios, volt + 2);
  60                                 return volt;
  61                         }
  62                 }
  63         }
  64 
  65         return 0;
  66 }
  67 
  68 u32
  69 nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
  70                   struct nvbios_volt *info)
  71 {
  72         u32 volt = nvbios_volt_table(bios, ver, hdr, cnt, len);
  73         memset(info, 0x00, sizeof(*info));
  74         switch (!!volt * *ver) {
  75         case 0x12:
  76                 info->type    = NVBIOS_VOLT_GPIO;
  77                 info->vidmask = nvbios_rd08(bios, volt + 0x04);
  78                 info->ranged  = false;
  79                 break;
  80         case 0x20:
  81                 info->type    = NVBIOS_VOLT_GPIO;
  82                 info->vidmask = nvbios_rd08(bios, volt + 0x05);
  83                 info->ranged  = false;
  84                 break;
  85         case 0x30:
  86                 info->type    = NVBIOS_VOLT_GPIO;
  87                 info->vidmask = nvbios_rd08(bios, volt + 0x04);
  88                 info->ranged  = false;
  89                 break;
  90         case 0x40:
  91                 info->type    = NVBIOS_VOLT_GPIO;
  92                 info->base    = nvbios_rd32(bios, volt + 0x04);
  93                 info->step    = nvbios_rd16(bios, volt + 0x08);
  94                 info->vidmask = nvbios_rd08(bios, volt + 0x0b);
  95                 info->ranged  = true; /* XXX: find the flag byte */
  96                 info->min     = min(info->base,
  97                                     info->base + info->step * info->vidmask);
  98                 info->max     = nvbios_rd32(bios, volt + 0x0e);
  99                 if (!info->max)
 100                         info->max = max(info->base, info->base + info->step * info->vidmask);
 101                 break;
 102         case 0x50:
 103                 info->min     = nvbios_rd32(bios, volt + 0x0a);
 104                 info->max     = nvbios_rd32(bios, volt + 0x0e);
 105                 info->base    = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
 106 
 107                 /* offset 4 seems to be a flag byte */
 108                 if (nvbios_rd32(bios, volt + 0x4) & 1) {
 109                         info->type      = NVBIOS_VOLT_PWM;
 110                         info->pwm_freq  = nvbios_rd32(bios, volt + 0x5) / 1000;
 111                         info->pwm_range = nvbios_rd32(bios, volt + 0x16);
 112                 } else {
 113                         info->type    = NVBIOS_VOLT_GPIO;
 114                         info->vidmask = nvbios_rd08(bios, volt + 0x06);
 115                         info->step    = nvbios_rd16(bios, volt + 0x16);
 116                         info->ranged  =
 117                                 !!(nvbios_rd08(bios, volt + 0x4) & 0x2);
 118                 }
 119                 break;
 120         }
 121         return volt;
 122 }
 123 
 124 u32
 125 nvbios_volt_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
 126 {
 127         u8  hdr, cnt;
 128         u32 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len);
 129         if (volt && idx < cnt) {
 130                 volt = volt + hdr + (idx * *len);
 131                 return volt;
 132         }
 133         return 0;
 134 }
 135 
 136 u32
 137 nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
 138                         struct nvbios_volt_entry *info)
 139 {
 140         u32 volt = nvbios_volt_entry(bios, idx, ver, len);
 141         memset(info, 0x00, sizeof(*info));
 142         switch (!!volt * *ver) {
 143         case 0x12:
 144         case 0x20:
 145                 info->voltage = nvbios_rd08(bios, volt + 0x00) * 10000;
 146                 info->vid     = nvbios_rd08(bios, volt + 0x01);
 147                 break;
 148         case 0x30:
 149                 info->voltage = nvbios_rd08(bios, volt + 0x00) * 10000;
 150                 info->vid     = nvbios_rd08(bios, volt + 0x01) >> 2;
 151                 break;
 152         case 0x40:
 153                 break;
 154         case 0x50:
 155                 info->voltage = nvbios_rd32(bios, volt) & 0x001fffff;
 156                 info->vid     = (nvbios_rd32(bios, volt) >> 23) & 0xff;
 157                 break;
 158         }
 159         return volt;
 160 }

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