aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-01-14 17:33:25 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-11-08 00:40:16 -0500
commit0833428e7d1b250afbd41e0a4c8c247cccd15aad (patch)
tree57517e19a618cde12d3b9007aad09752da25713f
parentaa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6 (diff)
drm/nouveau/bios: parsing for various tables required for power management
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/Makefile6
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/boost.h29
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/cstep.h28
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h10
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h33
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h11
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/vmap.h25
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/volt.h27
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/boost.c127
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/cstep.c123
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/perf.c140
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c88
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/timing.c73
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c112
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/volt.c137
16 files changed, 969 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 7805ebc7255a..7d6173f1aa99 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -28,7 +28,9 @@ nouveau-y += core/subdev/bar/nv50.o
28nouveau-y += core/subdev/bar/nvc0.o 28nouveau-y += core/subdev/bar/nvc0.o
29nouveau-y += core/subdev/bios/base.o 29nouveau-y += core/subdev/bios/base.o
30nouveau-y += core/subdev/bios/bit.o 30nouveau-y += core/subdev/bios/bit.o
31nouveau-y += core/subdev/bios/boost.o
31nouveau-y += core/subdev/bios/conn.o 32nouveau-y += core/subdev/bios/conn.o
33nouveau-y += core/subdev/bios/cstep.o
32nouveau-y += core/subdev/bios/dcb.o 34nouveau-y += core/subdev/bios/dcb.o
33nouveau-y += core/subdev/bios/disp.o 35nouveau-y += core/subdev/bios/disp.o
34nouveau-y += core/subdev/bios/dp.o 36nouveau-y += core/subdev/bios/dp.o
@@ -39,7 +41,11 @@ nouveau-y += core/subdev/bios/init.o
39nouveau-y += core/subdev/bios/mxm.o 41nouveau-y += core/subdev/bios/mxm.o
40nouveau-y += core/subdev/bios/perf.o 42nouveau-y += core/subdev/bios/perf.o
41nouveau-y += core/subdev/bios/pll.o 43nouveau-y += core/subdev/bios/pll.o
44nouveau-y += core/subdev/bios/rammap.o
45nouveau-y += core/subdev/bios/timing.o
42nouveau-y += core/subdev/bios/therm.o 46nouveau-y += core/subdev/bios/therm.o
47nouveau-y += core/subdev/bios/vmap.o
48nouveau-y += core/subdev/bios/volt.o
43nouveau-y += core/subdev/bios/xpio.o 49nouveau-y += core/subdev/bios/xpio.o
44nouveau-y += core/subdev/bus/nv04.o 50nouveau-y += core/subdev/bus/nv04.o
45nouveau-y += core/subdev/bus/nv31.o 51nouveau-y += core/subdev/bus/nv31.o
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/boost.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/boost.h
new file mode 100644
index 000000000000..662b20726851
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/boost.h
@@ -0,0 +1,29 @@
1#ifndef __NVBIOS_BOOST_H__
2#define __NVBIOS_BOOST_H__
3
4u16 nvbios_boostTe(struct nouveau_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *);
5
6struct nvbios_boostE {
7 u8 pstate;
8 u32 min;
9 u32 max;
10};
11
12u16 nvbios_boostEe(struct nouveau_bios *, int idx, u8 *, u8 *, u8 *, u8 *);
13u16 nvbios_boostEp(struct nouveau_bios *, int idx, u8 *, u8 *, u8 *, u8 *,
14 struct nvbios_boostE *);
15u16 nvbios_boostEm(struct nouveau_bios *, u8, u8 *, u8 *, u8 *, u8 *,
16 struct nvbios_boostE *);
17
18struct nvbios_boostS {
19 u8 domain;
20 u8 percent;
21 u32 min;
22 u32 max;
23};
24
25u16 nvbios_boostSe(struct nouveau_bios *, int, u16, u8 *, u8 *, u8, u8);
26u16 nvbios_boostSp(struct nouveau_bios *, int, u16, u8 *, u8 *, u8, u8,
27 struct nvbios_boostS *);
28
29#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/cstep.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/cstep.h
new file mode 100644
index 000000000000..a80a43809883
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/cstep.h
@@ -0,0 +1,28 @@
1#ifndef __NVBIOS_CSTEP_H__
2#define __NVBIOS_CSTEP_H__
3
4u16 nvbios_cstepTe(struct nouveau_bios *,
5 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz);
6
7struct nvbios_cstepE {
8 u8 pstate;
9 u8 index;
10};
11
12u16 nvbios_cstepEe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
13u16 nvbios_cstepEp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr,
14 struct nvbios_cstepE *);
15u16 nvbios_cstepEm(struct nouveau_bios *, u8 pstate, u8 *ver, u8 *hdr,
16 struct nvbios_cstepE *);
17
18struct nvbios_cstepX {
19 u32 freq;
20 u8 unkn[2];
21 u8 voltage;
22};
23
24u16 nvbios_cstepXe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
25u16 nvbios_cstepXp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr,
26 struct nvbios_cstepX *);
27
28#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
index 96d3364f6db3..c7b2e586be0b 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
@@ -7,7 +7,15 @@ enum dcb_gpio_func_name {
7 DCB_GPIO_TVDAC1 = 0x2d, 7 DCB_GPIO_TVDAC1 = 0x2d,
8 DCB_GPIO_FAN = 0x09, 8 DCB_GPIO_FAN = 0x09,
9 DCB_GPIO_FAN_SENSE = 0x3d, 9 DCB_GPIO_FAN_SENSE = 0x3d,
10 DCB_GPIO_UNUSED = 0xff 10 DCB_GPIO_UNUSED = 0xff,
11 DCB_GPIO_VID0 = 0x04,
12 DCB_GPIO_VID1 = 0x05,
13 DCB_GPIO_VID2 = 0x06,
14 DCB_GPIO_VID3 = 0x1a,
15 DCB_GPIO_VID4 = 0x73,
16 DCB_GPIO_VID5 = 0x74,
17 DCB_GPIO_VID6 = 0x75,
18 DCB_GPIO_VID7 = 0x76,
11}; 19};
12 20
13#define DCB_GPIO_LOG_DIR 0x02 21#define DCB_GPIO_LOG_DIR 0x02
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h
index 0b285e99be5a..16ff06ec2a88 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h
@@ -3,6 +3,39 @@
3 3
4struct nouveau_bios; 4struct nouveau_bios;
5 5
6u16 nvbios_perf_table(struct nouveau_bios *, u8 *ver, u8 *hdr,
7 u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
8
9struct nvbios_perfE {
10 u8 pstate;
11 u8 fanspeed;
12 u8 voltage;
13 u32 core;
14 u32 shader;
15 u32 memory;
16 u32 vdec;
17 u32 disp;
18 u32 script;
19};
20
21u16 nvbios_perf_entry(struct nouveau_bios *, int idx,
22 u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
23u16 nvbios_perfEp(struct nouveau_bios *, int idx,
24 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *);
25
26struct nvbios_perfS {
27 union {
28 struct {
29 u32 freq;
30 } v40;
31 };
32};
33
34u32 nvbios_perfSe(struct nouveau_bios *, u32 data, int idx,
35 u8 *ver, u8 *hdr, u8 cnt, u8 len);
36u32 nvbios_perfSp(struct nouveau_bios *, u32 data, int idx,
37 u8 *ver, u8 *hdr, u8 cnt, u8 len, struct nvbios_perfS *);
38
6struct nvbios_perf_fan { 39struct nvbios_perf_fan {
7 u32 pwm_divisor; 40 u32 pwm_divisor;
8}; 41};
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h
new file mode 100644
index 000000000000..bc15e0320877
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h
@@ -0,0 +1,11 @@
1#ifndef __NVBIOS_RAMMAP_H__
2#define __NVBIOS_RAMMAP_H__
3
4u16 nvbios_rammap_table(struct nouveau_bios *, u8 *ver, u8 *hdr,
5 u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
6u16 nvbios_rammap_entry(struct nouveau_bios *, int idx,
7 u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
8u16 nvbios_rammap_match(struct nouveau_bios *, u16 khz,
9 u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
10
11#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h
new file mode 100644
index 000000000000..963694b54224
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h
@@ -0,0 +1,8 @@
1#ifndef __NVBIOS_TIMING_H__
2#define __NVBIOS_TIMING_H__
3
4u16 nvbios_timing_table(struct nouveau_bios *,
5 u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
6u16 nvbios_timing_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
7
8#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/vmap.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/vmap.h
new file mode 100644
index 000000000000..ad5a8f20e113
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/vmap.h
@@ -0,0 +1,25 @@
1#ifndef __NVBIOS_VMAP_H__
2#define __NVBIOS_VMAP_H__
3
4struct nouveau_bios;
5
6struct nvbios_vmap {
7};
8
9u16 nvbios_vmap_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
10u16 nvbios_vmap_parse(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
11 struct nvbios_vmap *);
12
13struct nvbios_vmap_entry {
14 u8 unk0;
15 u8 link;
16 u32 min;
17 u32 max;
18 s32 arg[6];
19};
20
21u16 nvbios_vmap_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *len);
22u16 nvbios_vmap_entry_parse(struct nouveau_bios *, int idx, u8 *ver, u8 *len,
23 struct nvbios_vmap_entry *);
24
25#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/volt.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/volt.h
new file mode 100644
index 000000000000..6a11dcd59770
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/volt.h
@@ -0,0 +1,27 @@
1#ifndef __NVBIOS_VOLT_H__
2#define __NVBIOS_VOLT_H__
3
4struct nouveau_bios;
5
6struct nvbios_volt {
7 u8 vidmask;
8 u32 min;
9 u32 max;
10 u32 base;
11 s16 step;
12};
13
14u16 nvbios_volt_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
15u16 nvbios_volt_parse(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
16 struct nvbios_volt *);
17
18struct nvbios_volt_entry {
19 u32 voltage;
20 u8 vid;
21};
22
23u16 nvbios_volt_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *len);
24u16 nvbios_volt_entry_parse(struct nouveau_bios *, int idx, u8 *ver, u8 *len,
25 struct nvbios_volt_entry *);
26
27#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/boost.c b/drivers/gpu/drm/nouveau/core/subdev/bios/boost.c
new file mode 100644
index 000000000000..c1835e591c44
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/boost.c
@@ -0,0 +1,127 @@
1/*
2 * Copyright 2013 Red Hat Inc.
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: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/bit.h>
27#include <subdev/bios/boost.h>
28
29u16
30nvbios_boostTe(struct nouveau_bios *bios,
31 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
32{
33 struct bit_entry bit_P;
34 u16 boost = 0x0000;
35
36 if (!bit_entry(bios, 'P', &bit_P)) {
37 if (bit_P.version == 2)
38 boost = nv_ro16(bios, bit_P.offset + 0x30);
39
40 if (boost) {
41 *ver = nv_ro08(bios, boost + 0);
42 switch (*ver) {
43 case 0x11:
44 *hdr = nv_ro08(bios, boost + 1);
45 *cnt = nv_ro08(bios, boost + 5);
46 *len = nv_ro08(bios, boost + 2);
47 *snr = nv_ro08(bios, boost + 4);
48 *ssz = nv_ro08(bios, boost + 3);
49 return boost;
50 default:
51 break;
52 }
53 }
54 }
55
56 return 0x0000;
57}
58
59u16
60nvbios_boostEe(struct nouveau_bios *bios, int idx,
61 u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
62{
63 u8 snr, ssz;
64 u16 data = nvbios_boostTe(bios, ver, hdr, cnt, len, &snr, &ssz);
65 if (data && idx < *cnt) {
66 data = data + *hdr + (idx * (*len + (snr * ssz)));
67 *hdr = *len;
68 *cnt = snr;
69 *len = ssz;
70 return data;
71 }
72 return 0x0000;
73}
74
75u16
76nvbios_boostEp(struct nouveau_bios *bios, int idx,
77 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info)
78{
79 u16 data = nvbios_boostEe(bios, idx, ver, hdr, cnt, len);
80 memset(info, 0x00, sizeof(*info));
81 if (data) {
82 info->pstate = (nv_ro16(bios, data + 0x00) & 0x01e0) >> 5;
83 info->min = nv_ro16(bios, data + 0x02) * 1000;
84 info->max = nv_ro16(bios, data + 0x04) * 1000;
85 }
86 return data;
87}
88
89u16
90nvbios_boostEm(struct nouveau_bios *bios, u8 pstate,
91 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info)
92{
93 u32 data, idx = 0;
94 while ((data = nvbios_boostEp(bios, idx++, ver, hdr, cnt, len, info))) {
95 if (info->pstate == pstate)
96 break;
97 }
98 return data;
99}
100
101u16
102nvbios_boostSe(struct nouveau_bios *bios, int idx,
103 u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len)
104{
105 if (data && idx < cnt) {
106 data = data + *hdr + (idx * len);
107 *hdr = len;
108 return data;
109 }
110 return 0x0000;
111}
112
113u16
114nvbios_boostSp(struct nouveau_bios *bios, int idx,
115 u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len,
116 struct nvbios_boostS *info)
117{
118 data = nvbios_boostSe(bios, idx, data, ver, hdr, cnt, len);
119 memset(info, 0x00, sizeof(*info));
120 if (data) {
121 info->domain = nv_ro08(bios, data + 0x00);
122 info->percent = nv_ro08(bios, data + 0x01);
123 info->min = nv_ro16(bios, data + 0x02) * 1000;
124 info->max = nv_ro16(bios, data + 0x04) * 1000;
125 }
126 return data;
127}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/cstep.c b/drivers/gpu/drm/nouveau/core/subdev/bios/cstep.c
new file mode 100644
index 000000000000..d3b15327fbfd
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/cstep.c
@@ -0,0 +1,123 @@
1/*
2 * Copyright 2013 Red Hat Inc.
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: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/bit.h>
27#include <subdev/bios/cstep.h>
28
29u16
30nvbios_cstepTe(struct nouveau_bios *bios,
31 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz)
32{
33 struct bit_entry bit_P;
34 u16 cstep = 0x0000;
35
36 if (!bit_entry(bios, 'P', &bit_P)) {
37 if (bit_P.version == 2)
38 cstep = nv_ro16(bios, bit_P.offset + 0x34);
39
40 if (cstep) {
41 *ver = nv_ro08(bios, cstep + 0);
42 switch (*ver) {
43 case 0x10:
44 *hdr = nv_ro08(bios, cstep + 1);
45 *cnt = nv_ro08(bios, cstep + 3);
46 *len = nv_ro08(bios, cstep + 2);
47 *xnr = nv_ro08(bios, cstep + 5);
48 *xsz = nv_ro08(bios, cstep + 4);
49 return cstep;
50 default:
51 break;
52 }
53 }
54 }
55
56 return 0x0000;
57}
58
59u16
60nvbios_cstepEe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr)
61{
62 u8 cnt, len, xnr, xsz;
63 u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
64 if (data && idx < cnt) {
65 data = data + *hdr + (idx * len);
66 *hdr = len;
67 return data;
68 }
69 return 0x0000;
70}
71
72u16
73nvbios_cstepEp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr,
74 struct nvbios_cstepE *info)
75{
76 u16 data = nvbios_cstepEe(bios, idx, ver, hdr);
77 memset(info, 0x00, sizeof(*info));
78 if (data) {
79 info->pstate = (nv_ro16(bios, data + 0x00) & 0x01e0) >> 5;
80 info->index = nv_ro08(bios, data + 0x03);
81 }
82 return data;
83}
84
85u16
86nvbios_cstepEm(struct nouveau_bios *bios, u8 pstate, u8 *ver, u8 *hdr,
87 struct nvbios_cstepE *info)
88{
89 u32 data, idx = 0;
90 while ((data = nvbios_cstepEp(bios, idx++, ver, hdr, info))) {
91 if (info->pstate == pstate)
92 break;
93 }
94 return data;
95}
96
97u16
98nvbios_cstepXe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr)
99{
100 u8 cnt, len, xnr, xsz;
101 u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
102 if (data && idx < xnr) {
103 data = data + *hdr + (cnt * len) + (idx * xsz);
104 *hdr = xsz;
105 return data;
106 }
107 return 0x0000;
108}
109
110u16
111nvbios_cstepXp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr,
112 struct nvbios_cstepX *info)
113{
114 u16 data = nvbios_cstepXe(bios, idx, ver, hdr);
115 memset(info, 0x00, sizeof(*info));
116 if (data) {
117 info->freq = nv_ro16(bios, data + 0x00) * 1000;
118 info->unkn[0] = nv_ro08(bios, data + 0x02);
119 info->unkn[1] = nv_ro08(bios, data + 0x03);
120 info->voltage = nv_ro08(bios, data + 0x04);
121 }
122 return data;
123}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c b/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c
index bcbb056c2887..675e221680aa 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c
@@ -26,8 +26,9 @@
26#include <subdev/bios/bit.h> 26#include <subdev/bios/bit.h>
27#include <subdev/bios/perf.h> 27#include <subdev/bios/perf.h>
28 28
29static u16 29u16
30perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) 30nvbios_perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
31 u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
31{ 32{
32 struct bit_entry bit_P; 33 struct bit_entry bit_P;
33 u16 perf = 0x0000; 34 u16 perf = 0x0000;
@@ -38,10 +39,22 @@ perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
38 if (perf) { 39 if (perf) {
39 *ver = nv_ro08(bios, perf + 0); 40 *ver = nv_ro08(bios, perf + 0);
40 *hdr = nv_ro08(bios, perf + 1); 41 *hdr = nv_ro08(bios, perf + 1);
42 if (*ver >= 0x40 && *ver < 0x41) {
43 *cnt = nv_ro08(bios, perf + 5);
44 *len = nv_ro08(bios, perf + 2);
45 *snr = nv_ro08(bios, perf + 4);
46 *ssz = nv_ro08(bios, perf + 3);
47 return perf;
48 } else
49 if (*ver >= 0x20 && *ver < 0x40) {
50 *cnt = nv_ro08(bios, perf + 2);
51 *len = nv_ro08(bios, perf + 3);
52 *snr = nv_ro08(bios, perf + 4);
53 *ssz = nv_ro08(bios, perf + 5);
54 return perf;
55 }
41 } 56 }
42 } else 57 }
43 nv_error(bios, "unknown offset for perf in BIT P %d\n",
44 bit_P.version);
45 } 58 }
46 59
47 if (bios->bmp_offset) { 60 if (bios->bmp_offset) {
@@ -50,19 +63,132 @@ perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
50 if (perf) { 63 if (perf) {
51 *hdr = nv_ro08(bios, perf + 0); 64 *hdr = nv_ro08(bios, perf + 0);
52 *ver = nv_ro08(bios, perf + 1); 65 *ver = nv_ro08(bios, perf + 1);
66 *cnt = nv_ro08(bios, perf + 2);
67 *len = nv_ro08(bios, perf + 3);
68 *snr = 0;
69 *ssz = 0;
70 return perf;
53 } 71 }
54 } 72 }
55 } 73 }
56 74
75 return 0x0000;
76}
77
78u16
79nvbios_perf_entry(struct nouveau_bios *bios, int idx,
80 u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
81{
82 u8 snr, ssz;
83 u16 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 0x0000;
92}
93
94u16
95nvbios_perfEp(struct nouveau_bios *bios, int idx,
96 u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
97 struct nvbios_perfE *info)
98{
99 u16 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len);
100 memset(info, 0x00, sizeof(*info));
101 info->pstate = nv_ro08(bios, perf + 0x00);
102 switch (!!perf * *ver) {
103 case 0x12:
104 case 0x13:
105 case 0x14:
106 info->core = nv_ro32(bios, perf + 0x01) * 10;
107 info->memory = nv_ro32(bios, perf + 0x05) * 20;
108 info->fanspeed = nv_ro08(bios, perf + 0x37);
109 if (*hdr > 0x38)
110 info->voltage = nv_ro08(bios, perf + 0x38);
111 break;
112 case 0x21:
113 case 0x23:
114 case 0x24:
115 info->fanspeed = nv_ro08(bios, perf + 0x04);
116 info->voltage = nv_ro08(bios, perf + 0x05);
117 info->shader = nv_ro16(bios, perf + 0x06) * 1000;
118 info->core = info->shader + (signed char)
119 nv_ro08(bios, perf + 0x08) * 1000;
120 switch (nv_device(bios)->chipset) {
121 case 0x49:
122 case 0x4b:
123 info->memory = nv_ro16(bios, perf + 0x0b) * 1000;
124 break;
125 default:
126 info->memory = nv_ro16(bios, perf + 0x0b) * 2000;
127 break;
128 }
129 break;
130 case 0x25:
131 info->fanspeed = nv_ro08(bios, perf + 0x04);
132 info->voltage = nv_ro08(bios, perf + 0x05);
133 info->core = nv_ro16(bios, perf + 0x06) * 1000;
134 info->shader = nv_ro16(bios, perf + 0x0a) * 1000;
135 info->memory = nv_ro16(bios, perf + 0x0c) * 1000;
136 break;
137 case 0x30:
138 info->script = nv_ro16(bios, perf + 0x02);
139 case 0x35:
140 info->fanspeed = nv_ro08(bios, perf + 0x06);
141 info->voltage = nv_ro08(bios, perf + 0x07);
142 info->core = nv_ro16(bios, perf + 0x08) * 1000;
143 info->shader = nv_ro16(bios, perf + 0x0a) * 1000;
144 info->memory = nv_ro16(bios, perf + 0x0c) * 1000;
145 info->vdec = nv_ro16(bios, perf + 0x10) * 1000;
146 info->disp = nv_ro16(bios, perf + 0x14) * 1000;
147 break;
148 case 0x40:
149 info->voltage = nv_ro08(bios, perf + 0x02);
150 break;
151 default:
152 return 0x0000;
153 }
57 return perf; 154 return perf;
58} 155}
59 156
157u32
158nvbios_perfSe(struct nouveau_bios *bios, u32 perfE, int idx,
159 u8 *ver, u8 *hdr, u8 cnt, u8 len)
160{
161 u32 data = 0x00000000;
162 if (idx < cnt) {
163 data = perfE + *hdr + (idx * len);
164 *hdr = len;
165 }
166 return data;
167}
168
169u32
170nvbios_perfSp(struct nouveau_bios *bios, u32 perfE, int idx,
171 u8 *ver, u8 *hdr, u8 cnt, u8 len,
172 struct nvbios_perfS *info)
173{
174 u32 data = nvbios_perfSe(bios, perfE, idx, ver, hdr, cnt, len);
175 memset(info, 0x00, sizeof(*info));
176 switch (!!data * *ver) {
177 case 0x40:
178 info->v40.freq = (nv_ro16(bios, data + 0x00) & 0x3fff) * 1000;
179 break;
180 default:
181 break;
182 }
183 return data;
184}
185
60int 186int
61nvbios_perf_fan_parse(struct nouveau_bios *bios, 187nvbios_perf_fan_parse(struct nouveau_bios *bios,
62 struct nvbios_perf_fan *fan) 188 struct nvbios_perf_fan *fan)
63{ 189{
64 u8 ver = 0, hdr = 0, cnt = 0, len = 0; 190 u8 ver, hdr, cnt, len, snr, ssz;
65 u16 perf = perf_table(bios, &ver, &hdr, &cnt, &len); 191 u16 perf = nvbios_perf_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
66 if (!perf) 192 if (!perf)
67 return -ENODEV; 193 return -ENODEV;
68 194
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c
new file mode 100644
index 000000000000..916fa9d302b7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c
@@ -0,0 +1,88 @@
1/*
2 * Copyright 2013 Red Hat Inc.
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: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/bit.h>
27#include <subdev/bios/rammap.h>
28
29u16
30nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
31 u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
32{
33 struct bit_entry bit_P;
34 u16 rammap = 0x0000;
35
36 if (!bit_entry(bios, 'P', &bit_P)) {
37 if (bit_P.version == 2)
38 rammap = nv_ro16(bios, bit_P.offset + 4);
39
40 if (rammap) {
41 *ver = nv_ro08(bios, rammap + 0);
42 switch (*ver) {
43 case 0x10:
44 case 0x11:
45 *hdr = nv_ro08(bios, rammap + 1);
46 *cnt = nv_ro08(bios, rammap + 5);
47 *len = nv_ro08(bios, rammap + 2);
48 *snr = nv_ro08(bios, rammap + 4);
49 *ssz = nv_ro08(bios, rammap + 3);
50 return rammap;
51 default:
52 break;
53 }
54 }
55 }
56
57 return 0x0000;
58}
59
60u16
61nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
62 u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
63{
64 u8 snr, ssz;
65 u16 rammap = nvbios_rammap_table(bios, ver, hdr, cnt, len, &snr, &ssz);
66 if (rammap && idx < *cnt) {
67 rammap = rammap + *hdr + (idx * (*len + (snr * ssz)));
68 *hdr = *len;
69 *cnt = snr;
70 *len = ssz;
71 return rammap;
72 }
73 return 0x0000;
74}
75
76u16
77nvbios_rammap_match(struct nouveau_bios *bios, u16 khz,
78 u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
79{
80 int idx = 0;
81 u32 data;
82 while ((data = nvbios_rammap_entry(bios, idx++, ver, hdr, cnt, len))) {
83 if (khz >= nv_ro16(bios, data + 0x00) &&
84 khz <= nv_ro16(bios, data + 0x02))
85 break;
86 }
87 return data;
88}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c
new file mode 100644
index 000000000000..151c2d6aaee8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c
@@ -0,0 +1,73 @@
1/*
2 * Copyright 2013 Red Hat Inc.
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: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/bit.h>
27#include <subdev/bios/timing.h>
28
29u16
30nvbios_timing_table(struct nouveau_bios *bios,
31 u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
32{
33 struct bit_entry bit_P;
34 u16 timing = 0x0000;
35
36 if (!bit_entry(bios, 'P', &bit_P)) {
37 if (bit_P.version == 1)
38 timing = nv_ro16(bios, bit_P.offset + 4);
39 else
40 if (bit_P.version == 2)
41 timing = nv_ro16(bios, bit_P.offset + 8);
42
43 if (timing) {
44 *ver = nv_ro08(bios, timing + 0);
45 switch (*ver) {
46 case 0x10:
47 *hdr = nv_ro08(bios, timing + 1);
48 *cnt = nv_ro08(bios, timing + 2);
49 *len = nv_ro08(bios, timing + 3);
50 return timing;
51 case 0x20:
52 *hdr = nv_ro08(bios, timing + 1);
53 *cnt = nv_ro08(bios, timing + 3);
54 *len = nv_ro08(bios, timing + 2);
55 return timing;
56 default:
57 break;
58 }
59 }
60 }
61
62 return 0x0000;
63}
64
65u16
66nvbios_timing_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
67{
68 u8 hdr, cnt;
69 u16 timing = nvbios_timing_table(bios, ver, &hdr, &cnt, len);
70 if (timing && idx < cnt)
71 return timing + hdr + (idx * *len);
72 return 0x0000;
73}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c b/drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c
new file mode 100644
index 000000000000..f343a1b060e8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c
@@ -0,0 +1,112 @@
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
25#include <subdev/bios.h>
26#include <subdev/bios/bit.h>
27#include <subdev/bios/vmap.h>
28
29u16
30nvbios_vmap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
31{
32 struct bit_entry bit_P;
33 u16 vmap = 0x0000;
34
35 if (!bit_entry(bios, 'P', &bit_P)) {
36 if (bit_P.version == 2) {
37 vmap = nv_ro16(bios, bit_P.offset + 0x20);
38 if (vmap) {
39 *ver = nv_ro08(bios, vmap + 0);
40 switch (*ver) {
41 case 0x10:
42 case 0x20:
43 *hdr = nv_ro08(bios, vmap + 1);
44 *cnt = nv_ro08(bios, vmap + 3);
45 *len = nv_ro08(bios, vmap + 2);
46 return vmap;
47 default:
48 break;
49 }
50 }
51 }
52 }
53
54 return 0x0000;
55}
56
57u16
58nvbios_vmap_parse(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
59 struct nvbios_vmap *info)
60{
61 u16 vmap = nvbios_vmap_table(bios, ver, hdr, cnt, len);
62 memset(info, 0x00, sizeof(*info));
63 switch (!!vmap * *ver) {
64 case 0x10:
65 case 0x20:
66 break;
67 }
68 return vmap;
69}
70
71u16
72nvbios_vmap_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
73{
74 u8 hdr, cnt;
75 u16 vmap = nvbios_vmap_table(bios, ver, &hdr, &cnt, len);
76 if (vmap && idx < cnt) {
77 vmap = vmap + hdr + (idx * *len);
78 return vmap;
79 }
80 return 0x0000;
81}
82
83u16
84nvbios_vmap_entry_parse(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len,
85 struct nvbios_vmap_entry *info)
86{
87 u16 vmap = nvbios_vmap_entry(bios, idx, ver, len);
88 memset(info, 0x00, sizeof(*info));
89 switch (!!vmap * *ver) {
90 case 0x10:
91 info->link = 0xff;
92 info->min = nv_ro32(bios, vmap + 0x00);
93 info->max = nv_ro32(bios, vmap + 0x04);
94 info->arg[0] = nv_ro32(bios, vmap + 0x08);
95 info->arg[1] = nv_ro32(bios, vmap + 0x0c);
96 info->arg[2] = nv_ro32(bios, vmap + 0x10);
97 break;
98 case 0x20:
99 info->unk0 = nv_ro08(bios, vmap + 0x00);
100 info->link = nv_ro08(bios, vmap + 0x01);
101 info->min = nv_ro32(bios, vmap + 0x02);
102 info->max = nv_ro32(bios, vmap + 0x06);
103 info->arg[0] = nv_ro32(bios, vmap + 0x0a);
104 info->arg[1] = nv_ro32(bios, vmap + 0x0e);
105 info->arg[2] = nv_ro32(bios, vmap + 0x12);
106 info->arg[3] = nv_ro32(bios, vmap + 0x16);
107 info->arg[4] = nv_ro32(bios, vmap + 0x1a);
108 info->arg[5] = nv_ro32(bios, vmap + 0x1e);
109 break;
110 }
111 return vmap;
112}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/core/subdev/bios/volt.c
new file mode 100644
index 000000000000..bb590de4ecb2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/volt.c
@@ -0,0 +1,137 @@
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
25#include <subdev/bios.h>
26#include <subdev/bios/bit.h>
27#include <subdev/bios/volt.h>
28
29u16
30nvbios_volt_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
31{
32 struct bit_entry bit_P;
33 u16 volt = 0x0000;
34
35 if (!bit_entry(bios, 'P', &bit_P)) {
36 if (bit_P.version == 2)
37 volt = nv_ro16(bios, bit_P.offset + 0x0c);
38 else
39 if (bit_P.version == 1)
40 volt = nv_ro16(bios, bit_P.offset + 0x10);
41
42 if (volt) {
43 *ver = nv_ro08(bios, volt + 0);
44 switch (*ver) {
45 case 0x12:
46 *hdr = 5;
47 *cnt = nv_ro08(bios, volt + 2);
48 *len = nv_ro08(bios, volt + 1);
49 return volt;
50 case 0x20:
51 *hdr = nv_ro08(bios, volt + 1);
52 *cnt = nv_ro08(bios, volt + 2);
53 *len = nv_ro08(bios, volt + 3);
54 return volt;
55 case 0x30:
56 case 0x40:
57 case 0x50:
58 *hdr = nv_ro08(bios, volt + 1);
59 *cnt = nv_ro08(bios, volt + 3);
60 *len = nv_ro08(bios, volt + 2);
61 return volt;
62 }
63 }
64 }
65
66 return 0x0000;
67}
68
69u16
70nvbios_volt_parse(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
71 struct nvbios_volt *info)
72{
73 u16 volt = nvbios_volt_table(bios, ver, hdr, cnt, len);
74 memset(info, 0x00, sizeof(*info));
75 switch (!!volt * *ver) {
76 case 0x12:
77 info->vidmask = nv_ro08(bios, volt + 0x04);
78 break;
79 case 0x20:
80 info->vidmask = nv_ro08(bios, volt + 0x05);
81 break;
82 case 0x30:
83 info->vidmask = nv_ro08(bios, volt + 0x04);
84 break;
85 case 0x40:
86 info->base = nv_ro32(bios, volt + 0x04);
87 info->step = nv_ro16(bios, volt + 0x08);
88 info->vidmask = nv_ro08(bios, volt + 0x0b);
89 /*XXX*/
90 info->min = 0;
91 info->max = info->base;
92 break;
93 case 0x50:
94 info->vidmask = nv_ro08(bios, volt + 0x06);
95 info->min = nv_ro32(bios, volt + 0x0a);
96 info->max = nv_ro32(bios, volt + 0x0e);
97 info->base = nv_ro32(bios, volt + 0x12) & 0x00ffffff;
98 info->step = nv_ro16(bios, volt + 0x16);
99 break;
100 }
101 return volt;
102}
103
104u16
105nvbios_volt_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
106{
107 u8 hdr, cnt;
108 u16 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len);
109 if (volt && idx < cnt) {
110 volt = volt + hdr + (idx * *len);
111 return volt;
112 }
113 return 0x0000;
114}
115
116u16
117nvbios_volt_entry_parse(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len,
118 struct nvbios_volt_entry *info)
119{
120 u16 volt = nvbios_volt_entry(bios, idx, ver, len);
121 memset(info, 0x00, sizeof(*info));
122 switch (!!volt * *ver) {
123 case 0x12:
124 case 0x20:
125 info->voltage = nv_ro08(bios, volt + 0x00) * 10000;
126 info->vid = nv_ro08(bios, volt + 0x01);
127 break;
128 case 0x30:
129 info->voltage = nv_ro08(bios, volt + 0x00) * 10000;
130 info->vid = nv_ro08(bios, volt + 0x01) >> 2;
131 break;
132 case 0x40:
133 case 0x50:
134 break;
135 }
136 return volt;
137}