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/cstep.h>
0027
0028 u32
0029 nvbios_cstepTe(struct nvkm_bios *bios,
0030 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz)
0031 {
0032 struct bit_entry bit_P;
0033 u32 cstep = 0;
0034
0035 if (!bit_entry(bios, 'P', &bit_P)) {
0036 if (bit_P.version == 2 && bit_P.length >= 0x38)
0037 cstep = nvbios_rd32(bios, bit_P.offset + 0x34);
0038
0039 if (cstep) {
0040 *ver = nvbios_rd08(bios, cstep + 0);
0041 switch (*ver) {
0042 case 0x10:
0043 *hdr = nvbios_rd08(bios, cstep + 1);
0044 *cnt = nvbios_rd08(bios, cstep + 3);
0045 *len = nvbios_rd08(bios, cstep + 2);
0046 *xnr = nvbios_rd08(bios, cstep + 5);
0047 *xsz = nvbios_rd08(bios, cstep + 4);
0048 return cstep;
0049 default:
0050 break;
0051 }
0052 }
0053 }
0054
0055 return 0;
0056 }
0057
0058 u32
0059 nvbios_cstepEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
0060 {
0061 u8 cnt, len, xnr, xsz;
0062 u32 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
0063 if (data && idx < cnt) {
0064 data = data + *hdr + (idx * len);
0065 *hdr = len;
0066 return data;
0067 }
0068 return 0;
0069 }
0070
0071 u32
0072 nvbios_cstepEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
0073 struct nvbios_cstepE *info)
0074 {
0075 u32 data = nvbios_cstepEe(bios, idx, ver, hdr);
0076 memset(info, 0x00, sizeof(*info));
0077 if (data) {
0078 info->pstate = (nvbios_rd16(bios, data + 0x00) & 0x01e0) >> 5;
0079 info->index = nvbios_rd08(bios, data + 0x03);
0080 }
0081 return data;
0082 }
0083
0084 u32
0085 nvbios_cstepEm(struct nvkm_bios *bios, u8 pstate, u8 *ver, u8 *hdr,
0086 struct nvbios_cstepE *info)
0087 {
0088 u32 data, idx = 0;
0089 while ((data = nvbios_cstepEp(bios, idx++, ver, hdr, info))) {
0090 if (info->pstate == pstate)
0091 break;
0092 }
0093 return data;
0094 }
0095
0096 u32
0097 nvbios_cstepXe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
0098 {
0099 u8 cnt, len, xnr, xsz;
0100 u32 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
0101 if (data && idx < xnr) {
0102 data = data + *hdr + (cnt * len) + (idx * xsz);
0103 *hdr = xsz;
0104 return data;
0105 }
0106 return 0;
0107 }
0108
0109 u32
0110 nvbios_cstepXp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
0111 struct nvbios_cstepX *info)
0112 {
0113 u32 data = nvbios_cstepXe(bios, idx, ver, hdr);
0114 memset(info, 0x00, sizeof(*info));
0115 if (data) {
0116 info->freq = nvbios_rd16(bios, data + 0x00) * 1000;
0117 info->unkn[0] = nvbios_rd08(bios, data + 0x02);
0118 info->unkn[1] = nvbios_rd08(bios, data + 0x03);
0119 info->voltage = nvbios_rd08(bios, data + 0x04);
0120 }
0121 return data;
0122 }