0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <subdev/bios.h>
0025 #include <subdev/bios/bit.h>
0026 #include <subdev/bios/volt.h>
0027
0028 u32
0029 nvbios_volt_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
0030 {
0031 struct bit_entry bit_P;
0032 u32 volt = 0;
0033
0034 if (!bit_entry(bios, 'P', &bit_P)) {
0035 if (bit_P.version == 2)
0036 volt = nvbios_rd32(bios, bit_P.offset + 0x0c);
0037 else
0038 if (bit_P.version == 1)
0039 volt = nvbios_rd32(bios, bit_P.offset + 0x10);
0040
0041 if (volt) {
0042 *ver = nvbios_rd08(bios, volt + 0);
0043 switch (*ver) {
0044 case 0x12:
0045 *hdr = 5;
0046 *cnt = nvbios_rd08(bios, volt + 2);
0047 *len = nvbios_rd08(bios, volt + 1);
0048 return volt;
0049 case 0x20:
0050 *hdr = nvbios_rd08(bios, volt + 1);
0051 *cnt = nvbios_rd08(bios, volt + 2);
0052 *len = nvbios_rd08(bios, volt + 3);
0053 return volt;
0054 case 0x30:
0055 case 0x40:
0056 case 0x50:
0057 *hdr = nvbios_rd08(bios, volt + 1);
0058 *cnt = nvbios_rd08(bios, volt + 3);
0059 *len = nvbios_rd08(bios, volt + 2);
0060 return volt;
0061 }
0062 }
0063 }
0064
0065 return 0;
0066 }
0067
0068 u32
0069 nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
0070 struct nvbios_volt *info)
0071 {
0072 u32 volt = nvbios_volt_table(bios, ver, hdr, cnt, len);
0073 memset(info, 0x00, sizeof(*info));
0074 switch (!!volt * *ver) {
0075 case 0x12:
0076 info->type = NVBIOS_VOLT_GPIO;
0077 info->vidmask = nvbios_rd08(bios, volt + 0x04);
0078 info->ranged = false;
0079 break;
0080 case 0x20:
0081 info->type = NVBIOS_VOLT_GPIO;
0082 info->vidmask = nvbios_rd08(bios, volt + 0x05);
0083 info->ranged = false;
0084 break;
0085 case 0x30:
0086 info->type = NVBIOS_VOLT_GPIO;
0087 info->vidmask = nvbios_rd08(bios, volt + 0x04);
0088 info->ranged = false;
0089 break;
0090 case 0x40:
0091 info->type = NVBIOS_VOLT_GPIO;
0092 info->base = nvbios_rd32(bios, volt + 0x04);
0093 info->step = nvbios_rd16(bios, volt + 0x08);
0094 info->vidmask = nvbios_rd08(bios, volt + 0x0b);
0095 info->ranged = true;
0096 info->min = min(info->base,
0097 info->base + info->step * info->vidmask);
0098 info->max = nvbios_rd32(bios, volt + 0x0e);
0099 if (!info->max)
0100 info->max = max(info->base, info->base + info->step * info->vidmask);
0101 break;
0102 case 0x50:
0103 info->min = nvbios_rd32(bios, volt + 0x0a);
0104 info->max = nvbios_rd32(bios, volt + 0x0e);
0105 info->base = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
0106
0107
0108 if (nvbios_rd32(bios, volt + 0x4) & 1) {
0109 info->type = NVBIOS_VOLT_PWM;
0110 info->pwm_freq = nvbios_rd32(bios, volt + 0x5) / 1000;
0111 info->pwm_range = nvbios_rd32(bios, volt + 0x16);
0112 } else {
0113 info->type = NVBIOS_VOLT_GPIO;
0114 info->vidmask = nvbios_rd08(bios, volt + 0x06);
0115 info->step = nvbios_rd16(bios, volt + 0x16);
0116 info->ranged =
0117 !!(nvbios_rd08(bios, volt + 0x4) & 0x2);
0118 }
0119 break;
0120 }
0121 return volt;
0122 }
0123
0124 u32
0125 nvbios_volt_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
0126 {
0127 u8 hdr, cnt;
0128 u32 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len);
0129 if (volt && idx < cnt) {
0130 volt = volt + hdr + (idx * *len);
0131 return volt;
0132 }
0133 return 0;
0134 }
0135
0136 u32
0137 nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
0138 struct nvbios_volt_entry *info)
0139 {
0140 u32 volt = nvbios_volt_entry(bios, idx, ver, len);
0141 memset(info, 0x00, sizeof(*info));
0142 switch (!!volt * *ver) {
0143 case 0x12:
0144 case 0x20:
0145 info->voltage = nvbios_rd08(bios, volt + 0x00) * 10000;
0146 info->vid = nvbios_rd08(bios, volt + 0x01);
0147 break;
0148 case 0x30:
0149 info->voltage = nvbios_rd08(bios, volt + 0x00) * 10000;
0150 info->vid = nvbios_rd08(bios, volt + 0x01) >> 2;
0151 break;
0152 case 0x40:
0153 break;
0154 case 0x50:
0155 info->voltage = nvbios_rd32(bios, volt) & 0x001fffff;
0156 info->vid = (nvbios_rd32(bios, volt) >> 23) & 0xff;
0157 break;
0158 }
0159 return volt;
0160 }