diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2013-01-14 17:33:25 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-11-08 00:40:16 -0500 |
commit | 0833428e7d1b250afbd41e0a4c8c247cccd15aad (patch) | |
tree | 57517e19a618cde12d3b9007aad09752da25713f | |
parent | aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6 (diff) |
drm/nouveau/bios: parsing for various tables required for power management
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
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 | |||
28 | nouveau-y += core/subdev/bar/nvc0.o | 28 | nouveau-y += core/subdev/bar/nvc0.o |
29 | nouveau-y += core/subdev/bios/base.o | 29 | nouveau-y += core/subdev/bios/base.o |
30 | nouveau-y += core/subdev/bios/bit.o | 30 | nouveau-y += core/subdev/bios/bit.o |
31 | nouveau-y += core/subdev/bios/boost.o | ||
31 | nouveau-y += core/subdev/bios/conn.o | 32 | nouveau-y += core/subdev/bios/conn.o |
33 | nouveau-y += core/subdev/bios/cstep.o | ||
32 | nouveau-y += core/subdev/bios/dcb.o | 34 | nouveau-y += core/subdev/bios/dcb.o |
33 | nouveau-y += core/subdev/bios/disp.o | 35 | nouveau-y += core/subdev/bios/disp.o |
34 | nouveau-y += core/subdev/bios/dp.o | 36 | nouveau-y += core/subdev/bios/dp.o |
@@ -39,7 +41,11 @@ nouveau-y += core/subdev/bios/init.o | |||
39 | nouveau-y += core/subdev/bios/mxm.o | 41 | nouveau-y += core/subdev/bios/mxm.o |
40 | nouveau-y += core/subdev/bios/perf.o | 42 | nouveau-y += core/subdev/bios/perf.o |
41 | nouveau-y += core/subdev/bios/pll.o | 43 | nouveau-y += core/subdev/bios/pll.o |
44 | nouveau-y += core/subdev/bios/rammap.o | ||
45 | nouveau-y += core/subdev/bios/timing.o | ||
42 | nouveau-y += core/subdev/bios/therm.o | 46 | nouveau-y += core/subdev/bios/therm.o |
47 | nouveau-y += core/subdev/bios/vmap.o | ||
48 | nouveau-y += core/subdev/bios/volt.o | ||
43 | nouveau-y += core/subdev/bios/xpio.o | 49 | nouveau-y += core/subdev/bios/xpio.o |
44 | nouveau-y += core/subdev/bus/nv04.o | 50 | nouveau-y += core/subdev/bus/nv04.o |
45 | nouveau-y += core/subdev/bus/nv31.o | 51 | nouveau-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 | |||
4 | u16 nvbios_boostTe(struct nouveau_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *); | ||
5 | |||
6 | struct nvbios_boostE { | ||
7 | u8 pstate; | ||
8 | u32 min; | ||
9 | u32 max; | ||
10 | }; | ||
11 | |||
12 | u16 nvbios_boostEe(struct nouveau_bios *, int idx, u8 *, u8 *, u8 *, u8 *); | ||
13 | u16 nvbios_boostEp(struct nouveau_bios *, int idx, u8 *, u8 *, u8 *, u8 *, | ||
14 | struct nvbios_boostE *); | ||
15 | u16 nvbios_boostEm(struct nouveau_bios *, u8, u8 *, u8 *, u8 *, u8 *, | ||
16 | struct nvbios_boostE *); | ||
17 | |||
18 | struct nvbios_boostS { | ||
19 | u8 domain; | ||
20 | u8 percent; | ||
21 | u32 min; | ||
22 | u32 max; | ||
23 | }; | ||
24 | |||
25 | u16 nvbios_boostSe(struct nouveau_bios *, int, u16, u8 *, u8 *, u8, u8); | ||
26 | u16 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 | |||
4 | u16 nvbios_cstepTe(struct nouveau_bios *, | ||
5 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz); | ||
6 | |||
7 | struct nvbios_cstepE { | ||
8 | u8 pstate; | ||
9 | u8 index; | ||
10 | }; | ||
11 | |||
12 | u16 nvbios_cstepEe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr); | ||
13 | u16 nvbios_cstepEp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr, | ||
14 | struct nvbios_cstepE *); | ||
15 | u16 nvbios_cstepEm(struct nouveau_bios *, u8 pstate, u8 *ver, u8 *hdr, | ||
16 | struct nvbios_cstepE *); | ||
17 | |||
18 | struct nvbios_cstepX { | ||
19 | u32 freq; | ||
20 | u8 unkn[2]; | ||
21 | u8 voltage; | ||
22 | }; | ||
23 | |||
24 | u16 nvbios_cstepXe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr); | ||
25 | u16 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 | ||
4 | struct nouveau_bios; | 4 | struct nouveau_bios; |
5 | 5 | ||
6 | u16 nvbios_perf_table(struct nouveau_bios *, u8 *ver, u8 *hdr, | ||
7 | u8 *cnt, u8 *len, u8 *snr, u8 *ssz); | ||
8 | |||
9 | struct 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 | |||
21 | u16 nvbios_perf_entry(struct nouveau_bios *, int idx, | ||
22 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | ||
23 | u16 nvbios_perfEp(struct nouveau_bios *, int idx, | ||
24 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *); | ||
25 | |||
26 | struct nvbios_perfS { | ||
27 | union { | ||
28 | struct { | ||
29 | u32 freq; | ||
30 | } v40; | ||
31 | }; | ||
32 | }; | ||
33 | |||
34 | u32 nvbios_perfSe(struct nouveau_bios *, u32 data, int idx, | ||
35 | u8 *ver, u8 *hdr, u8 cnt, u8 len); | ||
36 | u32 nvbios_perfSp(struct nouveau_bios *, u32 data, int idx, | ||
37 | u8 *ver, u8 *hdr, u8 cnt, u8 len, struct nvbios_perfS *); | ||
38 | |||
6 | struct nvbios_perf_fan { | 39 | struct 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 | |||
4 | u16 nvbios_rammap_table(struct nouveau_bios *, u8 *ver, u8 *hdr, | ||
5 | u8 *cnt, u8 *len, u8 *snr, u8 *ssz); | ||
6 | u16 nvbios_rammap_entry(struct nouveau_bios *, int idx, | ||
7 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | ||
8 | u16 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 | |||
4 | u16 nvbios_timing_table(struct nouveau_bios *, | ||
5 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | ||
6 | u16 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 | |||
4 | struct nouveau_bios; | ||
5 | |||
6 | struct nvbios_vmap { | ||
7 | }; | ||
8 | |||
9 | u16 nvbios_vmap_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | ||
10 | u16 nvbios_vmap_parse(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
11 | struct nvbios_vmap *); | ||
12 | |||
13 | struct nvbios_vmap_entry { | ||
14 | u8 unk0; | ||
15 | u8 link; | ||
16 | u32 min; | ||
17 | u32 max; | ||
18 | s32 arg[6]; | ||
19 | }; | ||
20 | |||
21 | u16 nvbios_vmap_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *len); | ||
22 | u16 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 | |||
4 | struct nouveau_bios; | ||
5 | |||
6 | struct nvbios_volt { | ||
7 | u8 vidmask; | ||
8 | u32 min; | ||
9 | u32 max; | ||
10 | u32 base; | ||
11 | s16 step; | ||
12 | }; | ||
13 | |||
14 | u16 nvbios_volt_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | ||
15 | u16 nvbios_volt_parse(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
16 | struct nvbios_volt *); | ||
17 | |||
18 | struct nvbios_volt_entry { | ||
19 | u32 voltage; | ||
20 | u8 vid; | ||
21 | }; | ||
22 | |||
23 | u16 nvbios_volt_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *len); | ||
24 | u16 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 | |||
29 | u16 | ||
30 | nvbios_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 | |||
59 | u16 | ||
60 | nvbios_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 | |||
75 | u16 | ||
76 | nvbios_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 | |||
89 | u16 | ||
90 | nvbios_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 | |||
101 | u16 | ||
102 | nvbios_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 | |||
113 | u16 | ||
114 | nvbios_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 | |||
29 | u16 | ||
30 | nvbios_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 | |||
59 | u16 | ||
60 | nvbios_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 | |||
72 | u16 | ||
73 | nvbios_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 | |||
85 | u16 | ||
86 | nvbios_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 | |||
97 | u16 | ||
98 | nvbios_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 | |||
110 | u16 | ||
111 | nvbios_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 | ||
29 | static u16 | 29 | u16 |
30 | perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | 30 | nvbios_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 | |||
78 | u16 | ||
79 | nvbios_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 | |||
94 | u16 | ||
95 | nvbios_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 | ||
157 | u32 | ||
158 | nvbios_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 | |||
169 | u32 | ||
170 | nvbios_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 | |||
60 | int | 186 | int |
61 | nvbios_perf_fan_parse(struct nouveau_bios *bios, | 187 | nvbios_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 | |||
29 | u16 | ||
30 | nvbios_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 | |||
60 | u16 | ||
61 | nvbios_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 | |||
76 | u16 | ||
77 | nvbios_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 | |||
29 | u16 | ||
30 | nvbios_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 | |||
65 | u16 | ||
66 | nvbios_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 | |||
29 | u16 | ||
30 | nvbios_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 | |||
57 | u16 | ||
58 | nvbios_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 | |||
71 | u16 | ||
72 | nvbios_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 | |||
83 | u16 | ||
84 | nvbios_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 | |||
29 | u16 | ||
30 | nvbios_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 | |||
69 | u16 | ||
70 | nvbios_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 | |||
104 | u16 | ||
105 | nvbios_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 | |||
116 | u16 | ||
117 | nvbios_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 | } | ||